Reduce Dream QA hero copy
#41
by ADJCJH - opened
- dream_customs/ui/app.py +3 -1
- dream_customs/ui/copy.py +10 -10
- dream_customs/ui/styles.py +33 -13
- tests/test_ui_actions.py +5 -3
dream_customs/ui/app.py
CHANGED
|
@@ -686,6 +686,8 @@ def _hero_html(language: str = DEFAULT_LANGUAGE, status: str = "record") -> str:
|
|
| 686 |
if index < active_step:
|
| 687 |
line_classes.append("is-complete")
|
| 688 |
step_html.append(f'<i class="{" ".join(line_classes)}" aria-hidden="true"></i>')
|
|
|
|
|
|
|
| 689 |
return f"""
|
| 690 |
<header class="dc-hero">
|
| 691 |
<div class="dc-hero-top">
|
|
@@ -699,7 +701,7 @@ def _hero_html(language: str = DEFAULT_LANGUAGE, status: str = "record") -> str:
|
|
| 699 |
</div>
|
| 700 |
<div class="dc-sun-mark" aria-hidden="true"></div>
|
| 701 |
</div>
|
| 702 |
-
|
| 703 |
<div class="dc-hero-ribbon" aria-label="{escape(copy['hero_badge'])}">
|
| 704 |
<span>{escape(copy['hero_badge'])}</span>
|
| 705 |
<small>{escape(copy['hero_mobile_note'])}</small>
|
|
|
|
| 686 |
if index < active_step:
|
| 687 |
line_classes.append("is-complete")
|
| 688 |
step_html.append(f'<i class="{" ".join(line_classes)}" aria-hidden="true"></i>')
|
| 689 |
+
hero_body = copy.get("hero_body", "").strip()
|
| 690 |
+
hero_body_html = f"<p class=\"dc-hero-body\">{escape(hero_body)}</p>" if hero_body else ""
|
| 691 |
return f"""
|
| 692 |
<header class="dc-hero">
|
| 693 |
<div class="dc-hero-top">
|
|
|
|
| 701 |
</div>
|
| 702 |
<div class="dc-sun-mark" aria-hidden="true"></div>
|
| 703 |
</div>
|
| 704 |
+
{hero_body_html}
|
| 705 |
<div class="dc-hero-ribbon" aria-label="{escape(copy['hero_badge'])}">
|
| 706 |
<span>{escape(copy['hero_badge'])}</span>
|
| 707 |
<small>{escape(copy['hero_mobile_note'])}</small>
|
dream_customs/ui/copy.py
CHANGED
|
@@ -9,11 +9,11 @@ APP_COPY = {
|
|
| 9 |
"en": {
|
| 10 |
"title": "Dream QA",
|
| 11 |
"hero_kicker": "Dream QA / The Morning Question Desk",
|
| 12 |
-
"hero_title": "What did the dream
|
| 13 |
-
"subtitle": "
|
| 14 |
-
"hero_body": "
|
| 15 |
-
"hero_badge": "Text
|
| 16 |
-
"hero_mobile_note": "
|
| 17 |
"brand_subtitle": "Dream Customs",
|
| 18 |
"steps": ["Record", "One Question", "Today Tip"],
|
| 19 |
"notice_record": "Write one dream fragment, then use a demo chip if you want the 90-second judge path.",
|
|
@@ -80,11 +80,11 @@ APP_COPY = {
|
|
| 80 |
"zh": {
|
| 81 |
"title": "梦境问答台",
|
| 82 |
"hero_kicker": "梦境问答台 / 清晨问讯室",
|
| 83 |
-
"hero_title": "这个梦
|
| 84 |
-
"subtitle": "
|
| 85 |
-
"hero_body": "
|
| 86 |
-
"hero_badge": "文字
|
| 87 |
-
"hero_mobile_note": "适合半醒时
|
| 88 |
"brand_subtitle": "Dream Customs",
|
| 89 |
"steps": ["记录", "一个追问", "清晨小票"],
|
| 90 |
"notice_record": "写一个梦境片段;想走 90 秒演示路径,也可以直接点示例 chip。",
|
|
|
|
| 9 |
"en": {
|
| 10 |
"title": "Dream QA",
|
| 11 |
"hero_kicker": "Dream QA / The Morning Question Desk",
|
| 12 |
+
"hero_title": "What did the dream ask?",
|
| 13 |
+
"subtitle": "One fragment. One gentle question. One Morning Ticket.",
|
| 14 |
+
"hero_body": "",
|
| 15 |
+
"hero_badge": "Text · image · voice",
|
| 16 |
+
"hero_mobile_note": "Half-awake friendly",
|
| 17 |
"brand_subtitle": "Dream Customs",
|
| 18 |
"steps": ["Record", "One Question", "Today Tip"],
|
| 19 |
"notice_record": "Write one dream fragment, then use a demo chip if you want the 90-second judge path.",
|
|
|
|
| 80 |
"zh": {
|
| 81 |
"title": "梦境问答台",
|
| 82 |
"hero_kicker": "梦境问答台 / 清晨问讯室",
|
| 83 |
+
"hero_title": "这个梦在问什么?",
|
| 84 |
+
"subtitle": "一个片段,一个追问,一张清晨小票。",
|
| 85 |
+
"hero_body": "",
|
| 86 |
+
"hero_badge": "文字 · 图片 · 语音",
|
| 87 |
+
"hero_mobile_note": "适合半醒时使用",
|
| 88 |
"brand_subtitle": "Dream Customs",
|
| 89 |
"steps": ["记录", "一个追问", "清晨小票"],
|
| 90 |
"notice_record": "写一个梦境片段;想走 90 秒演示路径,也可以直接点示例 chip。",
|
dream_customs/ui/styles.py
CHANGED
|
@@ -3125,23 +3125,37 @@ button.secondary {
|
|
| 3125 |
"""
|
| 3126 |
|
| 3127 |
CSS += """
|
| 3128 |
-
/* Hero proportion fix: make the desk invitation feel calm,
|
| 3129 |
.dc-hero {
|
| 3130 |
align-content: center;
|
|
|
|
| 3131 |
background:
|
| 3132 |
radial-gradient(circle at 74% 37%, rgba(255, 253, 248, 0.54) 0 16%, rgba(255, 253, 248, 0.88) 33%, rgba(255, 253, 248, 0.98) 62%),
|
| 3133 |
linear-gradient(180deg, rgba(246, 251, 246, 0.96), rgba(255, 250, 240, 0.99)),
|
| 3134 |
url("https://images.unsplash.com/photo-1494438639946-1ebd1d20bf85?auto=format&fit=crop&w=1600&q=80") 74% 43% / cover !important;
|
| 3135 |
-
gap: clamp(
|
| 3136 |
-
min-height: clamp(
|
| 3137 |
overflow: hidden;
|
| 3138 |
-
padding: clamp(
|
|
|
|
| 3139 |
}
|
| 3140 |
|
| 3141 |
.dc-hero-top {
|
|
|
|
| 3142 |
grid-template-columns: 44px minmax(0, 1fr) 44px;
|
| 3143 |
}
|
| 3144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3145 |
.dc-menu-mark {
|
| 3146 |
opacity: 0.78;
|
| 3147 |
}
|
|
@@ -3158,19 +3172,23 @@ CSS += """
|
|
| 3158 |
}
|
| 3159 |
|
| 3160 |
.dc-hero h1 {
|
| 3161 |
-
font-size: clamp(2.
|
| 3162 |
-
line-height: 1.
|
| 3163 |
margin-left: auto;
|
| 3164 |
margin-right: auto;
|
| 3165 |
-
max-width:
|
|
|
|
| 3166 |
text-wrap: balance;
|
| 3167 |
}
|
| 3168 |
|
| 3169 |
.dc-brand-subtitle {
|
| 3170 |
color: #6f7f8b;
|
| 3171 |
-
font-size: clamp(1rem, 1.
|
| 3172 |
line-height: 1.45;
|
| 3173 |
-
|
|
|
|
|
|
|
|
|
|
| 3174 |
text-wrap: balance;
|
| 3175 |
}
|
| 3176 |
|
|
@@ -3183,6 +3201,7 @@ CSS += """
|
|
| 3183 |
}
|
| 3184 |
|
| 3185 |
.dc-hero-ribbon {
|
|
|
|
| 3186 |
background: rgba(255, 253, 248, 0.62);
|
| 3187 |
border-color: rgba(95, 143, 104, 0.2);
|
| 3188 |
border-radius: 999px;
|
|
@@ -3214,7 +3233,8 @@ CSS += """
|
|
| 3214 |
}
|
| 3215 |
|
| 3216 |
.dc-stepper {
|
| 3217 |
-
|
|
|
|
| 3218 |
max-width: 680px;
|
| 3219 |
}
|
| 3220 |
|
|
@@ -3235,12 +3255,12 @@ CSS += """
|
|
| 3235 |
|
| 3236 |
@media (max-width: 900px) {
|
| 3237 |
.dc-hero {
|
| 3238 |
-
min-height:
|
| 3239 |
padding: 24px 22px 32px;
|
| 3240 |
}
|
| 3241 |
|
| 3242 |
.dc-hero h1 {
|
| 3243 |
-
font-size: clamp(2.
|
| 3244 |
}
|
| 3245 |
|
| 3246 |
.dc-brand-subtitle,
|
|
@@ -3251,7 +3271,7 @@ CSS += """
|
|
| 3251 |
|
| 3252 |
@media (max-width: 640px) {
|
| 3253 |
.dc-hero {
|
| 3254 |
-
min-height:
|
| 3255 |
}
|
| 3256 |
|
| 3257 |
.dc-hero-top {
|
|
|
|
| 3125 |
"""
|
| 3126 |
|
| 3127 |
CSS += """
|
| 3128 |
+
/* Hero proportion fix: make the desk invitation feel calm, centered, and brief. */
|
| 3129 |
.dc-hero {
|
| 3130 |
align-content: center;
|
| 3131 |
+
justify-items: center;
|
| 3132 |
background:
|
| 3133 |
radial-gradient(circle at 74% 37%, rgba(255, 253, 248, 0.54) 0 16%, rgba(255, 253, 248, 0.88) 33%, rgba(255, 253, 248, 0.98) 62%),
|
| 3134 |
linear-gradient(180deg, rgba(246, 251, 246, 0.96), rgba(255, 250, 240, 0.99)),
|
| 3135 |
url("https://images.unsplash.com/photo-1494438639946-1ebd1d20bf85?auto=format&fit=crop&w=1600&q=80") 74% 43% / cover !important;
|
| 3136 |
+
gap: clamp(10px, 1.8vw, 16px);
|
| 3137 |
+
min-height: clamp(360px, 44vh, 500px);
|
| 3138 |
overflow: hidden;
|
| 3139 |
+
padding: clamp(22px, 3.6vw, 40px) clamp(18px, 5vw, 70px) clamp(26px, 4.2vw, 48px);
|
| 3140 |
+
text-align: center;
|
| 3141 |
}
|
| 3142 |
|
| 3143 |
.dc-hero-top {
|
| 3144 |
+
justify-self: stretch;
|
| 3145 |
grid-template-columns: 44px minmax(0, 1fr) 44px;
|
| 3146 |
}
|
| 3147 |
|
| 3148 |
+
.dc-brand-lockup {
|
| 3149 |
+
justify-content: center;
|
| 3150 |
+
text-align: center;
|
| 3151 |
+
}
|
| 3152 |
+
|
| 3153 |
+
.dc-brand-lockup > div {
|
| 3154 |
+
display: grid;
|
| 3155 |
+
justify-items: center;
|
| 3156 |
+
max-width: min(100%, 900px);
|
| 3157 |
+
}
|
| 3158 |
+
|
| 3159 |
.dc-menu-mark {
|
| 3160 |
opacity: 0.78;
|
| 3161 |
}
|
|
|
|
| 3172 |
}
|
| 3173 |
|
| 3174 |
.dc-hero h1 {
|
| 3175 |
+
font-size: clamp(2.45rem, 5.2vw, 4.35rem) !important;
|
| 3176 |
+
line-height: 1.01;
|
| 3177 |
margin-left: auto;
|
| 3178 |
margin-right: auto;
|
| 3179 |
+
max-width: 820px;
|
| 3180 |
+
text-align: center;
|
| 3181 |
text-wrap: balance;
|
| 3182 |
}
|
| 3183 |
|
| 3184 |
.dc-brand-subtitle {
|
| 3185 |
color: #6f7f8b;
|
| 3186 |
+
font-size: clamp(1rem, 1.55vw, 1.2rem);
|
| 3187 |
line-height: 1.45;
|
| 3188 |
+
margin-left: auto;
|
| 3189 |
+
margin-right: auto;
|
| 3190 |
+
max-width: 560px;
|
| 3191 |
+
text-align: center;
|
| 3192 |
text-wrap: balance;
|
| 3193 |
}
|
| 3194 |
|
|
|
|
| 3201 |
}
|
| 3202 |
|
| 3203 |
.dc-hero-ribbon {
|
| 3204 |
+
justify-self: center;
|
| 3205 |
background: rgba(255, 253, 248, 0.62);
|
| 3206 |
border-color: rgba(95, 143, 104, 0.2);
|
| 3207 |
border-radius: 999px;
|
|
|
|
| 3233 |
}
|
| 3234 |
|
| 3235 |
.dc-stepper {
|
| 3236 |
+
justify-self: center;
|
| 3237 |
+
margin-top: clamp(14px, 2.4vw, 26px);
|
| 3238 |
max-width: 680px;
|
| 3239 |
}
|
| 3240 |
|
|
|
|
| 3255 |
|
| 3256 |
@media (max-width: 900px) {
|
| 3257 |
.dc-hero {
|
| 3258 |
+
min-height: 430px;
|
| 3259 |
padding: 24px 22px 32px;
|
| 3260 |
}
|
| 3261 |
|
| 3262 |
.dc-hero h1 {
|
| 3263 |
+
font-size: clamp(2.15rem, 9.4vw, 3.45rem) !important;
|
| 3264 |
}
|
| 3265 |
|
| 3266 |
.dc-brand-subtitle,
|
|
|
|
| 3271 |
|
| 3272 |
@media (max-width: 640px) {
|
| 3273 |
.dc-hero {
|
| 3274 |
+
min-height: 460px;
|
| 3275 |
}
|
| 3276 |
|
| 3277 |
.dc-hero-top {
|
tests/test_ui_actions.py
CHANGED
|
@@ -101,10 +101,12 @@ def test_hero_subtitle_explains_app_instead_of_legacy_name():
|
|
| 101 |
hero_html = ui_app._hero_html()
|
| 102 |
|
| 103 |
assert "The Morning Question Desk" in hero_html
|
| 104 |
-
assert "What did the dream
|
| 105 |
-
assert "
|
| 106 |
assert "dc-hero-ribbon" in hero_html
|
| 107 |
-
assert "Text
|
|
|
|
|
|
|
| 108 |
assert "Dream Customs" not in hero_html
|
| 109 |
|
| 110 |
|
|
|
|
| 101 |
hero_html = ui_app._hero_html()
|
| 102 |
|
| 103 |
assert "The Morning Question Desk" in hero_html
|
| 104 |
+
assert "What did the dream ask?" in hero_html
|
| 105 |
+
assert "One fragment. One gentle question. One Morning Ticket." in hero_html
|
| 106 |
assert "dc-hero-ribbon" in hero_html
|
| 107 |
+
assert "Text · image · voice" in hero_html
|
| 108 |
+
assert "A small-model dream desk" not in hero_html
|
| 109 |
+
assert "dc-hero-body" not in hero_html
|
| 110 |
assert "Dream Customs" not in hero_html
|
| 111 |
|
| 112 |
|