Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,15 @@ landing page read as machine-generated. Keep it that way when extending it:
headings or nav any more, so the case you write is the case that renders.
- **No em dashes in site copy.** Use a full stop or a comma. `src/main.test.jsx`
guards this against the rendered DOM.
- **Radius scale is 6-14px** for site chrome. The capsule (`99px`) radius is reserved
for progress bars and for the in-phone surfaces that mirror native iOS controls.
- **No capsule buttons anywhere.** Site chrome sits on a 6-14px radius scale; the
in-phone buttons use ~7px, which is `RoundedRectangle(cornerRadius: 18)` from the
Swift consent sheets at the stage's scale. The `99px` radius is reserved for
progress bars, slider tracks, sheet grab handles, the iOS switch and the toast,
all of which are capsule in the native app too. An e2e test enforces this.
- **`.app-screen` children carry `flex-shrink: 0`.** It is a column flex container,
so without it a screen taller than the stage squeezes the last card instead of
scrolling. That silently collapsed the "Lumen noticed" card to a 14px sliver at
common laptop sizes; an e2e test now guards it.
- **One reveal per section.** `FadeIn` is opacity plus a short travel, with no delay
prop and no per-card stagger. Do not wrap individual grid items in it.
- **Icons come from lucide-react**, never emoji or dingbat glyphs.
Expand Down
11 changes: 9 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,15 @@ landing page read as machine-generated. Keep it that way when extending it:
headings or nav any more, so the case you write is the case that renders.
- **No em dashes in site copy.** Use a full stop or a comma. `src/main.test.jsx`
guards this against the rendered DOM.
- **Radius scale is 6-14px** for site chrome. The capsule (`99px`) radius is reserved
for progress bars and for the in-phone surfaces that mirror native iOS controls.
- **No capsule buttons anywhere.** Site chrome sits on a 6-14px radius scale; the
in-phone buttons use ~7px, which is `RoundedRectangle(cornerRadius: 18)` from the
Swift consent sheets at the stage's scale. The `99px` radius is reserved for
progress bars, slider tracks, sheet grab handles, the iOS switch and the toast,
all of which are capsule in the native app too. An e2e test enforces this.
- **`.app-screen` children carry `flex-shrink: 0`.** It is a column flex container,
so without it a screen taller than the stage squeezes the last card instead of
scrolling. That silently collapsed the "Lumen noticed" card to a 14px sliver at
common laptop sizes; an e2e test now guards it.
- **One reveal per section.** `FadeIn` is opacity plus a short travel, with no delay
prop and no per-card stagger. Do not wrap individual grid items in it.
- **Icons come from lucide-react**, never emoji or dingbat glyphs.
Expand Down
2 changes: 1 addition & 1 deletion Lumen/Components/EmptyStateView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct EmptyStateView: View {
.font(.body.bold())
.padding(.horizontal, 24)
.padding(.vertical, 10)
.background(Color("MuhaBrown"), in: Capsule())
.background(Color("MuhaBrown"), in: RoundedRectangle(cornerRadius: 18))
.foregroundStyle(Color("MuhaCream"))
}
.padding(.top, 4)
Expand Down
43 changes: 43 additions & 0 deletions e2e/live-demo.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,49 @@ test.describe('Lumen live demo', () => {
await expect(page.locator('.app-fullscreen')).toHaveCount(0);
});

test('preview rows keep their height instead of being crushed', async ({ page }) => {
// .app-screen is a column flex container, so its children shrink below
// their own content by default rather than letting the screen scroll. That
// squeezed the "Lumen noticed" card from 106px down to 14px at common
// laptop sizes. Check the short viewport, where the squeeze was worst.
await page.setViewportSize({ width: 1280, height: 720 });
await page.goto('/');

const crushed = await page.evaluate(() => {
const screen = document.querySelector('.app-preview-stage .app-screen');
return [...screen.children]
.filter(el => el.scrollHeight > el.clientHeight + 2)
.map(el => `${el.className}: ${el.scrollHeight} > ${el.clientHeight}`);
});

expect(crushed).toEqual([]);
});

test('no button in the preview or its chrome is capsule-shaped', async ({ page }) => {
// The native app uses RoundedRectangle(cornerRadius: 18) for its buttons;
// capsules there are grab handles, progress bars and the iOS switch. A
// fully-rounded button is the landing-page tell we removed, so keep it out.
await page.goto('/');
await page.locator('#demo').getByRole('button', { name: /review evening scene/i }).click();
await expect(page.locator('#demo').getByText(/why lumen noticed/i)).toBeVisible();

const pills = await page.evaluate(() => {
const out = [];
for (const el of document.querySelectorAll('button, a[href]')) {
if (el.offsetParent === null) continue;
const h = el.getBoundingClientRect().height;
const cs = getComputedStyle(el);
if (!h || cs.borderRadius.includes('%')) continue; // circular icon buttons are fine
if (parseFloat(cs.borderRadius) >= h / 2 - 0.5) {
out.push(`${el.className}: r=${cs.borderRadius} h=${Math.round(h)}`);
}
}
return out;
});

expect(pills).toEqual([]);
});

