diff --git a/CHANGELOG.md b/CHANGELOG.md index 69a7e4e..03fd25f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ turns the section for that version into the release notes shown in the app. fix still corrects spelling with macOS's own spell checker, leaving names and your taught words alone. +### Changed +- The icon's bars are a little heavier, to match the wordmark (GDR-0021). + ### Fixed - Fix, shorten and plain no longer touch Slack mentions and channels, links, email addresses, dates, times, units, versions or abbreviations like diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_1024.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_1024.png index 40eafe3..5b94f41 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_1024.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_1024.png differ diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_128.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_128.png index 579ec62..4533224 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_128.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_128.png differ diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_16.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_16.png index 0d42cbe..78ed7f5 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_16.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_16.png differ diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_256.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_256.png index 18482fa..ae58bdb 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_256.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_256.png differ diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_32.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_32.png index 1e38371..d88e01d 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_32.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_32.png differ diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_512.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_512.png index 6a03be9..955fabe 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_512.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_512.png differ diff --git a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_64.png b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_64.png index f0caca5..f289928 100644 Binary files a/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_64.png and b/apps/Timbre/Sources/Assets.xcassets/AppIcon.appiconset/icon_64.png differ diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 0a8ee05..0f24eb3 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -65,3 +65,5 @@ Two kinds of records live here. The boundary rule: | [0018](gdr/0018-words-appear-as-you-speak.md) | Words appear as you speak; the cleanup replaces them on release | Accepted | | [0019](gdr/0019-outfit-and-a-simpler-drawing.md) | Outfit, served by the site; the keyboard goes; keys are flat (amends 0017) | Accepted | | [0020](gdr/0020-nunito.md) | Nunito: the rounded face (amends 0019) | Accepted | +| [0021](gdr/0021-the-wordmark.md) | The wordmark: bars beside "timbre", stroke 3; an underlined secondary (amends 0019, 0017) | Accepted | +| [0022](gdr/0022-nunito-sans-for-text.md) | Nunito Sans for text; Nunito keeps the headlines (amends 0020) | Accepted | diff --git a/docs/decisions/gdr/0021-the-wordmark.md b/docs/decisions/gdr/0021-the-wordmark.md new file mode 100644 index 0000000..cef0802 --- /dev/null +++ b/docs/decisions/gdr/0021-the-wordmark.md @@ -0,0 +1,23 @@ +# 0021 — The wordmark: the bare bars beside "timbre", stroke 3, with an underlined secondary + +- **Status:** Accepted +- **Date:** 2026-10-14 +- **Amends:** [GDR-0019](0019-outfit-and-a-simpler-drawing.md), point 5; [GDR-0017](0017-retro-identity-one-colour-per-gesture.md), point 3 (where the rainbow sits) + +## Context + +With Nunito chosen (GDR-0020), the wordmark was laid out on the Brand room in every arrangement that was still open: title case and lowercase, the mark tiled and bare, the rounded rainbow under the word, beside it, or absent, and the bars at three weights. Each round narrowed by looking: lowercase first, then the tile dropped beside the word ("if we show the icon with the wordmark we shouldn't show it with a background"), then the doubled rainbow dropped, then the weight. + +## Decision + +1. **The primary wordmark is the bare bars beside "timbre"**, lowercase, Nunito at its heaviest, no underline. The rainbow appears once in a lockup: in the bars. **The secondary is "timbre" with the rounded rainbow beneath it**, no bars — for the places the tiled icon already stands (an App Store listing, a window with the icon in its title) or where the bars would repeat. Never both rainbows in one lockup. +2. **The bars are drawn at stroke 3 of the 32-unit grid**, up from 2.6, everywhere they appear: the favicon, the app icon, the header, the share image. Heavy enough to sit beside Nunito's extra-bold; light enough that the sixteen-pixel icon keeps its gaps. +3. **The tile stays for the icon alone** — the favicon, the Dock, the update prompt — where a box is wanted. Beside the word the tile would be a second box. +4. **The name in prose stays "Timbre."** Lowercase is the drawing, not the spelling. +5. The rounded rainbow underline keeps its place in the headline, under one word, and the stripe keeps its places between sections. The primary wordmark does not carry it; the secondary is where it belongs. + +## Consequences + +- One lockup, drawn once (`Mark.svelte` with `tile={false}`), used by the site header and footer, the Backstage sidebar, the login card and the share image. The secondary is the same word with the `rainbow` bar beneath; the Brand room shows both. +- The app icon set and the favicon are regenerated from the same stroke; `tools/app-icon.swift` and `tools/og-image.swift` carry the number. +- The Brand room keeps every round so the next question starts from the comparison. diff --git a/docs/decisions/gdr/0022-nunito-sans-for-text.md b/docs/decisions/gdr/0022-nunito-sans-for-text.md new file mode 100644 index 0000000..e180808 --- /dev/null +++ b/docs/decisions/gdr/0022-nunito-sans-for-text.md @@ -0,0 +1,21 @@ +# 0022 — Nunito Sans for text; Nunito keeps the headlines + +- **Status:** Accepted +- **Date:** 2026-10-14 +- **Amends:** [GDR-0020](0020-nunito.md), point 1 + +## Context + +Nunito everywhere was friendly and, at paragraph size, a little tiring: rounded terminals on every letter of a long line. Six pairings went on the Brand room, Nunito over a text face each, with the wordmark, a headline, a paragraph and a button. Nunito Sans was chosen, with Inter named as also good. + +## Decision + +1. **Headlines and the wordmark stay Nunito**, at its heaviest, as GDR-0020 and GDR-0021 have it. They are `--font-display`. +2. **Text is Nunito Sans**: regular for paragraphs, semibold for emphasis and buttons. It was drawn as Nunito's companion — the same proportions, square terminals — so the two read as one voice at two sizes. It is `--font-sans`. +3. **Inter is the recorded runner-up.** If Nunito Sans ever reads wrong, Inter is the next thing tried, not another round. +4. Both are served by the site, under the OFL, like everything else in `web/static/fonts`. + +## Consequences + +- Two faces, one family, no decorative third. Labels stay IBM Plex Mono. +- The Brand room marks the pairing in use and keeps the other five. diff --git a/tools/app-icon.swift b/tools/app-icon.swift index 0bd4234..b825982 100644 --- a/tools/app-icon.swift +++ b/tools/app-icon.swift @@ -56,7 +56,7 @@ NSBezierPath(roundedRect: NSRect(x: inset, y: inset, width: tileSide, height: ti let grid = tileSide / 32 let centres: [Double] = [8, 13.3, 18.6, 24] let heights: [Double] = [6, 14, 9, 3] -let width = 2.6 * grid +let width = 3.0 * grid for (i, cx) in centres.enumerated() { let h = heights[i] * grid + width // round caps extend a stroke by half its width each end let x = inset + cx * grid - width / 2 diff --git a/tools/og-image.swift b/tools/og-image.swift index c6b6554..e04458c 100644 --- a/tools/og-image.swift +++ b/tools/og-image.swift @@ -72,7 +72,7 @@ func drawMark(x: Double, y: Double, side: Double) { caseColor.setFill() NSBezierPath(roundedRect: NSRect(x: x, y: y, width: side, height: side), xRadius: side * 7 / 32, yRadius: side * 7 / 32).fill() let grid = side / 32 - let barWidth = 2.6 * grid + let barWidth = 3.0 * grid for (i, cx) in [8.0, 13.3, 18.6, 24.0].enumerated() { let h = [6.0, 14.0, 9.0, 3.0][i] * grid + barWidth [rainbow[0], rainbow[2], rainbow[3], rainbow[4]][i].setFill() @@ -81,9 +81,19 @@ func drawMark(x: Double, y: Double, side: Double) { } drawMark(x: 880, y: 200, side: 260) -// Wordmark, with the small mark beside it, as the header shows it. -drawMark(x: 80, y: 446, side: 64) -draw("Timbre", at: NSPoint(x: 160, y: 436), font: nunito(72, weight: 800), color: ink, kern: -1) +// The tiled icon already stands on this card, so the wordmark is the +// secondary: the word with the rounded rainbow beneath, no bars (GDR-0021). +let wordmark = nunito(76, weight: 800) +draw("timbre", at: NSPoint(x: 80, y: 430), font: wordmark, color: ink, kern: -1.5) +let wordWidth = size(of: "timbre", font: wordmark, kern: -1.5).width +let wordBand = wordWidth / Double(rainbow.count) +NSGraphicsContext.saveGraphicsState() +NSBezierPath(roundedRect: NSRect(x: 82, y: 420, width: wordWidth - 4, height: 9), xRadius: 4.5, yRadius: 4.5).addClip() +for (i, color) in rainbow.enumerated() { + color.setFill() + NSRect(x: 82 + Double(i) * wordBand, y: 420, width: wordBand + 0.5, height: 9).fill() +} +NSGraphicsContext.restoreGraphicsState() // The claim, wrapped by hand, with the rainbow under "never". let headline = nunito(58, weight: 800) @@ -91,10 +101,13 @@ draw("Dictation that", at: NSPoint(x: 80, y: 318), font: headline, color: ink, k draw("never leaves your Mac.", at: NSPoint(x: 80, y: 250), font: headline, color: ink, kern: -1) let neverWidth = size(of: "never", font: headline, kern: -1).width let band = neverWidth / Double(rainbow.count) +NSGraphicsContext.saveGraphicsState() +NSBezierPath(roundedRect: NSRect(x: 80, y: 242, width: neverWidth, height: 8), xRadius: 4, yRadius: 4).addClip() for (i, color) in rainbow.enumerated() { color.setFill() - NSRect(x: 80 + Double(i) * band, y: 246, width: band + 0.5, height: 6).fill() + NSRect(x: 80 + Double(i) * band, y: 242, width: band + 0.5, height: 8).fill() } +NSGraphicsContext.restoreGraphicsState() draw("Zero network requests* · No account · Free · Open source", at: NSPoint(x: 82, y: 170), font: mono, color: muted) draw("timbre.hugopretorius.dev", at: NSPoint(x: 82, y: 124), font: mono, color: ink) diff --git a/web/src/app.css b/web/src/app.css index 3dfc8de..a8aba45 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -156,7 +156,8 @@ --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); - --font-sans: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-sans: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-display: "Nunito", "Nunito Sans", -apple-system, BlinkMacSystemFont, sans-serif; --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace; } @@ -169,12 +170,13 @@ -webkit-font-smoothing: antialiased; } /* Headlines: Nunito at its heaviest, rounded terminals and all — the - friendliness Hugo asked for, in the same family as the text so the - page has one voice (GDR-0020). Rounded faces want less tightening. */ + friendliness Hugo asked for (GDR-0020). Text is Nunito Sans, its own + companion: the same bones, square terminals, easier at small sizes + (GDR-0022). Rounded faces want less tightening. */ h1, h2, h3 { - font-family: var(--font-sans); + font-family: var(--font-display); font-weight: 800; letter-spacing: -0.015em; line-height: 1.08; @@ -187,7 +189,7 @@ /* The headline cut, for anything that is not a heading but should carry it. */ @utility display { - font-family: var(--font-sans); + font-family: var(--font-display); font-weight: 800; letter-spacing: -0.015em; line-height: 1.08; @@ -215,21 +217,32 @@ var(--retro-violet) 83.33% 100% ); } -/* A word underlined with the rainbow: the one emphasis the headline gets. */ -@utility underline-rainbow { - background-image: linear-gradient( - 90deg, - var(--retro-red) 0 16.66%, - var(--retro-orange) 16.66% 33.33%, - var(--retro-yellow) 33.33% 50%, - var(--retro-green) 50% 66.66%, - var(--retro-blue) 66.66% 83.33%, - var(--retro-violet) 83.33% 100% - ); - background-repeat: no-repeat; - background-size: 100% 0.14em; - background-position: 0 92%; - padding-bottom: 0.04em; +/* A word underlined with the rainbow: the one emphasis the headline gets. + A rounded bar beneath the word (GDR-0020's rounded face wants rounded + ends everywhere the rainbow sits). */ +@layer components { + .underline-rainbow { + position: relative; + display: inline-block; + } + .underline-rainbow::after { + content: ""; + position: absolute; + left: 0.02em; + right: 0.02em; + bottom: -0.06em; + height: 0.14em; + border-radius: 999px; + background-image: linear-gradient( + 90deg, + var(--retro-red) 0 16.66%, + var(--retro-orange) 16.66% 33.33%, + var(--retro-yellow) 33.33% 50%, + var(--retro-green) 50% 66.66%, + var(--retro-blue) 66.66% 83.33%, + var(--retro-violet) 83.33% 100% + ); + } } @utility rainbow-text { background-image: linear-gradient( diff --git a/web/src/lib/assets/favicon.svg b/web/src/lib/assets/favicon.svg index adf76b6..6ac7a4e 100644 --- a/web/src/lib/assets/favicon.svg +++ b/web/src/lib/assets/favicon.svg @@ -3,7 +3,7 @@ mark as the app icon (tools/app-icon.swift): charcoal case, four bars in the retro accents (GDR-0017). --> - + diff --git a/web/src/lib/components/marketing/Mark.svelte b/web/src/lib/components/marketing/Mark.svelte index 13a5e7d..60412f9 100644 --- a/web/src/lib/components/marketing/Mark.svelte +++ b/web/src/lib/components/marketing/Mark.svelte @@ -1,20 +1,25 @@ -

