Do not hesitate to ask me any questions. ASK ME ANYTHING YOU NEED! Use the AskUserQuestion tool to ask as many follow ups as you need to reach clarity.

# ikas Code Components Project

You are building **Preact + TypeScript components for an e-commerce storefront**.
This project uses the ikas Code Components framework with an MCP server for API documentation.

**ALWAYS query MCP tools before writing code that uses storefront APIs.**
Never guess function signatures or type shapes — the MCP server is the source of truth.

## CRITICAL: Auto-Generated Files

**NEVER manually create or edit `ikas.config.json`, `types.ts`, `global-types.ts`, or `src/components/index.ts`** — they are all auto-generated by CLI commands.
Use `npx ikas-component config add-component --props '[...]'` or `npx ikas-component config add-prop` to manage components and props.
These commands update `ikas.config.json`, `types.ts`, `global-types.ts`, AND `src/components/index.ts` (including the component export) automatically.

**The CLI does NOT edit your component source.** `remove-prop` and `remove-enum` update `ikas.config.json` and the generated `types.ts` / `global-types.ts` only — `index.tsx`, sub-components, and `styles.css` are untouched. After removing a prop or enum, grep the source for the old identifier and clean up dead references yourself before building.

## MCP Tools (12 tools)

### Starting a New Section

| Tool                                | Purpose                                                                                                                                                                                                                     |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `get_section_template(sectionType)` | **Start here** — production-ready starter template (index.tsx + types.ts + styles.css + config) for common sections: header, footer, product-detail, product-list, cart, login, register, hero-banner, blog-post, faq, etc. |
| `get_framework_guide(topic)`        | Framework docs — "ai-workflow", "common-pitfalls", "prop-types", "css-scoping", "form-handling", "imports", "sections-vs-components"                                                                                        |
| `get_code_example(task)`            | Code examples — "add to cart", "variant selection", "image-handling", "product-detail-section", "cart-section"                                                                                                              |

### Looking Up APIs

