| 1 |
|
| 2 |
DISCOVER PAGE |
| 3 |
=========================================== |
| 4 |
|
| 5 |
.discover-layout { display: grid; grid-template-columns: 200px 1fr; gap: var(--gap-pane); } |
| 6 |
.discover-layout.no-sidebar { grid-template-columns: 1fr; } |
| 7 |
.discover-layout.no-sidebar .discover-sidebar { display: none; } |
| 8 |
.discover-sidebar { font-size: var(--text-note); } |
| 9 |
.filter-section { margin-bottom: var(--gap-section); } |
| 10 |
.filter-title { font-family: var(--font-display); font-weight: bold; font-size: var(--text-note); margin-bottom: var(--gap-peer); color: var(--content); } |
| 11 |
.filter-list { list-style: none; } |
| 12 |
|
| 13 |
is a real <button> child so Enter/Space work without scripting. |
| 14 |
.filter-item { display: flex; align-items: center; gap: var(--gap-bound); transition: opacity 0.1s ease; } |
| 15 |
.filter-item:hover { opacity: 0.6; } |
| 16 |
.filter-item.is-selected { font-weight: bold; } |
| 17 |
.filter-item .count { opacity: 0.4; font-size: var(--text-fine); } |
| 18 |
.tag-follow-btn { background: none; border: 1px solid var(--border); cursor: pointer; font-family: var(--font-mono); font-size: var(--text-fine); opacity: 0.55; padding: var(--gap-bound) var(--gap-peer); color: var(--content); } |
| 19 |
.tag-follow-btn:hover { opacity: 1; } |
| 20 |
.tag-follow-btn.is-selected { opacity: 0.85; border-color: var(--focus-ring); background: var(--highlight-faint); } |
| 21 |
.filter-checkbox { display: flex; align-items: center; gap: var(--gap-peer); padding: var(--gap-bound) 0; cursor: pointer; } |
| 22 |
.filter-checkbox input { width: auto; margin: 0; } |
| 23 |
.price-inputs { display: flex; gap: var(--gap-bound); align-items: center; margin-bottom: var(--gap-peer); } |
| 24 |
.price-inputs input { width: 60px; padding: var(--gap-bound); font-size: var(--text-fine); background: var(--surface-sunken); border: none; } |
| 25 |
.price-inputs span { opacity: 0.4; } |
| 26 |
.discover-main { min-width: 0; } |
| 27 |
|
| 28 |
|
| 29 |
Tags are the sidebar's structure, not one facet among several, so the spine |
| 30 |
reads as the primary surface and .filter-refine below it is subordinate. |
| 31 |
Everything here composes existing primitives: .filter-item carries the row |
| 32 |
and its .is-selected recipe, the described field draws its own list, and |
| 33 |
.breadcrumb carries the crumb idiom. |
| 34 |
.tag-spine { padding-bottom: var(--gap-section); border-bottom: 1px solid var(--border); } |
| 35 |
|
| 36 |
|
| 37 |
selected tint rather than a new colour. |
| 38 |
.tag-chips { list-style: none; display: flex; flex-wrap: wrap; gap: var(--gap-bound); margin-bottom: var(--gap-section); } |
| 39 |
.tag-chip { display: flex; align-items: center; gap: var(--gap-bound); padding: var(--gap-bound) var(--gap-peer); font-size: var(--text-fine); background: var(--highlight-faint); border: 1px solid var(--focus-ring); } |
| 40 |
.tag-chip-label { overflow-wrap: anywhere; } |
| 41 |
.tag-chip-remove { text-decoration: none; color: var(--content-secondary); font-size: var(--text-body); line-height: 1; padding: 0 var(--gap-bound); } |
| 42 |
.tag-chip-remove:hover { color: var(--content); } |
| 43 |
.tag-chip-clear { background: none; border: 1px dashed var(--border-strong); } |
| 44 |
.tag-chip-clear a { text-decoration: none; color: var(--content-secondary); font-size: var(--text-fine); } |
| 45 |
.tag-chip-clear a:hover { color: var(--content); } |
| 46 |
|
| 47 |
|
| 48 |
the described field's, so all this carries is the positioning context the |
| 49 |
list is drawn against. |
| 50 |
.tag-combobox { position: relative; margin-bottom: var(--gap-section); } |
| 51 |
|
| 52 |
|
| 53 |
rows with both put the chevron after the label. |
| 54 |
.tag-crumbs { list-style: none; display: flex; flex-wrap: wrap; font-family: var(--font-mono); font-size: var(--text-fine); color: var(--content-muted); margin-bottom: var(--gap-peer); } |
| 55 |
.tag-crumbs li + li::before { content: "/"; opacity: 0.4; margin: 0 var(--gap-bound); } |
| 56 |
.tag-crumbs a { color: var(--content); text-decoration: none; } |
| 57 |
.tag-crumbs a:hover { text-decoration: underline; } |
| 58 |
.tag-drill-select { flex: 1; display: flex; align-items: center; gap: var(--gap-peer); cursor: pointer; padding: var(--gap-bound) 0; } |
| 59 |
.tag-drill-select input { width: auto; margin: 0; } |
| 60 |
.tag-drill-select span:first-of-type { flex: 1; } |
| 61 |
.tag-drill-into { display: flex; align-items: center; gap: var(--gap-peer); flex: 1; text-decoration: none; color: inherit; padding: var(--gap-bound) 0; } |
| 62 |
.tag-drill-into span:first-child { flex: 1; } |
| 63 |
.tag-drill-chevron { opacity: 0.4; } |
| 64 |
|
| 65 |
|
| 66 |
Subordinate to the spine: same controls, quieter. |
| 67 |
.filter-refine { margin-top: var(--gap-section); } |
| 68 |
.filter-fieldset { border: none; padding: 0; margin: 0; min-width: 0; } |
| 69 |
.filter-check { flex: 1; display: flex; align-items: center; gap: var(--gap-peer); cursor: pointer; padding: var(--gap-bound) 0; } |
| 70 |
.filter-check input { width: auto; margin: 0; } |
| 71 |
.filter-check span:first-of-type { flex: 1; } |
| 72 |
|
| 73 |
|
| 74 |
stays legible as filters narrow. No existing rule covers a disabled input |
| 75 |
inside a label, so this is the checkbox counterpart of the button rule. |
| 76 |
`.is-empty` covers the drill rungs, which are links and carry no input at |
| 77 |
all; they were rendering identically to rungs with items. |
| 78 |
.filter-item:has(input:disabled), .filter-item.is-empty { opacity: 0.5; } |
| 79 |
.filter-item:has(input:disabled) .filter-check { cursor: not-allowed; } |
| 80 |
|
| 81 |
|
| 82 |
.price-buckets { margin-top: var(--gap-peer); } |
| 83 |
.price-bucket { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: var(--gap-peer); text-decoration: none; color: inherit; padding: var(--gap-bound) 0; } |
| 84 |
|
| 85 |
.mode-toggle { display: flex; gap: var(--gap-peer); margin-bottom: var(--gap-section); } |
| 86 |
.toggle-btn { background: var(--surface-sunken); border: none; padding: var(--gap-peer) var(--gap-section); font-size: var(--text-note); font-family: inherit; cursor: pointer; transition: background 0.1s ease, opacity 0.1s ease; } |
| 87 |
.toggle-btn:hover { opacity: 0.7; } |
| 88 |
.toggle-btn.is-selected { background: var(--primary-dark); color: var(--primary-light); } |
| 89 |
.table-controls { background: var(--surface-sunken); display: flex; align-items: center; gap: var(--gap-section); padding: var(--gap-peer) var(--gap-section); } |
| 90 |
.table-meta { font-size: var(--text-fine); opacity: 0.6; white-space: nowrap; flex-shrink: 0; } |
| 91 |
.sort-select { background: var(--surface-page); border: none; padding: var(--gap-bound) var(--gap-peer); font-size: var(--text-fine); font-family: inherit; cursor: pointer; width: auto; flex-shrink: 0; } |
| 92 |
.table-header { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: var(--gap-peer); padding: var(--gap-peer) var(--gap-section); background: var(--surface-overlay); font-size: var(--text-fine); opacity: 0.7; text-transform: uppercase; letter-spacing: 0.03em; } |
| 93 |
.table-header.projects-header { grid-template-columns: 1fr 100px 80px 70px; } |
| 94 |
|
| 95 |
.table-header.is-hidden { display: none; } |
| 96 |
.col-right { text-align: right; } |
| 97 |
.results-table { border: 1px solid var(--border); border-top: none; } |
| 98 |
.table-row { |
| 99 |
but has no vocabulary for column tracks, so the tracks and the display that carries |
| 100 |
them are stated together here. display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: var(--gap-peer); padding: var(--gap-peer) var(--gap-section); align-items: center; text-decoration: none; color: var(--content); font-size: var(--text-note); border-bottom: 1px solid var(--border); transition: background 0.1s ease; } |
| 101 |
.table-row-item { grid-template-columns: 1fr 30px; padding: 0; gap: 0; } |
| 102 |
.table-row-item .table-row-link { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: var(--gap-peer); padding: var(--gap-peer) var(--gap-section); align-items: center; text-decoration: none; color: inherit; flex: 1; } |
| 103 |
.table-row-item .row-save { display: flex; align-items: center; justify-content: center; } |
| 104 |
.table-row.project-row { grid-template-columns: 1fr 100px 80px 70px; } |
| 105 |
.table-row:last-child { border-bottom: none; } |
| 106 |
.table-row:hover { background: var(--surface-sunken); text-decoration: none; } |
| 107 |
.row-type { font-size: var(--text-fine); background: var(--surface-sunken); padding: var(--gap-bound) var(--gap-peer); text-align: center; opacity: 0.7; } |
| 108 |
.row-info { min-width: 0; display: flex; flex-direction: column; gap: var(--gap-bound); } |
| 109 |
.row-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
| 110 |
.row-creator { font-size: var(--text-fine); opacity: 0.5; }.row-category { font-size: var(--text-fine); opacity: 0.6; } |
| 111 |
.row-price { text-align: right; } |
| 112 |
.row-items { text-align: right; opacity: 0.6; font-size: var(--text-fine); } |
| 113 |
.row-date { text-align: right; opacity: 0.5; font-size: var(--text-fine); }.pagination { display: flex; gap: var(--gap-bound); } |
| 114 |
.pagination button { background: var(--surface-page); border: none; padding: var(--gap-bound) var(--gap-group); font-size: var(--text-fine); cursor: pointer; } |
| 115 |
.pagination button:disabled { opacity: 0.3; cursor: not-allowed; } |
| 116 |
.pagination button.is-selected { background: var(--primary-dark); color: var(--primary-light); } |
| 117 |
|
| 118 |
|
| 119 |
.issue-tabs { display: flex; gap: var(--gap-peer); margin-bottom: var(--gap-section); } |
| 120 |
.issue-tab { |
| 121 |
padding: var(--gap-peer) var(--gap-section); |
| 122 |
border: 1px solid var(--border); |
| 123 |
background: var(--surface-overlay); |
| 124 |
font-family: var(--font-mono); |
| 125 |
font-size: var(--text-note); |
| 126 |
color: var(--content); |
| 127 |
text-decoration: none; |
| 128 |
opacity: 0.7; |
| 129 |
} |
| 130 |
.issue-tab:hover { opacity: 1; } |
| 131 |
.issue-tab.is-selected { |
| 132 |
opacity: 1; |
| 133 |
background: var(--highlight-faint); |
| 134 |
border-color: var(--focus-ring); |
| 135 |
} |
| 136 |
.page-info { opacity: 0.6; } |
| 137 |
.padded-page .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--gap-section); padding-bottom: var(--gap-section); border-bottom: 1px solid var(--border); } |
| 138 |
.padded-page .page-header h1 { font-size: var(--text-head); text-align: center; position: absolute; left: 50%; transform: translateX(-50%); } |
| 139 |
.padded-page .page-header nav { margin: 0; } |
| 140 |
.padded-page .page-header .nav-links { gap: var(--gap-pane); } |
| 141 |
.discover-filter-toggle { |
| 142 |
display: none; |
| 143 |
font-family: var(--font-mono); |
| 144 |
font-size: var(--text-note); |
| 145 |
padding: var(--gap-peer) var(--gap-section); |
| 146 |
background: var(--surface-overlay); |
| 147 |
border: 1px solid var(--border); |
| 148 |
cursor: pointer; |
| 149 |
margin-bottom: var(--gap-section); |
| 150 |
} |
| 151 |
|
| 152 |
.discover-filter-toggle.active { background: var(--surface-sunken); border-color: var(--border-strong); } |
| 153 |
|
| 154 |
.discover-filter-toggle .filter-count { |
| 155 |
background: var(--action); |
| 156 |
color: var(--primary-light); |
| 157 |
font-size: var(--text-fine); |
| 158 |
padding: var(--gap-bound) var(--gap-peer); |
| 159 |
border-radius: var(--radius-control); |
| 160 |
margin-left: var(--gap-bound); |
| 161 |
} |
| 162 |
|
| 163 |
@media (max-width: 839px) { |
| 164 |
.discover-filter-toggle { display: inline-block; } |
| 165 |
.discover-layout { grid-template-columns: 1fr; } |
| 166 |
.discover-sidebar { display: none; } |
| 167 |
|
| 168 |
by an out-of-band swap on every filter change and would lose the class. |
| 169 |
.discover-layout.filters-open .discover-sidebar { display: block; margin-bottom: var(--gap-section); } |
| 170 |
.table-header, .table-row { grid-template-columns: 40px 1fr 60px; } |
| 171 |
.table-row-item { grid-template-columns: 1fr 30px; } |
| 172 |
.table-row-item .table-row-link { grid-template-columns: 40px 1fr 60px; } |
| 173 |
.table-header.projects-header, .table-row.project-row { grid-template-columns: 1fr 70px; } |
| 174 |
.row-date, .row-items, .row-category { display: none; } |
| 175 |
.table-header span:nth-child(3), .table-header span:nth-child(4), .table-header span:nth-child(5) { display: none; } |
| 176 |
.table-header.projects-header span:nth-child(3), .table-header.projects-header span:nth-child(4) { display: none; } |
| 177 |
} |
| 178 |
|
| 179 |
@media (max-width: 599px) { |
| 180 |
.table-header, .table-row { grid-template-columns: 1fr 60px; } |
| 181 |
.table-row-item { grid-template-columns: 1fr 30px; } |
| 182 |
.table-row-item .table-row-link { grid-template-columns: 1fr 60px; } |
| 183 |
.row-type { display: none; } |
| 184 |
.table-header span:first-child { display: none; } |
| 185 |
.table-header.projects-header, .table-row.project-row { grid-template-columns: 1fr; } |
| 186 |
.table-header.projects-header span:nth-child(2) { display: none; } |
| 187 |
.row-price { font-size: var(--text-fine); } |
| 188 |
.table-controls { flex-wrap: wrap; } |
| 189 |
.mode-toggle { flex-wrap: wrap; } |
| 190 |
.table-footer { flex-direction: column; gap: var(--gap-peer); align-items: flex-start; } |
| 191 |
} |
| 192 |
|
| 193 |
|
| 194 |
|
| 195 |
.type-grid { |
| 196 |
display: grid; |
| 197 |
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| 198 |
gap: var(--gap-section); |
| 199 |
margin-bottom: var(--gap-section); |
| 200 |
} |
| 201 |
|
| 202 |
|
| 203 |
Used by wizard type pickers, pricing-model pickers, content-choice pickers, |
| 204 |
monetization-mode pickers, anywhere a radio-like choice is rendered as a card. |
| 205 |
.card--selectable { |
| 206 |
cursor: pointer; |
| 207 |
display: block; |
| 208 |
} |
| 209 |
.card--selectable input[type="radio"], |
| 210 |
.card--selectable input[type="checkbox"] { |
| 211 |
position: absolute; |
| 212 |
opacity: 0; |
| 213 |
pointer-events: none; |
| 214 |
} |
| 215 |
|
| 216 |
.card--selectable-inner { |
| 217 |
display: flex; |
| 218 |
flex-direction: column; |
| 219 |
align-items: center; |
| 220 |
justify-content: center; |
| 221 |
padding: var(--gap-section); |
| 222 |
border: 2px solid var(--border); |
| 223 |
border-radius: var(--radius-square); |
| 224 |
background: var(--surface-page); |
| 225 |
text-align: center; |
| 226 |
transition: border-color 0.15s, background 0.15s; |
| 227 |
min-height: 60px; |
| 228 |
} |
| 229 |
|
| 230 |
.card--selectable.is-text-heavy .card--selectable-inner { |
| 231 |
align-items: stretch; |
| 232 |
text-align: left; |
| 233 |
padding: var(--gap-section); |
| 234 |
} |
| 235 |
|
| 236 |
.card--selectable input:checked + .card--selectable-inner, |
| 237 |
.card--selectable.is-selected .card--selectable-inner { |
| 238 |
border-color: var(--action); |
| 239 |
background: var(--highlight-faint); |
| 240 |
} |
| 241 |
|
| 242 |
.card--selectable:hover .card--selectable-inner { |
| 243 |
background: var(--surface-sunken); |
| 244 |
} |
| 245 |
|
| 246 |
|
| 247 |
lands on the input and the ring has to be drawn on the inner surface. The |
| 248 |
<a> form of the card takes focus itself. |
| 249 |
.card--selectable:focus-visible, |
| 250 |
.card--selectable input:focus-visible + .card--selectable-inner { |
| 251 |
outline: 2px solid var(--focus-ring); |
| 252 |
outline-offset: 2px; |
| 253 |
} |
| 254 |
|
| 255 |
.card--selectable-label { |
| 256 |
font-weight: bold; |
| 257 |
font-size: var(--text-note); |
| 258 |
} |
| 259 |
|
| 260 |
.card--selectable-desc { |
| 261 |
font-size: var(--text-fine); |
| 262 |
color: var(--content-muted); |
| 263 |
margin-top: var(--gap-bound); |
| 264 |
} |
| 265 |
|
| 266 |
|
| 267 |
.card--selectable.is-disabled { |
| 268 |
opacity: 0.7; |
| 269 |
pointer-events: none; |
| 270 |
} |
| 271 |
|
| 272 |
.suggestion-input { |
| 273 |
position: relative; |
| 274 |
} |
| 275 |
|
| 276 |
.suggestion-dropdown { |
| 277 |
display: none; |
| 278 |
position: absolute; |
| 279 |
top: 100%; |
| 280 |
left: 0; |
| 281 |
right: 0; |
| 282 |
background: var(--surface-page); |
| 283 |
border: 1px solid var(--border); |
| 284 |
border-top: none; |
| 285 |
border-radius: 0 0 var(--radius-square) var(--radius-square); |
| 286 |
max-height: 200px; |
| 287 |
overflow-y: auto; |
| 288 |
z-index: var(--z-dropdown); |
| 289 |
box-shadow: var(--elevation-overlay); |
| 290 |
} |
| 291 |
|
| 292 |
.suggestion-dropdown.open { |
| 293 |
display: block; |
| 294 |
} |
| 295 |
|
| 296 |
.suggestion-item { |
| 297 |
padding: var(--gap-peer) var(--gap-section); |
| 298 |
cursor: pointer; |
| 299 |
font-size: var(--text-note); |
| 300 |
} |
| 301 |
|
| 302 |
.suggestion-item:hover { |
| 303 |
background: var(--surface-overlay); |
| 304 |
} |
| 305 |
|
| 306 |
.suggestion-create { |
| 307 |
font-style: italic; |
| 308 |
opacity: 0.8; |
| 309 |
border-top: 1px solid var(--border); |
| 310 |
} |
| 311 |
|
| 312 |
|
| 313 |
disclosure, its two fields and its submit are the design system's. What was |
| 314 |
here restated them, and a restated rule fails the drift check. |
| 315 |
|
| 316 |
|
| 317 |
COLLECTION PICKER (shared dropdown) |
| 318 |
=========================================== |
| 319 |
|
| 320 |
.collection-picker-anchor { position: relative; } |
| 321 |
.collection-picker { |
| 322 |
position: absolute; left: 0; right: 0; top: 100%; z-index: var(--z-picker); |
| 323 |
background: var(--surface-page); border: 1px solid var(--border); |
| 324 |
box-shadow: var(--elevation-overlay); min-width: 220px; |
| 325 |
} |
| 326 |
.collection-picker-list { max-height: 200px; overflow-y: auto; padding: var(--gap-bound) 0; } |
| 327 |
.collection-picker-item { |
| 328 |
display: flex; align-items: center; gap: var(--gap-peer); |
| 329 |
padding: var(--gap-peer) var(--gap-section); cursor: pointer; font-size: var(--text-note); |
| 330 |
} |
| 331 |
.collection-picker-item:hover { background: var(--surface-sunken); } |
| 332 |
.collection-picker-loading, |
| 333 |
.collection-picker-create { border-top: 1px solid var(--border); padding: var(--gap-peer) var(--gap-section); } |
| 334 |
.collection-picker-create form { display: flex; gap: var(--gap-peer); } |
| 335 |
.collection-picker-create input { flex: 1; padding: var(--gap-bound) var(--gap-peer); font-size: var(--text-note); min-width: 0; } |
| 336 |
.collection-picker-create button { font-size: var(--text-note); white-space: nowrap; } |
| 337 |
|
| 338 |
|
| 339 |
.row-save, .grid-card-save { |
| 340 |
background: none; border: none; cursor: pointer; |
| 341 |
font-size: var(--text-note); padding: var(--gap-bound) var(--gap-peer); opacity: 0.4; |
| 342 |
color: var(--content); transition: opacity 0.15s; |
| 343 |
} |
| 344 |
.row-save:hover, .grid-card-save:hover { opacity: 1; } |
| 345 |
.grid-card-save { |
| 346 |
position: absolute; top: 0.4rem; right: 0.4rem; z-index: var(--z-raised); |
| 347 |
background: var(--surface-page); border-radius: var(--radius-control); padding: var(--gap-bound) var(--gap-peer); |
| 348 |
box-shadow: var(--elevation-overlay); opacity: 0; |
| 349 |
} |
| 350 |
.grid-card:hover .grid-card-save { opacity: 0.7; } |
| 351 |
.grid-card-save:hover { opacity: 1; } |
| 352 |
|
| 353 |
|
| 354 |
button.saved { border-color: var(--action); color: var(--action); } |
| 355 |
|
| 356 |
|
| 357 |
SEARCH BOX |
| 358 |
=========================================== |
| 359 |
The box and its suggestion list are a described Field (N8), which draws its |
| 360 |
own control and its own list. What is left here is where the toolbar puts |
| 361 |
it: a flex child that takes the rest of the row, and the positioning context |
| 362 |
the list is absolutely placed against. |
| 363 |
|
| 364 |
.search-wrapper { position: relative; flex: 1; min-width: 0; } |
| 365 |
|
| 366 |
|
| 367 |
DOC UI EXAMPLES (embedded live UI in docs) |
| 368 |
=========================================== |
| 369 |
|
| 370 |
.doc-ui { |
| 371 |
margin: var(--gap-pane) 0; border: 1px solid var(--border); border-radius: var(--radius-control); overflow: hidden; |
| 372 |
} |
| 373 |
.doc-ui-frame { |
| 374 |
padding: var(--gap-section); background: var(--surface-overlay); pointer-events: none; user-select: none; |
| 375 |
} |
| 376 |
.doc-ui figcaption { |
| 377 |
padding: var(--gap-peer) var(--gap-section); font-size: var(--text-fine); opacity: 0.6; |
| 378 |
border-top: 1px solid var(--border); background: var(--surface-overlay); |
| 379 |
font-family: var(--font-mono); |
| 380 |
} |
| 381 |
.doc-ui-missing { |
| 382 |
padding: var(--gap-section); opacity: 0.4; font-style: italic; |
| 383 |
} |
| 384 |
|
| 385 |
|
| 386 |
it takes no tone; it is the plain badge with the accent hue and a little |
| 387 |
more weight, since "New" is the one badge meant to catch the eye. |
| 388 |
.badge-new { |
| 389 |
color: var(--action); font-weight: bold; |
| 390 |
margin-left: var(--gap-peer); vertical-align: middle; |
| 391 |
} |
| 392 |
|
| 393 |
|
| 394 |
BENEFIT LIST (bulleted feature lists, e.g. Stripe Connect prompt) |
| 395 |
=========================================== |
| 396 |
.benefit-list { |
| 397 |
list-style: none; |
| 398 |
padding: 0; |
| 399 |
margin: 0 auto var(--gap-pane); |
| 400 |
max-width: 280px; |
| 401 |
text-align: left; |
| 402 |
display: flex; |
| 403 |
flex-direction: column; |
| 404 |
gap: var(--gap-peer); |
| 405 |
} |
| 406 |
.benefit-list li { |
| 407 |
position: relative; |
| 408 |
padding-left: var(--gap-section); |
| 409 |
font-size: var(--text-note); |
| 410 |
} |
| 411 |
.benefit-list li::before { |
| 412 |
content: ""; |
| 413 |
position: absolute; |
| 414 |
left: 0.15rem; |
| 415 |
top: 0.55rem; |
| 416 |
width: 6px; |
| 417 |
height: 6px; |
| 418 |
border-radius: var(--radius-round); |
| 419 |
background: var(--success); |
| 420 |
} |
| 421 |
|
| 422 |
|
| 423 |
CHECKLIST (setup / onboarding step lists) |
| 424 |
=========================================== |
| 425 |
.checklist { |
| 426 |
margin-bottom: var(--gap-pane); |
| 427 |
padding: var(--gap-section) var(--gap-pane); |
| 428 |
background: var(--surface-overlay); |
| 429 |
border: 1px solid var(--border); |
| 430 |
} |
| 431 |
.checklist-header { |
| 432 |
display: flex; |
| 433 |
justify-content: space-between; |
| 434 |
align-items: center; |
| 435 |
margin-bottom: var(--gap-section); |
| 436 |
} |
| 437 |
.checklist-title { |
| 438 |
margin: 0; |
| 439 |
font-family: var(--font-display); |
| 440 |
font-weight: bold; |
| 441 |
} |
| 442 |
.checklist-mark { |
| 443 |
width: 1.1rem; |
| 444 |
height: 1.1rem; |
| 445 |
border-radius: var(--radius-round); |
| 446 |
border: 2px solid var(--border); |
| 447 |
flex-shrink: 0; |
| 448 |
box-sizing: border-box; |
| 449 |
} |
| 450 |
.checklist-mark--done { |
| 451 |
border-color: var(--success); |
| 452 |
background: var(--success); |
| 453 |
} |
| 454 |
.checklist-label { |
| 455 |
flex: 1; |
| 456 |
font-size: var(--text-note); |
| 457 |
} |
| 458 |
.checklist-label--done { |
| 459 |
opacity: 0.5; |
| 460 |
text-decoration: line-through; |
| 461 |
} |
| 462 |
|
| 463 |
|