diff --git a/assets/apple-touch-icon-180.png b/assets/apple-touch-icon-180.png index 9a208f2..c3b7baf 100644 Binary files a/assets/apple-touch-icon-180.png and b/assets/apple-touch-icon-180.png differ diff --git a/assets/banner.svg b/assets/banner.svg index a0080b1..1253587 100644 --- a/assets/banner.svg +++ b/assets/banner.svg @@ -10,8 +10,8 @@ - - + + @@ -21,17 +21,17 @@ - - - + + + - - - + + + - + @@ -170,55 +170,55 @@ - - - - - - + + + + + + - + - + - - - + + + - - - + + + - + - - - + - - - - - - - + + + + + + - + diff --git a/assets/favicon.svg b/assets/favicon.svg index 6b4c4aa..8257da0 100644 --- a/assets/favicon.svg +++ b/assets/favicon.svg @@ -3,25 +3,25 @@ LLeMbas - - - + + + - - - + + + - + - - - + + - - + diff --git a/assets/icon-192.png b/assets/icon-192.png index 6c528e8..6b355de 100644 Binary files a/assets/icon-192.png and b/assets/icon-192.png differ diff --git a/assets/icon-512.png b/assets/icon-512.png index 2a23230..1b4560a 100644 Binary files a/assets/icon-512.png and b/assets/icon-512.png differ diff --git a/assets/icon-maskable-512.png b/assets/icon-maskable-512.png index c9a1f13..8e6481d 100644 Binary files a/assets/icon-maskable-512.png and b/assets/icon-maskable-512.png differ diff --git a/assets/logo-lockup.svg b/assets/logo-lockup.svg index 37fbd2e..07dce92 100644 --- a/assets/logo-lockup.svg +++ b/assets/logo-lockup.svg @@ -3,55 +3,55 @@ LLeMbas - - - + + + - - - + + + - + - + - - - + + + - - - + + + - + - - - + - - - - - - - + + + + + + diff --git a/assets/logo-mark.svg b/assets/logo-mark.svg index 787cb74..99b6d60 100644 --- a/assets/logo-mark.svg +++ b/assets/logo-mark.svg @@ -1,49 +1,49 @@ LLeMbas - A silver mallorn leaf laid across a scored golden lembas wafer. + A pale mallorn leaf laid across a scored green lembas wafer. - - - + + + - - - + + + - + - + - - - + + + - - - + + + - + - - - + - - - - - - - + + + + + + diff --git a/assets/wordmark.svg b/assets/wordmark.svg index dcfc679..994aa68 100644 --- a/assets/wordmark.svg +++ b/assets/wordmark.svg @@ -5,10 +5,10 @@ LLM and take the accent colour; see scripts/build_artwork.py. --> diff --git a/scripts/build_artwork.py b/scripts/build_artwork.py index c70b912..42fa934 100755 --- a/scripts/build_artwork.py +++ b/scripts/build_artwork.py @@ -64,18 +64,26 @@ TAGLINE = "Waybread for the long road of thought" ACCENT_GLYPHS = frozenset({0, 1, 3}) # --- Palette ----------------------------------------------------------------- -GOLD_LIGHT = "#EACB74" -GOLD = "#C9A227" -GOLD_DARK = "#916F13" -GOLD_SCORE = "#7A5C10" -GOLD_HILIGHT = "#F6E3A8" -RUNE_GOLD = "#E0B252" +# The wafer is mallorn green because that is how lembas travels: wrapped in the +# leaves, not bare. Green also leaves yellow free to mean one thing in the +# interface -- a warning -- instead of two. +WAFER_LIGHT = "#7FB758" +WAFER = "#4C8C33" +WAFER_DARK = "#2A5522" +WAFER_SCORE = "#1F4019" +WAFER_HILIGHT = "#C7E7A6" +# The brand green, matching --leaf in tokens.css. Type accent and the drifting +# leaves on the banner. +MALLORN = "#9BCC5A" +MALLORN_DEEP = "#4C7A22" -LEAF_EDGE = "#93A5B6" -LEAF_LIGHT = "#F1F6FA" -LEAF_MID = "#B8C7D5" -LEAF_VEIN = "#61758A" -LEAF_STEM = "#8A9AA8" +# The blade stays pale: a leaf the same green as the wafer it lies on has no +# silhouette, and the silhouette is the whole mark at 16px. +LEAF_EDGE = "#9DB49A" +LEAF_LIGHT = "#F3F8EE" +LEAF_MID = "#C6D8BE" +LEAF_VEIN = "#57734F" +LEAF_STEM = "#8B9E86" NIGHT_TOP = "#080B0F" NIGHT_MID = "#101822" @@ -85,22 +93,37 @@ INK = "#1B1F23" MUTED = "#9AA7B4" # --- The mallorn leaf -------------------------------------------------------- -# Drawn once, in a 64x64 box, and reused everywhere. Tuned so the silhouette -# still reads as a leaf at 16px, where veins and score lines disappear. +# Drawn once, in a 64x64 box, and reused everywhere. The blade runs corner to +# corner and fills most of the tile, because at 16px the only thing that +# survives is the outline: a small leaf on a large tile reads as a green square +# with a smudge on it. Veins and the score line are detail-only for the same +# reason. +# Ovate, not lens-shaped: the widest point sits about a third up from the base, +# the base is a rounded cusp where the stem meets it, and only the tip is drawn +# out to a point. A blade pointed at both ends reads as an eye. LEAF_BLADE = ( - "M20.5 45.5 C13.8 31.7 23.8 20.9 45.5 18.5 C49.8 35 39.8 45.8 20.5 45.5 Z" + "M21 46 C19.6 40.5 20.4 34.2 23.4 30.5 C27.5 25.5 35 20.5 46 18 " + "C43.5 26.5 40.5 36.5 36.1 41.9 C33 45.6 26.5 47 21 46 Z" ) -LEAF_MIDRIB = "M20.5 45.5 C28 38 36 29 45.5 18.5" -LEAF_STEM_PATH = "M21.2 44.8 L17 49.4" +LEAF_MIDRIB = "M21 46 Q30.5 34.5 46 18" +LEAF_STEM_PATH = "M21.4 45.6 L16.3 51.2" +# Veins sweep towards the tip rather than leaving the midrib square-on, and +# shorten as the blade narrows. LEAF_VEINS = [ - "M26.9 38.8 Q25.2 35.8 24.9 32.1", - "M32.3 33.1 Q30.9 30.3 30.4 26.9", - "M37.8 27.0 Q36.6 24.6 36.3 21.7", - "M26.9 38.8 Q30.5 40.1 33.7 40.3", - "M32.3 33.1 Q35.8 34.3 38.6 34.5", - "M37.8 27.0 Q40.8 27.9 43.2 28.1", + "M26.8 39.2 Q24.9 37.4 24.7 35.3", + "M32.0 33.3 Q30.1 31.5 29.8 29.2", + "M37.8 26.9 Q36.4 25.6 36.1 23.7", + "M26.8 39.2 Q28.7 40.9 30.7 40.8", + "M32.0 33.3 Q33.9 35.0 36.1 34.9", + "M37.8 26.9 Q39.4 28.2 40.9 28.2", ] +# The wafer's break-lines. Axis-aligned and crossed, deliberately: a single +# diagonal behind a diagonal leaf does not read as scoring, it reads as a line +# struck through the mark. Thin and faint, so it is texture and not structure. +WAFER_SCORES = ("M32 5 V59", "M5 32 H59") +WAFER_SCORE_HILIGHTS = ("M33.1 5 V59", "M5 33.1 H59") + HEADER = ' str: """ return f"""{indent}""" @@ -205,9 +228,9 @@ def type_style(indent: str = " ") -> str: def mark_defs(prefix: str) -> str: return f""" - - - + + + @@ -215,7 +238,7 @@ def mark_defs(prefix: str) -> str: - + """ @@ -223,23 +246,23 @@ def mark_defs(prefix: str) -> str: def mark_body(prefix: str, *, detail: bool = True) -> str: """The wafer-and-leaf mark in a 64x64 box. - detail=False drops the score lines, rim and veins for small-size use. + detail=False drops the score line, rim and veins for small-size use. """ - parts = [f' '] + parts = [f' '] if detail: + scores = "\n".join(f' ' for s in WAFER_SCORES) + hilights = "\n".join(f' ' for s in WAFER_SCORE_HILIGHTS) parts.append(f""" - - - + +{scores} - - - + +{hilights} - """) + """) parts.append(f""" str: return f"""{HEADER} viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="LLeMbas"> LLeMbas - A silver mallorn leaf laid across a scored golden lembas wafer. + A pale mallorn leaf laid across a scored green lembas wafer. {mark_defs("m")} {mark_body("m")} @@ -272,14 +295,19 @@ def build_logo_mark() -> str: def build_favicon() -> str: - """Small-size variant: no score lines or veins, larger blade, tighter tile.""" + """Small-size variant: no score line or veins, larger blade, tighter tile. + + The tile grows to the edge of the box and the leaf is scaled up again on top + of that: at 16px the padding of the full mark is several device pixels of + nothing, spent on a rounded corner nobody can see. + """ return f"""{HEADER} viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="LLeMbas"> LLeMbas {mark_defs("f")} - - - + + str: out.append( f' ' - f'' + f'' ) return "\n".join(out) @@ -481,8 +509,8 @@ def build_banner() -> str: - - + + @@ -506,7 +534,7 @@ def build_banner() -> str: {_mountains(width, 366, 3, 150, "#1C2836")} {_mountains(width, 392, 8, 112, "#111A25")} {_mountains(width, 416, 21, 74, "#080D13")} - + @@ -514,7 +542,7 @@ def build_banner() -> str: {mark_body("b")} - + {run.paths(ACCENT_GLYPHS, indent=" ")} diff --git a/src/lembas/web/static/css/app.css b/src/lembas/web/static/css/app.css index aeca9ed..98580e7 100644 --- a/src/lembas/web/static/css/app.css +++ b/src/lembas/web/static/css/app.css @@ -342,7 +342,7 @@ button, input, textarea, select { background: var(--surface-active); color: var(--ink-muted); } -.badge--gold { background: var(--gold-soft); color: var(--gold); } +.badge--leaf { background: var(--leaf-soft); color: var(--leaf); } .badge--success { background: var(--success-soft); color: var(--success); } .badge--danger { background: var(--danger-soft); color: var(--danger); } @@ -381,7 +381,7 @@ button, input, textarea, select { } .sidebar__brand:hover { color: var(--ink); } .sidebar__brand .brand-mark { width: 1.65rem; height: 1.65rem; flex: none; } -.sidebar__brand .brand-llm { color: var(--gold); } +.sidebar__brand .brand-llm { color: var(--leaf); } .sidebar__actions { display: flex; @@ -554,7 +554,7 @@ button, input, textarea, select { place-items: center; padding: var(--sp-6); background: - radial-gradient(ellipse 60% 50% at 50% 0%, var(--gold-soft), transparent 70%), + radial-gradient(ellipse 60% 50% at 50% 0%, var(--leaf-soft), transparent 70%), var(--bg); } .auth__card { @@ -826,7 +826,7 @@ button, input, textarea, select { font-size: var(--text-sm); font-weight: 500; } -.picker__pin { color: var(--gold); } +.picker__pin { color: var(--leaf); } .picker__option-desc { font-size: var(--text-xs); color: var(--ink-faint); @@ -842,8 +842,8 @@ button, input, textarea, select { font-size: 0.6875rem; padding: 0 0.35rem; border-radius: var(--radius-sm); - background: var(--gold-soft); - color: var(--gold); + background: var(--leaf-soft); + color: var(--leaf); } .picker__tick { color: var(--accent); flex: none; margin-top: 0.35rem; } .picker__empty { diff --git a/src/lembas/web/static/css/chat.css b/src/lembas/web/static/css/chat.css index b2ac815..fc9794b 100644 --- a/src/lembas/web/static/css/chat.css +++ b/src/lembas/web/static/css/chat.css @@ -131,7 +131,7 @@ height: 1.05em; margin-left: 1px; vertical-align: text-bottom; - background: var(--gold); + background: var(--leaf); opacity: 0.75; animation: caret 1.05s steps(1) infinite; } @@ -167,7 +167,7 @@ .reasoning__summary::-webkit-details-marker { display: none; } .reasoning__summary:hover { color: var(--ink); background: var(--surface-hover); } -.reasoning__icon { color: var(--gold); flex: none; } +.reasoning__icon { color: var(--leaf); flex: none; } .reasoning__label { flex: 1; font-style: italic; } .reasoning__chevron { @@ -225,7 +225,7 @@ } .tool-activity__summary::-webkit-details-marker { display: none; } .tool-activity__summary:hover { color: var(--ink); background: var(--surface-hover); } -.tool-activity__icon { color: var(--gold); flex: none; } +.tool-activity__icon { color: var(--leaf); flex: none; } .tool-activity__label { flex: 1; } .tool-activity__count { color: var(--ink-faint); } .tool-activity[open] .reasoning__chevron { transform: rotate(180deg); } @@ -423,7 +423,9 @@ so code follows the active theme. classprefix "pg-" is set in markdown.py. */ .pg-c, .pg-c1, .pg-cm, .pg-cs, .pg-cp { color: var(--ink-faint); font-style: italic; } -.pg-k, .pg-kn, .pg-kd, .pg-kc, .pg-kr, .pg-kt { color: var(--gold); } +/* Keywords take --warning, not the brand accent: strings are already green, and + two greens in one code block is not a colour scheme, it is a bug report. */ +.pg-k, .pg-kn, .pg-kd, .pg-kc, .pg-kr, .pg-kt { color: var(--warning); } .pg-s, .pg-s1, .pg-s2, .pg-sb, .pg-sd, .pg-se, .pg-sh, .pg-si, .pg-sx { color: var(--success); } .pg-m, .pg-mi, .pg-mf, .pg-mh, .pg-mo { color: var(--danger); } .pg-nf, .pg-nd { color: var(--accent); } diff --git a/src/lembas/web/static/css/tokens.css b/src/lembas/web/static/css/tokens.css index 9048c90..b73bcc0 100644 --- a/src/lembas/web/static/css/tokens.css +++ b/src/lembas/web/static/css/tokens.css @@ -77,7 +77,7 @@ MORIA (default, dark) Deep stone and lamplight: the halls under the mountain. Surfaces are cool and - near-neutral so the gold and mithril accents carry all the colour. + near-neutral so the mallorn and mithril accents carry all the colour. --------------------------------------------------------------------------- */ :root, @@ -105,18 +105,27 @@ --accent-ink: #0B0E11; --accent-soft: rgba(143, 179, 204, 0.14); - /* Rune gold: the warm accent. Brand colour, and the assistant's mark. */ - --gold: #E0B252; - --gold-hover: #EDC46F; - --gold-soft: rgba(224, 178, 82, 0.13); + /* + Mallorn: the brand accent, and the assistant's mark. A yellow-leaning leaf + green, so it stays warm against the mithril blue rather than turning the + palette into two cool accents that compete. + */ + --leaf: #9BCC5A; + --leaf-hover: #B1DD74; + --leaf-soft: rgba(155, 204, 90, 0.14); /* Ember: destructive actions and errors. */ --danger: #E2795A; --danger-hover: #EC8E72; --danger-soft: rgba(226, 121, 90, 0.14); - --success: #7FB77E; - --success-soft: rgba(127, 183, 126, 0.14); + /* + Success leans teal rather than leaf. Two greens a hue apart read as one + colour rendered inconsistently -- an unread dot beside a brand badge has to + be tellable from it at a glance. + */ + --success: #5FBFA0; + --success-soft: rgba(95, 191, 160, 0.14); --warning: #DFAE58; --warning-soft: rgba(223, 174, 88, 0.14); @@ -137,7 +146,7 @@ SHIRE (light) Parchment, ink and moss: warm, low-contrast, easy to read for a long time. - Backgrounds are deliberately off-white -- pure #FFF next to the gold accent + Backgrounds are deliberately off-white -- pure #FFF next to the leaf accent reads as clinical rather than as paper. --------------------------------------------------------------------------- */ @@ -165,16 +174,17 @@ --accent-ink: #FDFBF5; --accent-soft: rgba(62, 107, 122, 0.12); - --gold: #A8801A; - --gold-hover: #8E6B12; - --gold-soft: rgba(168, 128, 26, 0.13); + /* The same mallorn, darkened until it holds its own as text on parchment. */ + --leaf: #4C7A22; + --leaf-hover: #3C6318; + --leaf-soft: rgba(76, 122, 34, 0.13); --danger: #A6432B; --danger-hover: #8C3722; --danger-soft: rgba(166, 67, 43, 0.11); - --success: #4F7A3F; - --success-soft: rgba(79, 122, 63, 0.12); + --success: #2C7360; + --success-soft: rgba(44, 115, 96, 0.12); --warning: #98701A; --warning-soft: rgba(152, 112, 26, 0.13); diff --git a/src/lembas/web/static/img/apple-touch-icon-180.png b/src/lembas/web/static/img/apple-touch-icon-180.png index 9a208f2..c3b7baf 100644 Binary files a/src/lembas/web/static/img/apple-touch-icon-180.png and b/src/lembas/web/static/img/apple-touch-icon-180.png differ diff --git a/src/lembas/web/static/img/banner.svg b/src/lembas/web/static/img/banner.svg index a0080b1..1253587 100644 --- a/src/lembas/web/static/img/banner.svg +++ b/src/lembas/web/static/img/banner.svg @@ -10,8 +10,8 @@ - - + + @@ -21,17 +21,17 @@ - - - + + + - - - + + + - + @@ -170,55 +170,55 @@ - - - - - - + + + + + + - + - + - - - + + + - - - + + + - + - - - + - - - - - - - + + + + + + - + diff --git a/src/lembas/web/static/img/favicon.svg b/src/lembas/web/static/img/favicon.svg index 6b4c4aa..8257da0 100644 --- a/src/lembas/web/static/img/favicon.svg +++ b/src/lembas/web/static/img/favicon.svg @@ -3,25 +3,25 @@ LLeMbas - - - + + + - - - + + + - + - - - + + - - + diff --git a/src/lembas/web/static/img/icon-192.png b/src/lembas/web/static/img/icon-192.png index 6c528e8..6b355de 100644 Binary files a/src/lembas/web/static/img/icon-192.png and b/src/lembas/web/static/img/icon-192.png differ diff --git a/src/lembas/web/static/img/icon-512.png b/src/lembas/web/static/img/icon-512.png index 2a23230..1b4560a 100644 Binary files a/src/lembas/web/static/img/icon-512.png and b/src/lembas/web/static/img/icon-512.png differ diff --git a/src/lembas/web/static/img/icon-maskable-512.png b/src/lembas/web/static/img/icon-maskable-512.png index c9a1f13..8e6481d 100644 Binary files a/src/lembas/web/static/img/icon-maskable-512.png and b/src/lembas/web/static/img/icon-maskable-512.png differ diff --git a/src/lembas/web/static/img/logo-mark.svg b/src/lembas/web/static/img/logo-mark.svg index 787cb74..99b6d60 100644 --- a/src/lembas/web/static/img/logo-mark.svg +++ b/src/lembas/web/static/img/logo-mark.svg @@ -1,49 +1,49 @@ LLeMbas - A silver mallorn leaf laid across a scored golden lembas wafer. + A pale mallorn leaf laid across a scored green lembas wafer. - - - + + + - - - + + + - + - + - - - + + + - - - + + + - + - - - + - - - - - - - + + + + + + diff --git a/src/lembas/web/templates/_macros.html b/src/lembas/web/templates/_macros.html index 3fe95e5..e224380 100644 --- a/src/lembas/web/templates/_macros.html +++ b/src/lembas/web/templates/_macros.html @@ -20,33 +20,34 @@ - - - + + + - - - + + + - + - + - - + + - - + + - - + - - {%- endmacro %} @@ -54,7 +55,7 @@ {# The wordmark as live text rather than the outlined SVG: it stays selectable, searchable and readable to a screen reader, and scales with the user's font - size. The capitals spelling LLM take the gold accent. + size. The capitals spelling LLM take the leaf accent. #} {% macro wordmark() -%} LLeMbas diff --git a/src/lembas/web/templates/admin/model_detail.html b/src/lembas/web/templates/admin/model_detail.html index 31bda6c..9ab262a 100644 --- a/src/lembas/web/templates/admin/model_detail.html +++ b/src/lembas/web/templates/admin/model_detail.html @@ -38,7 +38,7 @@
{% if model.model_id == default_model %} - {{ icon("star", "icon--sm") }} default model + {{ icon("star", "icon--sm") }} default model {% else %}
diff --git a/src/lembas/web/templates/library/_share.html b/src/lembas/web/templates/library/_share.html index c6f083b..11fc8ca 100644 --- a/src/lembas/web/templates/library/_share.html +++ b/src/lembas/web/templates/library/_share.html @@ -14,7 +14,7 @@