Context

\n

Nunito everywhere was friendly and, at paragraph size, a little tiring: rounded terminals on every letter of a long line. Six pairings went on the Brand room, Nunito over a text face each, with the wordmark, a headline, a paragraph and a button. Nunito Sans was chosen, with Inter named as also good.

\n

Decision

\n
    \n
  1. Headlines and the wordmark stay Nunito, at its heaviest, as GDR-0020 and GDR-0021 have it. They are --font-display.
  2. \n
  3. Text is Nunito Sans: regular for paragraphs, semibold for emphasis and buttons. It was drawn as Nunito's companion — the same proportions, square terminals — so the two read as one voice at two sizes. It is --font-sans.
  4. \n
  5. Inter is the recorded runner-up. If Nunito Sans ever reads wrong, Inter is the next thing tried, not another round.
  6. \n
  7. Both are served by the site, under the OFL, like everything else in web/static/fonts.
  8. \n
\n

Consequences

\n
    \n
  • Two faces, one family, no decorative third. Labels stay IBM Plex Mono.
  • \n
  • The Brand room marks the pairing in use and keeps the other five.
  • \n
\n" + }, + { + "id": "GDR-0021", + "kind": "GDR", + "number": "0021", + "slug": "the-wordmark", + "path": "docs/decisions/gdr/0021-the-wordmark.md", + "title": "The wordmark: the bare bars beside \"timbre\", stroke 3, with an underlined secondary", + "status": "Accepted", + "statusKind": "accepted", + "statusNote": null, + "supersededBy": null, + "supersedes": [], + "date": "2026-10-14", + "relations": [ + { + "label": "Amends", + "summary": "GDR-0019, point 5; GDR-0017, point 3 (where the rainbow sits)", + "refs": [ + "GDR-0019", + "GDR-0017" + ] + } + ], + "excerpt": "With Nunito chosen (GDR-0020), the wordmark was laid out on the Brand room in every arrangement that was still open: title case and lowercase, the mark tiled and bare, the rounded rainbow under the word, beside it, or absent, and the bars at three weights. Each round narrowed by looking: lowercase first, then the tile dropped beside the word (\"if we show…", + "plain": "Accepted.\nContext.\nWith Nunito chosen (GDR-0020), the wordmark was laid out on the Brand room in every arrangement that was still open: title case and lowercase, the mark tiled and bare, the rounded rainbow under the word, beside it, or absent, and the bars at three weights. Each round narrowed by looking: lowercase first, then the tile dropped beside the word (\"if we show the icon with the wordmark we shouldn't show it with a background\"), then the doubled rainbow dropped, then the weight.\nDecision.\n1. The primary wordmark is the bare bars beside \"timbre\", lowercase, Nunito at its heaviest, no underline. The rainbow appears once in a lockup: in the bars. The secondary is \"timbre\" with the rounded rainbow beneath it, no bars — for the places the tiled icon already stands (an App Store listing, a window with the icon in its title) or where the bars would repeat. Never both rainbows in one lockup.\n2. The bars are drawn at stroke 3 of the 32-unit grid, up from 2.6, everywhere they appear: the favicon, the app icon, the header, the share image. Heavy enough to sit beside Nunito's extra-bold; light enough that the sixteen-pixel icon keeps its gaps.\n3. The tile stays for the icon alone — the favicon, the Dock, the update prompt — where a box is wanted. Beside the word the tile would be a second box.\n4. The name in prose stays \"Timbre.\" Lowercase is the drawing, not the spelling.\n5. The rounded rainbow underline keeps its place in the headline, under one word, and the stripe keeps its places between sections. The primary wordmark does not carry it; the secondary is where it belongs.\nConsequences.\nOne lockup, drawn once (Mark.svelte with tile={false}), used by the site header and footer, the Backstage sidebar, the login card and the share image. The secondary is the same word with the rainbow bar beneath; the Brand room shows both.\nThe app icon set and the favicon are regenerated from the same stroke; tools/app-icon.swift and tools/og-image.swift carry the number.\nThe Brand room keeps every round so the next question starts from the comparison.", + "html": "

