Bogen

Pseudo-elements and conditions

A layer's own style is its inline style. Some CSS cannot be said inline: a ::before that draws an arrow head, a + after a menu title that turns into − when the menu opens, a grid that stacks when its container gets narrow, a colour under the pointer. A layer can hold these too, and they render the same on the canvas, in your agent's screenshots, in exports and in code.

What a layer can hold

Each layer has a list of blocks. A block is a pseudo-element, a condition, or both, with its own properties:

BlockMeans
::before, ::afterA box before or after the layer's content. It shows only with a content property; content: "" draws an empty box you style.
::marker, ::placeholder, ::selection, ::first-letter, ::first-lineThe parts of a layer CSS gives these names.
@container (max-width: 560px)Applies while the nearest container around the layer is at most 560px wide. @container card (…) asks the container named card.
@media (max-width: 760px)Applies while the artboard is at most 760px wide. See below.
:hover, :focus, :focus-visible, :focus-within, :activeApplies in that state.
[open]Applies while a details layer is open.
parent:hover, parent[open]Applies while the parent is in that state.

Parts combine: @container (max-width: 560px) ::after, @media (max-width: 760px) :hover, parent[open]::after. A query can use a breakpoint token, as in @media (max-width: var(--bp-md)).

In the inspector

The Pseudo-elements and conditions section lists a layer's blocks. The plus adds one: pick a pseudo-element, type a condition, and write the first property, such as content: "+". Each block has its properties as text, edited like Other styles, and a bin to remove it. In the layers panel, ::before and ::after show as rows under their layer, with their content. A click on one selects the layer.

Containers

A container query needs a container: a layer around it with container-type: inline-size (or size) in its style, and container-name if you want to ask for it by name. On the canvas the query answers to that layer's real width, so resizing the container, or the artboard it sits in, shows the change at once.

Media queries read the artboard

A web page's media queries ask about the browser window. On the canvas there is no window per artboard, so Bogen reads a media width query against the artboard the layer is in: an artboard of 390 is a phone, whatever the size of your screen. The same goes for screenshots, video, PDF, responsive_check and layer_styles_computed with a width, so your agent sees what you see. Under the hood the artboard becomes a container named bogen-artboard, and the query a container query on it.

States

Hover, focus and active blocks apply in preview mode and in exported pages. While you edit, the canvas leaves them out, so that pointing at layers does not change them. [open] blocks follow the open attribute of a details layer, in editing too.

From HTML

When your agent writes HTML with a <style> block, the rules land on the layers their selectors match, as plain rules do:

<style>
  pre[data-lang]::before { content: attr(data-lang); display: block }
  .menu > summary::after { content: "+" }
  .menu[open] > summary::after { content: "−" }
  .row { display: grid; grid-template-columns: repeat(3, 1fr) }
  .diagram { container-type: inline-size }
  @container (max-width: 560px) { .row { grid-template-columns: 1fr } }
</style>

Snapshot

A captured page keeps working as before: its ::before and ::after become child layers named Before and After, or after their text, at the size the page had. Conditions are not captured, as a capture is the page at one width. If you or your agent add a ::before to a captured layer that already has such a child, it shows twice, and layer_style says so. The page's hover and focus rules stay a record your agent reads with interaction_rules; it can turn one into a :hover block with layer_style.

In exports and code

For agents

layer_style takes pseudo and when, and clear_block removes a block. layer_tree shows which blocks a layer has, layer_get their properties, and layer_styles_computed reads a pseudo-element or lays the artboard out at a width first. design_lint and brand_check look at colours, sizes and fonts inside blocks too. See the MCP tools.

Sync and older versions

Blocks are stored per property, so two people or devices changing different blocks, or different properties of one block, both keep their change. The first block on a layer made before this existed is the exception: if two devices each give that layer its first block while apart, one side's first blocks are kept. A device running an older Bogen ignores blocks: it shows the layer without them and leaves them in place.