Skip to content

ai: Stabileo AI becomes a panel, and says it is not finished yet - #173

Open
Batuis wants to merge 3 commits into
basic/mobile-uifrom
basic/ai-panel
Open

ai: Stabileo AI becomes a panel, and says it is not finished yet#173
Batuis wants to merge 3 commits into
basic/mobile-uifrom
basic/ai-panel

Conversation

@Batuis

@Batuis Batuis commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Stabileo AI opened a 380 px container of its own beside the application. This makes it a panel destination instead, which fixes what was broken and gives it a phone for free — and states, unmistakably, that it is not usable yet.

What was wrong

PRO looked broken. Opening the assistant took the 3-D viewport from 960×784 to 80×80 — a black screen, with the status bar still reporting 8 nodos, 8 barras. The model was there; nothing drew it. The PRO panel disappeared with it.

The cause is one line. .app-body is a flex row and .app-body-pro is a flex column, and AiDrawer was written for the row: width: 380px; height: 100%. As a column item, that height took the whole column and left .pro-body-row — which holds the model and the panel — with none.

It had no phone at all. The trigger was behind !isMobile.

It was in Education, where there is no use for it yet.

And it is from another era of the app. 96 hardcoded colours and zero --st-* tokens. Two of them, #16213e and #0f3460, are literally from the palette styles/tokens.css documents as the old one, with the note that "there was no rule about which went where". It is also effectively untranslated — 8 t() calls in 1,265 lines — in a trilingual app.

Which section it belongs to: none

The assistant spans modelling, results and design, so it is not a step of the work — which is exactly what PRO_TAB_STAGE already says about Project by mapping it to ''. ai joins it there.

A fifth stage would have claimed it is a step. Filing it under ANALYSE would have claimed it only reads results. It opens from the header corner, in Basic and PRO, at every width — the same place in all four combinations, where the controls that act on the application rather than on a step already live.

What being a panel buys

The PRO collapse is not patched — it cannot happen, because the assistant is no longer a participant in that layout. Measured after: 960×784 → 960×784, unchanged.

And there was no mobile presentation to design. It is the bottom sheet, draggable, answering the density setting, because that is what happens to any panel.

This is the fourth time on this line of work that a parallel container turned out to belong in the panel system — after Basic's left drawer, the Model dropdown, and PRO's tab <select>.

Saying it is unfinished

A banner above an input you can still type into is a notice its own surface contradicts: the reader believes the box, not the label.

One constant, AI_IN_DEVELOPMENT, disables the field, the send button and the actions; the note explains what the disabling means. It is drawn in --st-warn before anything else — the same shape and the same bargain as conn.experimentalBanner, so a reader who has met one recognises the other. The header button carries a warn dot, so the state reads before the panel is opened. When it ships, one line changes and no control is left behind still greyed.

Out of Education as a condition rather than a deletion, with the reason written down: there are ideas for the assistant helping a teacher build exercises and none for a student solving them, so this is expected to be revisited. Verified absent by all three routes — the URL, the phone, and switching mode in-session.

Verification

before after
PRO canvas with the assistant open 80×80 960×784, unchanged
Button in Education present absent, all three routes
Mobile presentation none the sheet, in both modes
Input usable while unfinished yes disabled, and says why
  • npm run typecheck — 479, unchanged from baseline
  • npx playwright test --grep @smoke317 passed, the same count as the base branch
  • The eleven test files covering the AI drawer, the i18n dictionaries and the PRO stage tree — all green

Not done here, deliberately

The 96 colours and the translation. That is presentation of the content, not of the container — the long, low-risk part, and it does not block anything in this PR. Worth its own change.

