Place AC between initiative and name to group static reference
stats on the left, leaving HP as the sole dynamic element on
the right. Dim the shield outline to 40% opacity so it recedes
visually, and nudge the number up 2px toward the visual center.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Group current HP, temp HP, and max HP into a single bordered
pill container with a subtle slash separator. Removes the
scattered layout with separate elements and gaps. Temp HP +N
only renders when present (no invisible spacer).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Temp HP absorbs damage before current HP, cannot be healed, and
does not stack (higher value wins). Displayed as cyan +N after
current HP with a Shield button in the HP adjustment popover.
Column space is reserved across all rows only when any combatant
has temp HP. Concentration pulse fires on any damage, including
damage fully absorbed by temp HP.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Render condition picker via React portal with fixed positioning so it
is no longer clipped by the overflow-y-auto combatant list container.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Name click now opens/collapses the stat block panel; a hover-visible
pencil icon next to the name handles renaming. Removes the standalone
book icon for a cleaner, more intuitive combatant row.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Right-click or long-press the d20 button (per-combatant or Roll All)
to open a context menu with Advantage and Disadvantage options.
Normal left-click behavior is unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow OS color scheme by default, with a three-way toggle
(System / Light / Dark) in the kebab menu. Light theme uses warm,
neutral tones with soft card-to-background contrast. Semantic colors
(damage, healing, conditions) keep their hue across themes.
Closes#10
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use Book/BookOpen icons to indicate stat block open state
- Bump combatant icons (bestiary + PC) from 14px to 16px
- Use text-foreground for bestiary icon visibility
- Auto-update stat block panel to active combatant's creature on turn advance
- Update bestiary spec edge case to reflect new behavior
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a user clicks the d20 to roll initiative for a single combatant whose
bestiary source isn't cached, show an informative toast and open the stat
block panel so they can load the source directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the side panel is in its initial closed state (not user-collapsed),
adding a combatant from the bestiary now opens the panel to show its
stat block. This makes the panel discoverable without overriding a
deliberate collapse.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Apply a soft blue radial glow centered on the viewport to add depth
to the dark background, replacing the flat solid color.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Give all combatant rows a consistent border-l-2 + border on all sides
(transparent when inactive) so toggling active/concentration states
never changes the row's box size. Show purple left border when a
combatant is both active and concentrating.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cap the editable name input at max-w-48 so it doesn't stretch the
full column width and push icons/conditions onto separate lines.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Increase radius-md from 6px to 8px and radius-lg from 8px to 12px
for a more modern, polished look on buttons, inputs, and card surfaces.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shift the dark theme from neutral gray to a richer blue-tinted palette
inspired by CharBuilder-style TTRPG apps. Deeper navy background, steel-blue
card surfaces, and visible blue borders create more depth and visual layering.
- Update design tokens: background, card, border, input, muted colors
- Add card-glow utility (radial gradient + blue box-shadow) for card surfaces
- Add panel-glow utility (top-down gradient) for tall panels like stat blocks
- Apply glow and rounded-lg to all card surfaces, dropdowns, dialogs, toasts
- Give outline buttons a subtle fill instead of transparent background
- Active combatant row now uses full border with glow instead of left accent
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tailwind v4's static extractor missed classes adjacent to ${} in template
literals (e.g. `pb-8${...}`), causing missing styles in production builds.
Migrated all dynamic classNames to cn() and added a check script to prevent
regressions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Buttons should declare their own text color rather than relying on
inheritance, which breaks in contexts like native <dialog>. Remove
the text-foreground workaround from the dialog elements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tailwind v4 preflight resets dialog margins and color inheritance.
Add m-auto to restore showModal() centering, and text-foreground
so ghost buttons inherit the correct color.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use h-dvh (100dvh) instead of h-screen (100vh) so the layout
accounts for browser chrome (address bar, bottom toolbar).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The _copy field is a real property in the raw bestiary JSON — adding it
to the interface is more accurate than casting through any. Ratchet
source ignore threshold from 3 to 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the for-loop with await-in-loop with a .reduce() chain that
sequences Promise.allSettled batches without triggering the lint rule.
Ratchet source ignore threshold from 4 to 3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 250ms click timer and double-click detection with immediate
single-click rename for all combatant types. Add a BookOpen icon before
the name on bestiary rows as the dedicated stat block trigger. Remove
auto-show stat block on turn advance. Update specs to match: consistent
collapse/expand terminology, book icon requirements, no row-click stat
block behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds scripts/check-lint-ignores.mjs with four enforcement mechanisms:
ratcheting count cap (12 source / 3 test), banned rule prefixes,
required justification, and separate test thresholds. Wired into
pnpm check.
Converts player-management and create-player-modal from div-based
modals to native <dialog> with showModal()/close(), removing 8
biome-ignore comments. Remaining ignores are legitimate (Biome
false positives or stopPropagation wrappers with no fitting role).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 integration tests render the full <App /> and exercise multi-component
flows: add/remove combatant, turn tracking across two combatants, and
HP adjustment with unconscious state. Add aria-label to the clickable HP
button so tests query accessible names instead of CSS classes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds threshold entries for application, hooks, components, and components/ui
directories. Ratchets existing thresholds to match actual coverage. Excludes
**/dist/** from coverage to remove build output noise.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds aria-label attributes to HP placeholder and source delete buttons
for both accessibility and testability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
29 tests covering state transitions, persistence sync, domain error
propagation, bestiary/PC add flows, and panel state machine logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests verify the get→call→save wiring and error propagation for each
use case. The 15 formulaic use cases share a test file; rollInitiative
and rollAllInitiative have dedicated suites covering their multi-step
logic (creature lookup, modifier calculation, iteration, early return).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mark component props as Readonly<> across 15 component files and
simplify edit-player-character field access with optional chaining
and nullish coalescing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace escaped backslash in template literal with String.raw in
auto-number.ts. Use RegExp#exec() instead of String#match() in
bestiary-adapter.ts. Enable typescript/prefer-regexp-exec in oxlint
for automated enforcement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Install oxlint with tsgolint for TypeScript type information. Enable
rules for unnecessary type assertions, deprecated API usage, preferring
replaceAll over replace with global regex, and String.raw for escaped
backslashes. Fix all violations: remove redundant as-casts, replace
deprecated FormEvent with SubmitEvent, convert replace(/g) to
replaceAll, and use String.raw in escapeRegExp. Add oxlint to the
pnpm check gate alongside Biome.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Store creature map in useState instead of useRef with a dummy
tick counter. React now re-renders naturally when the map changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Source rows disappear immediately when cleared instead of waiting
for the IndexedDB operation to complete. Real state syncs after.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defer rendering of bestiary suggestions and player character matches
in ActionBar so the input stays responsive as the bestiary grows.
Keyboard navigation and selection logic still use the latest values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Relocate isEmpty, hasCreatureCombatants, and canRollAllInitiative
from App.tsx into useEncounter(), reducing inline derivations in
the component (Phase 5 of App decomposition plan).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>