# CSS/SCSS Skill

**When:** Any styling task. `wordpress-plugin-foundation-skill.md` always applies.

---

## BANNED: CSS Custom Properties

`var(--)`, `:root {}`, `--presszone-forum-*` — STRICTLY FORBIDDEN everywhere. No exceptions. No legacy excuses.

Never: `:root { --presszone-forum-primary: #1f71dd; }` or `background: var(--presszone-forum-primary)` or `body.dark-mode { --presszone-forum-*: value; }`

Use SCSS variables: `$presszone-forum-primary: #1f71dd;` — static hex values only.

---

## SCSS Variables

Source of truth: `assets/css/abstracts/_variables.scss`

Every color needs both variants: `$presszone-forum-primary: #1f71dd;` and `$presszone-forum-primary-dark: #60a5fa;`

Adding new color: define `$presszone-forum-new-color: #hex;` + `$presszone-forum-new-color-dark: #hex;` in `_variables.scss`.

---

## CSS Scoping (CRITICAL)

Plugin must not leak styles to host theme header/footer.

| Context | Selector | Use for |
|---------|----------|---------|
| Body-level | `body.presszone-forum-template` | background, color-scheme, min-height only |
| All element styles | `.presszone-forum-wrapper` | typography, colors, layouts |
| Dark mode overrides | `body.dark-mode .presszone-forum-*` | explicit SCSS var overrides |
| Widgets | `.presszone-forum-widget` | same containment as wrapper |

Allowed on `body.presszone-forum-template`: `background`, `color-scheme`, `min-height`, `scroll-behavior`, `padding-bottom`.

NEVER on `body.presszone-forum-template`: `:where()` selectors, direct `h1-h6 p a ul` styling, any descendant element selectors.

NEVER: `body.dark-mode h1 { }` — affects entire page. Use `body.dark-mode .presszone-forum-wrapper h1 { }`.

Exception: `assets/scss/pages/_embed.scss` — intentionally global (iframe standalone page).

---

## Dark Mode

Default light, explicit dark override pattern: `.presszone-forum-card { background: $presszone-forum-surface; }` then `body.dark-mode .presszone-forum-card { background: $presszone-forum-surface-dark; }`.

---

## BEM Naming

`.block`, `.block__element`, `.block--modifier`, `.block__element--modifier`. All classes use `presszone-forum-` prefix.

---

## Animations

Use shared keyframes from `_animations.css` — don't duplicate.

Use `$presszone-forum-duration-fast`, `$presszone-forum-duration-normal`, `$presszone-forum-duration-slow` variables — no hardcoded durations.

Reduced motion (required, scoped): `@media (prefers-reduced-motion: reduce) { .presszone-forum-wrapper * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }`

Don't remove animation class on `animationend` — breaks dependent CSS rules.

---

## Responsive

Mobile-first. Use CSS media queries — never `wp_is_mobile()`. Breakpoint variables: `$breakpoint-mobile: 480px`, `$breakpoint-tablet: 768px`, `$breakpoint-desktop: 1024px`, `$breakpoint-wide: 1440px`.

---

## Layout

Flexbox for alignment/rows. Grid for 2D layouts. Never `<table>` for layout. Never global `*`, `html`, `body` selectors — scope to `.presszone-forum-wrapper`.

---

## Z-Index Scale

`$presszone-forum-z-base: 1`, `z-dropdown: 100`, `z-sticky: 200`, `z-modal-backdrop: 900`, `z-modal: 1000`, `z-toast: 1100`.

---

## Spacing Variables

`$presszone-forum-space-xs: 4px`, `sm: 8px`, `md: 12px`, `lg: 16px`, `xl: 24px`, `2xl: 32px`.

---

## Inline CSS: ABSOLUTELY FORBIDDEN

No `wp_add_inline_style()`, no `<style>` tags in templates, no `style=""` attributes. No exceptions.

| "Need" | Solution |
|--------|----------|
| Dynamic admin color | Write to `custom.css` on save |
| User-specific value | Predefined CSS classes |
| Conditional styling | Add/remove CSS classes |
| Nesting depth | `.presszone-forum-depth-1..6` classes |

Dynamic colors: write to `wp-content/uploads/presszone-forum/custom.css` via WP Filesystem API.

---

## Dropdown Component

Single source: `assets/css/components/_dropdowns.scss`.

| Element | Class |
|---------|-------|
| Wrapper | `presszone-forum-actions-dropdown` |
| Trigger | `presszone-forum-actions-dropdown__trigger` |
| Menu panel | `presszone-forum-actions-dropdown__menu` |
| Item | `presszone-forum-actions-dropdown__item` |
| Danger item | `presszone-forum-actions-dropdown__item--danger` |
| Icon | `presszone-forum-actions-dropdown__icon` |
| Divider | `presszone-forum-actions-dropdown__divider` |

Open state: JS adds `presszone-forum-actions-dropdown--open` to wrapper.

Menu panel needs `overflow: hidden` when `border-radius` set.

Navbar `__dropdown` uses `opacity/visibility/transform` animation (not `display:none`), CSS in `_navbar.scss`, same `--open` class. Don't add `__menu` class to it.

---

## File Structure

`assets/scss/abstracts/_variables.scss` — SCSS vars (source of truth). Components in `assets/scss/components/`. Pages in `assets/scss/pages/`. Admin-customized colors in `wp-content/uploads/presszone-forum/custom.css`.

SCSS files with duplicate styles — check ALL when editing: `pages/threads.scss`, `frontend.scss`, `_legacy-frontend.scss`, `compiled/*.scss`, `extracted/*.scss`.

---

## Build

From plugin root: `npm run build:css` after ANY SCSS change. `npm run watch:css` for dev.

---

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| `var(--)` or `:root {}` | Use `$presszone-forum-*` SCSS vars |
| Element styles on `body.presszone-forum-template` | Scope to `.presszone-forum-wrapper` |
| Dark mode without explicit override | Add `body.dark-mode .class {}` |
| Hardcoded hex colors | Use vars from `_variables.scss` |
| Missing `-dark` variant | Every color needs both |
| Prefix <4 chars | Use `.presszone-forum-*` |
| Forgot CSS build | `npm run build:css` |
| No reduced motion | Add `@media (prefers-reduced-motion)` |
| Inline styles | Use CSS classes |
| Global selectors | Scope to `.presszone-forum-wrapper` |
| `outline: none` | Use `outline: 2px solid` on `:focus-visible` |
| New color without dark variant | Define both in `_variables.scss` |
| Renaming CSS class | Check `writeCustomCss()` in Plugin.php |

---

## Related Skills

`accessibility-skill.md` — focus states, ARIA. `javascript-skill.md` — class toggling.
