# `MishkaChelekom.CSS`
[🔗](https://github.com/mishka-group/mishka_chelekom/blob/v0.0.9/lib/mishka_chelekom/css.ex#L1)

Tailwind-aware class composition with a **swappable merge seam** (Layer 3).

`classes/1` flattens nested/conditional class inputs (the same shapes HEEx accepts) into a
single deduplicated string — last occurrence wins, so a caller's `@class` reliably overrides
defaults. This is the zero-dependency built-in default.

For real Tailwind conflict resolution (e.g. `px-2` vs `px-4`), point the seam at a
`tailwind_merge`-style library:

    config :mishka_chelekom, :class_merger, {TailwindMerge, :merge, 1}

The configured merger is resolved at runtime via `Application.get_env/3`; when unset, the
built-in `dedupe/1` is used. This mirrors Pyro's approach and keeps the dependency optional.

# `input`

```elixir
@type input() :: String.t() | [input()] | nil | false | {boolean(), input()}
```

# `classes`

```elixir
@spec classes(input()) :: String.t()
```

Flattens and merges class inputs into a single class string.

Accepts strings, nested lists, `nil`/`false` (dropped), and `{condition, classes}` tuples.

    iex> MishkaChelekom.CSS.classes(["px-2 py-1", nil, {true, "font-bold"}, {false, "hidden"}])
    "px-2 py-1 font-bold"

# `dedupe`

```elixir
@spec dedupe(String.t()) :: String.t()
```

Built-in default merger: collapses whitespace and removes exact duplicate tokens, keeping
the **last** occurrence so later (caller) classes win. Does not resolve Tailwind utility
conflicts — adopt `tailwind_merge` via the seam for that.

# `merge`

```elixir
@spec merge(String.t()) :: String.t()
```

Runs the configured class merger over a space-separated class string. Defaults to
`dedupe/1` (token de-duplication, last wins) when no `:class_merger` is configured.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
