# Claude Code Guidelines

## Project Overview

This is a SvelteKit 2.x application using Svelte 5 with Tailwind CSS v4.

## Code Style Rules

### SVG Attributes

When using SVG elements, use `style` attribute instead of `fill` attribute to avoid IDE obsolete attribute warnings:

```svelte
<!-- Correct -->
<svg style="fill: currentColor" ...>
<svg style="fill: none" ...>

<!-- Incorrect (triggers obsolete attribute warning) -->
<svg fill="currentColor" ...>
<svg fill="none" ...>
```

### Svelte 5 Runes

- Use `$state()` for reactive state
- Use `$derived()` for computed values
- Use `$props()` for component props
- Use `$effect()` for side effects

### Page Store

Use `$app/state` instead of `$app/stores` for the page object:

```svelte
<!-- Correct -->
import {page} from '$app/state'; const path = page.url.pathname;

<!-- Incorrect -->
import {page} from '$app/stores'; const path = $page.url.pathname;
```

### Theme Classes

Use the custom theme utility classes defined in `layout.css`:

- `text-theme`, `text-theme-secondary`, `text-theme-muted`
- `bg-theme`, `bg-theme-card`
- `border-theme`
- `shadow-theme`, `shadow-theme-lg`

### Hover/Active States

Use consistent hover/active patterns:

```
hover:bg-black/5 dark:hover:bg-white/10
active:bg-black/10 dark:active:bg-white/15
```

### Mobile Grid Layouts

For card grids that should display single-column on mobile and multi-column on larger screens, always:

1. Explicitly set `grid-cols-1` (don't rely on CSS grid's implicit single column)
2. Add `min-w-0` on grid items with flex content to allow proper shrinking

```svelte
<!-- Correct -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
	<div class="card-example flex min-w-0 items-center justify-between">
		<div class="min-w-0 flex-1">...</div>
	</div>
</div>

<!-- Incorrect (may overflow on mobile) -->
<div class="grid gap-4 sm:grid-cols-2">
	<div class="card-example flex items-center justify-between">...</div>
</div>
```

### Button Element Content

Button elements can only contain phrasing content (inline elements). Use `<span>` instead of `<div>`, `<p>`, or `<h1>`-`<h6>` inside buttons:

```svelte
<!-- Correct -->
<button>
	<span class="flex items-center gap-2">
		<span>Click me</span>
	</span>
</button>

<!-- Incorrect (triggers HTML validation warning) -->
<button>
	<div class="flex items-center gap-2">
		<p>Click me</p>
	</div>
</button>
```

For multi-line button content, use `<span class="block">` to create line breaks:

```svelte
<button>
	<span class="flex items-center gap-2">Title</span>
	<span class="text-muted block text-sm">Subtitle on new line</span>
</button>
```

### SvelteSet Reactivity

`SvelteSet` from `svelte/reactivity` is already reactive and does NOT need to be wrapped in `$state()`:

```svelte
<!-- Correct -->
import { SvelteSet } from 'svelte/reactivity';
let expandedItems = new SvelteSet<string>();

<!-- Incorrect (unnecessary wrapper) -->
let expandedItems = $state(new SvelteSet<string>());
```

### Each Block Keys

Always provide a key for `{#each}` blocks to avoid ESLint warnings:

```svelte
<!-- Correct -->
{#each items as item (item.id)}
{#each days as day (day)}

<!-- Incorrect -->
{#each items as item}
```

### Date Formatting

Use the date utilities from `$lib/utils/date` which use `date-fns` to properly handle ISO date strings without timezone offset issues:

```svelte
import {formatDate} from '$lib/utils/date';

<!-- Returns empty string for null/undefined, so add fallback -->
{formatDate(startDate) || '—'}
```

### File Organization

- Place `.svelte.ts` files (stores, shared state) in `src/lib/stores/`, not in component folders
- GraphQL mutations go in `src/lib/graphql/mutations/{entity}/`
- GraphQL queries go in `src/lib/graphql/queries/{entity}/`

### Backend Integration Notes

- The backend uses a unique constraint allowing only ONE active scope per address
- The `isConditional` field on tasks is legacy and should always be set to `false`
- GraphQL inputs use camelCase (e.g., `isActive`, `accountId`) which maps to snake_case in Django

### Task Frequency Values

The backend `TaskFrequencyChoices` enum uses **lowercase** values. Handle frequency differently depending on the operation:

**Individual mutations** (create/update task or task template) - use lowercase:

```typescript
frequency: 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'triannual' | 'annual' | 'as_needed';
```

**JSON import** (`createScopeTemplateFromJson`) - uppercase is acceptable:

```json
{ "frequency": "DAILY" }
```

The backend's `build_scope_template` service normalizes uppercase to lowercase automatically.

Valid frequency values: `daily`, `weekly`, `monthly`, `quarterly`, `triannual`, `annual`, `as_needed`