| Tool                        | Purpose                                                                                                                                                                   |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search_docs(query)`        | Search across all storefront API docs and framework guides                                                                                                                |
| `get_function_doc(name)`    | Full docs for a specific function (e.g. "addItemToCart", "Router.navigate")                                                                                               |
| `list_functions(category?)` | List functions by category: ProductDetail, Cart, ProductList, Navigation, Customer, Order, Image, Blog, Brand, Category, Pricing, Form, Validation, Pagination, Filtering |
| `get_prop_types()`          | All available ikas.config.json prop types with TS types and examples                                                                                                      |

### Exploring Types

| Tool                               | Purpose                                                                                                                              |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `get_model_guide(model)`           | **One-stop-shop** — type definition + all utility functions + examples + related types for a model (e.g. "IkasProduct", "IkasOrder") |
| `get_type_definition(name)`        | Full definition of a type or enum (e.g. "IkasProduct", "IkasOrderStatus")                                                            |
| `get_functions_for_type(typeName)` | All utility functions for a type (e.g. "IkasImage")                                                                                  |
| `search_types(query)`              | Search types/enums by keyword (e.g. "price", "address", "status")                                                                    |
| `list_types(domain?, kind?)`       | List all types, optionally filtered by domain ("product", "cart", "order") or kind ("type", "enum")                                  |

## CLI Commands

**Never edit ikas.config.json or types.ts manually** — use the CLI commands:

| Command                                                                                                                             | Purpose                                                      |
| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| `npx ikas-component config add-component --name "Name" --type section --props '[...]'`                                              | **Primary** — create component with all props in one command |
| `npx ikas-component config add-component --name "Name" --type section`                                                              | Create component with no props (add later)                   |
| `npx ikas-component config add-prop --component "Name" --name title --displayName "Title" --type TEXT --required [--group content]` | Add a single prop incrementally                              |
| `npx ikas-component config update-prop --component "Name" --prop title --type RICH_TEXT [--group colors]`                           | Update a prop's type or group                                |
| `npx ikas-component config remove-prop --component "Name" --prop title`                                                             | Remove a prop                                                |
| `npx ikas-component config remove-component --name "Name"`                                                                          | Remove a component                                           |
| `npx ikas-component config add-prop-group --component "Name" --id colors --name "Colors" [--description "..."] [--parent style]`    | Create a prop group                                          |
| `npx ikas-component config update-prop-group --component "Name" --id colors [--name "..."] [--description "..."]`                   | Update a prop group                                          |
| `npx ikas-component config remove-prop-group --component "Name" --id colors`                                                        | Remove a prop group                                          |
| `npx ikas-component config list`                                                                                                    | List all components and their props                          |
| `npx ikas-component config add-enum --name "Size" --options '[{"name":"Small","value":"s"}]'`                                       | Create a custom ENUM type (returns `enumTypeId`)              |
| `npx ikas-component config update-enum --id <enumId> --name "..." [--options '[...]']`                                              | Update enum name/options                                      |
| `npx ikas-component config remove-enum --id <enumId>`                                                                               | Remove enum (fails if any prop still references it)          |
| `npx ikas-component config list-enums`                                                                                              | List all custom enums                                         |
| `npx ikas-component check --json`                                                                                                   | Type-check all components, output errors as JSON             |
| `npx ikas-component build`                                                                                                          | Compile server.js + client.js + styles.css per component     |
| `npx ikas-component dev`                                                                                                            | Start dev server (Vite 5200 + WebSocket 5201)                |

## Workflow: Building a New Section

1. `get_section_template("product-detail-section")` → get starter files + CLI command with --props
2. For any custom ENUM props the section needs: `config add-enum` **first** (capture the returned `enumTypeId`), then reference it in `add-prop --type ENUM --enumTypeId <id>`. Order matters — an ENUM prop without a pre-existing `enumTypeId` is rejected.
3. Run the CLI command (creates component + props + types.ts in one step)
4. Write `index.tsx` and `styles.css` using the template (do NOT edit `types.ts` or `global-types.ts` — both are regenerated on every prop/enum mutation)
5. Look up APIs → `get_model_guide("IkasProduct")`, `get_function_doc("addItemToCart")`
6. `npx ikas-component check --json` → fix type errors
7. `npx ikas-component build` → verify clean build

### Custom ENUM lifecycle

- **Create:** `add-enum` → `add-prop --type ENUM --enumTypeId <id>`. The enum must exist before the prop is created.
- **Rename options:** `update-enum --id <id> --options '[...]'`. `types.ts` regenerates automatically.
- **Remove:** remove (or repoint) every prop that references the enum **first**, then `remove-enum`. `remove-enum` blocks with an error while any prop still references the id.
- `global-types.ts` is regenerated unconditionally on `add-enum` / `update-enum` / `remove-enum` / `remove-prop` — never hand-edit it.

## Sub-Component Structure

**ALWAYS create sub-components in `src/sub-components/` with their own folder containing `index.tsx` and `styles.css`. NEVER create flat .tsx files inside a component folder.**

```
src/
├── components/
│   ├── ProductList/
│   │   ├── index.tsx         # imports from ../../sub-components/...
│   │   ├── types.ts          # auto-generated (CLI-managed)
│   │   └── styles.css
│   └── index.ts
└── sub-components/
    ├── ProductCard/
    │   ├── index.tsx          # sub-component with inline Props
    │   └── styles.css
    └── FilterSidebar/
        ├── index.tsx
        └── styles.css
```

**Key rules:**

- `src/components/` = registered in ikas.config.json. `src/sub-components/` = internal helpers (NOT in ikas.config.json)
- Sub-components do NOT have `types.ts` — define `Props` inline in `index.tsx`
- TSX: use `import ProductCard from "../../sub-components/ProductCard";`
- Sub-components that read MobX stores need `observer()`, others don't
- Sub-components can be shared across multiple parent sections

```tsx
// src/sub-components/ProductCard/index.tsx — inline Props, no types.ts
import { IkasProduct, getSelectedProductVariant } from "@ikas/bp-storefront";