Context

\n

With Nunito chosen (GDR-0020), the wordmark was laid out on the Brand room in every arrangement that was still open: title case and lowercase, the mark tiled and bare, the rounded rainbow under the word, beside it, or absent, and the bars at three weights. Each round narrowed by looking: lowercase first, then the tile dropped beside the word ("if we show the icon with the wordmark we shouldn't show it with a background"), then the doubled rainbow dropped, then the weight.

\n

Decision

\n
    \n
  1. The primary wordmark is the bare bars beside "timbre", lowercase, Nunito at its heaviest, no underline. The rainbow appears once in a lockup: in the bars. The secondary is "timbre" with the rounded rainbow beneath it, no bars — for the places the tiled icon already stands (an App Store listing, a window with the icon in its title) or where the bars would repeat. Never both rainbows in one lockup.
  2. \n
  3. The bars are drawn at stroke 3 of the 32-unit grid, up from 2.6, everywhere they appear: the favicon, the app icon, the header, the share image. Heavy enough to sit beside Nunito's extra-bold; light enough that the sixteen-pixel icon keeps its gaps.
  4. \n
  5. The tile stays for the icon alone — the favicon, the Dock, the update prompt — where a box is wanted. Beside the word the tile would be a second box.
  6. \n
  7. The name in prose stays "Timbre." Lowercase is the drawing, not the spelling.
  8. \n
  9. The rounded rainbow underline keeps its place in the headline, under one word, and the stripe keeps its places between sections. The primary wordmark does not carry it; the secondary is where it belongs.
  10. \n
