@madeinbruno/atelier 0.1.0 → 0.4.3

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/README.md CHANGED
@@ -1,61 +1,63 @@
1
- # @madeinbruno/atelier
2
-
3
- madeinbruno.com의 서비스들이 같이 쓰는 공용 컴포넌트예요. 옷 만드는 작업실(아틀리에) 컨셉이라 컴포넌트도 택, 라벨, 도장처럼 옷에 붙는 것들로 지어요.
4
-
5
- ## 설치
6
-
7
- ```bash
8
- pnpm add @madeinbruno/atelier
9
- ```
10
-
11
- React 18 이상이 필요해요.
12
-
13
- ## 컴포넌트
14
-
15
- ### `Tag` — 공용 푸터
16
-
17
- 흰 옷 택(행택) 모양의 푸터예요. 택 위쪽에 한 줄 박음질이 있고, 옷 택처럼 `MADE IN BRUNO / STYLE / SIZE / CONTACT`와 madeinbruno.com 링크가 들어가요.
18
-
19
- ```tsx
20
- import { Tag } from '@madeinbruno/atelier';
21
- import '@madeinbruno/atelier/styles.css'; // 앱에서 한 번만
22
-
23
- export default function Footer() {
24
- return <Tag service="hangoutwithme" background="#d6efdf" />;
25
- }
26
- ```
27
-
28
- | prop | 기본값 | 설명 |
29
- |---|---|---|
30
- | `service` (필수) | | 택의 STYLE 줄. 서비스 이름 |
31
- | `email` | `pbk575@gmail.com` | CONTACT 줄 (mailto 링크) |
32
- | `href` | `https://madeinbruno.com` | "둘러보기" 링크 |
33
- | `since` | `EST. 2026` | 택 오른쪽 위 작은 글씨 |
34
- | `eyebrow`, `message` | "Thanks for stopping by", "이 사이트도 madeinbruno에서 만들었어요." | 택 왼쪽 글. 둘 다 비우면 택만 가운데에 |
35
- | `background` | `#f4f1ea` | 푸터 바탕. 서비스 바탕색에 맞추기 |
36
- | `stitch` | `#9a948b` (회색) | 박음질 색 |
37
-
38
- 색은 CSS 변수(`--mib-ground`, `--mib-stitch`, `--mib-ink`)로도 바꿀 수 있어요. 클래스는 모두 `mib-`로 시작해 서비스 스타일과 겹치지 않아요. 글꼴(Archivo, IBM Plex Mono)은 `styles.css`가 Google Fonts에서 불러와요.
39
-
40
- ## 개발
41
-
42
- ```bash
43
- pnpm --filter @madeinbruno/atelier build # dist/ 생성
44
- pnpm --filter @madeinbruno/atelier dev # 고칠 때마다 다시 빌드
45
- ```
46
-
47
- ## 배포 (npm)
48
-
49
- 처음 한 번: npm에 `madeinbruno` 조직(무료, 공개 패키지)을 만들고 로그인해요.
50
-
51
- ```bash
52
- npm login
53
- ```
54
-
55
- 배포할 때마다 `package.json`의 `version`을 올리고:
56
-
57
- ```bash
58
- pnpm --filter @madeinbruno/atelier publish --access public
59
- ```
60
-
61
- (`prepublishOnly`가 먼저 빌드해요.)
1
+ # @madeinbruno/atelier
2
+
3
+ madeinbruno.com의 서비스들이 같이 쓰는 공용 컴포넌트예요. 옷 만드는 작업실(아틀리에) 컨셉이라 컴포넌트도 택, 라벨, 도장처럼 옷에 붙는 것들로 지어요.
4
+
5
+ ## 설치
6
+
7
+ ```bash
8
+ pnpm add @madeinbruno/atelier
9
+ ```
10
+
11
+ React 18 이상이 필요해요.
12
+
13
+ ## 컴포넌트
14
+
15
+ ### `Tag` — 공용 푸터
16
+
17
+ 흰 옷 택(행택) 모양의 푸터예요. 택 위쪽에 한 줄 박음질이 있고, 픽셀 글씨 `madeinbruno`, `SERVICE / CONTACT`와 madeinbruno.com 링크가 들어가요.
18
+
19
+ ```tsx
20
+ import { Tag } from '@madeinbruno/atelier';
21
+ import '@madeinbruno/atelier/styles.css'; // 앱에서 한 번만
22
+
23
+ export default function Footer() {
24
+ return <Tag service="hangoutwithme" background="#d6efdf" />;
25
+ }
26
+ ```
27
+
28
+ | prop | 기본값 | 설명 |
29
+ |---|---|---|
30
+ | `service` (필수) | | 택의 SERVICE 줄. 서비스 이름 |
31
+ | `email` | `pbk575@gmail.com` | CONTACT 줄 (mailto 링크) |
32
+ | `href` | `https://madeinbruno.com` | 택 아래 링크 (밑줄 친 주소) |
33
+ | `since` | `EST. 2026` | 택 오른쪽 위 작은 글씨 |
34
+ | `eyebrow`, `message` | "Thanks for stopping by", "이 사이트도 madeinbruno에서 만들었어요." | 택 왼쪽 글. 둘 다 비우면 택만 가운데에 |
35
+ | `background` | `#f4f1ea` | 푸터 바탕. 서비스 바탕색에 맞추기 |
36
+ | `stitch` | `#9a948b` (회색) | 박음질 색 |
37
+
38
+ `madeinbruno` 글씨는 [Banquise](https://gitlab.com/bonjour-monde/fonderie/banquise-typeface)(Bonjour Monde, SIL Open Font License 1.1)로 쓴 글자를 SVG 그림으로 옮긴 거예요. 이 한 단어에만 쓰는 폰트라 폰트 파일을 싣지 않아요 (15KB → 1KB 미만, 글씨가 늦게 바뀌는 깜빡임도 없음).
39
+
40
+ 색은 CSS 변수(`--mib-ground`, `--mib-stitch`, `--mib-ink`)로도 바꿀 수 있어요. 클래스는 모두 `mib-`로 시작해 서비스 스타일과 겹치지 않아요. 글꼴(IBM Plex Mono, 택 옆 글의 Archivo)은 `styles.css`가 Google Fonts에서 불러와요.
41
+
42
+ ## 개발
43
+
44
+ ```bash
45
+ pnpm --filter @madeinbruno/atelier build # dist/ 생성
46
+ pnpm --filter @madeinbruno/atelier dev # 고칠 때마다 다시 빌드
47
+ ```
48
+
49
+ ## 배포 (npm)
50
+
51
+ GitHub Actions(`.github/workflows/publish-atelier.yml`)가 배포해요.
52
+
53
+ 1. 고친 뒤 `package.json`의 `version`을 올려서 `main`에 푸시해요 (버전을 안 올리면 건너뛰어요).
54
+
55
+ 버전은 이렇게 올려요:
56
+ - **패치** (0.4.0 → 0.4.1): 모양·문구·여백 수정, 버그 수정. 쓰는 쪽 코드는 그대로.
57
+ - **마이너** (0.4.x → 0.5.0): 새 prop·새 컴포넌트처럼 기능이 늘어날 때. 1.0 전에는 쓰는 쪽 코드를 고쳐야 하는 변경(prop 이름 변경·삭제)도 마이너로 올리고, 1.0 이후에는 메이저로 올려요.
58
+ 2. Actions가 빌드해서 npm 승인 대기열(staged)에 올려요.
59
+ 3. npmjs.com에서 그 버전을 승인(2단계 인증)하면 공개돼요.
60
+
61
+ npm 로그인은 trusted publishing(OIDC)이라 저장소에 토큰이 없어요. 처음 한 번, npmjs.com의 패키지 설정 → Trusted publishing에 GitHub 저장소 `codingbotPark/madeinbruno`, 워크플로 파일 `publish-atelier.yml`을 등록해 둬야 해요.
62
+
63
+ 손으로 올릴 때는 `npm login` 후 `packages/atelier`에서 `npm stage publish --access public`.
package/dist/index.d.ts CHANGED
@@ -2,11 +2,11 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
 
4
4
  type TagProps = {
5
- /** 이 서비스의 이름. 택의 STYLE 줄에 들어간다 (예: "hangoutwithme"). */
5
+ /** 이 서비스의 이름. 택의 SERVICE 줄에 들어간다 (예: "hangoutwithme"). */
6
6
  service: string;
7
7
  /** 연락받을 이메일. 택의 CONTACT 줄에 mailto 링크로 들어간다. */
8
8
  email?: string;
9
- /** "둘러보기" 링크가 가는 곳. */
9
+ /** 택 아래 링크(밑줄 친 주소)가 가는 곳. */
10
10
  href?: string;
11
11
  /** 택 오른쪽 위의 작은 글씨. */
12
12
  since?: string;
@@ -19,12 +19,6 @@ type TagProps = {
19
19
  stitch?: string;
20
20
  className?: string;
21
21
  };
22
- /**
23
- * madeinbruno 공용 푸터: 흰 옷 택(행택).
24
- * 택 위쪽에 한 줄 박음질, 끈 구멍, 모서리를 깎은 모양이고, 옷 택 형식으로
25
- * MADE IN BRUNO / STYLE(서비스 이름) / SIZE / CONTACT(이메일)와 madeinbruno.com 링크를 담는다.
26
- * 스타일은 '@madeinbruno/atelier/styles.css'를 한 번 불러와야 적용된다.
27
- */
28
22
  declare function Tag({ service, email, href, since, eyebrow, message, background, stitch, className, }: TagProps): react.JSX.Element;
29
23
 
30
24
  export { Tag, type TagProps };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/Tag.tsx
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
+ var WORDMARK = "M18 0h2v2h-2zM27 0h2v1h-2zM36 0h2v2h-2zM0 2h1v1h-1zM2 2h2v1h-2zM5 2h2v1h-2zM9 2h4v1h-4zM17 2h3v1h-3zM22 2h3v1h-3zM27 2h2v6h-2zM30 2h1v1h-1zM32 2h2v1h-2zM36 2h4v1h-4zM42 2h1v1h-1zM44 2h2v1h-2zM50 2h2v5h-2zM53 2h1v1h-1zM55 2h2v1h-2zM60 2h3v1h-3zM0 3h2v5h-2zM3 3h2v5h-2zM6 3h2v5h-2zM9 3h2v1h-2zM12 3h2v2h-2zM15 3h2v4h-2zM18 3h2v4h-2zM21 3h2v1h-2zM24 3h2v1h-2zM30 3h2v5h-2zM33 3h2v5h-2zM36 3h2v4h-2zM39 3h2v4h-2zM42 3h4v1h-4zM47 3h2v4h-2zM53 3h2v5h-2zM56 3h2v5h-2zM62 3h2v4h-2zM21 4h5v1h-5zM42 4h2v4h-2zM59 4h2v3h-2zM9 5h5v1h-5zM21 5h2v2h-2zM9 6h2v1h-2zM12 6h2v1h-2zM25 6h1v1h-1zM10 7h2v1h-2zM13 7h1v1h-1zM16 7h2v1h-2zM19 7h1v1h-1zM23 7h2v1h-2zM36 7h1v1h-1zM38 7h1v1h-1zM48 7h2v1h-2zM51 7h1v1h-1zM61 7h2v1h-2z";
3
4
  function Tag({
4
5
  service,
5
6
  email = "pbk575@gmail.com",
@@ -24,22 +25,19 @@ function Tag({
24
25
  ] }),
25
26
  /* @__PURE__ */ jsx("div", { className: "mib-tag-hang", children: /* @__PURE__ */ jsx("div", { className: "mib-tag", children: /* @__PURE__ */ jsxs("div", { className: "mib-tag__card", children: [
26
27
  /* @__PURE__ */ jsx("span", { className: "mib-tag__stitch", "aria-hidden": "true" }),
27
- /* @__PURE__ */ jsx("span", { className: "mib-tag__hole", "aria-hidden": "true" }),
28
28
  /* @__PURE__ */ jsxs("div", { className: "mib-tag__head", children: [
29
- /* @__PURE__ */ jsx("span", { className: "mib-tag__brand", children: "MADE IN BRUNO" }),
29
+ /* @__PURE__ */ jsx("svg", { className: "mib-tag__brand", viewBox: "0 0 64 8", role: "img", "aria-label": "madeinbruno", children: /* @__PURE__ */ jsx("path", { d: WORDMARK }) }),
30
30
  /* @__PURE__ */ jsx("span", { className: "mib-tag__since", children: since })
31
31
  ] }),
32
32
  /* @__PURE__ */ jsxs("dl", { className: "mib-tag__specs", children: [
33
- /* @__PURE__ */ jsx("dt", { children: "STYLE" }),
33
+ /* @__PURE__ */ jsx("dt", { children: "SERVICE" }),
34
34
  /* @__PURE__ */ jsx("dd", { children: service }),
35
- /* @__PURE__ */ jsx("dt", { children: "SIZE" }),
36
- /* @__PURE__ */ jsx("dd", { children: "ONE OF ONE" }),
37
35
  /* @__PURE__ */ jsx("dt", { children: "CONTACT" }),
38
36
  /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: `mailto:${email}`, children: email }) })
39
37
  ] }),
40
38
  /* @__PURE__ */ jsxs("a", { className: "mib-tag__link", href, children: [
41
39
  linkLabel,
42
- " \uB458\uB7EC\uBCF4\uAE30 \u2192"
40
+ " \u2192"
43
41
  ] })
44
42
  ] }) }) })