interface Props { product: IkasProduct; }

export default function ProductCard({ product }: Props) { ... }
```

## SVG Icons

**CRITICAL: Never write inline `<svg>` in components or sub-components.**
All icons live in `src/sub-components/icons/index.tsx` as named exports.

```tsx
// Adding a new icon — IconProps extends SVGAttributes<SVGSVGElement>
export function HeartSVG({ className, ...props }: IconProps) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      className={`kombos-icon ${className}`}
      {...props}
    >
      <path d="M20.84 4.61..." fill="currentColor" />
    </svg>
  );
}

// Using it
import { HeartSVG } from "../../sub-components/icons";
<HeartSVG />;
```

### Rules

- One file (`index.tsx`) holds all icons — no separate files per icon
- `IconProps` extends `SVGAttributes<SVGSVGElement>` from Preact — accepts all standard SVG attributes
- Pattern: `{ className, ...props }` with `className={`kombos-icon ${className}`}` and `{...props}` spread
- Icons use `fill="currentColor"` — they inherit color from the parent element's CSS `color` property
- Before adding a new icon, check if it already exists in the file

### Sizing Icons

**CRITICAL: Never pass `width`/`height` props to size icons.** Icon sizing is controlled via CSS `font-size` on the parent element or a wrapping class.

The `.kombos-icon` base class uses `width: 1em; height: 1em` so icons scale with `font-size`.

```css
/* Size an icon via font-size on the parent or the icon itself */
.my-section__icon-btn {
  font-size: 1.5rem;
} /* icon inside will be 24x24 */
.my-section__small-icon {
  font-size: 1rem;
} /* icon will be 16x16 */
```

```tsx
/* In JSX — no width/height props needed */
<button className="my-section__icon-btn"><HeartSVG /></button>
<span className="my-section__small-icon"><PackageSVG /></span>
```

## Button Sub-Component

**CRITICAL: Never write custom button styles in components.** All buttons MUST use `src/sub-components/Button`.
Import: `import Button from "../../sub-components/Button";`

### Variants

| Prop      | Values                       | Default     |
| --------- | ---------------------------- | ----------- |
| `variant` | `"primary"` \| `"secondary"` | `"primary"` |
| `size`    | `"xs"` \| `"s"` \| `"m"`     | `"s"`       |

### Size Specs (from Figma)

| Size | Padding   | Typography class   |
| ---- | --------- | ------------------ |
| `xs` | 8px 16px  | `text-sm-semibold` |
| `s`  | 10px 20px | `text-md-semibold` |
| `m`  | 12px 24px | `text-lg-semibold` |

### Variant Styles

- **Primary:** bg gray-900, text white. Hover: bg gray-800. Disabled: bg gray-300, text gray-50.
- **Secondary:** bg white, border gray-200, text gray-900. Hover: border gray-300. Disabled: bg gray-50, text gray-300.

All: `border-radius: 6px`, typography class auto-applied by size.

### Usage

```tsx
import Button from "../../sub-components/Button";

<Button variant="primary" size="s">{buttonText}</Button>
<Button variant="secondary" size="m" disabled>{disabledText}</Button>
<Button variant="primary" size="xs" onClick={handleClick}>{label}</Button>
```

Extends `JSX.HTMLAttributes<HTMLButtonElement>` — accepts all standard button props (`onClick`, `disabled`, `className`, `aria-label`, etc.).
When placed in flex containers, add a layout class (e.g. `className="my-section__footer-btn"`) with `flex: 1` for full-width behavior.

## Input Sub-Component

**CRITICAL: Never write custom input styles in components.** All text inputs MUST use `src/sub-components/Input`.
Import: `import Input from "../../sub-components/Input";`

Input is a pure input field — no label, no helper text. Wrap with `FormItem` for labels and validation messages.

### Props

| Prop       | Type                    | Default | Description                                                          |
| ---------- | ----------------------- | ------- | -------------------------------------------------------------------- |
| `password` | `boolean`               | `false` | Shows eye toggle icon for password visibility                        |
| `disabled` | `boolean`               | `false` | Disabled state                                                       |
| `leftIcon` | `ComponentChildren`     | —       | Icon rendered on the left (activates search-style border `gray-500`) |
| `inputRef` | `Ref<HTMLInputElement>` | —       | Ref forwarded to the native `<input>` element                        |

Also extends `InputHTMLAttributes<HTMLInputElement>` — accepts `placeholder`, `value`, `onInput`, `name`, etc.

### Design Specs (from Figma)

- Input field: padding `10px 14px`, border-radius `6px`, border `1px solid gray-200`
- Input text: `text-md-regular`, color `gray-900`
- Placeholder: color `gray-400`
- Hover: border `gray-300`
- With `leftIcon`: border `gray-500`, padding `10px 12px`, gap `12px`
- Disabled: bg `gray-50`, text `gray-300`

### Usage

```tsx
import Input from "../../sub-components/Input";

