Design token updates.
Some checks failed
Test / vitest (push) Successful in 10m47s
Test / playwright (push) Failing after 9m11s
Test / visual (push) Failing after 9m11s
Test / Notify on failure (push) Successful in 2s

This commit is contained in:
Jennie Robinson Faber 2026-04-11 23:24:38 +01:00
parent de3bcc479a
commit c6b970a621
13 changed files with 198 additions and 211 deletions

View file

@ -32,6 +32,8 @@
--parch-hover: #3a3025;
--parch-text: #ede4d0;
--parch-text-dim: #b8ae98;
--parch-accent: #c4a448;
--parch-border: #b8a880;
--c-community: #7a4838;
--c-founder: #8a4420;
--c-practitioner: #2a4650;
@ -58,10 +60,9 @@
--text-bright: #d0c8b0;
--text-dim: #958774;
--text-faint: #8b7b62;
--parch: #ede4d0;
--parch-hover: #d4c8a8;
--parch-text: #2a2015;
--parch-text-dim: #5a5040;
/* Parch family intentionally stays pinned to light-mode values
inverted blocks are a consistent zine/terminal inset in both themes.
See: --parch-accent and --parch-border for on-parch accents/borders. */
--c-community: #a06850;
--c-founder: #c06030;
--c-practitioner: #4a7080;

View file

