Replaces #FCC001, which was measured off the hexagons in
OffScaleAppIcon.png. Sampling was the wrong approach: PNG antialiasing and
the icon's own shading make any eyedropper result an approximation of the
brand value rather than the value itself. #FECF03 (hue 48.8deg) is the
canonical one.
All three yellows resolve through root.accent — the bar's tailnet label,
the active connection name, and the IP/DNS subtitle — so this is a single
value. The wordmark asset is unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Replace the mark with OffScaleAppIcon.png, run through the same pipeline
as before: trim the transparent margin, pad to square, scale to 256x256
(654 KB -> 62 KB). One asset, two render sites.
- Retune the accent to #FCC001, the modal hexagon fill of the new icon.
Sampled from fully-opaque pixels only — the yellows cluster at
252,192-196,1-2, so this is the flat colour and not an antialiased edge.
(`magick -alpha off` flattens onto black and gives a wrong answer here.)
Replaces #FAE204 from the previous logo, which was noticeably greener.
All three yellows — the bar's tailnet label, the active connection name,
and the IP/DNS subtitle — resolve through root.accent, so this is one
value.
- Hold the bar mark at 32px now that shell base-size is 24 rather than 20.
Every size in the shell is a multiple of fontScale, so raising base-size
to enlarge the stock bar icons would have scaled this one identically and
left the relative gap unchanged; the icon/canvas/slot values are scaled
down to compensate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The label was a plain Text with its own MouseArea, which is not registered
in bar.clickTargets. While a panel is open, KeyboardPanel puts a
full-screen overlay above everything and forwards clicks landing in the
bar strip only to registered targets — so a left click opened the panel
and then had the same click treated as "outside", dismissing it. It
looked like nothing happened. Right click was unaffected because
toggleOffscale() never involves the panel.
Use a WidgetButton instead: it registers itself via syncClickRegistration()
and renders the label text natively, so both the Text and the MouseArea
go away. Left toggles the panel, right toggles Offscale, middle refreshes
— the same three buttons as the icon, so the widget reads as one target.
`dimmed` handles the inactive state rather than darkening the colour,
since Qt.darker on yellow shifts the hue to olive.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds a label to the left of the mark naming the tailnet the selected
profile belongs to: the second-from-last label of the domain, so
offscale.pastilhas.dev reads "pastilhas" and headscale.pertento.ai reads
"pertento". Taking the second-level domain rather than a fixed index keeps
the distinctive part if a tailnet ever has four labels.
Read from the accounts list the service already polls, so no extra
process runs for it.
BarIconButton is icon-only by design (labelVisible: false, fixedWidth:
slotSize, and its `text` feeds a glyph rather than a label), so the label
could not live inside it — the bar widget is now a Row of label + button,
and its footprint comes from the row.
Coloured with the brand yellow, dimmed by opacity rather than by
darkening when Tailscale is off: Qt.darker on yellow shifts the hue to
olive instead of quietening it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Label each connection with its tailnet and account rather than the
nickname alone. `tailscale switch --list --json` carries both, and on a
multi-tailnet setup the nickname is the least useful field — "andre"
says nothing about which tailnet you would be switching to. Renders as
"headscale.pertento.ai (andre)", falling back through tailnet, then
account, then profile id when a field is missing.
- Mark the active connection with colour instead of a filled background:
brand yellow on its label, currentFill cleared. The theme sets
selected-border-width to 0, so clearing the fill leaves nothing drawn.
Hover still highlights through `fill`, so the row keeps its affordance.
Exit-node and Mullvad-region rows are untouched and still fill.
- Sort the active connection to the top. Done in parseAccounts rather
than at render time: the keyboard cursor indexes into
tailscale.accounts, so sorting only in the view would leave j/k acting
on a different row than the highlighted one. Array.sort is stable, so
the remaining profiles keep the CLI's order.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Colour the IP / DNS subtitle under each machine with the logo yellow
(#FAE204, sampled as the dominant opaque colour of offscale-logo.png).
Stock draws that line through `dim` = Qt.darker(foreground, 1.55), which
on yellow shifts the hue to olive (#A19203) rather than quietening it, so
it takes the flat accent instead. Everything else keeps the themed
foreground: section headers, machine names, account names and all the
iconography.
- Add OffscaleToggle.qml so the switch reads white when on. The stock
ToggleSwitch resolves its checked colours through
Style.selectedStateColor / selectedFillFor, which read [controls]
selected-color; Ethereal sets that to a literal "#ffcead" and
Style.resolveStateColor returns literals verbatim, ignoring the
foreground and accent properties entirely. No property on the stock
switch can reach it, and overriding the token globally would recolour
every selected state in the shell. The copy differs only in the checked
state and needs an explicit `import qs.Ui`, which the original gets
implicitly by living inside that module.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Regenerated from OfficerIcons/NewBrief/OffscaleLogo3.png with the same
pipeline as before: trim the transparent margin, pad back to square so it
centres, scale to 256x256 (1.08 MB -> 78 KB).
One asset, two render sites — OffscaleIcon.qml loads it and is
instantiated both in the bar and in the panel hero, so this covers both.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Forked from omarchy.tailscale at the packaged commit (omarchy-dev
4.0.0.r1744.gf002044). The `tailscale` branch holds the pristine upstream
subtree history so upstream changes can still be merged in; `master` is
this fork.
- Rename the plugin to pastilhas.offscale: manifest id/name, moduleName
and ipcTarget, and display strings. Deliberately NOT renamed: the
lowercase "tailscale" CLI invocations, the TailscaleIPs/TailscaleIPv6
JSON fields from `tailscale status --json`, and
authorizeTailscaleOperator. Renaming those loads fine but silently
breaks peer parsing.
- TailscaleIcon.qml -> OffscaleIcon.qml, now rendering offscale-logo.png
instead of the 3x3 dot grid, keeping the crossed/warning states.
- Add OffscaleHero.qml: a copy of qs.Ui.PanelHero with a titleComponent
slot, so the wordmark (offscale-text.png) can replace the title text.
Otherwise byte-identical to the original, so it stays diffable.
- Drop the cycling hero phrases entirely - the array, the 2.8s timer and
the metaOpacity fade.
- Show the local machine as a PeerRow of its own, so it gets the same
layout and copy menu as tailnet peers. Adds `navigable` to PeerRow so
that row stays out of the peers keyboard cursor.
- Enlarge the bar icon: BarIconButton pins its icon to opticalCanvas, so
opticalSize/slotSize are overridden alongside iconSize.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>