# Agent guide - drawing, layout, and effects

## Choose a composition boundary

Read [layout](/guides/compose-and-layout/), [drawing styles](/guides/style-and-draw/), and [responsive styles](/guides/responsive-styles/) before adapting a scene. A `Group` is not an HTML layout container. Choose `Absolute` for independently placed children, `Overlay` for a shared allocation, `Flow` for sequential layout, `Flex` for the supported flex subset, or `Grid` for explicit tracks and one-based placements. Grid auto-placement is not supported.

`Group`, `Clip`, and `Layer` preserve source paint order. A Layer is an explicit retained bitmap boundary. Do not assume ordinary components cache their pixels or that Pibbl automatically promotes expensive content into layers.

## Coordinates and ownership

| Space            | Meaning                                       | Read it from                                  |
| ---------------- | --------------------------------------------- | --------------------------------------------- |
| Logical root     | Scene units and Pibbl pointer event coordinates | Canvas configuration; event `x` and `y`       |
| Local allocation | Finite space assigned by a parent             | `useLayoutBox()` during component evaluation  |
| CSS display      | Browser content-box dimensions                | The HTML host's layout                        |
| Backing pixels   | Raster storage at selected density            | Canvas width/height, owned by Pibbl after mount |

A fixed viewport defaults to the canvas's initial attributes and centered contain fitting. A responsive viewport uses CSS content-box pixels as logical units and does not accept `fit`. The default density tracks the device; a numeric density is fixed. Set explicit CSS dimensions and let Pibbl own backing-store resizing. A zero-sized responsive host suspends presentation until positive dimensions return.

The child receives declared author style, not a mutated layout result. Read its computed allocation with `useLayoutBox`. Parent placement uses `left`/`top`; drawing-local geometry uses `x`/`y`. Forwarding `{ ...style }` follows the documented placement-consumption rule. An independently constructed style object is local geometry even if its numeric offsets happen to match the parent.

## Effects and limitations

Use real factories from `@pibbl/core/filters`, not invented objects such as `{ type: 'blur' }`. A filter captures the receiving primitive and descendants as one silhouette. Lists execute forward; nesting executes inside out. Filters affect pixels only: hit testing, measurement, layout, and focus use original geometry. See [filter options and exact units](/reference/types/filters/).

HTML from HtmlBox stays above Canvas and cannot join a Canvas filter or blend silhouette. External render layers are flattened pixels at one position in paint order. Pibbl does not capture live DOM. Clipping does not implement scrolling. Margins, reverse/reordered flex, intrinsic CSS layout, and auto-grid placement are not implied by familiar names.

## Complete example and adaptation

The source below is the existing Flex lesson. It mounts on a 720 by 420 canvas and uses `useLayoutBox` to draw within assigned allocations. [Open Flex](/playground/#/examples/layout/flex). Change one width, growth factor, or gap at a time and inspect resulting allocations before applying filters.

Use `@pibbl/core` as the JSX import source; retain and dispose the default mount's controller. No image asset is required. For custom shapes, use the appropriate public path/shape reference rather than reaching into `lib/`.

## Verification

Measure root and child rectangles at two host sizes and a higher pixel density. Assert finite nonnegative allocations and correct logical placement. Exercise zero size followed by restore. Confirm an unchanged mount retains its state through resize.

Test a target before and after blur: the soft halo must not become a larger hit area. Check transformed/clipped pointer targeting in root-logical coordinates. Capture screenshots only after those geometry assertions pass. A filter comparison should hold geometry, fill, viewport, and density constant.

If content is doubled in position, inspect style forwarding. If it appears stretched, inspect fixed fit versus responsive allocation. If text clips, inspect actual font metrics and allocated bounds rather than scaling all typography with viewport width.

## Complete source

Host setup for this source: use a canvas with width 720 and height 420, compile with `jsx: "react-jsx"` and `jsxImportSource: "@pibbl/core"`, import its default `mount`, and call `const controller = mount(canvas)` after attaching the canvas. Call `controller.dispose()` before removing it.

### flex.example.tsx

```tsx
import {
  pibbl,
  useLayoutBox,
  useSignal,
  Flex,
  Rectangle,
  Text,
  type BoxStyle,
  type PibblController,
  type FlexItemStyle,
} from "@pibbl/core";

interface FlexCardProps {
  onSelect: () => void;
  side: "left" | "right";
  style: BoxStyle & FlexItemStyle;
}

function FlexCard({ onSelect, side, style: _specifiedStyle }: FlexCardProps) {
  const box = useLayoutBox();

  return (
    <Rectangle
      style={{
        width: box.width,
        height: box.height,
        fill: side === "left" ? "#1f4bd8" : "#ff6b57",
        stroke: "#17211d",
        strokeWidth: 4,
        cursor: "pointer",
      }}
      onClick={onSelect}
    />
  );
}

function FlexStudy() {
  const active = useSignal<"left" | "right">("left");
  return [
    <Rectangle
      style={{
        width: 720,
        height: 420,
        fill: "#f7f0df",
      }}
    />,
    <Flex
      style={{
        width: 560,
        height: 260,
        padding: 80,
        gap: 18,
        alignItems: "center",
      }}
    >
      {(["left", "right"] as const).map((side) => (
        <FlexCard
          key={side}
          onSelect={() => active.set(side)}
          side={side}
          style={{
            width: 170,
            height: active.get() === side ? 190 : 140,
            minWidth: 90,
            flexBasis: 170,
            flexGrow: active.get() === side ? 2 : 1,
            flexShrink: 1,
          }}
        />
      ))}
    </Flex>,
    <Text
      style={{
        left: 360,
        top: 54,
        fill: "#17211d",
        font: "900 20px sans-serif",
        textAlign: "center",
      }}
    >
      {"GROW · SHRINK · ALIGN"}
    </Text>,
  ];
}
export default function mount(canvas: HTMLCanvasElement): PibblController {
  return pibbl(canvas, <FlexStudy />);
}

```

## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
