How a panel looks
Lives in: themes/default.json → panel.<preset>
Presets are named looks. The story picks a preset; the theme decides size, colour, padding, name-plate docking, and how tall the box may grow before the text scrolls.
{
"panel": {
"default": {
"width": "100%",
"anchor_v": "bottom",
"min_height": 200,
"padding": { "top": 20, "left": 24, "right": 24, "bottom": 24 },
"bg": "#1e2133e0",
"corner_radius": 12
},
"whisper": {
"extends": "default",
"width": "60%",
"anchor_h": "center",
"bg": "#00000099"
},
"side_log": {
"extends": "default",
"width": "36%",
"anchor_h": "right",
"offset_x": -16,
"anchor_v": "stretch",
"max_height": "full",
"scrollbar_layout": "reserve"
}
}
}
default is the fallback preset. Other names are yours. "extends" merges another preset’s keys — Reusing settings.
Same box, two moments. The plate grows with its text, holds the name plate and portrait, and hosts choices when they appear. Continue is hidden while choices are up.
Same stage, two presets. Only the preset name changed — size, colour, and where the plate sits come from panel.<preset> in the theme.
Usually you tune
| Key | Effect |
|---|---|
width | "NN%", "100%", "stretch", or pixels |
anchor_h / anchor_v | left / center / right / stretch and top / center / bottom / stretch |
offset_x / offset_y | Nudge from the anchors (negative to move inward from right/bottom) |
min_height / max_height | Floor and ceiling — pixels, "NN%", or "full" |
padding | Inner margins |
bg | Flat plate colour |
bg_texture / bg_9slice | Nine-slice plate image (wins over flat bg) |
corner_radius | Rounded corners on the flat plate |
speaker_gap / choices_gap / choices_separation | Gaps around name and choices |
scrollbar_style | Optional element pack for the body scrollbar (else theme scrollbar.*) |
scrollbar_layout | How the scrollbar column is laid out — see below |
scroll_pin_duration | Seconds to ease to the newest line after height settles (0 = snap) |
labelplate_style_key | Which name-plate style — Name plate |
labelplate_layout | Dock the name plate to a panel edge (omit = inline above the text) |
Height and body scroll
The plate grows with text (and panel-hosted choices) up to max_height. Past that ceiling, the body text scrolls inside the plate. Name plate, panel-placed Continue / Back, and choices stay outside the scroll area.
| Height value | Meaning |
|---|---|
| number | Pixels |
"40%" | Share of window height |
"full" | Window height |
omit min_height | 160 |
omit max_height | Default share of the window (same idea as before: about 65%, with a floor from min_height) |
A sticky { "type": "panel", "max_height": … } overrides the theme preset until reset.
Scrollbar column
scrollbar_layout | Effect |
|---|---|
default (omit) | Bar appears when needed and takes width from the text when it does |
reserve | Keep a scrollbar column so wrap width stays stable; track stays hidden until there is something to scroll |
overlay | Not available yet — falls back to default |
Use reserve on logs, phone panels, or any fixed-height plate that scrolls often. Leave normal ADV boxes on default.
Panel-hosted choices (host: "panel") share the plate and shrink the body. Overlay choices sit on the screen and do not take body space. A choice list taller than the ceiling can still clip — body scroll is for dialogue text, not a separate choice scroller.
Mood for one scene
A scene can load another theme/mood file that overrides panel presets for that stretch — Theme and the dialogue box. Otherwise, prefer a second preset (whisper) or a sticky panel command.
Bind and shader
A panel command can tint or hide from flags (bind on opacity / visible) and attach a panel shader. Flag binds in depth: Reacting to flags live.
Usually you need
| Want | Do |
|---|---|
| Full-width bottom box | default with anchor_v: "bottom", width: "100%" |
| Narrow centre whisper | Preset with smaller width + anchor_h: "center" |
| Tall side log | max_height: "full" + scrollbar_layout: "reserve" — Several panels |
| Reuse most of default | "extends": "default" then override a few keys |