{"version":{"head":"afb5f42","date":"2026-11-05T21:37:33+01:00","dirty":false,"conflict":false,"dir":"/root/ds-export/extracted"},"main":{"head":"de2572c8a2f3cde926b76c6eb000cd6cb1975992","date":"2026-11-05T21:27:39+00:00","builtAt":"2026-11-05T21:47:22Z"},"catalog":"http://192.168.230.131:3777/ds/catalog/","coverage":{"covered":96,"total":106,"pct":91},"categories":[{"name":"Forms & input","slug":"forms-and-input","url":"http://192.168.230.131:3777/ds/components/forms-and-input","subs":36,"coverage":94},{"name":"Overlays & dialogs","slug":"overlays-and-dialogs","url":"http://192.168.230.131:3777/ds/components/overlays-and-dialogs","subs":11,"coverage":91},{"name":"Navigation","slug":"navigation","url":"http://192.168.230.131:3777/ds/components/navigation","subs":12,"coverage":92},{"name":"Records & data","slug":"records-and-data","url":"http://192.168.230.131:3777/ds/components/records-and-data","subs":25,"coverage":84},{"name":"Identity","slug":"identity","url":"http://192.168.230.131:3777/ds/components/identity","subs":6,"coverage":83},{"name":"States & feedback","slug":"states-and-feedback","url":"http://192.168.230.131:3777/ds/components/states-and-feedback","subs":13,"coverage":92},{"name":"AI","slug":"ai","url":"http://192.168.230.131:3777/ds/components/ai","subs":3,"coverage":100}],"sections":["Default","Variants","Sizes","States","With icon & kbd","Composition"],"families":[{"id":"button","name":"Button","category":"Forms & input","summary":"Buttons trigger actions; one primary per view, the rest default or ghost.","url":"http://192.168.230.131:3777/ds/components/button","coverage":100,"subcomponents":[{"id":"button","name":"Button","summary":"Text button in primary, default, ghost and danger variants.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"kbd hint = slot of Button (see With icon & kbd); .dlr-save is not a component (review ACRM-76–81). Sizes = default + compact (24px, table/list rows; .sm aliases it) — proposal proto/button-compact-split. Compact (24px, only inside table and list rows) approved by the owner 26 Sep 2026 with the Split button (acrm !3903); the .sm alias was replaced by <Button compact> (acrm !3940, wave 1; further waves follow). Button href renders a link (external URLs, OAuth, deep links only — in-app navigation stays on the router), AD 26 Sep 2026. Touch variant (full-width 44px commit on phones) replaces three scoped copies, AD 26 Sep 2026 per the owner’s 14 Sep rule. Keyboard hint: always the Button `kbd` slot (.acrm-kbd, framed key) — the plain .tk-kb in dialog footers is replaced (owner 27 Sep 2026, preview kbd-paticky); on phones (responsive breakpoint) the hint is hidden for every button. acrm !4038 (27 Sep 2026): the last legacy `.btn` usages in the app became <Button>; the `.sm` alias is gone. Remaining own button shapes are parts of their canonical primitives (Dialog window buttons, SectionTopBar identity, Toast, chart mark, \"Vše/Nic\") or the app-shell top-bar chrome (bell, record-now: 32 px = --field-h, aligned with the search field — documented exception). Second inventory of native <button>s (28 Sep 2026, DS repo docs/button/INVENTURA-nativni-button-2026-09-28.md: A 45 · B 128 · C 18) delivered in acrm !4057, !4059, !4064, !4066, !4067, !4068, !4069 — every hand-built copy of Button/IconButton in the app is gone. acrm !4067: Button renders type=\"button\" by default (submit only explicit type=\"submit\"; converting <button type=\"button\"> used to submit forms) and `ref` is part of its type (React 19). pressed exists only on IconButton; an on/off property is a Switch (wf-parbtn → Switch \"Paralelně\"), a fixed 2–4 option set is Segmented. tone=\"muted\" (owner 2026-09-28, acrm !4088): quiet ghost secondary action, --fg-secondary → --fg on hover („Vymazat filtry\"). Touch target (owner 8 Oct 2026, acrm !4882, RULES §19): below 720 px an invisible ::after makes the tap area ≥ 44 × 44 without changing the look; checked on dev 8 Oct (⋮ top bar 42×44 at the screen edge, 0 stolen taps). Clipped targets fixed in acrm !4892 (checked on dev 8 Oct: Ajda 78×44, Pošta stars 44×44 except a row cut by the scroll edge). Remaining by design: column-header ⋮ 24×40 (header row is 40 px). Registry repaired 17 Oct 2026 (review F4/F11): attached css button.css.","source":"package","react":["Button"],"classes":[".acrm-btn",".acrm-btn-lbl",".acrm-btn.primary",".acrm-btn.ghost",".acrm-btn.danger",".acrm-btn.compact"],"files":["packages/ui/src/components/Button.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/responsive.css","apps/web/src/ds/button.css"],"stories":{"Default":["components--button--default"],"Variants":["components--button--variants"],"Sizes":["components--button--sizes"],"States":["components--button--states"],"With icon & kbd":["components--button--with-icon-kbd"],"Composition":["components--button--composition"]},"legacy":["buttons.html"],"related":["icon-button"],"docs":"docs/button/button","url":"http://192.168.230.131:3777/ds/components/button/button","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Buttons","card":"buttons.html","react":["Button"],"classes":[".btn"],"tokens":[],"status":"OK","note":""}}},{"id":"icon-button","name":"Icon button","summary":"Square button carrying only an icon; label lives in the tooltip. Quiet at rest, variant=\"framed\" for the bordered one, variant=\"secondary\" (beta) for a hairline-bordered tool row.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"variant=\"secondary\" has ONE size (owner 19 Oct 2026, acrm ACRM-542): --control-h square + --ico-sm glyph; size/iconSize are ignored; text beside a row uses .acrm-icobtn-text (padding-inline --sp-4). Window headers stay quiet (AD 27 Sep 2026). variant=\"framed\" (11 September 2026, BTN-A3) is a 1:1 port of the hand-drawn .pr-iconbtn / .rr-iconbtn, which were deleted with it: 32px wide on the base height, 1px --border-strong, --surface-100, --shadow-xs, --ico-sm glyph in --ink-700, hover --surface-75. Pressed, open and disabled deliberately keep the rest look, because the hand-drawn rules had no such states; the validator rule iconbtn-framed-raw blocks the old classes. Variant by CONTEXT (AD 26 Sep 2026, acrm !3910 — in the docstring): dense list row (ItemList, timeline, relations, thread, project/meeting/milestone row) = quiet size=\"sm\"; detail header / toolbar = quiet default; variant=\"framed\" ONLY next to framed siblings (rail action row, section header next to framed buttons, dialog footer next to Button default). Kebab = dots-vertical; a kebab with one item is replaced by the direct action (trash + confirm, link-off without danger) — rule \"kebab with one action\" landed as the wave C cleanup (AD 26 Sep 2026, acrm !3997: ProjectMilestonesSection trash, IdentityImageDialog trash, ProjectMeetingsTab link-off, none get a Popover around a single choice). Wave 16 (acrm !3997) finished the context rule above by migrating the last hand-drawn icon buttons onto it: 32px `.icobtn` (Uživatelé domains, segment detail/share ×2) → framed size default (30); 22px `.eml-icobtn` (draft/pinned mail rows) → `size=\"sm\"`; 26px `.aichat-hbtn` (assistant panel header) → default, with `pressed` for the settings toggle; TabStrip scroll arrows → `size=\"sm\"`. Exception kept: the App shell chrome's 32px `.as-icobtn` / `.as-util .icobtn` sits among 32–34px neighbours and stays hand-drawn. State pressed (acrm !3936): pressed?: boolean → aria-pressed + --active-surface, also on hover — for toggles (format, panel, template/AI in mail compose). The open look applies only to menu triggers ([aria-expanded=true][aria-haspopup]); a disclosure (collapse/expand) carries its state in the glyph. Link (`href`, AD 27 Sep 2026 — attachment download): renders `<a class=\"acrm-icobtn …\">` with the same look, same pattern as `<Button href>` — real link semantics (middle-click, \"save link as\", a screen reader announces a link), `target=\"_blank\"` gets `rel=\"noopener noreferrer\"` merged in, `disabled` with `href` renders `<a aria-disabled>` without `href` (a link cannot be disabled by attribute). External/file URLs only — in-app navigation stays on the router. `ref` forwards onto the `<a>` too (review fix in !3997), so it can anchor a Popover. Touch target (owner 8 Oct 2026, acrm !4882, RULES §19): below 720 px an invisible ::after makes the tap area ≥ 44 × 44 without changing the look; checked on dev 8 Oct (⋮ top bar 42×44 at the screen edge, 0 stolen taps). Clipped targets fixed in acrm !4892 (checked on dev 8 Oct: Ajda 78×44, Pošta stars 44×44 except a row cut by the scroll edge). Remaining by design: column-header ⋮ 24×40 (header row is 40 px). Registry repaired 17 Oct 2026 (review F6): added exported Icon to react[].","source":"package","react":["IconButton","Icon"],"classes":[".acrm-icobtn",".acrm-icobtn.sm",".acrm-icobtn.framed",".acrm-icobtn.secondary"],"files":["packages/ui/src/components/IconButton.tsx","packages/ui/src/components/ds-icons.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/responsive.css"],"stories":{"Default":["components--icon-button--default"],"Variants":["components--icon-button--variants"],"Sizes":["components--icon-button--sizes"],"States":["components--icon-button--states"],"With icon & kbd":[],"Composition":["components--icon-button--composition"]},"legacy":["buttons.html"],"related":["button","tooltip"],"docs":"docs/button/icon-button","url":"http://192.168.230.131:3777/ds/components/button/icon-button","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Buttons","card":"buttons.html","react":["Button"],"classes":[".btn"],"tokens":[],"status":"OK","note":""}}},{"id":"menu-button","name":"Menu button","summary":"The one action menu of the app: a labelled button with a chevron, or the kebab „⋯“ (iconOnly), opening a menu of actions; no action is the default one.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"AD + owner 28 Sep 2026 („sjednotit popover do menu-button“): Menu button is THE action menu — the row anatomy moved here from Popover. Row: .ic (icon | iconNode) · label (.tx > .nm when something is on the right) · .tag · .acrm-kbd (aria-hidden) · .chk (checked rows); variants danger (auto separator before the first danger row), strong, disabled + title (tooltip + aria-describedby); empty/loading row {empty} = .acrm-popover-empty. Kebab = iconOnly → canonical IconButton (sm / framed), label = aria-label + phone sheet title, aria-haspopup/expanded + stopPropagation by the component. „Dimmed but clickable“ rows do not exist. Phone = BottomSheet. Mechanical refactor moved 18 hand-built Popover menus onto it (acrm MR, 28 Sep 2026); sub-menu (mail „Přesunout do složky ›“, reservation „Předat…“), menu header (account menu) and insert menus wait for an approved shape (MR-B). History: FA204, 26 Sep 2026 (acrm !3890) 1:1 port of „Přidat aktivitu“ (P144, TL-12); custom trigger({open, menu, onClick}) acrm !3899 (dialog chip row, rail link !4014). forceMenu (menu even with one item) and danger items (2026-09-28, acrm !4088). Touch (AD 28 Sep 2026, acrm !4111): in the phone sheet a disabled item shows its title as a visible second line .acrm-popover-reason (--hint, --ink-600, aligned with the label, outside the button) — MenuItems sheet; desktop keeps the tooltip. 3 Oct 2026: MenuButtonItem count / countTone / muted / actions / actionsLabel (acrm !4527). Registry repaired 17 Oct 2026 (review F6): added exported MenuPanel to react[].","source":"package","react":["MenuButton","MenuItems","MenuPanel"],"classes":[".acrm-popover-item",".acrm-popover-item.danger",".acrm-popover-item.strong",".acrm-popover-sep",".acrm-popover-empty",".acrm-kbd","acrm-popover-reason"],"files":["packages/ui/src/components/MenuButton.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--menu-button--default"],"Variants":["components--menu-button--variants","components--menu-button--row-actions-count"],"Sizes":[],"States":["components--menu-button--states"],"With icon & kbd":[],"Composition":["components--menu-button--composition"],"Anatomy":["components--menu-button--anatomy","components--menu-button--submenu-header-switch"]},"legacy":[],"related":["button","split-button","icon-button","picker-menu","popover","empty-state"],"docs":"docs/button/menu-button","url":"http://192.168.230.131:3777/ds/components/button/menu-button","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"split-button","name":"Split button","summary":"Main action plus a chevron that opens a menu of related variants of the same action.","status":"canon","shown":"canon","approvedAt":"2026-09-26","notes":"Approved by the owner 26 Sep 2026 („za me ok . schvaleno“, preview button-compact-split) and delivered in acrm !3903. Reverses review ACRM-81 (no use case then) on the owner’s request; pattern Atlassian Split button. Menu items shared with Menu button (one menu in the family). First adopter: mail „Odeslat hned / s odkladem“. Registry repaired 17 Oct 2026 (review F4/F11): attached css button.css.","source":"package","react":["SplitButton"],"classes":[".acrm-split",".acrm-split-more",".acrm-split.compact"],"files":["packages/ui/src/components/SplitButton.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/button.css"],"stories":{"Default":["components--split-button--default"],"Variants":["components--split-button--variants"],"Sizes":["components--split-button--sizes"],"States":["components--split-button--states"],"With icon & kbd":[],"Composition":["components--split-button--composition"]},"legacy":[],"related":["button","picker-menu"],"docs":"docs/button/split-button","url":"http://192.168.230.131:3777/ds/components/button/split-button","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"fab","name":"Fab","summary":"Floating primary action of a screen on a phone: round „+\" for Create, extended with a label otherwise.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Approved by the owner 2026-09-28 (Attio pattern, AD). Drawn by SectionTopBar from primaryAction data below 720 px only; acrm !4088. Used only through SectionTopBar (primaryAction below 720 px) — gen-usage shows 0 direct uses; that is expected, not unused.","source":"package","react":["Fab"],"classes":[".acrm-fab",".acrm-fab.extended",".acrm-fab.inline",".has-fab"],"files":["packages/ui/src/components/Fab.tsx"],"css":["apps/web/src/ds/section-top-bar.css"],"stories":{"Default":["components--fab--default"],"Variants":["components--fab--variants"],"Sizes":[],"States":["components--fab--states"],"With icon & kbd":[],"Composition":["components--fab--composition"]},"legacy":[],"related":["section-top-bar","button","menu-button"],"docs":"docs/button/fab","url":"http://192.168.230.131:3777/ds/components/button/fab","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"text-field","name":"Text field","category":"Forms & input","summary":"Single- and multi-line text entry with label, hint and error.","url":"http://192.168.230.131:3777/ds/components/text-field","coverage":100,"subcomponents":[{"id":"input","name":"Input","summary":"Single-line input in text, email, url, code, number and short widths.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"States include read-only (canon since 28 Sep 2026, !4102): --surface-75, full --fg text, cursor: text, focus ring kept; replaces the scoped .finput[readonly]. Registered exceptions from <Input> (AD 28 Sep 2026, !4110) — inline editing in context, a 32px box would break the header or the tool: .nt-bub-url (link field inside the note formatting bubble) and .sgb-th-edit (column rename in the segment table header), both --control-h-sm (24px); .sgb-th-edit carries the focus ring like .rr-edit; on touch (pointer: coarse) .nt-bub-url is 44px. Any other bare <input> with a text-field box class fails the input-raw HARD rule.","source":"package","react":["Input"],"classes":[".acrm-input",".acrm-input--num",".acrm-input--code",".acrm-input--short",".acrm-input--email",".acrm-range",".acrm-range-dash"],"files":["packages/ui/src/components/Input.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/inputs.css"],"stories":{"Default":["components--input--default"],"Variants":["components--input--variants"],"Sizes":["components--input--sizes"],"States":["components--input--states"],"With icon & kbd":[],"Composition":["components--input--composition"]},"legacy":["Inputs.html"],"related":["field","textarea","input-with-icon-kbd","date-field","select","combobox","record-select"],"docs":"docs/text-field/input","url":"http://192.168.230.131:3777/ds/components/text-field/input","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"textarea","name":"Textarea","summary":"Multi-line text input that grows with content.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"package","react":["Textarea"],"classes":[".acrm-textarea"],"files":["packages/ui/src/components/Textarea.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--textarea--default"],"Variants":[],"Sizes":["components--textarea--sizes"],"States":["components--textarea--states"],"With icon & kbd":[],"Composition":["components--textarea--composition"]},"legacy":["Inputs.html"],"related":["input","field","mention-input"],"docs":"docs/text-field/textarea","url":"http://192.168.230.131:3777/ds/components/text-field/textarea","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"field","name":"Field","summary":"Wrapper that stacks label, control, hint and error message.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"acrm MR !4085 (28 Sep 2026, \"fix(ui): chyba pod DS Field se čtečce provází sama\") added a new export, `useFieldDescribedBy`: `<Field>` now gives the rendered hint/error span an automatic `id` (`useId()`, error takes precedence over hint) and provides that id through a context. Any control rendered as a child of `<Field>`/`<DrawerField>` can call `useFieldDescribedBy()` and fall back to it for `aria-describedby` unless the caller passed an explicit `describedBy` — `masked-input` and `phone-input` both do this now. This does not add `htmlFor`/label association (the pre-existing known limit in `field.a11y.md` — no automatic label–control link), and it only helps a control that explicitly opts into the hook; a plain `<input>` still needs it wired by hand.","source":"package","react":["Field"],"classes":[".acrm-field",".acrm-field-label",".acrm-field-hint",".acrm-field-error",".acrm-note"],"files":["packages/ui/src/components/Field.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--field--default"],"Variants":["components--field--variants"],"Sizes":[],"States":["components--field--states"],"With icon & kbd":[],"Composition":["components--field--composition"]},"legacy":["Inputs.html"],"related":["input","textarea","select","date-field","checkbox","input-with-icon-kbd"],"docs":"docs/text-field/field","url":"http://192.168.230.131:3777/ds/components/text-field/field","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"input-with-icon-kbd","name":"Input with icon and kbd","summary":"Input with a leading icon or a trailing keyboard hint, used for search.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"app-css","react":[],"classes":[".acrm-inputwrap",".acrm-inputwrap--num",".acrm-inputwrap--code",".acrm-inputwrap--short",".acrm-inputwrap--email",".acrm-kbd"],"files":["apps/web/src/ds/inputs.css"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds.css"],"stories":{"Default":["components--input-with-icon-and-kbd--default"],"Variants":["components--input-with-icon-and-kbd--variants"],"Sizes":["components--input-with-icon-and-kbd--sizes"],"States":["components--input-with-icon-and-kbd--states"],"With icon & kbd":["components--input-with-icon-and-kbd--with-icon-kbd"],"Composition":["components--input-with-icon-and-kbd--composition"]},"legacy":["Inputs.html"],"related":["input","button","combobox","record-select"],"docs":"docs/text-field/input-with-icon-kbd","url":"http://192.168.230.131:3777/ds/components/text-field/input-with-icon-kbd","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"masked-input","name":"Masked input","summary":"Structured value typed straight into a visible mask (IČO, DIČ, PSČ, rodné číslo) with inline check-digit validation; input holds the typed text, a muted ghost draws the rest of the template.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Merged to origin/main 28 September 2026 (acrm MR !4082, \"fix(web): IČO, DIČ, PSČ a rodné číslo jako maska (MaskedInput v @acrm/ui)\"), under the owner's binding rule of 14 Sep 2026 (\".claude/rules/design-system.md\" §\"Vstupy a mobil\"): a structured value is a mask, never free text — only valid characters, separators added automatically, the template stays visible, the error is reported while typing. Unlike \"masked-date-input\", this component IS exported from @acrm/ui (source=package) and ships four masks as pure functions in `field-masks.ts`: IČO (8 digits, mod-11 check digit), DIČ (digits-first = Czech, \"CZ\" is added automatically; letters-first = the typed country code, CZ is never forced; mod-11 check only for CZ), PSČ (\"### ##\", Czech/Slovak only — a foreign address falls back to a plain Input in the host), rodné číslo (\"######/####\" or 9 digits before 1953, date part validated per segment, +50 on the month for women, 10-digit form checked mod 11 with the pre-1985 exception). Two host shapes, no new look: `variant=\"field\"` (default) wraps `.acrm-inputwrap` (`.acrm-mask`/`.acrm-mask-ghost` inside, `.acrm-maskwrap.is-error` colours the typed text `--critical-ink` in addition to the wrapper's usual red border+ring) — e.g. IČO/DIČ in the \"Nová firma\" drawer (`FirmyPage.tsx`); `variant=\"formless\"` reuses the exact `.fl-mask`/`.fl-mask-in`/`.fl-mask-ghost`/`.fl-mask.bad` classes `masked-date-input` already established in `dialog-formless.css` — e.g. rodné číslo in the \"Nová osoba\" dialog (`NewContactDialog.tsx`). Save gate: the host reads the value out only when `mask.complete(text)` is true (`ico: mask.complete(f.ico) ? f.ico : null`); an incomplete or invalid field is simply not saved, it never blocks the rest of the form (AD 28 Sep 2026) — same rule as `masked-date-input`'s ISO gate. An old invalid stored value (recorded before the mask existed) is loaded through `applyMask()` and shown as-is, editable, not rejected. `describedBy` links the error text via `aria-describedby` when the caller passes an id — the formless caller (`NewContactDialog`, rodné číslo) wires it; the field-variant callers in `FirmyPage` (IČO, DIČ, PSČ) do not, leaving the same label/error linking gap `text-field/input.a11y.md` documents for `<Field>`. Sibling pattern `MaskedPhoneInput` (phone, dial codes) moved into `packages/ui` 28 September 2026 (acrm MR !4085) alongside the new `PhoneInput` form field and `DialCodePicker`; it now has its own registry card, `phone-input`.","source":"package","react":["MaskedInput"],"classes":[".acrm-maskwrap",".acrm-maskwrap.is-error",".acrm-mask",".acrm-mask-ghost",".fl-mask",".fl-mask-in",".fl-mask-ghost",".fl-mask.bad"],"files":["packages/ui/src/components/MaskedInput.tsx","packages/ui/src/lib/field-masks.ts"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds/dialog-formless.css"],"stories":{"Default":["components--masked-input--default"],"Variants":["components--masked-input--variants"],"Sizes":[],"States":["components--masked-input--states"],"With icon & kbd":[],"Composition":["components--masked-input--composition"]},"legacy":[],"related":["input","masked-date-input","field","date-field"],"docs":"docs/text-field/masked-input","url":"http://192.168.230.131:3777/ds/components/text-field/masked-input","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"masked-date-input","name":"Masked date input","summary":"Date typed straight into a dd.mm.rrrr mask with inline validation; no leading zero required, ISO out only once complete and valid.","status":"canon","shown":"canon","approvedAt":"2026-09-15","notes":"Merged to origin/main 15 September 2026 (MR !3540), approved by the product owner as part of the New person dialog work (`.claude/rules/design-system.md` §\"Vstupy a mobil\", 14 Sep 2026: a structured value is a mask, never free text). Sibling pattern to `MaskedPhoneInput` (input + muted ghost-template) but that component has no card of its own yet in this registry — it is only listed under `record-rail/rail`'s files — so this is the mask pattern's first documented entry, filed under Text field for lack of a dedicated family. Code correction against the design brief: `inputMode` is `\"decimal\"`, not `\"numeric\"`. The component's only call site (`NewContactDialog`, the New person dialog) is not merged yet, and it wires no calendar next to the field — \"the calendar is a complement\" is the rule this component exists to satisfy, not yet an observed behaviour. No stories: lives in `apps/web/src/components/multivalue/`, which `packages/ui` must not import. Registry repaired 17 Oct 2026 (review F1, F10): now exported from @acrm/ui (packages/ui/src/components/MaskedDateInput.tsx, lib/date-mask.ts); the apps/web paths and the \"lives in apps/web\" caveat are outdated.","source":"package","react":["MaskedDateInput"],"classes":[".fl-mask",".fl-mask-in",".fl-mask-ghost",".fl-mask.bad"],"files":["packages/ui/src/components/MaskedDateInput.tsx","packages/ui/src/lib/date-mask.ts","apps/web/src/ds/dialog-formless.css"],"css":["apps/web/src/ds/dialog-formless.css"],"stories":{"Default":["components--masked-date-input--default"],"Variants":[],"Sizes":[],"States":["components--masked-date-input--states"],"With icon & kbd":[],"Composition":["components--masked-date-input--composition"]},"legacy":[],"related":["date-field","input","formless-dialog"],"docs":"docs/text-field/masked-date-input","url":"http://192.168.230.131:3777/ds/components/text-field/masked-date-input","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"phone-input","name":"Phone input","summary":"Phone number typed as a country-code prefix plus a national-number mask; an old value the mask cannot read is shown editable as-is.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Merged to origin/main 28 September 2026 (acrm MR !4085, \"fix(web): telefon jako maska s předvolbou (PhoneInput); vzor telefonu do @acrm/ui\"), under the owner's binding rule of 14 Sep 2026 (\".claude/rules/design-system.md\" §\"Vstupy a mobil\"): a structured value is a mask, never free text. AD 28 Sep 2026 moved the whole phone pattern into @acrm/ui (source=package): `lib/dial-codes.ts` (pure functions — `DIAL_CODES`, `DIAL_MASKS` per country, `maskNational`, `maskTemplate`, `splitDial`, `phoneDigitsFor`, `phoneComplete`, `searchDialCodes`), `DialCodePicker` (country-code chip + search) and two inputs sharing that mask: `PhoneInput` (this card's primary component — a FORM FIELD, `.acrm-inputwrap.acrm-maskwrap.acrm-phonewrap`) and `MaskedPhoneInput` (the row input of the Multi-value editor, `.phe-*`, no `.acrm-inputwrap` frame of its own). Both were previously app-only (`apps/web/src/components/multivalue/`); `masked-input`'s registry entry called this move out as pending — it is done as of !4085, and this is that promised card. Anatomy: the country code is a prefix inside the field (`DialCodePicker`, chip + search), the national number is masked per country from `DIAL_MASKS` (CZ/SK 3·3·3, DE/AT 3·4·4, fallback 3·3·3 for an unlisted code), with the same visible ghost template pattern as `masked-input` (`.acrm-mask-ghost`, typed part transparent, rest muted underscores). Below 720px `DialCodePicker` renders the canonical `BottomSheet` (\"Předvolba\" title, grab handle, search, full-width Hotovo, backdrop closes, portais into the modal's own dialog when opened from one) instead of the desktop `Popover` — rule 14 Sep 2026 item 5/6 for every mobile overlay; `useSheetMode()` picks the mode. The selected country is kept even with an empty number (a picked country used to snap back to +420 once the digits were cleared — fixed same MR). Value is the display string \"+420 601 123 456\" (identical to the app's `formatPhone`), so the stored data format is unchanged. An old value the mask cannot read without loss (several numbers \"a; b\", letters) is shown as-is via the `legacy` branch and stays editable, never rejected or blanked. `phoneComplete(value)` gates saving — an invalid or incomplete phone never blocks the rest of the form; the host simply does not send it (edit keeps the previous stored value). `aria-describedby` now comes from the enclosing `<Field>`/`<DrawerField>` automatically via `useFieldDescribedBy()` unless the caller passes its own `describedBy` (see `field` sub-entry). Used in: Nová firma (`FirmyPage.tsx`), Nová objednávka (`NewOrderForm.tsx`), Nastavení › Profil (\"Telefon\" and \"Telefon 2\", `NastaveniPage.tsx`), and SIM record evidence (`TelefonyPage.tsx`) — there the number is the record's key, so the host saves only a valid number or the unchanged old one, never a half-typed new one.","source":"package","react":["PhoneInput","DialCodePicker","MaskedPhoneInput"],"classes":[".acrm-inputwrap",".acrm-maskwrap",".acrm-maskwrap.is-error",".acrm-phonewrap",".acrm-mask",".acrm-mask-ghost",".phe-ccbox",".phe-cc",".phe-ccsheet",".phe-ccsearch",".phe-cclist",".phe-ccrow",".phe-ccempty",".phe-maskwrap",".phe-num",".phe-ghost"],"files":["packages/ui/src/components/PhoneInput.tsx","packages/ui/src/components/DialCodePicker.tsx","packages/ui/src/components/MaskedPhoneInput.tsx","packages/ui/src/lib/dial-codes.ts"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds/multi-value.css"],"stories":{"Default":["components--phone-input--default"],"Variants":["components--phone-input--variants"],"Sizes":[],"States":["components--phone-input--states"],"With icon & kbd":[],"Composition":["components--phone-input--composition"]},"legacy":[],"related":["masked-input","input","field"],"docs":"docs/text-field/phone-input","url":"http://192.168.230.131:3777/ds/components/text-field/phone-input","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"amount-input","name":"Amount input","summary":"Amount or count typed as a mask: digits and separators only, thousands grouped as you type, a dot read by context (12.345 = thousands, 12.5 = decimal), nothing typed is ever cut off silently.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Merged to origin/main 28 September 2026 (acrm MR !4089). Replaces raw <input type=\"number\"> for amounts on 16 app surfaces (advances, benefits, expenses, KPI, costs, documents, pricing, assets, budgets, vehicles, cash desk, orders, phones). Raw value contract -?\\d*(\\.\\d*)? unchanged for hosts. Dot rule and no-silent-truncation per AD 28 Sep 2026; caret anchoring after the decimal comma fixed in number-core (caretInFormatted), shared with RecordRail. Canon 28 Sep 2026 (AD approved M3; /ds renders the stories from the main build).","source":"package","react":["AmountInput"],"classes":[".acrm-inputwrap",".acrm-amountwrap",".acrm-amount-suffix"],"files":["packages/ui/src/components/AmountInput.tsx","packages/ui/src/lib/number-core.ts"],"css":["apps/web/src/ds/inputs.css"],"stories":{"Default":["components--amount-input--default"],"Variants":["components--amount-input--variants"],"Sizes":[],"States":["components--amount-input--states"],"With icon & kbd":[],"Composition":["components--amount-input--composition"]},"legacy":[],"related":["masked-input","phone-input","input","field"],"docs":"docs/text-field/amount-input","url":"http://192.168.230.131:3777/ds/components/text-field/amount-input","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"tag-input","name":"Tag input","summary":"Input that turns typed values into removable tags.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories. 19 Oct 2026 (owner, proto/mail-konverzace-chat-poradi@828a56aa0): clamp toggle moves INTO the bubble as the optional `more` prop (text button .cht-more \"Show all\" / \"Show less\", aria-expanded, white underlined on the accent bubble); the meta-row \"Full message\" action is removed; e-mail conversation order is oldest at top, newest at bottom, view anchored to the end of the thread.","source":"app-css","react":[],"classes":[".acrm-taginput",".acrm-tag",".acrm-tag-x"],"files":["apps/web/src/ds/inputs.css"],"css":["apps/web/src/ds/inputs.css"],"stories":{"Default":["components--tag-input--default","components--removable-chip--default"],"Variants":["components--removable-chip--variants"],"Sizes":[],"States":["components--tag-input--states","components--removable-chip--states"],"With icon & kbd":[],"Composition":["components--tag-input--composition","components--removable-chip--composition"]},"legacy":["Inputs.html"],"related":["removable-chip","option-chips","entity-ref","record-select"],"docs":"docs/text-field/tag-input","url":"http://192.168.230.131:3777/ds/components/text-field/tag-input","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"mention-input","name":"Mention input","summary":"Text editor that resolves @ references into entity chips.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":null,"source":"app-css","react":["MentionInput","MentionText"],"classes":[".mi-editor",".mi-multiline",".mi-menu",".mi-opt-ic",".mi-lost",".eref-chip.eref-mini"],"files":["apps/web/src/components/MentionInput.tsx","apps/web/src/ds/mention-input.css"],"css":["apps/web/src/ds/mention-input.css"],"stories":{"Default":["components--mention-input--default"],"Variants":[],"Sizes":["components--mention-input--sizes"],"States":["components--mention-input--states"],"With icon & kbd":[],"Composition":["components--mention-input--composition"]},"legacy":["task-dialog.html"],"related":["entity-ref","record-select","textarea","popover"],"docs":"docs/text-field/mention-input","url":"http://192.168.230.131:3777/ds/components/text-field/mention-input","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"select","name":"Select","category":"Forms & input","summary":"Two field types — Select for a closed list, Record select for a searchable list of records; both with an optional multiple mode. Never a native select.","url":"http://192.168.230.131:3777/ds/components/select","coverage":71,"subcomponents":[{"id":"select","name":"Select","summary":"Single or multiple choice from a closed list (roughly ten options or fewer); 32px field trigger opening the type A menu.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"3 Oct 2026: `multiple` replaced the separate Multi-select (acrm !4472). Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.","source":"package","react":["Select"],"classes":[".acrm-select-trigger",".acrm-select-val",".acrm-select-native",".acrm-popover-item"],"files":["packages/ui/src/components/Select.tsx"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds.css"],"stories":{"Default":["components--select--default"],"Variants":["components--select--variants"],"Sizes":[],"States":["components--select--states"],"With icon & kbd":[],"Composition":["components--select--composition","components--select--dropdown-types"]},"legacy":["Inputs.html"],"related":["record-select","combobox","picker-menu","popover"],"docs":"docs/select/select","url":"http://192.168.230.131:3777/ds/components/select/select","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"record-select","name":"Record select","summary":"Search-driven choice from records: framed field, or panel anchored to a rail row or a chip. Sections separated by a named hairline, one value = accent check.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Absorbed Rail picker on 12 September 2026 (AD, RP-1; acrm !3425–!3443): with anchorRef the panel hangs under a rail row or a chip instead of a framed trigger, so the rail has no picker of its own and RailPickerMenu is deleted. Also new: sections whose name sits IN the hairline (only when there are two or more; a single name would be the forbidden heading above a menu), selected pinned on top, accent check for one value (F261), diacritics-folded search over sub and keywords, quick-create footer, minWidth, loading/empty/busy, UserAvatar for a colleague. Known limit: the section name is var(--label) in --fg-muted = 2.85:1 light / 3.63:1 dark, below AA in both themes — the lighter tone is the AD's explicit choice of 12 September 2026 (ACRM-227, acrm !3460), made with the numbers in front of him; the group is announced from role=group + aria-label, not from this text. The hand-made panel shell is blocked by the validator rule recordselect-shell-handmade. Slot wrapOption(option, row) (acrm !3913, AD 26 Sep 2026): the host may WRAP an option row in an element that clicks nothing and does not change its size (hover preview EntityPreviewChip); selection, keys and look stay with RecordSelect. Used by RecordLinksChip — the one links chip of shape-A dialogs (task, deal, meeting, note), selected records show the record preview on hover.","source":"package","react":["RecordSelect"],"classes":[".acrm-recordselect",".acrm-recordselect-trigger",".acrm-recordselect-pop",".acrm-recordselect-search",".acrm-recordselect-opt",".acrm-recordselect-empty",".acrm-recordselect-list",".acrm-recordselect-tx",".acrm-recordselect-clear",".acrm-recordselect--full",".acrm-recordselect-ck",".acrm-recordselect-sec",".acrm-recordselect-grp",".acrm-recordselect-foot",".acrm-recordselect-create"],"files":["packages/ui/src/components/RecordSelect.tsx","packages/ui/src/lib/fold-text.ts"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds.css"],"stories":{"Default":["components--record-select--default"],"Variants":["components--record-select--variants"],"Sizes":["components--record-select--sizes"],"States":["components--record-select--states"],"With icon & kbd":[],"Composition":["components--record-select--composition"]},"legacy":["Inputs.html"],"related":["entity-picker","product-picker","combobox","avatar","entity-ref","record-rail","user-avatar"],"docs":"docs/select/record-select","url":"http://192.168.230.131:3777/ds/components/select/record-select","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"nav-select","name":"Nav select","summary":"Compact chip-style select used inside top bars to switch views.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":null,"source":"package","react":["NavSelect"],"classes":[".tchip",".acrm-popover-item"],"files":["packages/ui/src/components/NavSelect.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--nav-select--default"],"Variants":["components--nav-select--variants"],"Sizes":[],"States":["components--nav-select--states"],"With icon & kbd":["components--nav-select--with-icon-kbd"],"Composition":["components--nav-select--composition"]},"legacy":["Section top bar.html"],"related":["picker-menu","section-top-bar","check-menu","filter-chip"],"docs":"docs/select/nav-select","url":"http://192.168.230.131:3777/ds/components/select/nav-select","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Section top bar","card":"Section top bar.html","react":["SectionTopBar"],"classes":[".tbar"],"tokens":[],"status":"OK","note":"normativ .tbar; migrace 8 stránek z .pr-top = samostatné MR (viz PLAN-page-decomposition)"}}},{"id":"picker-menu","name":"Picker menu","summary":"Anchored menu of items with optional check marks and icons.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Slots added 27 Sep 2026 (acrm !3909, wave D): separator rows `{ key, sep: true }` with role=separator (edge/double separators dropped, same rule as Menu button), per-item `ariaLabel` for rows whose visible text is shorter than the full sentence, and a clear row (`clearLabel`/`clearIcon`/`onClear`) — role=menuitem, no check, NOT danger (clearing a value is reversible; red is only for deleting data). No group headings. Registry repaired 17 Oct 2026 (review F6): added exported PickerMenuPanel to react[].","source":"package","react":["PickerMenu","PickerMenuPanel"],"classes":[".acrm-popover",".acrm-popover-item",".acrm-popover-sep",".acrm-popover-empty"],"files":["packages/ui/src/components/PickerMenu.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--picker-menu--default"],"Variants":["components--picker-menu--variants"],"Sizes":[],"States":["components--picker-menu--states"],"With icon & kbd":["components--picker-menu--with-icon-kbd"],"Composition":["components--picker-menu--composition"]},"legacy":["popover.html"],"related":["popover","nav-select","check-menu","select"],"docs":"docs/select/picker-menu","url":"http://192.168.230.131:3777/ds/components/select/picker-menu","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Popover & menu","card":"popover.html","react":["Popover","PickerMenu","NavSelect"],"classes":[],"tokens":[],"status":"OK","note":""}}},{"id":"check-menu","name":"Check menu","summary":"The one menu for toggling a set of options (columns, tiles, categories): checkbox on the right, optional search, hidden items below a line, reorder by drag or Alt+↑/↓; bottom sheet with Hotovo on a phone.","status":"canon","shown":"canon","approvedAt":"2026-09-30","notes":"AD 30 Sep 2026: canon again. The one menu for toggling a set of OPTIONS (column visibility, tile layout, category filter) with optional search, hidden-below-divider and reorder; RecordSelect multi stays the picker of RECORDS. Select has no multiple mode, so the old replacedBy was void. approvedAt after the stories show search, hidden items, keyboard reorder (Alt+↑↓) and the phone sheet. Registry repaired 17 Oct 2026 (review F1): apps/web/src/ds/check-menu.css no longer exists; reorder styling is in ds/reorder.css (step F4). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .cm-reorder, .cm-dragging, .cm-drop-line, .cm-sheet. Registry repaired 17 Oct 2026 (review F4/F11): attached css reorder.css.","source":"app-css","react":["CheckMenu"],"classes":[".acrm-popover",".acrm-popover-item",".acrm-checkbox",".cm-list",".acrm-recordselect-search",".acrm-popover-sep",".acrm-popover-empty"],"files":["apps/web/src/components/CheckMenu.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/inputs.css","apps/web/src/ds/reorder.css"],"stories":{"Default":["components--check-menu--default"],"Variants":["components--check-menu--variants"],"Sizes":[],"States":["components--check-menu--states"],"With icon & kbd":[],"Composition":["components--check-menu--composition"]},"legacy":["popover.html","Inputs.html"],"related":["record-select","picker-menu","segment-table","checkbox"],"docs":"docs/select/check-menu","url":"http://192.168.230.131:3777/ds/components/select/check-menu","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"entity-picker","name":"Entity picker","summary":"Record reference field: removable record chips plus Add, built on the canonical RecordSelect (server search, recent, create from e-mail).","status":"beta","shown":"beta","approvedAt":null,"notes":" `apps/web/src/lib/anchored-panel.ts` is gone from origin/main — anchoring moved into the shared Popover (acrm 26de4b54b, AddRefMenu/RecipientInput/AssignPicker/deal-parts); the reference was dropped from this entry. Optional prop `recent` (27 Sep 2026, `RelationDialog`'s entity picker is the first consumer): on an empty/below-minimum query it offers recently opened records of the allowed `types` instead of the \"type at least N characters\" hint, sourced from `useRecentRecords` (`GET /search/recent` → `record_views`, written server-side when a record's detail loads — real opens, not search clicks). Rows reuse the exact `.acrm-recordselect-opt` markup and `add()` path as a search result; already-selected and locked records are filtered out client-side. Without the prop the picker behaves exactly as before. Debt: `EntityPicker` lives in `apps/web/src/components/EntityPicker.tsx`, not `packages/ui`, so it has no Ladle story — behaviour is covered by `relation-dialog.test` instead. Move it to `packages/ui` to get stories (AD 27 Sep 2026). 3 Oct 2026 (AD): deprecated → beta. The duplicate shell is gone (AddRefMenu removed, 4a9a934e0; ProductPicker on RecordSelect since 1 Oct); it is a composition over RecordSelect, not a second picker. Migrating its consumers would rebuild the same composition each time. Canon after: move into @acrm/ui with stories (Default · States · Composition) + baselines, usage/a11y rewritten. 3 Oct 2026: shell is DS.RecordRefField in @acrm/ui (acrm !4502); EntityPicker / ProductPicker are data wrappers around it, DOM 1:1. Focus returns to Přidat on close. Registry repaired 17 Oct 2026 (review F1): AddRefMenu.tsx is gone from main (file reference dropped). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .acrm-popover.eref-add-pop.","source":"app-css","react":["EntityPicker","RecordRefField"],"classes":[".eref-field",".eref-add",".add-ref",".acrm-recordselect-search",".acrm-recordselect-list",".acrm-recordselect-opt",".acrm-recordselect-empty",".mi-opt-ic"],"files":["apps/web/src/components/EntityPicker.tsx","apps/web/src/components/useAddRefPopover.ts","apps/web/src/components/search/useRecentRecords.ts","packages/ui/src/components/RecordRefField.tsx","packages/ui/stories/record-ref-field.stories.tsx"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds.css","apps/web/src/ds/task-form.css"],"stories":{"Default":["components--record-reference-field--default"],"Variants":[],"Sizes":[],"States":["components--record-reference-field--states"],"With icon & kbd":[],"Composition":["components--record-reference-field--composition"]},"legacy":["Inputs.html"],"related":["record-select","entity-ref","product-picker"],"docs":"docs/select/entity-picker","url":"http://192.168.230.131:3777/ds/components/select/entity-picker","coverage":{"stories":false,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":false,"approved":false,"api":true},"covered":false,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"product-picker","name":"Product picker","summary":"Product field: product chips plus Add, built on the canonical RecordSelect in adding mode, with free text.","status":"beta","shown":"beta","approvedAt":null,"notes":"3 Oct 2026 (AD): deprecated → beta. The duplicate shell is gone (AddRefMenu removed, 4a9a934e0; ProductPicker on RecordSelect since 1 Oct); it is a composition over RecordSelect, not a second picker. Migrating its consumers would rebuild the same composition each time. Canon after: move into @acrm/ui with stories (Default · States · Composition) + baselines, usage/a11y rewritten. 3 Oct 2026: shell is DS.RecordRefField in @acrm/ui (acrm !4502); EntityPicker / ProductPicker are data wrappers around it, DOM 1:1. Focus returns to Přidat on close. Registry repaired 17 Oct 2026 (review F1): AddRefMenu.tsx is gone from main (file reference dropped). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .acrm-popover.eref-add-pop.","source":"app-css","react":["ProductPicker","RecordRefField"],"classes":[".eref-field",".eref-add",".add-ref",".acrm-recordselect-search",".acrm-recordselect-list",".acrm-recordselect-opt",".acrm-recordselect-empty",".mi-opt-ic",".acrm-pill"],"files":["apps/web/src/components/ProductPicker.tsx","apps/web/src/components/useAddRefPopover.ts","packages/ui/src/components/RecordRefField.tsx","packages/ui/stories/record-ref-field.stories.tsx"],"css":["apps/web/src/ds/inputs.css","apps/web/src/ds.css","apps/web/src/ds/task-form.css"],"stories":{"Default":["components--record-reference-field--default"],"Variants":[],"Sizes":[],"States":["components--record-reference-field--states"],"With icon & kbd":[],"Composition":["components--record-reference-field--composition"]},"legacy":["Inputs.html"],"related":["entity-picker","record-select","entity-ref","pill"],"docs":"docs/select/product-picker","url":"http://192.168.230.131:3777/ds/components/select/product-picker","coverage":{"stories":false,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":false,"approved":false,"api":true},"covered":false,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}}]},{"id":"choice","name":"Choice","category":"Forms & input","summary":"Binary and small-set choices: checkbox, radio, switch, segmented and chips.","url":"http://192.168.230.131:3777/ds/components/choice","coverage":100,"subcomponents":[{"id":"checkbox","name":"Checkbox","summary":"One checkbox shape in the whole app: a drawn 16px box (5px corners, bold check) over a transparent native input; menu rows use the same box with state classes. For selecting items — a property on/off is a Switch.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Owner approved v2 on 28 Sep 2026: ONE shape (drawn box, bold check stroke 3.5, 5px corners in the compact-button ratio, border --fg-secondary 3.93:1, mixed = accent, disabled state, indeterminate prop). Replaces D6 (22 Aug 2026: native accent-color box in forms, drawn box in menus). Properties of a record (Active, Track opens, Default for domain) moved to Switch. Validator checkbox-native-no-ds is HARD.","source":"package","react":["Checkbox"],"classes":[".acrm-checkfield",".acrm-check-input",".acrm-checkbox",".acrm-check-label",".acrm-check-row",".is-on",".is-mixed",".is-disabled"],"files":["packages/ui/src/components/Checkbox.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/inputs.css"],"stories":{"Default":["components--checkbox--default"],"Variants":["components--checkbox--variants"],"Sizes":[],"States":["components--checkbox--states"],"With icon & kbd":[],"Composition":["components--checkbox--composition"]},"legacy":["Inputs.html"],"related":["radio","switch"],"docs":"docs/choice/checkbox","url":"http://192.168.230.131:3777/ds/components/choice/checkbox","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"radio","name":"Radio","summary":"Exclusive choice within a group.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"app-css","react":[],"classes":[".acrm-radio",".acrm-radio-group",".acrm-radio-input",".acrm-radio-dot"],"files":["apps/web/src/ds/inputs.css"],"css":["apps/web/src/ds/inputs.css"],"stories":{"Default":["components--radio--default"],"Variants":[],"Sizes":[],"States":["components--radio--states"],"With icon & kbd":[],"Composition":["components--radio--composition"]},"legacy":["Inputs.html"],"related":["checkbox","segmented-control"],"docs":"docs/choice/radio","url":"http://192.168.230.131:3777/ds/components/choice/radio","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"switch","name":"Switch","summary":"On/off control that applies immediately.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Size sm (acrm !3911, AD 26 Sep 2026): 30×17, knob 13px, --shadow-xs, label var(--small) in --fg-secondary, gap --sp-2 — ONLY the secondary option in a dialog footer next to buttons (Další / Vytvořit další / Nevolat / Pozvánky); the full size would compete with the primary. Replaces the private .tk-more/.sw copy — migrated on 27 Sep 2026 (acrm !3950): TaskDialog „Další“, NewContactDialog „Vytvořit další“/„Nevolat“, NewMeetingForm „Pozvánky“/„Nahrávat“; .tk-more/.sw deleted, the app has ONE switch. Clickable label (acrm !3933, AD 26 Sep 2026): a click on the VISIBLE label toggles (not with labelHidden); focus stays on the role=switch button, onChange(on, event) keeps stopPropagation for clickable rows, no double toggle.","source":"package","react":["Switch"],"classes":[".acrm-switch",".acrm-switch-row"],"files":["packages/ui/src/components/Switch.tsx","apps/web/src/ds/inputs.css"],"css":["apps/web/src/ds/inputs.css"],"stories":{"Default":["components--switch--default"],"Variants":["components--switch--variants"],"Sizes":["components--switch--sizes"],"States":["components--switch--states"],"With icon & kbd":[],"Composition":["components--switch--composition"]},"legacy":["Inputs.html"],"related":["checkbox"],"docs":"docs/choice/switch","url":"http://192.168.230.131:3777/ds/components/choice/switch","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"segmented-control","name":"Segmented control","summary":"Inline group of mutually exclusive buttons for switching modes.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"acrm !4066 (28 Sep 2026): SegmentedOption.count?: number — neutral .acrm-count after the label (CountBadge look, never accent), 0 not drawn; first use segment detail \"Vše | Přírůstky (N)\" (replaced .sgb-ctl chips). 30 Sep 2026 (acrm !4252, AD FA218): option prop tone?: positive | warning | critical colours only the TEXT of the selected option (.on.seg-tone-*) with --positive-ink / --warning-ink / --critical-ink (AA ≥ 5.3:1 light and dark). Only for an answer with meaning (yes / maybe / no, e.g. meeting RSVP), never decoration; selection still carried by the surface and aria-pressed.","source":"package","react":["Segmented"],"classes":[".acrm-segmented"],"files":["packages/ui/src/components/Segmented.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/inputs.css"],"stories":{"Default":["components--segmented-control--default"],"Variants":["components--segmented-control--variants"],"Sizes":[],"States":[],"With icon & kbd":["components--segmented-control--with-icon-kbd"],"Composition":["components--segmented-control--composition"]},"legacy":["segmented.html"],"related":["tab-strip","radio"],"docs":"docs/choice/segmented-control","url":"http://192.168.230.131:3777/ds/components/choice/segmented-control","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"option-chips","name":"Option chips","summary":"Row of selectable chips for a small set of options.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"app-css","react":[],"classes":[".acrm-optchips",".acrm-optchip"],"files":["apps/web/src/ds/inputs.css"],"css":["apps/web/src/ds/inputs.css"],"stories":{"Default":["components--option-chips--default"],"Variants":[],"Sizes":[],"States":["components--option-chips--states"],"With icon & kbd":["components--option-chips--with-icon-kbd"],"Composition":["components--option-chips--composition"]},"legacy":["Inputs.html"],"related":["segmented-control","removable-chip"],"docs":"docs/choice/option-chips","url":"http://192.168.230.131:3777/ds/components/choice/option-chips","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Inputs","card":"inputs.html","react":["Field","Input","Select","Textarea","Checkbox","Switch"],"classes":[".acrm-input",".acrm-field"],"tokens":[],"status":"OK","note":""}}},{"id":"color-picker","name":"Color picker","summary":"Grid of colour swatches (radiogroup, arrows, optional 'no colour' row) and its canonical wrapper: popover on desktop, sheet on the phone, InSheet panel inside a dialog.","status":"canon","shown":"canon","approvedAt":"2026-10-01","notes":"acrm !4337 (one swatch grid instead of four copies: EventLabelPicker, EventTypeFilter, MailLabelDialog use ColorPicker; SegmentIconPicker keeps its own panel and uses ColorSwatches for SEGMENT_TONES — validator exception), !4347 (phone: swatches span the width, 44 px targets, segment icon tiles capped at --tap-min), !4354 (stories + usage/a11y), !4363 (a11y: 'Bez barvy' is a radio of the same group with a check on the right; roving tabindex — one Tab stop on the chosen option; focus ring and selection ring read apart). Canon 1. 10. 2026 (AD) after before/after app screenshots (1440 + 390, light/dark) and the States story. Custom hex colour in the segment picker unchanged; dropping it is a separate owner decision.","source":"app-css","react":["ColorSwatches","ColorPicker"],"classes":[".ctype-grid",".ctype-sw",".cs-tones"],"files":["apps/web/src/components/color/ColorSwatches.tsx","apps/web/src/components/color/ColorPicker.tsx"],"css":["apps/web/src/ds/calendar.css","apps/web/src/ds/segment-screen.css","apps/web/src/ds/responsive.css"],"stories":{"Default":["components--color-picker--default"],"Variants":["components--color-picker--variants"],"Sizes":[],"States":["components--color-picker--states"],"With icon & kbd":[],"Composition":["components--color-picker--composition"]},"legacy":[],"related":["check-menu","picker-menu","popover"],"docs":"docs/choice/color-picker","url":"http://192.168.230.131:3777/ds/components/choice/color-picker","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"slider","name":"Slider","summary":"Native range input with an accent fill driven by --acrm-slider-p.","status":"deprecated","shown":"deprecated","approvedAt":null,"notes":"Registry repaired 17 Oct 2026 (review F3): added as candidate so its existing Ladle stories (packages/ui/stories/slider.stories.tsx) are visible; no usage.md / a11y.md yet.","source":"app-css","react":[],"classes":[".acrm-slider"],"files":["apps/web/src/ds/inputs.css"],"css":["apps/web/src/ds/inputs.css"],"stories":{"Default":["components--slider--default"],"Variants":[],"Sizes":[],"States":["components--slider--states"],"With icon & kbd":[],"Composition":["components--slider--composition"]},"legacy":[],"related":["switch"],"docs":"docs/choice/slider","url":"http://192.168.230.131:3777/ds/components/choice/slider","coverage":{"stories":true,"props":false,"classes":true,"usage":false,"a11y":false,"baseline":true,"approved":false,"api":true},"covered":false,"implementation":{"acrm":null}}]},{"id":"date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first.","name":"Date & time","category":"Forms & input","summary":"Typed and picked dates, times and ranges sharing one calendar.","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first.","coverage":100,"subcomponents":[{"id":"date-field","name":"Date field","summary":"Input that parses typed dates and opens the calendar panel.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"package","react":["DateField"],"classes":[".dp-field",".dp-input",".dp-open",".dp-clear"],"files":["packages/ui/src/components/DateField.tsx"],"css":["apps/web/src/ds/date-picker.css"],"stories":{"Default":["components--date-field--default"],"Variants":["components--date-field--variants"],"Sizes":[],"States":["components--date-field--states"],"With icon & kbd":[],"Composition":["components--date-field--composition"]},"legacy":["dates.html"],"related":["calendar","picker-panel","time-field"],"docs":"docs/date-time/date-field","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first./date-field","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"time-field","name":"Time field","summary":"Input that parses typed times with a list of quarter-hour options.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"acrm !4087 (28 Sep 2026, owner): the visible duration next to times uses `fmtDurShort` — „45 m“ · „1 h“ · „1 h 30 m“ (in the context of time „m“ = minutes). Screen readers keep the full „min“ via `fmtDur` (TimeField option aria-label, DateTimeRange hidden live text) so „m“ is not read as metres. Other durations in the app (timeline, Setkání, tasks, reminders) keep „min“.","source":"package","react":["TimeField"],"classes":[".dp-field",".dp-timelist",".dp-topt"],"files":["packages/ui/src/components/TimeField.tsx"],"css":["apps/web/src/ds/date-picker.css"],"stories":{"Default":["components--time-field--default"],"Variants":["components--time-field--variants"],"Sizes":[],"States":["components--time-field--states"],"With icon & kbd":[],"Composition":["components--time-field--composition"]},"legacy":["dates.html"],"related":["date-field","date-time-range"],"docs":"docs/date-time/time-field","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first./time-field","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"date-range","name":"Date range","summary":"Paired inputs for a from–to date span with presets.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"package","react":["DateRangeField"],"classes":[".dp-field",".dp-entry",".dp-sep",".dp-presets",".dp-preset"],"files":["packages/ui/src/components/DateRangeField.tsx"],"css":["apps/web/src/ds/date-picker.css"],"stories":{"Default":["components--date-range--default"],"Variants":["components--date-range--variants"],"Sizes":[],"States":["components--date-range--states"],"With icon & kbd":[],"Composition":["components--date-range--composition"]},"legacy":["dates.html"],"related":["date-field","calendar"],"docs":"docs/date-time/date-range","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first./date-range","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"date-time-range","name":"Date-time range","summary":"Start and end with time, all-day toggle and duration presets.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"M4c (owner 28 Sep 2026, approved): all-day renders the canonical DateRangeField (from–to in one field, shared calendar, day count) instead of two DateFields with their own day arithmetic — one shape for a range of days; `.dp-field.range` ends share the field width (width 0 + flex 1), so the term row no longer overflows on 390 px (acrm branch feat/celodenni-rozsah). acrm !4087 (28 Sep 2026, owner): the visible duration next to times uses `fmtDurShort` — „45 m“ · „1 h“ · „1 h 30 m“ (in the context of time „m“ = minutes). Screen readers keep the full „min“ via `fmtDur` (TimeField option aria-label, DateTimeRange hidden live text) so „m“ is not read as metres. Other durations in the app (timeline, Setkání, tasks, reminders) keep „min“.","source":"package","react":["DateTimeRangeField"],"classes":[".dp-stack",".dp-termin",".dp-timegroup",".dp-switches",".dp-recur",".dp-dur",".dp-status"],"files":["packages/ui/src/components/DateTimeRangeField.tsx"],"css":["apps/web/src/ds/date-picker.css"],"stories":{"Default":["components--date-time-range--default"],"Variants":["components--date-time-range--variants"],"Sizes":[],"States":["components--date-time-range--states"],"With icon & kbd":[],"Composition":["components--date-time-range--composition"]},"legacy":["dates.html"],"related":["date-range","time-field"],"docs":"docs/date-time/date-time-range","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first./date-time-range","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"calendar","name":"Calendar","summary":"Month grid with navigation and presets, single or range selection.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Calendar PAGE chrome (acrm !3942, AD 27 Sep 2026): month label = SectionTopBarChip opening the jump popover (the page title stays „Kalendář“); year ←→ = IconButton sm; the 12-month grid reuses the day cell `.dp-day` with `.sel` + aria-current — one „selected“ look for date picking, no button variant as state. DELIBERATE EXCEPTION: the nav trio ‹ ● › (previous · today · next) keeps its own look per the owner’s ACRM-91/97/103 (arrows without a hover surface that only darken, „Dnes“ a small grey circle-dot) — real <button>s with aria-label and a focus ring, tokens only; do not convert to IconButton. The day-panel ear (.cal-ear) is a second exception (surface chrome, tokens only).","source":"package","react":["Calendar"],"classes":[".dp-pop",".dp-month",".dp-grid",".dp-day",".dp-nav",".dp-wd"],"files":["packages/ui/src/components/Calendar.tsx"],"css":["apps/web/src/ds/date-picker.css"],"stories":{"Default":["components--calendar--default"],"Variants":["components--calendar--variants"],"Sizes":["components--calendar--sizes"],"States":["components--calendar--states"],"With icon & kbd":[],"Composition":["components--calendar--composition"]},"legacy":["dates.html"],"related":["date-field","picker-panel"],"docs":"docs/date-time/calendar","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first./calendar","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"picker-panel","name":"Picker panel","summary":"Anchored floating container that hosts the calendar or time list.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"package","react":["PickerPanel"],"classes":[".dp-panel",".dp-scrim"],"files":["packages/ui/src/components/PickerPanel.tsx"],"css":["apps/web/src/ds/date-picker.css"],"stories":{"Default":["components--picker-panel--default"],"Variants":["components--picker-panel--variants"],"Sizes":[],"States":[],"With icon & kbd":[],"Composition":["components--picker-panel--composition"]},"legacy":["dates.html"],"related":["calendar","popover"],"docs":"docs/date-time/picker-panel","url":"http://192.168.230.131:3777/ds/components/date-time AD 24 Oct 2026: 0 uses in the app (only Ladle stories) → deprecated; reopen as a candidate only with a real consumer. Subtract-first./picker-panel","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"filter","name":"Filter","category":"Forms & input","summary":"Notion-style filter bar: every chip carries a value, no empty chips.","url":"http://192.168.230.131:3777/ds/components/filter","coverage":100,"subcomponents":[{"id":"filter-bar","name":"Filter bar","summary":"Row of filter chips with add, reset and save controls.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"React implementation lives in the app (apps/web/src/components/FilterBar.tsx), not in @acrm/ui. Phone (owner 2026-09-28, acrm !4088): with onOpenChange the bar is the bottom sheet „Filtry\" (search, conditions with ⋮ Odebrat, Přidat filtr, Vymazat vše, Hotovo); the Filtr toggle shows a neutral CountBadge, Řadit (SegmentScreen) a sort sheet; „Uložit pro všechny\" moves to the bar's ⋮ (phoneOnly). „Vymazat filtry\" = Button ghost tone muted. Desktop unchanged. 14 Oct 2026 (owner \"24c approved\", proto/lista-vypisu@a16fe17a7, acrm !5045): no word labels — Filtr = icon (+ dot), Seskupit/Řadit/Zobrazení = icon + chosen value, field name only in aria-label/tooltip; open row: chip = field icon + value, „+\" and „×\" icons; closed by default, „Jen moje\" is a chip inside Filtr. Dev check 14 Oct on /tasks /pipeline /objednavky /setkani /lide, 1440 + 390: 0 label words, no overflow. Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .fb-add, .fb-reset, .fb-save.","source":"app-css","react":["FilterBar","FilterToggleChip"],"classes":[".fb-clear",".fb-conj",".fb-menu",".fb-sheet",".fb-sheet-body",".fb-sheet-row",".fb-count"],"files":["apps/web/src/ds/filter-bar.css","apps/web/src/components/FilterBar.tsx"],"css":["apps/web/src/ds/filter-bar.css"],"stories":{"Default":["components--filter-bar--default"],"Variants":["components--filter-bar--variants"],"Sizes":[],"States":["components--filter-bar--states"],"With icon & kbd":["components--filter-bar--with-icon-and-kbd"],"Composition":["components--filter-bar--composition"]},"legacy":["filter-bar.html"],"related":["filter-chip","section-top-bar","picker-menu","fab"],"docs":"docs/filter/filter-bar","url":"http://192.168.230.131:3777/ds/components/filter/filter-bar","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"filter-chip","name":"Filter chip","summary":"One filter field written out: icon, field name and value; the chip opens the field menu.","status":"canon","shown":"canon","approvedAt":"2026-09-09","notes":"Rendered by FilterBar.tsx (ChipMenu); the menu frame is the canonical Popover. 14 Oct 2026 (acrm !5045): chip = field icon + value, field name in aria-label/title (RULES §24.3).","source":"app-css","react":[],"classes":[".fb-chip",".fb-opt",".fb-group"],"files":["apps/web/src/ds/filter-bar.css"],"css":["apps/web/src/ds/filter-bar.css"],"stories":{"Default":["components--filter-chip--default"],"Variants":["components--filter-chip--variants"],"Sizes":[],"States":["components--filter-chip--states"],"With icon & kbd":["components--filter-chip--with-icon-and-kbd"],"Composition":["components--filter-chip--composition"]},"legacy":["filter-bar.html"],"related":["filter-bar","removable-chip"],"docs":"docs/filter/filter-chip","url":"http://192.168.230.131:3777/ds/components/filter/filter-chip","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"dialog","name":"Dialog","category":"Overlays & dialogs","summary":"Modal and modeless windows for focused tasks, from confirm to full form.","url":"http://192.168.230.131:3777/ds/components/dialog","coverage":86,"subcomponents":[{"id":"dialog","name":"Dialog","summary":"Window for one focused task, in four variants: plain, form-less (creates or edits one record without form fields — see Form-less dialog), confirm (the one way to ask \"are you sure?\") and window states (expanded · compact · minimised to the dock).","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Merged 14 September 2026 (AD, OV-1): Confirm and Window states were separate cards; measured in the DOM they are the same <Dialog> with the same shell, differing only in width (640 / 400 / 380) and in whether the window can shrink. No code changed. Accessibility docs corrected at the same time: the focus trap, the scroll lock and the inert background exist on main since 9 September 2026 (G2, ccd9350dc) — the old cards still listed them as missing. Registry repaired 17 Oct 2026 (review F6): added exported BottomSheet, InSheetProvider, PortalRoot to react[].","source":"package","react":["Dialog","ConfirmProvider","useConfirm","BottomSheet","InSheetProvider","PortalRoot"],"classes":[".acrm-dialog",".acrm-dialog-scrim",".acrm-dialog-head",".acrm-dialog-body",".acrm-dialog-foot",".acrm-dialog-ic",".acrm-dialog-confirm-text",".acrm-dialog-bar",".acrm-dialog-bar-t",".acrm-dialog-bar-x",".acrm-dialog-ctl",".acrm-dialog-dock",".acrm-dialog-grab"],"files":["packages/ui/src/components/Dialog.tsx","packages/ui/src/components/Confirm.tsx","packages/ui/src/lib/dialog-dock.ts","apps/web/src/ds/dialog-window.css","packages/ui/src/components/BottomSheet.tsx","packages/ui/src/lib/portal-root.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/dialog-window.css"],"stories":{"Default":["components--dialog--default"],"Variants":["components--dialog--variants","components--form-less-dialog--default","components--confirm--default","components--confirm--variants","components--window-states--default","components--window-states--variants"],"Sizes":["components--dialog--sizes"],"States":["components--dialog--states","components--confirm--states","components--window-states--states"],"With icon & kbd":["components--dialog--with-icon-and-kbd"],"Composition":["components--dialog--composition","components--confirm--composition","components--window-states--composition"]},"legacy":["dialog.html","dialog-window-states.html"],"related":["formless-dialog","drawer-form","record-drawer","popover","toast","button"],"docs":"docs/dialog/dialog","url":"http://192.168.230.131:3777/ds/components/dialog/dialog","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Dialog system","card":"dialog.html","react":["Dialog","ConfirmProvider"],"classes":[".acrm-dialog"],"tokens":[],"status":"OK","note":""}}},{"id":"multi-step-dialog","name":"Multi-step dialog","summary":"One window that walks through steps and reshapes itself between them (width and height, on the canonical spring) instead of closing and opening another window. First case: New deal — search for the person or company first (Attio \"Choose record\" anatomy, with a persistent footer), then the form-less detail.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"27 September 2026: the Attio rework merged (feat/acrm-322-vyber-zaznamu, main 40402b85) — DealSubjectStep gained a persistent footer (↑↓ Navigate + MorphText primary action \"Select record\"/\"Create person\"), Records/Actions sections, record type in the meta slot, and paletteWidth(phone). The window reshape moved from the 0.29s cubic-bezier curve to the canonical spring (packages/ui/src/lib/spring.ts, merged as !3957) — see the `spring` and `morph-text` subcomponents. 25 September 2026: the AD had rejected the search step as shipped (palette anatomy without header/footer) — it did not follow the brief (Attio \"Choose record\"); rework then went to proto/obchod-vyber-attio, now merged as above. AD approved 18 September 2026 on the prototype :3777/preview/obchod-vicekrokovy.html (ACRM-322, ACRM-323). Code: acrm !3777 (<Dialog morphKey>, dialog-morph.css, story + baseline) and !3779 (new-deal flow: DealSubjectStep, Založit osobu → NewContactDialog). Merged 18 September 2026 (!3775, !3777, !3779) — canon. 14 Oct 2026 (owner: the big palette is intentional — „v malém inline dialogu se blbě hledá“): the palette shell (PickPalette, extracted from DealSubjectStep) is the RULES §21 pattern for assigning a record — chat Přiřadit ke kontaktu, Komunikace Přiřadit k projektu, Přidat produkt, Vztahy › Přidat (acrm !5039, 0c0f21ee1). Dev check 14 Oct: 1440 = 800 px, focus in search; 390 = full height 0–844 for the §21 places; Nový obchod on phone 0–844 too (re-measured after deploy). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .gsp-cancel. Registry repaired 17 Oct 2026 (review F5): DealDialog, DealSubjectStep, NewContactDialog live in apps/web (see files), not exported by @acrm/ui; dropped from react[].","source":"package","react":["Dialog"],"classes":[".acrm-dialog.morph",".acrm-dialog.deal.pick",".gsp-q",".gsp-body",".gsp-sec",".acrm-dialog-foot"],"files":["packages/ui/src/components/Dialog.tsx","apps/web/src/ds/dialog-morph.css","apps/web/src/components/deal/DealDialog.tsx","apps/web/src/components/deal/DealSubjectStep.tsx","apps/web/src/ds/deal-dialog.css","apps/web/src/components/person/NewContactDialog.tsx"],"css":["apps/web/src/ds/dialog-morph.css","apps/web/src/ds/global-search.css","apps/web/src/ds/deal-dialog.css"],"stories":{"Default":["components--multi-step-dialog--default"],"Variants":[],"Sizes":[],"States":[],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["dialog","formless-dialog","command-palette","spring","morph-text"],"docs":"docs/dialog/multi-step-dialog","url":"http://192.168.230.131:3777/ds/components/dialog/multi-step-dialog","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"spring","name":"Spring","summary":"Damped-oscillator physics (stiffness 190, damping 17, ~750ms, ~6% overshoot) sampled into WAAPI keyframes — the one physical motion for every reshape between states (dialog window, button/text width, list cursor). Replaces the earlier 0.29s cubic-bezier(0.32, 0.72, 0, 1) curve as canon (RULES.md §11).","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"27 September 2026: merged on main as !3957 (feat/acrm-322: pružina — přetvarování dialogu a MorphText). Drives <Dialog morphKey>'s window resize and MorphText's width. Small-element morphs written before this module (ChipMorph, NoteRecChip) still run the old 0.29s cubic-bezier curve pending their own migration — see ChipMorph.tsx's own comment (\"do doby, než ho nahradí pružina\").","source":"package","react":["springAnimate","springValues","prefersReducedMotion","SPRING_MS","SPRING_ARRIVE_MS"],"classes":[],"files":["packages/ui/src/lib/spring.ts"],"css":[],"stories":{"Default":["components--spring--default"],"Variants":[],"Sizes":[],"States":["components--spring--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["dialog","multi-step-dialog","morph-text"],"docs":"docs/dialog/spring","url":"http://192.168.230.131:3777/ds/components/dialog/spring","coverage":{"stories":true,"props":false,"classes":false,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":false},"covered":false,"implementation":{"acrm":null}},{"id":"morph-text","name":"MorphText","summary":"A text layer whose width moves on the spring while the old and new text cross-fade in place — one element that reshapes, never two labels swapped. First shipped use: the New deal search step's primary action, \"Select record\" ↔ \"Create person\".","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"27 September 2026: merged on main as !3957. Used live in DealSubjectStep's footer CTA (feat/acrm-322-vyber-zaznamu, main 40402b85).","source":"package","react":["MorphText"],"classes":[".acrm-morph-text",".acrm-morph-text-l"],"files":["packages/ui/src/components/MorphText.tsx","apps/web/src/ds/dialog-morph.css"],"css":["apps/web/src/ds/dialog-morph.css"],"stories":{"Default":["components--morphtext--default"],"Variants":[],"Sizes":[],"States":["components--morphtext--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["multi-step-dialog","button","spring"],"docs":"docs/dialog/morph-text","url":"http://192.168.230.131:3777/ds/components/dialog/morph-text","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"formless-dialog","name":"Form-less dialog","summary":"Creates or edits one record without form fields: an icon carries each row and the placeholder names it. Shape A writes text plus properties as chips in the body; shape B asks what · when · with whom · how · where.","status":"canon","shown":"canon","approvedAt":"2026-09-09","notes":"Promoted to a rule by the product owner on 9 September 2026 (\"promote form-less to a rule and review the other form dialogs with the aim of unifying them\"); the pattern itself was approved by the AD on 7 September and shape B shipped to dev on 8 September (ACRM-132, MRs !3163–!3166). The code is the source of truth. THE RULE: form-less when the dialog creates or edits one record whose properties can be named by a placeholder; a form when it is data entry with many typed values and the label carries the meaning — the test is whether the label can be replaced by a placeholder without losing the field identity. Shape B (`.fl-*`) is the documented engine and the only one with a shared sheet. Shape A still runs as three private copies — `.tk-*` (task-dialog.css), `.dl-*` (deal-dialog.css), `.nd-*` + `.dlg-title` (note-dialog.css, dialog-doc.css) — with MetaChip declared twice in TSX; merging them onto `.fl-*` is wave 0 and until it lands shape A is a named shape, not a catalogued one. Adoption measured at main 06fb6b236: 2 dialogs on shape B, 3 on shape A, 43 forms — of which 12 are correctly forms (accounting document 13 fields, Spravovat segment 37, payroll relation, VAT period, mailbox) and 12 are conversion candidates with their questions listed in docs/REVIEW-form-dialogy.md. No stories yet — the pattern lives in apps/web, which packages/ui must not import, so they will be ported markup like Filter bar and Command palette. Three defects open in the shipped code (all in the review): the RSVP dot has no accessible name because aria-label sits on a role=\"generic\" span (EntityPicker.tsx:191); --ic-amber 2.14:1 light and --ic-grey 2.97:1 dark fail the 3:1 non-text minimum while colour is the state’s only carrier; the availability day is mouse-only and role=\"presentation\" (MeetingAvailability.tsx:233). A row may carry several values stacked in `.fl-vals` with the icon on the first: the video-call link sits under the meeting type rather than asking its own question (AD 9 September 2026), which also ended the `link` glyph naming two different rows; the in-person meeting type took `coffee` the same day, so `users` names only the attendees and no glyph in the dialog carries two meanings. The rule is one meaning per AXIS, not per app: the *Typy událostí* filter keeps `users` for its Schůzky row because it switches categories of event rather than describing one meeting (AD, 9 September 2026). The EDIT footer deliberately has no Zrušit — over an existing record the word reads as \"cancel the meeting\", and the close control already closes the window (product owner, 8 September 2026). The CREATE dialog still has it, because with nothing saved yet the word is unambiguous; whether create should drop it too is open. Delivered 13 Sep 2026 (FL-5; ACRM-223/224/226; acrm !3466–!3476): shape A in all of task, deal and note; header = primary record (EntityRef) then classification, separated by --sp-5 rhythm without a slash, classification and ID in --fg-muted (.head-muted); links chip names records instead of counting them and never repeats the primary; the title is a growing textarea. The note keeps its 1128 × 828 work window. Person dialog (shape B, on main since 15 September 2026, acrm !3561 — `apps/web/src/components/person/NewContactDialog.tsx`, channel editor draft mode in acrm !3548, wiring into the people list and palette in !3575): reuses the record rail's own multi-value channel editor in draft mode (`local-channels.ts`, `draft`/`plainValues`) for e-mail and phone, adds `.fl-dup`/`.fl-chan`/`.fl-chan-v`, and is the first shape-B dialog to use `masked-date-input` for a typed field. `.fl-dup`/`.fl-chan`/`.fl-chan-v` ship in `dialog-formless.css`. See the \"person dialog\" subsection in formless-dialog.usage.md. Person dialog, custom fields (acrm !3699, 16 Sep 2026, ACRM-277): behind the same \"More details\" chip, after the tag row, the create dialog draws the tenant's custom fields of a person from the SAME registry the record rail reads (`api.customFields('contact')`) — no drift, a deactivated definition is not drawn. The definition's type picks the input: date → dd.mm.rrrr mask, select and yes/no → PickerMenu (free text would put a value outside the code list into the jsonb, where no filter finds it), number → numeric keyboard but not type=\"number\". Two items per row (like title prefix/suffix), leading glyph `clipboard-list` as in the rail. Values are written only after the record exists, via `setCustomValues` (the only path that merges jsonb; PATCH would overwrite keys from import, enrichment and the agent) and only the filled ones. Task dialog, suggestions from the typed title (acrm !3771, ACRM-213, approved 17 Sep 2026 — Linear \"Apply all quick suggestions\"): in a NEW task the existing `.flc-navrhy` group also offers what the title says — due date, priority, assignee only, only for an empty property (the default \"Ty\" assignee counts as empty), assignee only when the name fits exactly one colleague. Chip = canonical `.tk-chip` with the glyph of the property it sets (calendar · flag · user) and the sentence's own word (\"zítra\", \"v pátek\"); a quiet `IconButton` bolt (sm, 24px) BEFORE the chips applies all, drawn from two suggestions up. No new CSS. Computed in the browser (`lib/task-suggest.ts`), no model, no server call. ACRM-355 (acrm !3775): the note `.fl-note` is drawn by MentionInput (`.mi-editor.mi-multiline` = form-field frame, 88px); the form-less selectors carry `.mi-editor.mi-multiline.fl-note` so the note stays borderless at rest, on focus and while typing, whatever the CSS order. Relation dialog (shape B, acrm !4011, 27 Sep 2026 — `apps/web/src/components/relations/RelationDialog.tsx`, data/rules in `relations-data.ts`): the „New relation\"/„Edit relation\" dialog on a person or company card. The anchor (the card's own subject) is fixed as the `LeadEntity` in the header and is never repicked — a relation is an edge between two subjects, and `PATCH /relations/:id` does not accept `from`/`to` — so on edit the anchor never shows as an editable row. Icon+value rows carry no labels. The other side is a **generic entity** — company OR person, one `EntityPicker` (`types={['organization','contact']}`, `max={1}`) — because the product owner asked for the picker to stay general (\"vztah můžu mít i s osobou\", 27 Sep 2026) rather than splitting into a company dialog and a person dialog. Relation type is a `PickerMenu` grouped by the chosen entity's kind, with a `sep: true` separator row between the two groups; before an entity is picked, both groups show at once (the entity picked after the type discards a type that belongs to the other kind). \"Valid from\" is optional and typed into the `dd.mm.rrrr` mask (`MaskedDateInput`): the placeholder reads `field.validFromToday` while creating with nothing chosen (empty submits today) and `field.validFrom` on edit (empty keeps the stored date — clearing the field is never a silent delete of the start date). Position and share % rows draw only when the selected relation type's `allowsPosition`/`allowsShare` say so; a field outside the allowed set is always sent as `null` on submit, so switching type (e.g. „Společník\" → „Zaměstnanec\") clears it server-side instead of leaving a stale value. Footer: create = Cancel `Esc` + „Add relation\" `⌘↵`; edit = „Save\" only, no Cancel (the family rule — over an existing record `Zrušit` reads as \"cancel the relation\", and the close control already closes the window). Relationship type catalogue, person↔person (acrm !4010, migration `0416_relation_types_chot_prarodic.sql`, same 27 Sep 2026 change): „Manžel/ka\" renamed to „Choť\" (one word for both spouses), „Partner/ka\" renamed to „Partner\", and a new „Prarodič / Vnouče\" (Grandparent/Grandchild) type was added after Parent/Child. The migration only rewrites rows still holding the old default name — an admin rename made in Nastavení → Data → Vztahy is left alone. Shape B — the add-to-list dialog (acrm !4019, 27 Sep 2026): `AddToListDialog` (`apps/web/src/components/segment/AddToListDialog.tsx`) is a multi-select-from-search instance of the pattern — \"Multi-select from search in a dialog\". The card's own record (company or person) is the `LeadEntity` anchor in the header, unpickable, same as the relation dialog's anchor. The body is ONE field, \"Hledat nebo založit seznam\" (search or create a list), filtering the tenant's manual lists (`segment kind='manual'`) by normalized, diacritic-insensitive match. Each list is a row with the anatomy of `check-menu` — `.acrm-popover-item` holding the list's own segment tile (`.sg`, 18px, reused from the left menu — see \"Segment tile debt\" below) then the name and member count, with `.acrm-checkbox` on the right (`aria-pressed` on the row) — and a click toggles membership immediately, so the footer carries only \"Hotovo\". A \"Založit seznam „…\"\" row is appended only when nothing in the list matches the typed text exactly (no row for a name that already exists, so re-adding it is a toggle, not a duplicate). Enter is overloaded on the match count, not just an exact-match shortcut: with exactly one row still shown — even from a partial match like \"fin\" → \"Fintech — sledovat\" — Enter toggles that row; otherwise it creates the typed name (verified in `add-to-list-dialog.test.tsx`, case \"Enter při jediné ČÁSTEČNÉ shodě list přepne\"). Dynamic (filter) segments are excluded from this dialog on purpose — membership in them can't be set by hand, so an earlier version that listed them read-only was pure noise; the old `.atl-row`/`.atl-ic` row shape this dialog used before 27 Sep 2026 is now only used by the Trash page and the duplicates panel, not by any form-less dialog. \"Change role\" on the company card's person row (acrm !4020, 27 Sep 2026) now opens this same `RelationDialog` with `presetOther` set to the person — not a separate dialog: the older `PersonRoleDialog` component is REMOVED (`company/PersonRoleRelationDialog.tsx` is the new, thin wrapper that resolves the existing relation row, or passes `presetOther` when the person has no relation yet, and renders `RelationDialog`). `presetOther` (a `Mention`) fixes the picked-but-not-yet-saved other side of a NEW relation the same way `anchor` fixes the card's own side, so the entity picker does not show when the context already names both ends. Contact log dialog (shape A, `apps/web/src/components/timeline/ContactLogDialog.tsx`) — ONE dialog for „Zaznamenat kontakt“ on person, company, deal AND project (product owner 27 Sep 2026: „to je ten stejný dialog… použij ten samý prvek z DS“). Project as the main entity (acrm !4084, 28 Sep 2026): `entityType=\"project\"` writes the 4th slot via `POST /timeline/entry` (`projectId`, from !4048) rather than a picked link; the old, project-only `ProjectEntryDialog` is REMOVED (279-line component + its test deleted, `ProjectMeetingsTab` now opens `ContactLogDialog`). Recording chip (acrm !4072, 28 Sep 2026, approved „doplň možnost přidání nahrávky všude“): a `MetaChip` (glyph `microphone`) driven by `PickerMenu` in the chip row — items „Z Plaudu“ (only when `plaudQ.data?.configured`) and „Nahrát soubor“, plus a clear row „Odebrat nahrávku“ once something is picked. The chip's VALUE is the SOURCE (`t('contactLog.recordingPlaud')` / „N z Plaudu“ / „Soubor“), never the file or dictaphone item's name — those run long and the chip must not truncate (source: `apps/web/src/components/meetings/recording-sources.ts`, `RECORDING_SOURCE_ICON`). A log with a recording is submitted as a proběhlá SCHŮZKA (only a meeting can hold a recording): `POST /timeline/entry` returns `meetingId`, then the binary/Plaud import goes as a second call; a failed second call closes the dialog like a success with a warning toast rather than reopening a half-filled form (review !4072). `.fl-note.fl-note-open`: the writing area is the dialog's CORE (REVIEW-form-dialogy.md §3.1) and must hold its three-line height even after focus leaves it for a chip — before this the area collapsed on every chip click and the dialog jumped 38 px (28 Sep 2026). Pitfall, already hit once: the fix must NOT be a bare `.open` class on `.fl-note` — `ds:sync-check` then reads `.x.open` elsewhere in the DS sheet as adopted-and-missing and broke the person-record golden; the CSS/TSX carry the dialog-specific `.fl-note-open` name instead. Header centring: `.acrm-dialog-lead .flc { align-items: center }` plus, in a row with more than the entity alone, `margin-top: -1px` on the wrapper around the entity's `.eref-chip` (its 1px dashed name underline extends the box 1px down, which without the correction put the entity's optical centre 2.8px above the classification chip and the × — product owner 28 Sep 2026: „položky v záhlaví nejsou zarovnané vertikálně na střed“). The single-entity header next to the title alone (ACRM-319) is untouched — the rule only fires with a second flex child. 14 Oct 2026 (owner \"26 souhlas\", proto/schuzka-ticho@19b777808, acrm !5041): Nová schůzka is the quiet reference — row placeholders are one or two words (Účastníci · Místo nebo odkaz · Cíl · Poznámka pro účastníky), a property of a row (internal goal) is an icon with tooltip, never a sentence in the placeholder. Dev check 14 Oct 1440 + 390: rows single-line (40 / 44 px). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .fl-copy, .tk-att-w, .tk-att-x. Registry repaired 17 Oct 2026 (review F4/F11): attached css share-dialog-formless.css.","source":"app-css","react":["NewMeetingForm","EditMeetingForm","TaskDialog","DealDialog","NoteDialog","LeadEntity","RelationDialog","AddToListDialog","ContactLogDialog"],"classes":[".acrm-dialog.formless",".fl-body",".fl-stack",".fl-title-row",".fl-title",".fl-rows",".fl-row",".fl-ic",".fl-vals",".fl-in",".fl-text",".fl-sub",".fl-hint",".fl-link",".fl-when",".fl-when-edit",".fl-note",".fl-note-open",".fl-err",".fl-dup",".fl-chan",".fl-chan-v",".eref-wstate",".eref-dot",".eref-meta",".acrm-dialog.formless.avail",".fla",".fla-view",".fla-grid",".fla-hours",".fla-hour",".fla-track",".fla-line",".fla-plan",".flc",".flc-navrhy",".flc-mark",".tk-duo",".acrm-dialog-lead",".acrm-dialog.head-muted","textarea.fl-title",".acrm-popover-item",".acrm-checkbox",".atl-list"],"files":["apps/web/src/components/meetings/NewMeetingForm.tsx","apps/web/src/components/calendar/EditMeetingForm.tsx","apps/web/src/components/meetings/MeetingAvailability.tsx","apps/web/src/ds/dialog-formless.css","apps/web/src/components/tasks/TaskDialog.tsx","apps/web/src/components/ChipDuo.tsx","apps/web/src/ds/task-dialog.css","apps/web/src/components/person/NewContactDialog.tsx","apps/web/src/components/tasks/TaskTitleSuggestions.tsx","apps/web/src/lib/task-suggest.ts","apps/web/src/components/relations/RelationDialog.tsx","apps/web/src/components/relations/relations-data.ts","apps/web/src/components/segment/AddToListDialog.tsx","apps/web/src/components/timeline/ContactLogDialog.tsx"],"css":["apps/web/src/ds/dialog-formless.css","apps/web/src/ds/responsive.css","apps/web/src/ds/task-dialog.css","apps/web/src/ds.css","apps/web/src/ds/segment-screen.css","apps/web/src/ds/share-dialog-formless.css"],"stories":{"Default":["components--form-less-dialog--default"],"Variants":["components--form-less-dialog--variants"],"Sizes":[],"States":["components--form-less-dialog--states"],"With icon & kbd":["components--form-less-dialog--with-icon-and-kbd"],"Composition":["components--form-less-dialog--composition"]},"legacy":[],"related":["dialog","drawer-form","entity-reference","date-time","record-rail","check-menu"],"docs":"docs/dialog/formless-dialog","url":"http://192.168.230.131:3777/ds/components/dialog/formless-dialog","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"note-dialog","name":"Note dialog","summary":"The note detail: a document-class form-less dialog with autosave. One chip row under the title: Link (RecordLinksChip, avatars + „+N“) · Dictate (voice → text, audio discarded) · Magic (AI rewrite, undo) · Add audio (file or Plaud kept below the text with player and transcript; the AI summary becomes note text).","status":"canon","shown":"canon","approvedAt":"2026-09-17","notes":"Voice approved by the product owner 16–17 Sep 2026 (proto/poznamka-audio). Dictate: acrm !3807/!3808. Add audio + recordings on notes: !3891 (mig. 0414), !3892 (dialog), !3893 (project recordings migrated into notes, mig. 0415). E2E on dev 26 Sep 2026 with real Czech speech: dictation → text, upload → transcript 3 s → summary 27 s written into the body once, 390 px sheet. No Ladle stories: the pattern lives in apps/web, which packages/ui must not import (same as formless-dialog). Updated 27 Sep 2026: „Přidat audio“ = Menu button with a MetaChip trigger (acrm !3919), sources from recording-sources.ts (Plaud · file); „Magic“ AI rewrite chip with glyph sparkles-2, undo = history, both voice/AI chips share ChipMorph (idle slot .chip-morph-hit, one transition constant, ds/chip-morph.css — acrm !3902); links move to RecordLinksChip (follow-up MR, owner approved 27 Sep). NoteAudioMenu/NoteMetaRow listed above are superseded by those. Verified on dev 27 Sep 2026 (acrm !3944 + !3919 + Magic, Playwright): desktop 1440 — Link · Dictate · Magic · Add audio, all 28 px, radius 8 px, 600/12 px, gap 4 px, one line; phone 390 (touch) — same chips, wrap after Magic with 4 px row gap; old .eref-chip/.add-ref pills in the row: 0; Magic → „Undo“ keeps 28 px. Phone overlays (27 Sep 2026, verified on dev by touch at 390 px, 25/25): the Link picker (RecordSelect) and Add audio (MenuButton) open as a BottomSheet — grab handle, title, full-width Done = <Button touch> 44 px, tap-to-close backdrop, portalled into the dialog scrim so taps do not fall through (acrm !4009 + !4028). Desktop unchanged (anchored panel / popover). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .nd-rec-layer, .nd-rec-hit. Registry repaired 17 Oct 2026 (review F4/F11): attached css chip-morph.css.","source":"app-css","react":["NoteDialog","NoteMetaRow","NoteRecChip","NoteLevelMeter","NoteAudioMenu","NoteRecordings","RecordLinksChip","ChipMorph"],"classes":[".acrm-dialog.note",".nd-meta",".nd-rec-chip",".nd-rec-live",".nd-rec-swap",".nd-rec-stop",".nd-level",".nd-audio",".nd-audio-item",".prj-rec",".prj-rec-nm",".prj-rec-audio",".prj-rec-fold",".prj-rec-transcript",".prj-rec-dot",".prj-rec-clock"],"files":["apps/web/src/components/notes/NoteDialog.tsx","apps/web/src/components/notes/NoteMetaRow.tsx","apps/web/src/components/notes/NoteDictation.tsx","apps/web/src/components/notes/use-dictation.ts","apps/web/src/components/notes/NoteAudio.tsx","apps/web/src/components/notes/NoteSaveStatus.tsx","apps/web/src/lib/api/note-recordings.ts","apps/web/src/lib/api/note-dictation.ts","apps/web/src/components/RecordLinksChip.tsx","apps/web/src/components/notes/ChipMorph.tsx"],"css":["apps/web/src/ds/note-dialog.css","apps/web/src/ds/dialog-doc.css","apps/web/src/ds/project-overview.css","apps/web/src/ds/chip-morph.css"],"stories":{"Default":["components--note-dialog--default"],"Variants":["components--note-dialog--variants"],"Sizes":[],"States":["components--note-dialog--states"],"With icon & kbd":[],"Composition":["components--note-dialog--composition"]},"legacy":["note-dialog.html"],"related":["formless-dialog","dialog","note-card","entity-reference"],"docs":"docs/dialog/note-dialog","url":"http://192.168.230.131:3777/ds/components/dialog/note-dialog","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"record-drawer","name":"Record drawer","summary":"The side panel that opens a record next to its listing without leaving it; the listing behind stays live. The only drawer in the canon.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"React implementation lives in the app (apps/web/src/components/drawer/RecordDrawer.tsx); DrawerForm shares only the .pdr shell, not .pdr-sec/.pdr-row. AD 14 September 2026 (OV-2): the only drawer — Drawer form is deprecated. The catalog stories and the overlays proposal still show an OLD body (.pdr-sec/.pdr-row sections) and an old two-button footer („Přidat do segmentu\" / „Odemknout informace\"). Measured on deployed dev (Lidé → row click): the body is the record rail in drawer variant (PersonRail variant=\"drawer\": stav spolupráce, quick actions, nejbližší aktivita, quick note, Aktivita/Poznámky tabs, Detail záznamu) and the footer holds one primary „Otevřít osobu\" — the same card the ↗ in the header opens in a new tab. Stories must be rebuilt from the real call site. Delivered 14 September 2026 (OV-2b, acrm !3515), verified on dev: the footer is gone; ↗ in the head opens the detail in the same tab with the listing context (onOpenDetail), Ctrl/⌘+click opens a new tab; the dead „Odemknout informace\" button in segments went with it. Catalog stories still show the old body and footer — to be rebuilt.","source":"app-css","react":["RecordDrawer"],"classes":[".pdr",".pdr-rail",".pdr-sec",".pdr-row",".pdr-top-av"],"files":["apps/web/src/ds/record-drawer.css","apps/web/src/components/drawer/RecordDrawer.tsx"],"css":["apps/web/src/ds/record-drawer.css"],"stories":{"Default":["components--record-drawer--default"],"Variants":["components--record-drawer--variants"],"Sizes":[],"States":["components--record-drawer--states"],"With icon & kbd":[],"Composition":["components--record-drawer--composition"]},"legacy":["Person Drawer.html","Company Drawer.html","Deal Drawer.html"],"related":["rail","drawer-slot","formless-dialog"],"docs":"docs/dialog/record-drawer","url":"http://192.168.230.131:3777/ds/components/dialog/record-drawer","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"drawer-form","name":"Drawer form","summary":"Deprecated — create/edit forms move to the form-less dialog (e.g. „Nový kontakt\"). The side panel with a field form is no longer used for new work.","status":"deprecated","shown":"deprecated","approvedAt":null,"notes":null,"source":"package","react":["DrawerForm","DrawerField"],"classes":[".pdr",".pdr-top",".pdr-body",".pdr-foot"],"files":["packages/ui/src/components/DrawerForm.tsx"],"css":["apps/web/src/ds/record-drawer.css"],"stories":{"Default":["components--drawer-form--default"],"Variants":["components--drawer-form--variants"],"Sizes":[],"States":["components--drawer-form--states"],"With icon & kbd":[],"Composition":["components--drawer-form--composition"]},"legacy":["drawer-form.html"],"related":["dialog","record-drawer","field"],"docs":"docs/dialog/drawer-form","url":"http://192.168.230.131:3777/ds/components/dialog/drawer-form","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":true},"covered":false,"implementation":{"acrm":null}}]},{"id":"popover","name":"Popover","category":"Overlays & dialogs","summary":"Anchored overlay layers: the Popover building layer (action menus → Menu button, choice → Picker menu), tooltips and entity previews.","url":"http://192.168.230.131:3777/ds/components/popover","coverage":100,"subcomponents":[{"id":"tooltip","name":"Tooltip","summary":"One-line label for a control, on hover and on keyboard focus.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"AD 14 September 2026 (OV-3): Popover and Tooltip stay two separate elements — they differ in how they open (click vs hover/focus), layer (101 vs 120), role and keyboard (arrows only in Popover); merging would rewrite both for no saving.","source":"package","react":["Tooltip"],"classes":[".acrm-tooltip",".acrm-tooltip-wrap"],"files":["packages/ui/src/components/Tooltip.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--tooltip--default"],"Variants":["components--tooltip--variants"],"Sizes":[],"States":["components--tooltip--states"],"With icon & kbd":[],"Composition":["components--tooltip--composition"]},"legacy":["tooltip.html"],"related":["icon-button","popover"],"docs":"docs/popover/tooltip","url":"http://192.168.230.131:3777/ds/components/popover/tooltip","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"entity-preview","name":"Entity preview","summary":"Hover card with head, facts and actions for a CRM record.","status":"canon","shown":"canon","approvedAt":"2026-09-11","notes":null,"source":"package","react":["EntityPreview"],"classes":[".eref-hc",".eref-hc-head",".eref-hc-facts",".eref-hc-act",".eref-hc-more"],"files":["packages/ui/src/components/EntityPreview.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--entity-preview--default"],"Variants":["components--entity-preview--variants"],"Sizes":[],"States":["components--entity-preview--states"],"With icon & kbd":[],"Composition":["components--entity-preview--composition"]},"legacy":["entity-previews.html"],"related":["entity-ref","popover","avatar"],"docs":"docs/popover/entity-preview","url":"http://192.168.230.131:3777/ds/components/popover/entity-preview","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Entity preview popover","card":"entity-previews.html","react":["EntityPreview"],"classes":[".eref-hc"],"tokens":[],"status":"OK","note":"NON-modální hover náhled entity; place() sdílené s Popoverem (lib/place.ts); generická jména karty scopována (.st → .eref-hc-st, .faces → .eref-hc-faces, .av-* → .acrm-avatar / .eref-hc-tile)"}}},{"id":"info-tip","name":"Info tip","summary":"An (i) next to a section heading or field label that opens a short explanation on click or tap.","status":"canon","shown":"canon","approvedAt":"2026-10-03","notes":"Owner 3 Oct 2026: no long descriptive text in the base UI — explanations behind (i) (RULES §14). acrm !4504. Glyph is a control: --fg-secondary 4.72:1 / 6.20:1 (AD). Canon 3 Oct 2026 after visual audit of the stories (light/dark).","source":"package","react":["InfoTip"],"classes":[".acrm-infotip",".acrm-infotip-btn",".acrm-infotip-panel"],"files":["packages/ui/src/components/InfoTip.tsx","apps/web/src/ds/info-tip.css"],"css":["apps/web/src/ds/info-tip.css"],"stories":{"Default":["components--info-tip--default"],"Variants":[],"Sizes":[],"States":["components--info-tip--states"],"With icon & kbd":[],"Composition":["components--info-tip--composition"]},"legacy":[],"related":["tooltip","section-block"],"docs":"docs/popover/info-tip","url":"http://192.168.230.131:3777/ds/components/popover/info-tip","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"popover","name":"Popover","summary":"Internal overlay layer of the canonical panels (MenuPanel, PickerPanel, RecordSelect, InfoTip, MenuButton…). Never used bare on a screen.","status":"deprecated","shown":"deprecated","approvedAt":null,"notes":"AD + owner 28 Sep 2026 („sjednotit popover do menu-button“): Popover is the overlay LAYER — portal, placement, flip, Escape/outside click, frame .acrm-popover. Screens never compose menus from it: action menus → Menu button (row anatomy documented there), choice → Picker menu. Stories stay — they document the layer. AD 14 September 2026 (OV-3): Popover and Tooltip stay two separate elements — they differ in how they open (click vs hover/focus), layer (101 vs 120), role and keyboard (arrows only in Popover); merging would rewrite both for no saving. AD 14 September 2026: „nic se nemá ořezávat\" — a menu row label is never truncated; the panel grows to the longest row (at least the anchor, clamped only by the viewport edges; a label longer than the viewport wraps rather than ellipsises). Supersedes the „one line, ellipsised\" rule and the 360px cap (acrm !3532). Correction: the record actions menu was never actually clipped — the „…\" in „Sloučit s jinou osobou…\" is part of the label (the action opens a further step); the rule is preventive. 3 Oct 2026 (AD): inventory done — bare popovers on screens 0 after acrm !4521 + !4523; the bare-popover validator also watches useAnchoredMenu outside packages/ui. Allowed internal uses with ds-ok: FilterBar chip menu (filter family), NotifBell (notifications family).","source":"package","react":["Popover","useAnchoredMenu"],"classes":[".acrm-popover",".acrm-popover-scrim",".acrm-popover-item"],"files":["packages/ui/src/components/Popover.tsx","packages/ui/src/lib/useAnchoredMenu.ts"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--popover--default"],"Variants":["components--popover--variants"],"Sizes":[],"States":["components--popover--states"],"With icon & kbd":["components--popover--with-icon-and-kbd"],"Composition":["components--popover--composition"]},"legacy":["popover.html"],"related":["menu-button","picker-menu","tooltip","picker-panel"],"docs":"docs/popover/popover","url":"http://192.168.230.131:3777/ds/components/popover/popover","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":true},"covered":false,"implementation":{"acrm":{"group":"Components","name":"Popover & menu","card":"popover.html","react":["Popover","PickerMenu","NavSelect"],"classes":[],"tokens":[],"status":"OK","note":""}}}]},{"id":"app-shell","name":"App shell","category":"Navigation","summary":"Application frame: sidebar navigation, top bar and the drawer slot.","url":"http://192.168.230.131:3777/ds/components/app-shell","coverage":100,"subcomponents":[{"id":"sidebar-nav-item","name":"Sidebar nav item","summary":"Row of the left navigation: top-level row, section divider and sub-item, plus the split parent that navigates and folds.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"React implementation lives in the app (apps/web/src/components/AppShell.tsx — WorkspaceNav/NavGo), not in @acrm/ui. The dead rules .as-row .notif/.count were removed on 11 September 2026 (NAV-1, acrm !3403); counts are .acrm-pill. Debt: no standalone segment-tile component — `.sg` (the 18px coloured tile with the list's glyph) exists only as `.as-sub .sg` in `apps/web/src/ds/app-shell.css`. `AddToListDialog` (acrm !4019, 27 Sep 2026, see the \"add-to-list dialog\" subsection of formless-dialog.usage.md) reuses it by extending the same selector rather than duplicating the rule — `.as-sub .sg, .atl-list .sg { … }` — one definition serving both the left menu and the dialog's list rows; accepted by the AD 27 Sep 2026 as a stopgap. Target: extract a canonical `SegmentTile` so a third consumer does not repeat the same selector-extension trick. 30 Sep 2026 (acrm !4296, AD FA216/FA233): optional dot?: blue | amber | green | purple | rose | critical draws the canonical category dot .il-dot[data-tone] (6 px, gap --sp-1) before the PLAIN count, no capsule. Category meaning only (Komunikace: Důležité critical, Delegováno mnou purple — owner R15, Delegováno mně amber); never unread (unread = blue dot elsewhere). acrm !4319 (1. 10. 2026, ověřeno na devu 1440/390 světlá+tmavá): tichý počet .as-navcnt místo modré kapsle, kapsle jen kritický odznak, horní blok 6, ⋯ akce seznamů (MenuButton) a + u Seznamů. Komunikace menu (20 Oct 2026, owner \"1 Schváleno\", proto/komunikace-menu-zobrazit-vse@0b7180f3a, ACRM-558, 560–569): rarely used Mail views (Newsletters, Sent, Archive, Trash, Snoozed, Drafts, Scheduled) live in a collapsible section \"Další\" (`.as-grp.as-more`, heading styled like \"Chaty\", collapsed by default, hidden-unread count on the right while collapsed); the active hidden view is shown as a copy above it; rows drag (HTML5 DnD) within and between groups and move with Alt+↑/↓ (aria-live announces the new place); personal preference in localStorage. No ⋮ menu on views. Row marks: `sgDot` = colour dot in the label colour (`.as-sub .sg.dot`, labels), `sgPlain` = bare muted glyph (\"+ New label/folder/deal\" rows), `sgTint` = bare glyph in the channel colour (chats: Telegram --ic-blue, WhatsApp --ic-green, SMS new token --ic-mint #34c759; the Chaty section is collapsible and open by default); a folder tile takes its own icon and tone (fallback grey `folder`). Tokens: new `--ic-mint`. Module icon Komunikace = `message-chatbot`, \"All chats\" = `message-circle`. AD 24 Oct 2026 (a2a FA278, acrm !5560): menu axis UX-62 accepted — .as-row-chev / .as-sub-chev / .as-sub-more share one axis (the sub-menu ⋯ sits exactly on the count, count hides on hover/open); .as-shared = sharing badge with ONE meaning only: the subject is shared with other users (who + level reachable on touch via ⋮/detail, not hover-only). Amber capsule (badgeAmber) NOT approved: the only coloured capsule in the menu stays critical; other counts are quiet. Pending from the author: stories States „sdílený“ + „osa“ with light/dark baseline, 390 check.","source":"app-css","react":[],"classes":[".as-nav",".as-row",".as-row-nav",".as-row-chev",".as-sub",".as-grp",".as-navcnt",".acrm-pill.sm.critical",".as-sub-chev",".as-sub-more",".as-shared"],"files":["apps/web/src/ds/app-shell.css"],"css":["apps/web/src/ds/app-shell.css"],"stories":{"Default":["components--sidebar-nav-item--default"],"Variants":["components--sidebar-nav-item--variants"],"Sizes":[],"States":["components--sidebar-nav-item--states"],"With icon & kbd":["components--sidebar-nav-item--with-icon-and-kbd"],"Composition":["components--sidebar-nav-item--composition"]},"legacy":["nav-item.html","App Shell.html"],"related":["top-bar","count-badge"],"docs":"docs/app-shell/sidebar-nav-item","url":"http://192.168.230.131:3777/ds/components/app-shell/sidebar-nav-item","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Sidebar nav","card":"nav-item.html","react":[],"classes":[".as-row"],"tokens":[],"status":"OK","note":"nav je součást AppShellu (apps/web), samostatné primitivum netřeba"}}},{"id":"top-bar","name":"Top bar","summary":"The application frame bar: workspace switch, global search (⌘K), utilities and account — never changes with the screen.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"React implementation lives in the app (AppShell.tsx — TopBar). .as-ai-trigger is a reserved, unused variant — decision A4.","source":"app-css","react":[],"classes":[".as-top",".as-util",".as-search",".tbar",".tbar-h",".tbar-id"],"files":["apps/web/src/ds/app-shell.css","apps/web/src/ds.css"],"css":["apps/web/src/ds/app-shell.css","apps/web/src/ds.css"],"stories":{"Default":["components--top-bar--default"],"Variants":["components--top-bar--variants"],"Sizes":[],"States":["components--top-bar--states"],"With icon & kbd":["components--top-bar--with-icon-and-kbd"],"Composition":["components--top-bar--composition"]},"legacy":["App Shell.html"],"related":["sidebar-nav-item","section-top-bar"],"docs":"docs/app-shell/top-bar","url":"http://192.168.230.131:3777/ds/components/app-shell/top-bar","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"drawer-slot","name":"Drawer slot","summary":"Non-modal panel slot beside the page; the side is chosen away from the click and the content survives closing.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Slot rendered by AppShell; screens fill it through <ShellDrawer>. .as-drawer.full was removed on 11 September 2026 (NAV-1, acrm !3403) — it had had no consumer since P276.","source":"app-css","react":["ShellDrawer"],"classes":[".as-drawer",".as-drawer-left"],"files":["apps/web/src/ds/app-shell.css","apps/web/src/components/shell/ShellDrawer.tsx"],"css":["apps/web/src/ds/app-shell.css"],"stories":{"Default":["components--drawer-slot--default"],"Variants":["components--drawer-slot--variants"],"Sizes":[],"States":["components--drawer-slot--states"],"With icon & kbd":[],"Composition":["components--drawer-slot--composition"]},"legacy":["App Shell.html"],"related":["record-drawer","ai-assistant"],"docs":"docs/app-shell/drawer-slot","url":"http://192.168.230.131:3777/ds/components/app-shell/drawer-slot","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"layout-switch","name":"Layout switch","summary":"Floating group at the bottom of the side menu that switches the layout: collapse the menu, list layout, context panel.","status":"canon","shown":"canon","approvedAt":"2026-09-30","notes":"Owner 29 Sep 2026 (FA214, dev-be): \"create it, add to DS and apply across the app, it should work the same everywhere\". Replaces the \"Sbalit navigaci\" row in every module. Up to 3 segments (menu [ · list layout · context panel ]), canonical IconButton with pressed, 1px divider. AD 30 Sep: the floating group sits over a scrolling menu, so --shadow-sm is allowed (overlay rule, RULES §4); phone ≤720 hidden. Becomes beta when the shared shell component and its story are on main. On main 30 Sep (acrm !4216, !4221, !4259); docs from dev-be FA226.","source":"app-css","react":["LayoutSwitch"],"classes":[".pp-layout",".pp-ldiv",".pp-float"],"files":["apps/web/src/components/shell/LayoutSwitch.tsx","apps/web/src/components/shell/layout-switch.css","apps/web/src/lib/layout-slots.ts"],"css":["apps/web/src/components/shell/layout-switch.css"],"stories":{"Default":["components--layout-switch--default"],"Variants":["components--layout-switch--variants"],"Sizes":[],"States":["components--layout-switch--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["sidebar-nav-item","top-bar","icon-button"],"docs":"docs/app-shell/layout-switch","url":"http://192.168.230.131:3777/ds/components/app-shell/layout-switch","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"split-view","name":"Split view","summary":"The one two-pane layout: aside next to the main content (rail | detail, list | reader, work | discussion); bar above, not resizable.","status":"canon","shown":"beta","approvedAt":null,"notes":"React lives in the app (SplitView.tsx); stories render its markup 1:1. Beta 4 Oct 2026: stories + usage + a11y done; canon after AD approval. Open: settings (OpravneniRole, SadyOpravneniTab) use SplitView with fill={false} although DS-SPLITVIEW lists Settings as not-SplitView, and pass gap without divider=\"gap\" (no effect).","source":"app","react":["SplitView"],"classes":[".sv",".sv-aside",".sv-main",".sv-pad",".sv-r",".sv-div-line",".sv-div-gap",".sv-fill",".sv-collapse"],"files":["apps/web/src/components/SplitView.tsx","apps/web/src/ds/split-view.css","apps/web/src/ds/responsive.css"],"css":["apps/web/src/ds/split-view.css","apps/web/src/ds/responsive.css"],"stories":{"Default":["components--split-view--default"],"Variants":["components--split-view--variants"],"Sizes":["components--split-view--sizes"],"States":["components--split-view--states"],"With icon & kbd":[],"Composition":["components--split-view--composition"]},"legacy":[],"related":["record-rail","section-top-bar","command-palette"],"docs":"docs/app-shell/split-view","url":"http://192.168.230.131:3777/ds/components/app-shell/split-view","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant.","name":"Section top bar","category":"Navigation","summary":"One bar above every list or record: title, chips, search and actions.","url":"http://192.168.230.131:3777/ds/components/section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant.","coverage":80,"subcomponents":[{"id":"section-top-bar","name":"Section top bar","summary":"Composable bar with title, chips, search, dividers and spacer.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Four screens hand-roll the identity instead of SectionTopBarTitle — decision A6. Phone two-step (AD 27 Sep 2026, acrm !3997, fix/nastaveni-mobil-dvoukrok): Nastavení (SettingsLayout.tsx) below the 720px breakpoint drops the side rail and becomes ⌘K's own two-step — `/nastaveni` with no section shows only the grouped menu full-width (`.nastaveni-page.m-menu`), `/nastaveni/<sekce>` shows only that section's `SectionTopBar` (`flat`) and body (`.m-section`) with a quiet `IconButton icon=\"arrow-left\"` (`.set-back`) as the bar's first item, wired to `navigate('/nastaveni')`. Desktop keeps rail + content side by side unchanged. Side rail at ≥720px would take ~260px on a 390px phone and clip every section's fields — the same two-step shape as the ⌘K palette's list→detail step, not a new pattern. acrm !4029 (27 Sep 2026): new app-only layer apps/web/src/ds/section-top-bar.css (home for bar rules; ds.css is over the 100 kB ratchet and must not grow) — a long name in the bar stays on one line with an ellipsis and SectionTopBarTitle carries `title` with the full name; switch labels in the bar do not wrap. acrm !4044 (27 Sep 2026): the record view switcher on person/company (Activities / Profile) is the canonical `.tchip` with chevron (RULES §8: a switcher in the bar = .tchip + menu), the bespoke `.rvsw-*` was deleted. Menu items without description text (acrm !4051). Phone layout, Attio pattern (owner 2026-09-28, acrm !4088): actions as data — primaryAction {label, icon, onClick, kind} → Fab below 720 px (round only for kind 'create'), secondaryActions (menuOnly, danger, phoneOnly) → one ⋮ bottom sheet, closeAction last; row 1 = title + ⋮, row 2 = tools (view picker left, Filtr/Řadit right). Desktop unchanged. PageHeader forwards the same props. 14 Oct 2026 (owner \"schvaleno\" 24b v4, proto/detail-jednotne@9600c16a2, acrm !5055; RULES §26): record detail header = ↑↓ · name · ⋮ · ✕ with NO blue primary. Rare actions stay in context (Nový obchod in Nejbližší aktivita + Obchody tab; project Aktualizace in its section); an order shows one button only for the step it waits for. Dev check 14 Oct 1440 + 390: person, company, project, order — 0 primaries in the header, the project label chip gone. Registry repaired 17 Oct 2026 (review F5): PageHeader, RecordCloseButton live in apps/web (see files), not exported by @acrm/ui; dropped from react[]. 20 Oct 2026 (ACRM-569, proto/komunikace-menu-zobrazit-vse@0b7180f3a): `SectionTopBarTitle dot` — identity by colour with no glyph (`.pipe-dot`, a 12 px circle inside the `--tile-sm` frame, CSS in apps/web/src/ds/section-top-bar-dot.css); used by a mail label list. Story: \"With dot\".","source":"package","react":["SectionTopBar","SectionTopBarChip","SectionTopBarSearch","SectionTopBarDivider","SectionTopBarSpacer"],"classes":[".tbar",".tchip",".acrm-input",".vspace",".tbar.has-acts",".tbar-title",".tbar-tools",".tbar-acts",".tbar-more",".tbar-overflow",".tbar-sort"],"files":["packages/ui/src/components/SectionTopBar.tsx","apps/web/src/components/PageHeader.tsx","apps/web/src/components/record/RecordCloseButton.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/section-top-bar.css"],"stories":{"Default":["components--section-top-bar--default"],"Variants":["components--section-top-bar--variants"],"Sizes":[],"States":["components--section-top-bar--states"],"With icon & kbd":["components--section-top-bar--with-icon-and-kbd"],"Composition":["components--section-top-bar--composition"]},"legacy":["Section top bar.html"],"related":["title-with-entity-tile","nav-select","filter-bar","fab","menu-button"],"docs":"docs/section-top-bar/section-top-bar","url":"http://192.168.230.131:3777/ds/components/section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant./section-top-bar","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Section top bar","card":"Section top bar.html","react":["SectionTopBar"],"classes":[".tbar"],"tokens":[],"status":"OK","note":"normativ .tbar; migrace 8 stránek z .pr-top = samostatné MR (viz PLAN-page-decomposition)"}}},{"id":"title-with-entity-tile","name":"Title with entity tile","summary":"Identity of the Section top bar: exactly one of icon, colour tile, avatar, heading dropdown or inline rename.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Rule confirmed in code on meeting detail (acrm !4014, 27 Sep 2026): a record that IS a thing, not an identity, gets the flat `icon` prop (20px, `--fg-secondary`) inherited from its section's menu mark — `MeetingDetailPage.tsx` passes `entityMark(...).icon` from the Kalendář mark, same as Deals/Tasks; no 32px `kind` tile, since a meeting is not a person or a company.","source":"package","react":["SectionTopBarTitle"],"classes":[".tbar-h",".pipe-tile",".nav-pav"],"files":["packages/ui/src/components/SectionTopBar.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--title-with-entity-tile--default"],"Variants":["components--title-with-entity-tile--variants"],"Sizes":[],"States":["components--title-with-entity-tile--states"],"With icon & kbd":[],"Composition":["components--title-with-entity-tile--composition"]},"legacy":["Section top bar.html"],"related":["section-top-bar","avatar"],"docs":"docs/section-top-bar/title-with-entity-tile","url":"http://192.168.230.131:3777/ds/components/section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant./title-with-entity-tile","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Section top bar","card":"Section top bar.html","react":["SectionTopBar"],"classes":[".tbar"],"tokens":[],"status":"OK","note":"normativ .tbar; migrace 8 stránek z .pr-top = samostatné MR (viz PLAN-page-decomposition)"}}},{"id":"settings-page","name":"Settings page","summary":"Settings screen: left rail menu with search, section top bar and a 660px content column (Attio pattern).","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Lives in apps/web (SettingsLayout). Menu = SETTINGS_NAV, one icon per item, sections ≤660px, no two tab levels (RULES §12).","source":"app-css","react":["SettingsLayout"],"classes":[".set-shell",".set-rail",".set-nav",".set-group",".set-grp",".set-item",".sbody",".scol",".set-stack",".table-wrap"],"files":["apps/web/src/pages/settings/SettingsLayout.tsx","apps/web/src/pages/settings/settings-nav.ts"],"css":["apps/web/src/ds/settings.css"],"stories":{"Default":["components--settings-page--default"],"Variants":["components--settings-page--variants"],"Sizes":[],"States":["components--settings-page--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["section-top-bar","title-with-entity-tile","tab-strip","section-block","sidebar-nav-item"],"docs":"docs/section-top-bar/settings-page","url":"http://192.168.230.131:3777/ds/components/section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant./settings-page","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"record-actions-menu","name":"Record actions menu","summary":"⋮ actions of a record in the header and drawer, non-destructive first, destructive last.","status":"canon","shown":"canon","approvedAt":"2026-10-19","notes":"Owner approved 6 Oct 2026 (acrm !4800, prototype proto/record-actions-menu@eabe09c8d): one trigger ⋮ (IconButton dots-vertical, default size) via kebabTrigger on person, company, deal, meeting, document, Datamart, project; order non-destructive → separator → Smazat last; no disabled Smazat; action menus fit the window height (fit-height). Dev check 7 Oct 2026: company detail 1440/390 light/dark, trigger 30 px, 5 items, Smazat last in --critical, phone sheet with Hotovo, brown 0. Usage + a11y docs written. Stories added in acrm !4923 (11 Oct 2026) → beta. 14 Oct 2026 (acrm !5055): project and order use the same ⋮ (RecordKebab); order Náhled / E-podpis / Smazat / Odeslat znovu live here. Canon 19 Oct 2026 (AD): dev check with real data on Firmy preview — 1440 light/dark: ⋮ 30×30 in the header after ↑ ↓ 1/50, menu Sloučit s jinou firmou… · Zkopírovat odkaz · Nastavení práv · Změnit vlastníka · separator · Smazat firmu (--critical); 390 light/dark: bottom sheet with grip, title „Další akce\", same 5 items, full-width Hotovo, scrim; brown 0, page errors 0. Stories Default · States · Composition (acrm !4923).","source":"app","react":["RecordActionsMenu","RecordMenu"],"classes":[],"files":["apps/web/src/components/record/RecordActionsMenu.tsx","apps/web/src/components/record/kebab-trigger.tsx","apps/web/src/components/meetings/RecordMenu.tsx","packages/ui/src/lib/fit-height.ts"],"css":[],"stories":{"Default":["components--record-actions-menu--default"],"Variants":[],"Sizes":[],"States":["components--record-actions-menu--states"],"With icon & kbd":[],"Composition":["components--record-actions-menu--composition"]},"legacy":[],"related":["menu-button","section-top-bar","popover"],"docs":"docs/section-top-bar/record-actions-menu","url":"http://192.168.230.131:3777/ds/components/section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant./record-actions-menu","coverage":{"stories":true,"props":false,"classes":false,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":false},"covered":false,"implementation":{"acrm":null}},{"id":"record-nav-arrows","name":"Record nav arrows","summary":"Previous / next record with the position n/m in the record header.","status":"canon","shown":"canon","approvedAt":"2026-10-17","notes":"Owner approved 11 Oct 2026 (R47, R48; acrm !4962, prototype proto/record-nav-arrows@5f98c373d): one order ↑ ↓ then „Plocha · n/m\" incl. the mail reader; J/K keys; no arrows on the phone. Dev check 11 Oct: mail reader 1440 light/dark — order prev · next · „Doručené · 1/50\", titles „Předchozí (K)\" / „Další (J)\"; 390 no arrows. Preview drawer unified in acrm !4963 (RecordDrawer: ↑ ↓ + quiet „2/50\", J/K) — checked on dev 11 Oct, Lidé 1440/390 light/dark. Full person detail via ↗ not checked on dev by script (MR screenshots). Registry repaired 17 Oct 2026 (review F1): RecordDrawer moved to components/drawer/. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories. Canon 17 Oct 2026 (AD): own stories Default · States · Composition + 6 light/dark baselines in acrm !5080 (f9b052d7e); usage + a11y in docs/section-top-bar. Story markup mirrors the app component 1:1 (RecordNavArrows reads router state, packages/ui must not import it).","source":"app","react":["RecordNavArrows"],"classes":[".tbar-pos",".tbar-pos.is-link"],"files":["apps/web/src/components/RecordNavArrows.tsx","apps/web/src/pages/komunikace/MessagePage.tsx","apps/web/src/components/drawer/RecordDrawer.tsx"],"css":[],"stories":{"Default":["components--record-nav-arrows--default"],"Variants":[],"Sizes":[],"States":["components--record-nav-arrows--states"],"With icon & kbd":[],"Composition":["components--record-nav-arrows--composition"]},"legacy":[],"related":["section-top-bar","record-actions-menu","icon-button"],"docs":"docs/section-top-bar/record-nav-arrows","url":"http://192.168.230.131:3777/ds/components/section-top-bar AD 24 Oct 2026: approved as canon — stories, usage and a11y done since 4 Oct; it is the mandated list|detail layout (CLAUDE.md UI acceptance). The fill={false} settings cases stay as a known variant./record-nav-arrows","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"tabs","name":"Tabs","category":"Navigation","summary":"Horizontal tab strips for switching views within a page or record.","url":"http://192.168.230.131:3777/ds/components/tabs","coverage":100,"subcomponents":[{"id":"tab-strip","name":"Tab strip","summary":"Controlled tablist that scrolls and fades when the tabs do not fit; no overflow menu, no disabled tab.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"package","react":["TabStrip"],"classes":[".acrm-tabs",".acrm-tab",".acrm-tabswrap",".acrm-tabsedge",".acrm-tabsbtn"],"files":["packages/ui/src/components/TabStrip.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--tab-strip--default"],"Variants":["components--tab-strip--variants"],"Sizes":[],"States":["components--tab-strip--states"],"With icon & kbd":["components--tab-strip--with-icon-and-kbd"],"Composition":["components--tab-strip--composition"]},"legacy":["tabs.html"],"related":["record-tabs","segmented-control"],"docs":"docs/tabs/tab-strip","url":"http://192.168.230.131:3777/ds/components/tabs/tab-strip","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Tabs (record sub-nav)","card":"tabs.html","react":["TabStrip"],"classes":[],"tokens":[],"status":"OK","note":""}}},{"id":"record-tabs","name":"Record tabs","summary":"Record tab row: tab strip plus „+ N další“ overflow and a personal layout; an empty tab drops out, a loading one does not.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"React implementation lives in the app (record/RecordTabsRow.tsx + record-tabs.ts); it uses TabStrip internally and adds the overflow trigger and the layout menu. 14 Oct 2026 (owner \"24g scvaleno\", proto/zalozky-jeden-ovladac@489bb3bd6, acrm !5043): ONE icon button „Záložky\" with a count badge of hidden tabs replaces „+ N další\" and ⚙; its menu lists all tabs — name = open, switch = show/hide, grip/Alt+↑↓ = order; phone = bottom sheet with „Hotovo\". Badge --accent-press + white, 5.73:1. Dev check 14 Oct 1440 + 390 (company Druid): badge 8, 15 switches, sheet ok.","source":"app-css","react":["RecordTabsRow"],"classes":[".acrm-tabs",".acrm-tab"],"files":["apps/web/src/components/record/RecordTabsRow.tsx","apps/web/src/components/record/record-tabs.ts"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--record-tabs--default"],"Variants":["components--record-tabs--variants"],"Sizes":[],"States":["components--record-tabs--states"],"With icon & kbd":[],"Composition":["components--record-tabs--composition"]},"legacy":["Record tabs (unified).html"],"related":["tab-strip","rail"],"docs":"docs/tabs/record-tabs","url":"http://192.168.230.131:3777/ds/components/tabs/record-tabs","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"item-list","name":"Item list","category":"Records & data","summary":"The canonical listing: one row pattern for tasks, e-mails, activities, notes, files and queues.","url":"http://192.168.230.131:3777/ds/components/item-list","coverage":100,"subcomponents":[{"id":"item-list","name":"Item list","summary":"Row in three densities (sm 28, md 44, lg 52) with lead, title, byline, content, tags and meta — no trailing slot. Slot `tags` carries the row’s label pills to the right, just before the date; on `lg` (phone) they drop to their own line. Variant `.il-seamless` drops the dividers for short selection lists.","status":"canon","shown":"canon","approvedAt":"2026-10-09","notes":"React implementation lives in the app (apps/web/src/components/ItemList.tsx), not in @acrm/ui. This is the canon that replaces Record list (AD 20 Jul 2026, docs/PLAN-listview.md). Approved 15 September 2026 (AD, RD-2): stamped as canon; examples lose the card frame the app does not have; the remaining Record list screens (17 uses in 9 files) move onto Item list and Record list is deleted. Listbox cursor that arrives on a spring (owner 26 Sep 2026, ACRM-322, acrm !3997): a `role=\"listbox\"` list (⌘K palette) no longer paints `.il-cursor` background per row — one persistent `.il-cursor-bar` behind the rows slides to the row under the cursor via `springAnimate` (packages/ui/src/lib/spring.ts), the same curve as a dialog window; on an unrelated jump (cursor arrives from another section, new results) the bar snaps into place and only fades in. The whole listbox cross-fades in on mount/new-results (`animation: ilListIn 0.2s ease-out`), so it never re-paints while typing. The kbd hint on the cursor row (`.il-meta .acrm-kbd`, → / ↵) is hidden while the bar is travelling (`[data-cursor-moving]`, set for `SPRING_ARRIVE_MS`) and fades in only once the bar has landed, so it cannot jump ahead of the highlight. `prefers-reduced-motion` turns both the bar's spring and `ilListIn` off — the cursor and the list appear instantly. Only consumer of `role=\"listbox\"` is GlobalSearch.tsx. Separately, acrm !3997 also replaced the button-row selector antipattern in Nastavení › Oprávnění (Role, Sady oprávnění) with a list|editor split: a plain `role=\"list\"` Item list `sm` on the left (name, headcount in `meta`, selection painted with `.il-active`, not the cursor bar) and the editor on the right (`.opr-editor`, settings.css) — the first migration off \"selection = primary button\" onto Item list. Slot `tags` (owner 8 Oct 2026, acrm !4915, merged 10 Oct 2026; AD review FA258/FA259/FA264): label pills (`.acrm-pill sm`) of a row live in the `tags` slot, never in `cols` or `meta` — `.il-tags` sits right-aligned just before `.il-meta`, no fixed column width (the old 200 px `cols` column left a gap between pills and date that varied with the number of tags), it may shrink (pills clip from the left, `min-width: 0`) but never grows past half of the row so the title wins. The list sets `--il-meta-w` on its wrapper to give every `.il-meta` (the date) one width, so the right edge of the tags lines up across rows; without the variable nothing changes. On density `lg` (phone) the component itself (via `DensityCtx`) puts the tags on their own line under the title and the date, full width (`.il-tags-below`, row gets `.il-tags-wrap`, plus `.il-tags-wrap-lead` to indent the line to the title when there is a lead); `lg` `padding-block` is now `var(--sp-3)` (was `--sp-2`). Group bar over an embedded list: `.tl-grp.is-embedded` (explicit modifier, no `:has`) makes the group header `.tl-grp` span the full width of the box with the list’s hairlines — it replaces per-screen patches (Hovory `dialer.css`, timeline `timeline.css`). Consumers moved to the slot: MailRow, SourceGroupedMailList, ProjectTaskRow, `TaskList` in `@acrm/ui` (its tags left the Provázané slot `.tl-rel`). A status pill in a table column is not a tag and stays where it is. Docs: docs/item-list/item-list.usage.md, RULES.md §20. Registry repaired 17 Oct 2026 (review F4/F11): attached css reorder.css.","source":"app-css","react":["ItemList"],"classes":[".il",".il-row",".il-lead",".il-main",".il-t",".il-by",".il-c",".il-meta",".il-li",".il-seamless",".il-when",".il-col",".il-dot",".il-cursor-bar",".il-cursor",".il-tags",".il-tags-below",".il-tags-wrap",".il-tags-wrap-lead",".il-has-tags",".tl-grp.is-embedded"],"files":["apps/web/src/components/ItemList.tsx","apps/web/src/ds/item-list.css"],"css":["apps/web/src/ds/item-list.css","apps/web/src/ds/reorder.css"],"stories":{"Default":["components--item-list--default"],"Variants":["components--item-list--variants"],"Sizes":["components--item-list--sizes"],"States":["components--item-list--states"],"With icon & kbd":["components--item-list--with-icon-and-kbd"],"Composition":["components--item-list--composition"]},"legacy":[],"related":["item-list","task-list","email-list","timeline","audit-detail"],"docs":"docs/item-list/item-list","url":"http://192.168.230.131:3777/ds/components/item-list/item-list","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"audit-detail","name":"Audit detail","summary":"Expanded content of an Item list row that records what changed: field grid before → after, batch items, sent e-mail, note. Fills the row block slot; actions come from the caller.","status":"canon","shown":"canon","approvedAt":"2026-10-21","notes":"Owner decision 19 Oct 2026: sub-component of the Item list family (candidate README had asked detail-block vs own family). Source acrm !5275 (K3-2, merged), approved prototype proto/asistent-audit@60ff4f48f (18 Oct 2026). The arrow is not drawn for e-mail recipient and subject (the prototype drew a stray \"— →\"); the narrow-row title wrapping rule lives in the audit page stylesheet, not here. Not yet AD-approved: no approvedAt, shown as beta/candidate until stamped. AD review 21 Oct 2026: returned for 3 fixes before canon. (1) ds/audit-detail.css still carries page-only rules (.acrm-audit-page .il-row .il-t, .il-col .acrm-audit-actor); move them to the audit page stylesheet. (2) .acrm-audit-empty duplicates the DS EmptyState (RULES §27) and is reused as the load-more wrapper; use EmptyState and drop the class. (3) AuditItems draws before→after as a text glyph while AuditChanges uses Icon arrow-right; unify on the Icon. Minor: the 2px mail rule should use a line token. All four fixed in acrm !5378 (merged 21 Oct 2026; page rules in pages/asistent-audit.css, DS EmptyState, load-more in .tlx-more, batch arrow = Icon arrow-right, var(--line-thick)); checked on dev 21 Oct at 1440/390 (rows expand, actor column, 0 JS errors; no batch row or empty filter in dev data, so those two were checked by tests only). AD-approved as canon 21 Oct 2026.","source":"app-css","react":["AuditDetail","AuditChanges","AuditItems","AuditMail"],"classes":[".acrm-audit",".acrm-audit-note",".acrm-audit-ch",".acrm-audit-items",".acrm-audit-mail",".acrm-audit-mail-h",".acrm-audit-act"],"files":["apps/web/src/components/assistant/audit/AuditDetail.tsx","apps/web/src/ds/audit-detail.css"],"css":["apps/web/src/ds/audit-detail.css"],"stories":{"Default":["components--audit-detail--default"],"Variants":["components--audit-detail--variants"],"Sizes":[],"States":["components--audit-detail--states"],"With icon & kbd":[],"Composition":["components--audit-detail--composition"]},"legacy":[],"related":["item-list","timeline","count-badge"],"docs":"docs/item-list/audit-detail","url":"http://192.168.230.131:3777/ds/components/item-list/audit-detail","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"record-rail","name":"Record rail","category":"Records & data","summary":"The record panel: the single source of truth for its fields, one card.","url":"http://192.168.230.131:3777/ds/components/record-rail","coverage":100,"subcomponents":[{"id":"rail","name":"Rail","summary":"The record panel: context actions, 34px key-value rows edited in place (several values = several rows), tags, description and relations.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Merged 14 September 2026 (AD, RD-1): Key-value row, Editable field and Multi-value were separate pages; they are parts of this one card. The app copy of the row (KeyValueRow, .pr-row) is being replaced by the rail row and deleted. A value with href/onOpen never opens the editor on click and keeps a permanently visible pencil (AD FA10-re); errors are the caller’s toast. The multi-value editor popover lives in the app (components/multivalue/*, ds/multi-value.css). Mobile sheet merged 15 September 2026 (MR !3539): below 720px `MultiValuePopover` renders as a bottom sheet instead of an anchored popover (`.phe-scrim`, `.phe-grab`, `.phe-sheethead`, `.phe-sheetfoot` in `ds/responsive.css`) so it can be closed and confirmed without a keyboard — see \"Mobile\" in rail.usage.md / rail.a11y.md. Stories rebuilt from the real person rail 15 September 2026 (acrm !3544): four quiet icon actions, Detail záznamu / Procesy / Seznamy, no empty section header; the rail has no shortcuts, so its „With icon & kbd\" story and both its baselines are gone. Meeting attendees composition (owner 25.–27. Sep 2026, acrm !4014/!3985, all in `apps/web/src/ds/meeting-record.css` — not yet ported into record-rail.css): field `type: 'number'` for a small bounded count paired with `useConfirm` (speaker count, range 1–20 per the diarization service, raised from 10 on acrm !3985); a relation row's right-aligned talk-share bar (56px `--line-200` track, 4ch tabular-nums percentage) — candidate for a named \"share bar\" element; an unassigned-voice row with `--sp-3` icon-to-text / `--sp-4` name-to-action spacing; and a scoped exception (`.rr-list--attendees`) that keeps the removable reference's × contextual on touch instead of the global `ds.css` always-visible rule, so it never sits permanently over the share bar. Touch (AD 28 Sep 2026, acrm !4111): the description measures its real clamp (.rr-desc-v.is-clamped, ResizeObserver) and shows the chevron only then; on hover: none copy and the chevron are always visible with 44px hit areas, and copy ↔ pencil keep a 30px gap so two 44px targets never overlap (the rule beats --sp-2). Overrides live in apps/web/src/ds/responsive.css. Registry repaired 17 Oct 2026 (review F4/F11): attached css detail-field.css.","source":"package","react":["RecordRail","EditableField","useInlineEdit","RailRows","RailRow"],"classes":[".rr-row",".rr-sec-h",".rr-relrow",".rr-dot",".rr-status",".rr-tags",".rr-actions",".rr-desc",".rr-row .ri",".rr-row .k",".rr-row .v",".rr-ev",".rr-ev-pen",".rr-ev-copy",".rr-edit",".rr-vals",".rr-val",".rr-allvals",".chf-lbl",".phe-row",".phe-type",".phe-addrow",".phe-x",".phe-copy",".phe-scrim",".phe-grab",".phe-sheethead",".phe-sheetfoot","is-clamped"],"files":["packages/ui/src/components/RecordRail.tsx","packages/ui/src/lib/useInlineEdit.ts","apps/web/src/ds/multi-value.css","apps/web/src/components/ChannelsField.tsx","apps/web/src/components/multivalue/ChannelsPopoverEditor.tsx","apps/web/src/components/multivalue/MultiValuePopover.tsx","apps/web/src/ds/responsive.css","packages/ui/stories/record-rail-rows.stories.tsx"],"css":["apps/web/src/ds/record-rail.css","apps/web/src/ds.css","apps/web/src/ds/multi-value.css","apps/web/src/ds/responsive.css","apps/web/src/ds/detail-field.css"],"stories":{"Default":["components--rail--default","components--record-rail-rows--default","components--editable-field--default","components--multi-value--default"],"Variants":["components--rail--variants","components--record-rail-rows--variants","components--editable-field--variants","components--multi-value--variants"],"Sizes":[],"States":["components--rail--states","components--record-rail-rows--states","components--editable-field--states","components--multi-value--states"],"With icon & kbd":[],"Composition":["components--rail--composition","components--record-rail-rows--composition","components--editable-field--composition","components--multi-value--composition"]},"legacy":["Record detail rail.html","Multi-value editor.html"],"related":["record-drawer","entity-ref","record-select","input"],"docs":"docs/record-rail/rail","url":"http://192.168.230.131:3777/ds/components/record-rail/rail","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"table","name":"Table","category":"Records & data","summary":"Segment tables with sortable headers, clipped cells and summary row.","url":"http://192.168.230.131:3777/ds/components/table","coverage":100,"subcomponents":[{"id":"segment-table","name":"Segment table","summary":"Listing table: sortable header, frozen checkbox and identity columns, lazy loading by 50 and an optional summary row in its own tfoot.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Engine lives in the app (components/segment/SegmentScreen.tsx — SegmentTable); the lite variant strips checkbox, column menu, summary and frozen identity. Row height is --row-h (37px) — the 44/52 densities belong to Item list, not here. The registry previously listed .sgb-summary, which does not exist: the summary row is the table tfoot and .sgb-sum is the per-column control.","source":"app-css","react":["SegmentTable","SegmentScreen"],"classes":[".table-wrap",".sgb-table",".sgb-th-col",".sgb-th-sortable",".sgb-ck",".sgb-rowclick",".sgb-sum"],"files":["apps/web/src/ds/segment-screen.css","apps/web/src/ds/list-view.css","apps/web/src/components/segment/SegmentScreen.tsx"],"css":["apps/web/src/ds/segment-screen.css","apps/web/src/ds/list-view.css"],"stories":{"Default":["components--segment-table--default"],"Variants":["components--segment-table--variants"],"Sizes":[],"States":["components--segment-table--states"],"With icon & kbd":["components--segment-table--with-icon-and-kbd"],"Composition":["components--segment-table--composition","components--segment-table--column-panel"]},"legacy":["list-view.html"],"related":["table-row","filter-bar","section-top-bar"],"docs":"docs/table/segment-table","url":"http://192.168.230.131:3777/ds/components/table/segment-table","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Table listing","card":"list-view.html","react":[],"classes":[".sgb-table"],"tokens":[],"status":"OK","note":"kompoziční karta segment-screen enginu (SegmentScreen.tsx) — ne RecordList; zavádí normativ .tbar → follow-up refactor top barů"}}},{"id":"table-row","name":"Table row","summary":"Row anatomy of a listing table: frozen checkbox and identity cells, then value cells at one height.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"There is no per-row action column — the only hover affordance is the checkbox.","source":"app-css","react":[],"classes":[".sgb-rowclick",".col-ck",".cell-id",".cell-v",".cell-mono",".cell-link",".grade"],"files":["apps/web/src/ds/list-view.css"],"css":["apps/web/src/ds/list-view.css","apps/web/src/ds/segment-screen.css"],"stories":{"Default":["components--table-row--default"],"Variants":["components--table-row--variants"],"Sizes":[],"States":["components--table-row--states"],"With icon & kbd":[],"Composition":["components--table-row--composition"]},"legacy":["table-row.html"],"related":["segment-table","item-list"],"docs":"docs/table/table-row","url":"http://192.168.230.131:3777/ds/components/table/table-row","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Table","card":"table-row.html","react":[],"classes":[".sgb-table"],"tokens":[],"status":"OK","note":"segment tabulky ve screen vrstvě; React primitivum = backlog #23"}}},{"id":"bulk-action-bar","name":"Bulk action bar","summary":"Floating pill at the bottom of a table or list once rows are selected: count, actions, ⋮ for the rest and × to clear; folds to one inline action on phones.","status":"canon","shown":"canon","approvedAt":"2026-10-19","notes":"Beta 5 Oct 2026 (acrm !4743): one implementation everywhere (Lidé, Firmy, Segment, Pipeline table, Datamart, Komunikace). Phone (≤ 720 px) folding into ⋮, × always visible, page FAB hidden, Esc clears selection everywhere. Dev check 5 Oct 2026 at 390: Lidé '3 vybráno · Vytvořit obchod · ⋯ · ×', FAB hidden. Open: overflow trigger uses dots (⋯) — align with canon dots-vertical in the record-actions-menu wave. Canon after that wave. Owner approved 11 Oct 2026 (item 17 c, acrm !4961, prototype proto/bulkbar-mobile@d457d2c90): on the phone „Vybrat všech N\" is the first item in ⋮ (divider, actions, divider, Koš last; gone when all selected); the bar hides under an open sheet or modal dialog at every width; one rule in bulk-bar.css. Dev check 11 Oct (Komunikace, 360/390 light/dark): × inside the bar (309 < 316 / 324 < 331), ⋮ order as approved, bar hidden under the sheet. ⋮ tap target 43×43 (as prototype). Dev check 19 Oct 2026 (Lidé, real data): 1440 light/dark bar '2 vybráno · Vytvořit obchod · Změnit vlastníka · Exportovat · Smazat', 390 dark '2 vybráno · Vytvořit obchod · ⋮ · ×' (⋮ = dots-vertical, menu Změnit vlastníka · Exportovat · Smazat), FAB hidden, brown 0. Blocker for canon: Esc does not clear the selection when focus is on a row checkbox (BulkActionBar Esc guard skips every input, incl. type=checkbox) — contradicts a11y.md; fix in acrm, then canon. Esc blocker fixed in acrm !5293 (19 Oct 2026): checkbox/radio no longer count as a typing field; re-checked on dev (Lidé 1440, focus on the row checkbox → Esc clears, bar unmounts). Canon 19 Oct 2026 (AD): stories Default · States · Composition, usage + a11y, dev check 1440/390 light/dark.","source":"app","react":["BulkActionBar"],"classes":[".acrm-bulkbar",".acrm-bulkbar-count",".acrm-bulkbar-sep"],"files":["apps/web/src/components/bulk/BulkActionBar.tsx"],"css":["apps/web/src/components/bulk/bulk-bar.css"],"stories":{"Default":["components--bulk-action-bar--default"],"Variants":[],"Sizes":[],"States":["components--bulk-action-bar--states"],"With icon & kbd":[],"Composition":["components--bulk-action-bar--composition"]},"legacy":[],"related":["table-row","segment-table","menu-button","fab"],"docs":"docs/table/bulk-action-bar","url":"http://192.168.230.131:3777/ds/components/table/bulk-action-bar","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"task-list","name":"Task list","category":"Records & data","summary":"Task rows led by priority and state glyph, no hairline or header, one linked entity, owner and due date; compact or full mode.","url":"http://192.168.230.131:3777/ds/components/task-list","coverage":100,"subcomponents":[{"id":"task-list","name":"Task list","summary":"Linear-model row (no hairline, no header, no id/state-name text) in three width modes; the mode changes one thing — how the assignee is shown.","status":"canon","shown":"canon","approvedAt":"2026-09-15","notes":"AD schváleno 15 Sep 2026 (prototype ukoly-tabulka-oprava.html, Linear model) — the default row in every mode, replacing the row entirely: no hairline (hover fills --hover-surface, the grid + hover lead the eye), no column header in any mode incl. full, no readable id or state-name text drawn in the row (state name lives only in the state button's title tooltip), no attachment count. One row gap throughout, --sp-4. Lead = priority slot (always reserved, 24px box) · state glyph, --sp-4 apart. Right side in Linear order: linked entity (.tl-rel, full mode only, exactly ONE reference: task.project + .tl-milestone diamond chip, else deal, else first contact — never \"+N\", never project alongside deal/contacts) → tags (.tl-tags.tl-tags-slot, own row element at every width, .acrm-pill.sm, max 2 shown + .tl-more \"+N\" with full list in title) → assignee → due date. width narrow = avatar+initials · wide = avatar + full name · full = /tasks overview, due/assignee columns sized from content (--tl-due-ch) and pinned to opposite edges. .tl-rcheck gone from real task rows (since 11 Sep 2026); AI suggestion rows have no checkbox either — their state slot is a muted, non-interactive .tl-state.sug glyph. Subtasks (.tl-row.sub) indent 28px/depth with a light ::before connector in the gutter, right columns stay in axis. Group bar .tl-grp = tinted strip (--surface-75, --radius-sm) at row height/type scale, --fg-secondary only, leading .tl-grp-ic mark for the grouping axis (state/assignee/milestone/type — host-supplied via TLGroup.icon). Mobile ≤720px (apps/web/src/ds/responsive.css, app-only — not ported): two-line row, linked-entity slot hidden, suggestion actions always visible. Host behaviour on /tasks (ACRM-273, app-only, not props of this component): a \"Seskupit\" NavSelect chip groups the loaded page client-side (none/state/milestone/assignee/type, apps/web/src/lib/task-groups.ts) and a separate Návrhy view (sparkles chip + count) shows the suggestion collector alone and uncapped; that view's container gets .tl-navrhy, which narrows --tl-w-lead above 1101px. Drag reorder, 16 Sep 2026 (acrm !3687, !3692, !3695): the gesture runs on POINTER events, not HTML5 drag-and-drop (dragstart never fires from a finger, so the old build silently did nothing on touch) — mouse arms after 4px, touch after a 320ms hold, a >8px move inside that hold is a scroll and cancels; `touch-action: none` only on the lifted row, so the list still scrolls with a finger. Drop position comes from `data-tl-grp` (useId per group) + `data-tl-pos`, `data-tl-item` marks what can be picked up (a done row is target only); moves tracked on document, touchmove non-passive. Offered in EVERY sort and with grouping on — the ungrouped list always gets `onReorder`, each group gets it when grouped, and the drop switches `Řadit` to `Vlastní` without overwriting a sort the user changed meanwhile (before this it was reachable only after finding `Řadit → Vlastní`). Group bar: the tinted look is scoped `.tl .tl-grp`, never bare — `.tl-grp` is shared canon (Aktivita timeline `.tlx-body .tl-grp`, calls page, entity timeline) and an unscoped restyle tints those too (caught by timeline-lead.test.ts). Mobile additions (responsive.css): the due column is capped at `min(var(--tl-w-due), 9ch)` with `.tl-meta` sized to the same ceiling and the date ellipsised — one task worded „za 3 týdny\" was widening the column on every row; and Návrhy gets its own phone entry `button.tk-navrhy-vstup` (apps/web/src/ds/tasks.css, ≥44px = calc(var(--sp-7) + var(--sp-1)), sparkles mark + count + chevron styled through `> .ti`) because the desktop chip row folds away at this width. acrm !4068 (28 Sep 2026, AD): .tl-addrow is THE quiet add-row primitive — also \"Přidat milník\" and the empty Share dialog; button.tl-addrow resets the native button; inside an inset host it bleeds by --sp-5 (label aligned, hover edge to edge). acrm !4069: suggestion actions always visible on touch/≤720px, own right-aligned line on phone, 44 px = calc(var(--sp-7) + var(--sp-1)); CRM change suggestions of a meeting use the same Zamítnout/Přijmout Button compact pair. Tags (11 Oct 2026, acrm !4964, AD review of DS !5): tags are their own row element `TaskTags` (`.tl-tags.tl-tags-slot`, row gets `.has-tags`) drawn at EVERY width — no longer inside the linked slot, which only `width=\"full\"` renders. They sit right-aligned just before assignee and due (the slot carries `margin-left: auto`, the meta follows at the row gap); on a phone they drop to their own full-width line after the meta (RULES §20). Rules live in `apps/web/src/ds/item-list.css`. Registry repaired 17 Oct 2026 (review F1): ds/task-list-dnd.css no longer exists; drag styling is in ds/reorder.css. Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .tl-drop-line. Registry repaired 17 Oct 2026 (review F4/F11): attached css reorder.css.","source":"package","react":["TaskList","TaskPriorityIcon"],"classes":[".tl-row",".tl-row.sub",".tl-lead",".tl-prio",".tl-state",".tl-state.sug",".tl-tags",".tl-row.has-tags",".tl-tags-slot",".tl-milestone",".tl-person.ini",".tl-navrhy",".tl-grp",".tl-grp-ic",".tl-grouped",".tl-addrow",".tl-full",".tl-counts",".tl-rcheck",".tl-rdue",".tl-reorder",".tl-row.dragging","button.tk-navrhy-vstup","button.tl-addrow"],"files":["packages/ui/src/components/TaskList.tsx","packages/ui/src/components/TaskPriorityIcon.tsx","packages/ui/src/lib/task-glyphs.ts"],"css":["apps/web/src/ds/task-list.css","apps/web/src/ds/responsive.css","apps/web/src/ds/tasks.css","apps/web/src/ds/item-list.css","apps/web/src/ds/reorder.css"],"stories":{"Default":["components--task-list--default"],"Variants":["components--task-list--variants"],"Sizes":["components--task-list--sizes"],"States":["components--task-list--states"],"With icon & kbd":["components--task-list--with-icon-and-kbd"],"Composition":["components--task-list--composition"]},"legacy":["Task list.html"],"related":["item-list","entity-ref","avatar"],"docs":"docs/task-list/task-list","url":"http://192.168.230.131:3777/ds/components/task-list/task-list","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Task list","card":"Task list.html","react":["TaskList"],"classes":[".tl"],"tokens":[],"status":"OK","note":""}}}]},{"id":"email-list","name":"Email list","category":"Records & data","summary":"Mailbox rows with sender, subject, snippet and quick actions.","url":"http://192.168.230.131:3777/ds/components/email-list","coverage":100,"subcomponents":[{"id":"email-list","name":"Email list","summary":"Mail listing built on Item list rows; the mail family only adds the star, the sender, the date and hover actions.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"The old row engine (.eml-row, .eml-sender, .eml-subj, .eml-snip, .eml-ck, .eml-chip, .eml-att, .eml-name, .eml-count, .eml-line) is DEAD CSS — the row migrated onto ItemList.Row.","source":"app-css","react":["EmailList"],"classes":[".eml-tabs",".eml-tab",".eml-who",".eml-date",".eml-meta",".eml-star",".eml-icobtn",".il-row"],"files":["apps/web/src/ds/email-list.css","apps/web/src/components/mail/EmailList.tsx"],"css":["apps/web/src/ds/email-list.css"],"stories":{"Default":["components--email-list--default"],"Variants":["components--email-list--variants"],"Sizes":[],"States":["components--email-list--states"],"With icon & kbd":[],"Composition":["components--email-list--composition"]},"legacy":["email-list.html"],"related":["item-list","checkbox","icon-button"],"docs":"docs/email-list/email-list","url":"http://192.168.230.131:3777/ds/components/email-list/email-list","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Email list","card":"email-list.html","react":[],"classes":[".eml-il"],"tokens":[],"status":"OK","note":"kanonický ItemList (.eml-il, řádek EmailRow) — sdílí /posta + záložky E-maily; starý engine .eml-row smazán jako mrtvý (!4425)"}}}]},{"id":"attachment","name":"Attachment","category":"Records & data","summary":"One shape of a file attachment everywhere: name, size and context actions in a 28px chip.","url":"http://192.168.230.131:3777/ds/components/attachment","coverage":100,"subcomponents":[{"id":"attachment","name":"Attachment","summary":"Chip with a type glyph, a name that opens the preview, muted size and IconButton actions by context (download, save to CRM, remove); dashed `auto` variant for a file that does not exist yet.","status":"canon","shown":"canon","approvedAt":"2026-09-27","notes":"Approved by the owner 27 Sep 2026 (variant A) and delivered in acrm !3997 (feat/ds-attachment + refactor/prilohy-ctecka), replacing four earlier families in one move: the mail reader's segmented frame (.mv-att), the compose chip (.mc-att), the template preview's dashed auto chip (.pv-att-auto) and the task tile (.tk-att-*, AttachmentTile). Anatomy: name = `<Button variant=\"ghost\" compact>` (type glyph + name, opens the preview) when `onOpen` is set, else a static span; size is muted meta (`formatAttachmentSize` — ONE algorithm everywhere: below 1 MB shows rounded kB, at/above 1 MB shows MB to one decimal with a comma, e.g. \"482 kB\", \"2,3 MB\" — no other place in the app formats a file size); actions are `IconButton size=\"sm\"` by context — download (`href`, opens in a new tab) → save to CRM (`file-import`) → remove (`x`, always LAST). `auto` = a file that does not exist yet (an automatic template attachment before send): dashed border, no size, no actions. `busy` dims the name and disables the actions during upload/save. Row wrapper `.acrm-atts` wraps the chips (28px tall, aligned with `.tk-chip`). Consumers migrated in the same MR: EmailReader/MessageCard/ThreadView (mail reader), mail-drafts, AktivityPage, ProjectMeetingsTab, ProjectMilestonesSection, TaskDialog — `.mv-atts` on the mail reader keeps only layout, the chip itself is DS.Attachment (the temporary ds-ok on .mv-atts from !3997 was removed in acrm !4023, which aligned the mail-compose mirror card with DS.Attachment). File-size formatting bug fixed in the same MR (post-merge review !3997): saved attachment ids are held as a Set so a concurrent save cannot double-save the same attachment. Migration COMPLETED in acrm !4021 (27 Sep 2026): compose, mail templates, task dialog and task detail now also render DS.Attachment, so an attachment has ONE look everywhere (reader, thread, Activity, compose, templates, task dialog, task detail). Removed with it: mail-glyphs.tsx, AttachmentTile.tsx and the CSS families .mc-att*, .pv-att-auto, .tk-att*. The size algorithm was unified in a separate, revertable commit (base 1024; before, the same file showed 482 kB in the reader and 471 kB on the card). Registry repaired 17 Oct 2026 (review F5): FilePreview, FilePreviewModal live in apps/web (see files), not exported by @acrm/ui; dropped from react[]. Registry repaired 17 Oct 2026 (review F4/F11): attached css FilePreview.css.","source":"package","react":["Attachment"],"classes":[".acrm-atts",".acrm-att",".acrm-att-static",".acrm-att-nm",".acrm-att-sz",".acrm-att.auto",".acrm-att.busy"],"files":["packages/ui/src/components/Attachment.tsx","apps/web/src/components/FilePreview.tsx"],"css":["apps/web/src/ds/attachment.css","apps/web/src/components/FilePreview.css"],"stories":{"Default":["components--attachment--default"],"Variants":["components--attachment--variants"],"Sizes":[],"States":["components--attachment--states"],"With icon & kbd":[],"Composition":["components--attachment--composition"]},"legacy":[],"related":["icon-button","button","email-list","task-list"],"docs":"docs/attachment/attachment","url":"http://192.168.230.131:3777/ds/components/attachment/attachment","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"file-drop","name":"File drop","summary":"The one surface for choosing a file: drop zone with a glyph, label, accepted formats, upload progress and an inline error.","status":"canon","shown":"canon","approvedAt":"2026-10-03","notes":"Owner approved v2 on 3 Oct 2026 (acrm !4548): replaced Import .drop, the identity image .idimg-pick and the Documents step-1 zone. Import on dev = approved design, 0 px difference (1440 and 390). Canon since 4 Oct 2026: also used by step 1 of the Documents form-less dialog (acrm !4574), checked on dev at 1440 and 390.","source":"package","react":["FileDrop"],"classes":[".acrm-filedrop-wrap",".acrm-filedrop",".fd-ic",".fd-label",".fd-formats",".fd-prog",".fd-err"],"files":["packages/ui/src/components/FileDrop.tsx"],"css":["apps/web/src/ds/file-drop.css"],"stories":{"Default":["components--file-drop--default"],"Variants":[],"Sizes":[],"States":["components--file-drop--states"],"With icon & kbd":[],"Composition":["components--file-drop--composition"]},"legacy":[],"related":["attachment","formless-dialog"],"docs":"docs/attachment/file-drop","url":"http://192.168.230.131:3777/ds/components/attachment/file-drop","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"voice-message","name":"Voice message","category":"Records & data","summary":"Media messages in a chat bubble — voice note, round video note and 16:9 video — with one shared player and a collapsible transcript.","url":"http://192.168.230.131:3777/ds/components/voice-message","coverage":100,"subcomponents":[{"id":"voice-message","name":"Voice message","summary":"A voice note in a chat bubble: round play, 64-bar waveform track, duration, speed and a Přepis link.","status":"canon","shown":"canon","approvedAt":"2026-10-08","notes":"acrm !4918 (DS) + !4935 (Komunikace) + !4956 (44 px tap target), prototype proto/chat-hlasove-zpravy@6ed969dc9 (owner approved 8 Oct 2026). Family split from discussion/voice-message on 11 Oct 2026 (owner R43 a). Dev check 10 Oct 2026 (chat Erik Olšiak, 1440/390 light/dark): bubble 358/301 px, play 32×32 centred on the track. Owner 11 Oct 2026: on phone the track bars have NO gap so 64 bars fit — main still has gap 1px at ≤720 px, fix comes in a separate acrm MR (.91). Open for acrm: .vm-time / .vm-speed use tabular-nums on time (RULES mono/time rule). Canon 14 Oct 2026: dev check after !4957 + !4982 — 390 px 64 bars × 3.7 px, gap 0; time without tabular-nums (StableTime). Signed off by AD.","source":"package","react":["VoiceMessage"],"classes":[".vmx",".vm-msg",".vm",".vm-play",".vm-wave",".vm-row",".vm-time",".vm-dot",".vm-grow",".vm-speed",".vm-unplayable",".vm-trlink",".vm-trst",".vm-tr",".vm-tr-meta",".vm-tr-t",".vm-seg",".vm-copy"],"files":["packages/ui/src/components/VoiceMessage.tsx","packages/ui/src/components/voice-message-parts.tsx","apps/web/src/pages/komunikace/ChatMessageAttachments.tsx"],"css":["apps/web/src/ds/voice-message.css"],"stories":{"Default":["components--voice-message--default"],"Variants":["components--voice-message--in-out"],"Sizes":[],"States":["components--voice-message--transcript-states"],"With icon & kbd":[],"Composition":["components--voice-message--conversation"]},"legacy":[],"related":["video-note","video-message","chat-thread","button"],"docs":"docs/voice-message/voice-message","url":"http://192.168.230.131:3777/ds/components/voice-message/voice-message","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"video-note","name":"Video note","summary":"A round 200 px video without a bubble, with a 3 px accent progress ring, duration and a Přepis link.","status":"canon","shown":"canon","approvedAt":"2026-10-08","notes":"acrm !4918 (DS) + !4935 (Komunikace) + !4956 (44 px tap target), prototype proto/chat-hlasove-zpravy@6ed969dc9 (owner approved 8 Oct 2026). Family split from discussion/voice-message on 11 Oct 2026 (owner R43 a). Not on dev with data (stories only). Canon 14 Oct 2026: dev check after !4957 + !4982 — 390 px 64 bars × 3.7 px, gap 0; time without tabular-nums (StableTime). Signed off by AD. Own stories + light/dark baseline: acrm !5079 (Default · In-out · States; fixed wrapping of „Přepis se nepodařil · Zkusit znovu“ under the 200 px circle).","source":"package","react":["VideoNote"],"classes":[".vmx",".vm-bare",".vn",".vn-circle",".vn-ring",".vn-ico",".vn-row",".vm-time",".vm-grow",".vm-trlink",".vm-trst",".vm-tr",".vm-tr-meta",".vm-tr-t",".vm-seg",".vm-copy"],"files":["packages/ui/src/components/VoiceMessage.tsx","packages/ui/src/components/voice-message-parts.tsx","apps/web/src/pages/komunikace/ChatMessageAttachments.tsx"],"css":["apps/web/src/ds/voice-message.css"],"stories":{"Default":["components--video-note--default"],"Variants":["components--video-note--in-out"],"Sizes":[],"States":["components--video-note--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["voice-message","video-message","chat-thread"],"docs":"docs/voice-message/video-note","url":"http://192.168.230.131:3777/ds/components/voice-message/video-note","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"video-message","name":"Video message","summary":"A 16:9 video in a chat bubble with duration on a scrim, a progress bar, a time row, Přepis link and optional caption.","status":"canon","shown":"canon","approvedAt":"2026-10-08","notes":"acrm !4918 (DS) + !4935 (Komunikace) + !4956 (44 px tap target), prototype proto/chat-hlasove-zpravy@6ed969dc9 (owner approved 8 Oct 2026). Family split from discussion/voice-message on 11 Oct 2026 (owner R43 a). Not on dev with data (stories only). Canon 14 Oct 2026: dev check after !4957 + !4982 — 390 px 64 bars × 3.7 px, gap 0; time without tabular-nums (StableTime). Signed off by AD. Own stories + light/dark baseline: acrm !5079 (Default · In-out · States; fixed wrapping of „Přepis se nepodařil · Zkusit znovu“ under the 200 px circle).","source":"package","react":["VideoMessage"],"classes":[".vmx",".vv-msg",".vv-frame",".vv-dur",".vv-bar",".vv-row",".vn-ico",".vm-time",".vm-grow",".vm-trlink",".vm-trst",".vm-tr",".vm-tr-meta",".vm-tr-t",".vm-seg",".vm-copy"],"files":["packages/ui/src/components/VoiceMessage.tsx","packages/ui/src/components/voice-message-parts.tsx","apps/web/src/pages/komunikace/ChatMessageAttachments.tsx"],"css":["apps/web/src/ds/voice-message.css"],"stories":{"Default":["components--video-message--default"],"Variants":["components--video-message--in-out"],"Sizes":[],"States":["components--video-message--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["voice-message","video-note","chat-thread","attachment"],"docs":"docs/voice-message/video-message","url":"http://192.168.230.131:3777/ds/components/voice-message/video-message","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"deal-card","name":"Deal card","category":"Records & data","summary":"Pipeline board card summarising a deal.","url":"http://192.168.230.131:3777/ds/components/deal-card","coverage":100,"subcomponents":[{"id":"deal-card","name":"Deal card","summary":"Kanban card of a deal: mark, name, value, subtitle, products, due date and counts.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Known defect: the card root is a plain div onClick — no role, no tab stop, no keys — so a deal can only be opened with a mouse (StatTile shows the correct pattern). acrm !4026 (27 Sep 2026): card padding = var(--sp-4) (was 10/11 px, no token) — card 82 → 86 px; token-by-meaning rule, AD-approved. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories. Registry repaired 17 Oct 2026 (review F4/F11): attached css deal-card-rows.css.","source":"package","react":["DealCard"],"classes":[".acrm-dealcard"],"files":["packages/ui/src/components/DealCard.tsx"],"css":["apps/web/src/ds.css","apps/web/src/ds/board.css","apps/web/src/ds/deal-card-rows.css"],"stories":{"Default":["components--deal-card--default"],"Variants":["components--deal-card--variants","components--deal-card--rows"],"Sizes":[],"States":["components--deal-card--states"],"With icon & kbd":[],"Composition":["components--deal-card--composition"]},"legacy":["deal-card.html"],"related":["entity-ref","avatar","pill"],"docs":"docs/deal-card/deal-card","url":"http://192.168.230.131:3777/ds/components/deal-card/deal-card","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Deal card","card":"deal-card.html","react":["DealCard"],"classes":[".acrm-dealcard"],"tokens":[],"status":"OK","note":"root .card → .acrm-dealcard (globální kolize); starší screen port v pipeline.css driftuje — migrace boardu follow-up"}}}]},{"id":"stat-tile","name":"Stat tile","category":"Records & data","summary":"KPI tile with value, label and target; hairline, no shadow.","url":"http://192.168.230.131:3777/ds/components/stat-tile","coverage":100,"subcomponents":[{"id":"stat-tile","name":"Stat tile","summary":"One number with its name: hairline card without a shadow, value in --h1 with tabular figures.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"A clickable tile is done right: role=button, tabIndex and Enter/Space — the pattern Deal card and Section block still lack.","source":"app-css","react":["StatTile","StatGrid"],"classes":[".stat-grid",".stat-tile",".stat-val",".stat-label",".stat-target",".stat-actual"],"files":["apps/web/src/ds/stat-tile.css","apps/web/src/components/StatTile.tsx"],"css":["apps/web/src/ds/stat-tile.css"],"stories":{"Default":["components--stat-tile--default"],"Variants":["components--stat-tile--variants"],"Sizes":["components--stat-tile--sizes"],"States":["components--stat-tile--states"],"With icon & kbd":[],"Composition":["components--stat-tile--composition"]},"legacy":["Stat tile.html"],"related":["section-block","skeleton-line"],"docs":"docs/stat-tile/stat-tile","url":"http://192.168.230.131:3777/ds/components/stat-tile/stat-tile","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"meter","name":"Meter","summary":"A thin static bar showing how full something is against a limit or a goal; the value stands next to it as text.","status":"canon","shown":"canon","approvedAt":"2026-09-26","notes":"AD 26 Sep 2026 (wave B inventory): Meter and Progress are two legitimate elements, the same pair as HTML <meter> vs <progress>. Meter = a static ratio to a limit or goal (budget drawn, room occupancy, KPI, progress to promotion, project done/total, portfolio weight); Progress = work running now that ends done or failed. 7 uses on main (Rozpočty ×2, Zasedačky, Tým detail, Člen týmu KPI + Rozpočty, Portfolio výsledky, StatTile pct); Kariéra (.kar-bar, acrm !3898) and the public project page (ProgressBar.tsx deleted, .dp-*, acrm !3900) were migrated onto it on 27 Sep 2026. Moved into @acrm/ui on 27 Sep 2026 (acrm !3929: Meter + usageTone, CSS layer ds/meter.css, stories with baseline, zero visual change on 776 snapshots). TaskList .tl-prog turned out to be dead API (no screen passed progress/pct) and is deleted (acrm !3947). Track = --border like Progress — approved by the owner 27 Sep 2026 (preview meter-draha: the --surface-75 track was practically invisible on white cards). Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.","source":"package","react":["Meter"],"classes":[".fin-bar",".fin-bar-fill",".fin-bar-fill.warn",".fin-bar-fill.crit"],"files":["packages/ui/src/components/Meter.tsx"],"css":["apps/web/src/ds/meter.css"],"stories":{"Default":["components--meter--default"],"Variants":["components--meter--variants"],"Sizes":["components--meter--sizes"],"States":["components--meter--states"],"With icon & kbd":[],"Composition":["components--meter--composition"]},"legacy":[],"related":["progress","stat-tile"],"docs":"docs/stat-tile/meter","url":"http://192.168.230.131:3777/ds/components/stat-tile/meter","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"chart","name":"Chart","category":"Records & data","summary":"Column or bar chart for structured numbers that come from a tool or a query: a pipeline by stage, volume by month, share by person.","url":"http://192.168.230.131:3777/ds/components/chart","coverage":100,"subcomponents":[{"id":"chart","name":"Chart","summary":"One or two series of a magnitude per category: columns (desktop) or horizontal bars (narrow hosts), marks ≤ 24 px with a rounded data end, hairline axis, values in text; selectable categories for a detail list below.","status":"candidate","shown":"candidate","approvedAt":null,"notes":"Candidate 16 Oct 2026 (assistant workspace, ZADANI-asistent-plocha.md W-pl/2, acrm feat/ds-chart). First host = the Pipeline artefact on /asistent; later the pinned view tile on Home. Palette validated with the dataviz validator on both surfaces: series 1 --accent, series 2 --ic-rose (deutan ΔE 11, normal ΔE 19); --ic-purple (deutan 7.4) and --ic-amber (lightness, contrast 2.08:1) rejected. Three or more series are not supported on purpose — small multiples instead. Known gaps for the canon decision: no built-in table view (host provides the list), no line chart, no texture fill for forced-colours.","source":"package","react":["Chart"],"classes":[".acrm-chart",".acrm-chart.column",".acrm-chart.bar",".acrm-chart.sm",".acrm-chart.multi",".acrm-chart-legend",".acrm-chart-key",".acrm-chart-plot",".acrm-chart-cat",".acrm-chart-cat.is-on",".acrm-chart-vals",".acrm-chart-val",".acrm-chart-track",".acrm-chart-mark",".acrm-chart-label",".acrm-chart-note"],"files":["packages/ui/src/components/Chart.tsx","packages/ui/src/components/Chart.test.tsx","packages/ui/stories/chart.stories.tsx"],"css":["apps/web/src/ds/chart.css"],"stories":{"Default":["components--chart--default"],"Variants":["components--chart--variants"],"Sizes":["components--chart--sizes"],"States":["components--chart--states"],"With icon & kbd":[],"Composition":["components--chart--composition"]},"legacy":[],"related":["stat-tile","meter","item-list"],"docs":"docs/chart/chart","url":"http://192.168.230.131:3777/ds/components/chart/chart","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"section-block","name":"Section block","category":"Records & data","summary":"Titled block with count and actions used to group record content.","url":"http://192.168.230.131:3777/ds/components/section-block","coverage":100,"subcomponents":[{"id":"section-block","name":"Section block","summary":"Two heading levels and no third: block (--h2) groups, sec (--h3) sections, count only on sec.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Known defect: a collapsible header is a plain div onClick — mouse only, no focus state. Reading column `.sb-flow`/`.sb-full` (owner 26 Sep 2026, acrm !3998): centres blocks at 800px (`calc(var(--sp-7) * 20)`), spaces them 32px; `.sb-full` opts a control child (player, filter row) back out to full width. Used on project detail + its Schůzky tab, and meeting detail's Minutes/Transcript tabs. NOT on person/company/deal cards (P443) and NOT on task detail — its document (`.tdl-doc`, task-detail.css) measures its own reading column, so `UkolDetailPage.tsx` deliberately omits `.sb-flow` on `main` and on its own error EmptyState (review fix in the same MR). No new stories yet for the variant.","source":"app-css","react":["SectionBlock","SectionAction"],"classes":[".sb-block",".sb-h",".sb-sec",".sb-acts",".sb-peek",".sb-flow",".sb-full"],"files":["apps/web/src/ds/section-block.css","apps/web/src/components/SectionBlock.tsx"],"css":["apps/web/src/ds/section-block.css"],"stories":{"Default":["components--section-block--default"],"Variants":["components--section-block--variants"],"Sizes":[],"States":["components--section-block--states"],"With icon & kbd":[],"Composition":["components--section-block--composition"]},"legacy":["Section block.html"],"related":["count-badge","stat-tile","note-card"],"docs":"docs/section-block/section-block","url":"http://192.168.230.131:3777/ds/components/section-block/section-block","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"timeline","name":"Timeline","category":"Records & data","summary":"Activity axis of a record: events, changes and the next-step nudge.","url":"http://192.168.230.131:3777/ds/components/timeline","coverage":100,"subcomponents":[{"id":"timeline","name":"Timeline","summary":"Vertical activity feed: ItemList rows on an axis, day groups, a tinted today block, task cards, a change grid and one nudge.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Not a list pattern of its own: every row is an ItemList row (.il-row) and timeline.css adds only the axis, the groups and the event-specific cells. The sheet MUST load after item-list.css and task-list.css. React lives in the app, not in @acrm/ui.","source":"app-css","react":["EntityTimeline","TimelineRow","TodayGroup"],"classes":[".tlx",".tlx-bar",".tlx-body",".tlx-narrow",".tl-rail",".tl-today",".tl-sec",".tl-grp",".tcard",".tc-prio",".chg",".chg-r",".tr",".tstack",".prods",".il-nudge",".is-taskev",".is-now"],"files":["apps/web/src/components/timeline/EntityTimeline.tsx","apps/web/src/components/timeline/TimelineRow.tsx","apps/web/src/components/timeline/TodayGroup.tsx","apps/web/src/ds/timeline.css"],"css":["apps/web/src/ds/timeline.css","apps/web/src/ds/item-list.css"],"stories":{"Default":["components--timeline--default"],"Variants":["components--timeline--variants"],"Sizes":["components--timeline--sizes"],"States":["components--timeline--states"],"With icon & kbd":["components--timeline--with-icon-and-kbd"],"Composition":["components--timeline--composition"]},"legacy":["timeline.html","Aktivity.html"],"related":["note-card","task-list","section-block"],"docs":"docs/timeline/timeline","url":"http://192.168.230.131:3777/ds/components/timeline/timeline","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"note-card","name":"Note card","category":"Records & data","summary":"Card of a note with author, time, title and body excerpt.","url":"http://192.168.230.131:3777/ds/components/note-card","coverage":100,"subcomponents":[{"id":"note-card","name":"Note card","summary":"A note as a card in the grid: five-line clamp, muted placeholders when empty, date never tabular.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"The card is a real button with its own focus ring; it is not exported as a component (private inside NotesGrid.tsx).","source":"app-css","react":[],"classes":[".note-grid",".note-card",".note-hd",".note-title",".note-body",".note-foot",".note-card--sk"],"files":["apps/web/src/ds/note-card.css"],"css":["apps/web/src/ds/note-card.css"],"stories":{"Default":["components--note-card--default"],"Variants":["components--note-card--variants"],"Sizes":[],"States":["components--note-card--states"],"With icon & kbd":[],"Composition":["components--note-card--composition"]},"legacy":["note-card.html"],"related":["timeline","section-block","skeleton-line"],"docs":"docs/note-card/note-card","url":"http://192.168.230.131:3777/ds/components/note-card/note-card","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"avatar","name":"Identity marks","category":"Identity","summary":"One mark for every record: initials or a photo for a person and a company, a typed tile for everything else, a generated face for our own users.","url":"http://192.168.230.131:3777/ds/components/avatar","coverage":80,"subcomponents":[{"id":"avatar","name":"Avatar","summary":"Identity mark in three sizes (inline 16 · sm 24 default · lg 32): circle for a person, square for a company, hue hashed from the name — or an uploaded picture filling the same box, ringed in --border.","status":"canon","shown":"canon","approvedAt":"2026-09-10","notes":"The hue colours the 1.5px ring and the initials, never the fill. A picture takes a neutral --border ring instead of the hue; screens render it through PersonPhoto / OrgLogo, never <Avatar photo> directly, because the primitive has no onError. The ladder lost its fourth rung (md 26) after measuring 73 call sites: it did the same job as sm and differed by 8 %. The smallest square is rounded 6px so it does not read boxier than the bigger ones. Registry repaired 17 Oct 2026 (review F4/F11): attached css OrgLogo.css, PersonPhoto.css.","source":"package","react":["Avatar","hashHue","initials","hueStyle"],"classes":[".acrm-avatar"],"files":["packages/ui/src/components/Avatar.tsx","packages/ui/src/lib/identity.ts","apps/web/src/components/person/PersonPhoto.tsx","apps/web/src/components/person/PersonPhoto.css","apps/web/src/components/OrgLogo.tsx","apps/web/src/components/OrgLogo.css"],"css":["apps/web/src/ds.css","apps/web/src/components/OrgLogo.css","apps/web/src/components/person/PersonPhoto.css"],"stories":{"Default":["components--avatar--default"],"Variants":["components--avatar--variants"],"Sizes":["components--avatar--sizes"],"States":["components--avatar--states"],"With icon & kbd":[],"Composition":["components--avatar--composition"]},"legacy":["avatars.html"],"related":["entity-ref","item-list","title-with-entity-tile"],"docs":"docs/avatar/avatar","url":"http://192.168.230.131:3777/ds/components/avatar/avatar","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Avatars","card":"avatars.html","react":["Avatar"],"classes":[],"tokens":[],"status":"OK","note":""}}},{"id":"entity-mark","name":"Entity mark","summary":"The mark of any record: tone says which world the type belongs to, glyph says the exact type, shape says person / company / thing. One vocabulary for over twenty types.","status":"canon","shown":"canon","approvedAt":"2026-09-10","notes":"Replaces seven parallel vocabularies (chip tile, palette glyph, listing tone, nav icons, ad-hoc header glyph, and the two picker maps in MentionInput and EntityPicker, which contradicted the canon — deal as businessplan, product rose in one picker and grey in the next, a tone on people and companies at all). Seven tones cannot cover twenty types, so the tone groups and the glyph identifies. Glyph size keeps the parity of the box — an odd difference puts the drawing on a half pixel.","source":"package","react":["EntityMark","entityMark","ENTITY_MARK","glyphNudge"],"classes":[".acrm-mark"],"files":["packages/ui/src/components/EntityMark.tsx","packages/ui/src/lib/entity-mark.ts"],"css":["apps/web/src/ds/entity-mark.css"],"stories":{"Default":["components--entity-mark--default"],"Variants":["components--entity-mark--variants"],"Sizes":["components--entity-mark--sizes"],"States":["components--entity-mark--states"],"With icon & kbd":[],"Composition":["components--entity-mark--composition"]},"legacy":[],"related":["avatar","user-avatar","entity-ref","item-list","section-top-bar"],"docs":"docs/avatar/entity-mark","url":"http://192.168.230.131:3777/ds/components/avatar/entity-mark","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"country-flag","name":"Country flag","summary":"Flat vector flag of a country (30 × 20, rounded, hairline outline) — the mark of a phone number by its dialling code.","status":"beta","shown":"beta","approvedAt":null,"notes":"Owner-approved 15 Oct 2026 in prototype proto/telefony-pin-puk (picks ACRM-515, ACRM-518: „vlajky úplně jednoduše, plošně vektorově\", style reference nucleoapp.com/svg-flag-icons — own drawing, no Nucleo SVG copied, licence unclear). First use: /telefony identity column and drawer head (acrm !5089). Covers the 50 countries of DIAL_CODES; unknown code falls back to the grey phone tile. Before beta: move to packages/ui next to EntityMark, stories (all flags, sizes sm/lg, fallback), props. DialCodePicker („CZ +420 ▾\") stays WITHOUT a flag — owner decision 15 Oct 2026. Registry repaired 17 Oct 2026 (review F1, F10): Flag/PhoneFlag now live in packages/ui/src/components/CountryFlag.tsx and are exported from @acrm/ui. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories. Beta 17 Oct 2026 (AD): moved to @acrm/ui next to EntityMark with stories Default · Variants · Sizes · States · Composition + 10 light/dark baselines (acrm !5124, 445b2e68b). AD 17 Oct 2026: a number without a dialling code is read as Czech (splitDial falls back to DEFAULT_DIAL +420, the same default as DialCodePicker and the phone mask) and shows the Czech flag — it is dialled as Czech; the grey phone tile stays only for a code outside DIAL_CODES. Canon after a dev check of /telefony with real data 1440/390 light/dark.","source":"package","react":["Flag","PhoneFlag"],"classes":[".acrm-flag"],"files":["packages/ui/src/components/CountryFlag.tsx"],"css":[],"stories":{"Default":["components--country-flag--default"],"Variants":["components--country-flag--variants"],"Sizes":["components--country-flag--sizes"],"States":["components--country-flag--states"],"With icon & kbd":[],"Composition":["components--country-flag--composition"]},"legacy":[],"related":["entity-mark","avatar"],"docs":"docs/avatar/country-flag","url":"http://192.168.230.131:3777/ds/components/avatar/country-flag","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"user-avatar Dev check 25 Oct 2026 (AD): /telefony renders .acrm-flag 20×13 in Chromium 1440/390 and WebKit (Safari) 1440/390, light, no overflow; dev has only ONE number (+420, Czech flag) and the dark run did not switch theme → stays beta until a check with several countries and a real dark run.","name":"User avatar","summary":"Our own person: a generated face from a five-colour palette, so a colleague is never mistaken for a contact. An uploaded photo wins over the drawing.","status":"canon","shown":"canon","approvedAt":"2026-09-10","notes":"Meeting attendees are one list mixing colleagues and outside contacts — that is the case this exists for. The palette is deliberately not --ic-*: seven muted UI tones would make colleagues look like siblings. Regenerating stores users.avatar_seed; without a seed the face follows the name. Registry repaired 17 Oct 2026 (review F6): added exported UserFacesProvider to react[].","source":"package","react":["UserAvatar","UserFacesProvider"],"classes":[".acrm-avatar.is-user",".acrm-avatar.generated"],"files":["packages/ui/src/components/UserAvatar.tsx","packages/ui/src/components/UserFacesContext.tsx"],"css":["apps/web/src/ds/entity-mark.css"],"stories":{"Default":["components--user-avatar--default"],"Variants":["components--user-avatar--variants"],"Sizes":["components--user-avatar--sizes"],"States":["components--user-avatar--states"],"With icon & kbd":[],"Composition":["components--user-avatar--composition"]},"legacy":[],"related":["avatar","entity-mark"],"docs":"docs/avatar/user-avatar","url":"http://192.168.230.131:3777/ds/components/avatar/user-avatar Dev check 25 Oct 2026 (AD): /telefony renders .acrm-flag 20×13 in Chromium 1440/390 and WebKit (Safari) 1440/390, light, no overflow; dev has only ONE number (+420, Czech flag) and the dark run did not switch theme → stays beta until a check with several countries and a real dark run.","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"brand-mark","name":"Brand mark","summary":"Brand tile of the workspace on auth and onboarding screens (white-label).","status":"beta","shown":"beta","approvedAt":null,"notes":"Candidate from gen-usage (AD 3 Oct 2026): used across the app, missing in the registry. Before beta: stories, usage + a11y docs, props. Stories in acrm !4923 (11 Oct 2026); usage + a11y docs still missing → stays candidate.","source":"app","react":["BrandMark"],"classes":[],"files":["apps/web/src/components/BrandMark.tsx"],"css":[],"stories":{"Default":["components--brand-mark--default"],"Variants":["components--brand-mark--variants"],"Sizes":[],"States":["components--brand-mark--states"],"With icon & kbd":[],"Composition":["components--brand-mark--composition"]},"legacy":[],"related":[],"docs":"docs/avatar/brand-mark","url":"http://192.168.230.131:3777/ds/components/avatar/brand-mark","coverage":{"stories":true,"props":false,"classes":false,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":false},"covered":false,"implementation":{"acrm":null}}]},{"id":"entity-reference AD 24 Oct 2026: usage.md + a11y.md written (docs/avatar/brand-mark), stories on main (acrm !4923) → beta; canon after a light/dark baseline check.","name":"Entity reference","category":"Identity","summary":"One component for referring to a record: default, mini or removable.","url":"http://192.168.230.131:3777/ds/components/entity-reference AD 24 Oct 2026: usage.md + a11y.md written (docs/avatar/brand-mark), stories on main (acrm !4923) → beta; canon after a light/dark baseline check.","coverage":100,"subcomponents":[{"id":"entity-ref","name":"Entity reference","summary":"Reference to a record in three variants: default (identity mark + name), mini (name only, for text and dense rows) and removable (token with ×).","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Merged 11 September 2026 (AD, ER-1): Entity reference mini and Entity reference removable were separate pages; they are variants of this one component (variant=\"mini\", removable). Mini draws no identity mark. Type project added 13 Sep 2026 (acrm !3466); it has no entity preview, so the reference renders without one. Registry repaired 17 Oct 2026 (review F5): EntityRefPreview live in apps/web (see files), not exported by @acrm/ui; dropped from react[].","source":"package","react":["EntityRef"],"classes":[".eref-chip",".eref-chip-nm",".eref-date",".eref-mini",".eref-token",".eref-x"],"files":["packages/ui/src/components/EntityRef.tsx","apps/web/src/components/entity-preview/EntityRefPreview.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--entity-reference--default"],"Variants":["components--entity-reference--variants","components--entity-reference-mini--default","components--entity-reference-mini--variants","components--entity-reference-removable--default","components--entity-reference-removable--variants"],"Sizes":[],"States":["components--entity-reference--states","components--entity-reference-mini--states","components--entity-reference-removable--states"],"With icon & kbd":[],"Composition":["components--entity-reference--composition","components--entity-reference-mini--composition","components--entity-reference-removable--composition"]},"legacy":["entity-ref.html","entity-ref-mini.html","entity-ref-removable.html"],"related":["entity-preview","avatar","item-list","mention-input","task-list","record-select","rail"],"docs":"docs/entity-reference/entity-ref","url":"http://192.168.230.131:3777/ds/components/entity-reference AD 24 Oct 2026: usage.md + a11y.md written (docs/avatar/brand-mark), stories on main (acrm !4923) → beta; canon after a light/dark baseline check./entity-ref","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Entity reference (mini)","card":"entity-ref-mini.html","react":["EntityRef"],"classes":[],"tokens":[],"status":"OK","note":"mini varianta téže komponenty"}}}]},{"id":"empty-state","name":"Empty state","category":"States & feedback","summary":"What a list or panel shows when there is nothing yet — or when loading it failed.","url":"http://192.168.230.131:3777/ds/components/empty-state","coverage":100,"subcomponents":[{"id":"empty-state","name":"Empty state","summary":"Icon, title, sub-line and optional action for a slot with nothing in it; tone=\"error\" turns the same block into the failed-to-load state.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Merged with Error state on 12 September 2026 (AD, ER-2; acrm !3424–!3444, 92 call sites in 61 files): one component with tone=\"empty\" | \"error\". The error tone keeps the red icon, role=\"alert\", the default wording and the retry action, but takes the empty state's geometry; ErrorState, ds/error-state.css and every .est* class are gone. Sizes V2 (AD, 12 September 2026, ACRM-228/229/230; acrm !3474): icon 24px via the new token --ico-xl (rule svg.acrm-empty-ic beats the global .ti), title var(--h2), sub-line var(--subtitle), 16px above the action; both tones and both sizes, 172 empty + 92 error call sites. `action.menu` (FA204, 26 Sep 2026, acrm !3890) draws a Menu button instead of a plain Button, confirmed in meeting Minutes/Transcript's empty states (acrm !4013/!4014, RECORDING_SOURCE_ICON-ordered sources). NotesTabBody (acrm !4013) hides its own header \"create\" button while the list is empty and hands the action to this component instead, so person/company/deal/meeting notes never offer the same create action twice.","source":"package","react":["EmptyState"],"classes":[".acrm-empty",".acrm-empty-ic",".acrm-empty-t",".acrm-empty-s",".acrm-empty.sm",".acrm-empty.error",".acrm-empty-act"],"files":["packages/ui/src/components/EmptyState.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--empty-state--default"],"Variants":["components--empty-state--variants"],"Sizes":["components--empty-state--sizes"],"States":["components--empty-state--states"],"With icon & kbd":[],"Composition":["components--empty-state--composition"]},"legacy":["empty-error-state.html","Empty states.html","Error states.html"],"related":["button","menu-button","skeleton-list","detail-state-screen","toast"],"docs":"docs/empty-state/empty-state","url":"http://192.168.230.131:3777/ds/components/empty-state/empty-state","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"loading","name":"Loading","category":"States & feedback","summary":"Skeletons and loaders that hold layout while data arrives.","url":"http://192.168.230.131:3777/ds/components/loading","coverage":100,"subcomponents":[{"id":"skeleton-line","name":"Skeleton line","summary":"Shimmering placeholder line in three heights (sm, default, lg); the atom every loading layout is built from.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"`.sk-sq`/`.sk-box`/`.sk-pill` were unused shape modifiers (SkLine never emitted them) and removed as dead code in acrm !4058 (28 Sep 2026).","source":"package","react":["SkLine"],"classes":[".sk",".sk-line",".sk-circle"],"files":["packages/ui/src/components/Skeleton.tsx"],"css":["apps/web/src/ds/skeleton.css","apps/web/src/ds.css"],"stories":{"Default":["components--skeleton-line--default"],"Variants":["components--skeleton-line--variants"],"Sizes":["components--skeleton-line--sizes"],"States":["components--skeleton-line--states"],"With icon & kbd":[],"Composition":["components--skeleton-line--composition"]},"legacy":["Loading (skeleton).html"],"related":["skeleton-list","loader"],"docs":"docs/loading/skeleton-line","url":"http://192.168.230.131:3777/ds/components/loading/skeleton-line","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"skeleton-list","name":"Skeleton list","summary":"Ready-made loading body for listings: avatar circle, main line and a meta line, with aria-busy on the wrapper.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"`.sk-card`/`.sk-kv` (kanban card and drawer composed skeletons) were unused and removed as dead code in acrm !4058 (28 Sep 2026); `SkeletonList` only ever emitted `.sk-task`.","source":"package","react":["SkeletonList"],"classes":[".sk-task"],"files":["packages/ui/src/components/Skeleton.tsx"],"css":["apps/web/src/ds/skeleton.css"],"stories":{"Default":["components--skeleton-list--default"],"Variants":["components--skeleton-list--variants"],"Sizes":["components--skeleton-list--sizes"],"States":["components--skeleton-list--states"],"With icon & kbd":[],"Composition":["components--skeleton-list--composition"]},"legacy":["Loading (skeleton).html"],"related":["skeleton-line","item-list","list-loader"],"docs":"docs/loading/skeleton-list","url":"http://192.168.230.131:3777/ds/components/loading/skeleton-list","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"loader","name":"Loader","summary":"The lying-eight loader for short waits — buttons, dialogs, inline pending; takes its colour from `color`.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":null,"source":"package","react":["Loader"],"classes":[".acrm-loadinf",".linf-track",".linf-run",".acrm-sr"],"files":["packages/ui/src/components/Loader.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--loader--default"],"Variants":["components--loader--variants"],"Sizes":["components--loader--sizes"],"States":["components--loader--states"],"With icon & kbd":[],"Composition":["components--loader--composition"]},"legacy":["Loading (skeleton).html"],"related":["list-loader","skeleton-line"],"docs":"docs/loading/loader","url":"http://192.168.230.131:3777/ds/components/loading/loader","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"list-loader","name":"List loader","summary":"The drumming hand shown while a long listing loads or pages in (AD P93); listings only, never buttons.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"Size via --lh-scale (default 0.4 ≈ 45 × 28 px), punch-out ground via --lh-bg (default --surface-100).","source":"package","react":["ListLoader"],"classes":[".acrm-loadhand",".lh-hand",".lh-finger",".lh-item",".lh-joints",".lh-nail",".lh-thumb",".acrm-sr"],"files":["packages/ui/src/components/ListLoader.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--list-loader--default"],"Variants":["components--list-loader--variants"],"Sizes":["components--list-loader--sizes"],"States":["components--list-loader--states"],"With icon & kbd":[],"Composition":["components--list-loader--composition"]},"legacy":["Loading (skeleton).html"],"related":["loader","segment-table","item-list"],"docs":"docs/loading/list-loader","url":"http://192.168.230.131:3777/ds/components/loading/list-loader","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"progress","name":"Progress","summary":"The one canonical progress bar: work that takes minutes — the step in words, an optional number, time left, optional steps; running, done or failed.","status":"canon","shown":"canon","approvedAt":"2026-09-25","notes":"Product owner 25 Sep 2026 (FA202): approved as THE one progress bar, 6 px (--sp-2) like .tl-prog instead of the 4 px candidate; the product-extraction bar (.pr-ex) was migrated onto it in acrm !3883, the other scattered bars were inventoried on 26 Sep 2026 (wave B): static ratios moved to Meter (acrm !3898, !3900), .tf-progress/.tf-subs-bar were dead CSS and removed (acrm !3901), .tl-prog in Task list turned out to be dead API and was deleted (acrm !3947). Estimates are written in words (\"asi 23 %\").","source":"package","react":["Progress"],"classes":[".acrm-progress",".pg-head",".pg-label",".pg-val",".pg-track",".pg-fill",".pg-meta",".pg-steps",".pg-step",".pg-ic",".pg-sl",".pg-sd"],"files":["packages/ui/src/components/Progress.tsx"],"css":["apps/web/src/ds/progress.css"],"stories":{"Default":["components--progress--default"],"Variants":["components--progress--variants"],"Sizes":[],"States":["components--progress--states"],"With icon & kbd":[],"Composition":["components--progress--composition"]},"legacy":[],"related":["loader","list-loader","task-list"],"docs":"docs/loading/progress","url":"http://192.168.230.131:3777/ds/components/loading/progress","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"detail-state-screen","name":"Detail state screen","summary":"Minimal record-detail frame (back button + one line) for loading and not-found; same header geometry as the loaded detail.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Coupled to person-record.css: a detail route that does not load that sheet renders this frame unstyled.","source":"package","react":["DetailStateScreen"],"classes":[".pr",".pr-top",".pr-ico",".pr-name-top"],"files":["packages/ui/src/components/DetailStateScreen.tsx"],"css":["apps/web/src/ds/person-record.css"],"stories":{"Default":["components--detail-state-screen--default"],"Variants":["components--detail-state-screen--variants"],"Sizes":[],"States":["components--detail-state-screen--states"],"With icon & kbd":[],"Composition":["components--detail-state-screen--composition"]},"legacy":["Loading (skeleton).html"],"related":["empty-state","skeleton-line"],"docs":"docs/loading/detail-state-screen","url":"http://192.168.230.131:3777/ds/components/loading/detail-state-screen","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"toast","name":"Toast","category":"States & feedback","summary":"Transient bottom notifications for finished or failed actions.","url":"http://192.168.230.131:3777/ds/components/toast","coverage":100,"subcomponents":[{"id":"toast","name":"Toast","summary":"Short confirmation of an action, stacked bottom-center; max three, hover pauses the timers, error carries role=alert.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"React implementation lives in the app (ToastProvider), not in @acrm/ui; the story rebuilds the markup 1:1. The loading toast uses the canonical <Loader>.","source":"app-css","react":["ToastProvider"],"classes":[".toast-host",".toast",".toast-ic",".toast-main",".toast-t",".toast-d",".toast-act",".toast-btn",".toast-x"],"files":["apps/web/src/components/notifications/ToastProvider.tsx","apps/web/src/ds/toast.css"],"css":["apps/web/src/ds/toast.css","apps/web/src/ds.css"],"stories":{"Default":["components--toast--default"],"Variants":["components--toast--variants"],"Sizes":[],"States":["components--toast--states"],"With icon & kbd":[],"Composition":["components--toast--composition"]},"legacy":["Notifikace a toasty.html"],"related":["notifications","dialog"],"docs":"docs/toast/toast","url":"http://192.168.230.131:3777/ds/components/toast/toast","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"notifications","name":"Notifications","category":"States & feedback","summary":"Bell panel listing unread and past notifications.","url":"http://192.168.230.131:3777/ds/components/notifications","coverage":100,"subcomponents":[{"id":"notifications","name":"Notifications","summary":"Bell with capped badge and the panel it opens: two filters, day groups, unread dot, per-filter empty state.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"React implementation lives in the app (NotifBell), not in @acrm/ui; the story rebuilds the markup 1:1. Known gap: .nitem is a div with onClick — not keyboard reachable (copy the StatTile role=button pattern to fix).","source":"app-css","react":["NotifBell"],"classes":[".nbell",".nbell-badge",".npanel",".npanel-head",".npanel-tabs",".npanel-tab",".npanel-body",".npanel-empty",".npanel-foot",".nitem",".nitem-lead",".nitem-main",".nitem-t",".nitem-meta",".nitem-link",".nitem-dot",".ngroup-label"],"files":["apps/web/src/components/notifications/NotifBell.tsx","apps/web/src/ds/notifications.css"],"css":["apps/web/src/ds/notifications.css"],"stories":{"Default":["components--notifications--default"],"Variants":["components--notifications--variants"],"Sizes":[],"States":["components--notifications--states"],"With icon & kbd":[],"Composition":["components--notifications--composition"]},"legacy":["Notifikace (zvonek).html","Notifikace a toasty.html"],"related":["toast","popover","count-badge"],"docs":"docs/notifications/notifications","url":"http://192.168.230.131:3777/ds/components/notifications/notifications","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"status","name":"Status","category":"States & feedback","summary":"Small indicators of state and quantity; use sparingly.","url":"http://192.168.230.131:3777/ds/components/status","coverage":75,"subcomponents":[{"id":"pill","name":"Pill","summary":"Outlined label whose colour is carried by a saturated dot: seven hues for distinctness, plus one reserved tone, critical.","status":"canon","shown":"canon","approvedAt":"2026-10-09","notes":"No React component of its own — TagPills, StatusChip and the listing columns all emit .acrm-pill. AD 6 Sep 2026 (after Linear): the tinted ground was replaced by an outlined chip with a saturated --ic-* dot and full-contrast text. The old ground measured only 1.03-1.19:1 against the canvas, so in dark theme the tone did almost nothing and the colour was really carried by the text; it also left grey with no shape at all and needed a background AND an ink per tone. A label with an icon has no dot (:has(.ti)). The .dot class is now a no-op. There is deliberately no exception for tables: dropping the frame there needed two conditions, and the second (label alone in the cell) would make the same column render differently for a record with one tag than for one with two. AD 5 Sep 2026: the two-family tone model was dropped; red is the one reserved word. Leading icon from the whole Tabler set (owner 27 Sep 2026, acrm !4004): `TablerIcon` lazy-fetches `/tabler/<name>.svg`, caches it, restrokes to 1.75 and wraps it in `.ti` — same no-dot rule, DS `<Icon>` allowlist unchanged, app-level escape hatch for AI-picked meeting-topic glyphs only. \"Section tags\" composition (acrm !4013): removable `.acrm-pill` row with no frame + a quiet section action opening a `Popover` with one `Input` to add — used by meeting Minutes \"Probraná témata\"; a framed tag input stays a form-only control. Pill wave acrm !4079 (owner-approved 28 Sep 2026, variant A): ~20 hand-made \"pills\" with tinted backgrounds (20–24 px, 10–12 px type) replaced by ONE shape — `.acrm-pill` sm, 20 px, 12/500, outline + tone dot, no tinted fill. Rule: a CATEGORY (role, owner/share, segment) = `.acrm-pill` with a tone dot; a STATE (active/inactive, free/busy, call state, meeting state, prediction, import match, user status) = status chip (`.acrm-pill sm` + `data-status`); no new pill variant. Busy room = amber, never red (red is reserved for errors). Room equipment is NOT a pill: quiet text with a 14 px DS glyph per item (map apps/web/src/lib/room-equipment.ts, unknown item = text only), no dots between items (the icon separates), --fg-muted. Kept aside: `.grade` (credit grade) and `.pdr-pill`. The same MR fixed meeting status always showing grey \"done\". Leading icon carries the tone (owner 8 Oct 2026, acrm !4915, AD FA258-re no. 5): a pill with a DIRECT leading icon child has no dot (`:has(> .ti)`, not `:has(.ti)` — the remove cross `.x .ti` is a grandchild and must not take the dot away) and the icon is coloured by the tone instead: `.acrm-pill > .ti { color: var(--pill-dot, var(--ic-grey)) }`. General rule for every pill with a leading icon, not a special case of one component; first consumer is Project label.","source":"app-css","react":["TagPills","StatusChip","ContactStatusChip"],"classes":[".acrm-pill",".acrm-pill.sm",".acrm-pill::before",".acrm-pill .x",".acrm-pill .ti",".acrm-pill > .ti"],"files":["apps/web/src/ds.css","apps/web/src/components/TagPills.tsx","apps/web/src/components/StatusChip.tsx","apps/web/src/components/TablerIcon.tsx"],"css":["apps/web/src/ds.css"],"stories":{"Default":["components--pill--default"],"Variants":["components--pill--variants"],"Sizes":["components--pill--sizes"],"States":["components--pill--states"],"With icon & kbd":["components--pill--with-icon-and-kbd"],"Composition":["components--pill--composition"]},"legacy":["pills-status.html","colors-pills.html"],"related":["count-badge","project-label","deal-card"],"docs":"docs/status/pill","url":"http://192.168.230.131:3777/ds/components/status/pill","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Status & health","card":"pills-status.html","react":[],"classes":[".acrm-pill"],"tokens":[],"status":"OK","note":"CSS-only kánon (tóny + stavové pilly)"}}},{"id":"project-label","name":"Project label","summary":"Pill that names the project a piece of communication belongs to: the canonical `.acrm-pill sm` with the project’s own icon, coloured by the project’s tone (the icon carries the tone instead of the dot).","status":"canon","shown":"canon","approvedAt":"2026-10-09","notes":"Owner-approved prototype proto/komunikace-karta@649b8eca2 (8 Oct 2026, variant A; docs/ZADANI-komunikace-karta.md R8/R13/R14), implemented in the K-4 MR of acrm/acrm. Not a new pill variant and no CSS of its own (AD FA258-re): it is `.acrm-pill sm` + a leading `<Icon>` + the project name, and the general rule `.acrm-pill > .ti { color: var(--pill-dot) }` (see Pill) colours the icon. Icon and colour are set on the project detail with the same picker as a segment (`SegmentIconPicker`, `noun=\"projektu\"`); default when unset = `briefcase` + `grey`. Tone from the palette = tone class on the pill, own colour (`#rrggbb`) goes into `--pill-dot` directly. An AI-suggested project (not yet confirmed by a person) shows a `?` after the name. Always placed in the `tags` slot of Item list. Paths verified against acrm/acrm main after K-4 (acrm !4953): ProjectPill.tsx and the rule in ds.css; no project-pill.css exists. AD 11 Oct 2026: beta until checked on dev with data (company card Komunikace had no data). AD 12 Oct 2026: promoted to canon — verified on crm.dev.atsl.cz with data (e2e round 5, Chromium 1440 + 390): project with `rocket` + `purple` assigned to a manual entry; project detail › Komunikace shows the picker and preview, icon rgb(142, 78, 198); company card › Komunikace shows `.acrm-pill.sm.purple > .ti` before the date, right edge 1341 px in every row, phone 390 on its own line, 0 console errors, 0× 5xx. Report: https://crm.dev.atsl.cz/reports/acrm/komunikace-karta-e2e/kolo-5/. Open: Ladle stories per section (DoD) still empty.","source":"app-css","react":["ProjectPill"],"classes":[".acrm-pill",".acrm-pill.sm",".acrm-pill > .ti"],"files":["apps/web/src/components/projects/ProjectPill.tsx","apps/web/src/ds.css"],"css":["apps/web/src/ds.css"],"stories":{"Default":[],"Variants":[],"Sizes":[],"States":[],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["pill","item-list","avatar"],"docs":"docs/status/project-label","url":"http://192.168.230.131:3777/ds/components/status/project-label","coverage":{"stories":false,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":false,"approved":true,"api":true},"covered":false,"implementation":{"acrm":null}},{"id":"count-badge","name":"Count badge","summary":"Outlined count next to a heading, tab or column; accent is the filled tone for a count that must be cleared.","status":"canon","shown":"canon","approvedAt":"2026-09-28","notes":"Unified the scoped .cnt copies (F246). A count of zero is not drawn — that is an empty state. AD 5 Sep 2026: the .alert variant was deleted (never called anywhere, and white on --critical is 3.91:1, below AA). section-block.css re-declares the geometry 1px wider than ds.css (min-width 18 vs 16) — latent drift. acrm !4026 (27 Sep 2026): the section header count in SectionBlock and RecordRail now IS the canonical CountBadge (`acrm-count cnt`); the geometry overrides `.sb-h .cnt` and `.rr-sec-h .cnt` were deleted (19×17 → 21×16, padding 6). acrm !4034 (27 Sep 2026, count wave): tab counts (`.acrm-tab`, TabStrip in packages/ui) are CountBadge too; the segment builder toggle count `.sgb-ctl` = NEUTRAL CountBadge (an accent pill would vanish on the toggle's accent-tint on-state); dead `.sgb-tab .count` / `.eml-count` removed in app and mirror; inert `cnt` class names removed (kept only on RecordRail for a test). Intentionally NOT CountBadge: group-heading counts `.tl-grp .cnt` (bare number) and the notification bell overlay.","source":"app-css","react":["CountBadge"],"classes":[".acrm-count",".acrm-count.accent"],"files":["apps/web/src/components/CountBadge.tsx","apps/web/src/ds.css"],"css":["apps/web/src/ds.css","apps/web/src/ds/section-block.css"],"stories":{"Default":["components--count-badge--default"],"Variants":["components--count-badge--variants"],"Sizes":[],"States":["components--count-badge--states"],"With icon & kbd":[],"Composition":["components--count-badge--composition"]},"legacy":["pills-status.html"],"related":["pill","section-block","sidebar-nav-item"],"docs":"docs/status/count-badge","url":"http://192.168.230.131:3777/ds/components/status/count-badge","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Status & health","card":"pills-status.html","react":[],"classes":[".acrm-pill"],"tokens":[],"status":"OK","note":"CSS-only kánon (tóny + stavové pilly)"}}},{"id":"status-banner","name":"Status banner","summary":"One sentence about the state of a page or a record, with an optional glyph, actions and dismiss; tones neutral, accent, positive, critical (no warning tone).","status":"canon","shown":"canon","approvedAt":"2026-10-06","notes":"Owner approved wave A on 4 Oct 2026 (acrm !4579) and wave B on 6 Oct 2026 (acrm !4794, prototype proto/status-banner-b@83b789cc6). Wave A replaced .resv*, .fin-gap-banner, .zav-bez-smlouvy, .imp-reserved, .sr-rep-banner. Wave B replaced the dialog and accounting boxes .acc-fail (4 copies), .acc-warn, .acc-inv-warn, .pay-item-detail__warn, .aichat-warn, .ppf-conflict-title, .tl-log-fail; added title (tone only on glyph + title, body --fg) and actionsPlacement=below (RULES §15.6). No warning tone (RULES §15). Out of scope: .acrm-imp-banner, .dg-strip, .deal-cta; import K ověření / Konflikty still on .imp-reserved CSS until the owner decides. Dev checks: 4 Oct Závazky critical 1:1 with real data; 6 Oct Nová analytika rejected save = critical compact in the dialog, 1440/390 light/dark, brown 0, old classes 0. Other wave-B states not reachable with dev data (verified on fixtures in !4794, 46/52 pairs 0 px). Registry repaired 17 Oct 2026 (review F5): GoogleConnectBanner, RelationshipStatusBanner, RepBanner live in apps/web (see files), not exported by @acrm/ui; dropped from react[].","source":"package","react":["StatusBanner"],"classes":[".acrm-statusbanner",".acrm-statusbanner.compact",".acrm-statusbanner.is-neutral",".acrm-statusbanner.is-accent",".acrm-statusbanner.is-positive",".acrm-statusbanner.is-critical",".acrm-statusbanner.has-title",".acrm-statusbanner.acts-below"],"files":["packages/ui/src/components/StatusBanner.tsx","apps/web/src/components/GoogleConnectBanner.tsx","apps/web/src/components/RelationshipStatusBanner.tsx","apps/web/src/components/sales-reports/RepBanner.tsx"],"css":["apps/web/src/ds/status-banner.css"],"stories":{"Default":["components--status-banner--default"],"Variants":["components--status-banner--variants"],"Sizes":["components--status-banner--sizes"],"States":["components--status-banner--states"],"With icon & kbd":[],"Composition":["components--status-banner--composition"]},"legacy":[],"related":["toast","empty-state","stat-tile","file-drop"],"docs":"docs/status/status-banner","url":"http://192.168.230.131:3777/ds/components/status/status-banner","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"ai-assistant","name":"AI assistant","category":"AI","summary":"Right-hand assistant panel with threads, prompts and tool runs.","url":"http://192.168.230.131:3777/ds/components/ai-assistant","coverage":100,"subcomponents":[{"id":"ai-assistant","name":"AI assistant","summary":"Squeezing side panel with thread list, prompt row, tool runs and result tables.","status":"canon","shown":"canon","approvedAt":"2026-09-29","notes":"⚠️ The panel stands on TWO sheets and needs both — loading one gives a half-styled panel (recorded 5 September 2026, corrected in the registry 9 September 2026). `ds/ai-chat.css` (835 lines) carries the thread content; `components/assistant/assistant.css` (352 lines) carries the shell: panel header (`.aichat-head`/`.aichat-title`), the confirmation dialog (`.aichat-confirm*`), the mail preview (`.aichat-mail*`), the typing indicator and the recovery notice — 27 selectors that exist nowhere else. In the app both are imported by `AssistantPanel.tsx`, not by `main.tsx`; the catalogue loads them in the same order. Across both sheets the component has 81 distinct `.aichat-*` selectors, so the list above is a skeleton, not a transcript. The tool trace is a shared view (`assistant/tool-trace.tsx`, `.aichat-tools`/`.aichat-tools-t`/`.aichat-run`/`.aichat-tool`) used by the assistant, the mail composer and the palette answer — moved there rather than copied, so do not re-implement it per host. Stories render it collapsed only. Family review: docs/REVIEW-ai-family.md. Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .aichat-slash, .aichat-mail. Registry repaired 17 Oct 2026 (review F4/F11): attached css AskAssistantField.css.","source":"app-css","react":["ChatUserMessage","EmptyStarters","ChatComposer","AssistantChat","ToolTrace","AssistantMenu"],"classes":[".aichat-panel",".aichat-head",".aichat-title",".aichat-bodywrap",".aichat-body",".aichat-thread",".aichat-user",".aichat-msg",".aichat-md",".aichat-tools",".aichat-tools-t",".aichat-run",".aichat-tool",".aichat-acts",".aichat-act",".aichat-table",".aichat-composer",".aichat-send",".aichat-cfoot",".aichat-empty",".aichat-mark",".aichat-prompt-row",".aichat-confirm",".aichat-typing",".aichat-fups",".aichat-fup",".aichat-fup-t"],"files":["apps/web/src/ds/ai-chat.css","apps/web/src/components/assistant/assistant.css","apps/web/src/components/assistant/AssistantChat.tsx","apps/web/src/components/assistant/message-view.tsx","apps/web/src/components/assistant/tool-trace.tsx","apps/web/src/components/assistant/AssistantMenu.tsx"],"css":["apps/web/src/ds/ai-chat.css","apps/web/src/components/assistant/assistant.css","apps/web/src/components/assistant/AskAssistantField.css"],"stories":{"Default":["components--ai-assistant--default"],"Variants":["components--ai-assistant--variants"],"Sizes":["components--ai-assistant--sizes"],"States":["components--ai-assistant--states"],"With icon & kbd":["components--ai-assistant--with-icon-and-kbd"],"Composition":["components--ai-assistant--composition"]},"legacy":["ai-assistant.html"],"related":["drawer-slot","entity-ref","discussion"],"docs":"docs/ai-assistant/ai-assistant","url":"http://192.168.230.131:3777/ds/components/ai-assistant/ai-assistant","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"discussion","name":"Discussion","category":"AI","summary":"Conversation on a record: the task Activity section with events, comment cards and a composer under the thread.","url":"http://192.168.230.131:3777/ds/components/discussion","coverage":100,"subcomponents":[{"id":"discussion","name":"Discussion","summary":"Activity section of a task: one-line system events, framed comment cards, composer under the thread, edit/delete own comment, participants line.","status":"canon","shown":"canon","approvedAt":"2026-10-01","notes":"Beta, awaiting the AD visual check before canon. Built as the task Activity section (Linear Issue-view pattern); the project Activity tab does not use it. Stories render the canonical markup because the component lives in apps/web. Open: @mention picker arrives with the BE phase; participants line is visual only in the FE phase. Canon 1. 10. 2026 (AD): stories Default · States · Composition (acrm !4346) compared with dev task activity (/ukol/c5777f09…, light) — heading, event row, single-frame composer, placeholder and Komentovat match 1:1; comment cards checked from stories (dev task has no comments). Open: @mention picker with the BE phase.","source":"app-css","react":["TaskActivitySection"],"classes":[".tdl-act",".tdl-feed",".tdl-ev",".tdl-cm",".tdl-composer"],"files":["apps/web/src/components/projects/TaskActivitySection.tsx"],"css":["apps/web/src/ds/task-detail.css"],"stories":{"Default":["components--discussion--default"],"Variants":[],"Sizes":[],"States":["components--discussion--states"],"With icon & kbd":[],"Composition":["components--discussion--composition"]},"legacy":["discussion.html"],"related":["ai-assistant","note-card","timeline"],"docs":"docs/discussion/discussion","url":"http://192.168.230.131:3777/ds/components/discussion/discussion","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":{"group":"Components","name":"Discussion (návrh)","card":"discussion.html","react":[],"classes":[],"tokens":[],"status":"NÁVRH","note":"návrh — neimplementováno"}}},{"id":"chat-thread","name":"Chat thread","summary":"The canonical message bubble: incoming/outgoing, attachments inside, meta (avatar, name, time, delivery state, actions) below. Used by chats and the e-mail conversation view.","status":"canon","shown":"beta","approvedAt":null,"notes":"Canon 17 Oct 2026 (owner decision): bubble from prototype proto/mail-konverzace@6355a0399 (.kvb-*) replaces the K7-4 chat bubble (accent-tint, meta inside). Incoming --line-100, outgoing solid --accent; --radius-xl with --radius-xs sender-side corner; padding --sp-3 --sp-5; attachments inside under the text; meta below; max 80% (phone 85%). Voice/video outgoing stays on --accent-tint (follow-up). History: K7-4 (acrm !4447), AD review 2 Oct 2026, sending/failed states (!4514), published = meta text only (13 Oct 2026). Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .cht-bubble, .cht-atts, .cht-att, .cht-who, .cht-link. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.","source":"package","react":["ChatThread","ChatBubble"],"classes":[".cht-thread",".cht-day",".cht-msg",".cht-msg-t",".cht-msg-m",".cht-st",".cht-read",".cht-fail"],"files":["packages/ui/src/components/ChatThread.tsx","apps/web/src/ds/chat-thread.css"],"css":["apps/web/src/ds/chat-thread.css"],"stories":{"Default":["components--chat-thread--default"],"Variants":["components--chat-thread--variants","components--chat-thread--long-text"],"Sizes":[],"States":["components--chat-thread--states","components--chat-thread--delivery-states","components--chat-thread--send-states"],"With icon & kbd":[],"Composition":["components--chat-thread--composition","components--chat-thread--with-attachments"]},"legacy":[],"related":["discussion","ai-assistant","voice-message"],"docs":"docs/discussion/chat-thread","url":"http://192.168.230.131:3777/ds/components/discussion/chat-thread","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":false,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"command-palette","name":"Command palette","category":"Overlays & dialogs","summary":"The single ⌘K surface: search, commands and page actions in one overlay, results on the canonical Item list.","url":"http://192.168.230.131:3777/ds/components/command-palette","coverage":100,"subcomponents":[{"id":"command-palette","name":"Command palette","summary":"Dialog shell (800 role) with a query row, a two-column body — results left, detail of the row under the cursor right — a status strip and an assistant footer. Full screen and two-step on phones.","status":"canon","shown":"canon","approvedAt":"2026-09-07","notes":"Approved by the product owner on 7 September 2026 as deployed on dev; the code is the source of truth. Built from the AD wireframe for E1 (:3777/preview/hledani-v2-palette.html), which global-search.css still cites in its header — that page is now marked superseded and the citation needs updating. Rows are `.il .il-sm .il-embedded .il-seamless`; the `.il-seamless` variant originated here and became canon (AD 3 September 2026, D55). Prefixes: @ people, # companies, : commands, ? assistant — `:` replaced `>` deliberately (`>` needs right-Alt on a Czech keyboard and is now plain text, palette-model.ts:345), so a `>` written anywhere is out of date. Since 8 September 2026 the token `.gsp-pre` is a blue pill (`--accent-tint` / `--accent-ink`) carrying the prefix glyph plus the label — `@` at · `#` hash · `:` command · `?` sparkles-2, mapped in `PREFIXES`/`MODE_ICON`; the icon takes no `size` (`svg.ti` is 1em, so 12px follows from `font: var(--small)`), and the left padding is one step smaller than the right because the Tabler drawing carries its own inset. The empty state's two actions centre with the sentence above them (ACRM-161). Stories are ported markup, not an import: the palette lives in apps/web, which packages/ui must not import, so `stories/command-palette.stories.tsx` rebuilds it 1:1 from the canonical classes — the same way Filter bar is catalogued. The catalog therefore also loads `ds/split-view.css` and `ds/global-search.css` (added to .ladle/components.tsx; without them the palette drew as a bare ItemList). The assistant answer pane (`.gsp2-ans`, `.gsp2-ans-body`) landed with !3117 (main d108262b9) and is catalogued as the fourth mode; its body reuses the assistant's own `.aichat-thread` / `.aichat-tools` / `.aichat-msg`, moved rather than redesigned, so streaming and error states belong to the AI assistant family, not here. Registry repaired 17 Oct 2026 (review F2): removed classes with no CSS definition and no TSX use on main: .gsp-cancel.","source":"app-css","react":["GlobalSearch"],"classes":[".gsp-q",".gsp-pre",".gsp-body",".gsp-sec",".gsp-more",".gsp-strip",".gsp-sk",".gsp-acts",".gsp-act",".gsp-foot",".gsp-foot-q",".gsp2",".gsp2-detail",".gsp2-head",".gsp2-name",".gsp2-det-ic",".gsp2-cmd-d",".gsp2-run",".gsp2-def",".gsp2-fact",".gsp2-acts-list",".gsp-mobile-detail",".gsp-back",".gsp-sec-trunc",".gsp2-ans",".gsp2-ans-body"],"files":["apps/web/src/components/GlobalSearch.tsx","apps/web/src/components/search/PaletteDetail.tsx","apps/web/src/components/search/PaletteActionCard.tsx","apps/web/src/components/search/RowIdentity.tsx","apps/web/src/components/search/AnswerPane.tsx","apps/web/src/components/search/palette-model.ts","apps/web/src/ds/global-search.css"],"css":["apps/web/src/ds/global-search.css","apps/web/src/ds/split-view.css"],"stories":{"Default":["components--command-palette--default"],"Variants":["components--command-palette--variants"],"Sizes":[],"States":["components--command-palette--states"],"With icon & kbd":["components--command-palette--with-icon-kbd"],"Composition":["components--command-palette--composition"]},"legacy":[],"related":["item-list","dialog","entity-reference"],"docs":"docs/command-palette/command-palette","url":"http://192.168.230.131:3777/ds/components/command-palette/command-palette","coverage":{"stories":true,"props":false,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}}]},{"id":"meeting-analysis","name":"Meeting analysis","category":"Records & data","summary":"Charts of the meeting analysis and coaching module.","url":"http://192.168.230.131:3777/ds/components/meeting-analysis","coverage":20,"subcomponents":[{"id":"conversation-timeline","name":"Conversation timeline","summary":"Moments, phases, who speaks when and the sentiment curve of one meeting on a shared minute axis.","status":"canon","shown":"canon","approvedAt":"2026-09-30","notes":"Owner-approved 29 Sep 2026 (docs/ZADANI-koucink.md, acrm !4201; FA215). Candidate until component + stories + usage/a11y are on main. Sentiment colours via semantic tokens --sentiment-pos / --sentiment-neg (AD 30 Sep). On main 30 Sep 2026 (acrm !4229, !4234, !4238; tokens !4225); docs from dev-be FA220.","source":"package","react":["ConversationTimeline"],"classes":[".ma-chart",".ma-mo",".ma-ph",".ma-lane",".ma-plot",".ma-ov",".ma-tip"],"files":["packages/ui/src/components/ConversationTimeline.tsx","packages/ui/src/lib/timeline-geometry.ts","apps/web/src/ds/meeting-analysis.css"],"css":["apps/web/src/ds/meeting-analysis.css"],"stories":{"Default":["components--conversation-timeline--default"],"Variants":[],"Sizes":[],"States":["components--conversation-timeline--states"],"With icon & kbd":[],"Composition":["components--conversation-timeline--composition"]},"legacy":[],"related":["section-block","stat-tile"],"docs":"docs/meeting-analysis/conversation-timeline","url":"http://192.168.230.131:3777/ds/components/meeting-analysis/conversation-timeline","coverage":{"stories":true,"props":true,"classes":true,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":true},"covered":true,"implementation":{"acrm":null}},{"id":"voice-trace","name":"Voice trace","summary":"The signed-in user's pitch and pace against their own normal band — private.","status":"candidate","shown":"candidate","approvedAt":null,"notes":"Owner-approved 29 Sep 2026 (docs/ZADANI-koucink.md, acrm !4201; FA215). Candidate until component + stories + usage/a11y are on main. Sentiment colours via semantic tokens --sentiment-pos / --sentiment-neg (AD 30 Sep). 30 Sep 2026 (AD): stays candidate on purpose — V2b „Zrcadlo hlasu“ (docs/ZADANI-koucink.md) is opt-in and waits for a legal opinion before it is built; not debt.","source":"app-css","react":[],"classes":[],"files":[],"css":[],"stories":{"Default":[],"Variants":[],"Sizes":[],"States":[],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["section-block","stat-tile"],"docs":"docs/meeting-analysis/voice-trace","url":"http://192.168.230.131:3777/ds/components/meeting-analysis/voice-trace","coverage":{"stories":false,"props":false,"classes":false,"usage":false,"a11y":false,"baseline":false,"approved":false,"api":false},"covered":false,"implementation":{"acrm":null}},{"id":"range-bar","name":"Range bar","summary":"Band indicator in a stat tile: recommended zone, ghost of the value N weeks ago, team median, current value dot.","status":"canon","shown":"canon","approvedAt":"2026-10-02","notes":"acrm !4412 + !4413 (Reporty › Koučink, owner approved 1. 10. 2026), verified on dev 2. 10. 2026 (1440 light/dark + 390). Colour = --goal-in / --goal-in-ink / --goal-in-subtle (vivid green, owner rejected faded --positive here) vs --ic-amber; motion only under prefers-reduced-motion: no-preference. App-level next to Spark; before canon: stories (States: in band / out / no goal / no data), usage + a11y, and a decision whether it moves to packages/ui. 2. 10. 2026: beta — usage/a11y written, states reviewed by AD on the preview (koucink-stavy.html). Canon 2. 10. 2026: stories + light/dark baselines merged in !4422, AD-verified in the catalogue. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.","source":"app-css","react":["RangeBar"],"classes":[],"files":["apps/web/src/components/sales-reports/charts/RangeBar.tsx"],"css":["apps/web/src/ds/coach-report.css"],"stories":{"Default":["components--range-bar--default"],"Variants":[],"Sizes":[],"States":["components--range-bar--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["stat-tile","meter"],"docs":"docs/meeting-analysis/range-bar","url":"http://192.168.230.131:3777/ds/components/meeting-analysis/range-bar","coverage":{"stories":true,"props":false,"classes":false,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":false},"covered":false,"implementation":{"acrm":null}},{"id":"weekly-bars","name":"Weekly bars","summary":"Weekly columns from zero against a recommended band (gradient); in band = --goal-in, out of band = --ic-amber; team line breaks on weeks without data.","status":"canon","shown":"canon","approvedAt":"2026-10-02","notes":"acrm !4412 + !4413 (Reporty › Koučink, owner approved 1. 10. 2026), verified on dev 2. 10. 2026 (1440 light/dark + 390). Colour = --goal-in / --goal-in-ink / --goal-in-subtle (vivid green, owner rejected faded --positive here) vs --ic-amber; motion only under prefers-reduced-motion: no-preference. App-level next to Spark; before canon: stories (States: in band / out / no goal / no data), usage + a11y, and a decision whether it moves to packages/ui. 2. 10. 2026: beta — usage/a11y written, states reviewed by AD on the preview (koucink-stavy.html). Canon 2. 10. 2026: stories + light/dark baselines merged in !4422, AD-verified in the catalogue. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.","source":"app-css","react":["WeeklyBars"],"classes":[],"files":["apps/web/src/components/sales-reports/charts/WeeklyBars.tsx"],"css":["apps/web/src/ds/coach-report.css"],"stories":{"Default":["components--weekly-bars--default"],"Variants":[],"Sizes":[],"States":["components--weekly-bars--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["stat-tile","meter"],"docs":"docs/meeting-analysis/weekly-bars","url":"http://192.168.230.131:3777/ds/components/meeting-analysis/weekly-bars","coverage":{"stories":true,"props":false,"classes":false,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":false},"covered":false,"implementation":{"acrm":null}},{"id":"coach-hero","name":"Coach hero","summary":"Report header „Jak na tom jsi“: one sentence, metric blocks with goal, improvement from → to, what to work on; with GoalRing for the monthly goal.","status":"canon","shown":"canon","approvedAt":"2026-10-02","notes":"acrm !4412 + !4413 (Reporty › Koučink, owner approved 1. 10. 2026), verified on dev 2. 10. 2026 (1440 light/dark + 390). Colour = --goal-in / --goal-in-ink / --goal-in-subtle (vivid green, owner rejected faded --positive here) vs --ic-amber; motion only under prefers-reduced-motion: no-preference. App-level next to Spark; before canon: stories (States: in band / out / no goal / no data), usage + a11y, and a decision whether it moves to packages/ui. 2. 10. 2026: beta — usage/a11y written, states reviewed by AD on the preview (koucink-stavy.html). Canon 2. 10. 2026: stories + light/dark baselines merged in !4422, AD-verified in the catalogue. Registry repaired 17 Oct 2026 (review F3): mapped existing Ladle stories.","source":"app-css","react":["CoachHero","GoalRing"],"classes":[],"files":["apps/web/src/components/sales-reports/CoachHero.tsx"],"css":["apps/web/src/ds/coach-report.css"],"stories":{"Default":["components--coach-hero--default"],"Variants":[],"Sizes":[],"States":["components--coach-hero--states"],"With icon & kbd":[],"Composition":[]},"legacy":[],"related":["stat-tile","meter"],"docs":"docs/meeting-analysis/coach-hero","url":"http://192.168.230.131:3777/ds/components/meeting-analysis/coach-hero","coverage":{"stories":true,"props":false,"classes":false,"usage":true,"a11y":true,"baseline":true,"approved":true,"api":false},"covered":false,"implementation":{"acrm":null}}]}],"legacy":[{"path":"ai-assistant.html","group":"Components","name":"Components · AI assistant","title":"AI assistant","subtitle":"AI panel dokovaný VPRAVO (poslední flex dítě .body, zmenšuje obsah — žádný overlay; drawer se otevírá až za panelem, směrem dovnitř). Vlákno: dotaz = tichý blok · odpověď flat s formátovaným výstupem ","viewport":"1120x1500","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/ai-assistant.html","file":"http://192.168.230.131:3777/ds/ai-assistant.html"},{"path":"avatars.html","group":"Components","name":"Components · Avatars","title":"Avatars","subtitle":"Outline iniciálová značka — surface pozadí + barevný rámeček a ink, nikdy plná výplň. 3 velikosti (16/24/32) · kruh = osoba / čtverec = firma. Odstín z hashe jména.","viewport":"700x170","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/avatars.html","file":"http://192.168.230.131:3777/ds/avatars.html"},{"path":"buttons.html","group":"Components","name":"Components · Buttons","title":"Buttons","subtitle":"Tlačítka — primary · split · default · ghost · icon · muted + ⌘K kbd. Jeden accent jen pro primární akci, ostatní neutrální. KANONICKÝ ZDROJ elevace button-like prvků: každý orámovaný povrch nese --sh","viewport":"700x180","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/buttons.html","file":"http://192.168.230.131:3777/ds/buttons.html"},{"path":"deal-card.html","group":"Components","name":"Components · Deal card","title":"Deal card","subtitle":"Jednotná karta obchodu pro kanban i jinde — jedna kostra: název dealu + hodnota, provázané osoby a firmy (N:N) jako DS reference chipy, produkty a patička s tečkou zdraví (barva jen z termínu). Firma ","viewport":"1120x980","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/deal-card.html","file":"http://192.168.230.131:3777/ds/deal-card.html"},{"path":"deal-dialog.html","group":"Components","name":"Components · Dialog obchodu","title":"Dialog obchodu","subtitle":"NÁVRH — kanonický dialog nového obchodu na .acrm-dialog (React &lt;Dialog size=&quot;m&quot;&gt; z @acrm/ui, komponenta DealDialog): JEDEN dialog pro celou app místo dnešních TŘÍ implementací (NewComp","viewport":"960x3700","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/deal-dialog.html","file":"http://192.168.230.131:3777/ds/deal-dialog.html"},{"path":"dialog-window-states.html","group":"Components","name":"Components · Dialog — stavy okna","title":"Dialog — stavy okna","subtitle":"Modeless vrstva nad dialogovým pláštěm: TŘI STAVY VELIKOSTI — expanded (dnešek: scrim, aria-modal, Esc zavírá) · compact (380×460 kotvený vlevo dole, BEZ scrimu, Esc nezavírá) · min (lišta v doku vlev","viewport":"960x3320","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/dialog-window-states.html","file":"http://192.168.230.131:3777/ds/dialog-window-states.html"},{"path":"dialog.html","group":"Components","name":"Components · Dialog system","title":"Dialog system","subtitle":"KOMPLETNÍ dialogový systém na jedné stránce (.acrm-dialog). TŘI TŘÍDY — malý 400 · střední 640 · velký FLEXI (bez pevného rozměru, roste s oknem, strop 1200; &lt;Dialog size=&quot;s|m|l&quot;&gt;). DV","viewport":"960x5100","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/dialog.html","file":"http://192.168.230.131:3777/ds/dialog.html"},{"path":"discussion.html","group":"Components","name":"Components · Discussion (návrh)","title":"Discussion (návrh)","subtitle":"NÁVRH — vlákno diskuse (projekt, později kdekoliv): avatar autora (AI = gradient dlaždice + badge) · jméno · role · čas vpravo · víceřádkové tělo (pre-wrap) · delete na hover. Flat, hairline-free (§0)","viewport":"760x460","status":"draft","url":"http://192.168.230.131:3777/ds/legacy/discussion.html","file":"http://192.168.230.131:3777/ds/discussion.html"},{"path":"drawer-form.html","group":"Components","name":"Components · Drawer form","title":"Drawer form","subtitle":"Create-form v drawer slotu AppShellu (DrawerForm) — přebírá chrome RecordDraweru (.pdr): hlavička s dlaždicí ikony, skrolovatelné tělo s poli (DrawerField → .acrm-field), patka Zrušit + primár s ikono","viewport":"980x640","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/drawer-form.html","file":"http://192.168.230.131:3777/ds/drawer-form.html"},{"path":"email-list.html","group":"Components","name":"Components · Email list","title":"Email list","subtitle":"Mail klient (/posta + záložka E-maily) v anatomii Gmailu: kategorie taby → jednořádkové řádky (checkbox · hvězda · důležitost · odesílatel · předmět — snippet · přílohové chipy · datum). Nepřečtené = ","viewport":"1120x480","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/email-list.html","file":"http://192.168.230.131:3777/ds/email-list.html"},{"path":"empty-error-state.html","group":"Components","name":"Components · Empty & Error state","title":"Empty & Error state","subtitle":"Kanonická app implementace stavů: EmptyState (.acrm-empty · @acrm/ui) — plochá ikona, titulek, podtitulek, volitelná DS akce · ErrorState (.est · @acrm/ui) — kritická ikona u titulku, jedna věta, Zkus","viewport":"980x560","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/empty-error-state.html","file":"http://192.168.230.131:3777/ds/empty-error-state.html"},{"path":"entity-previews.html","group":"Components","name":"Components · Entity preview popover","title":"Entity preview popover","subtitle":"Jeden náhledový popover pro každý typ záznamu. Osoby/firmy nesou iniciálovou značku (kruh = osoba, čtverec = firma); typové objekty (schůzka / úkol / poznámka) plnou --ic dlaždici + bílý glyf. Sdílená","viewport":"960x720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/entity-previews.html","file":"http://192.168.230.131:3777/ds/entity-previews.html"},{"path":"entity-ref-mini.html","group":"Components","name":"Components · Entity reference (mini)","title":"Entity reference (mini)","subtitle":"Textová varianta entity reference pro husté seznamy a těsné buňky — bez značky/dlaždice, menší (12px), světlejší; tečkované podtržení zůstává jedinou afordancí. Typ je dán kontextem. Schůzky si nechaj","viewport":"880x760","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/entity-ref-mini.html","file":"http://192.168.230.131:3777/ds/entity-ref-mini.html"},{"path":"entity-ref-removable.html","group":"Components","name":"Components · Entity reference (odebíratelná)","title":"Entity reference (odebíratelná)","subtitle":"Reference jako položka seznamu/výběru — při najetí (nebo fokusu) se vpravo objeví křížek pro odebrání. Pro token-pole (lidé u úkolu, účastníci schůzky) i pro budování seznamu (portfolio / nabídka). Sa","viewport":"900x820","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/entity-ref-removable.html","file":"http://192.168.230.131:3777/ds/entity-ref-removable.html"},{"path":"entity-ref.html","group":"Components","name":"Components · Entity reference","title":"Entity reference","subtitle":"Inline křížový odkaz na entitu — kruh = osoba/uživatel, čtverec = firma (iniciály); plná --ic dlaždice + bílý glyf = deal / schůzka (s datem) / segment / úkol / soubor / produkt. Tečkované podtržení =","viewport":"860x720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/entity-ref.html","file":"http://192.168.230.131:3777/ds/entity-ref.html"},{"path":"filter-bar.html","group":"Components","name":"Filter bar","title":"Filter bar","subtitle":"Kanonický filtr tabulkových výpisů — lišta pod Section top barem: filtr chipy s hodnotou (accent tečka jen na chipu Filtr v top baru), „+ Filtr","viewport":"1120x920","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/filter-bar.html","file":"http://192.168.230.131:3777/ds/filter-bar.html"},{"path":"Inputs.html","group":"Components","name":"Components · Inputs","title":"Inputs","subtitle":"Kompletní sada vstupních prvků aplikace na jednom místě — posbíráno z reálných obrazovek (segment builder, import, nastavení, detaily). Textová pole (stavy default · fokus · vyplněno · disabled · chyb","viewport":"1180x1640","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Inputs.html","file":"http://192.168.230.131:3777/ds/Inputs.html"},{"path":"list-view.html","group":"Components","name":"Table listing","title":"Table listing","subtitle":"Kanonické složení tabulkového výpisu = skutečný DS.SegmentScreen (contentOnly): .sgb-top (identita + headerAction) → SavedChrome (jen segment) → SegmentTable → souhrnný řádek (.sgb-summary, prop summa","viewport":"1160x1520","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/list-view.html","file":"http://192.168.230.131:3777/ds/list-view.html"},{"path":"mail-compose.html","group":"Components","name":"Components · Mail compose (návrh)","title":"Mail compose (návrh)","subtitle":"Jeden vzor pro psaní i ČTENÍ e-mailu. Plášť UŽ NENÍ vlastní — obojí jede na kanonu &lt;Dialog size=&quot;l&quot;&gt; (flexi, na mobilu bottom sheet) s dokumentovým tělem `doc flush`. Hlavička je kanon","viewport":"1120x800","status":"draft","url":"http://192.168.230.131:3777/ds/legacy/mail-compose.html","file":"http://192.168.230.131:3777/ds/mail-compose.html"},{"path":"merge-dialog.html","group":"Components","name":"Components · Dialog sloučení","title":"Dialog sloučení","subtitle":"Kanonická slučovací / porovnávací tabulka (.mgt) v commit dialogu: řádek = pole, sloupec = záznam, poslední sloupec = živý náhled výsledku. STEJNĚ ŠIROKÉ obsahové sloupce (fixed layout: Pole 10.5rem, ","viewport":"1280x1210","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/merge-dialog.html","file":"http://192.168.230.131:3777/ds/merge-dialog.html"},{"path":"nav-item.html","group":"Components","name":"Components · Sidebar nav","title":"Sidebar nav","subtitle":"Levá navigace obou workspaců (Datamart & CRM) — horní řádky, foldable skupiny (CRM) i rozbalovací záznamové řádky (Datamart) s uloženými segmenty, Průvodce (wand), stavy active/hover/rest. Použij pro ","viewport":"820x500","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/nav-item.html","file":"http://192.168.230.131:3777/ds/nav-item.html"},{"path":"note-dialog.html","group":"Components","name":"Components · Dialog poznámky","title":"Dialog poznámky","subtitle":"NÁVRH — kanonický dialog poznámky na .acrm-dialog (React <Dialog> z @acrm/ui, komponenta NoteDialog): dokument = velký (800) + .tall, modální, dock ~11vh, autosave místo Uložit · inline NoteComposer s","viewport":"960x2720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/note-dialog.html","file":"http://192.168.230.131:3777/ds/note-dialog.html"},{"path":"pills-status.html","group":"Components","name":"Components · Status & health","title":"Status & health","subtitle":"Dot pills (stav dealu: Lead/Qualified/Proposal/Won/Lost) + health-score meter (Healthy/At risk/Critical). Desaturované sémantické barvy; odliš od soft attribute pills (kategorie).","viewport":"700x160","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/pills-status.html","file":"http://192.168.230.131:3777/ds/pills-status.html"},{"path":"popover.html","group":"Components","name":"Components · Popover & menu","title":"Popover & menu","subtitle":"Portálovaný, anchor-positioned overlay (.acrm-popover) — nikdy se neořízne v overflow. Anatomie menu: položky (ikona · název+popis · check) · separator · strong (návrh) + tag. PRAVIDLO: v drop-down me","viewport":"740x520","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/popover.html","file":"http://192.168.230.131:3777/ds/popover.html"},{"path":"Record detail rail.html","group":"Components","name":"Components · Record detail rail","title":"Record detail rail","subtitle":"Znovupoužitelný levý panel detailu záznamu s inline editací (vzor Attio) — sdílený napříč všemi typy (firma · osoba · obchod · projekt · schůzka). Přejetím myší se hodnota jemně podbarví, kliknutím se","viewport":"1000x820","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Record%20detail%20rail.html","file":"http://192.168.230.131:3777/ds/Record%20detail%20rail.html"},{"path":"Record list.html","group":"Components","name":"Record list","title":"Record list","subtitle":"Jeden výpisový vzor pro fronty, e-maily, aktivity a notifikace — lead (avatar/ikona) · název+podtitul · trailing (tag/čas/výsledek), stavy: vybráno / hotovo / ztlumeno.","viewport":"980x560","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Record%20list.html","file":"http://192.168.230.131:3777/ds/Record%20list.html"},{"path":"Record tabs (unified).html","group":"Components","name":"Components · Record tabs (unified)","title":"Record tabs (unified)","subtitle":"Věrný přenos reálné implementace Record tabs z běžící aplikace (origin/main) — reálný DOM + reálné CSS appky, nic vymyšleného. Přepínač typu: Obchod (9 tabů) · Osoba (10) · Firma (12) · Schůzka (3). K","viewport":"1180x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Record%20tabs%20(unified).html","file":"http://192.168.230.131:3777/ds/Record%20tabs%20(unified).html"},{"path":"Section block.html","group":"Components","name":"Components · Section block","title":"Section block","subtitle":"Kanonická sekční hlavička + tělo (AD ruling 19. 7. 2026) — jeden vzor pro všechny sekce: úroveň A (rail/sloupce, --h3 fg-secondary, volitelný caret collapse) a úroveň B (obsahové bloky detailů, --h2 i","viewport":"920x640","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Section%20block.html","file":"http://192.168.230.131:3777/ds/Section%20block.html"},{"path":"Section top bar.html","group":"Components","name":"Section top bar","title":"Section top bar","subtitle":"Horní lišta obrazovky — přepínač pipeline (nadpis-dropdown), zobrazení, řazení, filtr a jedna primární akce na 49px liště s vlasovou linkou. Jeden vzor pro pipeline, seznamy i detaily. Bez počtu (ani ","viewport":"1120x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Section%20top%20bar.html","file":"http://192.168.230.131:3777/ds/Section%20top%20bar.html"},{"path":"segmented.html","group":"Components","name":"Components · Segmented control","title":"Segmented control","subtitle":"Segmentový přepínač (.acrm-segmented / DS.Segmented) — jedna exkluzivní volba, 2–4 segmenty; aktivní nese .on + aria-pressed (bílý povrch + stín --shadow-xs). Kompaktní toolbar chip, volitelně s ikono","viewport":"700x220","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/segmented.html","file":"http://192.168.230.131:3777/ds/segmented.html"},{"path":"Stat tile.html","group":"Components","name":"Components · Stat tile","title":"Stat tile","subtitle":"Kanonická stat/KPI dlaždice (AD ruling 19. 7. 2026 — vzorem KPI scoreboard na dashboardu): hairline bez stínu, label --small + mono caption, hodnota --h1 tabular s tóny (reached/warn/crit/muted), voli","viewport":"920x640","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Stat%20tile.html","file":"http://192.168.230.131:3777/ds/Stat%20tile.html"},{"path":"table-row.html","group":"Components","name":"Components · Table","title":"Table","subtitle":"Skutečný .sgb-table engine — ukotvené záhlaví, zamrzlý identity sloupec + scroll-stín, select-all, řazení sloupců a sloupcové ⋮ menu (řadit · přesunout · přejmenovat · skrýt · přidat). Použij pro KAŽD","viewport":"920x560","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/table-row.html","file":"http://192.168.230.131:3777/ds/table-row.html"},{"path":"tabs.html","group":"Components","name":"Components · Tabs (record sub-nav)","title":"Tabs (record sub-nav)","subtitle":"JEDEN underline tab strip pro record sub-nav (.acrm-tabs, ruling: taby ne chipy) — 46px řádek, ikona · label · count pill, aktivní accent podtržení; při přetečení edge-fade + šipky (scroll po 60 % šíř","viewport":"760x190","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/tabs.html","file":"http://192.168.230.131:3777/ds/tabs.html"},{"path":"Task list.html","group":"Components","name":"Task list","title":"Task list","subtitle":"JEDEN výpis úkolů pro všechny detaily a drawery (DS.TaskList) — obchod, projekt, osoba i schůzka sdílí tentýž vzor, liší se jen šířkou: úzké (drawer, avatar) · široké (detail, jméno jako entity reference) · plné (přehled /tasks — edge-to-edge, jeden slot Provázané: obchod + kontakty za sebou, tiché sticky záhlaví sloupců, pod 1101 px se sklopí do širokého). Jedna řádková anatomie: hairline řádky · kulatý checkbox · text úkolu + počty · termín · řešitel; hotové úkoly se automaticky řadí na konec; strom podúkolů, skupinové lišty s progress barem. Akce AI návrhů jsou overlay přes pravý okraj řádku — prvky řádku se neskrývají; stavy načítání / chyba / prázdno.","viewport":"1440x1560","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Task%20list.html","file":"http://192.168.230.131:3777/ds/Task%20list.html"},{"path":"task-dialog.html","group":"Components","name":"Components · Dialog úkolu","title":"Dialog úkolu","subtitle":"NÁVRH — kanonický dialog úkolu na .acrm-dialog (React <Dialog size=&quot;m&quot;> z @acrm/ui, komponenta TaskDialog): JEDEN dialog pro celou app, žádný edit mód — otevřený úkol je rovnou editovatelný ","viewport":"960x3400","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/task-dialog.html","file":"http://192.168.230.131:3777/ds/task-dialog.html"},{"path":"timeline.html","group":"Components","name":"Components · Časová osa záznamu","title":"Časová osa záznamu","subtitle":"KANON. Sjednocená osa aktivit na kartě klienta, postavená na kanonickém ItemListu. Chronologii nese SVISLÁ OSA vlevo, která prochází za lead glyfy; vodorovná linka je jediná — horní hrana hlavičky sek","viewport":"1180x1400","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/timeline.html","file":"http://192.168.230.131:3777/ds/timeline.html"},{"path":"bonita.html","group":"Foundations","name":"Colors · Bonita rating","title":"Colors · Bonita rating","subtitle":"Výplně bonitního ratingu — syté + WCAG-AA ink. Odstup 4.5:1 se počítá, ne odhaduje. Výborná/Dobrá/Průměrná/Riziková/Bez dat.","viewport":"700x180","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/bonita.html","file":"http://192.168.230.131:3777/ds/bonita.html"},{"path":"colors-accent.html","group":"Foundations","name":"Colors · Functional blue","title":"Colors · Functional blue","subtitle":"Jediná modrá — znamená stav (fokus, výběr) a jednu primární akci. Tlačítka jsou jinak monochromatická. Používej střídmě.","viewport":"700x200","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/colors-accent.html","file":"http://192.168.230.131:3777/ds/colors-accent.html"},{"path":"colors-neutrals.html","group":"Foundations","name":"Colors · Neutrals & surfaces","title":"Colors · Neutrals & surfaces","subtitle":"Chladně laděná škála — ink → hairline (line) → surface. Základ pro text, linky a plochy.","viewport":"700x170","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/colors-neutrals.html","file":"http://192.168.230.131:3777/ds/colors-neutrals.html"},{"path":"colors-pills.html","group":"Foundations","name":"Colors · Attribute pills","title":"Colors · Attribute pills","subtitle":"Nízko-chroma kategorie (7 odstínů) — tónuje kategorii, nikdy stav. JEDNA sdílená komponenta .pill v _ds/pills.css: tóny lime…grey na tokenech --pill-*, velikosti výchozí (22 px) a .sm (20 px), volitel","viewport":"700x240","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/colors-pills.html","file":"http://192.168.230.131:3777/ds/colors-pills.html"},{"path":"colors-status.html","group":"Foundations","name":"Colors · Status","title":"Colors · Status","subtitle":"Desaturované sémantické páry — plná barva + subtle podklad (positive · warning · critical · info). Použij pro stavy dealů, health a hlášky.","viewport":"700x180","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/colors-status.html","file":"http://192.168.230.131:3777/ds/colors-status.html"},{"path":"dark-mode.html","group":"Foundations","name":"Colors · Dark mode","title":"Colors · Dark mode","subtitle":"Dark téma — surfaces, accent a živý UI vzorek. Přepíná se přes [data-theme=dark].","viewport":"700x190","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/dark-mode.html","file":"http://192.168.230.131:3777/ds/dark-mode.html"},{"path":"dates.html","group":"Foundations","name":"Datum","title":"Datum","subtitle":"Rok se píše jen tak přesně, jak je potřeba — „26. 8.","viewport":"860x420","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/dates.html","file":"http://192.168.230.131:3777/ds/dates.html"},{"path":"density.html","group":"Foundations","name":"Spacing · Density","title":"Spacing · Density","subtitle":"Výšky řádků a rozestupy pro datovou appku — --topbar-h 49 · --row-h 37 · --row-h-nav 28 · --sidebar-w 261.","viewport":"700x210","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/density.html","file":"http://192.168.230.131:3777/ds/density.html"},{"path":"entity-tiles.html","group":"Foundations","name":"Colors · Entity icon tiles","title":"Colors · Entity icon tiles","subtitle":"Sytá plná dlaždice + bílý glyf — jeden vyhrazený odstín (--ic-*) na typ záznamu (Lidé, Firmy, Deals, …). Použij pro typové ikony záznamů; odliš od soft attribute pills.","viewport":"700x180","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/entity-tiles.html","file":"http://192.168.230.131:3777/ds/entity-tiles.html"},{"path":"icon-sizes.html","group":"Foundations","name":"Iconography · Sizes","title":"Iconography · Sizes","subtitle":"Tabler line ikony — 12 / 14 / 16 / 18 / 20, stroke 1.5px. Default 16px (--ico-sm).","viewport":"700x150","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/icon-sizes.html","file":"http://192.168.230.131:3777/ds/icon-sizes.html"},{"path":"iconography.html","group":"Foundations","name":"Brand · Iconography (Tabler)","title":"Brand · Iconography (Tabler)","subtitle":"Tabler line ikony — produktová sada, stroke 1.75px, 16–18px, currentColor.","viewport":"700x150","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/iconography.html","file":"http://192.168.230.131:3777/ds/iconography.html"},{"path":"layout-containment.html","group":"Foundations","name":"Layout · Containment (DO / DON'T)","title":"Layout · Containment (DO / DON'T)","subtitle":"Max 1 úroveň rámování. Seskupuj prostorem + hierarchií, ne krabičkami. Ikona je ikona, ne dlaždice. RULES.md §0.","viewport":"760x420","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/layout-containment.html","file":"http://192.168.230.131:3777/ds/layout-containment.html"},{"path":"logo.html","group":"Foundations","name":"Brand · Logo slot & avatars","title":"Brand · Logo slot & avatars","subtitle":"Slot na logo (čeká na reálnou značku) + dlaždice POUZE jako logo celého systému — nikde jinde v UI se nepoužívají. Kulaté varianty neexistují.","viewport":"700x150","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/logo.html","file":"http://192.168.230.131:3777/ds/logo.html"},{"path":"radii.html","group":"Foundations","name":"Spacing · Radii","title":"Spacing · Radii","subtitle":"Rohový jazyk — od checkboxu (nejmenší) po avatar/dot (full). Škála --radius-xs…pill.","viewport":"700x160","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/radii.html","file":"http://192.168.230.131:3777/ds/radii.html"},{"path":"shadows.html","group":"Foundations","name":"Spacing · Elevation","title":"Spacing · Elevation","subtitle":"Zdrženlivá elevace — stíny s nízkou opacitou. xs tlačítka a inputy · sm hover lift a knoby · md plovoucí panely · pop menu a dialogy.","viewport":"700x160","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/shadows.html","file":"http://192.168.230.131:3777/ds/shadows.html"},{"path":"spacing.html","group":"Foundations","name":"Spacing · Scale","title":"Spacing · Scale","subtitle":"Rytmus panelů — 2 · 4 · 6 · 8 · 12 · 16 · 24 · 40 (--sp-0…7). Nikdy raw px; --sp-4 (12px) je hlavní panel gutter.","viewport":"700x280","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/spacing.html","file":"http://192.168.230.131:3777/ds/spacing.html"},{"path":"type-body-mono.html","group":"Foundations","name":"Type · Body & Data","title":"Type · Body & Data","subtitle":"Inter body 13px, Inter tabular-nums pro data (částky, kódy, data, %), overline. Workhorse pro pole záznamů a hustý text.","viewport":"700x230","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/type-body-mono.html","file":"http://192.168.230.131:3777/ds/type-body-mono.html"},{"path":"type-display.html","group":"Foundations","name":"Type · Display (Manrope)","title":"Type · Display (Manrope)","subtitle":"Hustá produktová škála — 16 / 15 / 13 + section; nad --h1 jen --kpi 23 pro KPI číslice. Hierarchie vedená vahou a barvou, ne velikostí. Manrope pro display/labels, Inter pro section.","viewport":"700x340","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/type-display.html","file":"http://192.168.230.131:3777/ds/type-display.html"},{"path":"type-weights.html","group":"Foundations","name":"Type · Weights","title":"Type · Weights","subtitle":"ROZHODNUTO 6.7.26: škála vah je 400 body · 500 cell/label · 600 semibold (názvy řádků, aktivní stavy, headingy, native bold). Váhy nad 600 (700, 800) se NEPOUŽÍVAJÍ — všude přemapovány na 600 (vč. typ","viewport":"700x300","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/type-weights.html","file":"http://192.168.230.131:3777/ds/type-weights.html"},{"path":"auth-google.html","group":"Registrace","name":"Registrace · Propojení Google","title":"Propojení Google","subtitle":"JÁDRO — samostatný OAuth (incremental). Per-zdroj E-maily/Kontakty/Komunikace/Dokumenty + „proč“ + trust (jen ty vidíš obsah, GDPR/ISO). Skippable.","viewport":"1200x760","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-google.html","file":"http://192.168.230.131:3777/ds/auth-google.html"},{"path":"auth-hotovo.html","group":"Registrace","name":"Registrace · Hotovo","title":"Hotovo","subtitle":"Přistání po onboardingu — potvrzení propojených zdrojů, vstup do CRM. (Skipnuté propojení se vrací jako banner v Lidé/Firmy + Nastavení.)","viewport":"1040x720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-hotovo.html","file":"http://192.168.230.131:3777/ds/auth-hotovo.html"},{"path":"auth-mobil.html","group":"Registrace","name":"Registrace · Mobil","title":"Mobil","subtitle":"Onboarding na telefonu (390 px) — dvousloupcová karta se sbalí do jednoho sloupce, dekorativní panel mizí, akce jsou palcové. Breakpointy 720 / 560.","viewport":"1300x980","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-mobil.html","file":"http://192.168.230.131:3777/ds/auth-mobil.html"},{"path":"auth-odemknout.html","group":"Registrace","name":"Registrace · Odemčení asistenta","title":"Odemčení asistenta","subtitle":"Veřejná jednoúčelová stránka /asistent/odemknout — uživatel na ni přijde z tlačítka v Telegramu a zadává heslo asistenta. Rodina au-* (žádný AppShell, žádná navigace, žádný recovery flow). Pět stavů: ","viewport":"1120x1720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-odemknout.html","file":"http://192.168.230.131:3777/ds/auth-odemknout.html"},{"path":"auth-otp.html","group":"Registrace","name":"Registrace · Ověření kódem","title":"Ověření kódem","subtitle":"6místný OTP kód (ne magic link) — auto-submit, paste, změnit e-mail, resend s odpočtem. Stejné pro login i registraci.","viewport":"1040x720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-otp.html","file":"http://192.168.230.131:3777/ds/auth-otp.html"},{"path":"auth-profil.html","group":"Registrace","name":"Registrace · Profil","title":"Profil","subtitle":"Minimální, volitelný krok — jméno (předvyplněné) + foto, e-mail read-only. Roli řídí administrátor. Lze přeskočit.","viewport":"1040x740","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-profil.html","file":"http://192.168.230.131:3777/ds/auth-profil.html"},{"path":"auth-vstup.html","group":"Registrace","name":"Registrace · Vstup","title":"Vstup","subtitle":"Jedna brána pro login i registraci — Google identita nebo pracovní e-mail (→ OTP). Bez hesla, bez forku sign-up/log-in.","viewport":"1040x720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-vstup.html","file":"http://192.168.230.131:3777/ds/auth-vstup.html"},{"path":"auth-whitelist.html","group":"Registrace","name":"Registrace · Mimo whitelist","title":"Mimo whitelist","subtitle":"Stav — přístup gated povolenou doménou (admin). Doména mimo seznam → požádat správce o přístup, zpět na přihlášení.","viewport":"1040x720","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/auth-whitelist.html","file":"http://192.168.230.131:3777/ds/auth-whitelist.html"},{"path":"Aktivity.html","group":"Screens","name":"Aktivity / schůzky","title":"Aktivity / schůzky","subtitle":"Dvoupanelová aktivita — vlevo timeline (schůzky, hovory, e-maily, poznámky; filtr dle typu), vpravo detail aktivity. Hlavička s outcome pills (výsledek, posun pipeline, navazující krok), pak řetězec A","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Aktivity.html","file":"http://192.168.230.131:3777/ds/Aktivity.html"},{"path":"ClenTymu.html","group":"Screens","name":"Detail člena týmu (práce)","title":"Detail člena týmu (práce)","subtitle":"Manažerský detail podřízeného — pracovní čas dne odvozený z aktivity (klikání): aktivní bloky vs přestávky (≥10 min bez akce = přerušení), relace práce od–do, denní/týdenní souhrn a feed akcí. Dostupn","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/ClenTymu.html","file":"http://192.168.230.131:3777/ds/ClenTymu.html"},{"path":"Company detail (CRM).html","group":"Screens","name":"Company detail (CRM)","title":"Company detail (CRM)","subtitle":"Detail firmy v CRM — Attio-style record page přes App Shell, 1:1 vzor person: levý rail (identita · akce · firmografika · seznamy) + pravá oblast se záložkami (Souhrn · Firmografika · Lidé · Obchody ·","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Company%20detail%20(CRM).html","file":"http://192.168.230.131:3777/ds/Company%20detail%20(CRM).html"},{"path":"Company Drawer.html","group":"Screens","name":"Company drawer","title":"Company drawer","subtitle":"Firmy table with the live company record drawer open — kontakt, lidé, bonita, růst, vlastnická struktura","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Company%20Drawer.html","file":"http://192.168.230.131:3777/ds/Company%20Drawer.html"},{"path":"Dashboard (CRM).html","group":"Screens","name":"Dashboard (CRM)","title":"Dashboard (CRM)","subtitle":"Home v Attio stylu — greeting (--h1), velké AI pole (zachováno, přerámováno na CRM asistenta) + 2 vycentrované chipy, pak holé sekce Schůzky (datum · ‹ › · ⋮) a Úkoly (Zobrazit vše · +). Ploché řádky:","viewport":"1440x980","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Dashboard%20(CRM).html","file":"http://192.168.230.131:3777/ds/Dashboard%20(CRM).html"},{"path":"Deal detail (CRM).html","group":"Screens","name":"Deal detail (CRM)","title":"Deal detail (CRM)","subtitle":"Detail obchodu (deal) — record page přes App Shell, vzor Company/Person detail: střízlivý top strip (identita · hodnota · akce, bez pilulek dle AD redukce), levý rail „Detail obchodu","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Deal%20detail%20(CRM).html","file":"http://192.168.230.131:3777/ds/Deal%20detail%20(CRM).html"},{"path":"Deal Drawer.html","group":"Screens","name":"Deal drawer (úkoly)","title":"Deal drawer (úkoly)","subtitle":"Pipeline board s otevřeným RecordDrawerem na dealu — detail obchodu + sekce Úkoly (sdílená DS.TaskList: úkoly, podúkoly, řešitelé, termíny, progres)","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Deal%20Drawer.html","file":"http://192.168.230.131:3777/ds/Deal%20Drawer.html"},{"path":"Dialer.html","group":"Screens","name":"Dialer","title":"Dialer","subtitle":"Volací workspace — vlevo fronta k volání (kontakt, firma, telefon, segment, „Volat teď","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Dialer.html","file":"http://192.168.230.131:3777/ds/Dialer.html"},{"path":"Empty states.html","group":"Screens","name":"Prázdné stavy","title":"Prázdné stavy","subtitle":"Sada prázdných stavů podle DS — prázdná pipeline / sloupec (jen „+ Nový obchod“), detail obchodu bez úkolů, žádné výsledky filtru; ikony bez pozadí, přes sdílenou DS.EmptyState","viewport":"1180x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Empty%20states.html","file":"http://192.168.230.131:3777/ds/Empty%20states.html"},{"path":"Error states.html","group":"Screens","name":"Chybové stavy","title":"Chybové stavy","subtitle":"Pravidlo selhání načtení — DS.ErrorState: critical ikona u nadpisu (bez pozadí), jedna akce (Zkusit znovu). Sdílené komponenty řídí přes prop error + onRetry; QA flag ?skerr.","viewport":"1180x760","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Error%20states.html","file":"http://192.168.230.131:3777/ds/Error%20states.html"},{"path":"Firmy.html","group":"Screens","name":"Firmy (segment table)","title":"Firmy (segment table)","subtitle":"Saved company segment — the SAME shared SegmentTable as Lidé, fed company columns + data (square avatars, IČO/obrat/web)","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Firmy.html","file":"http://192.168.230.131:3777/ds/Firmy.html"},{"path":"Home.html","group":"Screens","name":"Domů (dashboard)","title":"Domů (dashboard)","subtitle":"Home — greeting, AI segment composer, saved segments table, dataset gallery","viewport":"1440x980","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Home.html","file":"http://192.168.230.131:3777/ds/Home.html"},{"path":"Import.html","group":"Screens","name":"Import dat (CSV)","title":"Import dat (CSV)","subtitle":"Průvodce importem vlastních dat (BYO) — krok Nahrát (volba Lidé/Firmy + dropzone, detekce oddělovače/kódování), Mapování sloupců CSV → pole CRM (auto-match, náhled), Kontrola (validace: chyby/duplicit","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Import.html","file":"http://192.168.230.131:3777/ds/Import.html"},{"path":"Kalendar.html","group":"Screens","name":"Kalendář","title":"Kalendář","subtitle":"Týmový kalendář schůzek a úkolů — měsíční mřížka (dnes zvýrazněno, události jako chipy obarvené podle osoby), vpravo přepínatelný seznam Kalendáře (můj + kolegové, barva + checkbox) pro překryv kalend","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Kalendar.html","file":"http://192.168.230.131:3777/ds/Kalendar.html"},{"path":"Lide.html","group":"Screens","name":"Lidé (segment table)","title":"Lidé (segment table)","subtitle":"Saved people segment on the shared SegmentTable — sticky header + frozen Jméno column, column kebab menu, row select, sticky CTA","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Lide.html","file":"http://192.168.230.131:3777/ds/Lide.html"},{"path":"Loading (skeleton).html","group":"Screens","name":"Loading (skeleton)","title":"Loading (skeleton)","subtitle":"Pravidlo načítání — DS.Skeleton: každá plocha (board, tabulka, drawer, úkoly, karty) má skeleton se shodným layoutem (zero layout shift). Sdílené komponenty řídí loading přes prop.","viewport":"1180x1260","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Loading%20(skeleton).html","file":"http://192.168.230.131:3777/ds/Loading%20(skeleton).html"},{"path":"Meeting detail (CRM).html","group":"Screens","name":"Meeting detail (CRM)","title":"Meeting detail (CRM)","subtitle":"Detail schůzky v CRM přes App Shell: záhlaví s názvem a termínem, vlevo užší read-only sloupec s náležitostmi (účastníci · projekt · termín · typ) přes entity reference, vpravo záložky pro zpracování ","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Meeting%20detail%20(CRM).html","file":"http://192.168.230.131:3777/ds/Meeting%20detail%20(CRM).html"},{"path":"Nastaveni.html","group":"Screens","name":"Nastavení","title":"Nastavení","subtitle":"Nastavení dosažitelné z account menu — Profil · Tým (členové, role, pozvánky, whitelist domén) · Integrace (Google). Ploché řádky dle containment budget, DS field/avatar/pill/button, sentence-case.","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Nastaveni.html","file":"http://192.168.230.131:3777/ds/Nastaveni.html"},{"path":"Notifikace (zvonek).html","group":"Screens","name":"Notifikace (zvonek)","title":"Notifikace (zvonek)","subtitle":"Trvalý inbox v horní liště — DS.NotifBell + DS.NotifPanel. Přiřazení, naplánované události, dokončené async akce, aktivita týmu, systém. Nepřečtené (badge/tečka), skupiny Nové/Dříve, Označit vše. Dopl","viewport":"1120x1200","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Notifikace%20(zvonek).html","file":"http://192.168.230.131:3777/ds/Notifikace%20(zvonek).html"},{"path":"Notifikace a toasty.html","group":"Screens","name":"Notifikace a toasty","title":"Notifikace a toasty","subtitle":"Systém potvrzení akcí — DS.toast (success/info/warning/error/loading), bottom-center, undo/zobrazit/retry; anatomie, typy, živá ukázka a pravidla kdy/co. Autosave = tichý indikátor, ne toast.","viewport":"1100x1240","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Notifikace%20a%20toasty.html","file":"http://192.168.230.131:3777/ds/Notifikace%20a%20toasty.html"},{"path":"Person detail - migrated (ukázka).html","group":"Screens","name":"Person detail — migrated (ukázka)","title":"Person detail — migrated (ukázka)","subtitle":"Referenční migrace jednoho record detailu (osoba) na sdílený DS.RecordTabs. Levý identity rail + pravý sloupec poháněný modulem record-tabs.js — obrazovka jen deklaruje record = {ctx, tabs, data}, pan","viewport":"1240x860","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Person%20detail%20-%20migrated%20(uk%C3%A1zka).html","file":"http://192.168.230.131:3777/ds/Person%20detail%20-%20migrated%20(uk%C3%A1zka).html"},{"path":"Person detail (CRM).html","group":"Screens","name":"Person detail (CRM)","title":"Person detail (CRM)","subtitle":"Detail osoby v CRM — Attio-style record page přes App Shell: levý rail (identita · akce · detail záznamu · seznamy) + pravá oblast se záložkami (Souhrn · Aktivita · E-maily). Mapováno 1:1 z reference,","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Person%20detail%20(CRM).html","file":"http://192.168.230.131:3777/ds/Person%20detail%20(CRM).html"},{"path":"Person Drawer.html","group":"Screens","name":"Person drawer","title":"Person drawer","subtitle":"Lidé table with the universal RecordDrawer open on a person — parallel to the company drawer, one shared component","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Person%20Drawer.html","file":"http://192.168.230.131:3777/ds/Person%20Drawer.html"},{"path":"Pipeline.html","group":"Screens","name":"Pipeline (kanban)","title":"Pipeline (kanban)","subtitle":"Sjednocená pipeline s přepínačem více pipeline — heading „Obecná pipeline ▾“ otevře výběr (ikona·název·počet, aktivní zaškrtnutá) + „Nová pipeline“. Bílé plátno + šedé lajny, sloučená lišta, DS avatar","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Pipeline.html","file":"http://192.168.230.131:3777/ds/Pipeline.html"},{"path":"Pruvodce firmy.html","group":"Screens","name":"Průvodce segmentem — Firmy","title":"Průvodce segmentem — Firmy","subtitle":"Same builder engine as Lidé, fed the company config — all 12 filter tabs with full content (Sídlo · Firmografie · Obor · Bonita · Finance · Růst · Vlastníci · Rizika · Kontakt · Atributy · Tagy · Full","viewport":"1440x980","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Pruvodce%20firmy.html","file":"http://192.168.230.131:3777/ds/Pruvodce%20firmy.html"},{"path":"Pruvodce.html","group":"Screens","name":"Průvodce segmentem — Lidé","title":"Průvodce segmentem — Lidé","subtitle":"Build mode of the shared .sgb surface — all 10 filter tabs with full content (Lokalita · Demografie · Bonita · Práce · Investice · Majetek · Komunikace · Atributy · Tagy · Fulltext), address typeahead","viewport":"1440x980","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Pruvodce.html","file":"http://192.168.230.131:3777/ds/Pruvodce.html"},{"path":"Reporty.html","group":"Screens","name":"Reporty","title":"Reporty","subtitle":"Manažerské vyhodnocení týmu (hlavní pohled Tým) — týmová KPI, řaditelná srovnávací tabulka členů (obchody, hodnota, win rate, aktivity, spojené hovory, Ø odpracováno, úkoly hotovo/po termínu, trend) s","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Reporty.html","file":"http://192.168.230.131:3777/ds/Reporty.html"},{"path":"App Shell.html","group":"Shell","name":"App shell (skeleton)","title":"App shell (skeleton)","subtitle":"THE unified skeleton — topbar (logo · Datamart/CRM switch · search · account) + left nav + central content + preview drawer. Shared by every screen via _ds/app-shell.js; edit once, applies everywhere.","viewport":"1440x900","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/App%20Shell.html","file":"http://192.168.230.131:3777/ds/App%20Shell.html"},{"path":"Multi-value editor.html","group":"Components","name":"Components · Record detail rail","title":"Record detail rail","subtitle":"Znovupoužitelný levý panel detailu záznamu s inline editací (vzor Attio) — sdílený napříč všemi typy (firma · osoba · obchod · projekt · schůzka). Přejetím myší se hodnota jemně podbarví, kliknutím se pole aktivuje a rovnou se do něj píše (modrý rámeček + ring); po opuštění se změna automaticky uloží (Enter potvrdí, Esc zruší). Podporuje text, odkaz, dlouhý popis (textarea + rozbalení), barevné štítky (pilulky) a prázdný stav „Nastavit hodnotu…","viewport":"1000x820","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Multi-value%20editor.html","file":"http://192.168.230.131:3777/ds/Multi-value%20editor.html"},{"path":"Record tabs - handoff.html","group":"Unlisted","name":"Record tabs - handoff","title":"Record tabs - handoff","subtitle":"","viewport":"","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Record%20tabs%20-%20handoff.html","file":"http://192.168.230.131:3777/ds/Record%20tabs%20-%20handoff.html"},{"path":"Tab system - plán sjednocení.html","group":"Unlisted","name":"Tab system - plán sjednocení","title":"Tab system - plán sjednocení","subtitle":"","viewport":"","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/Tab%20system%20-%20pl%C3%A1n%20sjednocen%C3%AD.html","file":"http://192.168.230.131:3777/ds/Tab%20system%20-%20pl%C3%A1n%20sjednocen%C3%AD.html"},{"path":"identity-image-dialog.html","group":"Components","name":"Components · Dialog obrázku identity","title":"Dialog obrázku identity","subtitle":"KANON. Změna obrázku, který záznam reprezentuje — logo firmy, fotka osoby. Spouštěčem je ZNAČKA V LIŠTĚ DETAILU (.tbar-mark), ne blok v railu: značka je jediné místo, kde ten obrázek uživatel vidí, tak se mění tam, kde na něj kouká. Dialog je DOKUMENTOVÉ třídy (malý 400) — vybraný soubor se nahraje hned, nic se nepotvrzuje, stav nese hlavička a dialog zůstane otevřený, aby byl výsledek vidět. Patička proto NEMÁ modrý primár; hlavní plocha .idimg-pick je zároveň náhled i drop zóna. Tvar náhledu se řídí tvarem značky: firma = obdélník (loga jsou široká), osoba = kruh. Afordance je hover + tooltip, ne trvalý odznak — shodně s inline editací v railu. Ve VÝPISECH se na značku neklika. První adoptér: logo firmy. Další: fotka uživatele v Nastavení → Profil.","viewport":"1000x1500","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/identity-image-dialog.html","file":"http://192.168.230.131:3777/ds/identity-image-dialog.html"},{"path":"note-card.html","group":"Components","name":"Components · Karta poznámky","title":"Karta poznámky","subtitle":"Kanonický výpis poznámek — nadpis, pět řádků náhledu těla, patička s autorem a datem. Poznámka NENÍ vlastnictví osoby: týž prvek kreslí tab Poznámky na detailu osoby, firmy i obchodu a agregace „Z historie subjektů“. CSS je engine _ds/note-card.css; obrazovkové karty si .note-* nedefinují. Pro náhledy (Přehled, osa Aktivita, rail) zůstává řádek ItemList.","viewport":"1120x1180","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/note-card.html","file":"http://192.168.230.131:3777/ds/note-card.html"},{"path":"tooltip.html","group":"Components","name":"Components · Tooltip","title":"Tooltip","subtitle":"Kanonický APLIKAČNÍ tooltip (.acrm-tooltip) — jediný vzor pro „najedu a hned vidím“ (F78, 11. 8. 2026). Nativní title se u interních ovládacích prvků NEPOUŽÍVÁ: prohlížečová bublina naskakuje po sekundách a vypadá cizorodě. Tmavá pilulka ink-900, text 12/1.45 #fff, padding sp-1 sp-2, radius-sm, shadow-pop, max-width 280; portálovaná, fixed, z-index 120 (nad popoverem 101 i dialogem 80/90), pointer-events none. Zobrazení OKAMŽITÉ (≤100 ms po najetí NEBO fokusu), skrytí hned; Esc skrývá. Obsah = jedna krátká věta v sentence case — žádné nadpisy, odstavce ani klávesové výpisy (hint ⌘↵ patří do tlačítka, ne do tooltipu). Umístění nad středem spouštěče s odstupem 6, bez šipky; když nahoře není místo, jde pod prvek. Zhaslé spouštěče: dítě dostane pointer-events:none a hover nese obal — vzor .mc-sendtip (F67). React <Tooltip content=…> z @acrm/ui.","viewport":"960x760","status":"legacy","url":"http://192.168.230.131:3777/ds/legacy/tooltip.html","file":"http://192.168.230.131:3777/ds/tooltip.html"}],"candidates":[],"consumers":[{"id":"acrm","name":"ACRM (acrm/acrm)","url":"https://gitlab.atol.capital/acrm/acrm"}]}