@ -1,92 +1,61 @@
<template>
<ClientOnly>
<div v-if="!loading" class="onboarding-widget dashed-box no-hover">
<div v-if="!loading" class="onboarding-widget">
<!-- Welcome mode: onboarding in progress -->
<template v-if="!isComplete">
<div class="ow-header">
<h3 class="ow-title">Welcome to Ghost Guild</h3>
<p class="ow-intro">Get oriented here are a few things to explore as a new member.</p>
</div>
<div class="ow-suggestion">
<span class="ow-suggestion-text">{{ currentSuggestion.text }}</span>
<NuxtLink
v-if="currentSuggestion.action && !currentSuggestion.isExternal"
:to="currentSuggestion.action"
class="btn btn-primary ow-action"
>
{{ currentSuggestion.actionText }}
</NuxtLink>
<a
v-else-if="currentSuggestion.isExternal"
:href="currentSuggestion.action"
target="_blank"
rel="noopener"
class="btn btn-primary ow-action"
@click="trackGoal('wikiClicked')"
>
{{ currentSuggestion.actionText }}
</a>
</div>
<div class="ow-prompt">&gt; welcome</div>
<div class="ow-message">You are in the <strong>Ghost Guild</strong>. A few passages remain unexplored.</div>
<div class="ow-hint">Next: {{ currentSuggestion.text }}</div>
<NuxtLink
v-if="currentSuggestion.action && !currentSuggestion.isExternal"
:to="currentSuggestion.action"
class="ow-action"
>
{{ currentSuggestion.actionText }} &rarr;
</NuxtLink>
<a
v-else-if="currentSuggestion.isExternal"
:href="currentSuggestion.action"
target="_blank"
rel="noopener"
class="ow-action"
@click="trackGoal('wikiClicked')"
>
{{ currentSuggestion.actionText }} &rarr;
</a>
<div class="ow-progress">
<span class="ow-progress-label">{{ completedCount }} of 4</span>
<span class="ow-dots">
<span
v-for="i in 4"
:key="i"
class="ow-dot"
:class="{ 'ow-dot--done': i <= completedCount }"
/>
</span>
<span class="ow-bar"><span class="ow-bar-fill">{{ barFill }}</span><span class="ow-bar-empty">{{ barEmpty }}</span></span>
{{ completedCount }} of 4 explored
</div>
</template>
<!-- Suggestion mode: onboarding complete -->
<template v-else>
<!-- Empty state -->
<div v-if="currentSuggestion.key === 'empty'" class="ow-empty">
{{ currentSuggestion.text }}
</div>
<div v-if="currentSuggestion.key === 'empty'" class="ow-prompt">&gt; look</div>
<div v-if="currentSuggestion.key === 'empty'" class="ow-message ow-message--dim">{{ currentSuggestion.text }}</div>
<!-- Event recommendation -->
<div v-else-if="currentSuggestion.key === 'event'" class="ow-rec">
<div class="section-label">Suggested</div>
<span class="ow-rec-text">{{ currentSuggestion.text }}</span>
<NuxtLink
:to="currentSuggestion.action"
class="ow-rec-link"
>
{{ currentSuggestion.actionText }} &rarr;
</NuxtLink>
</div>
<!-- Ecology recommendation -->
<div v-else-if="currentSuggestion.key === 'ecology'" class="ow-rec">
<div class="section-label">Suggested</div>
<span class="ow-rec-text">{{ currentSuggestion.text }}</span>
<NuxtLink
:to="currentSuggestion.action"
class="ow-rec-link"
>
{{ currentSuggestion.actionText }} &rarr;
</NuxtLink>
</div>
<!-- Wiki recommendation -->
<div v-else-if="currentSuggestion.key === 'wiki'" class="ow-rec">
<div class="section-label">Suggested</div>
<span class="ow-rec-text">{{ currentSuggestion.text }}</span>
<!-- Recommendation (event, ecology, or wiki) -->
<template v-if="currentSuggestion.key !== 'empty'">
<div class="ow-prompt">&gt; look</div>
<div class="ow-message">{{ currentSuggestion.text }}</div>
<a
v-if="currentSuggestion.action"
v-if="currentSuggestion.isExternal && currentSuggestion.action"
:href="currentSuggestion.action"
target="_blank"
rel="noopener"
class="ow-rec-link"
class="ow-action"
>
{{ currentSuggestion.actionText }} &rarr;
</a>
</div>
<NuxtLink
v-else-if="currentSuggestion.action"
:to="currentSuggestion.action"
class="ow-action"
>
{{ currentSuggestion.actionText }} &rarr;
</NuxtLink>
</template>
</template>
</div>
</ClientOnly>
@ -100,115 +69,79 @@ const completedCount = computed(() => {
return [g.hasProfileTags, g.hasVisitedEvent, g.hasEngagedEcology, g.hasClickedWiki]
.filter(Boolean).length
})
const barFill = computed(() => '[' + '#'.repeat(completedCount.value * 2))
const barEmpty = computed(() => '-'.repeat((4 - completedCount.value) * 2) + ']')
</script>
<style scoped>
.onboarding-widget {
padding: 16px 20px;
}
/* Welcome mode */
.ow-header {
margin-bottom: 12px;
}
.ow-title {
font-family: var(--font-display);
font-size: 16px;
font-weight: 600;
color: var(--text-bright);
margin: 0 0 4px;
}
.ow-intro {
border-bottom: 1px dashed var(--parch-border);
background: var(--parch);
color: var(--parch-text);
font-size: 12px;
color: var(--text-dim);
margin: 0;
line-height: 1.5;
line-height: 1.7;
}
.ow-suggestion {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 0;
border-top: 1px dashed var(--border);
flex-wrap: wrap;
.ow-prompt {
color: var(--parch-accent);
margin-bottom: 6px;
}
.ow-suggestion-text {
font-size: 12px;
color: var(--text);
line-height: 1.5;
}
.ow-action {
flex-shrink: 0;
font-size: 11px;
padding: 5px 14px;
}
.ow-progress {
display: flex;
align-items: center;
gap: 8px;
padding-top: 10px;
border-top: 1px dashed var(--border);
}
.ow-progress-label {
font-size: 10px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-faint);
}
.ow-dots {
display: flex;
gap: 4px;
}
.ow-dot {
width: 6px;
height: 6px;
border: 1px dashed var(--border);
display: inline-block;
}
.ow-dot--done {
background: var(--candle);
border-color: var(--candle);
border-style: solid;
}
/* Suggestion mode (graduated) */
.ow-rec {
display: flex;
flex-direction: column;
gap: 4px;
}
.ow-rec .section-label {
.ow-message {
color: var(--parch-text);
margin-bottom: 2px;
}
.ow-rec-text {
font-size: 12px;
color: var(--text);
line-height: 1.5;
.ow-message--dim {
color: var(--parch-text-dim);
}
.ow-rec-link {
.ow-hint {
color: var(--parch-text-dim);
font-size: 11px;
color: var(--candle);
margin-top: 2px;
display: inline-block;
}
.ow-empty {
font-size: 12px;
color: var(--text-faint);
line-height: 1.5;
.ow-action {
display: inline-block;
margin-top: 8px;
padding: 4px 12px;
border: 1px dashed rgba(237, 228, 208, 0.25);
color: var(--parch-accent);
font-size: 11px;
text-decoration: none;
letter-spacing: 0.04em;
}
.ow-action:hover {
border-color: var(--parch-accent);
border-style: solid;
text-decoration: none;
}
.ow-progress {
margin-top: 10px;
padding-top: 8px;
border-top: 1px dashed rgba(237, 228, 208, 0.12);
font-size: 11px;
color: var(--parch-text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.ow-bar {
display: inline-flex;
gap: 0;
letter-spacing: 0;
}
.ow-bar-fill {
color: var(--parch-accent);
}
.ow-bar-empty {
color: rgba(237, 228, 208, 0.2);
}
</style>

View file

@ -10,7 +10,7 @@
color: var(--parch-text);
padding: 32px;
margin: 0;
border-bottom: 1px dashed var(--border);
border-bottom: 1px dashed var(--parch-border);
}
.parchment-inset :deep(h2) {
@ -30,6 +30,6 @@
}
.parchment-inset :deep(a) {
color: var(--candle-faint);
color: var(--parch-accent);
}
</style>

View file

@ -87,13 +87,6 @@ export function useOnboarding(options = {}) {
return buildRecommendation(selected, items[0])
}
// Fallback to first non-empty category (shouldn't happen since we filtered)
for (const cat of cats) {
if (recommendations.value[cat]?.length > 0) {
return buildRecommendation(cat, recommendations.value[cat][0])
}
}
return { key: 'empty', text: 'No suggestions right now' }
})

View file

@ -240,7 +240,7 @@ useHead({
<style scoped>
.loading-state {
padding: 60px 24px;
padding: 48px 24px;
text-align: center;
color: var(--text-faint);
font-size: 12px;
@ -256,7 +256,7 @@ useHead({
}
.filter-select {
font-family: "Commit Mono", monospace;
font-family: inherit;
font-size: 11px;
padding: 5px 10px;
border: 1px dashed var(--border);
@ -266,13 +266,14 @@ useHead({
outline: none;
-webkit-appearance: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%238a7e6a' stroke-width='1.2'/%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%23b8a880' stroke-width='1.2'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 8px center;
padding-right: 26px;
}
.filter-select:focus {
border-color: var(--candle-faint);
border-style: solid;
}
.connections-section {
@ -329,7 +330,6 @@ useHead({
.cc-name {
font-size: 13px;
font-weight: 600;
color: var(--text-bright);
}
.cc-name a {
@ -380,7 +380,6 @@ useHead({
.match-tag {
color: var(--text);
font-weight: 600;
min-width: 0;
}
@ -414,11 +413,11 @@ useHead({
.cc-slack {
font-size: 11px;
color: var(--candle-dim);
font-family: "Commit Mono", monospace;
font-family: inherit;
}
.text-action {
font-family: "Commit Mono", monospace;
font-family: inherit;
font-size: 11px;
color: var(--text-faint);
background: none;
@ -440,8 +439,8 @@ useHead({
text-align: center;
}
.empty-title {
font-family: "Brygada 1918", serif;
font-size: 18px;
font-family: var(--font-display);
font-size: 16px;
color: var(--text-dim);
margin-bottom: 6px;
}
@ -463,13 +462,13 @@ useHead({
.filter-bar {
flex-direction: column;
align-items: stretch;
padding: 14px 20px;
padding: 12px 20px;
}
.connections-section {
padding: 16px 20px;
}
.connection-card {
padding: 14px 16px;
padding: 12px 16px;
}
}
</style>

View file

@ -75,7 +75,7 @@
:to="`/series/${series._id}`"
class="series-box"
>
<h3>{{ series.title }}</h3>
<h2>{{ series.title }}</h2>
<p class="series-desc">{{ series.description }}</p>
<div class="series-meta">
<span
@ -108,7 +108,7 @@
<div class="full-section">
<div class="section-label">Have an idea?</div>
<DashedBox>
<h3>Propose an Event</h3>
<h2>Propose an Event</h2>
<p>
Members can propose events for any circle. Workshops, social hangs,
talks, or anything else that serves the community.
@ -187,11 +187,11 @@ const isAlmostFull = (event) => {
<style scoped>
.hero {
padding: 32px 32px 24px;
padding: 32px 28px 24px;
border-bottom: 1px dashed var(--border);
}
.hero h1 {
font-family: "Brygada 1918", serif;
font-family: var(--font-display);
font-size: 28px;
font-weight: 600;
color: var(--text-bright);
@ -207,7 +207,7 @@ const isAlmostFull = (event) => {
/* ---- EVENT LIST ---- */
.event-list-full {
padding: 0 32px;
padding: 0 28px;
border-bottom: 1px dashed var(--border);
}
@ -272,7 +272,7 @@ const isAlmostFull = (event) => {
}
.cancelled-tag {
font-size: 9px;
font-size: 10px;
letter-spacing: 0.07em;
text-transform: uppercase;
color: var(--ember);
@ -326,7 +326,7 @@ const isAlmostFull = (event) => {
gap: 4px;
}
.members-badge {
font-size: 9px;
font-size: 10px;
letter-spacing: 0.07em;
text-transform: uppercase;
color: var(--text-faint);
@ -338,7 +338,7 @@ const isAlmostFull = (event) => {
/* ---- FULL SECTION ---- */
.full-section {
padding: 32px;
padding: 32px 28px;
border-bottom: 1px dashed var(--border);
}
@ -350,7 +350,7 @@ const isAlmostFull = (event) => {
border: 1px dashed var(--border);
}
.series-box {
padding: 20px;
padding: 20px 24px;
border-right: 1px dashed var(--border);
text-decoration: none;
transition: background 0.15s;
@ -361,8 +361,8 @@ const isAlmostFull = (event) => {
.series-box:hover {
background: var(--surface-hover);
}
.series-box h3 {
font-family: "Brygada 1918", serif;
.series-box h2 {
font-family: var(--font-display);
font-size: 16px;
font-weight: 500;
color: var(--text-bright);
@ -383,8 +383,8 @@ const isAlmostFull = (event) => {
}
/* ---- PROPOSE ---- */
.full-section h3 {
font-family: "Brygada 1918", serif;
.full-section h2 {
font-family: var(--font-display);
font-size: 16px;
font-weight: 500;
color: var(--text-bright);
@ -431,6 +431,12 @@ const isAlmostFull = (event) => {
}
@media (max-width: 768px) {
.hero,
.event-list-full,
.full-section {
padding-left: 20px;
padding-right: 20px;
}
.event-row {
grid-template-columns: 70px 1fr;
gap: 8px;

View file

@ -860,7 +860,7 @@ onUnmounted(() => {
.form-submit {
display: inline-block;
background: var(--parch);
color: var(--candle-faint);
color: var(--parch-accent);
font-family: 'Commit Mono', monospace;
font-size: 13px;
font-weight: 600;
@ -875,7 +875,7 @@ onUnmounted(() => {
.form-submit:hover {
background: var(--parch-hover);
border-color: var(--parch-hover);
color: var(--candle-dim);
color: var(--parch-text);
text-decoration: none;
}
.form-submit:disabled {

View file

@ -89,6 +89,7 @@
<div class="ci-header">
<strong>How to Subscribe to Your Calendar</strong>
<button
type="button"
@click="showCalendarInstructions = false"
class="ci-close"
>
@ -435,7 +436,7 @@ useHead({
}
.unauth-state h2 {
font-family: "Brygada 1918", serif;
font-family: var(--font-display);
font-size: 20px;
font-weight: 500;
color: var(--text-bright);
@ -519,7 +520,7 @@ useHead({
/* ---- CALENDAR BUTTON ---- */
.calendar-btn {
font-family: "Commit Mono", monospace;
font-family: inherit;
font-size: 11px;
color: var(--candle-dim);
background: none;
@ -603,7 +604,7 @@ useHead({
/* ---- QUICK ACTIONS ---- */
.quick-action {
border: 1px dashed var(--border);
padding: 14px 20px;
padding: 12px 20px;
margin-bottom: 8px;
transition: border-color 0.2s;
display: flex;
@ -697,7 +698,7 @@ useHead({
}
.content-block {
padding: 20px;
padding: 20px 24px;
}
.event-item {

View file

@ -503,7 +503,7 @@ useHead({
.row-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
gap: 12px;
}
/* ---- PRIVACY TOGGLE SPACING ---- */
@ -615,7 +615,7 @@ useHead({
/* ---- CONNECTIONS PANEL ---- */
.connections-panel {
border: 1px dashed var(--border);
padding: 12px 14px;
padding: 12px 16px;
margin-top: 4px;
margin-bottom: 12px;
background: var(--surface);
@ -630,7 +630,7 @@ useHead({
/* ---- SAVE BAR ---- */
.save-bar {
flex-shrink: 0;
padding: 24px 28px 24px;
padding: 24px 28px;
margin-top: 0;
border-top: 1px dashed var(--border);
display: flex;
@ -644,7 +644,7 @@ useHead({
}
.save-msg-ok {
color: var(--green, var(--candle));
color: var(--green);
}
.save-msg-err {

View file

@ -468,6 +468,7 @@ useHead({
/* Bio: parch (inverted) block */
.profile-section--parch {
background: var(--parch);
border-bottom-color: var(--parch-border);
}
.profile-section--parch .section-label {
color: var(--parch-text-dim);
@ -476,7 +477,7 @@ useHead({
color: var(--parch-text);
}
.profile-section--parch .profile-bio :deep(a) {
color: var(--candle-faint);
color: var(--parch-accent);
text-decoration: underline;
text-underline-offset: 2px;
}