From 3ed8217c7eb5472f464f7e34d4716834a6b6743f Mon Sep 17 00:00:00 2001 From: Corey Ryan Dean Date: Wed, 10 Jun 2026 16:18:10 -0500 Subject: [PATCH] feat(loom): extend immersion-mode chrome to ribbon badges, atlas nodes, and quiet modals Co-Authored-By: Claude Opus 4.7 (1M context) --- src/Modules/Loom/Atlas.bb | 28 ++++++++++++++++++++++++++-- src/Modules/Loom/Palette.bb | 12 +++++++++++- src/Modules/Loom/Recents.bb | 12 +++++++++++- src/Modules/Loom/Ribbon.bb | 12 +++++++++++- src/Modules/Loom/SaveAll.bb | 13 ++++++++++++- src/Modules/Loom/Timeline.bb | 12 +++++++++++- src/Modules/Loom/Toasts.bb | 14 +++++++++++++- 7 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/Modules/Loom/Atlas.bb b/src/Modules/Loom/Atlas.bb index 52ff0efc..7ac05c8b 100644 --- a/src/Modules/Loom/Atlas.bb +++ b/src/Modules/Loom/Atlas.bb @@ -616,15 +616,39 @@ Type Atlas // Outdoors zones get a slightly warmer/lighter stone fill // so designers can scan the map for "is the forest the // big green cluster?" without opening each zone. + // + // Base-disk chrome varies by mode (mirrors the + // tool/balanced/in-world pattern from Browser::drawCardChrome): + // tool=flat, balanced=subtle gradient, in-world=dramatic + // gradient (+ inner brass ring ornament added below). The + // focused (brass) and hovered (arcane) states above stay flat + // highlights in every mode. If n\Outdoors = True - LoomFill(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_500_R, LOOM_STONE_500_G, LOOM_STONE_500_B) + If Loom_ChromeIsTool() = True + LoomFill(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_500_R, LOOM_STONE_500_G, LOOM_STONE_500_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_500_R, LOOM_STONE_500_G, LOOM_STONE_500_B, LOOM_STONE_900_R, LOOM_STONE_900_G, LOOM_STONE_900_B) + Else + LoomGradientV(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_500_R, LOOM_STONE_500_G, LOOM_STONE_500_B, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B) + EndIf Else - LoomFill(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B) + If Loom_ChromeIsTool() = True + LoomFill(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_950_R, LOOM_STONE_950_G, LOOM_STONE_950_B) + Else + LoomGradientV(sx - r, sy - r, r * 2, r * 2, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_800_R, LOOM_STONE_800_G, LOOM_STONE_800_B) + EndIf EndIf EndIf // Outer brass ring LoomBorder(sx - r, sy - r, r * 2, r * 2, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) + // In-world mode adds an inner brass ring as an engraved ornament + // (mirrors the double-brass framing the modals use in-world). + If Loom_ChromeIsInWorld() = True + LoomBorder(sx - r + 2, sy - r + 2, r * 2 - 4, r * 2 - 4, LOOM_BRASS_700_R, LOOM_BRASS_700_G, LOOM_BRASS_700_B) + EndIf // Spawn count inside the node -- "12" if non-zero, else // blank. Quick "is this zone empty?" cue. diff --git a/src/Modules/Loom/Palette.bb b/src/Modules/Loom/Palette.bb index 05146542..8906a67a 100644 --- a/src/Modules/Loom/Palette.bb +++ b/src/Modules/Loom/Palette.bb @@ -264,12 +264,22 @@ Type Palette // ------------------------------------------------------------------------- Method drawModalChrome(modalX%, modalY%) LoomShadowCard(modalX, modalY, PAL_MODAL_W, PAL_MODAL_H) - LoomFill(modalX, modalY, PAL_MODAL_W, PAL_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + // Modal backdrop varies by chrome mode (mirrors Composer:: + // renderAndUpdate): tool=flat, balanced=subtle gradient, + // in-world=dramatic gradient + brass bottom-rule ornament. + If Loom_ChromeIsTool() = True + LoomFill(modalX, modalY, PAL_MODAL_W, PAL_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(modalX, modalY, PAL_MODAL_W, PAL_MODAL_H, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_950_R, LOOM_STONE_950_G, LOOM_STONE_950_B) + Else + LoomGradientV(modalX, modalY, PAL_MODAL_W, PAL_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B, LOOM_STONE_900_R, LOOM_STONE_900_G, LOOM_STONE_900_B) + EndIf LoomBorder(modalX, modalY, PAL_MODAL_W, PAL_MODAL_H, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomBorder(modalX + 1, modalY + 1, PAL_MODAL_W - 2, PAL_MODAL_H - 2, LOOM_BRASS_700_R, LOOM_BRASS_700_G, LOOM_BRASS_700_B) // Top brass strip + LOOM tag LoomFill(modalX, modalY, PAL_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) + If Loom_ChromeIsInWorld() = True Then LoomFill(modalX, modalY + PAL_MODAL_H - 3, PAL_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomTheme_UseDisplay() LoomText(modalX + PAL_PAD, modalY + 6, "FIND ANYTHING", LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomTheme_UseBody() diff --git a/src/Modules/Loom/Recents.bb b/src/Modules/Loom/Recents.bb index 4604918b..63b9af1f 100644 --- a/src/Modules/Loom/Recents.bb +++ b/src/Modules/Loom/Recents.bb @@ -357,10 +357,20 @@ Type Recents Local modalY% = (sh - RECENTS_MODAL_H) / 3 LoomShadowCard(modalX, modalY, RECENTS_MODAL_W, RECENTS_MODAL_H) - LoomFill(modalX, modalY, RECENTS_MODAL_W, RECENTS_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + // Modal backdrop varies by chrome mode (mirrors Composer:: + // renderAndUpdate): tool=flat, balanced=subtle gradient, + // in-world=dramatic gradient + brass bottom-rule ornament. + If Loom_ChromeIsTool() = True + LoomFill(modalX, modalY, RECENTS_MODAL_W, RECENTS_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(modalX, modalY, RECENTS_MODAL_W, RECENTS_MODAL_H, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_950_R, LOOM_STONE_950_G, LOOM_STONE_950_B) + Else + LoomGradientV(modalX, modalY, RECENTS_MODAL_W, RECENTS_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B, LOOM_STONE_900_R, LOOM_STONE_900_G, LOOM_STONE_900_B) + EndIf LoomBorder(modalX, modalY, RECENTS_MODAL_W, RECENTS_MODAL_H, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomBorder(modalX + 1, modalY + 1, RECENTS_MODAL_W - 2, RECENTS_MODAL_H - 2, LOOM_BRASS_700_R, LOOM_BRASS_700_G, LOOM_BRASS_700_B) LoomFill(modalX, modalY, RECENTS_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) + If Loom_ChromeIsInWorld() = True Then LoomFill(modalX, modalY + RECENTS_MODAL_H - 3, RECENTS_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomTheme_UseDisplay() LoomText(modalX + RECENTS_PAD, modalY + 6, "RECENTS | " + Str(self\entryCount) + " entries", LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) diff --git a/src/Modules/Loom/Ribbon.bb b/src/Modules/Loom/Ribbon.bb index e05ecd6a..85970e05 100644 --- a/src/Modules/Loom/Ribbon.bb +++ b/src/Modules/Loom/Ribbon.bb @@ -223,10 +223,20 @@ Type Ribbon Local bh% = RIBBON_BADGE_H Local hovered% = (mx >= x And mx < x + bw And my >= by And my < by + bh) + // Dirty-indicator fill varies by chrome mode (mirrors the + // tool/balanced/in-world pattern from Browser::drawTopRibbon + + // Composer::renderAndUpdate): tool=flat brass, balanced=subtle + // brass gradient, in-world=bold brass gradient + brass ornament + // hairline. Hover stays a flat warning highlight in every mode. If hovered = True LoomFill(x, by, bw, bh, LOOM_WARNING_R, LOOM_WARNING_G, LOOM_WARNING_B) - Else + Else If Loom_ChromeIsTool() = True LoomFill(x, by, bw, bh, LOOM_BRASS_800_R, LOOM_BRASS_800_G, LOOM_BRASS_800_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(x, by, bw, bh, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B, LOOM_BRASS_800_R, LOOM_BRASS_800_G, LOOM_BRASS_800_B) + LoomHRule(x, by, bw, LOOM_BRASS_300_R, LOOM_BRASS_300_G, LOOM_BRASS_300_B) + Else + LoomGradientV(x, by, bw, bh, LOOM_BRASS_700_R, LOOM_BRASS_700_G, LOOM_BRASS_700_B, LOOM_BRASS_800_R, LOOM_BRASS_800_G, LOOM_BRASS_800_B) EndIf LoomBorder(x, by, bw, bh, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomText(x + RIBBON_BADGE_PAD_X, by + 4, label, LOOM_PARCHMENT_100_R, LOOM_PARCHMENT_100_G, LOOM_PARCHMENT_100_B) diff --git a/src/Modules/Loom/SaveAll.bb b/src/Modules/Loom/SaveAll.bb index f3f047bf..22b52b75 100644 --- a/src/Modules/Loom/SaveAll.bb +++ b/src/Modules/Loom/SaveAll.bb @@ -168,10 +168,21 @@ Type ExitPrompt Local modalY% = (sh - EXITPROMPT_MODAL_H) / 3 LoomShadowCard(modalX, modalY, EXITPROMPT_MODAL_W, EXITPROMPT_MODAL_H) - LoomFill(modalX, modalY, EXITPROMPT_MODAL_W, EXITPROMPT_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + // Modal backdrop varies by chrome mode (mirrors Composer:: + // renderAndUpdate): tool=flat, balanced=subtle gradient, + // in-world=dramatic gradient + brass bottom-rule ornament. The + // warning-colored top strip + border are preserved in every mode. + If Loom_ChromeIsTool() = True + LoomFill(modalX, modalY, EXITPROMPT_MODAL_W, EXITPROMPT_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(modalX, modalY, EXITPROMPT_MODAL_W, EXITPROMPT_MODAL_H, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_950_R, LOOM_STONE_950_G, LOOM_STONE_950_B) + Else + LoomGradientV(modalX, modalY, EXITPROMPT_MODAL_W, EXITPROMPT_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B, LOOM_STONE_900_R, LOOM_STONE_900_G, LOOM_STONE_900_B) + EndIf LoomBorder(modalX, modalY, EXITPROMPT_MODAL_W, EXITPROMPT_MODAL_H, LOOM_WARNING_R, LOOM_WARNING_G, LOOM_WARNING_B) LoomBorder(modalX + 1, modalY + 1, EXITPROMPT_MODAL_W - 2, EXITPROMPT_MODAL_H - 2, LOOM_BRASS_700_R, LOOM_BRASS_700_G, LOOM_BRASS_700_B) LoomFill(modalX, modalY, EXITPROMPT_MODAL_W, 3, LOOM_WARNING_R, LOOM_WARNING_G, LOOM_WARNING_B) + If Loom_ChromeIsInWorld() = True Then LoomFill(modalX, modalY + EXITPROMPT_MODAL_H - 3, EXITPROMPT_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomTheme_UseDisplay() LoomText(modalX + EXITPROMPT_PAD, modalY + 12, "UNSAVED CHANGES", LOOM_WARNING_R, LOOM_WARNING_G, LOOM_WARNING_B) diff --git a/src/Modules/Loom/Timeline.bb b/src/Modules/Loom/Timeline.bb index 68e1e9b8..f454f704 100644 --- a/src/Modules/Loom/Timeline.bb +++ b/src/Modules/Loom/Timeline.bb @@ -163,10 +163,20 @@ Type Timeline // Chrome LoomShadowCard(modalX, modalY, TIMELINE_MODAL_W, TIMELINE_MODAL_H) - LoomFill(modalX, modalY, TIMELINE_MODAL_W, TIMELINE_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + // Modal backdrop varies by chrome mode (mirrors Composer:: + // renderAndUpdate): tool=flat, balanced=subtle gradient, + // in-world=dramatic gradient + brass bottom-rule ornament. + If Loom_ChromeIsTool() = True + LoomFill(modalX, modalY, TIMELINE_MODAL_W, TIMELINE_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(modalX, modalY, TIMELINE_MODAL_W, TIMELINE_MODAL_H, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_950_R, LOOM_STONE_950_G, LOOM_STONE_950_B) + Else + LoomGradientV(modalX, modalY, TIMELINE_MODAL_W, TIMELINE_MODAL_H, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B, LOOM_STONE_900_R, LOOM_STONE_900_G, LOOM_STONE_900_B) + EndIf LoomBorder(modalX, modalY, TIMELINE_MODAL_W, TIMELINE_MODAL_H, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) LoomBorder(modalX + 1, modalY + 1, TIMELINE_MODAL_W - 2, TIMELINE_MODAL_H - 2, LOOM_BRASS_700_R, LOOM_BRASS_700_G, LOOM_BRASS_700_B) LoomFill(modalX, modalY, TIMELINE_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) + If Loom_ChromeIsInWorld() = True Then LoomFill(modalX, modalY + TIMELINE_MODAL_H - 3, TIMELINE_MODAL_W, 3, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) // Header in display font LoomTheme_UseDisplay() diff --git a/src/Modules/Loom/Toasts.bb b/src/Modules/Loom/Toasts.bb index 2a03ccee..04058848 100644 --- a/src/Modules/Loom/Toasts.bb +++ b/src/Modules/Loom/Toasts.bb @@ -159,7 +159,16 @@ Type Toasts // Background -- slightly transparent-looking via stone-800 over // the existing surface LoomShadowCard(x, y, TOAST_W, TOAST_H) - LoomFill(x, y, TOAST_W, TOAST_H, LOOM_STONE_800_R, LOOM_STONE_800_G, LOOM_STONE_800_B) + // Background varies by chrome mode (mirrors Composer:: + // renderAndUpdate): tool=flat, balanced=subtle gradient, + // in-world=dramatic gradient (+ mirror brass stripe added below). + If Loom_ChromeIsTool() = True + LoomFill(x, y, TOAST_W, TOAST_H, LOOM_STONE_800_R, LOOM_STONE_800_G, LOOM_STONE_800_B) + Else If Loom_ChromeIsInWorld() = True + LoomGradientV(x, y, TOAST_W, TOAST_H, LOOM_STONE_700_R, LOOM_STONE_700_G, LOOM_STONE_700_B, LOOM_STONE_900_R, LOOM_STONE_900_G, LOOM_STONE_900_B) + Else + LoomGradientV(x, y, TOAST_W, TOAST_H, LOOM_STONE_800_R, LOOM_STONE_800_G, LOOM_STONE_800_B, LOOM_STONE_850_R, LOOM_STONE_850_G, LOOM_STONE_850_B) + EndIf // Border in the kind's color LoomBorder(x, y, TOAST_W, TOAST_H, Toasts::kindR(self, t\Kind), Toasts::kindG(self, t\Kind), Toasts::kindB(self, t\Kind)) @@ -167,6 +176,9 @@ Type Toasts // Left brass accent stripe LoomFill(x, y, 3, TOAST_H, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) + // In-world mode mirrors the stripe on the right edge (book-spine + // ornament, same flourish the composer panel uses in-world). + If Loom_ChromeIsInWorld() = True Then LoomFill(x + TOAST_W - 3, y, 3, TOAST_H, LOOM_BRASS_500_R, LOOM_BRASS_500_G, LOOM_BRASS_500_B) // Message text (truncate if too long for the toast width) Local maxChars% = 40