

The surface system is how Cubitt keeps nested UI from flattening into the same background. Consumers declare the surface level only where the app paints its own boundary. Cubitt components then move relative to that level and pass the computed level to their children.

## Surface Levels [#surface-levels]

Use odd-numbered levels for major surfaces and even-numbered levels for interaction states.

| Level       | Role                                                       |
| ----------- | ---------------------------------------------------------- |
| `surface-1` | Main product inset or full-screen workspace                |
| `surface-2` | Hover, focus, or row state on `surface-1`                  |
| `surface-3` | App shell, sidebar, page chrome, or card above `surface-1` |
| `surface-4` | Hover, focus, or row state on `surface-3`                  |
| `surface-5` | Popover, panel, or floating content above `surface-3`      |
| `surface-6` | Hover, focus, or row state on `surface-5`                  |
| `surface-7` | Menu or deeply nested floating content                     |
| `surface-8` | Hover, focus, or row state on `surface-7`                  |

<Preview name="SurfaceNestingExample" />

## Ownership Model [#ownership-model]

Consumers set surface context only at app-owned painted boundaries. If the app
shell is built with Cubitt's sidebar components, `SidebarProvider` is that
painted boundary and owns the shell context. It defaults to shell `surface-3`
in light mode and shell `surface-2` in dark mode. `SidebarInset` defaults to
`surface-1` in both modes. Custom app shells should still pair their painted
background with `SurfaceProvider`.

| Boundary                           | Consumer responsibility                                                                                        |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Cubitt sidebar app shell           | Use `SidebarProvider`; pass `surfaceLevel` only when the shell should use a non-default level or theme mapping |
| Custom app root or shell           | Pair the painted `bg-surface-*` class with `SurfaceProvider level={n}`                                         |
| App-owned inset or workspace reset | Add a nested provider only when the app paints a new root surface                                              |
| Custom app-owned panel             | Use `SurfaceProvider` or `Surface` if the custom panel contains Cubitt components                              |
| Cubitt-owned components            | Do not add a provider; Cubitt advances or resets context internally                                            |

```tsx
import {
  SidebarInset,
  SidebarProvider,
} from "@tilt-legal/cubitt-components/sidebar";

export function SidebarAppShell({ children }: { children: React.ReactNode }) {
  return (
    <SidebarProvider>
      <AppSidebar />
      <SidebarInset>{children}</SidebarInset>
    </SidebarProvider>
  );
}
```

```tsx
import { SurfaceProvider } from "@tilt-legal/cubitt-components/utilities";

export function CustomAppShell({ children }: { children: React.ReactNode }) {
  return (
    <SurfaceProvider level={3}>
      <div className="min-h-screen bg-surface-3">
        <aside>App chrome</aside>

        <main className="bg-surface-1">
          <SurfaceProvider level={1}>{children}</SurfaceProvider>
        </main>
      </div>
    </SurfaceProvider>
  );
}
```

`SurfaceProvider` does not paint a background. It tells Cubitt components which
surface has already been painted by the app. `SidebarProvider` is the exception:
it paints the sidebar shell surface and provides that context for the app shell.

## Cubitt-Owned Surfaces [#cubitt-owned-surfaces]

Do not wrap normal Cubitt nesting with extra providers. If a Cubitt component owns and paints a container, it also owns the nested surface context.

For example, a `Card` inside a `surface-1` workspace lands on `surface-3` and provides `surface-3` context to its children. A secondary button inside that card then lands on `surface-4` without any consumer override.

```tsx
import { Button } from "@tilt-legal/cubitt-components/button";
import { Card } from "@tilt-legal/cubitt-components/card";

<Card>
  <Button variant="secondary">Secondary action</Button>
</Card>;
```

The same rule applies to floating surfaces. Popovers, menus, sheets, selection toolbars, sidebars, and sidebar insets handle their own context when they paint a surface.

<Preview name="SurfaceComponentBasesExample" />

## Custom App Surfaces [#custom-app-surfaces]

Use `Surface` when an app-owned custom container should both paint the next surface and provide that new level to its children.

```tsx
import { Button } from "@tilt-legal/cubitt-components/button";
import { Surface } from "@tilt-legal/cubitt-components/utilities";

<Surface offset={2} className="rounded-xl p-4">
  <Button variant="secondary">Nested action</Button>
</Surface>;
```

`offset={2}` means parent + 2. `Surface` paints that computed `surface-*` background, adds the next `border-*` half-stop edge, then provides the computed surface level to nested Cubitt components.

## Borders And Shadows [#borders-and-shadows]

Surface borders and shadows both derive from surface levels, but they do different jobs.

| Token                                    | Use                                                                                                                                             |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `border-border-1` to `border-border-8`   | 1px component edges and built-in divider lines. Component edges use the next stop; internal separators use two stops above the current surface. |
| `shadow-surface-1` to `shadow-surface-8` | Drop shadows only, matched to the floating surface level                                                                                        |

Use borders for in-flow containers such as cards, panels, controls, and internal separators. Use shadows only when a surface floats over other content, such as popovers, menus, sheets, and toolbars.

## Frosted Utilities [#frosted-utilities]

Frosted utilities combine a semi-transparent surface background with backdrop blur. Components can set the material surface from the active surface level; standalone usage falls back to `surface-2`.

```tsx
<div className="material-medium rounded-lg px-4 py-2">
  <h2>Frosted glass card</h2>
  <p>Content with backdrop blur</p>
</div>
```

<Preview name="FrostedUtilitiesExample" />

| Class                  | Opacity | Blur | Use                                       |
| ---------------------- | ------- | ---- | ----------------------------------------- |
| `material-ultra-thick` | 84%     | 30px | Strong glass separation                   |
| `material-thick`       | 72%     | 30px | Navigation bars and prominent glass cards |
| `material-medium`      | 60%     | 30px | Default frosted cards and controls        |
| `material-thin`        | 48%     | 30px | Subtle overlays                           |
| `material-ultra-thin`  | 36%     | 30px | Minimal blur                              |
