# BPL DS — Constraints/Forcing Rules (CfRs)

> Machine-readable rules for AI agents working with or consuming Be Partner DS.
> Two sections: **Contributor** (writing components in this repo) and **Consumer** (using the DS in an external project).

---

## §1 Contributor Rules (C1–C6)

Rules for agents adding or modifying components in the `BePartnerLabs/ds` repository.

Each rule includes a grep pattern to verify compliance.

---

### C1 — Private vars only on the component root selector

`--_*` custom properties must appear only on the root BEM class (`.bp-<name>`), never on child selectors.

**Violation pattern (grep):**
```
grep -rn "\.\(bp-[a-z].*__\|bp-[a-z].*--\).*{" src/styles/components/ -A 10 | grep "\-\-_"
```

**Why:** Private vars are resolved once at the root. Using them in children breaks the encapsulation — child selectors should reference plain values or Level 2 tokens.

---

### C2 — Token names match the CSS property exactly (Level 2 and Level 3)

No abbreviations in public slots or private resolvers:
- Level 2: `--btn-background` not `--btn-bg` · `--btn-border-radius` not `--btn-br`
- Level 3: `--_background` not `--_bg` · `--_border-radius` not `--_br`

**Violation pattern (grep):**
```
grep -rn "\-\-[a-z-]*-\(bg\|fg\|bd\|br\|sz\|clr\|col\)\b\|\-\-_\(bg\|fg\|bd\|br\|sz\|clr\|col\)\b" src/styles/components/
```

**Why:** Level 2 tokens are a consumer API — abbreviations break discoverability. Level 3 private vars should mirror Level 2 names exactly so the chain is readable at a glance.

---

### C3 — No state tokens

`--btn-background-hover`, `--btn-color-active`, `--input-border-focus` are all banned. Re-declare the same Level 2 token inside the state selector instead.

**Violation pattern (grep):**
```
grep -rn "\-\-[a-z-]*-\(hover\|active\|focus\|disabled\|checked\|visited\)" src/styles/components/
```

**Correct pattern:**
```css
.my-cta { --btn-background: var(--bp-cta); }
.my-cta:hover { --btn-background: var(--bp-cta-hover); }
```

---

### C4 — CSS layers declared in order at the top of every component file

Every `src/styles/components/*.css` file must start with:
```css
@layer bp-tokens, bp-reset, bp-grid, bp-components, bp-utilities;
```

**Violation pattern (grep):**
```
grep -rLn "@layer bp-tokens, bp-reset, bp-grid, bp-components, bp-utilities" src/styles/components/
```
(files listed have no layer declaration)

**Why:** Consistent layer ordering ensures cascade predictability and allows agents to reason about precedence when adding new rules.

---

### C5 — No `style=""` in MDX examples

Inline styles in documentation couple design to markup and teach consumers bad patterns.

**Violation pattern (grep):**
```
grep -rn 'style="' src/content/docs/
```

Use BEM demo classes instead: `demo-<component>--<modifier>` in a `<style>` block.

---

### C6 — Every component selector uses `.bp-` prefix

Component class names must start with `.bp-`. No unprefixed utility classes inside component files.

**Why:** The `.bp-` prefix signals DS ownership and prevents accidental namespace collisions with external utilities or ad-hoc component classes.

**Violation pattern (grep):**
```
grep -rn "^\s*\.[^bp_]" src/styles/components/ | grep -v "@layer\|/\*\|demo-"
```

---

### C7 — No `innerHTML` or `insertAdjacentHTML` in public JS

Web Component files in `public/*.js` must not use `innerHTML =` or `insertAdjacentHTML(`. Use DOM API (`createElement`, `textContent`, `appendChild`) instead.

**Why:** `innerHTML` with any dynamic value — even from an internal lookup object — is blocked by CSP policies enforcing `require-trusted-types-for 'script'` (Trusted Types). DOM API calls are CSP-safe without any additional headers.

**Violation pattern (grep):**
```
grep -rn "innerHTML\s*=\|insertAdjacentHTML\s*(" public/*.js
```

**Fix pattern:**
```js
// ❌ blocked by Trusted Types
el.innerHTML = `<span>${ICONS[variant]}</span>`

// ✅ CSP-safe
const span = document.createElement('span')
span.textContent = ICONS[variant] ?? ''
el.appendChild(span)
```

---

## §2 Consumer Rules (E1–E4)

Rules for agents implementing UI in external projects that import `@be-partner-labs/ds`.

These rules are **not enforced from this repo** — copy `docs/validate-consumer-template.md` into your own project to run them locally.

---

### E1 — Never modify `.bp-*` classes directly

Extend with a wrapper or scoped selector. Never edit the DS class itself.

**Wrong:**
```css
.bp-btn { background: red; } /* ❌ modifies DS internals */
```

**Correct:**
```css
.hero__cta { --btn-background: var(--brand-cta); } /* ✅ Level 2 override */
```

---

### E2 — Override tokens only via Level 2 on your own selector

Set `--btn-*` tokens on your wrapper, not on `:root`. `:root` is for Level 1 (`--bp-*`) only.

**Wrong:**
```css
:root { --btn-background: blue; } /* ❌ pollutes global scope */
```

**Correct:**
```css
.hero { --btn-background: var(--brand-primary); } /* ✅ scoped override */
```

---

### E3 — No `style=""` for variants — use BEM modifier or component token

**Wrong:**
```html
<button class="bp-btn" style="background: red">...</button>
```

**Correct:**
```html
<button class="bp-btn bp-btn--danger">...</button>
```
or define `.my-danger-btn { --btn-background: red; }` in your CSS.

---

### E4 — Import DS CSS before your own styles

The DS defines `@layer` order. Your styles must come after or the cascade breaks.

**Correct import order:**
```css
@import "@be-partner-labs/ds"; /* first */
@import "./my-styles.css";     /* after */
```