<Input placeholder="you@example.com" />
<Input password placeholder="Enter password" />
<Input disabled placeholder="Disabled" />
<Input leftIcon={<MagnifyingGlass1SVG />} placeholder="Search..." />
```

**Remember:** Use `onInput` instead of `onChange` for text inputs (Preact behavior).

## FormItem Sub-Component

Wraps form controls (Input, select, etc.) with a label and helper/error text.
Import: `import FormItem from "../../sub-components/FormItem";`

### Props

| Prop         | Type                                    | Default     | Description                                                |
| ------------ | --------------------------------------- | ----------- | ---------------------------------------------------------- |
| `label`      | `string`                                | —           | Label text above the input                                 |
| `status`     | `"default"` \| `"error"` \| `"success"` | `"default"` | Controls border color of child Input and helper text color |
| `helperText` | `string`                                | —           | Helper/error/success message below the input               |
| `children`   | `ComponentChildren`                     | —           | The form control (e.g. `<Input />`)                        |

### Design Specs (from Figma)

- Label: `text-xs-medium`, color `gray-700`
- Helper text: `text-xs-regular`, default `gray-500`
- Error: border & helper `--kombos-error` (#FF3C48)
- Success: border & helper `--kombos-success` (#12B76A)
- Gap between label / input / helper: `4px`

### Usage

```tsx
import FormItem from "../../sub-components/FormItem";
import Input from "../../sub-components/Input";

<FormItem label="Email">
  <Input placeholder="you@example.com" />
</FormItem>

<FormItem label="Password">
  <Input password placeholder="Enter password" />
</FormItem>

<FormItem label="Email" status="error" helperText="Invalid email">
  <Input value="bad@" />
</FormItem>

<FormItem label="Email" status="success" helperText="Looks good!">
  <Input value="ok@ikas.com" />
</FormItem>
```

## Media Utilities (`src/utils/media.ts`)

**CRITICAL: Never define local `ASPECT_RATIO_MAP`, `OBJECT_FIT_MAP`, or `ALIGNMENT_MAP` in components.**
All aspect ratio, object fit, and vertical alignment resolution MUST use the shared helpers from `src/utils/media.ts`.

```tsx
import {
  resolveAspectRatio,
  resolveObjectFit,
  resolveVerticalAlignment,
} from "../../utils/media";

// Each function accepts an optional value and returns the CSS string.
// When undefined is passed, defaults are applied: "Square" → "1 / 1", "Cover" → "cover", "Middle" → "center"
const ar = resolveAspectRatio(aspectRatio); // e.g. "1 / 1"
const of = resolveObjectFit(objectFit); // e.g. "cover"
const va = resolveVerticalAlignment(align); // e.g. "center"
```

- No need to set defaults in destructuring (`aspectRatio = "Square"`) — the functions handle it
- Components that only pass these values through to children (e.g. `ProductDetailBundleFurniture`) don't need to import the utils

## Hooks (`src/hooks/`)

### `useScrollLock` — overlay/modal scroll lock (`src/hooks/useScrollLock.ts`)

**CRITICAL: Never write inline `document.body.style.overflow = "hidden"` in components.** All overlay/modal scroll locking MUST use `useScrollLock`.

```tsx
import { useScrollLock } from "../../hooks/useScrollLock";

