hermes(voice): crop Hermes character into orb as a feathered watermark

The orb watermark was showing the character art as a low-opacity square
box (visible edges) — the earlier screen-blend pass washed it into a glow
that lost the artwork. Reprocess the source into a feathered circle so the
orb crops it (no box) while keeping the character's facial features, paint
it with a normal blend at 0.5 opacity, and size it to fill the orb (inset
7%). Verified by compositing over a simulated orb before shipping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
This commit is contained in:
jenkins 2026-08-24 20:36:51 -03:00
parent 1baab8e014
commit 12ec6e5a70
3 changed files with 16 additions and 15 deletions

File diff suppressed because one or more lines are too long

View File

@ -75,7 +75,7 @@
// FIX 1: the conversation orb's centred watermark is the Hermes CHARACTER
// glyph — the 512px character art, feathered to a circle and luminance-weighted
// to a warm near-white, inlined as a data URI and painted by
// .voice-conversation-orb-mark in atlas-voice.css with mix-blend-mode: screen
// .voice-conversation-orb-mark in atlas-voice.css cropped into the orb by a feathered circle mask (no box; normal blend)
// so the face features glow over the dark orb. A low-opacity, non-animating
// (reduced-motion safe) layer that scales with the orb and reads across every
// state tint. No separate static asset is served for it.

View File

@ -518,12 +518,13 @@ def test_conversation_language_selector_source_and_style_contract():
def test_conversation_orb_hermes_mark_source_and_style_contract():
"""FIX 1: the orb watermark is the Hermes CHARACTER glyph, a pre-processed
data URI (feathered to a circle, luminance-weighted to warm near-white),
painted with mix-blend-mode: screen so the face features glow on the dark orb.
It is a static, low-opacity layer that scales with the orb, respects reduced
motion and never animates — NOT the muddy hermes-agent-192.png box it used to
reference, and NOT the caduceus/staff SVG before that."""
"""FIX 1: the orb watermark is the Hermes CHARACTER art, a pre-processed
data URI feathered to a circle so the orb crops it and the box disappears,
keeping the character's facial features. It is a static, low-opacity layer
that scales with the orb, uses a normal blend (the art itself, not a washed-
out glow), respects reduced motion and never animates — NOT the muddy
hermes-agent-192.png box it used to reference, and NOT the caduceus/staff SVG
before that."""
source = VOICE_SCRIPT.read_text(encoding="utf-8")
css = (ROOT / "dockerfiles" / "hermes-webui-atlas-voice.css").read_text(encoding="utf-8")
@ -536,14 +537,14 @@ def test_conversation_orb_hermes_mark_source_and_style_contract():
assert ".voice-conversation-orb-mark" in css
mark_rule = css.split(".voice-conversation-orb-mark {", 1)[1].split("}", 1)[0]
# The character glyph is inlined as a data URI (no static asset reference) and
# painted as a scaling, centred, screen-blended watermark with no animation.
# The character art is inlined as a data URI (no static asset reference) and
# painted as a scaling, centred, feather-cropped watermark with no animation.
assert 'url("data:image/png;base64,' in mark_rule
assert "mix-blend-mode: screen" in mark_rule
assert "mix-blend-mode: normal" in mark_rule
assert "background-size: contain" in mark_rule
assert "background-position: center" in mark_rule
assert "background-repeat: no-repeat" in mark_rule
assert "opacity: 0.6" in mark_rule
assert "opacity: 0.5" in mark_rule
assert "animation" not in mark_rule
# The muddy raster box (hermes-agent-192.png) is gone from the whole sheet, as
# is the staff-era monochrome currentColor tint.