5ef2af6a9f
Establish the LLeMbas foundation: FastAPI/Jinja/SQLite layout, the ORM schema, and the original SVG identity. Notable decisions, all recorded in comments at the point they matter: - No Alembic. SQLite only, schema created at startup, so models carry a few columns nothing reads yet (Message.parent_id for branching, content_parts_json for multimodal turns). Adding them later to a live database without migrations is the painful path. - Sessions are server-side rows keyed by a SHA-256 of the cookie value, not JWTs, so logout and bans revoke access immediately. - Upstream API keys are Fernet-encrypted with a key derived from LEMBAS_SECRET_KEY. decrypt() fails soft to "" so rotating the secret degrades to re-entering keys rather than crashing the admin UI. - Artwork is generated by scripts/build_artwork.py rather than hand-drawn per file: the mallorn leaf appears in the icon, favicon, lockup and banner, and one source is the only way those stay in sync. The wordmark is Source Serif 4 (OFL) converted to outlines, because a README banner cannot load a webfont and <text> would render in whatever serif the viewer happens to have. - Icons live in a template partial, not assets/, because same-document <use href="#id"> is universally supported and the cross-document form is not. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
5.9 KiB
XML
68 lines
5.9 KiB
XML
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 342.25 72.00"
|
|
width="342.25" height="72.00" role="img" aria-label="LLeMbas">
|
|
<title>LLeMbas</title>
|
|
<defs>
|
|
<linearGradient id="l-wafer" x1="0" y1="0" x2="0.3" y2="1">
|
|
<stop offset="0" stop-color="#EACB74"/>
|
|
<stop offset="0.5" stop-color="#C9A227"/>
|
|
<stop offset="1" stop-color="#916F13"/>
|
|
</linearGradient>
|
|
<linearGradient id="l-leaf" x1="0.1" y1="1" x2="0.9" y2="0">
|
|
<stop offset="0" stop-color="#93A5B6"/>
|
|
<stop offset="0.4" stop-color="#F1F6FA"/>
|
|
<stop offset="1" stop-color="#B8C7D5"/>
|
|
</linearGradient>
|
|
<clipPath id="l-clip">
|
|
<rect x="6" y="6" width="52" height="52" rx="13"/>
|
|
</clipPath>
|
|
</defs>
|
|
<style>
|
|
.base { fill: var(--lembas-ink, #1B1F23); }
|
|
.accent { fill: var(--lembas-gold, #C9A227); }
|
|
@media (prefers-color-scheme: dark) {
|
|
.base { fill: var(--lembas-ink, #EDE6D6); }
|
|
.accent { fill: var(--lembas-gold, #E0B252); }
|
|
}
|
|
</style>
|
|
<g transform="translate(4.0 4.0)">
|
|
<rect x="6" y="6" width="52" height="52" rx="13" fill="url(#l-wafer)"/>
|
|
<g clip-path="url(#l-clip)" fill="none" stroke-linecap="round">
|
|
<g stroke="#7A5C10" stroke-opacity="0.38" stroke-width="2">
|
|
<path d="M32 6 V58"/>
|
|
<path d="M6 32 H58"/>
|
|
</g>
|
|
<g stroke="#F6E3A8" stroke-opacity="0.3" stroke-width="1">
|
|
<path d="M33.2 6 V58"/>
|
|
<path d="M6 33.2 H58"/>
|
|
</g>
|
|
</g>
|
|
<rect x="7.1" y="7.1" width="49.8" height="49.8" rx="11.9"
|
|
fill="none" stroke="#7A5C10" stroke-opacity="0.3" stroke-width="1.2"/>
|
|
<g>
|
|
<path d="M21.2 44.8 L17 49.4" stroke="#8A9AA8" stroke-width="3"
|
|
stroke-linecap="round" fill="none"/>
|
|
<path d="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" fill="url(#l-leaf)"/>
|
|
<path d="M20.5 45.5 C28 38 36 29 45.5 18.5" fill="none" stroke="#61758A" stroke-opacity="0.5"
|
|
stroke-width="1.5" stroke-linecap="round"/>
|
|
<g fill="none" stroke="#61758A" stroke-opacity="0.32"
|
|
stroke-width="1" stroke-linecap="round">
|
|
<path d="M26.9 38.8 Q25.2 35.8 24.9 32.1"/>
|
|
<path d="M32.3 33.1 Q30.9 30.3 30.4 26.9"/>
|
|
<path d="M37.8 27.0 Q36.6 24.6 36.3 21.7"/>
|
|
<path d="M26.9 38.8 Q30.5 40.1 33.7 40.3"/>
|
|
<path d="M32.3 33.1 Q35.8 34.3 38.6 34.5"/>
|
|
<path d="M37.8 27.0 Q40.8 27.9 43.2 28.1"/>
|
|
</g>
|
|
</g>
|
|
</g>
|
|
<g transform="translate(85.67 59.00)">
|
|
<path class="accent" data-char="L" d="M2.33 -44.28 7.41 -43.67C7.62 -38.24 7.62 -30.76 7.62 -24.51V-21.49C7.62 -15.10 7.62 -7.41 7.41 -1.92L2.33 -1.30V0.00H32.96L33.78 -13.39H32.47L28.15 -1.72H14.97C14.76 -7.14 14.69 -14.97 14.69 -21.49V-24.51C14.69 -30.76 14.76 -38.24 14.97 -43.67L19.98 -44.28V-45.59H2.33Z"/>
|
|
<path class="accent" data-char="L" d="M37.76 -44.28 42.84 -43.67C43.05 -38.24 43.05 -30.76 43.05 -24.51V-21.49C43.05 -15.10 43.05 -7.41 42.84 -1.92L37.76 -1.30V0.00H68.38L69.21 -13.39H67.90L63.58 -1.72H50.39C50.19 -7.14 50.12 -14.97 50.12 -21.49V-24.51C50.12 -30.76 50.19 -38.24 50.39 -43.67L55.41 -44.28V-45.59H37.76Z"/>
|
|
<path class="base" data-char="e" d="M87.88 -30.48C91.38 -30.48 93.72 -27.74 93.72 -22.59C93.72 -19.57 92.69 -18.54 89.53 -18.54H80.53C81.01 -27.33 84.38 -30.48 87.88 -30.48ZM87.95 0.89C93.10 0.89 97.42 -1.44 99.90 -6.73L98.93 -7.41C96.87 -4.87 94.20 -3.23 90.49 -3.23C84.72 -3.23 80.47 -8.10 80.47 -16.41V-16.96H99.35C99.62 -17.92 99.76 -18.74 99.76 -20.25C99.76 -27.39 94.81 -32.13 87.81 -32.13C80.19 -32.13 73.46 -25.75 73.46 -15.04C73.46 -4.94 79.85 0.89 87.95 0.89Z"/>
|
|
<path class="accent" data-char="M" d="M104.98 0.00H117.81V-1.30L112.32 -1.92V-40.16L126.60 0.00H129.14L143.42 -40.64V-21.49C143.42 -15.10 143.36 -7.35 143.15 -1.92L138.48 -1.30V0.00H155.78V-1.30L150.77 -1.92C150.56 -7.35 150.50 -15.10 150.50 -21.49V-24.51C150.50 -30.76 150.56 -38.24 150.77 -43.67L155.78 -44.28V-45.59H143.15L130.52 -10.16L118.02 -45.59H104.98V-44.28L110.33 -43.60V-1.92L104.98 -1.30Z"/>
|
|
<path class="base" data-char="b" d="M160.38 0.00 171.50 0.76V-4.26C173.84 -0.55 176.93 0.89 180.29 0.89C187.64 0.89 193.13 -5.49 193.13 -16.41C193.13 -26.78 187.84 -32.13 180.98 -32.13C176.79 -32.13 173.56 -29.80 171.50 -26.30V-36.25L171.78 -49.98L171.02 -50.67L160.11 -47.79V-46.69L164.84 -45.59V-14.28C164.84 -10.71 164.78 -5.70 164.64 -1.92L160.38 -1.30ZM178.10 -28.63C182.63 -28.63 186.06 -24.92 186.06 -16.00C186.06 -6.87 182.56 -2.68 178.23 -2.68C175.49 -2.68 173.70 -3.50 171.50 -5.84V-24.79C173.36 -27.12 175.56 -28.63 178.10 -28.63Z"/>
|
|
<path class="base" data-char="a" d="M221.49 0.76C224.58 0.76 226.50 -0.96 227.53 -3.43L226.70 -4.12C225.61 -2.88 224.99 -2.40 223.96 -2.40C222.79 -2.40 222.10 -3.16 222.10 -5.36V-20.67C222.10 -28.63 218.95 -32.13 211.94 -32.13C205.01 -32.13 200.07 -28.90 199.31 -24.24C199.65 -22.38 200.55 -21.35 202.40 -21.35C204.25 -21.35 205.83 -22.59 206.18 -25.54L206.93 -29.87C207.82 -30.14 208.65 -30.28 209.61 -30.28C213.80 -30.28 215.38 -28.15 215.38 -21.42V-19.02C212.77 -18.40 210.57 -17.78 209.06 -17.23C200.48 -14.49 198.14 -11.12 198.14 -6.87C198.14 -1.85 201.64 0.89 206.24 0.89C209.81 0.89 212.70 -0.41 215.44 -3.98C215.93 -0.96 217.92 0.76 221.49 0.76ZM204.73 -8.44C204.73 -11.47 206.11 -13.94 210.78 -16.00C211.67 -16.41 213.25 -16.96 215.38 -17.64V-5.36C213.11 -3.50 211.60 -3.09 209.54 -3.09C206.79 -3.09 204.73 -4.67 204.73 -8.44Z"/>
|
|
<path class="base" data-char="s" d="M240.78 0.89C248.40 0.89 252.59 -2.95 252.59 -8.93C252.59 -14.49 248.47 -16.55 244.42 -18.26L242.50 -19.09C239.13 -20.53 236.25 -22.04 236.25 -25.47C236.25 -28.49 238.44 -30.62 242.29 -30.62C244.01 -30.62 245.38 -30.41 246.61 -29.80L249.57 -21.76H250.73L251.01 -29.73C248.33 -31.31 245.72 -32.13 242.29 -32.13C234.94 -32.13 231.24 -28.01 231.24 -22.66C231.24 -17.23 235.15 -15.10 239.06 -13.46L240.99 -12.63C244.35 -11.19 247.30 -9.75 247.30 -6.25C247.30 -2.95 244.97 -0.55 240.78 -0.55C238.65 -0.55 237.14 -0.82 235.63 -1.37L232.54 -10.23H231.44L231.03 -1.72C234.12 0.00 236.93 0.89 240.78 0.89Z"/>
|
|
</g>
|
|
</svg>
|