Skip to content

iPhone: the Phosphor palette and type (WP2) - #36

Merged
frahlg merged 3 commits into
mainfrom
claude/ios-wp2-palette
Oct 14, 2026
Merged

frahlg merged 3 commits into
mainfrom
claude/ios-wp2-palette

Conversation

@frahlg

@frahlg frahlg commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

WP2 of the polish release: the app gets its own palette and type, as Fredrik decided on 13 Oct (decisions 1 and 3). The ground is blue-black, the interface is ink, there is no orange, and the grid is magenta both ways. Every screen changes at once; no layout moves.

What changes

  • Thirteen roles in Display P3, each with a dark variant, replace the sixteen web-token sets: ground, raised, hairline; ink, ink2, ink3; solar, gives, stores, grid, car; live, alarm.
  • One source for app and widgets. The catalog moves to appleApp/FTWCharts/Theme.xcassets, and FTWCharts/Palette.swift names the roles. Both targets build that folder. The widgets' hex copies (Tone pairs, Pair, GridColors) are gone.
  • The 0.3 names point at the new roles (fg is ink, surface is the ground, accent is ink, and so on). Where an old name meant two things, each use now says which: an error, a refusal or a warning is alarm; a confirmed outcome is live; an age that is not live is ink2; a battery giving power is gives. importing, exporting and generation are gone.
  • The system tint is ink and the launch screen is the ground. A primary button is inverse video: ink with the ground for its words.
  • The grid is magenta both ways: on Now, in the grid's chart and in the Grid today widget from iPhone: a Grid today widget, with today's energy over the grid, its cost and the day as a chart #30. The side of zero and the word say buying or selling.
  • Prices are ink by level (0.32, 0.50, 0.80 for cheap, middle and dear), never red and green. Theme.price serves the app and the widgets; PriceChart.swift is gone.
  • The home is ink, and the demo's status dot is live.
  • Type. Figures are SF Pro with even digits (Theme.figure) in place of bold SF Mono (Theme.number), so the slashed zero and the wide decimal gap go. Theme.mono is the terminal layer; kickers and the box's fingerprint on pairing use it now.
  • Card keeps its spacing and draws no fill and no border.
  • Switches are lime when on. With an ink tint the track turned white in dark mode and hid the white knob.
  • The car's violet draws the Live Activity, the Charge now control and its bolt. The Shortcuts tile is navy.
  • The app icon's bolt is FTW's gold (#FFB000) on the ground, where it was #FFAC41 on #0D0D0D. It was the last orange in the target. Small, but it is the home-screen icon, so say if it should stay as it was.
  • CLAUDE.md gets Fredrik's seven standing rules from 13 Oct (the phone's own cache first, the fastest live path, no ticking seconds, a small control mark, charts with volume, a small smooth flow, TUI without bloat), the look's rules (light means live, three tenses, colour is energy, no cards, type, the six TUI details, one palette source) and a new design references table.

Not here

The rest is layout, and other packages own it: Now's control card, plan card and node bubbles (WP8, WP9), the node views (WP6), the price chart (WP3), the plan view (WP11), and pairing, About and FTW Cloud (WP15). Those hand-made panels now draw in raised with a hairline border; in dark mode that sits close to the ground. The web tokens and the box's theme.css stay as they are. No glow and no new motion yet: WP9 brings them.

Two departures from the design

  • Dark ink3 is #727D90, one step lighter than #717C8F. The design's value reaches 4.48:1 on raised list rows; this one reaches 4.54:1.
  • The design puts the catalog in appleApp/FTW/UI/. It lives in appleApp/FTWCharts/ because both targets build that folder, which is how the widgets read the same source.

Contrast

WCAG ratios from the colour sets, with Display P3 luminance, as ThemeTests computes them.

Role Dark on ground on raised Light on ground on raised Use
ground #05080F – – #F5F6F8 – – Every screen
raised #0B111C – – #FFFFFF – – Sheets, menus, list rows
hairline #1B2433 1.3 1.2 #DCE0E7 1.2 1.3 Where two lists meet
ink #EEF3FF 18.0 17.0 #0A0F1A 17.7 19.2 Figures, chrome, the tint, the home
ink2 #9AA5B8 8.1 7.6 #545E70 6.0 6.5 Units, words, second lines
ink3 #727D90 4.8 4.5 #677184 4.5 4.9 Axes, footers, idle strokes
solar #FFE14D 15.4 14.5 #8A6C00 4.6 5.0 Sun
gives #FFB000 11.1 10.4 #A35700 4.9 5.3 Battery giving power
stores #18D9FF 11.7 11.0 #00739A 5.0 5.4 Battery storing, its level
grid #FF5FA8 7.4 7.0 #C2186F 5.0 5.5 Grid, both ways
car #B69CFF 8.9 8.4 #6A48D8 5.3 5.8 Car
live #83F52C 14.0 13.2 #2F7A00 5.1 5.5 State: live, confirmed
alarm #FF453A 6.2 5.8 #D70015 4.7 5.1 State: blocked, refused, failed
ink3, Increase Contrast #9AA5B8 8.1 7.6 #545E70 6.0 6.5 ink3 becomes ink2

