`genericapi` ran every response body through `JSON.parse`, falling back to
the raw text only when that threw. The nfproxy filter source is served as a
PlainTextResponse, so a filter file that happens to be valid JSON came back
as a number/array/object. Mantine's CodeHighlight then calls `code.trim()`
on it, which throws and takes the whole page down with it. `42`, `"abc"`,
`[1,2]` and `{"a":1}` are all both valid JSON and valid Python, so they
pass the upload validation and leave the service page unreachable.
Responses declaring text/plain are no longer parsed, and the render site
type-checks the code before handing it to CodeHighlight.
The Card carried Mantine's `w="100%"` prop, whose style props land in the
style attribute after anything passed via `style`, so it overrode the pixel
width dnd measures at lift time. On a `position: fixed` element `100%`
resolves against the viewport rather than the list, so grabbing a rule
snapped the card from 734px to 798px and pushed it past the right edge.
Moving the width into `style`, ahead of the dnd spread, leaves normal flow
untouched and lets the measured width win while dragging.
Three separate defects made the rule list impossible to reorder:
- The Card's own `style` was placed after `{...provided.draggableProps}`,
clobbering the `position`/`transform` dnd sets while dragging. The drag
did start, but nothing moved on screen. Styles are now merged with dnd's
winning, and the dragged card is highlighted.
- `Draggable index` used the position in the full `state` array and the
rules of the other table were filtered out afterwards, leaving gaps.
dnd requires contiguous indexes from 0 inside a Droppable, so a single
rule in the other table broke the visible tab entirely. Visible rules
are now re-indexed and mapped back to their `state` position on drop.
- `destination?.index || 0` reordered to the top instead of doing nothing
when a rule was dropped outside the list.