Targets basic/mobile-ui (#166).

Batuis added 3 commits August 25, 2026 17:24
Three defects and one omission, all reproduced before touching anything.

**PRO looked broken.** Opening the assistant took the 3-D viewport from
960×784 to **80×80** — a black screen with the status bar still reporting
"8 nodos, 8 barras". The model was there; nothing drew it. The cause is one
line: `.app-body` is a flex ROW and `.app-body-pro` is a flex COLUMN, and
`AiDrawer` was written for the row — `width: 380px; height: 100%`. As a column
item that height took everything and left the model's container with none.

It is not patched. The assistant is a panel destination now, so it is no longer
a participant in that layout and the collapse cannot happen. Measured after:
960×784 → 960×784, unchanged.

**Which section it belongs to: none, and that is the point.** The assistant
spans modelling, results and design, so it is not a step of the work — which is
exactly what `PRO_TAB_STAGE` already says about Project by mapping it to `''`.
`ai` joins it there. A fifth stage would have claimed it IS a step; filing it
under ANALYSE would have claimed it only reads results. It opens from the header
corner, in both modes and at every width, where the controls that act on the
application already live.

Being a panel is also what gives it a phone. It had none — the trigger was
behind `!isMobile` — and now it is the bottom sheet, draggable, answering the
density setting, because that is what happens to any panel.

**It says it is unfinished, and behaves like it.** A banner over an input you
can still type into is a notice the surface contradicts: the reader believes the
box. One constant, `AI_IN_DEVELOPMENT`, disables the field, the send button and
the actions, and the note explains what the disabling means — in `--st-warn`,
before anything else, the same shape and bargain as `conn.experimentalBanner`.
The header button carries a warn dot so the state reads before the panel opens.
When it ships, one line changes and no control is left behind still greyed.

**Out of Education**, as a condition rather than a deletion, with the reason
written down: there are ideas for the assistant helping a teacher BUILD
exercises and none for a student solving them, so this is expected to be
revisited. Verified absent by all three routes — the URL, the phone, and
switching mode in-session.

Not done here, and deliberately: the body still carries 96 hardcoded colours
and no `--st-*` tokens — two of them, #16213e and #0f3460, are literally from
the palette `styles/tokens.css` documents as the old one — and it is
untranslated, 8 `t()` calls in 1,265 lines. That is presentation of the
CONTENT, not of the container, and it is the long, low-risk part.

Local `--grep @smoke`: 317 passed, the same count as before this change.
The panel was ported from the interface Stabileo used to have and never
left it. Four things, three of them visual and one that was hiding
behind them.

The button was `class="btn btn-ai"`. `.btn` sets padding and a radius
and no ground at all — `.btn-primary` and `.btn-secondary` are what
carry colour here — so the assistant opened from the browser's own
#efefef button, black text and all, in a dark header. It is now built
from `.btn-settings`, its neighbour in that corner: transparent, one
hairline, `--st-accent` when lit. It reads △ AI, because the triangle
is the mark standing beside the word Stabileo in this same header, so
repeating it names the product without spending the width to spell it.

The body carried 96 hardcoded colours and no tokens — six navy blues
doing the work of four surfaces, a teal accent this application does
not use, and eleven greys. All 84 occurrences now go through `--st-*`,
which is what makes the panel answer the same theme as everything around it.
The tab row became a segmented control, since the four views are one
exclusive choice and a recessed track says that in the shape rather
than only in colour, and the empty state — which is what a reader
actually sees, most of the time — became a held-back brand mark, a
title, and the example prompts as chips instead of four italic lines
that looked like an apology for the panel. Its strings, and the tab
labels, now go through `t()` in the three locales; they were English
literals in a Spanish interface.

The in-development notice was a `--st-warn` banner above the tabs.
`--st-warn` in this application means the structure has a problem, and
spending it on an unfinished feature makes both meanings weaker. It is
a hairline-separated footnote at the foot of the panel now, in
`--st-text-3`, one sentence. The claim is still not carried by the text
alone: `AI_IN_DEVELOPMENT` disables the composer and its send button.

── and the one that was not cosmetic

On a PRO phone the assistant rendered UNDERNEATH the whole command
grid, 750 px down a 300 px sheet. `proGridOpen` is ProPanel's own
state, and only the Project cell had ever collapsed it; `openAiPanel`
sets `proActiveTab` from the header, so it arrived through a door that
did not. A stage-less tab has no errand for the grid to be open for,
which is a rule that covers both doors.

Chasing that turned up two flex items refusing to shrink, neither of
them about the assistant. `.pro-panel` came in as `flex: 0 1 auto` with
the default `min-height: auto`, so it ran 26 px past the bottom of the
sheet holding it, and `.pro-content` — the scroller — could not take
the slack because the box above it had already refused to. Every PRO
tab on a phone lost that much under the bottom bar, and because the
panel scrolled, the clipping read as content simply ending there.

The bottom bar itself had never been reserved. Both `.app-body`
padding rules wrote `padding-bottom` on the same element, so the later
one won outright rather than adding, and the bar sat on the bottom
61 px of every panel opened on a phone. `--st-bar-h` is now one number
three boxes agree about — the bar sets its height from it, the sheet
stops above it, and `.app-body` gives up the sum.

Gates: 7101 unit tests, 317 @smoke e2e, typecheck at baseline 479.
`.header-actions` was `align-items: normal`, which in a flex row means
stretch. The help button and the language select declare no height of
their own, so they grew to the row's 32 px. The assistant and settings
buttons DO declare one — 26 px — so stretch did not apply to them and
they were left against the top edge, six pixels short of their
neighbours. Four controls side by side on three different centre lines.

Centring alone would have fixed the alignment and kept them looking
undersized next to the pair beside them, so both are now 32 px — the
height the other two arrive at — with the glyph and the AI wordmark
brought up to match. The phone keeps its 44 px targets: those come from
`min-height` in the mobile block, which outranks a declared height.

Gates: typecheck at baseline 479, 317 @smoke e2e.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant