max / makenotwork
25 files changed,
+92 insertions,
-157 deletions
| @@ -83,7 +83,7 @@ | |||
| 83 | 83 | | Primitive | Canonical class | Variants | States | | |
| 84 | 84 | |---|---|---|---| | |
| 85 | 85 | | Page section box | `.content-section` | (none) | — | | |
| 86 | - | | Card | `.card` | `.card-muted` (surface-muted fill), `.card--bordered`, `.card--selectable` | `:hover`, `:focus-within`, `.is-selected` | | |
| 86 | + | | Card | `.card` | `.card-muted` (surface-muted fill), `.card--bordered`, `.card--selectable` (+ `.is-text-heavy` for left-aligned content) | `:hover`, `:focus-within`, `.is-selected`, `.is-disabled` | | |
| 87 | 87 | | Button | `.btn-primary` / `.btn-secondary` / `.btn-danger` | `.btn--large`, `.btn--icon`, `.btn--link`, `.small`, `.saved` | `:hover`, `:focus-visible`, `:disabled`, `.htmx-request` | | |
| 88 | 88 | | Heading | `.brand-h1` (wordmark), `.page-title` (h1), `.subtitle-h2` (auth/wizard h2), `.subsection-title` (default h2), `.section-header` (h2 with bottom border) | — | — | | |
| 89 | 89 | | Input shape | (base `input`/`textarea`/`select`) | `.input--xs`, `.input--sm`, `.input--mono`, `.input--upper`, `.input--numeric` | `:focus`, `:disabled` | | |
| @@ -122,6 +122,8 @@ | |||
| 122 | 122 | ||
| 123 | 123 | A new class is a smell, not a goal. Three usages without an entry above means a missing primitive, not a license to keep inlining. | |
| 124 | 124 | ||
| 125 | + | **No aliases.** A shared recipe is reached by writing its canonical name in the markup, never by adding a page-specific name to the recipe's selector list. A component that also needs rules of its own keeps its own class and puts the canonical modifier beside it: `class="card--bordered tier-card"`. The alias habit is what let `.card--selectable` and `.card--bordered` sit in this table for months while zero templates used either name, so a developer following the charter wrote a class that matched nothing else in the codebase. | |
| 126 | + | ||
| 125 | 127 | Page-scoped CSS (`.foo-page .bar`) is a last resort. Most page-scoped rules in `style.css` exist for genuine page-specific layout (e.g. `.item-page .item-layout` grid, `.article-page .article-body` typography). Don't add new ones for shapes that are really cards or list rows in disguise. | |
| 126 | 128 | ||
| 127 | 129 | ### How to use the macros |
| @@ -1105,9 +1105,9 @@ | |||
| 1105 | 1105 | .card.card--bordered bordered, padded, no fill (marketing cards: feature/tier/use-case). | |
| 1106 | 1106 | .card.card--selectable radio-card pattern; pair with .is-selected. | |
| 1107 | 1107 | .card.card--grid grid-cell card (discover grid). | |
| 1108 | - | Legacy class names (.stat-card, .analytics-card, .feature-card, .tier-card, | |
| 1109 | - | .use-case-card) are aliased to these recipes below, templates migrate at | |
| 1110 | - | their own pace. */ | |
| 1108 | + | No aliases. A template names the modifier it wants and adds its own | |
| 1109 | + | component class beside it; a recipe reached only through a per-page name is | |
| 1110 | + | a recipe nobody can find from the charter. */ | |
| 1111 | 1111 | .card { | |
| 1112 | 1112 | background: var(--surface-overlay); | |
| 1113 | 1113 | padding: var(--gap-pane); | |
| @@ -1129,12 +1129,10 @@ | |||
| 1129 | 1129 | background: var(--surface-sunken); | |
| 1130 | 1130 | padding: var(--gap-pane); | |
| 1131 | 1131 | } | |
| 1132 | - | /* Bordered card (.card--bordered alias for .feature-card, .tier-card, .use-case-card, .fork-card). */ | |
| 1133 | - | .card--bordered, | |
| 1134 | - | .feature-card, | |
| 1135 | - | .tier-card, | |
| 1136 | - | .use-case-card, | |
| 1137 | - | .fork-card { | |
| 1132 | + | /* Bordered card. Templates put this modifier on the element alongside any | |
| 1133 | + | component class of their own (.tier-card, .use-case-card, .fork-card), so | |
| 1134 | + | the name the charter teaches is the name in the markup. */ | |
| 1135 | + | .card--bordered { | |
| 1138 | 1136 | background: transparent; | |
| 1139 | 1137 | padding: var(--gap-section); | |
| 1140 | 1138 | border: 1px solid var(--border); | |
| @@ -1791,7 +1789,6 @@ | |||
| 1791 | 1789 | font-weight: bold; | |
| 1792 | 1790 | } | |
| 1793 | 1791 | ||
| 1794 | - | .project-page .item-title a { color: inherit; text-decoration: none; } | |
| 1795 | 1792 | .project-page .item-title a:hover { text-decoration: underline; } | |
| 1796 | 1793 | ||
| 1797 | 1794 | .project-page .item-meta { | |
| @@ -2078,10 +2075,6 @@ | |||
| 2078 | 2075 | color: var(--content); | |
| 2079 | 2076 | } | |
| 2080 | 2077 | ||
| 2081 | - | .article-page .author-name a { | |
| 2082 | - | color: inherit; | |
| 2083 | - | text-decoration: none; | |
| 2084 | - | } | |
| 2085 | 2078 | ||
| 2086 | 2079 | .article-page .author-name a:hover { text-decoration: underline; } | |
| 2087 | 2080 | ||
| @@ -2234,10 +2227,6 @@ | |||
| 2234 | 2227 | margin-bottom: var(--gap-peer); | |
| 2235 | 2228 | } | |
| 2236 | 2229 | ||
| 2237 | - | .article-page .author-bio-name a { | |
| 2238 | - | color: inherit; | |
| 2239 | - | text-decoration: none; | |
| 2240 | - | } | |
| 2241 | 2230 | ||
| 2242 | 2231 | .article-page .author-bio-name a:hover { text-decoration: underline; } | |
| 2243 | 2232 | ||
| @@ -3536,7 +3525,6 @@ | |||
| 3536 | 3525 | margin-bottom: var(--gap-pane); | |
| 3537 | 3526 | opacity: 0.7; | |
| 3538 | 3527 | } | |
| 3539 | - | .tag-tree-page .breadcrumbs a { text-decoration: none; color: inherit; } | |
| 3540 | 3528 | .tag-tree-page .breadcrumbs a:hover { opacity: 0.6; } | |
| 3541 | 3529 | .tag-tree-page .breadcrumbs .sep { margin: 0 var(--gap-bound); opacity: 0.4; } | |
| 3542 | 3530 | ||
| @@ -3736,7 +3724,6 @@ | |||
| 3736 | 3724 | ||
| 3737 | 3725 | .project-blog-page .post-entry:first-child { padding-top: 0; } | |
| 3738 | 3726 | .project-blog-page .post-title { font-size: var(--text-head); margin-bottom: var(--gap-peer); } | |
| 3739 | - | .project-blog-page .post-title a { color: inherit; text-decoration: none; } | |
| 3740 | 3727 | .project-blog-page .post-title a:hover { text-decoration: underline; } | |
| 3741 | 3728 | ||
| 3742 | 3729 | .project-blog-page .post-date { | |
| @@ -7634,27 +7621,18 @@ | |||
| 7634 | 7621 | /* Canonical selectable-card primitive. One recipe; per-context size modifiers. | |
| 7635 | 7622 | Used by wizard type pickers, pricing-model pickers, content-choice pickers, | |
| 7636 | 7623 | monetization-mode pickers, anywhere a radio-like choice is rendered as a card. */ | |
| 7637 | - | .card--selectable, | |
| 7638 | - | .type-card, | |
| 7639 | - | .pricing-card, | |
| 7640 | - | .content-choice-card { | |
| 7624 | + | .card--selectable { | |
| 7641 | 7625 | cursor: pointer; | |
| 7642 | 7626 | display: block; | |
| 7643 | 7627 | } | |
| 7644 | 7628 | .card--selectable input[type="radio"], | |
| 7645 | - | .card--selectable input[type="checkbox"], | |
| 7646 | - | .type-card input[type="radio"], | |
| 7647 | - | .type-card input[type="checkbox"], | |
| 7648 | - | .pricing-card input[type="radio"], | |
| 7649 | - | .content-choice-card input[type="radio"] { | |
| 7629 | + | .card--selectable input[type="checkbox"] { | |
| 7650 | 7630 | position: absolute; | |
| 7651 | 7631 | opacity: 0; | |
| 7652 | 7632 | pointer-events: none; | |
| 7653 | 7633 | } | |
| 7654 | 7634 | ||
| 7655 | - | .card--selectable-inner, | |
| 7656 | - | .type-card-inner, | |
| 7657 | - | .pricing-card-inner { | |
| 7635 | + | .card--selectable-inner { | |
| 7658 | 7636 | display: flex; | |
| 7659 | 7637 | flex-direction: column; | |
| 7660 | 7638 | align-items: center; | |
| @@ -7668,7 +7646,6 @@ | |||
| 7668 | 7646 | min-height: 60px; | |
| 7669 | 7647 | } | |
| 7670 | 7648 | /* Variant: column-aligned content (text-heavy pricing cards). */ | |
| 7671 | - | .pricing-card-inner, | |
| 7672 | 7649 | .card--selectable.is-text-heavy .card--selectable-inner { | |
| 7673 | 7650 | align-items: stretch; | |
| 7674 | 7651 | text-align: left; | |
| @@ -7676,48 +7653,28 @@ | |||
| 7676 | 7653 | } | |
| 7677 | 7654 | ||
| 7678 | 7655 | .card--selectable input:checked + .card--selectable-inner, | |
| 7679 | - | .card--selectable.is-selected .card--selectable-inner, | |
| 7680 | - | .type-card input:checked + .type-card-inner, | |
| 7681 | - | .type-card.is-selected .type-card-inner, | |
| 7682 | - | .pricing-card input:checked + .pricing-card-inner, | |
| 7683 | - | .pricing-card.is-selected .pricing-card-inner, | |
| 7684 | - | .content-choice-card.is-selected { | |
| 7656 | + | .card--selectable.is-selected .card--selectable-inner { | |
| 7685 | 7657 | border-color: var(--action); | |
| 7686 | 7658 | background: color-mix(in oklch, var(--action) 8%, transparent); | |
| 7687 | 7659 | } | |
| 7688 | 7660 | ||
| 7689 | - | .card--selectable:hover .card--selectable-inner, | |
| 7690 | - | .type-card:hover .type-card-inner, | |
| 7691 | - | .pricing-card:hover .pricing-card-inner, | |
| 7692 | - | .content-choice-card:hover { | |
| 7661 | + | .card--selectable:hover .card--selectable-inner { | |
| 7693 | 7662 | background: var(--surface-sunken); | |
| 7694 | 7663 | } | |
| 7695 | 7664 | ||
| 7696 | - | .card--selectable-label, | |
| 7697 | - | .type-card-label, | |
| 7698 | - | .pricing-card-label { | |
| 7665 | + | .card--selectable-label { | |
| 7699 | 7666 | font-weight: bold; | |
| 7700 | 7667 | font-size: var(--text-note); | |
| 7701 | 7668 | } | |
| 7702 | 7669 | ||
| 7703 | - | .card--selectable-desc, | |
| 7704 | - | .type-card-desc, | |
| 7705 | - | .pricing-card-desc { | |
| 7670 | + | .card--selectable-desc { | |
| 7706 | 7671 | font-size: var(--text-fine); | |
| 7707 | 7672 | color: var(--content-muted); | |
| 7708 | 7673 | margin-top: var(--gap-bound); | |
| 7709 | 7674 | } | |
| 7710 | 7675 | ||
| 7711 | - | /* Anchor-styled selectable card (used when the card itself is an `<a>` link | |
| 7712 | - | rather than a radio-wrapping label). */ | |
| 7713 | - | .content-choice-card { | |
| 7714 | - | text-decoration: none; | |
| 7715 | - | color: inherit; | |
| 7716 | - | } | |
| 7717 | - | ||
| 7718 | 7676 | /* Disabled selectable card, visually dimmed, ignores pointer events. */ | |
| 7719 | - | .card--selectable.is-disabled, | |
| 7720 | - | .content-choice-card.is-disabled { | |
| 7677 | + | .card--selectable.is-disabled { | |
| 7721 | 7678 | opacity: 0.7; | |
| 7722 | 7679 | pointer-events: none; | |
| 7723 | 7680 | } | |
| @@ -9047,10 +9004,6 @@ | |||
| 9047 | 9004 | display: block; | |
| 9048 | 9005 | } | |
| 9049 | 9006 | ||
| 9050 | - | .item-page .tag-link { | |
| 9051 | - | text-decoration: none; | |
| 9052 | - | color: inherit; | |
| 9053 | - | } | |
| 9054 | 9007 | ||
| 9055 | 9008 | .item-page .bundle-notice-inline { | |
| 9056 | 9009 | background: var(--surface-sunken); | |
| @@ -9429,10 +9382,6 @@ | |||
| 9429 | 9382 | opacity: 0.7; | |
| 9430 | 9383 | padding: var(--gap-peer) 0; | |
| 9431 | 9384 | } | |
| 9432 | - | .project-page .item-tags .tag { | |
| 9433 | - | text-decoration: none; | |
| 9434 | - | color: inherit; | |
| 9435 | - | } | |
| 9436 | 9385 | .project-page .promo-details { | |
| 9437 | 9386 | font-size: var(--text-note); | |
| 9438 | 9387 | margin-bottom: var(--gap-peer); | |
| @@ -10157,10 +10106,6 @@ | |||
| 10157 | 10106 | font-family: var(--font-mono); | |
| 10158 | 10107 | color: var(--content-muted); | |
| 10159 | 10108 | } | |
| 10160 | - | .video-tag-link { | |
| 10161 | - | text-decoration: none; | |
| 10162 | - | color: inherit; | |
| 10163 | - | } | |
| 10164 | 10109 | ||
| 10165 | 10110 | /* =========================================== | |
| 10166 | 10111 | LIBRARY LOCKED PAGE (templates/pages/library_locked.html) | |
| @@ -10270,10 +10215,6 @@ | |||
| 10270 | 10215 | font-family: var(--font-mono); | |
| 10271 | 10216 | color: var(--content-muted); | |
| 10272 | 10217 | } | |
| 10273 | - | .audio-tag-link { | |
| 10274 | - | text-decoration: none; | |
| 10275 | - | color: inherit; | |
| 10276 | - | } | |
| 10277 | 10218 | ||
| 10278 | 10219 | /* =========================================== | |
| 10279 | 10220 | SECTIONS WIZARD STEP (templates/wizards/steps/item/sections.html) | |
| @@ -10364,13 +10305,6 @@ | |||
| 10364 | 10305 | color: var(--content-muted); | |
| 10365 | 10306 | } | |
| 10366 | 10307 | ||
| 10367 | - | /* Plain (text-decoration-free, inherit-colored) tag link on text_reader. | |
| 10368 | - | Distinguishes from the default linked .article-tag in library_text. */ | |
| 10369 | - | .article-page .article-tag--plain { | |
| 10370 | - | text-decoration: none; | |
| 10371 | - | color: inherit; | |
| 10372 | - | } | |
| 10373 | - | ||
| 10374 | 10308 | /* Library back-link breadcrumb shared by the media library pages. */ | |
| 10375 | 10309 | .media-container .library-back { | |
| 10376 | 10310 | font-size: var(--text-note); | |
| @@ -10614,7 +10548,6 @@ | |||
| 10614 | 10548 | .key-code-small:hover { background: var(--border); } | |
| 10615 | 10549 | ||
| 10616 | 10550 | /* Library row title link reads as plain text until hovered. */ | |
| 10617 | - | .library-title-link { color: inherit; text-decoration: none; } | |
| 10618 | 10551 | .library-title-link:hover { text-decoration: underline; } | |
| 10619 | 10552 | /* =========================================== | |
| 10620 | 10553 | ADMIN ENTRIES (replaces inline styles in partials/admin_user_entries.html, |
| @@ -141,8 +141,8 @@ | |||
| 141 | 141 | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); | |
| 142 | 142 | } | |
| 143 | 143 | ||
| 144 | - | /* (.type-card primitive lives in style.css under the .card--selectable | |
| 145 | - | canonical recipe; this file only contains wizard-specific layouts.) */ | |
| 144 | + | /* (The cards themselves are .card--selectable, defined in style.css; this | |
| 145 | + | file only contains wizard-specific layouts.) */ | |
| 146 | 146 | ||
| 147 | 147 | /* Suggestion Input (category, tags) */ | |
| 148 | 148 | ||
| @@ -217,8 +217,8 @@ | |||
| 217 | 217 | margin-bottom: var(--gap-pane); | |
| 218 | 218 | } | |
| 219 | 219 | ||
| 220 | - | /* (`.pricing-card`, `.content-choice-card`, and the `.is-disabled` modifier | |
| 221 | - | all live in style.css under the canonical `.card--selectable` recipe.) */ | |
| 220 | + | /* (The cards are `.card--selectable`, the text-heavy pricing variant adds | |
| 221 | + | `.is-text-heavy`, and `.is-disabled` is its modifier. All in style.css.) */ | |
| 222 | 222 | .pricing-fields { | |
| 223 | 223 | margin-top: var(--gap-section); | |
| 224 | 224 | } |
| @@ -120,7 +120,7 @@ | |||
| 120 | 120 | {% if !item.tags.is_empty() %} | |
| 121 | 121 | <div class="media-tags"> | |
| 122 | 122 | {% for tag in item.tags %} | |
| 123 | - | <a href="/discover?tag={{ tag.slug }}" class="tag audio-tag-link">{{ tag.name }}</a> | |
| 123 | + | <a href="/discover?tag={{ tag.slug }}" class="tag unstyled-link">{{ tag.name }}</a> | |
| 124 | 124 | {% endfor %} | |
| 125 | 125 | </div> | |
| 126 | 126 | {% endif %} |
| @@ -54,7 +54,7 @@ | |||
| 54 | 54 | <header class="author-header"> | |
| 55 | 55 | <div class="author-avatar">{{ creator_avatar_initials }}</div> | |
| 56 | 56 | <div class="author-info"> | |
| 57 | - | <div class="author-name"><a href="/u/{{ creator_username }}">{% if let Some(name) = creator_display_name %}{{ name }}{% else %}{{ creator_username }}{% endif %}</a></div> | |
| 57 | + | <div class="author-name"><a href="/u/{{ creator_username }}" class="unstyled-link">{% if let Some(name) = creator_display_name %}{{ name }}{% else %}{{ creator_username }}{% endif %}</a></div> | |
| 58 | 58 | <div class="article-meta">{{ published_at }}</div> | |
| 59 | 59 | </div> | |
| 60 | 60 | </header> |
| @@ -77,7 +77,7 @@ | |||
| 77 | 77 | {% endif %} | |
| 78 | 78 | ||
| 79 | 79 | <div class="landing-fork"> | |
| 80 | - | <div class="fork-card{% if founder_window_open %} fork-card--founder{% endif %}"> | |
| 80 | + | <div class="card--bordered fork-card{% if founder_window_open %} fork-card--founder{% endif %}"> | |
| 81 | 81 | <h2 class="fork-heading">For creators</h2> | |
| 82 | 82 | ||
| 83 | 83 | {% if founder_window_open %} | |
| @@ -123,7 +123,7 @@ | |||
| 123 | 123 | </div> | |
| 124 | 124 | </div> | |
| 125 | 125 | ||
| 126 | - | <div class="fork-card"> | |
| 126 | + | <div class="card--bordered fork-card"> | |
| 127 | 127 | <h2 class="fork-heading">Fan+</h2> | |
| 128 | 128 | <p class="fork-lede">Support the platform directly and get something back every month.</p> | |
| 129 | 129 | <ul class="fork-list"> |
| @@ -121,7 +121,7 @@ | |||
| 121 | 121 | ||
| 122 | 122 | <div class="item-tags"> | |
| 123 | 123 | {% for tag in item.tags %} | |
| 124 | - | <a href="/discover?tag={{ tag.slug }}" class="tag tag-link{% if tag.is_primary %} tag-primary{% endif %}">{{ tag.name }}</a> | |
| 124 | + | <a href="/discover?tag={{ tag.slug }}" class="tag unstyled-link{% if tag.is_primary %} tag-primary{% endif %}">{{ tag.name }}</a> | |
| 125 | 125 | {% endfor %} | |
| 126 | 126 | </div> | |
| 127 | 127 |
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | <header class="author-header"> | |
| 20 | 20 | <div class="author-avatar">{{ creator_avatar_initials }}</div> | |
| 21 | 21 | <div class="author-info"> | |
| 22 | - | <div class="author-name"><a href="/u/{{ creator_username }}">{% if let Some(name) = creator_display_name %}{{ name }}{% else %}{{ creator_username }}{% endif %}</a></div> | |
| 22 | + | <div class="author-name"><a href="/u/{{ creator_username }}" class="unstyled-link">{% if let Some(name) = creator_display_name %}{{ name }}{% else %}{{ creator_username }}{% endif %}</a></div> | |
| 23 | 23 | <div class="article-meta">{{ item.release_date }}{% if let Some(rt) = reading_time %} | {{ rt }}{% endif %}</div> | |
| 24 | 24 | </div> | |
| 25 | 25 | </header> |
| @@ -34,25 +34,25 @@ | |||
| 34 | 34 | <h2 class="section-label">Your content tier</h2> | |
| 35 | 35 | <p class="tier-intro">Every tier is the complete platform: profile, project pages, forum, discovery, memberships, analytics, full data export. The tier picks the file-size envelope, not the feature set.</p> | |
| 36 | 36 | <div class="tier-selector" role="radiogroup" aria-label="Content tier"> | |
| 37 | - | <label class="tier-card tier-option"> | |
| 37 | + | <label class="card--bordered tier-card tier-option"> | |
| 38 | 38 | <input type="radio" name="tier" value="{{ tier_prices.basic_std }}" checked> | |
| 39 | 39 | <div class="tier-name">Basic</div> | |
| 40 | 40 | <div class="tier-price">${{ tier_prices.basic_std }}/mo</div> | |
| 41 | 41 | <div class="tier-desc">{{ tier_prices.basic_per_file }}/file, {{ tier_prices.basic_total }} total. Fits text, blogs, newsletters.</div> | |
| 42 | 42 | </label> | |
| 43 | - | <label class="tier-card tier-option"> | |
| 43 | + | <label class="card--bordered tier-card tier-option"> | |
| 44 | 44 | <input type="radio" name="tier" value="{{ tier_prices.small_files_std }}"> | |
| 45 | 45 | <div class="tier-name">Small Files</div> | |
| 46 | 46 | <div class="tier-price">${{ tier_prices.small_files_std }}/mo</div> | |
| 47 | 47 | <div class="tier-desc">{{ tier_prices.small_files_per_file }}/file, {{ tier_prices.small_files_total }} total. Fits audio, plugins, binaries.</div> | |
| 48 | 48 | </label> | |
| 49 | - | <label class="tier-card tier-option"> | |
| 49 | + | <label class="card--bordered tier-card tier-option"> | |
| 50 | 50 | <input type="radio" name="tier" value="{{ tier_prices.big_files_std }}"> | |
| 51 | 51 | <div class="tier-name">Big Files</div> | |
| 52 | 52 | <div class="tier-price">${{ tier_prices.big_files_std }}/mo</div> | |
| 53 | 53 | <div class="tier-desc">{{ tier_prices.big_files_per_file }}/file, {{ tier_prices.big_files_total }} total. Fits video, games, large software.</div> | |
| 54 | 54 | </label> | |
| 55 | - | <label class="tier-card tier-option"> | |
| 55 | + | <label class="card--bordered tier-card tier-option"> | |
| 56 | 56 | <input type="radio" name="tier" value="{{ tier_prices.everything_std }}"> | |
| 57 | 57 | <div class="tier-name">Everything</div> | |
| 58 | 58 | <div class="tier-price">${{ tier_prices.everything_std }}/mo</div> |
| @@ -129,11 +129,11 @@ | |||
| 129 | 129 | <div class="item-card"> | |
| 130 | 130 | <a href="{% if item.can_access %}/i/{{ item.id }}{% else %}/purchase/{{ item.id }}{% endif %}" class="item-thumbnail">{{ item.thumbnail }}</a> | |
| 131 | 131 | <div class="item-content"> | |
| 132 | - | <h3 class="item-title"><a href="{% if item.can_access %}/i/{{ item.id }}{% else %}/purchase/{{ item.id }}{% endif %}">{{ item.title }}</a></h3> | |
| 132 | + | <h3 class="item-title"><a class="unstyled-link" href="{% if item.can_access %}/i/{{ item.id }}{% else %}/purchase/{{ item.id }}{% endif %}">{{ item.title }}</a></h3> | |
| 133 | 133 | <div class="item-meta">{{ item.item_type }}{% if item.bundle_item_count > 0 %} ({{ item.bundle_item_count }} items){% endif %} · {{ item.release_date }}</div> | |
| 134 | 134 | <div class="item-tags"> | |
| 135 | 135 | {% for tag in item.tags %} | |
| 136 | - | <a href="/discover?tag={{ tag.slug }}" class="tag">{{ tag.name }}</a> | |
| 136 | + | <a href="/discover?tag={{ tag.slug }}" class="tag unstyled-link">{{ tag.name }}</a> | |
| 137 | 137 | {% endfor %} | |
| 138 | 138 | </div> | |
| 139 | 139 | <p class="item-description">{{ item.description }}</p> | |
| @@ -177,7 +177,7 @@ | |||
| 177 | 177 | <h2 class="section-header">Membership</h2> | |
| 178 | 178 | <div class="tiers-grid"> | |
| 179 | 179 | {% for tier in subscription_tiers %} | |
| 180 | - | <div class="tier-card"> | |
| 180 | + | <div class="card--bordered tier-card"> | |
| 181 | 181 | <div class="tier-name">{{ tier.name }}</div> | |
| 182 | 182 | <div class="tier-price">{{ tier.price }}</div> | |
| 183 | 183 | {% if !tier.description.is_empty() %} |
| @@ -29,7 +29,7 @@ | |||
| 29 | 29 | {% else %} | |
| 30 | 30 | {% for post in posts %} | |
| 31 | 31 | <div class="post-entry"> | |
| 32 | - | <h2 class="post-title"><a href="/p/{{ project_slug }}/blog/{{ post.slug }}">{{ post.title }}</a></h2> | |
| 32 | + | <h2 class="post-title"><a class="unstyled-link" href="/p/{{ project_slug }}/blog/{{ post.slug }}">{{ post.title }}</a></h2> | |
| 33 | 33 | <div class="post-date">{{ post.published_at }}</div> | |
| 34 | 34 | </div> | |
| 35 | 35 | {% endfor %} |
| @@ -66,7 +66,7 @@ | |||
| 66 | 66 | {% if !subscription_tiers.is_empty() %} | |
| 67 | 67 | <div class="paywall-tiers"> | |
| 68 | 68 | {% for tier in subscription_tiers %} | |
| 69 | - | <div class="tier-card"> | |
| 69 | + | <div class="card--bordered tier-card"> | |
| 70 | 70 | <h3>{{ tier.name }}</h3> | |
| 71 | 71 | <div class="tier-price">{{ tier.price }}/mo</div> | |
| 72 | 72 | {% if !tier.description.is_empty() %} |
| @@ -13,10 +13,10 @@ | |||
| 13 | 13 | <h1 class="page-title">Browse Tags</h1> | |
| 14 | 14 | ||
| 15 | 15 | <nav class="breadcrumbs" aria-label="Tag breadcrumbs"> | |
| 16 | - | <a href="/discover/tags">All Tags</a> | |
| 16 | + | <a href="/discover/tags" class="unstyled-link">All Tags</a> | |
| 17 | 17 | {% for bc in breadcrumbs %} | |
| 18 | 18 | <span class="sep">/</span> | |
| 19 | - | <a href="/discover/tags?parent={{ bc.slug }}">{{ bc.name }}</a> | |
| 19 | + | <a href="/discover/tags?parent={{ bc.slug }}" class="unstyled-link">{{ bc.name }}</a> | |
| 20 | 20 | {% endfor %} | |
| 21 | 21 | {% if let Some(ct) = current_tag %} | |
| 22 | 22 | <span class="sep">/</span> |