Audit caught Carousel ignored direction entirely: `getDirectionalKeys`
received a hardcoded `'ltr'` so ArrowLeft / ArrowRight had the same
semantics under RTL as LTR, and the horizontal translate had no
RTL flip so slides advanced the wrong way visually. Drag direction had
the same bug.
## Soma
- New `dir` + `locale` props on `Carousel.Provider` (fall back to
`soma.prefs.getDir()` then `'ltr'`).
- `onkeydown` now reads `this.opts.dir.current` for `getDirectionalKeys`.
- `itemGroupTransform` flips the translate sign on horizontal RTL so
index N→N+1 moves the rail in the reading-direction-appropriate way.
- `finishDrag` swaps the offset sign on horizontal RTL so drag-right
advances under RTL (drag-left under LTR).
- Root stamps `dir="..."`, `lang="..."`, and `data-dir="..."` for
consumers and the recipe.
- Test mocks updated.
## Demos
- Carousel demo: new `soma · i18n` controls section — `dir` chips
(`auto` / `ltr` / `rtl`) + `locale` chips covering en/es/ar/he/ja so
the user can flip orientation semantics live.
- Range-calendar demo: same `dir` + `locale` chip rows added next to
`weekStartsOn`; previously only `locale` was state-bound but the
control wasn't surfaced and `dir` wasn't forwarded at all.
- The eidos code snippet preview emits `dir="..."` and `locale="..."`
attrs when they differ from defaults.
## Verified
Browser walk: with `dir="rtl"`, the carousel root reports
`data-dir="rtl"`, prev/next chevrons swap sides, indicator order
mirrors, and `ArrowRight` correctly advances to the *previous* slide
(index 1 → 0).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>