Name and Title, in the editor column — the band row in the nav had only scrolled
the preview until now.
Both, not the title alone: a form showing one of two names invites somebody to
change the wrong one, and `name` could only be set when the band was created.
Last in the editor's order, so a block or a spacing editor wins — those were
opened deliberately, and the band is merely still selected underneath them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A fourth level under the open band only — a page of six bands with four blocks
each is thirty rows, and the nav stops being somewhere you can find anything.
Blocks are named by the same list the picker offers, so a thing is called the
same word wherever it appears.
Clicking a block in the PAGE now writes that address too, rather than calling the
handler directly. Both ways of picking a block are the same act, so neither can
disagree with the other about what is selected — and closing it is the band row.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A third level, under the selected page only — every page has bands, and listing
all of them would make the nav longer than the site.
Announced by the builder rather than fetched again: it already reads them to know
what it is looking at in the document, and it mounts exactly when a page is open.
Cleared on unmount, or the nav keeps listing the last page's bands.
Clicking one writes a third URL segment and the preview scrolls to it, keyed on
the render count too so the position survives a save replacing the frame.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A bar on every band, Edit / Spacing / Delete above every block, dotted outlines
around blocks and columns, an add-zone at the end. Look at that and you are
looking at the editor, not the page — on the screen whose whole purpose is
judging the page.
A click selects a block and its editor opens in the panel beside the preview,
where every other control now lives. data-fofos-component stays: it is how the
panel writes a draft into the page as somebody types.
Adding a section, adding a block, deleting either and opening a spacing editor
have no door any more. The handlers are untouched and nothing calls them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Menu item, address and page title — what the retired /fofos-admin/pages panel
held, moved to the column where everything else about that page is edited.
Above the device toggle, because the toggle scopes what is under it to one width
and none of these three have widths. Read from the URL rather than announced:
they belong to the page whatever is selected inside it, so picking a block must
not replace them.
A changed slug changes the page's own address, so the panel follows it — left
alone the URL would name a page the list no longer holds.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Home has no grip, and dropping onto it is refused — hiding the handle alone
would still let something be dragged above the site's front door.
Every preview now reloads on the change channel, not just the page builder's own
writes. The Layout preview draws the top menu and had no reload token at all, so
the one screen where a reorder is visible was the one that never showed it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The grip drags and the row is the drop target — a Link is draggable by default
and drags its URL, so making the row itself draggable fights the browser for what
the gesture means.
The list rearranges as the pointer crosses a row rather than on drop, and the
write happens once at the end: PUT /pages/order takes the whole set, because an
order is a property of the set.
/fofos-admin/pages was a list of cards beside a nav that already lists the pages.
Two lists of the same thing, and the one you were looking at was never the one
you had clicked. It redirects to the first page now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Top Menu, Content and Footer were a hierarchy the screen does not have — all
three are edited by the same controls at the same time, so clicking one changed
the URL and nothing else.
The pages were announced by PagesPanel and only by PagesPanel, which mounts when
Pages is open. So they were invisible in the nav until you had already been to
the page that lists them. The nav fetches them itself when nobody has said yet;
the channel stays, and is still why a rename shows here the moment it is typed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Inherit (default)" answers a question nobody asked. What somebody wants from
that dropdown is what it is now — and a label that will not say makes them change
the setting to find out, which is the one way to lose the answer.
It reads Default (4xl) at the smallest width and Inherit (2xl) above it. The
stylesheet's own sizes come from the API, which reads them out of styles.css.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The room between a band's columns: gap-8 in a two-column section, gap-x-24
gap-y-10 in the footer. Both were written into the template that drew them.
The canvas now SKIPS a utility nothing has chosen instead of stripping it. The
old rule lied twice — a section's own padding vanished while the panel was open,
and a band with no chosen gap lost the site's default.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A container query on the scroller, once, so a new section is responsive by being
in the column rather than by remembering to say so. Below 320px the two-column
sections stack instead of truncating every select to "Martia…".
Colors stays flex-wrap: three swatches in a two-column grid is 2 and 1.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fonts and Font Sizes are the same four things, so they now read in the same order
under the same names — Menu, Titles, Headings, Body — from one list.
font_display is the largest statements and font_title is a section heading, which
is the reverse of what the words suggest. The labels say what the reader sees.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A fifth section between Fonts and Spacing. The same four roles the families use,
so a template asks for a role and gets both — and a role used at two sizes on
purpose collapses to one, which was the trade taken over a separate list of text
roles.
The live preview builds the same stylesheet the site renders, because a size is
three values and an inline style cannot carry a media query.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every field in there writes one breakpoint, chosen by the tabs at the top of the
panel. Without the name the same six selects mean six different things depending
on something above them.
One span, not two: the trigger is justify-between and puts the chevron last.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The line under every nav row, the line under every font select, and the caption
under the preview. Each explained a control to somebody who has already found
it, and the caption was wrong as well — there is no Save to press.
The nav rows are one line now, so they centre.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
text-xs was the size of the labels under it, so the three headings read as one
more row of form furniture. Bigger and heavier — weight is the signal that
survives at this density without adding a second thing to look at.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A container query, not a screen one: this sits in a workspace panel whose width
is a divider somebody drags, so the window says nothing about the room. Below
240px the icons stand alone and the word is the tooltip.
Every editor section starts open. It opened on one, from ?tab=, which is what
tabs want — these are not tabs, and a collapsed column asks somebody to go
looking for the setting they came for. ?tab= is gone with it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Icons alone told three things apart by proportion at 12 pixels. Full width, one
of three filled, and the word from DEVICES.
The `size` prop is gone with the bar that needed the small one, and so is the
second copy inside Spacing — the panel header scopes the whole editor now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It sat across the top of the detail panel with Sync, Build and Publish — three
things that act on the site, beside one that decides how you are looking at it.
The toggle belongs with the settings it scopes: a spacing is chosen per width,
so the control saying which width is the first thing in that column.
Sync, Build and Publish are unmounted until they have a place of their own.
ViewModeProvider stays; it was never the bar's.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Save button is gone, and so is the SaveTarget context that announced it.
Every screen here is a preview of the thing being edited, so a change is already
visible before it is written — a button then asks somebody to confirm what they
can see.
useAutosave debounces a burst into one request. It takes the unsaved state as a
string rather than a flag, so a failed save is not retried on the next render,
and it flushes on unmount so a section change loses nothing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The frame took all the room the panel had, so a short page left a band of white
under the footer with the measure guides running down through it. An iframe has
no height: fit-content, so the page is measured inside it and the frame follows.
The wrapper, not the body — body is min-h-screen, so measuring it would ask the
frame how tall the frame is.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The admin declares its routes in the manifest, so /fofos-admin/layout/header and
/fofos-admin/pages/home are real URLs. One reader takes the two segments after
the mount; links carry no query string at all, so nothing leaks between
sections.
What stays in the query is how you are looking — device, tab, view — rather than
at what.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Space between became Vertical padding: space-y hangs its margin below the box,
and the box's bottom border is the separator, so the room never landed above a
rule. The canvas now rewrites both axes on a band.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Top Nav, Sections and Footer each get their own horizontal padding, plus the
one space that band owns: the room under the rule, the gap between bands, the
room above the footer.
The preview marker now names its band, so a change moves one band and not all
three.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The three columns became one select. Which breakpoint it writes comes from the device control above it,
so the value you see is the value for the view you are looking at.
Spacing's settings are per width, so the section has to say which width it is editing — and the answer
must be the one the preview is already showing, not a second selector able to disagree with it.
It reads `?device=` rather than the ViewMode context, and that is not a preference. The editor is a
SIBLING panel: an element built inside the detail panel resolves context where it is RENDERED, so a
toggle handed over would look up a tree with no provider in it and quietly show the default forever.
The URL is the shared state, which means there is nothing to share. Three components read one
parameter, so they cannot disagree, and the preview follows without being subscribed to anything — it
reads the same value. More editor sections can take the control by rendering it.
The bar's own toggle is now the same component. It had its own copy of the options and the handler,
which is exactly how two controls for one thing start to differ.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The heading only. What it does is unchanged for now — the word is widening ahead of the behaviour,
which is the right order: the section is about to hold more than one kind of space, and Padding names
only one of them.
Pressing Layout while a band was open gave `?section=layout&band=footer`, so the row for the whole
section led to one part of it. Pressing a section carried whatever the last one had left behind.
Every link built a copy of the current query string and deleted the parameters known to be scoped —
`media`, then `page`, and `band` would have been the third. That is a list of exceptions that has to
grow every time a section gains a parameter, and it fails silently when somebody forgets: the link
still works, it just goes somewhere more specific than it says.
Starting from an empty query string inverts the default. A parameter survives a navigation only if the
link says so, which is one decision at each link rather than a list of everything that must not leak.
So a section row is `?section=x`, and a sub-item is that plus its own `band` or `page`. Nothing else
rides along, including the device and the open tab — both are restored to their defaults by the panel
that owns them, which is where a default belongs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two headings take the site's own spelling and the shorter word. "Typefaces" is the more precise
term and "Fonts" is the one everybody reaches for; a section heading is a signpost, not a definition.
The fonts go two by two. Four across existed to keep this section the same height as Colours, because
as tabs they shared one grid cell and a taller panel moved everything below it. Stacked sections do not
have that constraint — each is as tall as it is and nothing above it moves — so the reason expired with
the tabs.
What four across cost was the labels: in a panel this narrow every select truncated to "Martia…", so
the row said four times that a font had been chosen and never which one. Two columns give each the room
to be read, which is the only thing the control is for.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three tabs became three collapsible sections in a column, because there are going to be more than
three. A tab strip works while the names fit on one line and degrades the moment they do not — it wraps,
or it scrolls, and either way the set stops being visible at a glance.
`type="multiple"`, so more than one can be open. Tabs enforced exactly one, which is right when the
panels are alternatives and wrong when they are parts of the same thing: the colours and the padding of
a layout are read together as often as separately.
The grid overlay went with them. Every panel shared one cell so the block stayed as tall as the tallest
and did not jump when the tab changed — a real problem that stacked sections do not have, because a
section that is closed occupies nothing and one that is open is as tall as it is.
`?tab=` still seeds which section starts open, so an old link keeps working and lands on the thing it
named.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It sat just inside the left guide, which is on top of the page — over the logo, on this site — and it
is not part of the page. The margin is the one strip on screen belonging to the editor rather than to
the site, so the number describing the measure lives there.
Right rather than left: the eye reads the guide and then the width, so the label is the answer to the
line beside it, and the right margin is the one a wide frame has room in.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two things, both asked for after looking at it.
The tint came out. Shading the margins was meant to say "the page does not use this", and against a
white page it read as a blue background — a colour the site does not have, on the screen that exists to
show the site's colours. The two hairlines say the same thing without claiming anything.
And Desktop is fluid. `width: null` means the frame takes whatever the panel gives it, which is the
honest answer for a device that has no width: a desktop is whatever window somebody opened. 1440 was a
guess that then had to be centred and scrolled inside the panel — a page rendered at one width and
looked at inside another, with dark room either side of it.
Tablet and mobile stay pinned, because 834 and 390 are claims about real devices and pinning them is
the only way the preview can answer "what does this look like on a phone".
Fluid, the frame IS a desktop window: the site's media queries answer the panel's real width, and the
measure guides mark where the content stops in the pixels you are actually looking at.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two hairlines said where the measure ends and left the reader to notice that everything outside them
was empty. The margins are tinted now, faintly, so the unused width reads as what it is — room the page
does not occupy, which is the question somebody widening a gutter or judging a desktop layout is
actually asking.
Faint on purpose: it is absence, and anything stronger competes with the content for the eye. Nothing
is drawn at all when the frame is no wider than the measure, which is the existing early return.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`1 | [1 | 1]`, and the brackets are a real container this time.
Nesting them as a GROUP was the first attempt and looked identical — a horizontal group inside a
horizontal group renders three columns, because that is what it is. All it bought was which divider
moved what, which is invisible until you drag one.
So the pair is a panel whose component hosts its own WorkspaceView, the way DashboardPreview does. It
has its own chrome, its own divider and its own persisted sizes, and the root layout has two children
rather than three: the shape on screen is now the shape in the file.
`useAuthoredLayout` rather than `useDashboardState`, and its own key beside the root's. The structure is
the author's and comes from source every render; only sizes are the user's. Sharing one key would have
the inner and outer trees persisting over each other's sizes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`1 | 1 | 1` became `1 | [1 | 1]`, and the nesting is the whole difference.
Three siblings means every divider sits between two of them: widening the editor took from the preview,
and dragging the nav re-proportioned all three. Three panels that could only be sized against each
other.
Nested, the outer divider moves the nav against THE WORK and the inner one splits the work between
looking and changing. Those are the two questions somebody actually has — "give me more room" and "I
need more of the controls right now" — and each is one drag that leaves the other answer alone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Colours, Typefaces and Padding sat below the preview and took their height from it — the same trade the
page builder's editors made, and undone for the same reason: this screen exists to be looked at, and
the controls were eating the thing being judged.
Announced through the same slot, so the panel still holds nothing and still knows nothing about what a
layout is.
One thing that does not survive the move: a JSX comment cannot be an argument. The block carried its
own `{/* … */}` above the tabs and it had to become an ordinary comment on the effect, which is where
the reasoning belongs anyway now that the element is announced rather than rendered in place.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The spacing and free-text editors rendered below the preview, so they took their height from the thing
being edited: choosing a spacing shrank the page you were choosing it for, and on a laptop two
dropdowns cost a third of the frame.
They are a third panel now, to the right of the preview. The workspace already knows how to size and
move panels; a drawer was a second, worse layout system living inside one of them.
The panel holds nothing. Whichever panel owns a selection BUILDS the editor and announces it through a
`useGlobal` slot — the two are siblings and neither may own the other, and a provider around both would
mean something above them knowing they exist.
The slot carries the ELEMENT, not a description of one. A descriptor plus a switch would move every
editor's loading, saving and cancelling into a panel that would have to learn what a section is — a
second place that understands the page builder, kept in step by hand. SaveTarget makes the same trade
for the same reason.
The hazard is real and worth naming: an element captures the props it was built with, so the announcing
effect must depend on everything the editor DISPLAYS. The save handlers sit in refs so they cannot drag
that list wider — depending on them would re-announce on every keystroke, and omitting them without
refs would announce a stale one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`element.style.margin = '2.5rem 0'` on every section — 40 pixels above and below every band that the
real page does not have. It was there to make room for the band's label, which sat above it.
So the preview overstated the spacing of every page in the site, on the screen whose entire purpose is
to show what a page looks like. It was reported as "there is a lot more space between the logo and the
text in the admin", and that is exactly what it was. I had looked at the component tools, found them
absolutely positioned, and said nothing the editor draws takes layout space. The section margin was two
lines above the thing I read.
The label moved inside the band it names. It is hover-only, so overlaying the first line for as long as
the pointer is there costs nothing — and lying about the layout costs the preview its whole point.
What remains is absolutely positioned or an outline, neither of which takes space. The add-section
zone keeps its margin: it is the editor's own element at the end of the page, spacing only itself.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The bar offered Edit and View, and View existed to see the page without the builder's outlines and
handles on top of it. It was the DEFAULT, which put a click in front of every arrival at the one panel
whose job is editing — and it put a branch in every painter that did nothing but wait for that click.
So the mode is gone rather than defaulted the other way: no toggle, no `?mode=`, no guard. The clean
page is still one click away and always was — it is the site, on its own URL. What the admin owes is
the editing surface, always.
The left group in the bar stays, empty. The middle one is centred against the BAR rather than against
its neighbours, so removing the left group would let Desktop/Tablet/Mobile drift as the right group
changes width.
The preview's caption stays too. It reads as a duplicate of the device buttons and is not: they say the
width, and it says which SERVER — development, not production — which nothing else on the screen does.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Top Menu, Content, Footer — the layout IS a page, and those are the only three things on it. They were
reachable by scrolling and by knowing which tab held what; as rows they take the shape the nav already
teaches with the pages under Pages, and the open one is `band` in the query string.
Fixed rather than fetched, unlike pages. A band cannot be added or removed from the admin — only the
code that draws it can — so reading them from the database would be a query that can only ever return
the same three rows in the same order.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two rows, one of them marked `soon`, for a distinction that was never the editor's to make. The path
names a real file and what that file IS is a fact about it — the site reads it off the extension the
way a gallery item always has. So the picker asks for a file and stops asking what kind.
`video` is gone from what an editor can create and still legal in the database. Every row was migrated;
one written by something older should still be editable rather than open nothing, which is why the
edit path answers to both.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Measured from the RUN, not from the press. `startedAt` is stamped by the server when the pass begins,
so the number is right for somebody who opened the modal halfway through, reloaded the page, or was
not the one who started it — the watcher starts runs too. A timer anchored to the click would read
zero in all three cases and be wrong by however long the run had already been going.
It freezes at `finishedAt` rather than counting up beside a finished run, because the total is the
useful number: it is what tells you the next full sync will also take forty minutes.
`tabular-nums`, so a digit changing every second does not shift the words beside it.
Clock skew is the one thing that can make this wrong, by exactly its error — both times are absolute,
so a timezone cannot. The alternative, anchoring locally the first time a run is seen, is exact for
whoever pressed the button and silently zero for everyone else.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The counters said how MUCH and never which file, so a run that was working normally and one that had
wedged produced the same screen: `done` stops moving either way. A photograph is around thirty encodes
and a video is three plus a poster ladder, and none of that was visible from outside.
So the run keeps a transcript and the button opens it.
Every rung reports itself by CONSTRUCTION. Ten `variants.push` call sites became one `add`, which is
the point — a rung added later is described without anybody remembering to describe it. The slow
stages that produce nothing until they finish say so BEFORE they start instead: the HEIC decode, each
video rung, the poster frame. Those are the pauses that read as a hang.
`?since=<n>` is what keeps it cheap. The transcript is thousands of lines and polls once a second, so
sending all of it every tick would be the same megabyte over and over; the client keeps what it has
and asks for the rest. No `since` means everything, which is what a modal opened mid-run wants.
The transcript lives in the shared slot, not the modal, so closing it does not throw away the run —
somebody who looks, closes, and looks again is watching one run rather than two. `startedAt` is what
identifies a run, because `n` restarts at 1 and appending across a boundary would interleave two.
Polling, not a socket. Each line transfers once and the events are seconds apart, so a second
transport to open, authenticate and reconnect would buy nothing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It sat under the two folders it acts on, which was right while it was a detail of setting fofos up. It
is not one: a stale `derived/` is why a picture is missing from a page somebody is looking at, and the
fix was three sections away in a card about where the site lives. Beside Build and Publish it reads as
what it is — the third thing you do to a site, and the one that has to happen first.
The card keeps what needs room: the progress bar, the failures, the run history.
Shared through `useGlobal`, keyed `['fofos-admin','media-sync']` — a slot in the app-wide query cache,
so no provider has to wrap the bar and the panel together and a third reader is one line. Not a
context: this codebase has one for Save because a SECTION owns that state and announces it upward.
Nobody owns this one; it is a fact about a folder, which is what a keyed slot is for.
`useGlobal` shares the value and not the work, so the fetching is a separate hook with exactly one
caller — the button. The bar is mounted whenever the plugin is open and the Administration card is
mounted only sometimes, so the thing that is always there is the thing that asks. Two callers would
poll the same endpoint twice a second.
Gated on `rootSet`, not `ready`: sync reads a folder on this machine and never speaks to fofos.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both hold nothing, so adding one opens no editor: a dialog with no field on it is a step that exists
only to be got past. The picker itself answers the opposite way for the kinds that DO have a choice
to make, which is the distinction worth keeping.
The canvas draws no Edit button for them either — an Edit that opens nothing is worse than no Edit.
It asks the panel rather than holding a list of kinds, because which kinds are editable is the same
knowledge that decides which editor opens, and that already lives there. Absent means editable, so a
caller that has never thought about it gets what it had.
The Spacing dialog's label became a map. It was two kinds and readable as a ternary, then three and
not.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A built page is full-bleed now, so each band can draw a separator the width of the window, and each
holds its own content to the measure. `[data-content-column]` is therefore no longer one element
wrapping every section — it is one per section, and appending the drop zone to the first match put
"add a section" inside section one.
So it goes in `main`, with its width taken from a column rather than from a constant: the measure is
Tailwind's `max-w-7xl` and this file has no business knowing that. No sections, no column to ask, and
full width is right anyway — there is nothing to line up with.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The picker listed it as `soon` beside Image. It is not soon any more — the set, its ordering and the
carousel that draws it were already built on the site, so the block is a reference to one and the
admin's whole job is choosing which.
`GalleryPicker` chooses a SET and nothing else. Editing what is IN the set stays under Galleries: a
block that could also rearrange its own pictures would be a second place to do one job, and the two
would disagree. No thumbnails — every stored path names an original a browser cannot display, and the
plugin has no way to address a rendition, so the name and the count identify it instead.
Saved on choose, like a video and for the same reason: picking one thing is one act with one outcome,
so there is nothing to draft and nothing to cancel out of.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A Spacing handle on the section bar and in the component tools, opening an editor below the preview —
the same place the text editor goes, and for the same reason: a dialog covers the thing being spaced.
The device toggle picks the breakpoint. Two axes across three widths is six controls, five of them for a
width you are not looking at; this way you switch to Mobile, see the phone, and change the padding you
can watch changing. The site's GUTTER is the exception and shows all three at once, because it is one
axis and one value and it is a progression judged as a whole.
Inherit and 0 stay separate options, and the select names the value it is inheriting rather than leaving
it to be worked out.
Written IMMEDIATELY rather than drafted. A step is one choice from a short list and the effect is on
screen before the menu closes; a Save for it would be a second thing to remember on a panel whose other
verbs already act.
Spacing sits before Delete in the section bar, ordered by how often each is wanted rather than how they
read — the destructive one furthest from where the hand arrives.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>