test('mobile stage is tappable without a nested bezel', async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto('/');
Expand Down
65 changes: 10 additions & 55 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -1092,16 +1092,6 @@ p {
flex-wrap: wrap;
}

.chat-chip {
padding: 4px 9px;
border-radius: 99px;
border: 1px solid rgba(255,255,255,0.1);
background: rgba(255,255,255,0.04);
color: rgba(232,224,212,0.52);
font-size: 9px;
cursor: pointer;
font-family: inherit;
}

.chat-chip.apply {
border-color: rgba(200,184,154,0.3);
Expand Down Expand Up @@ -1357,20 +1347,6 @@ p {
justify-content: center;
}

.chapter-strip button {
display: flex;
align-items: center;
gap: 6px;
padding: 7px 13px;
border-radius: 99px;
border: 1px solid rgba(255,255,255,0.07);
background: transparent;
color: rgba(232,224,212,0.38);
font-size: 11px;
font-family: inherit;
cursor: pointer;
transition: color 0.2s, border-color 0.2s, background 0.2s;
}

.chapter-strip button:hover {
color: rgba(232,224,212,0.7);
Expand Down Expand Up @@ -1414,6 +1390,14 @@ p {
gap: 5px;
}

/* Column flex children shrink below their content by default, so a screen
taller than the stage squeezes the last card instead of scrolling: the
"Lumen noticed" card collapsed from 106px to 14px at common laptop sizes.
Hold every row at its natural height and let .app-screen scroll. */
.app-screen > * {
flex-shrink: 0;
}

.app-screen.dimmed {
opacity: 0.3;
filter: blur(1.5px);
Expand Down Expand Up @@ -1915,7 +1899,7 @@ p {
width: 100%;
margin-top: 6px;
padding: 8px 14px;
border-radius: 99px;
border-radius: 7px;
border: none;
background: #C49A6C;
color: #0e0819;
Expand All @@ -1936,7 +1920,7 @@ p {
width: 100%;
margin-top: 6px;
padding: 8px 14px;
border-radius: 99px;
border-radius: 7px;
background: #C49A6C;
color: #0e0819;
font-size: 9.5px;
Expand Down Expand Up @@ -2789,38 +2773,9 @@ p {
z-index: 0;
}

.try-it-pill {
display: inline-flex;
align-items: center;
padding: 3px 8px;
border-radius: 99px;
background: rgba(196,154,108,0.16);
border: 1px solid rgba(196,154,108,0.32);
color: #C49A6C;
font-size: 8px;
letter-spacing: 0.1em;
text-transform: uppercase;
margin-left: auto;
flex-shrink: 0;
animation: pulseGlow 2.2s ease-in-out infinite;
}

/* ===== COMING PILL ===== */

.coming-pill {
display: inline-flex;
align-items: center;
padding: 3px 8px;
border-radius: 99px;
background: rgba(138,180,248,0.12);
border: 1px solid rgba(160,100,255,0.18);
color: rgba(180,130,255,0.65);
font-size: 8px;
letter-spacing: 0.1em;
text-transform: uppercase;
margin-left: auto;
flex-shrink: 0;
}

/* ===== RESPONSIVE (additions) ===== */

Expand Down
17 changes: 11 additions & 6 deletions src/simulator.css
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,9 @@

.app-preview-stage {
width: min(390px, 100%);
height: min(80vh, 780px);
/* 82vh rather than 80: at a 900px-tall viewport, the most common laptop
size, 80vh left the suggestion card 5px short of the fold. */
height: min(82vh, 780px);
min-height: 620px;
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -348,8 +350,11 @@
}

.app-preview-stage .app-screen {
padding: 12px 18px 14px;
gap: 10px;
/* Tight enough that the "Lumen noticed" card, which is the whole point of
the preview, clears the fold on a 900px-tall viewport. Below that the
screen scrolls, the same as the real phone would. */
padding: 12px 18px 10px;
gap: 8px;
}

.app-preview-stage .app-tabbar {
Expand Down Expand Up @@ -583,7 +588,7 @@
gap: 8px;
margin-top: 4px;
padding: 11px 20px;
border-radius: 99px;
border-radius: 12px;
border: 1px solid rgba(196, 154, 108, 0.4);
background: rgba(196, 154, 108, 0.12);
color: #e8d3b6;
Expand Down Expand Up @@ -653,7 +658,7 @@
align-items: center;
gap: 5px;
padding: 7px 13px;
border-radius: 99px;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.14);
background: rgba(20, 14, 34, 0.7);
backdrop-filter: blur(8px);
Expand Down Expand Up @@ -790,7 +795,7 @@
align-self: flex-start;
margin-top: 4px;
padding: 7px 12px;
border-radius: 99px;
border-radius: 7px;
border: 1px solid rgba(196, 154, 108, 0.35);
background: rgba(196, 154, 108, 0.1);
color: #e8d3b6;
Expand Down
Loading