Skip to content

fix: give the token gate some CSS, since it shipped with none - #16

Merged
StaticHumStudio merged 8 commits into
mainfrom
fix/auth-gate-has-no-styling
Aug 13, 2026
Merged

fix: give the token gate some CSS, since it shipped with none#16
StaticHumStudio merged 8 commits into
mainfrom
fix/auth-gate-has-no-styling

Conversation

@StaticHumStudio

Copy link
Copy Markdown
Owner

From a screenshot of a real v2.0.2 install. This is what every new user currently sees first.

The gap

Neither .hw-auth-prompt nor .hw-auth-status has a single rule anywhere in the stylesheets.

$ grep -rn "hw-auth-prompt\|hw-auth-status" static/css/*.css
(no matches)

So the gate renders as raw flow content underneath the sidebar: a bare heading, an unstyled password box, a default browser button, and the whole thing clipped off the left edge of the viewport. The heading reads equired because the rest is off-screen.

We locked the agent down in v2 and left the front door looking broken. It is the first screen of every install, and it looks like a rendering failure rather than a security control.

The fix

It is a gate, not a panel, so it is a fixed overlay covering the app, centred on a card, styled entirely through existing --hw-* tokens so all three themes follow.

The [hidden] override is load-bearing. display: flex beats the attribute's UA display: none, so without an explicit .hw-auth-prompt[hidden] { display: none } the gate would cover the app permanently and never close after a successful login. Verified in a browser:

gate:            position:fixed  display:flex  z-index:100  covers 1280x720 (full viewport)
hiddenAttrWorks: true
form:            384x210, centred, card bg, 1px border, 8px radius

The button is outlined, and that is measured rather than taste

My first attempt was a filled accent button. It fails:

theme      button bg  button fg   ratio  AA
default    #c9a84c    #0a0a0f      8.64  PASS
light      #3b82f6    #f5f3ef      3.32  FAIL      <-- under the 4.5:1 floor
terminal   #00ff41    #000000     15.38  PASS

--hw-accent-primary-dim (what .hw-btn-primary uses) is worse, because neither alternate theme redefines it and both silently inherit the base theme's dark olive.

Body text on the card is the pairing every theme has to keep readable:

default    #12121a    #e8e6e1     14.94  PASS
light      #ffffff    #1a1a2e     17.06  PASS
terminal   #0d1117    #00ff41     13.86  PASS

So the accent carries emphasis as a border, where its contrast against text does not matter. The card background needs var(--hw-bg-card, var(--hw-bg-secondary)) for the same class of reason: --hw-bg-card exists only in the two alternate themes.

Also: the sidebar was lying about the version

index.html hard-coded v1.0.0 into #app-version and nothing ever set it, so a v2.0.2 agent advertised v1.0.0. It now reads /api/v1/health, which is public and therefore resolves on the token screen too, and renders nothing at all when the agent is unreachable rather than naming a version it never got an answer from.

Notes

static/vendor/SHA256SUMS is re-pinned for components.css. The supply-chain guard caught the change on the first run, which is the system working.

241 passed, 5 skipped.

Related: this is the screen #15's guide tells people to paste their token into.

🤖 Generated with Claude Code

The v2 auth prompt is the first thing a new install shows anyone, and neither
.hw-auth-prompt nor .hw-auth-status has a single rule anywhere in the
stylesheets. The gate rendered as raw flow content underneath the sidebar: a
bare heading, an unstyled password box and a default browser button, half of
it clipped off the left edge of the viewport. We locked the agent down in v2
and left the front door looking broken.

It is a gate, not a panel, so it is now a fixed overlay that covers the app,
centred on a card. The [hidden] override is load-bearing: display:flex beats
the attribute's UA display:none, so without it the gate would cover the app
permanently and never close.

The button is outlined rather than filled, and that is measured, not taste. A
filled accent button is 3.32:1 in the light theme, under the 4.5:1 AA floor.
--hw-accent-primary-dim is worse still, because neither alternate theme
redefines it and both silently inherit the base theme's dark olive. Body text
on the card measures 14.94 / 13.82 / 14.50 across default, light and terminal,
so the accent carries emphasis as a border where its contrast does not matter.
The card background needs a var() fallback for the same class of reason:
--hw-bg-card exists only in the two alternate themes.

Also stops the sidebar lying about the version. It was hard-coded to v1.0.0 in
index.html and nothing ever updated it, so a v2.0.2 agent advertised v1.0.0.
It now reads /api/v1/health, which is public and so resolves on the token
screen too, and says nothing at all when the agent cannot be reached rather
than naming a version it never got an answer from.

241 passed, 5 skipped.

Co-Authored-By: Claude Opus 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: 35a343a291

ℹ️ 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".

Comment thread static/css/components.css
default browser button, rendered in page flow underneath the sidebar and
clipped off the viewport. It is a gate, not a panel, so it covers the app
instead of sitting inside it. */
.hw-auth-prompt {

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 Bump the cache keys for the changed frontend assets

On upgrades where a browser has cached /css/components.css?v=1.0.0 or /js/app.js?v=1.0.0, this commit keeps those same URLs in static/index.html, so the browser can reuse the previous files. That leaves the token gate unstyled—the regression this patch is intended to fix—and can leave the newly emptied version label blank because the cached app script lacks showAgentVersion; change the query versions for both modified assets.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Both changed assets now load as ?v=2.0.3 and the pinned components.css digest is updated. Fixed in b2c10c3.

Comment thread static/css/components.css Outdated
.hw-auth-prompt {
position: fixed;
inset: 0;
z-index: 100;

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 Raise the gate above the mobile navigation

At viewport widths of 768px or less, .hw-mobile-nav is displayed with z-index: 100 and appears after the auth prompt in the DOM. Giving the prompt the same stacking level causes that navigation bar to paint above the supposedly full-screen gate, so signed-out mobile users can see and interact with underlying navigation; use a higher stacking level for the gate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The gate moved to z-index 200, above the sidebar and mobile nav layers at 100. Verified in the running app at 375px: a hit-test at the mobile nav's center resolves to the gate in all three themes. Fixed in b2c10c3.

Both changed assets get new cache keys so upgraded installs load the
styled gate instead of a stale cached copy, and the gate moves to its
own stacking level above the sidebar and mobile nav layers at 100.

Co-Authored-By: Claude Fable 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: b2c10c3f58

ℹ️ 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".

Comment thread static/css/components.css
Comment on lines +559 to +560
position: fixed;
inset: 0;

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 Prevent focus from escaping behind the token gate

When a signed-out keyboard user tabs past the token input and Retry button, focus proceeds to the sidebar or mobile navigation even though this fixed overlay visually covers those controls. The user is then operating concealed links, and activating one can invoke the already-bound hash router while authentication is still pending; make the rest of the app inert or trap focus within the prompt until it closes.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The gate's siblings (sidebar, content, mobile nav) now go inert while the prompt is visible and recover on close, and auth.js gets a new cache key. Verified in the running app: a simulated tab walk from the token input cycles only between the input and Retry. Fixed in HEAD.

Tab order ignores paint order, so the covered sidebar, content, and
mobile nav go inert while the gate is visible and recover when it
closes.

Co-Authored-By: Claude Fable 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: c2a82f218b

ℹ️ 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".

Comment thread static/js/auth.js
Comment on lines +99 to +102
var siblings = prompt.parentElement ? prompt.parentElement.children : [];
for (var i = 0; i < siblings.length; i++) {
if (siblings[i] !== prompt) siblings[i].inert = visible;
}

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 Release the gate after a rate-limit retry succeeds

When the startup probe hits the authentication-failure 429 limit, handleRateLimited shows this prompt and schedules _authenticateThenStart; if the later probe succeeds, _startProtectedDashboard runs without ever calling _setPromptVisible(false). These new inert assignments therefore leave the sidebar, content, and mobile navigation inaccessible behind the full-screen gate even though authentication succeeded, with a page reload as the only recovery; clear the prompt and inert state on the successful retry path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

_startProtectedDashboard now runs HumWatch.auth.closePrompt(), which hides the gate, clears the inert siblings, and cancels any pending retry. Verified live: handleRateLimited then a successful start leaves the gate hidden and all three siblings interactive. Fixed in HEAD.

Comment thread static/css/components.css Outdated
Comment on lines +661 to +664
.hw-auth-prompt #auth-error {
margin: 0;
font-size: var(--hw-font-size-sm);
color: var(--hw-status-critical);

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 Use a readable light-theme error color

In the light theme, this renders the 0.8rem authentication error as #ef4444 on the form's white background, which has only about 3.76:1 contrast instead of the 4.5:1 required for small text. The affected text includes the rate-limit notice and token-entry errors users need to recover, so use a darker light-theme critical foreground here.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The gate error now uses --hw-auth-error with the status red as fallback, and the light theme sets it to a darker red measuring 6.47:1 on the white form. Theme stylesheets also gained cache keys so upgraded installs actually load the change. Fixed in HEAD.

… errors

The successful probe after a 429 now closes the prompt and clears the
inert siblings through one closePrompt path, the light theme gets a
darker error red for small text on the white form (6.5:1), and the
theme stylesheets pick up cache keys so upgraded installs load them.

Co-Authored-By: Claude Fable 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: e857541e13

ℹ️ 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".

Comment thread static/js/auth.js
Comment on lines +94 to +98
HumWatch.auth.closePrompt = function() {
HumWatch.auth._promptOpen = false;
HumWatch.auth._cancelRetry();
HumWatch.auth._setPromptVisible(false);
};

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 Clear the rate-limit error when closing the gate

When an automatic retry succeeds after handleRateLimited, this hides the prompt but leaves #auth-error visible with the old “retrying” message. If the user later logs out or receives another 401, requireToken() reopens the prompt without clearing that error, falsely claiming that a retry is scheduled; reset the error text/hidden state when closing or reopening the prompt.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

_setPromptVisible now resets the error text and hidden state whenever the prompt shows. Both writers (the rate-limit notice and the submit failure) run after that reset, verified live: rate-limit message shows, gate closes on success, and the reopened prompt is clean. Fixed in HEAD.

The retry notice from a rate-limited probe survived into the next
logout or 401 prompt, so the gate now clears the error whenever it
shows, before either writer runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@StaticHumStudio

Copy link
Copy Markdown
Owner Author

@codex review

@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: 9a9d8a6351

ℹ️ 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".

Comment thread static/css/components.css Outdated
font-size: var(--hw-font-size-xs);
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--hw-text-tertiary);

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 Increase the token label's contrast

When the authentication gate is shown, this 0.7rem label has insufficient contrast against the form in every theme: approximately 3.34:1 in default, 3.48:1 in light, and 4.46:1 in terminal, all below the 4.5:1 threshold for small text. Because this label identifies the required credential field, use a higher-contrast foreground such as the theme's primary or secondary text color.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The label now uses the secondary text tone, measured live at 6.45:1 default, 7.30:1 light, and 8.73:1 terminal against the form backdrop. Fixed in HEAD.

The tertiary tone missed 4.5:1 in every theme on the one label that
names the credential field. Secondary measures 6.5:1 or better in all
three.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@StaticHumStudio

Copy link
Copy Markdown
Owner Author

@codex review

@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: e0ca6dfe8d

ℹ️ 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".

Comment thread static/css/components.css Outdated
font-family: var(--hw-font-display);
font-size: var(--hw-font-size-lg);
font-weight: 500;
color: var(--hw-accent-primary);

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 Darken the light-theme gate heading

In the light theme, this 1.2rem, weight-500 heading renders as #3b82f6 on the form's white background, giving only about 3.68:1 contrast. At roughly 19.2px it does not qualify as large text, so the token gate's primary heading needs the 4.5:1 ratio; override it with a darker light-theme color or use a readable text token.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The heading now reads --hw-auth-heading with the accent as fallback, and the light theme sets a darker blue measured live at 6.70:1 on the white form. Fixed in HEAD.

Comment thread static/css/components.css Outdated
Comment on lines +681 to +682
font-size: var(--hw-font-size-xs);
color: var(--hw-text-tertiary);

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 Increase the authentication status contrast

The 0.7rem authentication state uses the tertiary tone, which is only about 3.34:1 on the default sidebar and 2.82:1 on the light-theme sidebar; the logout label repeats the same failing color below. These are meaningful status and action labels, so use the secondary/sidebar text tone or another color that reaches 4.5:1 in every theme.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Status and logout both moved to the secondary tone: measured 6.45:1 default, 5.91:1 light, 9.13:1 terminal on their sidebar backdrops. Fixed in HEAD.

The light theme overrides the gate heading to a darker blue (6.7:1 on
the form), and the sidebar auth status and logout labels move from the
tertiary to the secondary tone, reaching 5.9:1 or better everywhere.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@StaticHumStudio

Copy link
Copy Markdown
Owner Author

@codex review

@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: 82238bab73

ℹ️ 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".

Comment thread static/css/components.css Outdated
font-size: var(--hw-font-size-md);
padding: var(--hw-space-sm) var(--hw-space-md);
background: var(--hw-bg-primary);
border: 1px solid var(--hw-border-color);

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 Give the token input a visible boundary

When the authentication gate is shown and the field is not focused, the custom border does not reach the 3:1 non-text contrast needed to identify an interactive control in any theme: it is roughly 1.39:1 in default, 1.39:1 in light, and 1.66:1 in terminal against the input background, while the input fill is also nearly indistinguishable from the surrounding card. Because this is the only field through which signed-out users can recover access, use a higher-contrast border or a clearly contrasting fill for its resting state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The resting border now uses --hw-auth-input-border with the secondary text tone as fallback: measured 6.84:1 default, 4.36:1 light (dedicated override), 9.68:1 terminal against the input fill. Fixed in HEAD.

The stock border tone sat under 1.7:1 on the input fill in every
theme. The secondary text tone carries it to 6.8:1 default and 9.7:1
terminal, and the light theme overrides to a mid gray at 4.4:1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@StaticHumStudio

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: b5d1d9b7be

ℹ️ 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".

@StaticHumStudio
StaticHumStudio merged commit 771cd25 into main Aug 13, 2026
7 checks passed
@StaticHumStudio
StaticHumStudio deleted the fix/auth-gate-has-no-styling branch August 13, 2026 20:45
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