This "Core Concepts" guide will walk you through building a scene from scratch, demonstrating how **Tesserax** handles shapes, positioning, and composition.

## The Canvas and the First Shape

Every drawing starts with a `Canvas`. In Tesserax, the `Canvas` acts as the root container and provides a context manager to automatically add shapes created within its block.

We will start by creating a simple 100x50 rectangle.

```{python}
from tesserax import Canvas, Rect

# Initialize the canvas
with Canvas() as canvas:
    # Adding our first shape
    # Primitives support standard SVG attributes like fill
    Rect(100, 50, fill="lightblue")

# fit() adjusts the viewport to the content
# display() renders it directly in the documentation
canvas.fit(padding=10).display()

```

## Adding and Transforming Shapes

While you can add shapes and manually set their coordinates, Tesserax provides a fluent API for transformations. Here, we add a `Circle` and use `translated()` to move it into position.

```{python}
from tesserax import Canvas, Rect, Circle

with Canvas() as canvas:
    Rect(100, 50, fill="lightblue")

    # Adding a second shape and moving it manually
    # Circle is defined by its radius
    Circle(30, fill="salmon").translated(150, 25)

canvas.fit(padding=10).display()

```

## Simplifying with Layouts

Manually calculating offsets (like the `150, 25` above) becomes tedious in complex diagrams. **Layouts** automate this positioning. The `Row` layout arranges its children horizontally with an optional `gap`.

```{python}
from tesserax import Canvas, Rect, Circle
from tesserax.layout import Row

with Canvas() as canvas:
    # Row is also a context manager
    with Row(gap=20):
        Rect(100, 50, fill="lightblue")
        Circle(30, fill="salmon")

canvas.fit(padding=10).display()

```

## Composing Transforms and Groups

Because Layouts are themselves a type of `Group`, you can apply transformations to the entire layout at once. In this step, we will:

1. Create a `Row` layout.
2. Rotate that entire row by 45 degrees.
3. Add a new shape outside of that row.
4. Wrap everything in another `Group` to demonstrate hierarchical composition.


```{python}
from tesserax import Canvas, Rect, Circle, Group
from tesserax.layout import Row

with Canvas() as canvas:
    # Create and rotate a layout
    with Row(gap=20).rotated(45):
        Rect(100, 50, fill="lightblue")
        Circle(30, fill="salmon")

    # Add another shape to the scene
    Rect(40, 40, fill="lightgreen").translated(100, -50)

    # All shapes here are already part of the Canvas group.

canvas.fit(padding=10).display()

```

By nesting Layouts and Groups, you can build extremely complex diagrams without ever having to manually compute a single SVG coordinate string.

## Bridging Contexts with Anchors

One of the most powerful features of Tesserax is the **Anchor System**. When you place a shape inside a `Layout` or a `Group`, its local coordinates change to reflect its position within that container. However, Tesserax allows you to retrieve the "global" position of a shape's anchors, making it trivial to connect objects across different coordinate systems.

In this example, we will connect the `Circle` (which is inside a rotated `Row`) to the `Rect` (which is outside) using an `Arrow`, and the two shapes inside the row.

```{python}
from tesserax import Canvas, Rect, Circle, Arrow
from tesserax.layout import Row

with Canvas() as canvas:
    # 1. Create a Row and rotate it
    with Row(gap=40) as row:
        r1 = Rect(80, 40, fill="aliceblue")
        c1 = Circle(30, fill="mistyrose")

    row.rotated(30).translated(50, 50)

    # 2. Create a target rectangle outside the layout
    target = Rect(60, 60, fill="honeydew").translated(250, 0)

    # 3. Connect them!
    # We use .anchor() to get semantic points.
    # Even though c1 is inside a rotated row, c1.anchor("right")
    # returns the correct global coordinate for the arrow.
    Arrow(
        c1.anchor("top").dy(5),
        target.anchor("left").dx(-5),
        stroke="grey",
        width=2,
    )

    Arrow(
        r1.anchor("right").dx(5),
        c1.anchor("left").dx(-5),
        stroke="grey",
        width=2,
    )

canvas.fit(padding=10).display()
```

### How Coordinate Mapping Works

When you call `shape.anchor(name)`, Tesserax performs the following behind the scenes:

1. **Local Geometry**: It identifies the point on the shape (e.g., the rightmost edge of the `Circle`).
2. **Transformation Path**: It traverses up the hierarchy (from the `Circle` to the `Row`, then to the `Canvas`), applying every rotation, scale, and translation encountered along the way.
3. **Global Result**: It returns a `Point` that represents exactly where that anchor sits on the final SVG canvas.

This means you never have to manually calculate `sin()` or `cos()` to find where a rotated object's edge is located—you just ask for the anchor.

For explicit anchoring, you can use `Shape.resolve(p: Point)` to map a point in local space to the global space, this way you can, e.g., get the point at 2/3rds of the way inside a rectangle and map it to global space.