Shared with {% if shared_users or shared_groups %} - {{ shared_users|length + shared_groups|length }} + {{ shared_users|length + shared_groups|length }} {% else %} nobody {% endif %} diff --git a/src/lembas/web/templates/library/notes.html b/src/lembas/web/templates/library/notes.html index 2f6a39f..5ed8e96 100644 --- a/src/lembas/web/templates/library/notes.html +++ b/src/lembas/web/templates/library/notes.html @@ -44,7 +44,7 @@
{{ note.body[:160] }}{{ "…" if note.body|length > 160 }}
- {% if note.author == "model" %}written by a model{% endif %} + {% if note.author == "model" %}written by a model{% endif %} {% if note.owner_id != user.id %}shared{% endif %}
diff --git a/src/lembas/web/templates/library/skill_detail.html b/src/lembas/web/templates/library/skill_detail.html index 7c6c68c..34240e2 100644 --- a/src/lembas/web/templates/library/skill_detail.html +++ b/src/lembas/web/templates/library/skill_detail.html @@ -103,7 +103,7 @@
{{ revision.created_at.strftime("%Y-%m-%d %H:%M") }} {% if revision.author == "model" %} - model + model {% else %} you {% endif %} diff --git a/src/lembas/web/templates/library/skills.html b/src/lembas/web/templates/library/skills.html index 43a5858..8e6a1de 100644 --- a/src/lembas/web/templates/library/skills.html +++ b/src/lembas/web/templates/library/skills.html @@ -46,7 +46,7 @@
{% if not skill.enabled %}off{% endif %} - {% if skill.author == "model" %}written by a model{% endif %} + {% if skill.author == "model" %}written by a model{% endif %} {% if skill.owner_id != user.id %}shared{% endif %}
diff --git a/src/lembas/web/templates/partials/sidebar.html b/src/lembas/web/templates/partials/sidebar.html index ddff1de..015cd09 100644 --- a/src/lembas/web/templates/partials/sidebar.html +++ b/src/lembas/web/templates/partials/sidebar.html @@ -80,7 +80,7 @@ {{ icon("user", "icon--sm") }} {{ user.name }} - {% if user.is_admin %}admin{% endif %} + {% if user.is_admin %}admin{% endif %}
{% for name, on in (model.capabilities_json or {}).items() %} - {% if on %}{{ name }}{% endif %} + {% if on %}{{ name }}{% endif %} {% endfor %} {% if model.pinned %}pinned{% endif %}
@@ -312,7 +312,7 @@ {% if memory.author == "model" %} - remembered + remembered {% endif %} {% endfor %}