@goplusvn/core 0.1.72 → 0.1.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/branding/__tests__/identity.test.ts +101 -0
- package/src/branding/__tests__/logo-route.test.ts +143 -0
- package/src/branding/identity.ts +74 -0
- package/src/branding/index.ts +36 -0
- package/src/branding/logo-route.ts +249 -0
- package/src/branding/pwa.tsx +146 -0
- package/src/branding/types.ts +45 -0
- package/src/providers/tenant-provider.tsx +10 -0
- package/src/styles/base.css +16 -0
- package/src/ui/auth/auth-layout.tsx +183 -21
- package/src/ui/errors/error-view.tsx +80 -87
- package/src/ui/errors/index.ts +6 -1
- package/src/ui/errors/not-found-view.tsx +89 -16
- package/src/ui/errors/status-page.tsx +132 -0
- package/src/ui/layout/logo.tsx +5 -0
- package/src/ui/pages/not-found.tsx +11 -27
- package/templates/starter-app/next.config.mjs +8 -0
- package/templates/starter-app/package.json +1 -0
- package/templates/starter-app/public/images/illustrations/characters/character-01.svg +33 -0
- package/templates/starter-app/public/images/illustrations/characters/character-02.svg +30 -0
- package/templates/starter-app/public/images/illustrations/characters/character-03.svg +30 -0
- package/templates/starter-app/public/images/illustrations/characters/character-04.svg +27 -0
- package/templates/starter-app/public/images/logos/goeat_logo.png +0 -0
- package/templates/starter-app/src/app/[lang]/(main)/admin/system/company/company-profile-form.tsx +21 -5
- package/templates/starter-app/src/app/[lang]/(plain)/sign-in/page.tsx +5 -4
- package/templates/starter-app/src/app/[lang]/layout.tsx +26 -1
- package/templates/starter-app/src/app/api/branding/logo/route.ts +25 -0
- package/templates/starter-app/src/app/layout.tsx +42 -1
- package/templates/starter-app/src/app/manifest.ts +23 -19
- package/templates/starter-app/src/configs/tenant.ts +6 -1
- package/templates/starter-app/src/providers/index.tsx +12 -2
- package/templates/starter-app/src/proxy.ts +3 -1
|
@@ -2,14 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState } from "react"
|
|
4
4
|
import Link from "next/link"
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
CardHeader,
|
|
10
|
-
CardTitle,
|
|
11
|
-
} from "../index"
|
|
12
|
-
import { AlertTriangle, Check, Copy, Home, RefreshCw } from "lucide-react"
|
|
5
|
+
import { Button } from "../index"
|
|
6
|
+
import { Check, Copy, Home, RefreshCw } from "lucide-react"
|
|
7
|
+
|
|
8
|
+
import { StatusPage, STATUS_ILLUSTRATION } from "./status-page"
|
|
13
9
|
|
|
14
10
|
|
|
15
11
|
interface ErrorViewProps {
|
|
@@ -39,12 +35,19 @@ interface ErrorViewProps {
|
|
|
39
35
|
* `error.message` bị Next thay bằng câu chung chung nên ghi thêm chỉ đẻ rác.
|
|
40
36
|
* Vì vậy chỉ POST khi KHÔNG có digest — đó mới là lỗi runtime trình duyệt,
|
|
41
37
|
* khoảng trống mà server không thấy.
|
|
38
|
+
*
|
|
39
|
+
* **Về hình thức**: dùng chung `StatusPage` với 404/403/400 — cùng bố cục của
|
|
40
|
+
* trang 404 trong bộ kit (hình minh hoạ + mã lỗi lớn + một câu + hàng nút).
|
|
41
|
+
* Trang lỗi là chỗ người dùng đang bực; hình vẽ nét mộc làm nó bớt lạnh, nhưng
|
|
42
|
+
* KHÔNG tô màu cảnh báo lòe loẹt và không có gì nhấp nháy: đây là lúc hỏng
|
|
43
|
+
* việc, không phải lúc đùa. Mã lỗi vẫn là chip mono chép được — phần duy nhất
|
|
44
|
+
* thật sự hữu ích ở màn này.
|
|
42
45
|
*/
|
|
43
46
|
export function ErrorView({
|
|
44
47
|
error,
|
|
45
48
|
reset,
|
|
46
|
-
title = "
|
|
47
|
-
description = "
|
|
49
|
+
title = "Trang gặp sự cố",
|
|
50
|
+
description = "Lỗi kỹ thuật tạm thời, dữ liệu của bạn không mất. Bạn thử lại một lần xem sao; nếu vẫn vậy, gửi mã lỗi bên dưới cho quản trị viên.",
|
|
48
51
|
showHome = true,
|
|
49
52
|
fullScreen = false,
|
|
50
53
|
}: ErrorViewProps) {
|
|
@@ -78,87 +81,77 @@ export function ErrorView({
|
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
className="h-
|
|
102
|
-
|
|
103
|
-
title="Sao chép mã lỗi"
|
|
104
|
-
>
|
|
105
|
-
{copied ? (
|
|
106
|
-
<Check className="h-3.5 w-3.5 text-emerald-600" />
|
|
107
|
-
) : (
|
|
108
|
-
<Copy className="h-3.5 w-3.5" />
|
|
109
|
-
)}
|
|
110
|
-
</Button>
|
|
111
|
-
</div>
|
|
112
|
-
) : null}
|
|
113
|
-
|
|
114
|
-
{/* Chi tiết kỹ thuật chỉ mở ở máy dev. Trên production Next đã thay
|
|
115
|
-
`message` bằng câu chung chung nên hiện ra cũng không giúp gì, mà
|
|
116
|
-
còn dễ lộ đường dẫn nội bộ. */}
|
|
117
|
-
{process.env.NODE_ENV === "development" && error.stack ? (
|
|
118
|
-
<details className="rounded-md border border-border bg-muted/40 p-3">
|
|
119
|
-
<summary className="cursor-pointer text-xs font-medium text-muted-foreground">
|
|
120
|
-
Chi tiết kỹ thuật (chỉ hiện khi chạy dev)
|
|
121
|
-
</summary>
|
|
122
|
-
<pre className="mt-2 max-h-64 overflow-auto whitespace-pre-wrap break-all text-[11px] leading-relaxed text-muted-foreground">
|
|
123
|
-
{error.stack}
|
|
124
|
-
</pre>
|
|
125
|
-
</details>
|
|
126
|
-
) : null}
|
|
127
|
-
|
|
128
|
-
<div className="flex flex-wrap gap-2">
|
|
129
|
-
{reset ? (
|
|
130
|
-
<Button onClick={reset}>
|
|
131
|
-
<RefreshCw className="mr-2 h-4 w-4" />
|
|
132
|
-
Thử lại
|
|
133
|
-
</Button>
|
|
134
|
-
) : null}
|
|
135
|
-
<Button variant="outline" onClick={() => window.location.reload()}>
|
|
136
|
-
Tải lại trang
|
|
84
|
+
const details = (
|
|
85
|
+
<>
|
|
86
|
+
{error.digest ? (
|
|
87
|
+
<div className="flex items-center gap-2 rounded-md border border-border bg-muted/40 py-1 pl-2.5 pr-1">
|
|
88
|
+
<span className="shrink-0 text-[11px] uppercase tracking-wide text-muted-foreground">
|
|
89
|
+
Mã lỗi
|
|
90
|
+
</span>
|
|
91
|
+
<code className="min-w-0 flex-1 truncate font-mono text-xs text-foreground">
|
|
92
|
+
{error.digest}
|
|
93
|
+
</code>
|
|
94
|
+
<Button
|
|
95
|
+
variant="ghost"
|
|
96
|
+
size="icon-xs"
|
|
97
|
+
className="shrink-0 text-muted-foreground"
|
|
98
|
+
onClick={handleCopy}
|
|
99
|
+
title="Sao chép mã lỗi"
|
|
100
|
+
>
|
|
101
|
+
{copied ? (
|
|
102
|
+
<Check className="h-3.5 w-3.5 text-emerald-600" />
|
|
103
|
+
) : (
|
|
104
|
+
<Copy className="h-3.5 w-3.5" />
|
|
105
|
+
)}
|
|
137
106
|
</Button>
|
|
138
|
-
{showHome ? (
|
|
139
|
-
<Button variant="ghost" asChild>
|
|
140
|
-
<Link href="/">
|
|
141
|
-
<Home className="mr-2 h-4 w-4" />
|
|
142
|
-
Về trang chủ
|
|
143
|
-
</Link>
|
|
144
|
-
</Button>
|
|
145
|
-
) : null}
|
|
146
107
|
</div>
|
|
147
|
-
|
|
148
|
-
</Card>
|
|
149
|
-
)
|
|
108
|
+
) : null}
|
|
150
109
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
110
|
+
{/* Chi tiết kỹ thuật chỉ mở ở máy dev. Trên production Next đã thay
|
|
111
|
+
`message` bằng câu chung chung nên hiện ra cũng không giúp gì, mà
|
|
112
|
+
còn dễ lộ đường dẫn nội bộ. */}
|
|
113
|
+
{process.env.NODE_ENV === "development" && error.stack ? (
|
|
114
|
+
<details className="group rounded-md border border-border bg-muted/40 px-2.5 py-1.5">
|
|
115
|
+
<summary className="cursor-pointer list-none text-[11px] font-medium text-muted-foreground select-none hover:text-foreground">
|
|
116
|
+
<span className="mr-1 inline-block transition-transform group-open:rotate-90">
|
|
117
|
+
›
|
|
118
|
+
</span>
|
|
119
|
+
Chi tiết kỹ thuật (chỉ hiện khi chạy dev)
|
|
120
|
+
</summary>
|
|
121
|
+
<pre className="mt-2 max-h-56 overflow-auto whitespace-pre-wrap break-all font-mono text-[11px] leading-relaxed text-muted-foreground">
|
|
122
|
+
{error.stack}
|
|
123
|
+
</pre>
|
|
124
|
+
</details>
|
|
125
|
+
) : null}
|
|
126
|
+
</>
|
|
127
|
+
)
|
|
158
128
|
|
|
159
129
|
return (
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
|
|
130
|
+
<StatusPage
|
|
131
|
+
code="500"
|
|
132
|
+
title={title}
|
|
133
|
+
description={description}
|
|
134
|
+
illustration={STATUS_ILLUSTRATION.error}
|
|
135
|
+
fullScreen={fullScreen}
|
|
136
|
+
extra={error.digest || process.env.NODE_ENV === "development" ? details : null}
|
|
137
|
+
>
|
|
138
|
+
{reset ? (
|
|
139
|
+
<Button onClick={reset}>
|
|
140
|
+
<RefreshCw className="mr-1.5 h-4 w-4" />
|
|
141
|
+
Thử lại
|
|
142
|
+
</Button>
|
|
143
|
+
) : null}
|
|
144
|
+
<Button variant="outline" onClick={() => window.location.reload()}>
|
|
145
|
+
Tải lại trang
|
|
146
|
+
</Button>
|
|
147
|
+
{showHome ? (
|
|
148
|
+
<Button variant="ghost" className="text-muted-foreground" asChild>
|
|
149
|
+
<Link href="/">
|
|
150
|
+
<Home className="mr-1.5 h-4 w-4" />
|
|
151
|
+
Về trang chủ
|
|
152
|
+
</Link>
|
|
153
|
+
</Button>
|
|
154
|
+
) : null}
|
|
155
|
+
</StatusPage>
|
|
163
156
|
)
|
|
164
157
|
}
|
package/src/ui/errors/index.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
import Link from "next/link"
|
|
3
3
|
import { Button } from "../index"
|
|
4
|
-
import { FileQuestion } from "lucide-react"
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import { StatusPage, STATUS_ILLUSTRATION } from "./status-page"
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
|
-
* Màn "không tìm thấy" cho `not-found.tsx`. Tách khỏi `NotFoundPage` của
|
|
10
|
-
* bản
|
|
11
|
-
*
|
|
8
|
+
* Màn "không tìm thấy" cho `not-found.tsx`. Tách khỏi `NotFoundPage` của kit vì
|
|
9
|
+
* bản kit là tiếng Anh và `min-h-screen` cứng (tràn khi nằm trong vỏ app có
|
|
10
|
+
* sidebar) — còn bố cục thì dùng lại nguyên qua `StatusPage`.
|
|
12
11
|
*
|
|
13
12
|
* Đây là màn cho `notFound()` gọi TỪ TRONG trang — chứng từ bị xoá, id sai, hết
|
|
14
13
|
* quyền xem. Khác với URL gõ sai: cái đó do `[lang]/[...not-found]/page.tsx` lo.
|
|
@@ -25,20 +24,94 @@ export function NotFoundView({
|
|
|
25
24
|
fullScreen?: boolean
|
|
26
25
|
}) {
|
|
27
26
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
<StatusPage
|
|
28
|
+
code="404"
|
|
29
|
+
title={title}
|
|
30
|
+
description={description}
|
|
31
|
+
illustration={STATUS_ILLUSTRATION.notFound}
|
|
32
|
+
fullScreen={fullScreen}
|
|
33
33
|
>
|
|
34
|
-
<FileQuestion className="h-12 w-12 text-muted-foreground" />
|
|
35
|
-
<div className="space-y-1">
|
|
36
|
-
<h1 className="text-xl font-bold">{title}</h1>
|
|
37
|
-
<p className="max-w-md text-sm text-muted-foreground">{description}</p>
|
|
38
|
-
</div>
|
|
39
34
|
<Button asChild>
|
|
40
35
|
<Link href={homeHref}>Về trang chủ</Link>
|
|
41
36
|
</Button>
|
|
42
|
-
</
|
|
37
|
+
</StatusPage>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Màn "không có quyền". Trước đây app không có màn này: `requirePageAccess`
|
|
43
|
+
* lặng lẽ đẩy người dùng về trang chủ, nên người bị thiếu quyền chỉ thấy mình
|
|
44
|
+
* "bị bật ra" mà không biết vì sao và phải xin ai.
|
|
45
|
+
*/
|
|
46
|
+
export function ForbiddenView({
|
|
47
|
+
title = "Bạn không có quyền vào trang này",
|
|
48
|
+
description = "Tài khoản của bạn chưa được cấp quyền cho chức năng này. Nếu cần dùng, hãy báo quản trị viên kèm tên quyền bên dưới.",
|
|
49
|
+
permission,
|
|
50
|
+
homeHref = "/",
|
|
51
|
+
fullScreen = false,
|
|
52
|
+
}: {
|
|
53
|
+
title?: string
|
|
54
|
+
description?: string
|
|
55
|
+
/** Mã quyền còn thiếu, dạng `resource:action` — thứ quản trị viên cần để tick. */
|
|
56
|
+
permission?: string
|
|
57
|
+
homeHref?: string
|
|
58
|
+
fullScreen?: boolean
|
|
59
|
+
}) {
|
|
60
|
+
return (
|
|
61
|
+
<StatusPage
|
|
62
|
+
code="403"
|
|
63
|
+
title={title}
|
|
64
|
+
description={description}
|
|
65
|
+
illustration={STATUS_ILLUSTRATION.forbidden}
|
|
66
|
+
fullScreen={fullScreen}
|
|
67
|
+
extra={
|
|
68
|
+
permission ? (
|
|
69
|
+
<div className="flex items-center gap-2 rounded-md border border-border bg-muted/40 px-2.5 py-1.5">
|
|
70
|
+
<span className="shrink-0 text-[11px] uppercase tracking-wide text-muted-foreground">
|
|
71
|
+
Quyền cần cấp
|
|
72
|
+
</span>
|
|
73
|
+
<code className="min-w-0 flex-1 truncate font-mono text-xs text-foreground">
|
|
74
|
+
{permission}
|
|
75
|
+
</code>
|
|
76
|
+
</div>
|
|
77
|
+
) : null
|
|
78
|
+
}
|
|
79
|
+
>
|
|
80
|
+
<Button asChild>
|
|
81
|
+
<Link href={homeHref}>Về trang chủ</Link>
|
|
82
|
+
</Button>
|
|
83
|
+
</StatusPage>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Màn "yêu cầu không hợp lệ" (400): tham số trên URL sai kiểu, thiếu mã, ngày
|
|
89
|
+
* không đọc được. Khác 404 ở chỗ đường dẫn có tồn tại — chỉ dữ liệu gửi kèm là
|
|
90
|
+
* sai, nên lối thoát là quay lại chứ không phải về trang chủ.
|
|
91
|
+
*/
|
|
92
|
+
export function BadRequestView({
|
|
93
|
+
title = "Yêu cầu không hợp lệ",
|
|
94
|
+
description = "Đường dẫn hoặc bộ lọc kèm theo không đúng định dạng nên trang không mở được. Hãy quay lại và thao tác từ danh sách.",
|
|
95
|
+
homeHref = "/",
|
|
96
|
+
fullScreen = false,
|
|
97
|
+
}: {
|
|
98
|
+
title?: string
|
|
99
|
+
description?: string
|
|
100
|
+
homeHref?: string
|
|
101
|
+
fullScreen?: boolean
|
|
102
|
+
}) {
|
|
103
|
+
return (
|
|
104
|
+
<StatusPage
|
|
105
|
+
code="400"
|
|
106
|
+
title={title}
|
|
107
|
+
description={description}
|
|
108
|
+
illustration={STATUS_ILLUSTRATION.invalid}
|
|
109
|
+
fullScreen={fullScreen}
|
|
110
|
+
>
|
|
111
|
+
<Button onClick={() => window.history.back()}>Quay lại</Button>
|
|
112
|
+
<Button variant="outline" asChild>
|
|
113
|
+
<Link href={homeHref}>Về trang chủ</Link>
|
|
114
|
+
</Button>
|
|
115
|
+
</StatusPage>
|
|
43
116
|
)
|
|
44
117
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useState } from "react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../utils"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Khung chung cho MỌI màn trạng thái: 404, 403, 400, lỗi hệ thống.
|
|
9
|
+
*
|
|
10
|
+
* Bố cục là của trang 404 sẵn có trong bộ kit (`ui/pages/not-found.tsx`): hình
|
|
11
|
+
* minh hoạ nằm cạnh mã lỗi cỡ lớn, tiêu đề lồng dưới mã, rồi một câu giải
|
|
12
|
+
* thích và hàng nút. Không vẽ mới — việc ở đây là gom thành một khung dùng
|
|
13
|
+
* chung, dịch sang tiếng Việt, và sửa ba chỗ khiến bản kit không dùng được
|
|
14
|
+
* trong app thật:
|
|
15
|
+
*
|
|
16
|
+
* 1. `min-h-screen` cứng ⇒ tràn khi màn nằm trong vỏ app có sidebar. Nay chọn
|
|
17
|
+
* theo `fullScreen`, và cỡ chữ/hình co lại khi nhúng — trang chiếm cả màn
|
|
18
|
+
* thì nói to được, còn thay mỗi vùng nội dung mà vẫn hét cỡ 60px thì lạc
|
|
19
|
+
* quẻ với phần còn lại của app.
|
|
20
|
+
* 2. Hình kit là nét đen trên nền trong suốt ⇒ **tàng hình ở dark mode**. Nay
|
|
21
|
+
* `dark:invert`.
|
|
22
|
+
* 3. App nào chưa chép `public/images/illustrations` sẽ hiện ô ảnh vỡ. Nay
|
|
23
|
+
* `onError` ⇒ bỏ hình, phần chữ vẫn đủ nghĩa.
|
|
24
|
+
*/
|
|
25
|
+
export function StatusPage({
|
|
26
|
+
code,
|
|
27
|
+
title,
|
|
28
|
+
description,
|
|
29
|
+
illustration,
|
|
30
|
+
fullScreen = false,
|
|
31
|
+
children,
|
|
32
|
+
extra,
|
|
33
|
+
}: {
|
|
34
|
+
/** Mã trạng thái, hiện cỡ lớn. Bỏ trống khi không có mã (lỗi phía client). */
|
|
35
|
+
code?: string
|
|
36
|
+
title: string
|
|
37
|
+
description?: string
|
|
38
|
+
/** Đường dẫn hình trong `public/` của app. Thiếu file thì tự bỏ hình. */
|
|
39
|
+
illustration?: string
|
|
40
|
+
fullScreen?: boolean
|
|
41
|
+
/** Hàng nút hành động. */
|
|
42
|
+
children?: React.ReactNode
|
|
43
|
+
/** Khối phụ giữa mô tả và nút — mã lỗi, chi tiết kỹ thuật… */
|
|
44
|
+
extra?: React.ReactNode
|
|
45
|
+
}) {
|
|
46
|
+
const [imageBroken, setImageBroken] = useState(false)
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
className={cn(
|
|
51
|
+
// `w-full` bắt buộc: boundary tầng [lang] thay cả vỏ app nhưng vẫn nằm
|
|
52
|
+
// trong SidebarProvider (`display:flex`) — thiếu nó thì khối co lại
|
|
53
|
+
// bằng nội dung và dán vào mép trái dù đã `justify-center`.
|
|
54
|
+
"flex w-full flex-col items-center justify-center gap-6 p-6 text-center",
|
|
55
|
+
fullScreen ? "min-h-screen bg-background" : "min-h-0 flex-1"
|
|
56
|
+
)}
|
|
57
|
+
>
|
|
58
|
+
<div
|
|
59
|
+
className={cn(
|
|
60
|
+
"motion-safe:animate-status-in flex flex-col-reverse items-center justify-center gap-4",
|
|
61
|
+
"sm:flex-row sm:gap-6 sm:text-start"
|
|
62
|
+
)}
|
|
63
|
+
>
|
|
64
|
+
{illustration && !imageBroken ? (
|
|
65
|
+
// <img> chứ không phải next/image: cần `onError` để app thiếu file
|
|
66
|
+
// ảnh vẫn ra màn tử tế, và không phải khai `images` trong next.config.
|
|
67
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
68
|
+
<img
|
|
69
|
+
src={illustration}
|
|
70
|
+
alt=""
|
|
71
|
+
aria-hidden
|
|
72
|
+
onError={() => setImageBroken(true)}
|
|
73
|
+
className={cn(
|
|
74
|
+
"w-auto select-none dark:invert",
|
|
75
|
+
fullScreen ? "h-40 sm:h-48" : "h-28 sm:h-36"
|
|
76
|
+
)}
|
|
77
|
+
/>
|
|
78
|
+
) : null}
|
|
79
|
+
|
|
80
|
+
<h1
|
|
81
|
+
className={cn(
|
|
82
|
+
"inline-grid font-black leading-none tracking-tight text-foreground",
|
|
83
|
+
fullScreen ? "text-5xl sm:text-6xl" : "text-4xl"
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
{code}
|
|
87
|
+
<span
|
|
88
|
+
className={cn(
|
|
89
|
+
"font-semibold text-balance leading-snug",
|
|
90
|
+
code ? "mt-2" : null,
|
|
91
|
+
fullScreen ? "text-2xl sm:text-3xl" : "text-lg"
|
|
92
|
+
)}
|
|
93
|
+
>
|
|
94
|
+
{title}
|
|
95
|
+
</span>
|
|
96
|
+
</h1>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
{description ? (
|
|
100
|
+
<p
|
|
101
|
+
className={cn(
|
|
102
|
+
"motion-safe:animate-status-in max-w-prose text-pretty leading-relaxed text-muted-foreground [animation-delay:60ms]",
|
|
103
|
+
fullScreen ? "text-base" : "text-sm"
|
|
104
|
+
)}
|
|
105
|
+
>
|
|
106
|
+
{description}
|
|
107
|
+
</p>
|
|
108
|
+
) : null}
|
|
109
|
+
|
|
110
|
+
{extra ? (
|
|
111
|
+
<div className="motion-safe:animate-status-in w-full max-w-md space-y-2 text-left [animation-delay:100ms]">
|
|
112
|
+
{extra}
|
|
113
|
+
</div>
|
|
114
|
+
) : null}
|
|
115
|
+
|
|
116
|
+
{children ? (
|
|
117
|
+
<div className="motion-safe:animate-status-in flex flex-wrap items-center justify-center gap-2 [animation-delay:140ms]">
|
|
118
|
+
{children}
|
|
119
|
+
</div>
|
|
120
|
+
) : null}
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Hình của bộ kit, dùng lại nguyên — app chép sẵn trong `public/`. */
|
|
126
|
+
export const STATUS_ILLUSTRATION = {
|
|
127
|
+
/** Bản kit vốn dùng hình này cho 404. Giữ nguyên để không đổi cái đã quen. */
|
|
128
|
+
notFound: "/images/illustrations/characters/character-02.svg",
|
|
129
|
+
forbidden: "/images/illustrations/characters/character-01.svg",
|
|
130
|
+
invalid: "/images/illustrations/characters/character-03.svg",
|
|
131
|
+
error: "/images/illustrations/characters/character-04.svg",
|
|
132
|
+
} as const
|
package/src/ui/layout/logo.tsx
CHANGED
|
@@ -14,6 +14,11 @@ const DEFAULT_TAGLINE = "ERP System";
|
|
|
14
14
|
* KHÔNG có logo cấu hình → monogram chữ cái đầu, KHÔNG trỏ vào một file magic
|
|
15
15
|
* trong public/. Bản cũ default "/images/logos/goeat_logo.png" (di sản goeat)
|
|
16
16
|
* làm mọi app mới init 400 ảnh trên từng trang vì template không ship file đó.
|
|
17
|
+
*
|
|
18
|
+
* Logo mặc định của app init GIỜ nằm ở tầng app, đúng chỗ có thể ship kèm file:
|
|
19
|
+
* templates/starter-app/public/images/logos/goeat_logo.png +
|
|
20
|
+
* `tenant.branding.logo` trong src/configs/tenant.ts (bị `Company.logoUrl` đè
|
|
21
|
+
* khi admin upload). Đừng hardcode lại đường dẫn nào vào component này.
|
|
17
22
|
*/
|
|
18
23
|
function Monogram({
|
|
19
24
|
name,
|
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Link from "next/link";
|
|
3
|
-
import { Button } from "../primitives/button";
|
|
1
|
+
import { NotFoundView } from "../errors/not-found-view";
|
|
4
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Trang 404 cho URL gõ sai (`[lang]/[...not-found]/page.tsx` của app bọc nó
|
|
5
|
+
* trong vỏ app có sidebar).
|
|
6
|
+
*
|
|
7
|
+
* Bố cục gốc của bộ kit nay sống trong `NotFoundView`/`StatusPage`, nên đây chỉ
|
|
8
|
+
* còn là lối vào giữ nguyên tên cho app đang import. Hai thứ sửa cùng lúc:
|
|
9
|
+
* chữ tiếng Việt như phần còn lại của app, và bỏ `min-h-screen` — nó nằm TRONG
|
|
10
|
+
* vỏ app nên chiều cao cứng làm trang thừa ra một màn cuộn.
|
|
11
|
+
*/
|
|
5
12
|
export function NotFoundPage() {
|
|
6
|
-
return
|
|
7
|
-
<div className="min-h-screen w-full flex flex-col items-center justify-center gap-y-6 text-center text-foreground bg-background p-4">
|
|
8
|
-
<div className="flex flex-col-reverse justify-center items-center gap-y-6 md:flex-row md:text-start">
|
|
9
|
-
<Image
|
|
10
|
-
src="/images/illustrations/characters/character-02.svg"
|
|
11
|
-
alt=""
|
|
12
|
-
height={232}
|
|
13
|
-
width={249}
|
|
14
|
-
priority
|
|
15
|
-
/>
|
|
16
|
-
|
|
17
|
-
<h1 className="inline-grid text-6xl font-black">
|
|
18
|
-
404 <span className="text-3xl font-semibold">Page Not Found</span>
|
|
19
|
-
</h1>
|
|
20
|
-
</div>
|
|
21
|
-
<p className="max-w-prose text-xl text-muted-foreground">
|
|
22
|
-
We couldn't find the page you're looking for. It might have
|
|
23
|
-
been moved or doesn't exist.
|
|
24
|
-
</p>
|
|
25
|
-
<Button size="lg" asChild>
|
|
26
|
-
<Link href="/">Home Page</Link>
|
|
27
|
-
</Button>
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
13
|
+
return <NotFoundView />;
|
|
30
14
|
}
|
|
@@ -35,6 +35,14 @@ const nextConfig = {
|
|
|
35
35
|
// "@goerp/core" (giữ qua alias pnpm) còn package thật trên đĩa là "@goplusvn/core".
|
|
36
36
|
transpilePackages: ["@goerp/core", "@goplusvn/core"],
|
|
37
37
|
|
|
38
|
+
// Next 16 CHẶN next/image tối ưu ảnh local có query string nếu path đó chưa
|
|
39
|
+
// khai (chống enumeration). Logo phục vụ qua `/api/branding/logo?v=<updatedAt>`
|
|
40
|
+
// nên không khai là sidebar ném lỗi đỏ ngay khi vào app. Bỏ trống `search`
|
|
41
|
+
// = cho phép MỌI query trên đúng path đó.
|
|
42
|
+
images: {
|
|
43
|
+
localPatterns: [{ pathname: "/api/branding/logo" }],
|
|
44
|
+
},
|
|
45
|
+
|
|
38
46
|
// Docker image gọn: chỉ .next/standalone + static. Xem Dockerfile.
|
|
39
47
|
output: "standalone",
|
|
40
48
|
turbopack: { root: workspaceRoot },
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 171 242" width="171" height="242">
|
|
2
|
+
<title>character-01</title>
|
|
3
|
+
<style>
|
|
4
|
+
.s0 { fill: #ffffff }
|
|
5
|
+
.s1 { fill: #000000 }
|
|
6
|
+
</style>
|
|
7
|
+
<g id="Introduction">
|
|
8
|
+
<g id="variations">
|
|
9
|
+
<g id="images">
|
|
10
|
+
<g id="a-person/bust">
|
|
11
|
+
<g id="body/Button-Shirt-1">
|
|
12
|
+
<path id="🎨-Background" fill-rule="evenodd" class="s0" d="m13.5 237.1c27.6 4.1 55.7 4.4 83.5 2.8 11-0.8 22.1-0.9 33.1 0.1 6.5 0.5 35 2.7 37.3-3.1-1.5-31.1-4.4-62.4-13.5-92.2-3.8-10.6-7-19.4-14.3-28.2-2.3-2.4-7.3-7.4-10.1-9-2.5-1.4-3.5-0.9-4.9-3.3-1.5-2.7-2.5-7.1-4.5-9-2-1.9-5-1.2-8.8-0.6 0.7-9.3-3.6-11.6-9.5-13.4-10.4-3.9-20.6-2-23.2 10.7-4.9 0-7.6 2.1-10.5 4.1-1.2 0.8-0.4 2.9-1.8 3.5-2.7 1-7.4 0.7-9.9 1.9-11.7 5.3-22 13-28.8 24.2-15.3 23.9-25.7 74.3-23.9 102.7-0.8 1.3 0.3 3 0.6 4.4 0.3 1.2 1.5 1.9 2.6 1.8 1.7 1.8 4.3 2.2 6.6 2.6z"/>
|
|
13
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m127.7 106.8c-0.2-0.1 0-0.4 0.2-0.3 8.1 3.9 14.4 10.6 18.8 18.4 4.6 8.1 7.2 17.2 9.5 26.2l0.1 0.3c2.4 9.6 4.4 19.2 6.2 28.9 1.9 9.8 3.4 19.7 4.6 29.6q0.9 7.4 1.5 14.8 0.3 3.7 0.6 7.4 0.1 1.4 0.2 2.9v0.8c0 0.6 0.1 1.3-0.1 2-0.1 0.5-0.4 1-0.7 1.6-0.5 1-1.9 0.8-2.5 0l-0.2-0.3c-0.3-0.6-0.6-1.1-0.8-1.8-0.1-0.7-0.1-1.5-0.1-2.2q-0.2-1.9-0.3-3.9-0.3-4.1-0.6-8.2c-0.5-5.4-1-10.8-1.6-16.1q-1.7-14.4-4.2-28.6c-1.6-9.3-3.6-18.5-5.7-27.6l-0.2-1c-3.7-16-9.4-34.4-24.7-42.9zm-87.2 62.6c0.1-0.2 0.3-0.2 0.4 0 0.5 2.5 0.6 5 0.7 7.6q0.1 3.8 0 7.5c-0.1 9.3-0.4 18.5-0.6 27.7q-0.2 6.9-0.3 13.8 0 2.6-0.1 5.2v2.3c0 1 0 2-0.1 3-0.1 0.7-0.3 1.3-0.7 1.9-0.2 0.4-0.6 0.6-1 0.9q-0.7 0.6-1.4 0l-0.2-0.1c-0.4-0.3-0.8-0.6-1-1.1-0.4-0.8-0.5-1.6-0.6-2.4-0.1-1.3 0-2.5 0-3.8q0.1-3.8 0.1-7.5c0.2-9.3 0.5-18.5 1.1-27.7q0.4-6.5 1.1-13l0.1-0.8q0.3-2 0.5-3.9c-2.3-1.6-4.4-3.6-6.1-5.9-0.2-0.2 0-0.4 0.2-0.2 1.8 1.8 3.8 3.3 6.1 4.4 0.4-2.7 0.9-5.4 1.8-7.9zm38.9-82.3q0.1 0 0.1 0c0.5 0.6 0.4 1.5 0.4 2.2v0.1q0.1 1.6 0.1 3.3v3.4c0 0.5-0.1 1-0.1 1.4l0.1 0.2c0.2 0.3 0.3 0.7 0.3 1.1-0.1 0.5-0.3 0.9-0.7 1.2l0.8 1.1 0.8 1.2q2.6 3.6 5.2 7.1 2.7 3.6 5.8 6.9 1.5 1.6 3 3.1 0.7 0.7 1.3 1.3l0.4 0.4c0.3 0.2 0.6 0.5 0.7 0.8 0.1 0.2 0.2 0.6 0.2 0.7 0.3 0.7-0.2 1.8-1.1 1.5v-0.1q0.3-0.1-0.3 0-0.3 0-0.6-0.1l-0.1-0.1c-0.3-0.1-0.5-0.4-0.8-0.6v-0.1q-0.8-0.7-1.6-1.5-1.6-1.6-3.1-3.4-3-3.4-5.7-7.1c-1.9-2.4-3.6-5.1-5-7.8q-0.9-1.5-1.6-3.1c-0.9-0.3-1.2-1.4-1.1-2.5-0.4-0.8-0.7-1.7-0.9-2.5 0-0.1 0.2-0.2 0.3-0.1q0.4 0.5 0.8 1.1c0.2-0.8 0.4-1.6 0.5-2.1l0.4-2c-2.4-0.2-5 0.8-6.6 2.5-0.1 0.5-0.5 0.8-0.8 1.2q-0.6 0.7-1 1.6c-0.5 1.2-0.2 3.1-1.3 4q-0.2 0.1-0.3 0.2c0.5 2.5 0.2 5.2 0.2 7.8v0.2c0 2.8-0.1 5.6-0.2 8.5l-0.1 2.8c-0.1 3.7-0.2 7.5 0.1 11.2q2.5-2.2 5.2-4.2 1.7-1.3 3.5-2.6l1-0.6c1.2-0.8 2.4-1.6 3.7-2.2 1.7-0.7 3.3-0.5 4.9 0.3 1.6 0.7 3.2 1.6 4.8 2.4q2.4 1.3 4.9 2.5c1.1 0.6 2.6 1.1 3.4 2.1q0.1-0.4 0.2-0.7c-0.1-0.3-0.1-0.7 0.1-1 2.7-4.9 5.1-9.9 7.6-14.9 1.2-2.5 2.4-5 3.6-7.6l1.2-2.4q0.3-0.6 0.6-1.2 0.5-0.9 0.9-1.9c0.2-0.2 0.3-0.5 0.4-0.7l0.1-0.2c0 0 0.3-0.9 0.1-0.8h-0.1c-0.1 0.1-0.2-0.1-0.1-0.2 0.3-0.3 0.8 0 1 0.4 0.5 1-0.5 2.5-0.8 3.5-1.1 3.1-2.4 6.2-3.6 9.2-2.4 5.8-5.1 11.5-7.7 17.2v0.1c0.6-0.4 1.2-0.8 1.7-1.2q1.9-1.4 3.9-2.7 3.6-2.5 7.4-4.7l0.5-0.3c1.2-0.7 2.5-1.3 4-1.1 1.4 0.2 2.7 0.9 3.9 1.5l0.1 0.1 3.9 1.9q-0.6-2.5-1.3-5-1.4-4.8-3-9.5-1.5-4.4-3.3-8.7l-0.3-0.8c-0.5-1.2-1-2.5-2.3-2.9-1.4-0.4-3 0.2-4.2-0.6-0.1-0.1-0.1-0.2 0.1-0.3l0.7-0.2c1.4-0.3 3.1-0.7 4.5-0.3 1.5 0.3 2.7 1.6 3.4 2.9 0.8 1.4 1.3 3 2 4.5v0.3q1.1 2.6 2 5.2 2 5.2 3.5 10.6 0.8 2.6 1.5 5.2c0.1 0.5 0.3 1.1 0.5 1.7q0.3 0.3 0.6 0.7c0.3 0.4 0.1 0.9-0.3 1.2q0 0.6-0.3 1.1c-0.9 1.4-3.3 1.1-3.2-0.8q0-0.4 0.3-0.7v-0.1l-0.1-0.1q-0.6-0.3-1.2-0.6l-4.1-2c-1.2-0.6-2.5-1.5-3.8-1.7-1.2-0.2-2.5 0.7-3.5 1.3h-0.1q-3.8 1.9-7.5 4-1.9 1-3.7 2c-1 0.6-2.1 1.4-3.3 1.7-0.4 0.4-1 0.3-1.5 0 0.2 1.3 0.2 2.7 0.3 4.1 0.1 1.8 0.1 3.6 0.1 5.4v0.7q0.1 6 0.1 12c0.1 14.2-0.1 28.5-0.1 42.7 0 7.2-0.2 14.3-0.3 21.5-0.1 3-0.3 6-0.5 9.1l-0.1 1.6c-0.2 3.5-0.3 7-0.9 10.5-0.1 0.4-0.9 0.4-1 0-0.5-3.7-0.6-7.5-0.7-11.2v-0.8q-0.2-6-0.2-12c0-14.2 0.4-28.5 0.7-42.7 0.2-7.2 0.3-14.3 0.5-21.5q0.2-5.3 0.4-10.7 0.1-2.4 0.3-4.8v-0.7q0.1-0.7 0.1-1.3c-1.4 0.5-2.8-0.5-4.1-1.1q-2.2-1.2-4.4-2.3l-1.5-0.8-3-1.5c-1.4-0.7-2.4-1.4-3.9-0.6-5.1 2.9-9.9 6.8-14.2 10.8-0.8 0.8-2.6 0.6-2.8-0.7-0.9-5.6-0.3-11.2 0.1-16.8l0.2-2.1q0.3-3.7 0.7-7.4 0.2-1.7 0.4-3.3l0.1-0.9c0.2-1.3 0.3-2.6 0.7-3.8q-0.2-0.1-0.3-0.2c-1.2-1.1-0.6-3.1-0.1-4.4 0.5-1.3 1.3-2.4 2.3-3.4 0.3-0.2 0.6-0.4 0.9-0.4 2.4-1.6 5.1-2.4 7.9-1.5q0.1-0.6 0.2-1.1l0.1-0.4c0.2-0.9 0.3-2.4 1.1-3.1zm25 146.1c0.8-0.2 1.6 0 2.2 0.6 0.5 0.5 0.7 1.4 0.5 2.1q-0.1 0.6-0.5 1-0.4 0.4-0.9 0.5l-0.1 0.1h-0.1q-0.6 0.2-1.2 0-0.5-0.1-0.9-0.5-0.4-0.4-0.6-1-0.1-0.5 0-1.1l0.1-0.1q0.1-0.6 0.6-1 0.4-0.4 0.9-0.6zm45-75.5c0.1-0.1 0.3 0.1 0.2 0.2-1.1 2.3-2.5 4.6-3.7 6.9q0.1 0.9 0.3 1.8c0.5 2.6 1.1 5.1 1.5 7.7 1.4 9.4 2.2 18.8 2.8 28.3 0.7 9.4 0.8 18.9 0.9 28.4 0 0.8-0.7 1.7-1.5 1.9-0.4 0.1-0.7 0.1-1.1 0-0.8-0.1-1.4-1.1-1.4-1.9q-0.4-8-1-15.9c-0.7-9.4-1.1-18.8-1.7-28.2l-0.2-3.3c-0.2-3.5-0.4-7.1-0.5-10.7 0-2.3 0.1-4.7 0-7 0-2.2-0.3-4.6 0.2-6.7 0-0.1 0.2-0.1 0.2 0 0.5 1 0.8 2.2 1 3.3 1.3-1.6 2.6-3.2 4-4.8zm-84.2-57.5c0.2 0 0.2 0.3 0 0.3-2.5 0.3-4.9 1.3-7.3 2.2l-0.2 0.1q-3.6 1.3-7 3.1c-4.4 2.4-8.5 5.4-12.1 8.9-14.3 13.9-20.8 34-25.6 52.9-2.6 10.5-4.5 21.2-5.7 32q-0.9 8-1.3 16-0.2 4.1-0.3 8.2 0 2.1 0 4.2c0 0.7 0.1 1.5 0 2.1-0.2 0.6-0.6 1.1-1 1.6-0.4 0.6-1.1 0.5-1.5 0l-0.1-0.2c-0.5-0.6-0.9-1.1-0.9-1.9-0.1-0.8-0.1-1.6-0.1-2.4q0-2.4 0.1-4.8 0.1-4.6 0.3-9.2 0.6-9.4 1.9-18.7c1.5-11 3.8-21.9 6.8-32.6 2.9-10.1 6.2-20.1 11-29.4 4.5-8.7 10.3-16.8 18-22.9 3.6-2.8 7.5-5.1 11.7-6.9 2.1-0.9 4.3-1.6 6.6-2 2.2-0.4 4.5-0.4 6.7-0.6zm39.7 115.2c0.4 0 0.8 0.1 1.1 0.3l0.5 0.4q0.2 0.2 0.4 0.4c0.3 0.4 0.3 1 0.2 1.5q0 0.4-0.2 0.8l-0.4 0.4c-0.3 0.3-0.6 0.5-1 0.6q-0.3 0.1-0.6 0.1h-0.1 0.1-0.1q-0.1 0-0.2 0-0.1 0-0.2 0 0 0-0.1 0c-0.5 0-1-0.3-1.4-0.6-0.3-0.3-0.6-1-0.6-1.4l0.1-0.2c0-0.3 0-0.5 0.2-0.8q0.1-0.4 0.5-0.8 0.8-0.7 1.8-0.7zm-1.6-23.5c0.6-0.8 1.8-0.8 2.7-0.4 0.2 0.1 0.4 0.3 0.5 0.5 0.5 0.3 0.7 1 0.7 1.6 0 0.5-0.3 1.2-0.7 1.6v0.1c-0.3 0.2-0.6 0.4-1 0.5-0.5 0.1-0.9 0.1-1.4-0.2q-0.7-0.2-1.1-0.8v-0.1q0 0-0.1-0.1c-0.5-0.9-0.3-2 0.4-2.7zm0.3-23.7q0.5-0.1 0.9 0 0.4 0 0.6 0.1 0.3 0.1 0.5 0.3 0.3 0.2 0.5 0.5 0.3 0.3 0.4 0.8l0.1 0.6-0.1 0.6-0.3 0.5q-0.1 0.2-0.2 0.3-0.1 0.3-0.4 0.4-0.1 0.2-0.4 0.3c-0.5 0.3-1.2 0.5-1.8 0.3q-0.5-0.2-0.9-0.6-0.4-0.4-0.6-0.9v-0.3c-0.1-0.4-0.1-0.6 0-1.1 0.1-0.2 0.2-0.5 0.3-0.7 0.3-0.5 0.8-0.9 1.4-1.1zm26.9-17q1.3 0 2.6 0h0.7c1.1 0.1 2-0.1 2.9 0.7 0.7 0.6 0.4 1.5-0.2 1.9-0.9 0.7-2.1 0.4-3.1 0.3q-1.7-0.1-3.4-0.2-3.2-0.1-6.4-0.2-3.2 0-6.5 0.1c-2.1 0-4.4 0.2-6.6 0-0.3 0-0.4-0.4-0.1-0.5 2.1-0.7 4.4-1 6.5-1.2q3.3-0.5 6.7-0.6 3.4-0.2 6.9-0.3zm-26.9-6.9h0.1q0.6 0 1.1 0.2l0.1 0.1 0.4 0.3q0.5 0.5 0.6 1.1l0.1 0.6q0 0.5-0.2 0.9-0.1 0.4-0.5 0.7-0.3 0.4-0.7 0.5-0.4 0.2-0.8 0.2h-0.1q-0.6 0-1.2-0.3l-0.5-0.4q-0.4-0.4-0.6-1v-0.6q-0.1-0.5 0.2-0.9 0.1-0.4 0.4-0.8 0.4-0.3 0.8-0.4 0.4-0.2 0.8-0.2zm6.9-54.5c0.5-0.7 1.4-0.1 1.3 0.5 0 1.6 0.1 3.2 0.4 4.8 0.2 0.8 0.4 1.5 0.8 2.2l0.1 0.2c0.5 0.9 0.8 1.8 0.2 2.7-0.3 0.5-0.8 0.8-1.3 0.8-2.5-0.1-2.8-3.5-3-5.4-0.1-2 0.4-4.2 1.5-5.8z"/>
|
|
14
|
+
</g>
|
|
15
|
+
<g id="head/No-Hair-3">
|
|
16
|
+
<path id="🎨-Background" fill-rule="evenodd" class="s0" d="m128.9 29.6c-7.5-19.5-20.9-33.8-43.5-24.8-0.6-0.5-1.5-0.6-2.3-0.1-12.3 7.7-21.1 20.1-25 34.1-2.3 0.4-4.6 1.2-6.6 2.5-4.4 2.8-7.4 7.2-10.2 11.4-0.8 1.3 0 3.5 1.6 3.7q1 0.2 2 0.3-0.3 0.9-0.7 1.7c-1 1.9 0.9 3.9 2.7 3.4q0.3 0.1 0.6 0.2c0 1.1 0.6 2.6 1.7 2.8 1.7 0.4 4.1-1 3.7-3q0.8 0.1 1.6 0c0 1.1 0 2.2 0.2 3.1 0.4 4.5 4.9 7.5 9.2 6.2 0.3 1.4 0.6 3.3 2 4.1 1.6 4.5 4.4 9.7 8.9 11.8-0.4 1-0.2 2.3 1.1 3 8.3 4.7 18.3 6.3 27.8 4.6 3.8-0.3 7.4-1.1 11-2.9 2.5-1.4 4.9-3 7.2-4.8 2.3-1.7 4.8-3.4 6.6-5.7 2-2.4 3-5.3 3.6-8.3 2.8-14 1.8-27.6-3.2-40.9-6.3-16.4 6.2 14 0-2.4z"/>
|
|
17
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m92.9 0.9c3.8-0.2 7.7 0.4 11.3 1.6 5.8 1.8 11.1 5 15.5 9.2 4.5 4.4 7.8 9.7 9.8 15.6 2.4 7.1 2.8 14.7 3.5 22.1 0.3 3.8 0.9 7.5 1.5 11.2l0.1 0.6c0.6 3.6 0.9 7.3 0.1 10.9-1.3 6-5.3 11.1-10.1 14.8-9.7 7.8-24.8 12.5-36.2 5.4-1.7-1.1-0.1-3.9 1.6-2.8 1.2 0.8 2.5 1.5 3.9 2 5.7 2.1 12 1.3 17.6-0.6 5.6-1.8 10.9-5 15.1-9.2 4.3-4.5 6.7-10 6.3-16.2-0.2-3.7-1-7.3-1.5-11-0.4-3.3-0.7-6.6-1-9.8l-0.1-1.2c-0.6-6.7-1.4-13.5-4.5-19.6-2.5-5.1-6.3-9.6-10.8-13.1-4.7-3.7-10.3-6.2-16.2-7.2-6.9-1.1-13.5 0.9-19.3 4.7-5.1 3.4-9.5 7.9-12.9 13-1.7 2.5-3.1 5.2-4.3 7.9-1.1 2.5-1.9 5.2-2.8 7.9q1.1-0.1 2.3 0.1c4 0.4 7.7 2.5 10 5.7 2.9 4 2.2 8.9 3.3 13.4 0.1 0.3-0.1 0.7-0.4 0.9-1.7 1.1-4 1.1-5.6-0.1-1.5-1.1-2.1-3.1-1.6-4.8 0.1-0.2 0.4-0.1 0.4 0.1 0.2 2.9 2.8 5.1 5.5 3.8-1.1-3.9-0.5-8.3-2.9-11.8-4.1-6.3-12.5-6.5-18.5-3-3.1 1.8-5.6 4.6-7.5 7.7l-0.5 0.9c-0.7 1.2-1.5 2.6-1.6 3.9-0.1 0.8 0.2 1.5 1.1 1.1 0.7-0.3 1.2-1 1.7-1.6 0.7-1.1 2.3-0.2 1.7 1-0.8 1.5-1.4 3.2-1.5 5v0.5c0 0.3 0 0.8 0 0.9 0.1 0 0.8-0.7 0.9-0.8 0.5-0.5 1-0.9 1.7-1 0.9-0.2 1.8 0.9 1 1.7-0.7 0.6-0.7 1.9 0.1 2.4 1.1 0.9 2.5-0.5 2.7-1.6 0.1-1.2 1.8-1.3 1.8 0 0.2 2.6-2.9 4.9-5.4 3.5-0.9-0.5-1.5-1.5-1.7-2.5q-0.5 0.2-1 0.3c-1.1 0.1-1.9-0.7-2.1-1.8-0.2-1.2-0.1-2.6 0.2-3.8-0.6 0.1-1.2 0-1.9-0.3-2-1.2-1.4-3.7-0.6-5.4 3.1-7.3 9.7-13.9 17.8-14.4 0.1-1.3 0.3-2.5 0.5-3.8 2.8-12.6 11.9-24.2 23.6-29.7 3.1-1.4 6.5-2.4 9.9-2.7zm-30.8 50.3h0.1c1.3-0.3 4.6-0.6 4.2 1.5 0 0.1-0.1 0.1-0.2 0-0.3-1.3-3-0.2-3.8 0.1-1.1 0.4-2.1 1.1-3 1.8-2 1.7-3.2 4.1-3.4 6.6-0.2 2.6 0.5 5.3 2.3 7.2 0.9 0.9 2.1 1.5 3.4 1.5 1.1 0.1 2.4-0.8 3.5-0.3 0.2 0.1 0.3 0.4 0.3 0.6 0 0.4-0.2 0.8-0.5 1.1 1.8 3.2 3.2 6.7 5.5 9.6 1.2 1.5 2.5 2.9 3.9 4.1q1.1 0.8 2.3 1.4c0.9 0.5 1.7 0.9 2.3 1.7 0.6 0.7 0 2.2-0.9 2.3-2.2 0.3-4.3-1.5-5.8-2.8-1.6-1.3-3-2.9-4.1-4.6-2.2-3.3-3.7-7.2-4.3-11.1-0.7 0.2-1.5 0.2-2.1 0.2-1.5 0-3-0.5-4.2-1.5-4.5-3.4-5-10.6-1.9-15.1 1.6-2.1 3.9-3.7 6.4-4.3zm0 8.3c1.1-0.1 2.1 0 3.1 0.4l0.4 0.1c0.9 0.4 1.8 0.7 2.4 1.4 0.9 0.9 0 2.6-1.4 2.3-1.4-0.5-2.6-1.7-4.1-2.2-1.3-0.5-2.8-0.4-4 0.4-0.2 0.1-0.4-0.1-0.3-0.3 0.9-1.4 2.4-2 3.9-2.1z"/>
|
|
18
|
+
</g>
|
|
19
|
+
<g id="face/Smiling">
|
|
20
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m109.2 79.3c-1.5-0.6-2.7-1.6-3.7-2.8-0.3-0.4-0.4-0.9-0.3-1.3 0.1-0.5 0.4-0.9 0.7-1.2 0.4-0.3 0.9-0.4 1.3-0.3 0.4 0 0.8 0.2 1.1 0.7l0.1 0.1c0.6 0.7 1.3 1.3 2.1 1.7 0.8 0.4 1.7 0.6 2.6 0.5 1.7-0.2 2.9-1.1 4.2-2.4q0.2-0.3 0.5-0.5 0.1-0.2 0.3-0.3 0.3-0.1 0.6 0 0.3 0.1 0.4 0.3 0.2 0.2 0.2 0.5c-0.2 1.4-0.9 2.5-1.8 3.5-1.1 1-2.6 1.7-3.9 2-1.5 0.2-3.1 0-4.4-0.5zm5.9-21.6c8.1 1.4 3.9 15.4-6.5 7.7-1.2-1 0.3-3.2 1.6-2.3 1.5 1.1 4.4 3.5 6.4 1.4 1.7-2.4-0.7-4.7-2.3-5.6-0.4-0.3-0.1-1.3 0.8-1.2zm-19.4-7.8c0.2-2.1 3.5-2.6 3.9-0.5 0.2 2-0.1 3.7-1 5.5-0.8 1.7-2.9 0.9-3.1-0.6-0.2-2.1 0.1-3 0.2-4.4zm25.4-0.9c0.4-0.6 1.1-1.1 1.9-0.8 2.5 0.7 1.8 4.3 0.9 6-0.5 1-2 1.2-2.7 0.4-1.2-1.4-1.7-4.1-0.3-5.4q0.1-0.1 0.2-0.2zm-22.5-8.6l0.4-0.1c1.2-0.2 2.7-0.4 3.6 0.6 0.5 0.5 0.6 1.5 0 2-1.1 0.8-2.3 0.5-3.6 0.6q-1.6 0.1-3.1 0.5c-2.3 0.7-4.2 1.8-6.1 3.2-0.3 0.1-0.5-0.2-0.4-0.4 1.1-2.2 3.3-4 5.5-5.1 1.1-0.6 2.4-1.1 3.7-1.3zm20.2-1h0.3c3.3 0.7 7.6 2.1 9.2 5.4 0 0.4-0.1 0.5-0.1 0.6-0.1 0.1-0.1 0.1-0.3 0.2q-0.1 0-0.2 0c-0.7-0.2-1.2-0.5-1.8-0.8l-0.6-0.3c-0.7-0.3-1.4-0.6-2.1-0.9q-2.4-0.7-4.9-1-0.5-0.1-0.9-0.4-0.4-0.3-0.6-0.8c-0.1-0.5-0.1-0.8 0.2-1.3q0.3-0.4 0.8-0.6 0.4-0.2 1-0.1z"/>
|
|
21
|
+
</g>
|
|
22
|
+
<g id="facial-hair/Moustache-9">
|
|
23
|
+
<path id="🎨-Background" fill-rule="evenodd" class="s0" d="m122.4 67.4c-2.9-0.5-6 0.3-8.9 1-4.5-2.9-10.4 0.1-13.7 3.8-1.1 0.9-3.4 2.1-2.2 3.9-0.4 1.2-0.6 1.8 0.4 0.4 5.5 0.6 11.3-0.6 16.7-1.7 1.9 0.6 3.5 2 5.5 1.5 1.9 0.4 4 0.8 5.7-0.4 1.4-0.1 4.3 2.3 4.2-0.4-0.4-2.7-5.6-7.1-7.7-8.1z"/>
|
|
24
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m131.1 78c-3.8-2.7-9.3 2.1-16.1-2.4-3.5 2.9-13.1-0.1-18.7 3.1-4.5 1 5-10.9 6.7-11 4-2.4 7.3-1.6 11.3-0.1 1.3 0.1 2.8-0.8 4.1-1 6.7-1 11.5 5.1 13.9 10.5 0.4 0.8-0.5 1.6-1.2 0.9zm-1.2-2.3c-2.2-4.5-6.7-9.1-12.2-7.8-0.3 0.1-3.9 1.4-3.2 0.8-7.9-2.8-13.1 0.3-16.8 7.6 3.9-1.3 8.1-1 12.1-1.1 1.2 0 3.5 0.3 4.2-1 0.1-0.4 0.4-0.5 0.7-0.4 0.2-0.2 0.5-0.2 0.8 0 2.7 1.9 5.9 2.4 9.1 2.1 1.8-0.2 3.6-0.6 5.3-0.2z"/>
|
|
25
|
+
</g>
|
|
26
|
+
<g id="accessories/Glasses-3">
|
|
27
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m139.2 45.7c-0.9 0.4-1.5 1.3-1.2 2.3 0.1 0.8-0.2 1.4-0.7 1.7-0.1 4.7-0.9 10.1-4.6 13.6-8.6 5.6-17.1-1.3-15.3-12.2q-0.2-0.1-0.3-0.3-0.1-0.2-0.2-0.3c-0.1-0.2-1.5-0.7-3.3-0.4-1.8 0.2-2.4 1.1-3.3 2-0.1 0.3-0.4 0.5-0.7 0.6-0.8 4-1.5 8.4-4.6 11.4-7.7 7.2-21 1.3-20.5-9.7-2.7-0.5-0.4-3.6-4.7-4.3-0.7-0.3-1.4-0.7-1.9-1.3-6.4-0.7-12.6-0.4-18.7 1.8-2.5 1-5.7 1.5-4.3 5.1 0 1-1.2 1.6-2 0.8q0 0 0 0c-4.2-7.5 4.1-8.7 10.1-9.6 3.3-0.7 6.6-1 9.9-1 1.5 0.1 3.5 0 4.9 0.4q0 0 0 0c1.4-4.2 30.7-5.2 32.4 1.8 2.2 0 3.9 0.6 5.8-0.1 0.6-5.1 14.5-7.1 20.5-5.7q0.7 0.1 1.3 0.2 0.3 0.1 0.5 0.2 0.2 0 0.5 0.1c1.3 0.2 1.5 2.3 0.4 2.9zm-31.3 5.9c-2.4-2.1-3.7-4.1-8.4-4.4-3.7 0-7.7-0.1-11 2-2 1-1.6 3.9-3.2 5 1.7 13.1 18.7 16.6 21.8 2 0.4-1.5 0.7-3.2 0.8-4.6zm27.3-2.3c-1.9-1.9-0.7-4.5-4.9-4.1-12.1 0.7-8.3 7.8-11.8 6.8 0.2 4.6 1.8 10.6 7.1 11.1 2.4 0.2 5.1-0.4 6.5-2.3 2.4-3.3 3.1-7.6 3.1-11.5z"/>
|
|
28
|
+
</g>
|
|
29
|
+
</g>
|
|
30
|
+
</g>
|
|
31
|
+
</g>
|
|
32
|
+
</g>
|
|
33
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 249 232" width="249" height="232">
|
|
2
|
+
<title>character-02</title>
|
|
3
|
+
<style>
|
|
4
|
+
.s0 { fill: #ffffff }
|
|
5
|
+
.s1 { fill: #000000 }
|
|
6
|
+
</style>
|
|
7
|
+
<g id="Introduction">
|
|
8
|
+
<g id="variations">
|
|
9
|
+
<g id="images">
|
|
10
|
+
<g id="a-person/bust">
|
|
11
|
+
<g id="body/Whatever">
|
|
12
|
+
<path id="🎨-Background" fill-rule="evenodd" class="s0" d="m234.9 146.9q3.3-1.7 6.4-3.6c1.4-0.9 0.1-3.1-1.4-2.3q-1.1 0.6-2.3 1.2 0.9-0.7 1.7-1.7c1.9-1.7-0.6-5-2.8-3.6-1.9 1.4-3.9 2.9-6.1 3.8-4.6 2-9.7 2.3-14.7 2.3-1.8-0.1-3.5 0.2-5.3 0.6 0.7-2.8 2.4-4.9 3.3-7.6 0.7-2.7-3.2-4.5-4.6-1.9q-0.5 0.9-0.9 1.9c-3 2.7-8 2.5-11.1 5.4-1.7 1.5-2.5 3.6-2.8 5.7-0.3 1.4 0.1 2.8-0.8 4.1-4.1 5.8-10.6 15-13.9 21.4-2.4-15.2-8.6-34.1-15.1-48-2.1-4.5-4.6-8.9-7.8-12.6 0.4-1.3-0.9-3.5-1.7-2.9-2.5-3-7-3.8-10.5-5.4-4.9-2-8.9-6.3-10.8-11.2-2.6-9.3-8.8-10.4-17.4-10-8.3 0-14.4 3.5-16.2 11.9-3.6 6.4-12.3 5.3-18.5 7-4.6 1.1-9 2.7-13.2 4.7-4.7-4.4-21.4 14.2-22.9 19q1.3 0.2 2.7 0.6c0.7 0.3 0.4 1.4-0.4 1.3q-1.5-0.4-3-0.6 0 0.2 0 0.3-0.2 0-0.4 0 0.4 0.2 0.7 0.5c0.6 0.4-0.1 1.3-0.7 1-0.6-0.5-1.3-0.4-2-0.5 0 1.4-5-0.2-5.8-0.7-3.4-0.4-6.9 0.1-10.1-1.6-4.3-0.9-8.5-1.9-12.8-3-1.1 0.4-2.1 2-1.2 3.1 0.5 0.5-0.2 1.4-0.8 1-2.1-1.2-3.7-3.1-5.1-5.2-0.6-0.7-1.8-0.5-2.7-0.8q-0.1 0.3-0.2 0.7c-3.6 0.6-1 4.6 0.8 5.9-0.9 0.6-1 1.9-0.9 2.9-0.2 0.4-0.3 0.9-0.1 1.3 0.7 1.6 2.2 2.9 3.4 4.2 1.2 1.5 2.3 2.9 3.9 4.1 5.8 4.4 12.9 6.9 20.1 7.9 2.6 0.4 6.3 1 7.9 3.2-0.4 2.5-1.1 5-1.8 7.5-0.9 3.4-0.8 6.9-0.8 10.3-0.2-0.1-0.4-0.1-0.4 0.1-0.3 1.4-0.4 2.9-1.3 4-0.7 2.2-1.2 4.6-1.5 6.9-1.1 11-1.4 22.3 1.1 33.1 1 4.1 2.6 7.9 4.8 11.4 0.6 1 1.7 1.3 2.6 1.1 3.1 1.7 7.1 2.2 10.5 1.8 11.5-3.3 7.4 4.5 23.6 2.1 27.8-3.5 55.9 3.5 83.7-0.6 0.7 5.3 9.6 3.7 12.7 1.5 9.3-6.9 14-28.9 18.7-40 3.2-8.8 8.6-24.3 15.6-30.2 2.1-1.7 4.7-2.6 7.2-3.3 9.6-2.4 19.2-4.7 28.7-7.1 1.7-0.4 1.4-3.2-0.4-3q-3.4 0.3-6.9 0.6z"/>
|
|
13
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m22.4 145.3c-0.7-0.1-1.3-0.3-1.9-0.5q-1.5-0.4-2.9-1c-1.9-0.7-3.7-1.7-5.5-2.8-2.8-1.8-5.3-4.1-7.1-6.8l-0.2-0.2c-1-1.7-3-5.3-0.8-6.5-1.4-1.2-2.8-3.3-2.7-5 0.1-2.3 3-2.3 4.5-1.3 0.9 0.6 1.7 1.5 2.4 2.4q1.2 1.5 2.6 2.9 0.3 0.4 0.7 0.7l0.2 0.2q0-0.1-0.1-0.2c-0.5-1.6 0.1-3.6 1.7-4.3 0.9-0.4 1.9-0.2 2.8 0.2l0.1 0.1q1.9 0.7 3.8 1.3c5.2 1.5 10.6 1.7 16 2.4 2.1 0.3 4.2 0.7 6.2 1.2 0.8-3.3 2.7-6.5 4.8-9.1 9.9-12.5 26.4-16.7 41.4-19.4 1.3-0.2 2.5 1.6 3.3 1.2 1.5-0.8 2.8-2 4-3.2 2.5-2.7 4.2-5.8 6.3-8.8 1-1.5 3.4-0.2 2.4 1.4l-0.4 0.8c-2 3.1-4.1 6.4-6.8 8.8-1.5 1.3-3.1 2.4-5 3-1.4 0.5-3.3 0.9-4.9 0.4l-0.2-0.2q0.1 0.1 0.2 0.2c4 5.8 9.1 10.8 14.4 15.4 5.3 4.7 11.1 8.9 16.9 13l0.5 0.3c9.5-6.9 17.5-15.9 23.1-26.2-1.2-0.1-2.3-0.9-3.3-1.4-1.3-0.7-2.4-1.5-3.3-2.6-1.9-2.4-1.7-5.4-2-8.3 0-0.1 0.2-0.2 0.3-0.1 1.1 0.9 1.4 2.3 1.9 3.5 0.4 1.4 1 2.5 2.1 3.5 1 0.8 2.3 1.5 3.5 2.1 0.6 0.3 3.7 1 4.1 1.7 5.4-1.3 10.6 0.9 14.6 4.6 3.9 3.6 6.7 8.2 9.2 12.8 2.7 4.8 4.9 9.9 6.8 15.2 1.9 5.3 3.3 10.7 4.1 16.3 0.7 4.7 1.1 9.5 1.4 14.3v0.5q6-9.3 12.3-18.6c-1-2.5 0.1-5.1 1.9-7 1.9-2.2 4.7-3.2 7.3-4.4l0.3-0.1c1.3-0.6 2.5-1.2 3.6-2.1 1-0.8 1.8-2 2.9-2.7 1.6-1.1 4.5-0.9 4.6 1.5 0 1.4-0.5 2.8-1.1 4-0.6 1.4-1.4 2.6-2.3 3.7q-0.1 0.1-0.2 0.2c1.3 0.2 2.6 0.4 4 0.4 2.7 0.2 5.5 0 8.1-0.6 2.8-0.6 5.4-1.6 7.9-2.9 2.1-1.1 4-2.6 6.4-2.9q0.3-0.1 0.7-0.1c0.3 0 0.7 0.4 0.6 0.8q-0.2 0.3-0.3 0.6c-0.8 1.8-2.1 3.6-3.7 4.9l-0.1 0.1q0.9-0.3 1.7-0.6c3.1-1.5 6-3.6 9.4-4.5q0.2 0 0.5-0.1c1-0.2 1.6 0.9 1 1.7q-0.2 0.2-0.3 0.4-2.3 2.8-5.1 5.2-0.9 0.8-1.9 1.5 3.1-0.9 6.1-2.2c0.8-0.3 1.4 0.5 1.5 1.2 0.3 2.2-2.2 3.8-3.8 4.9-1.6 1-3.3 1.9-5.2 2.5-3.5 1.3-7.1 1.9-10.8 2.4l-1.8 0.2c-7 1-14.3 2.2-19.4 7.7-2.8 3-4.7 6.8-6.5 10.6-1.7 3.7-3.3 7.6-4.7 11.4-1.5 4-2.8 8.1-4.2 12.2-1.3 3.7-2.9 7.3-4.4 11l-0.2 0.5c-3.2 7.8-7.1 15-12.5 21.5-0.9 1-2.3-0.5-1.5-1.5 5.6-7.3 9.6-15.8 12.8-24.4 1.5-3.8 2.7-7.8 4.1-11.7l0.8-2.3q1.7-4.7 3.5-9.3c1.5-3.9 3.1-7.7 5-11.4l0.2-0.4c1.8-3.6 4-7.1 7-9.8 5.4-4.9 12.6-6 19.6-7l2.2-0.3c2.9-0.3 5.9-0.8 8.7-1.6 1.7-0.4 3.3-1 4.8-1.8q0.9-0.5 1.8-1-2.5 0.7-5 1.1-1.2 0.3-2.4 0.4c-2.1 0.2-4.2 0.2-6.3 0.1-0.2 0-0.3-0.3-0.1-0.4q2.3-0.4 4.5-0.9l0.4-0.1q0.1-0.4 0.4-0.8c0.7-0.9 2.1-1.4 3.1-2q1.5-1 2.9-2.1 1.3-1.1 2.5-2.3 0 0 0 0c-2.1 1-4.2 2.3-6.4 3.1-1.8 0.6-3.7 1-5.6 1.2h-0.1-0.1c-2 0.1-4 0.1-5.9 0.5-0.2 0.1-0.3-0.2-0.1-0.3 1.7-0.7 3.5-1 5.2-1.3q0.1-0.2 0.4-0.4l0.4-0.2c1.4-0.6 2.6-1.3 3.8-2.4q1.5-1.4 2.4-3.2c-2.5 0.6-4.7 2.4-6.9 3.5-2.5 1.2-5.1 2-7.8 2.5h-0.3c-5 0.9-11.1 0.8-15.6-1.9-0.1 0 0-0.2 0.1-0.2 1.3 0.2 2.6 0.4 3.8 0.7-0.2-0.3-0.3-0.7 0-1 1.1-1.3 2-2.8 2.6-4.4l0.1-0.3c0.2-0.8 0.7-2 0.2-2.6-0.4-0.7-1.4-0.6-2-0.3-1.3 0.6-2.2 2-3.2 2.9-1.2 0.9-2.5 1.6-3.9 2.2l-0.3 0.2c-2.3 1-4.9 1.9-6.7 3.8-1 1-1.9 2.3-2.2 3.7q-0.2 0.9 0.1 1.9c0.1 0.5 0.4 0.8 0.2 1.3-0.2 0.7-0.9 1.5-1.3 2.1q-0.7 1-1.4 2-1.4 2-2.7 4.1-2.7 4.1-5.4 8.2-0.8 1.3-1.7 2.7l-0.8 1.3h-0.1q-0.2 0.4-0.4 0.7l0.4-0.7q0 0 0.1 0v0.2c0 0.7-0.4 1.1-1 1.2q0.1 0 0.1 0l-0.4 0.5q0.1 0.2 0 0.4c-0.1 0.3-0.4 0.6-0.7 0.8-4.5 7.1-9 14.3-13.4 21.5q-0.4 3.2-0.7 6.5c-0.4 4.9-0.7 9.9-0.8 14.9-0.1 2.4 0.1 4.8 0.2 7.2q0.1 1.7 0.2 3.4l0.1 0.8c0.1 1.1 0.1 2.2-0.3 3.3-0.3 0.9-1.4 1.1-2.1 0.4q-12.5-0.5-25-0.7c-15-0.3-29.9-0.3-44.9 0q-11.3 0.2-22.6 0.6c-3.7 0.2-7.4 0.3-11.1 0.4-2 0-5.1-0.7-5.3-3q-0.3 0.1-0.7 0.1-0.2 0.1-0.4 0c-3 0.9-6.8-0.4-9.6-1.1l-0.2-0.1c-2.7-0.7-4.9-1.7-6.7-3.9-3-4-4.1-9.2-4.7-14.1-0.5-4.5-0.5-9.2 0.1-13.7-0.3-3.7 0-7.6 0.4-11.3q0.3-2.7 0.8-5.4 0.2-1.5 0.6-3c0.1-0.4 0.1-0.9 0.2-1.3l0.1-0.1q-0.5 0-1.1-0.3c-0.8-0.4-1.1-1.4-1.1-2.3 0-2.7 0.3-5.5 0.6-8.2q0.4-4.1 1.2-8.1l0.1-0.7c0.4-2 0.9-4.1 1.7-5.9-3-0.6-6-1.1-8.9-2q-2.1-0.7-4.1-1.7zm158.9 25.4q-0.2 0.3-0.4 0.7l0.4-0.7q0 0 0 0zm58.5-24.5q0 0 0 0-0.1 0.1-0.1 0.1 0 0 0.1-0.1 0 0 0 0zm-0.7 0.6q-0.1 0-0.2 0.1 0.1-0.1 0.2-0.1zm-0.3 0.2q0.1-0.1 0.1-0.1zm4.1-6.4q0.2-0.1 0.3-0.2zm-3.3 5.7q-0.3 0.2-0.6 0.4 0.3-0.2 0.6-0.4zm-61.7 27.4q0 0-0.1 0c-1.2 0.3-2.4 0.6-3.6 0.9-2.1 0.5-4.1 1.1-6 2-0.4 5.1-1 10.2-1.6 15.3l-0.1 1q1.3-2.4 2.7-4.8 4.3-7.3 8.7-14.4zm-160-31.4q-0.2-0.2-0.4-0.4c-1.2-1.1-2.2-2.3-2.9-3.7l-0.2-0.4c-0.6-1.2-1.4-2.8 0.1-3.7 0.8-0.5 1.8-0.3 2.8 0q0.1 0 0.2 0 0.6 0.3 1.2 0.5c1.5 0.7 2.9 1.8 4.4 2.7 1.6 1 3.1 1.7 5 2.1h0.1c1.7 0.3 3.6 0.5 4.8 2 0.3 0.3 0 1-0.5 0.8-3.3-1.1-6.8-1.4-9.8-3.2-1.3-0.7-2.5-1.6-3.8-2.3q-1-0.6-2.1-1l-0.4-0.1c-0.2-0.1-0.5-0.1-0.7-0.1-0.4 0.2-0.3 0.4-0.1 0.7 0.9 2.8 3.4 5.1 5.7 6.6q0.8 0.5 1.7 1c3.8 2 8.1 3 12.2 4.1q2.4 0.7 3.2 0.9c0.9-0.1 2 0.2 2.6 0.6q1 0.6 1.6 1.5c0 0 0.4 0.3 0.5 0.8q0.3 0.7 0.4 1.4 0 0.5-0.2 0.7c0.4 6.7-1.4 13.3-3.4 19.6l-0.2 0.6-0.1 0.4c-2.2 6.7-4.7 13.3-5.8 20.3-0.8 4.6-0.7 9.5-0.2 14.1v0.4c0.6 4.4 1.6 9.3 4.4 12.9 1.5 1.8 3.2 2.6 5.3 3.2h0.2c1.9 0.6 3.9 1.3 6 1.5 1.9 0.2 3.4-0.5 5.1-1.1 3.6-3.2 5.2-7.8 6.4-12.4 3.1-12 2.7-24.5 1-36.7-1-6.3-2.2-12.6-3.4-18.9-0.7-3.2-1.3-6.3-1.9-9.5l-0.3-1.9q-0.3-1.5-0.5-3.1c-0.2-1.4-0.3-2.7-0.4-4.1-1.7-2.9-4.2-5.2-7-6.9-2.1-1.2-4.3-2-6.5-2.6-6.4-1.7-13.4-1.6-19.9-2.9-2.2-0.5-4.2-1.1-6.3-1.9l-0.3-0.2c-0.9-0.3-1.9-0.5-2.3 0.6-0.4 0.8-0.2 1.6 0.3 2.3 1.3 1.6 3.7 2.4 5.6 2.9q1.7 0.6 3.4 0.9c1.2 0.2 2.3 0.3 3.4 0.7 0.4 0.1 0.5 0.8 0 0.9-1.4 0.3-2.8 0.1-4.2-0.2q-2.3-0.5-4.5-1.3-0.4-0.1-0.8-0.3l-0.2-0.1q0.3 0.3 0.6 0.5c0.1 0 0 0.1 0 0.1-3.5-1.3-6.6-3.6-9-6.3l-0.2-0.2c-0.8-1-2.8-3.9-4.4-3.1-1.6 0.8 1.1 3.8 2.1 5l0.1 0.1c1.1 0.1 2.2 0.8 3.1 1.3 1.6 1 3.3 1.9 5 2.7 3.4 1.6 7 2.7 10.3 4.4 0.1 0 0.1 0 0 0-2.1-0.3-4.2-0.8-6.3-1.5h-0.1l-0.1-0.1q-1.9-0.6-3.8-1.4-2.1-0.8-4-1.9c-1.2-0.7-2.6-1.8-3.9-2q-0.3 0-0.4 0c-1.6 0.1-0.3 2.7 0.1 3.5q1.1 2 2.6 3.6c2.1 2.2 4.5 4 7.2 5.3q1.4 0.7 2.8 1.3zm26.7-6.1q1.9 0.2 3.7 0.9h0.1c0.9 0.4 2.2 0.8 2.5 1.7 0 0.3-0.2 0.5-0.4 0.5-1 0.1-2.1-0.9-3-1.3q-1.4-0.5-3-0.8c-2.3-0.3-4.8-0.1-6.9 0.8-0.2 0-0.3-0.2-0.1-0.2 2.2-1.2 4.6-1.8 7.1-1.6zm-9.9 38c0 0.6-0.2 1.2-0.2 1.8q-0.2 1.4-0.3 2.8-0.4 2.9-0.6 5.7-0.1 1.9-0.2 3.7c1.2-4.5 2.8-8.8 4.3-13.2q-0.4-0.1-0.8-0.2l-0.4-0.1c-0.3-0.1-1.1-0.3-1.8-0.5z"/>
|
|
14
|
+
</g>
|
|
15
|
+
<g id="head/hat-beanie">
|
|
16
|
+
<path id="Path" fill-rule="evenodd" class="s0" d="m119.3 2.5c9.5 0 20.8 4.5 21.8 4.6q0.8 0 6 4.6l-3.8 7.3 0.3 0.3c1.5 1.4 2.7 2.6 3.7 3.6 8 8.2 9.4 40.3 7.5 51.4-1.9 11.2-5.3 22.2-21.6 22.2-16.2 0-34.2-9.8-37-12.8q-2.8-3.1-6.3-3-0.1-0.1-0.3-0.3l-0.3-0.1q-4.8-0.7-6.9-1.8c-2.7-1.6-5.6-9.6-5.6-11.4 0-1.7-4.5-14.5-4.6-15.9 0-1.1-5.8-6.3-5.8-8 0-1.6-1.1-1.5 0-7.3l0.4-1.7c1.2-6.2 3.6-16.5 12.9-20.9 10.2-4.9 30.1-10.8 39.6-10.8z"/>
|
|
17
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m78.1 13.1c5.1-5.5 34-13.8 48.6-12h0.5q1.7 0.2 3.4 0.7c3.7 0.9 7.5 2.2 10.5 4.3 2.5 1.8 10.5 4.7 8.2 9.3 0.8 1.7 1.2 3.7 0.6 5.3-0.1 0.6-0.3 1.1-0.5 1.7 1.9 2.7 3.3 5.8 4.5 8.8 2.1 7.4 3.4 15.2 3.6 22.8 0.6 14.4-0.9 31.6-13.5 41-7.6 5.9-19.5 6.1-28-1.3-0.5-0.5-2.8-2.1-2-2.4q0.3 0.4 0.7 0.7 0 0 0 0l-0.2-0.2c-0.5-0.4-1-1-0.4-0.9q0.1 0.1 0.1 0.1 0.2 0.1 0.3 0.2v0.1-0.1c-0.3-0.3-0.5-0.7 0-0.5l0.1 0.1q0.3 0.3 0.7 0.7 0-0.1 0-0.1l-0.2-0.2c-0.2-0.2-0.2-0.2-0.1-0.4-0.5-0.7 0.4-0.3 0.5 0 0.5-0.2 1 0.9 1.4 1 15.6 12 38.3 1.4 37.9-32.1v-0.7c-0.1-10.7-1-21.7-5.4-31.4q-0.7-1.4-1.5-2.7-0.5-1-1.1-2-1.8-0.1-3.5-0.6-0.6-0.2-1.2-0.4c-5.7 0.4-11.2 0.7-16.9 1l-1.8 0.1c-4.8 0.3-9.8 0.8-13.7 3.8-3.8 2.7-3.8 8.1-7.1 11.1-4.7 3.1-4.7 6-5.6 10.7 0.1 3.5 2.5 8.6-2 10.1 0.8 1-0.3 0.5-0.4 0.1q0 0.1 0 0.1c0.7 1.2-0.3 0.4-0.4 0q-0.1 0-0.1-0.1c0.6 1.1-0.5 0.3-0.4 0.1-1.3-2-4-2.3-5.9-1.8 0 0.1-0.1 0.1-0.2 0.1-8 1.7-6 18.5 2.3 16.8 0.4 0 0.4 0.1 0.4 0.2-0.2-0.5 0.4-0.3 0.4-0.2 0 0 0 0 0 0-0.1-1.1 0.9 0.4 0.8 0.5q0.1 0 0.1 0v-0.1c-0.2-0.5-0.2-0.3-0.2-0.6-0.1-0.3-0.1-0.2-0.1-0.4 0.5-0.3 0.6 0.7 0.8 0.8-0.3-0.3-0.1-0.6 0.2-0.4 1.8 3.9 4.2 7.6 7.3 10.5q0.5 0.4 1.1 0.8c1.3 1.1 3.3 1.8 4.6 2.9q0 0 0 0v0.1l0.4 0.2q0.2 0.2 0.4 0.4 0.1 0.1 0.3 0.4c0 0.1-0.1 0.2-0.3 0.1q-0.1 0-0.2 0 0 0 0 0c0.1 0 0.2 0.4 0 0.3q-0.1 0-0.3-0.1 0.2 0.2 0.3 0.4 0.2 0.2 0.2 0.4 0 0.1-0.1 0.1-0.2 0-0.4-0.1l0.1 0.1c0.1 0.1 0.2 0.4 0 0.3q-0.3-0.1-0.6-0.2 0 0.1-0.1 0-0.8-0.3-1.6-0.7-0.7-0.5-1.4-1-0.6-0.4-1.2-0.9c-2.7-1.7-5.1-3.9-6.9-6.3-3.1 2.7-9.3 0.1-13.2-2-3.4-1.9-4.7-5.4-5-9.1-0.8-5.1-4.9-6.8-4.6-17.9q0 0 0 0-0.2 0-0.4-0.2-0.3-0.1-0.4-0.2l-0.2-0.2q-0.1-0.1-0.2-0.1c-0.1 0.1-0.1-0.1-0.1-0.1l-0.2-0.4c-0.7-0.8-1.4-1.8-1.9-2.6q-0.1 0.1-0.1 0.1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0c-1.3-1.9-2.6-4.3-2.9-6.6-0.4-1.7-0.3-3.5 0.1-5.1 1.5-5.7 6.6-18.5 13.3-24zm-10.5 35.7q0 0 0 0 0 0 0 0zm47.2 42.7l-0.1-0.1 0.1 0.1q0.1 0.1 0.1 0.2 0-0.1 0-0.1 0 0-0.1-0.1zm11.9-87.6c-9.9-0.8-19.7 1.3-29.1 4l-0.7 0.2c-5.4 1.5-11.1 2.9-15.6 6.2-6.4 4.8-9.6 12.6-12.5 19.7-2.5 5.3-1.2 11.3 2.6 15 0.3-3.7 1-7.2 2.1-10.8 0.2-0.5 0-0.7 0.5-0.8 0.7 9.6-2.8 16.6 4.1 28 3 5.3-0.5 9.2 8 12l0.2 0.1c1.8 0.7 3.7 1.2 5.4 0.8l-0.1-0.2c-0.2-0.3-0.2-0.4 0-0.5q0 0 0 0-0.3-0.6-0.5-1.1-0.1 0-0.3 0c0.1 0.1 0.1 0.2 0 0.3q-0.7 0.2-1.5 0.1h-0.1c-0.5 0-0.9-0.1-1.2-0.2q-0.1 0-0.3 0c-1-0.3-2.1-0.8-2.7-1.4-7.9-4.4-7.1-19.6 2.6-21 0.2-9.6 4.7-25.6 12.2-34.7 6.8-8.4 25.4-12 38.3-10.7q0.3 0.1 0.6 0.2c2 0.1 3.9 1 5.9 1.4-1.5-1-3.1-1.7-4.8-2.4-3.3-2-7.1-3.1-10.8-3.9q-1.1-0.3-2.3-0.3zm-39.6 58c0.6-0.2 0.5 0 0.6 0 3.8-0.4 7.8 2.9 9.9 5.6-0.2 0.2-0.6-0.3-0.7-0.4q0 0-0.1 0l0.1 0.1c0.8 1.2-0.8-0.2-1-0.5q0 0-0.1 0c0.2 0.2 0.6 0.5 0.6 0.8h0.1c1.1 0.9 1 1.6-0.2 0.3q0.1 0.1 0 0.2h0.1c0.5 0.4 1 1.5-0.2 0.4 0.2 0.8-1.1-0.8-1.2-0.8-2.2-1.7-5.5-3.5-8.3-3.7h-0.1c-0.6-0.1-0.8-0.2-0.6-0.6-0.7-0.1-0.5-0.4-0.2-0.4-0.5-0.3-0.1-0.6 0.2-0.5-0.2-0.5 0.5-0.1 0.6-0.2 0.4-0.6 0.5-0.1 0.5-0.3zm-7.8-30.7c1.8-0.6 7.1 1.3 6.7 3.9-0.3 0.6-1.1 1-1.7 0.6l-0.7-0.5c-1.4-0.9-2.6-1.6-4-2.4-0.8-0.4-1.1-1.2-0.3-1.6zm10.2-3.8l-0.7-0.5c-3.7-2.4-9-6.2 0.4-2.3 1 0.4 2.5 0.7 3 1.7 1 1.9-1.4 2-2.7 1.1zm0.4-11c-0.3-1.2 3.5 0.2 4.6 0.5l0.1 0.1c1.1 0.4 2.3 0.7 2.9 1.7 0.8 1.2-0.7 1.5-1.7 0.9-1.9-1.2-4-2.2-5.9-3.2zm9.5-5.3c-2.1-2.3 3.5-0.1 4.4 0.5 0.6 0.4 0.5 1.4-0.1 1.7-1.7 0-2.9-1.4-4.3-2.2zm9.6-2.5c-3.4-2.4 1-1.3 2.6-0.4 1 1-0.1 2.5-2.6 0.4z"/>
|
|
18
|
+
</g>
|
|
19
|
+
<g id="face/Tired">
|
|
20
|
+
<path id="🖍-Ink" fill-rule="evenodd" class="s1" d="m141.1 77.8c1.4-0.3 2.4 0.8 2.1 2.1-0.2 1.4-1.7 1.9-3 1.8-1.4 0-2.8-0.3-4.2-0.4q-2.2-0.1-4.4 0c-1.3 0-2.7 0.3-4 0-0.5 0-0.5-0.7-0.2-1 1.1-0.7 2.4-1 3.5-1.3q1.9-0.5 3.7-0.7 1.9-0.2 3.8-0.2c0.6 0 1.3 0.1 1.8 0 0.3-0.1 0.6-0.3 0.9-0.3zm-3-19.1c8.1 1.4 3.9 15.4-6.5 7.7-1.2-1 0.3-3.2 1.6-2.3 1.5 1.1 4.4 3.5 6.4 1.4 1.7-2.4-0.7-4.7-2.3-5.6-0.4-0.3-0.1-1.3 0.8-1.2zm-12.4-6.1c2.1-0.3 2.5 2.7 0.4 2.9q-0.7 0.1-1.3 0.1 0 0.3 0.1 0.5 0 0.2 0 0.4c0.1 0.7-0.5 1.5-1.1 1.9-0.6 0.3-1.5 0.4-2.2 0-0.3-0.3-0.6-0.5-0.8-0.9q-0.4-0.5-0.4-1.2c-1 0.2-2 0.6-3 0.8q0.1 0 0.1 0.1c0.1 0 0 0.1 0 0l-0.5-0.1q-0.2 0.1-0.5 0.1c-0.2 0-0.4-0.3-0.2-0.6 0.9-0.9 2.2-1.5 3.5-2l1.2-0.5c1.5-0.6 3.1-1.2 4.7-1.5zm17.2 1c1.4-0.2 2.8-0.1 4.2 0 2.3 0.1 1.3 3.5-0.6 2.7q0.1 0.2 0 0.4c0 0.6-0.2 1.1-0.8 1.4-0.5 0.4-1.2 0.3-1.7 0-0.5-0.3-0.8-0.7-0.9-1.3-0.1-0.5-0.1-0.9 0-1.3q0-0.2 0.2-0.4-0.2-0.1-0.4-0.1c-1.2-0.3-2.4-0.2-3.5-0.4-0.2 0-0.2-0.2-0.1-0.3 1.1-0.5 2.4-0.6 3.6-0.7zm-17.4-10.7c0.8-0.3 1.8 0.3 2.2 1 0.5 0.8 0.3 1.7-0.3 2.4-0.9 1-2.6 1.6-3.8 2.2l-0.1 0.1q-1.9 0.9-3.9 1.6c-1.3 0.5-2.7 0.9-4 1.2q-1.1 0.3-2.2 0.4c-0.6 0.1-1-0.1-1.6-0.1-0.1 0-0.1-0.1 0-0.1 0.5-0.3 0.9-0.8 1.4-1.1q0.9-0.4 1.8-0.9c1.2-0.6 2.3-1.3 3.5-2q1.8-1.1 3.5-2.3c1.2-0.8 2.2-1.9 3.5-2.4zm14.4-0.6c1-0.2 2 0.3 2.3 1.3 0.3 1 0 1.2 0.7 1.9 0.6 0.6 1.3 1.1 1.9 1.6l1 0.7c1.8 1.3 3.6 2.5 5.6 3.4 0.2 0.1 0.1 0.3-0.1 0.3-3.2 0.1-6.3-0.3-9.2-1.8-1.4-0.7-2.8-1.5-3.5-2.9-1-1.5-0.9-4.1 1.3-4.5z"/>
|
|
21
|
+
</g>
|
|
22
|
+
<g id="facial-hair/*-None">
|
|
23
|
+
</g>
|
|
24
|
+
<g id="accessories/*-None">
|
|
25
|
+
</g>
|
|
26
|
+
</g>
|
|
27
|
+
</g>
|
|
28
|
+
</g>
|
|
29
|
+
</g>
|
|
30
|
+
</svg>
|