Inverse video, ground on ink: 18.0 dark, 17.7 light. Ground on alarm (the danger button): 6.2 dark, 4.7 light.

Screens

From the demo, on an iPhone SE (3rd generation) and an iPhone 17 Pro Max, iOS 26.5, in dark, light and the largest text size (Accessibility XXXL, dark). Each picture puts before beside after; SE on top, Pro Max below.

Now

Now

Node views

Solar
Battery
Home
Grid
Car node

Car

Car

Plan and price

Plan
Price

Mode sheet, and its switch turned on (Pro Max, after)

Mode
Switch on

Pairing and About

Pairing
About

Widgets (17 Pro): Grid today, price, plan

Widgets

App icon

Icon

Tests

  • swift test in appleApp/FTWKit: 105 (FTWShared) and 277 (FTWKit) pass.
  • ThemeTests now checks that every role is Display P3 with a dark variant; that ink, ink2 and ink3 reach 4.5:1 on ground and raised in light, dark and Increase Contrast; that energy colours reach 4.5:1 in light and 7:1 in dark, and states 4.5:1 in both; that Increase Contrast turns ink3 into ink2; that AccentColor is ink and LaunchBackground the ground; and that no Swift, JSON or SVG file under FTW, FTWCharts, FTWWidgets or FTWNotify holds #DA7F00 or #FFAC41 or writes a colour in code. I planted a file with both to see it fail.
  • GridTodayShareTests checks that the grid widget draws in the grid role and in no other energy's hue.
  • The app and the widgets build for the iOS Simulator, and both bundles carry the thirteen colours (assetutil).

Not done: a recording and an Animation Hitches run from a device. This PR changes colour and type only and adds no motion; WP9 and later bring the motion that needs them.

🤖 Generated with Claude Code

The app gets its own palette and type, as Fredrik decided on 13 Oct:
a blue-black ground, an ink interface, no orange, and the grid in
magenta both ways.

- Thirteen roles in Display P3 replace the sixteen web-token sets. They
  live in FTWCharts/Theme.xcassets, which the app and the widgets both
  build, and FTWCharts/Palette.swift names them for both.
- The 0.3 names point at the new roles, so every screen changes at once.
  Where an old name meant two things, each use now says which: errors and
  warnings are alarm, confirmed outcomes are live, an age that is not
  live is ink2, and a battery that gives power is gives.
- The system tint is ink and the launch screen is the ground.
- Prices are ink by level, never red and green.
- Figures are SF Pro with even digits (Theme.figure); Theme.mono is the
  terminal layer, used by kickers and the box's fingerprint.
- Card keeps its spacing and draws no fill or border.
- Switches are lime when on: an ink track would hide the white knob in
  dark mode.
- The widgets read the shared palette; Grid today draws the grid in
  magenta. The Live Activity and the Charge now control use the car's
  violet.
- The app icon's bolt is FTW's gold on the ground, the last orange in
  the target.
- ThemeTests checks P3, contrast, Increase Contrast, the tint and the
  launch colour, and fails on any orange or any colour written in code.
- CLAUDE.md gets the look's rules and new design references.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T18:20:59.383654Z ee6a95d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Seven rules that outlive the polish release: the phone's own cache
first, the fastest live path, no ticking seconds, a small control mark,
charts with volume, a small smooth flow, and TUI without bloat. They
sit at the top of the look's section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee6a95d6fe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

yEnd: .value("Price", Self.priceFloor + Self.priceRise * max(0, bar.minor) / top)
)
.foregroundStyle(grey ? Theme.fgMuted : PriceBars.color(bar.tone))
.foregroundStyle(grey ? Theme.fgMuted : Theme.price(bar.tone))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid applying opacity twice to price bars

Theme.price already encodes the intended cheap/flat/dear strengths as 0.32/0.50/0.80 alpha, but this chart retains the following .opacity(0.4), reducing the effective values to 0.128/0.20/0.32 and making the cheaper bars especially faint. The plan widget has the same issue through Tone.of(bar.tone) followed by .opacity(0.4); apply the existing dimming only to the grey state, or otherwise avoid multiplying the full-color price alpha.

Useful? React with 👍 / 👎.

@frahlg frahlg mentioned this pull request Oct 14, 2026
@frahlg
frahlg merged commit f7fb8ba into main Oct 14, 2026
1 check passed
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