// Always-on (mount-triggered overlays: CartSidebar, AddressModal, ImagePreviewModal, SearchModal)
useScrollLock();

// Conditional (prop-triggered overlays: MobileFilterModal)
useScrollLock(isOpen);

// With skip-cleanup (overlay handoff: MobileMenu → CartSidebar)
const skipCleanupRef = useRef(false);
useScrollLock(true, skipCleanupRef);
// Set skipCleanupRef.current = true before closing to keep scroll locked for the next overlay
```

**Parameters:**

- `enabled` (default `true`) — lock when true, unlock cleanup when false or unmount
- `skipCleanupRef` (optional `RefObject<boolean>`) — when `.current` is true, cleanup skips restoring scroll (for seamless overlay transitions)

**What it does:** calculates scrollbar width, sets `overflow: hidden` + `paddingRight` on body, restores on cleanup.

**Exception:** `Header/index.tsx` uses a raw reset (`overflow = ""`) as a safety cleanup on mount — this is intentionally NOT using the hook.

### `useRedirectIfLoggedIn` — auth page guard (`src/hooks/useRedirectIfLoggedIn.ts`)

Redirects logged-in users away from auth pages (Login, Register, ForgotPassword, RecoverPassword).
Returns `isChecking: boolean` — render `null` while checking to avoid flash.

```tsx
import { useRedirectIfLoggedIn } from "../../hooks/useRedirectIfLoggedIn";

