npm package: @sprig-and-prose/sprig-texture
Description: Procedurally generated, calm background textures
Latest version: 0.1.0

# sprig-texture

Procedurally generated, calm, parasympathetic background textures for use across projects.

## Purpose

This library generates seamless, tiling textures designed to:
- Eliminate gradient banding and grid artifacts
- Provide subtle "paper / watercolor surface" material
- Create calm, non-distracting backgrounds
- Be deterministic (same key = same texture)

**Important**: This library generates neutral material textures. Lighting, vignettes, and mood gradients belong in CSS, not in the texture bitmap.

## Usage

```javascript
import { generateTexture, releaseObjectUrl, nightInk, bloom } from 'sprig-texture';

const { canvas, blob, url } = await generateTexture({
  key: 'my-unique-key',
  palette: nightInk,
  preset: bloom,
});

// Use the URL as a background image
element.style.backgroundImage = `url(${url})`;
element.style.backgroundRepeat = 'repeat';
element.style.backgroundSize = '1024px 1024px';

// Clean up when done (prevents memory leaks)
releaseObjectUrl(url);
```

## Determinism

Textures are deterministic: the same `key` + `palette` + `preset` will always produce the same texture. This allows caching and consistent rendering across sessions.

## Palettes

- **nightInk**: Dark blue-gray tones (default)
- **parchment**: Warm paper tones

## Presets

- **quiet**: Minimal variation, subtle
- **bloom**: Slightly richer, more variation (default)

## Watercolor Stroke CSS

This package includes a reusable CSS module for creating watercolor brush stroke effects, perfect for highlighting keywords, badges, or decorative elements.

### Importing the CSS

```css
/* In your CSS file */
@import 'sprig-texture/src/styles/watercolor-stroke.css';
```

Or in JavaScript/TypeScript (if your bundler supports CSS imports):

```javascript
import 'sprig-texture/src/styles/watercolor-stroke.css';
```

### Basic Usage

Apply the `.watercolor-stroke` class to an element and set CSS variables for color and opacity:

```html
<span class="watercolor-stroke" style="--watercolor-pigment-color: rgba(50, 80, 160, 1); --watercolor-opacity: 0.30;">
  COLLECTS
</span>
```

The effect is applied via a `::before` pseudo-element, so ensure your element has `position: relative`:

```css
.my-badge {
  position: relative;
  display: inline-block;
  padding: 0.1rem 0.45rem;
}
```

### Using Pre-configured Variants

The CSS includes several pre-configured color variants that you can use via data attributes:

```html
<span class="watercolor-stroke" data-variant="collects">COLLECTS</span>
<span class="watercolor-stroke" data-variant="expands">EXPANDS</span>
<span class="watercolor-stroke" data-variant="optional">OPTIONAL</span>
<span class="watercolor-stroke" data-variant="aggregates">AGGREGATES</span>
```

### Customizing Colors

Override the CSS variables to use your own colors:

```css
.custom-stroke {
  --watercolor-pigment-color: rgba(120, 60, 200, 1);
  --watercolor-opacity: 0.35;
}
```

### Adjusting Stroke Position

The stroke position is controlled by four CSS properties on the `::before` pseudo-element. To adjust the position, override these values:

```css
.my-element::before {
  top: -1.2rem;      /* move stroke DOWN = make this LESS negative */
  bottom: -0.54rem;   /* move stroke UP   = make this MORE negative */
  left: -0.80rem;
  right: -0.80rem;
}
```

### How It Works

The watercolor effect is created using:
- **Radial gradients** for the pigment color distribution
- **Clip-path polygon** for the wavy brush stroke shape
- **Blur filter** for soft edges
- **Mix-blend-mode: screen** for the watercolor blending effect
- **Subtle transforms** (rotate, skew) for natural variation

## Design Principles

1. **Texture ≠ lighting**: The generated bitmap is neutral material; CSS handles mood
2. **Micro-variation prevents banding**: Multi-scale noise (low, mid, high frequency)
3. **Subtlety over effect**: Everything should be "barely there"
4. **Forgiving defaults**: `generateTexture({ key })` should look good

## Layers

The texture is generated in 5 layers:

1. **Base fill**: Palette-driven base color
2. **Ultra-low-frequency tone drift**: Very large radial washes to prevent flat regions
3. **Mid-frequency mottling**: Soft radial blobs for material variation
4. **Paper grain / speckles**: Soft dots for texture and anti-banding
5. **Fiber strokes**: Thin strokes with vertical bias

All layers tile seamlessly.

## API

### `generateTexture(args)`

Generates a texture and returns a Promise resolving to `{ canvas, blob, url }`.

- `args.key` (string, required): Deterministic seed key
- `args.size` (number, optional, default: 1024): Canvas size (square)
- `args.palette` (Palette, optional): Color palette (default: `nightInk`)
- `args.preset` (Preset, optional): Numeric parameters (default: `bloom`)

### `releaseObjectUrl(url)`

Releases an object URL created by `generateTexture()`. Call this when you're done using the texture to prevent memory leaks in long-running sessions.

## Examples

See `examples/demo.html` for a working demo with controls.

To run the demo, start a local server:

```bash
npm run serve
```

Then open http://localhost:3000/examples/demo.html in your browser.

Alternatively, you can use any static file server:
- `npx serve .` (if you have `serve` installed)
- `python3 -m http.server 8000` (Python 3)
- Or any other static file server