\n

Consequences

\n
    \n
  • One lockup, drawn once (Mark.svelte with tile={false}), used by the site header and footer, the Backstage sidebar, the login card and the share image. The secondary is the same word with the rainbow bar beneath; the Brand room shows both.
  • \n
  • The app icon set and the favicon are regenerated from the same stroke; tools/app-icon.swift and tools/og-image.swift carry the number.
  • \n
  • The Brand room keeps every round so the next question starts from the comparison.
  • \n
\n" + }, { "id": "GDR-0020", "kind": "GDR", diff --git a/web/src/lib/releases/releases.json b/web/src/lib/releases/releases.json index 515bd4e..5795211 100644 --- a/web/src/lib/releases/releases.json +++ b/web/src/lib/releases/releases.json @@ -10,12 +10,16 @@ "name": "Added", "html": "
    \n
  • Words appear as you speak. Confirmed words are typed into the app\nwhile you are still talking, a sentence or so behind your voice, and the\ncleanup replaces them the moment you let go. The pill now shows only the\nwords still being heard. Off in Settings › General if you would rather\nkeep everything in the pill until release. Where an app cannot be read\nback — Terminal, secure fields — the pill-then-paste flow remains.
  • \n
  • An icon. The waveform from the website's favicon — four bars, the\nshape of a voice — on a charcoal tile, in the retro colours. Timbre had\nshipped with Xcode's placeholder until now.
  • \n
  • A disk image. The download is now a .dmg with an Applications\nfolder to drag Timbre onto; the zip remains for updates and for anyone\nwho prefers it.
  • \n
  • A usage count in Settings — words dictated, dictations, commands,\nto-dos and readings, this week and all time. Stored in this Mac's\npreferences and nowhere else.
  • \n
  • To-dos by voice. Hold right Command with nothing selected and say it —\n"call the dentist Thursday" — and it lands in a Timbre list in Apple's\nReminders, with the date read on your Mac, so it's on your iPhone too. Tap\nleft Option with nothing selected to hear the list. Pick any list in\nSettings.
  • \n
  • Plain. A fourth command: hold right Command on machine-sounding or\ncorporate text and say "plain" to get what it actually says, in your\nown words.
  • \n
  • Fix without Apple Intelligence. On a Mac without the on-device model,\nfix still corrects spelling with macOS's own spell checker, leaving names\nand your taught words alone.
  • \n
\n" }, + { + "name": "Changed", + "html": "
    \n
  • The icon's bars are a little heavier, to match the wordmark (GDR-0021).
  • \n
\n" + }, { "name": "Fixed", "html": "
    \n
  • Fix, shorten and plain no longer touch Slack mentions and channels, links,\nemail addresses, dates, times, units, versions or abbreviations like\n"e.g." — they come back exactly as they were.
  • \n
  • Fixing a single selected word keeps its case: "teh" becomes "the", not\n"The".
  • \n
\n" } ], - "items": 9 + "items": 10 }, { "version": "0.3.1", diff --git a/web/src/routes/(public)/+layout.svelte b/web/src/routes/(public)/+layout.svelte index e634e0b..0a209c7 100644 --- a/web/src/routes/(public)/+layout.svelte +++ b/web/src/routes/(public)/+layout.svelte @@ -19,9 +19,9 @@