const isChecking = useRedirectIfLoggedIn(() => {
  initLoginForm(loginForm);
});
if (isChecking) return null;
```

## Utility Modules (`src/utils/`)

### `cx()` — className joiner (`src/utils/cx.ts`)

**CRITICAL: Use `cx()` for conditional className assembly.** Never use template literal ternaries for conditional classes.

Wrong: `className={\`base ${cond ? "modifier" : ""}\`}`Correct:`className={cx("base", cond && "modifier")}`

Import: `import { cx } from "../../utils/cx";`

### `getSelectValuePrice()` — option price formatter (`src/utils/optionPrice.ts`)

Formats price for product option select values. Used by ChoiceBox, ChoiceSelect, ChoiceSwatch.

### `isBundleOutOfStock()` — bundle helpers (`src/utils/bundle.ts`)

Bundle validation logic shared across ProductDetailAddToCart and ProductDetailPrices.

## Key Patterns

### Component Exports & Reactivity

```tsx
// Root components are automatically reactive — the ikas runtime wraps them in autorun().
// Do NOT import or use observer() on root exports.
import { Props } from "./types";

export function MySection({ product }: Props) { ... }
export default MySection;
```

```tsx
// Only use observer() on extracted SUB-COMPONENTS that independently read MobX stores:
import { observer } from "@ikas/component-utils";

const CartBadge = observer(function CartBadge() {
  const count = cartStore.order?.orderLineItems?.length ?? 0;
  return <span>{count}</span>;
});
```

```tsx
// ALSO wrap EXTRACTED HELPER COMPONENTS declared inside a component file —
// especially list items rendered via .map() that read/write MobX state
// (e.g., offer.isSelected, option.values). Without observer(), the helper
// won't re-render when the observable changes.
const OfferCard = observer(function OfferCard({ offer }) {
  const isSelected = offer.isSelected;
  return <div>{isSelected ? "ON" : "OFF"}</div>;
});

export function MySection({ product }: Props) {
  return product.offers.map((offer) => (
    <OfferCard key={offer.id} offer={offer} />
  ));
}
```

**Rule of thumb:** if a non-root component reads or writes MobX observables (store fields, `offer.isSelected`, `option.values`, etc.), wrap it with `observer()`. Without it, MobX mutations won't trigger re-renders.

### Null Safety

```tsx
// Storefront models can be null — always check before accessing
if (!product) return null;
const price = product.selectedVariant?.price?.formattedPrice ?? "";
```

### Mutations

```tsx
// Functions like addItemToCart() mutate the model in-place (MobX observable)
// No need to capture return value — root components re-render automatically via autorun()
await addItemToCart({ product });
```

### CSS Scoping

All CSS is auto-scoped with `.cc_{componentId}` prefix. Write plain class names — they are scoped at build time.

### Preact Event Handling

Use `onInput` instead of `onChange` for text inputs (Preact behavior).

### Import Source

```tsx
import { addItemToCart, IkasProduct, IkasImage } from "@ikas/bp-storefront";
```

## No Static Text Rule

**CRITICAL: Never hardcode user-visible text in JSX.** All text strings (headings, button labels,
empty states, loading messages, form labels) MUST be TEXT props with defaultValues.

Wrong: `<h1>Sign In</h1>`
Correct: `<h1>{title}</h1>` with `title` as TEXT prop (defaultValue: "Sign In")

For button loading states, use two separate props:

- `submitButtonText` (default: "Sign In")
- `submittingButtonText` (default: "Signing in...")

Group text props under a "Texts" propGroup when the component has 5+ props.

**Assistive strings (`aria-label`, `aria-describedby`, `alt`, sr-only text):** if the string is meaningful to end users (e.g. icon-only button label, product image alt), make it a TEXT prop. English literal defaults are acceptable for purely structural labels a merchant would never want to change (e.g. `role="dialog" aria-modal="true"`). When in doubt, make it a prop.

## Sections vs Components

- **Sections** = page-level, full-width containers (Header, Hero, Product Grid, Footer).
  Set `"type": "section"` via CLI. Use `<section>` root element. Props interface: `Props`.
  **Sections MUST use `kombos-container` for max-width.** The `<section>` root stays full-width (for background color),
  but all inner content MUST be wrapped in a `<div className="kombos-container">` (or added to an existing inner div).
  This limits content to `var(--kombos-max-width)` (1500px) and centers it with `margin: auto`.
  Padding/layout styles go on the container wrapper, NOT on the `<section>` root.
  **Exceptions:** Header (sticky, renders child components via IkasComponentRenderer) and HeroSlider (full-width by design) do NOT use the container.
- **Components** = child elements placed inside sections (buttons, cards, badges).
  Defaults to `"component"`. Use `<div>` root element. Props interface: `Props`.

## Prop Groups

Organize props into collapsible groups in the editor sidebar. Use prop groups when a component has 5+ props to improve UX.

### Config Format

- Define groups in `propGroups` array on the component in `ikas.config.json`
- Assign props to groups via `groupId` on each prop
- Groups can nest 1 level deep via `children`
- Props without `groupId` appear ungrouped at root level
- Group IDs must be unique within a component
- **NEVER assign `COMPONENT` or `COMPONENT_LIST` props to a prop group** — they don't render in the editor sidebar, so grouping them is meaningless. Leave them ungrouped at root level.

### CLI Commands

- `config add-prop-group --component "Name" --id content --name "Content"` — create group
- `config add-prop-group --component "Name" --id colors --name "Colors" --parent style` — create nested group
- `config add-prop --component "Name" --name title --displayName "Title" --type TEXT --group content` — add prop to group
- `config update-prop --component "Name" --prop title --group colors` — move prop to different group
- `config remove-prop-group --component "Name" --id content` — remove group (props become ungrouped)

### When to Use

- 5+ props → group related props
- Sections with content + style props → separate "Content" and "Appearance" groups
- Complex sections → use nested groups (e.g., "Style" → "Colors", "Typography")

## Workflow Addition

When building a section with 5+ props, organize into prop groups after defining props:

```bash
npx ikas-component config add-prop-group --component "Name" --id content --name "Content"
npx ikas-component config update-prop --component "Name" --prop title --group content
```

## Global Z-Index (Kombos Design System)

**CRITICAL: Never hardcode `z-index` values in component CSS.**
All z-index levels are defined as CSS custom properties in `src/global.css` under `:root`.

| Variable              | Value | Usage                                        |
| --------------------- | ----- | -------------------------------------------- |
| `--kombos-z-dropdown` | 50    | Dropdown menus                               |
| `--kombos-z-header`   | 100   | Sticky header                                |
| `--kombos-z-overlay`  | 200   | Overlays (cart sidebar, mobile menu, modals) |

```css
.my-dropdown {
  z-index: var(--kombos-z-dropdown);
}
.my-header {
  z-index: var(--kombos-z-header);
}
.my-overlay {
  z-index: var(--kombos-z-overlay);
}
```

## Global Colors (Kombos Design System)

**CRITICAL: Never hardcode hex color values in component CSS.**
All colors are defined as CSS custom properties in `src/global.css` under `:root`.
Use `var(--kombos-*)` in component CSS. Only `rgba()` values for overlays/shadows are exempt.

### Available Variables

| Variable            | Hex     | Usage                               |
| ------------------- | ------- | ----------------------------------- |
| `--kombos-white`    | #ffffff | Backgrounds, text on dark           |
| `--kombos-gray-50`  | #fafafa | Hover backgrounds                   |
| `--kombos-gray-100` | #f6f6f6 | Light borders, image placeholders   |
| `--kombos-gray-200` | #ececed | Separator borders                   |
| `--kombos-gray-300` | #c4c4c6 | Disabled/muted borders, muted icons |
| `--kombos-gray-400` | #9c9c9f | Placeholder/empty state text        |
| `--kombos-gray-500` | #727276 | Secondary text (sublinks, captions) |
| `--kombos-gray-600` | #4a4a4f | —                                   |
| `--kombos-gray-700` | #2e2e33 | Primary text, icons                 |
| `--kombos-gray-800` | #202025 | —                                   |
| `--kombos-gray-900` | #14141a | Headings, buttons, badges           |
| `--kombos-badge-bg` | #ff0000 | Cart badge background               |

### Usage in CSS

```css
.my-section__title {
  color: var(--kombos-gray-900);
}
.my-section__border {
  border: 1px solid var(--kombos-gray-100);
}
.my-section__btn {
  background: var(--kombos-gray-900);
  color: var(--kombos-white);
}
.my-section__btn:hover {
  background: var(--kombos-gray-700);
}
```

### Rules

- Every color in component CSS MUST use a `var(--kombos-*)` variable
- Only exception: `rgba()` for overlays (`rgba(0,0,0,0.35)`) and box-shadows
- When props provide dynamic colors (e.g., `backgroundColor`, `textColor`), apply via inline `style` in JSX — CSS variables are for static/design-system colors only

## Global Typography (Kombos Design System)

**CRITICAL: Never write `font-family`, `font-weight`, `font-size`, or `line-height` in component CSS.**
All typography is defined as utility classes in `src/global.css`. Apply them via `className` in JSX.

**`font-family` is NOT set by typography classes.** The storefront injects a global `* { font-family: ... }` rule
which acts as the base font. Our typography classes only control `font-weight`, `font-size`, and `line-height`.
Never add `font-family` in component CSS or global typography classes — let the storefront's global font cascade through.

Font: **Montserrat** | Weights: Regular 400, Medium 500, Semibold 600

### Class Naming Convention

```
{scale}-{size}-{weight}
```

- **Scale:** `display` (large headings) or `text` (body/UI text)
- **Size:** `xxl`, `xl`, `lg`, `md`, `sm`, `xs`
- **Weight:** `regular`, `medium`, `semibold`
- **Special variants:** append `-strike` (line-through) or `-underline`

### Available Classes & Sizes

| Class prefix    | Font size | Line height |
| --------------- | --------- | ----------- |
| `display-xxl-*` | 72px      | 90px        |
| `display-xl-*`  | 60px      | 72px        |
| `display-lg-*`  | 48px      | 60px        |
| `display-md-*`  | 36px      | 44px        |
| `display-sm-*`  | 30px      | 38px        |
| `display-xs-*`  | 24px      | 32px        |
| `text-xl-*`     | 20px      | 30px        |
| `text-lg-*`     | 18px      | 28px        |
| `text-md-*`     | 16px      | 24px        |
| `text-sm-*`     | 14px      | 20px        |
| `text-xs-*`     | 12px      | 18px        |

### Usage in JSX

```tsx
// Combine component class with typography class
<h1 className="my-section__title display-sm-semibold">{title}</h1>
<p className="my-section__desc text-md-regular">{description}</p>
<a className="my-section__link text-sm-medium">{label}</a>
<button className="my-section__btn text-md-semibold">{buttonText}</button>
```

### Responsive Prefixes (Tailwind-style)

- No prefix = mobile/base (all breakpoints)
- `sm:` = 640px+
- `md:` = 768px+
- `lg:` = 1024px+

Usage: `className="text-sm-medium md:text-md-medium lg:text-lg-medium"`
This renders `text-sm` on mobile, `text-md` on 768px+, `text-lg` on 1024px+.

### Rules

- Every visible text element MUST have a typography class in its `className`
- Component CSS handles layout, spacing, color, decoration — NOT font properties
- Only exception: elements with non-standard sizes not in the scale (e.g., 10px badge, 22px logo text) can use inline font properties in component CSS
- Use responsive prefixes (`sm:`, `md:`, `lg:`) instead of writing font-size media queries in component CSS

## Responsive Breakpoints

All components use a **mobile-first** approach with three breakpoints: **640px**, **768px**, and **1024px**.

- Base styles → Small mobile (< 640px: tightest padding, minimal layout)
- `≥ 640px` → Small tablet (slightly wider padding)
- `≥ 768px` → Tablet (hamburger menu, mobile logo size, medium padding)
- `≥ 1024px` → Desktop (full nav, desktop logo size, wider padding)

```css
/* Mobile-first: base styles are small mobile, then scale up */
.my-section__element {
  padding: 0.625rem 1rem;
}

@media (min-width: 768px) {
  .my-section__element {
    padding: 0.75rem 2rem;
  }
  /* tablet adjustments */
}

@media (min-width: 1024px) {
  .my-section__element {
    padding: 0.75rem 4.5rem;
  }
  /* full nav visible, desktop logo size, wider padding */
}
```

## CSS Units — rem Convention

**CRITICAL: Use `rem` for all spacing and sizing values. Keep `px` only for borders, border-radius, box-shadow, and outlines.**

Base: `16px = 1rem`. Figma gives pixel values — convert with `value / 16`.

### Convert to rem

- `font-size`, `line-height`
- `padding`, `margin` (all sides)
- `gap`, `row-gap`, `column-gap`
- `width`, `height`, `max-width`, `max-height`, `min-width`, `min-height`
- `top`, `right`, `bottom`, `left`
- CSS custom properties for spacing/sizing

### Keep as px

- `border`, `border-width` (1px, 2px borders)
- `border-radius`
- `box-shadow`
- `outline`
- `@media` breakpoints (640px, 768px, 1024px)

### Common Conversions (Figma px → CSS rem)

| px  | rem   |     | px  | rem   |
| --- | ----- | --- | --- | ----- |
| 4   | 0.25  |     | 24  | 1.5   |
| 6   | 0.375 |     | 28  | 1.75  |
| 8   | 0.5   |     | 30  | 1.875 |
| 10  | 0.625 |     | 32  | 2     |
| 12  | 0.75  |     | 36  | 2.25  |
| 14  | 0.875 |     | 40  | 2.5   |
| 16  | 1     |     | 48  | 3     |
| 18  | 1.125 |     | 60  | 3.75  |
| 20  | 1.25  |     | 72  | 4.5   |

```css
/* Correct */
.my-section {
  padding: 1rem 1.5rem;
  gap: 0.75rem;
}
.my-section {
  border: 1px solid var(--kombos-gray-200);
  border-radius: 6px;
}

/* Wrong */
.my-section {
  padding: 16px 24px;
  gap: 12px;
}
```

## Build Verification

IMPORTANT: After completing any task, always run `npx ikas-component build` (or `npm run build`) to check for
TypeScript and build errors. Fix any errors before considering the task done.