45
43
  ] }) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madeinbruno/atelier",
3
- "version": "0.1.0",
3
+ "version": "0.4.3",
4
4
  "description": "madeinbruno.com 서비스들이 같이 쓰는 공용 컴포넌트 (옷 만드는 작업실 컨셉: 택, 라벨, 도장…)",
5
5
  "license": "MIT",
6
6
  "author": "codingbotPark <pbk575@gmail.com>",
@@ -27,6 +27,12 @@
27
27
  "dist",
28
28
  "styles.css"
29
29
  ],
30
+ "scripts": {
31
+ "build": "tsup",
32
+ "dev": "tsup --watch",
33
+ "check": "tsc --noEmit",
34
+ "prepublishOnly": "pnpm build"
35
+ },
30
36
  "peerDependencies": {
31
37
  "react": ">=18"
32
38
  },
@@ -38,10 +44,5 @@
38
44
  },
39
45
  "publishConfig": {
40
46
  "access": "public"
41
- },
42
- "scripts": {
43
- "build": "tsup",
44
- "dev": "tsup --watch",
45
- "check": "tsc --noEmit"
46
47
  }
47
- }
48
+ }
package/styles.css CHANGED
@@ -1,200 +1,189 @@
1
- /* @madeinbruno/atelier 공용 스타일. 쓰는 쪽에서 한 번만 불러온다: import '@madeinbruno/atelier/styles.css'
2
- 클래스 이름은 모두 mib- 로 시작해 서비스 자체 스타일과 겹치지 않는다.
3
- 색은 CSS 변수로 바꿀 수 있다: --mib-ground(푸터 바탕), --mib-stitch(박음질), --mib-ink(글씨). */
4
- @import url('https://fonts.googleapis.com/css2?family=Archivo:wght@500;800&family=IBM+Plex+Mono:wght@400;500&display=swap');
5
-
6
- /* ───────── Tag: 흰 옷 택 푸터 ───────── */
7
-
8
- .mib-footer {
9
- --mib-ground: #f4f1ea;
10
- --mib-stitch: #9a948b;
11
- --mib-ink: #1f1d1a;
12
- --mib-muted: #6b655c;
13
- box-sizing: border-box;
14
- width: 100%;
15
- overflow: hidden;
16
- padding: 0 24px;
17
- border-top: 1px solid rgba(31, 29, 26, 0.12);
18
- background: var(--mib-ground);
19
- font-family: 'IBM Plex Mono', ui-monospace, monospace;
20
- color: var(--mib-ink);
21
- }
22
-
23
- .mib-footer *,
24
- .mib-footer *::before,
25
- .mib-footer *::after {
26
- box-sizing: border-box;
27
- }
28
-
29
- .mib-footer a {
30
- color: inherit;
31
- text-decoration: none;
32
- }
33
-
34
- .mib-footer a:hover {
35
- color: #b4442f;
36
- }
37
-
38
- .mib-footer__inner {
39
- display: flex;
40
- flex-wrap: wrap;
41
- align-items: center;
42
- justify-content: space-between;
43
- gap: 32px 64px;
44
- max-width: 1120px;
45
- margin: 0 auto;
46
- padding-bottom: 56px;
47
- }
48
-
49
- .mib-footer__inner--solo {
50
- justify-content: center;
51
- }
52
-
53
- .mib-footer__message {
54
- display: flex;
55
- flex: 1 1 300px;
56
- flex-direction: column;
57
- gap: 14px;
58
- max-width: 440px;
59
- padding-top: 64px;
60
- }
61
-
62
- .mib-footer__eyebrow {
63
- margin: 0;
64
- font-size: 13px;
65
- letter-spacing: 0.08em;
66
- text-transform: uppercase;
67
- color: var(--mib-muted);
68
- }
69
-
70
- .mib-footer__text {
71
- margin: 0;
72
- font-family: 'Archivo', system-ui, sans-serif;
73
- font-size: clamp(20px, 3vw, 28px);
74
- font-weight: 500;
75
- line-height: 1.35;
76
- letter-spacing: -0.01em;
77
- word-break: keep-all;
78
- }
79
-
80
- .mib-tag-hang {
81
- position: relative;
82
- flex: 0 1 470px;
83
- padding-top: 56px;
84
- }
85
-
86
- /* 구멍을 축으로 살짝 기울어 매달려 있다. */
87
- .mib-tag {
88
- transform: rotate(-4deg);
89
- transform-origin: 77px 13px;
90
- filter: drop-shadow(0 10px 18px rgba(31, 29, 26, 0.14));
91
- }
92
-
93
- .mib-tag__card {
94
- position: relative;
95
- display: flex;
96
- flex-direction: column;
97
- gap: 14px;
98
- min-height: 236px;
99
- padding: 46px 34px 26px;
100
- background: #ffffff;
101
- /* 옷 택처럼 위쪽 두 모서리를 비스듬히 깎는다 */
102
- clip-path: polygon(18px 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%, 0 18px);
103
- }
104
-
105
- .mib-tag__stitch {
106
- position: absolute;
107
- top: 22px;
108
- left: 22px;
109
- right: 22px;
110
- height: 2px;
111
- background: repeating-linear-gradient(90deg, var(--mib-stitch) 0 9px, transparent 9px 15px);
112
- }
113
-
114
- .mib-tag__hole {
115
- position: absolute;
116
- top: 6px;
117
- left: 70px;
118
- width: 14px;
119
- height: 14px;
120
- border-radius: 50%;
121
- background: var(--mib-ground);
122
- box-shadow: inset 0 0 0 3px #d9d2c5;
123
- }
124
-
125
- .mib-tag__head {
126
- display: flex;
127
- flex-wrap: wrap;
128
- align-items: baseline;
129
- justify-content: space-between;
130
- gap: 4px 12px;
131
- }
132
-
133
- .mib-tag__brand {
134
- font-family: 'Archivo', system-ui, sans-serif;
135
- font-size: clamp(24px, 7vw, 31px);
136
- font-weight: 800;
137
- letter-spacing: 0.02em;
138
- white-space: nowrap;
139
- }
140
-
141
- .mib-tag__since {
142
- font-size: 12px;
143
- color: var(--mib-muted);
144
- }
145
-
146
- .mib-tag__specs {
147
- display: grid;
148
- grid-template-columns: auto minmax(0, 1fr);
149
- gap: 6px 24px;
150
- margin: 0;
151
- padding-top: 14px;
152
- border-top: 1px solid #e7e1d6;
153
- font-size: 13px;
154
- }
155
-
156
- .mib-tag__specs dt {
157
- color: var(--mib-muted);
158
- }
159
-
160
- .mib-tag__specs dd {
161
- margin: 0;
162
- overflow-wrap: anywhere;
163
- }
164
-
165
- .mib-tag__link {
166
- align-self: flex-start;
167
- margin-top: auto;
168
- padding-bottom: 2px;
169
- border-bottom: 1px solid currentColor;
170
- font-size: 14px;
171
- font-weight: 500;
172
- }
173
-
174
- /* 좁은 화면: 글 아래에 택이 오고, 택은 화면 폭에 맞춘다. */
175
- @media (max-width: 640px) {
176
- .mib-footer__inner {
177
- flex-direction: column;
178
- align-items: stretch;
179
- gap: 8px;
180
- padding-bottom: 40px;
181
- }
182
-
183
- .mib-footer__message {
184
- flex: none;
185
- padding-top: 48px;
186
- }
187
-
188
- .mib-tag-hang {
189
- flex: none;
190
- width: 100%;
191
- max-width: 470px;
192
- align-self: center;
193
- padding-top: 24px;
194
- }
195
-
196
- .mib-tag__card {
197
- min-height: 0;
198
- padding: 44px 24px 24px;
199
- }
200
- }
1
+ /* @madeinbruno/atelier 공용 스타일. 쓰는 쪽에서 한 번만 불러온다: import '@madeinbruno/atelier/styles.css'
2
+ 클래스 이름은 모두 mib- 로 시작해 서비스 자체 스타일과 겹치지 않는다.
3
+ 색은 CSS 변수로 바꿀 수 있다: --mib-ground(푸터 바탕), --mib-stitch(박음질), --mib-ink(글씨). */
4
+ @import url('https://fonts.googleapis.com/css2?family=Archivo:wght@500&family=IBM+Plex+Mono:wght@400;500&display=swap');
5
+
6
+ /* ───────── Tag: 흰 옷 택 푸터 ───────── */
7
+
8
+ .mib-footer {
9
+ --mib-ground: #f4f1ea;
10
+ --mib-stitch: #9a948b;
11
+ --mib-ink: #1f1d1a;
12
+ --mib-muted: #6b655c;
13
+ box-sizing: border-box;
14
+ width: 100%;
15
+ overflow: hidden;
16
+ padding: 0 24px;
17
+ background: var(--mib-ground);
18
+ font-family: 'IBM Plex Mono', ui-monospace, monospace;
19
+ color: var(--mib-ink);
20
+ }
21
+
22
+ .mib-footer *,
23
+ .mib-footer *::before,
24
+ .mib-footer *::after {
25
+ box-sizing: border-box;
26
+ }
27
+
28
+ .mib-footer a {
29
+ color: inherit;
30
+ text-decoration: none;
31
+ }
32
+
33
+ .mib-footer a:hover {
34
+ color: #b4442f;
35
+ }
36
+
37
+ .mib-footer__inner {
38
+ display: flex;
39
+ flex-wrap: wrap;
40
+ /* 택은 페이지 맨 아래 끝에 붙는다 (아래 여백 없이) */
41
+ align-items: flex-end;
42
+ justify-content: space-between;
43
+ gap: 32px 64px;
44
+ max-width: 1120px;
45
+ margin: 0 auto;
46
+ }
47
+
48
+ .mib-footer__inner--solo {
49
+ justify-content: center;
50
+ }
51
+
52
+ .mib-footer__message {
53
+ display: flex;
54
+ flex: 1 1 300px;
55
+ flex-direction: column;
56
+ gap: 14px;
57
+ max-width: 440px;
58
+ padding-top: 64px;
59
+ }
60
+
61
+ .mib-footer__eyebrow {
62
+ margin: 0;
63
+ font-size: 13px;
64
+ letter-spacing: 0.08em;
65
+ text-transform: uppercase;
66
+ color: var(--mib-muted);
67
+ }
68
+
69
+ .mib-footer__text {
70
+ margin: 0;
71
+ font-family: 'Archivo', system-ui, sans-serif;
72
+ font-size: clamp(20px, 3vw, 28px);
73
+ font-weight: 500;
74
+ line-height: 1.35;
75
+ letter-spacing: -0.01em;
76
+ word-break: keep-all;
77
+ }
78
+
79
+ .mib-tag-hang {
80
+ position: relative;
81
+ flex: 0 1 470px;
82
+ padding-top: 32px;
83
+ }
84
+
85
+ /* 아래가 화면 끝에 닿아 있으니 그림자는 위쪽으로만 옅게 */
86
+ .mib-tag {
87
+ filter: drop-shadow(0 -4px 16px rgba(31, 29, 26, 0.1));
88
+ }
89
+
90
+ .mib-tag__card {
91
+ position: relative;
92
+ display: flex;
93
+ flex-direction: column;
94
+ gap: 14px;
95
+ min-height: 236px;
96
+ padding: 46px 34px 26px;
97
+ background: #ffffff;
98
+ /* 옷 택처럼 위쪽 두 모서리를 비스듬히 깎는다 */
99
+ clip-path: polygon(18px 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%, 0 18px);
100
+ }
101
+
102
+ .mib-tag__stitch {
103
+ position: absolute;
104
+ top: 22px;
105
+ left: 22px;
106
+ right: 22px;
107
+ height: 2px;
108
+ background: repeating-linear-gradient(90deg, var(--mib-stitch) 0 9px, transparent 9px 15px);
109
+ }
110
+
111
+ .mib-tag__head {
112
+ display: flex;
113
+ flex-wrap: wrap;
114
+ align-items: baseline;
115
+ justify-content: space-between;
116
+ gap: 10px 12px;
117
+ }
118
+
119
+ .mib-tag__brand {
120
+ /* 64×8 칸 그림. 칸이 흐려지지 않게 경계를 픽셀에 맞춘다 */
121
+ display: block;
122
+ width: auto;
123
+ height: clamp(24px, 7.2vw, 32px);
124
+ fill: currentColor;
125
+ shape-rendering: crispEdges;
126
+ }
127
+
128
+ .mib-tag__since {
129
+ font-size: 12px;
130
+ color: var(--mib-muted);
131
+ }
132
+
133
+ .mib-tag__specs {
134
+ display: grid;
135
+ grid-template-columns: auto minmax(0, 1fr);
136
+ gap: 6px 24px;
137
+ margin: 0;
138
+ padding-top: 14px;
139
+ border-top: 1px solid #e7e1d6;
140
+ font-size: 13px;
141
+ }
142
+
143
+ .mib-tag__specs dt {
144
+ color: var(--mib-muted);
145
+ }
146
+
147
+ .mib-tag__specs dd {
148
+ margin: 0;
149
+ overflow-wrap: anywhere;
150
+ }
151
+
152
+ .mib-tag__link {
153
+ align-self: flex-start;
154
+ margin-top: auto;
155
+ padding-bottom: 2px;
156
+ border-bottom: 1px solid currentColor;
157
+ font-size: 14px;
158
+ font-weight: 500;
159
+ }
160
+
161
+ /* 좁은 화면: 글 아래에 택이 오고, 택은 화면 폭에 맞춘다. */
162
+ @media (max-width: 640px) {
163
+ /* 좁은 화면: 택이 양옆은 띄우고 아래 끝에만 붙는다 */
164
+ .mib-footer {
165
+ padding: 0 16px;
166
+ }
167
+
168
+ .mib-footer__inner {
169
+ flex-direction: column;
170
+ align-items: stretch;
171
+ gap: 8px;
172
+ }
173
+
174
+ .mib-footer__message {
175
+ flex: none;
176
+ padding-top: 48px;
177
+ }
178
+
179
+ .mib-tag-hang {
180
+ flex: none;
181
+ width: 100%;
182
+ padding-top: 16px;
183
+ }
184
+
185
+ .mib-tag__card {
186
+ min-height: 0;
187
+ padding: 44px 24px 24px;
188
+ }
189
+ }