diff --git a/apps/mapgen-studio/src/features/configOverrides/rjsfTemplates.tsx b/apps/mapgen-studio/src/features/configOverrides/rjsfTemplates.tsx
index 7a995ab42f..701075874f 100644
--- a/apps/mapgen-studio/src/features/configOverrides/rjsfTemplates.tsx
+++ b/apps/mapgen-studio/src/features/configOverrides/rjsfTemplates.tsx
@@ -14,7 +14,13 @@ export type BrowserConfigFormContext = {
// tokens (`card`/`muted`/`border`/`accent`/…), so there is no `lightMode` read.
const FORM = {
card: "bg-card border-border",
- nested: "bg-muted/40 border-border-subtle",
+ // Group well: nesting is a surface, not an indent (Pass-3 config-surface
+ // spec). One recess below the stage card — tinted toward the page token so
+ // groups read as machined slots in the slate. `background` sits below `card`
+ // in BOTH themes (5%<9% dark, 96%<100% light), so the tint recesses in both.
+ // Two surface tiers maximum: card → well; deeper nesting adds headings and
+ // rhythm only, never a third surface.
+ well: "bg-background/40 border-border-subtle",
divider: "border-border",
// Field labels sit a full tier above prose (Pass-2 form hierarchy): labels are
// foreground anchors the eye scans; descriptions/help/gs-comments recede on the
@@ -25,6 +31,19 @@ const FORM = {
text: "text-foreground",
borderSubtle: "border-border-subtle",
button: "bg-muted text-foreground border-border hover:bg-accent",
+ // Group headings are eyebrows: the well's geometry carries the grouping, so
+ // its caption recedes below field labels (the brightest scan line in a card).
+ groupHeading: "text-label font-semibold uppercase tracking-wider text-muted-foreground",
+ subGroupHeading: "text-label font-semibold uppercase tracking-wider text-muted-foreground/70",
+ // Rhythm on the 4px base (Pass-3): 4px inside a field block, 8px between
+ // sibling fields, 12px between groups/stage sections. Group wells carry
+ // `my-1`, which composes with the sibling gap to the 12px group step.
+ rhythm: {
+ field: "gap-1",
+ siblings: "gap-2",
+ sections: "gap-3",
+ groupPull: "my-1",
+ },
} as const;
function humanizeSchemaLabel(label: string): string {
@@ -85,7 +104,7 @@ export function BrowserConfigFieldTemplate(
if (!showLabel) {
return (
-