// The Housecarl logo and the login page's wordmark, drawn as inline SVG so // they appear together with the page instead of loading afterwards. // // The "HOUSECARL" wordmark: the angular letters of Jarl's and Steward's // wordmarks (A, R and L are Jarl's, S and E Steward's), with an H whose // crossbar rises like the doorway's roof. Drawn as paths so no font is // needed. The login page shows it over a rule with an FW node; the header // shows the letters alone. The letters use the text color and the rule the // accent color. import * as logoData from "./logo.js"; const NS = "http://www.w3.org/2000/svg"; function el(tag, attrs, ...children) { const e = document.createElementNS(NS, tag); for (const [k, v] of Object.entries(attrs || {})) e.setAttribute(k, v); for (const c of children) e.append(c instanceof Node ? c : document.createTextNode(c)); return e; } // Letters on a 100-unit cap height; counters are cut with evenodd. const letters = [ // H: two stems; the crossbar rises to a peak, like the doorway's roof { x: 0, d: "M0 0 H18 V40 L32 32 L46 40 V0 H64 V100 H46 V58 L32 50 L18 58 V100 H0 Z" }, // O: an octagon, with the cut corners of R's bowl { x: 76, d: "M20 0 H44 L64 20 V80 L44 100 H20 L0 80 V20 Z M24 16 H40 L46 22 V78 L40 84 H24 L18 78 V22 Z" }, // U: cut corners at the foot { x: 152, d: "M0 0 H18 V78 L24 84 H40 L46 78 V0 H64 V80 L44 100 H20 L0 80 Z" }, // S and E: Steward's { x: 228, d: "M10 0 H54 L58 30 L40 16 H18 V41 H48 L58 51 V90 L48 100 H4 L0 70 L18 84 H40 V59 H10 L0 49 V10 Z" }, { x: 298, d: "M0 0 H52 L56 18 H18 V41 H44 V59 H18 V82 H40 L58 70 L54 100 H0 Z" }, // C: S's downward barb at the top, E's upswept spike at the foot { x: 368, d: "M20 0 H56 L60 30 L42 16 H24 L18 22 V78 L24 84 H42 L60 70 L56 100 H20 L0 80 V20 Z" }, // A, R and L: Jarl's { x: 440, d: "M35 0 L46 10 L64 90 L70 100 H50 L44 76 L35 62 L26 76 L20 100 H0 L6 90 L24 10 Z M35 26 L41 40 L35 54 L29 40 Z" }, { x: 522, d: "M0 0 H48 L60 12 V40 L50 50 L66 100 H46 L34 60 H18 V100 H0 Z M18 14 H41 L46 19 V35 L41 46 H18 Z" }, { x: 600, d: "M0 0 H18 V84 H40 L58 70 L54 100 H0 Z" }, ]; const W = 658; // the letters' width // wordmark returns the login page's wordmark, letters over the rule. // wordmark({ rule: false, height: 19, cls: "brand-name" }) returns just the // letters, height pixels tall. export function wordmark({ rule = true, height, cls = "wordmark" } = {}) { const letterG = el("g", { fill: "currentColor", "fill-rule": "evenodd" }, ...letters.map((l) => el("path", { d: l.d, transform: `translate(${l.x} 0)` }))); if (!rule) { const attrs = { class: cls, viewBox: `-2 -2 ${W + 4} 104`, role: "img", "aria-label": "Housecarl" }; if (height) Object.assign(attrs, { height, width: Math.round(height * (W + 4) / 104) }); return el("svg", attrs, el("title", null, "Housecarl"), letterG); } const c = W / 2; const ruleG = el("g", { class: "wordmark-rule", transform: "translate(0 118)" }, el("path", { d: `M2 18 L${c - 60} 15.6 V20.4 Z M${W - 2} 18 L${c + 60} 15.6 V20.4 Z`, class: "fill" }), el("circle", { cx: c - 52, cy: 18, r: 4.6, class: "line" }), el("path", { d: `M${c - 47.4} 18 H${c - 24} M${c + 24} 18 H${c + 47.4}`, class: "line" }), el("circle", { cx: c, cy: 18, r: 24, class: "line" }), el("circle", { cx: c + 52, cy: 18, r: 4.6, class: "line" }), el("text", { x: c, y: 24.5, "text-anchor": "middle", class: "tag" }, "FW")); return el("svg", { class: cls, viewBox: `-4 -4 ${W + 8} 176`, role: "img", "aria-label": "Housecarl" }, el("title", null, "Housecarl"), letterG, ruleG); } // logo returns the Housecarl logo (artwork/logo.svg, via scripts/logo.py) // as an SVG of the given size in pixels: the full doorway, or with small // the one without carvings (for sizes under about 64 pixels). Its color // is the .logo-mark rule in style.css. export function logo(size, { small = false, cls = "logo" } = {}) { return el("svg", { class: cls, width: size, height: size, viewBox: logoData.viewBox, "aria-hidden": "true", focusable: "false" }, el("path", { d: small ? logoData.small : logoData.full, "fill-rule": "evenodd", class: "logo-mark" })); }