chore: apply prettier formatting and fix lint errors

This commit is contained in:
codenamewont
2026-06-15 09:25:01 +09:00
parent 063a193396
commit 84c8a0aac9
29 changed files with 1421 additions and 471 deletions

View File

@@ -132,7 +132,9 @@ async function main() {
const size = process.env.OPENAI_IMAGE_CATALOG_SIZE || '1024x1536'; const size = process.env.OPENAI_IMAGE_CATALOG_SIZE || '1024x1536';
const quality = process.env.OPENAI_IMAGE_CATALOG_QUALITY || 'low'; const quality = process.env.OPENAI_IMAGE_CATALOG_QUALITY || 'low';
console.log(`대상: ${targets.length}종 · ${size} · quality=${quality}${dryRun ? ' (dry-run)' : ''}`); console.log(
`대상: ${targets.length}종 · ${size} · quality=${quality}${dryRun ? ' (dry-run)' : ''}`
);
for (const flower of targets) { for (const flower of targets) {
const outPath = join(OUT_DIR, `${flower.id}.png`); const outPath = join(OUT_DIR, `${flower.id}.png`);

View File

@@ -19,13 +19,13 @@
</script> </script>
<section <section
class="relative flex w-full shrink-0 flex-col border-b border-line lg:min-h-0 lg:h-full lg:w-[44%] lg:shrink-0 lg:overflow-y-auto lg:border-r lg:border-b-0" class="relative flex w-full shrink-0 flex-col border-b border-line lg:h-full lg:min-h-0 lg:w-[44%] lg:shrink-0 lg:overflow-y-auto lg:border-r lg:border-b-0"
> >
<!-- <!--
mobile: row · desktop: 꽃 슬롯 높이 고정 → 설명 카드 길이와 무관하게 Y·크기 유지 mobile: row · desktop: 꽃 슬롯 높이 고정 → 설명 카드 길이와 무관하게 Y·크기 유지
--> -->
<div <div
class="mx-auto flex min-h-0 w-full max-w-100 flex-1 flex-row items-start gap-8 px-6 pt-6 pb-8 lg:flex-col lg:items-center lg:justify-start lg:gap-4 lg:px-6 lg:pb-12 lg:pt-[calc(50%-5rem)]" class="mx-auto flex min-h-0 w-full max-w-100 flex-1 flex-row items-start gap-8 px-6 pt-6 pb-8 lg:flex-col lg:items-center lg:justify-start lg:gap-4 lg:px-6 lg:pt-[calc(50%-5rem)] lg:pb-12"
> >
<div <div
class="flex h-[11rem] shrink-0 items-end justify-center sm:h-[13rem] lg:h-[min(24rem,36vh)] lg:w-full" class="flex h-[11rem] shrink-0 items-end justify-center sm:h-[13rem] lg:h-[min(24rem,36vh)] lg:w-full"
@@ -43,7 +43,7 @@
{/if} {/if}
</div> </div>
<div class="min-w-0 shrink-0 lg:w-full lg:flex lg:justify-center"> <div class="min-w-0 shrink-0 lg:flex lg:w-full lg:justify-center">
<DescriptionCard {title} {description} mode={cardMode} /> <DescriptionCard {title} {description} mode={cardMode} />
</div> </div>
</div> </div>

View File

@@ -7,9 +7,14 @@
} = $props(); } = $props();
</script> </script>
<div class="w-64 max-w-full flex-none border border-line-strong bg-white px-4 py-3 shadow-sm lg:px-6 lg:py-5"> <div
class="w-64 max-w-full flex-none border border-line-strong bg-white px-4 py-3 shadow-sm lg:px-6 lg:py-5"
>
<h3 <h3
class={['text-sm leading-snug font-semibold', mode === 'instruction' ? 'text-muted' : 'text-ink']} class={[
'text-sm leading-snug font-semibold',
mode === 'instruction' ? 'text-muted' : 'text-ink'
]}
> >
{title} {title}
</h3> </h3>

View File

@@ -1,9 +1,7 @@
<script> <script>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import FlowContinueBar, { import FlowContinueBar, { FLOW_CONTINUE_BUTTON } from '$lib/components/ui/FlowContinueBar.svelte';
FLOW_CONTINUE_BUTTON
} from '$lib/components/ui/FlowContinueBar.svelte';
import GrowthMetaphorIllustration from '$lib/components/ui/landing/GrowthMetaphorIllustration.svelte'; import GrowthMetaphorIllustration from '$lib/components/ui/landing/GrowthMetaphorIllustration.svelte';
function handleStart() { function handleStart() {
@@ -15,7 +13,7 @@
class="relative flex min-h-dvh flex-col bg-surface px-6 py-8 pb-[3.75rem] font-sans text-ink sm:px-10 sm:py-10 lg:px-14 lg:pb-8" class="relative flex min-h-dvh flex-col bg-surface px-6 py-8 pb-[3.75rem] font-sans text-ink sm:px-10 sm:py-10 lg:px-14 lg:pb-8"
aria-label="Every bouquet starts with a muse — seed to bouquet growth metaphor" aria-label="Every bouquet starts with a muse — seed to bouquet growth metaphor"
> >
<div class="mx-auto flex w-full max-w-6xl min-h-0 flex-1 flex-col justify-center"> <div class="mx-auto flex min-h-0 w-full max-w-6xl flex-1 flex-col justify-center">
<GrowthMetaphorIllustration /> <GrowthMetaphorIllustration />
<p class="mt-3 text-left text-sm tracking-[0.18em] text-muted sm:mt-4 sm:text-base"> <p class="mt-3 text-left text-sm tracking-[0.18em] text-muted sm:mt-4 sm:text-base">

View File

@@ -1,8 +1,5 @@
<script> <script>
let { let { enPlainText = '', koPlainText = '' } = $props();
enPlainText = '',
koPlainText = ''
} = $props();
/** @type {'ko' | 'en'} */ /** @type {'ko' | 'en'} */
let activeLang = $state('ko'); let activeLang = $state('ko');
@@ -61,10 +58,14 @@
rows={4} rows={4}
value={activeText} value={activeText}
oninput={handleInput} oninput={handleInput}
aria-label={activeLang === 'ko' ? '꽃집 주문 멘트 (한국어)' : 'Florist order message (English)'} aria-label={activeLang === 'ko'
? '꽃집 주문 멘트 (한국어)'
: 'Florist order message (English)'}
></textarea> ></textarea>
{:else} {:else}
<p class="min-w-0 flex-1 text-sm text-muted">Complete the flow to generate your order message.</p> <p class="min-w-0 flex-1 text-sm text-muted">
Complete the flow to generate your order message.
</p>
{/if} {/if}
<div class="flex shrink-0 flex-col items-stretch gap-2"> <div class="flex shrink-0 flex-col items-stretch gap-2">

View File

@@ -1,5 +1,6 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { SvelteMap } from 'svelte/reactivity';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
let { let {
@@ -23,8 +24,8 @@
let mapInstance = $state(null); let mapInstance = $state(null);
/** @type {ReturnType<typeof window.kakao.maps.InfoWindow> | null} */ /** @type {ReturnType<typeof window.kakao.maps.InfoWindow> | null} */
let infoWindow = null; let infoWindow = null;
/** @type {Map<string, { marker: ReturnType<typeof window.kakao.maps.Marker>; shop: (typeof shops)[number] }>} */ /** @type {SvelteMap<string, { marker: ReturnType<typeof window.kakao.maps.Marker>; shop: (typeof shops)[number] }>} */
let shopMarkerMap = new Map(); let shopMarkerMap = new SvelteMap();
function relayoutMap() { function relayoutMap() {
mapInstance?.relayout?.(); mapInstance?.relayout?.();
@@ -226,9 +227,7 @@
{mapError} {mapError}
</div> </div>
{:else if !mapReady} {:else if !mapReady}
<div <div class="absolute inset-0 flex items-center justify-center bg-track text-sm text-muted">
class="absolute inset-0 flex items-center justify-center bg-track text-sm text-muted"
>
Loading map... Loading map...
</div> </div>
{/if} {/if}

View File

@@ -71,10 +71,12 @@
{/if} {/if}
<div class="flex min-h-0 flex-1 flex-col gap-6 px-6 pb-8 md:px-10 lg:flex-row lg:px-12 lg:pb-10"> <div class="flex min-h-0 flex-1 flex-col gap-6 px-6 pb-8 md:px-10 lg:flex-row lg:px-12 lg:pb-10">
<div class="relative flex min-h-64 flex-1 flex-col overflow-hidden border border-line lg:min-h-0"> <div
class="relative flex min-h-64 flex-1 flex-col overflow-hidden border border-line lg:min-h-0"
>
<KakaoMap <KakaoMap
initialLat={initialLat} {initialLat}
initialLng={initialLng} {initialLng}
{shops} {shops}
selectedId={selectedShopId} selectedId={selectedShopId}
{fitBounds} {fitBounds}
@@ -96,7 +98,7 @@
{#if loading && shops.length === 0} {#if loading && shops.length === 0}
<p class="text-sm text-muted">Searching for flower shops...</p> <p class="text-sm text-muted">Searching for flower shops...</p>
{:else} {:else}
<ShopList shops={shops} bind:selectedId={selectedShopId} onselect={handleShopSelect} /> <ShopList {shops} bind:selectedId={selectedShopId} onselect={handleShopSelect} />
{/if} {/if}
</div> </div>
</div> </div>

View File

@@ -8,7 +8,7 @@
'Thank you for always being there', 'Thank you for always being there',
'I love you', 'I love you',
"I'm proud of you", "I'm proud of you",
'Congratulations!', 'Congratulations!'
]; ];
const selectedPreset = $derived(presets.find((preset) => preset === message) ?? null); const selectedPreset = $derived(presets.find((preset) => preset === message) ?? null);

View File

@@ -1,14 +1,7 @@
<script> <script>
import flowerIconUrl from '$lib/assets/flower.svg'; import flowerIconUrl from '$lib/assets/flower.svg';
let { let { name, nameKo, wordOfFlower, wordOfFlowerKo, imageSrc, role = 'main' } = $props();
name,
nameKo,
wordOfFlower,
wordOfFlowerKo,
imageSrc,
role = 'main'
} = $props();
let flipped = $state(false); let flipped = $state(false);
@@ -26,7 +19,7 @@
<button <button
type="button" type="button"
class="flip-card h-[16.25rem] w-40 shrink-0 snap-start cursor-pointer border-none bg-transparent p-0 text-left" class="flip-card h-[16.25rem] w-40 shrink-0 cursor-pointer snap-start border-none bg-transparent p-0 text-left"
aria-label={flipped ? `${nameKo} card, show English` : `${name} card, show Korean`} aria-label={flipped ? `${nameKo} card, show English` : `${name} card, show Korean`}
onclick={toggleFlip} onclick={toggleFlip}
> >
@@ -48,7 +41,7 @@
/> />
</div> </div>
<div class="shrink-0 px-3 pb-4 pt-2"> <div class="shrink-0 px-3 pt-2 pb-4">
<h3 <h3
class="flex min-h-8 items-center justify-center text-center text-sm leading-tight tracking-wide text-ink" class="flex min-h-8 items-center justify-center text-center text-sm leading-tight tracking-wide text-ink"
> >
@@ -79,7 +72,7 @@
/> />
</div> </div>
<div class="shrink-0 px-3 pb-4 pt-2"> <div class="shrink-0 px-3 pt-2 pb-4">
<h3 <h3
class="flex min-h-8 items-center justify-center text-center text-sm leading-tight tracking-wide text-ink" class="flex min-h-8 items-center justify-center text-center text-sm leading-tight tracking-wide text-ink"
> >

View File

@@ -12,7 +12,7 @@
<p class="mb-4 text-xs tracking-[0.2em] text-muted uppercase">Flowers in your bouquet</p> <p class="mb-4 text-xs tracking-[0.2em] text-muted uppercase">Flowers in your bouquet</p>
<div <div
class="flex snap-x snap-mandatory gap-4 overflow-x-auto px-0.5 py-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden" class="flex snap-x snap-mandatory [scrollbar-width:none] gap-4 overflow-x-auto px-0.5 py-1 [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden"
> >
{#each flowers as flower (flower.id)} {#each flowers as flower (flower.id)}
<BouquetFlowerCard <BouquetFlowerCard

View File

@@ -16,8 +16,7 @@ export const ARTWORK_CARD_DEFAULTS = {
}, },
generating: { generating: {
title: 'Crafting your bouquet', title: 'Crafting your bouquet',
description: description: 'We are turning their mood, photos, and message into a one-of-a-kind arrangement.'
'We are turning their mood, photos, and message into a one-of-a-kind arrangement.'
}, },
map: { map: {
title: 'Choose a florist', title: 'Choose a florist',

View File

@@ -20,7 +20,9 @@ export function formatStrictBouquetImagePrompt(recipe) {
'Generate a realistic Korean florist bouquet product photo.', 'Generate a realistic Korean florist bouquet product photo.',
'', '',
'STRICT RECIPE — the bouquet must contain ONLY these flowers and NO other flower species:', 'STRICT RECIPE — the bouquet must contain ONLY these flowers and NO other flower species:',
allFlowers.length > 0 ? allFlowers.map((flower) => `- ${flower}`).join('\n') : '- (none listed)', allFlowers.length > 0
? allFlowers.map((flower) => `- ${flower}`).join('\n')
: '- (none listed)',
'', '',
`Main focal blooms (each must be clearly visible): ${mains.join(', ') || 'none'}`, `Main focal blooms (each must be clearly visible): ${mains.join(', ') || 'none'}`,
`Supporting filler/line flowers (each must appear): ${subs.join(', ') || 'none'}`, `Supporting filler/line flowers (each must appear): ${subs.join(', ') || 'none'}`,

View File

@@ -60,7 +60,10 @@ export function buildFloristOrderMessage(input) {
`Would a reservation be possible?`; `Would a reservation be possible?`;
const segments = [ const segments = [
{ text: "Hello, I'd like to inquire about a flower order. It's a bouquet for ", highlight: false }, {
text: "Hello, I'd like to inquire about a flower order. It's a bouquet for ",
highlight: false
},
{ text: relationship, highlight: true }, { text: relationship, highlight: true },
{ text: ' for ', highlight: false }, { text: ' for ', highlight: false },
{ text: occasion, highlight: true }, { text: occasion, highlight: true },

View File

@@ -3,468 +3,468 @@
/** @type {{ id: number, name: string, wordOfFlower: string }[]} */ /** @type {{ id: number, name: string, wordOfFlower: string }[]} */
export const flowerCatalogLite = [ export const flowerCatalogLite = [
{ {
"id": 1, id: 1,
"name": "Daffodil", name: 'Daffodil',
"wordOfFlower": "self-love" wordOfFlower: 'self-love'
}, },
{ {
"id": 2, id: 2,
"name": "Stock", name: 'Stock',
"wordOfFlower": "lasting beauty" wordOfFlower: 'lasting beauty'
}, },
{ {
"id": 3, id: 3,
"name": "Amaryllis", name: 'Amaryllis',
"wordOfFlower": "dazzling beauty" wordOfFlower: 'dazzling beauty'
}, },
{ {
"id": 4, id: 4,
"name": "Sweet Pea", name: 'Sweet Pea',
"wordOfFlower": "delicate pleasures" wordOfFlower: 'delicate pleasures'
}, },
{ {
"id": 5, id: 5,
"name": "Anthurium", name: 'Anthurium',
"wordOfFlower": "hospitality" wordOfFlower: 'hospitality'
}, },
{ {
"id": 6, id: 6,
"name": "Freesia", name: 'Freesia',
"wordOfFlower": "purity" wordOfFlower: 'purity'
}, },
{ {
"id": 7, id: 7,
"name": "Tulip", name: 'Tulip',
"wordOfFlower": "benevolence" wordOfFlower: 'benevolence'
}, },
{ {
"id": 8, id: 8,
"name": "Hyacinth", name: 'Hyacinth',
"wordOfFlower": "joy of the heart" wordOfFlower: 'joy of the heart'
}, },
{ {
"id": 9, id: 9,
"name": "Ranunculus", name: 'Ranunculus',
"wordOfFlower": "radiant charm" wordOfFlower: 'radiant charm'
}, },
{ {
"id": 10, id: 10,
"name": "Lilac", name: 'Lilac',
"wordOfFlower": "memories of youth" wordOfFlower: 'memories of youth'
}, },
{ {
"id": 11, id: 11,
"name": "Iris", name: 'Iris',
"wordOfFlower": "good news" wordOfFlower: 'good news'
}, },
{ {
"id": 12, id: 12,
"name": "Tree Peony", name: 'Tree Peony',
"wordOfFlower": "wealth and honor" wordOfFlower: 'wealth and honor'
}, },
{ {
"id": 13, id: 13,
"name": "Peony", name: 'Peony',
"wordOfFlower": "shyness" wordOfFlower: 'shyness'
}, },
{ {
"id": 14, id: 14,
"name": "Rose", name: 'Rose',
"wordOfFlower": "passionate love" wordOfFlower: 'passionate love'
}, },
{ {
"id": 15, id: 15,
"name": "Snowball Viburnum", name: 'Snowball Viburnum',
"wordOfFlower": "grace" wordOfFlower: 'grace'
}, },
{ {
"id": 16, id: 16,
"name": "Carnation", name: 'Carnation',
"wordOfFlower": "a woman's affection" wordOfFlower: "a woman's affection"
}, },
{ {
"id": 17, id: 17,
"name": "Clematis", name: 'Clematis',
"wordOfFlower": "nobility" wordOfFlower: 'nobility'
}, },
{ {
"id": 18, id: 18,
"name": "Lily", name: 'Lily',
"wordOfFlower": "purity" wordOfFlower: 'purity'
}, },
{ {
"id": 19, id: 19,
"name": "Hydrangea", name: 'Hydrangea',
"wordOfFlower": "heartlessness" wordOfFlower: 'heartlessness'
}, },
{ {
"id": 20, id: 20,
"name": "Agapanthus", name: 'Agapanthus',
"wordOfFlower": "love letter" wordOfFlower: 'love letter'
}, },
{ {
"id": 21, id: 21,
"name": "Allium", name: 'Allium',
"wordOfFlower": "endless sorrow" wordOfFlower: 'endless sorrow'
}, },
{ {
"id": 22, id: 22,
"name": "Bellflower (Campanula)", name: 'Bellflower (Campanula)',
"wordOfFlower": "a coquettish look" wordOfFlower: 'a coquettish look'
}, },
{ {
"id": 23, id: 23,
"name": "China Aster (Callistephus)", name: 'China Aster (Callistephus)',
"wordOfFlower": "trusting love" wordOfFlower: 'trusting love'
}, },
{ {
"id": 24, id: 24,
"name": "Poppy (Papaver)", name: 'Poppy (Papaver)',
"wordOfFlower": "consolation" wordOfFlower: 'consolation'
}, },
{ {
"id": 25, id: 25,
"name": "Dahlia", name: 'Dahlia',
"wordOfFlower": "gratitude" wordOfFlower: 'gratitude'
}, },
{ {
"id": 26, id: 26,
"name": "Lotus", name: 'Lotus',
"wordOfFlower": "purity" wordOfFlower: 'purity'
}, },
{ {
"id": 27, id: 27,
"name": "Gentian", name: 'Gentian',
"wordOfFlower": "I love you when you're sad" wordOfFlower: "I love you when you're sad"
}, },
{ {
"id": 28, id: 28,
"name": "Sunflower", name: 'Sunflower',
"wordOfFlower": "adoration" wordOfFlower: 'adoration'
}, },
{ {
"id": 29, id: 29,
"name": "Chrysanthemum", name: 'Chrysanthemum',
"wordOfFlower": "purity" wordOfFlower: 'purity'
}, },
{ {
"id": 30, id: 30,
"name": "Cockscomb (Celosia)", name: 'Cockscomb (Celosia)',
"wordOfFlower": "ardent love" wordOfFlower: 'ardent love'
}, },
{ {
"id": 31, id: 31,
"name": "Anemone", name: 'Anemone',
"wordOfFlower": "sincerity" wordOfFlower: 'sincerity'
}, },
{ {
"id": 32, id: 32,
"name": "Cosmos", name: 'Cosmos',
"wordOfFlower": "a girl's pure heart" wordOfFlower: "a girl's pure heart"
}, },
{ {
"id": 33, id: 33,
"name": "Red Spider Lily (Lycoris radiata)", name: 'Red Spider Lily (Lycoris radiata)',
"wordOfFlower": "true love" wordOfFlower: 'true love'
}, },
{ {
"id": 34, id: 34,
"name": "Gerbera", name: 'Gerbera',
"wordOfFlower": "mystery" wordOfFlower: 'mystery'
}, },
{ {
"id": 35, id: 35,
"name": "Calla Lily", name: 'Calla Lily',
"wordOfFlower": "joy" wordOfFlower: 'joy'
}, },
{ {
"id": 36, id: 36,
"name": "Bird of Paradise (Strelitzia)", name: 'Bird of Paradise (Strelitzia)',
"wordOfFlower": "mystery" wordOfFlower: 'mystery'
}, },
{ {
"id": 37, id: 37,
"name": "Hellebore", name: 'Hellebore',
"wordOfFlower": "reason for being" wordOfFlower: 'reason for being'
}, },
{ {
"id": 38, id: 38,
"name": "Lisianthus (Eustoma)", name: 'Lisianthus (Eustoma)',
"wordOfFlower": "appreciation" wordOfFlower: 'appreciation'
}, },
{ {
"id": 39, id: 39,
"name": "Scabiosa", name: 'Scabiosa',
"wordOfFlower": "I have lost all" wordOfFlower: 'I have lost all'
}, },
{ {
"id": 40, id: 40,
"name": "Wax Flower (Chamelaucium)", name: 'Wax Flower (Chamelaucium)',
"wordOfFlower": "lasting love" wordOfFlower: 'lasting love'
}, },
{ {
"id": 41, id: 41,
"name": "Caspia (Limonium)", name: 'Caspia (Limonium)',
"wordOfFlower": "remembrance" wordOfFlower: 'remembrance'
}, },
{ {
"id": 42, id: 42,
"name": "Ruscus", name: 'Ruscus',
"wordOfFlower": "endurance" wordOfFlower: 'endurance'
}, },
{ {
"id": 43, id: 43,
"name": "Veronica (Speedwell)", name: 'Veronica (Speedwell)',
"wordOfFlower": "fidelity" wordOfFlower: 'fidelity'
}, },
{ {
"id": 44, id: 44,
"name": "Solidago (Goldenrod)", name: 'Solidago (Goldenrod)',
"wordOfFlower": "encouragement" wordOfFlower: 'encouragement'
}, },
{ {
"id": 45, id: 45,
"name": "Bouvardia", name: 'Bouvardia',
"wordOfFlower": "enthusiasm" wordOfFlower: 'enthusiasm'
}, },
{ {
"id": 46, id: 46,
"name": "Tweedia (Oxypetalum)", name: 'Tweedia (Oxypetalum)',
"wordOfFlower": "believe in me" wordOfFlower: 'believe in me'
}, },
{ {
"id": 47, id: 47,
"name": "Craspedia (Billy Balls)", name: 'Craspedia (Billy Balls)',
"wordOfFlower": "good health" wordOfFlower: 'good health'
}, },
{ {
"id": 48, id: 48,
"name": "Amaranthus", name: 'Amaranthus',
"wordOfFlower": "immortality" wordOfFlower: 'immortality'
}, },
{ {
"id": 49, id: 49,
"name": "Queen Anne's Lace (Ammi)", name: "Queen Anne's Lace (Ammi)",
"wordOfFlower": "sanctuary" wordOfFlower: 'sanctuary'
}, },
{ {
"id": 50, id: 50,
"name": "Nigella (Love-in-a-mist)", name: 'Nigella (Love-in-a-mist)',
"wordOfFlower": "perplexity" wordOfFlower: 'perplexity'
}, },
{ {
"id": 51, id: 51,
"name": "Brunia", name: 'Brunia',
"wordOfFlower": "unity" wordOfFlower: 'unity'
}, },
{ {
"id": 52, id: 52,
"name": "Snapdragon", name: 'Snapdragon',
"wordOfFlower": "desire" wordOfFlower: 'desire'
}, },
{ {
"id": 53, id: 53,
"name": "Lupine", name: 'Lupine',
"wordOfFlower": "lust for life" wordOfFlower: 'lust for life'
}, },
{ {
"id": 54, id: 54,
"name": "Gladiolus", name: 'Gladiolus',
"wordOfFlower": "secret meeting" wordOfFlower: 'secret meeting'
}, },
{ {
"id": 55, id: 55,
"name": "Foxglove (Digitalis)", name: 'Foxglove (Digitalis)',
"wordOfFlower": "ardent love" wordOfFlower: 'ardent love'
}, },
{ {
"id": 56, id: 56,
"name": "Delphinium", name: 'Delphinium',
"wordOfFlower": "understand my heart" wordOfFlower: 'understand my heart'
}, },
{ {
"id": 57, id: 57,
"name": "Salvia (Scarlet Sage)", name: 'Salvia (Scarlet Sage)',
"wordOfFlower": "burning heart" wordOfFlower: 'burning heart'
}, },
{ {
"id": 58, id: 58,
"name": "Grape Hyacinth (Muscari)", name: 'Grape Hyacinth (Muscari)',
"wordOfFlower": "disappointment" wordOfFlower: 'disappointment'
}, },
{ {
"id": 59, id: 59,
"name": "Forget-me-not", name: 'Forget-me-not',
"wordOfFlower": "true love" wordOfFlower: 'true love'
}, },
{ {
"id": 60, id: 60,
"name": "Statice (Limonium)", name: 'Statice (Limonium)',
"wordOfFlower": "eternal love" wordOfFlower: 'eternal love'
}, },
{ {
"id": 61, id: 61,
"name": "Astilbe", name: 'Astilbe',
"wordOfFlower": "bashfulness" wordOfFlower: 'bashfulness'
}, },
{ {
"id": 62, id: 62,
"name": "Strawflower (Helichrysum)", name: 'Strawflower (Helichrysum)',
"wordOfFlower": "always remember" wordOfFlower: 'always remember'
}, },
{ {
"id": 63, id: 63,
"name": "Cornflower (Centaurea)", name: 'Cornflower (Centaurea)',
"wordOfFlower": "happiness" wordOfFlower: 'happiness'
}, },
{ {
"id": 64, id: 64,
"name": "Chinese Lantern (Physalis)", name: 'Chinese Lantern (Physalis)',
"wordOfFlower": "falsehood" wordOfFlower: 'falsehood'
}, },
{ {
"id": 65, id: 65,
"name": "Globe Amaranth (Gomphrena)", name: 'Globe Amaranth (Gomphrena)',
"wordOfFlower": "immortality" wordOfFlower: 'immortality'
}, },
{ {
"id": 66, id: 66,
"name": "Showy Stonecrop (Sedum)", name: 'Showy Stonecrop (Sedum)',
"wordOfFlower": "hope" wordOfFlower: 'hope'
}, },
{ {
"id": 67, id: 67,
"name": "Baby's Breath (Gypsophila)", name: "Baby's Breath (Gypsophila)",
"wordOfFlower": "earnest joy" wordOfFlower: 'earnest joy'
}, },
{ {
"id": 68, id: 68,
"name": "Cattleya", name: 'Cattleya',
"wordOfFlower": "you are a beauty" wordOfFlower: 'you are a beauty'
}, },
{ {
"id": 69, id: 69,
"name": "Oncidium", name: 'Oncidium',
"wordOfFlower": "innocent heart" wordOfFlower: 'innocent heart'
}, },
{ {
"id": 70, id: 70,
"name": "Dendrobium", name: 'Dendrobium',
"wordOfFlower": "a beauty" wordOfFlower: 'a beauty'
}, },
{ {
"id": 71, id: 71,
"name": "Vanda Orchid", name: 'Vanda Orchid',
"wordOfFlower": "a token of affection" wordOfFlower: 'a token of affection'
}, },
{ {
"id": 72, id: 72,
"name": "Holly", name: 'Holly',
"wordOfFlower": "protection" wordOfFlower: 'protection'
}, },
{ {
"id": 73, id: 73,
"name": "Nandina (Heavenly Bamboo)", name: 'Nandina (Heavenly Bamboo)',
"wordOfFlower": "enduring love" wordOfFlower: 'enduring love'
}, },
{ {
"id": 74, id: 74,
"name": "Pussy Willow (Salix gracilistyla)", name: 'Pussy Willow (Salix gracilistyla)',
"wordOfFlower": "freedom" wordOfFlower: 'freedom'
}, },
{ {
"id": 75, id: 75,
"name": "Maidenhair Fern (Adiantum)", name: 'Maidenhair Fern (Adiantum)',
"wordOfFlower": "charm" wordOfFlower: 'charm'
}, },
{ {
"id": 76, id: 76,
"name": "Cotton", name: 'Cotton',
"wordOfFlower": "mother's love" wordOfFlower: "mother's love"
}, },
{ {
"id": 77, id: 77,
"name": "Hosta (Plantain Lily)", name: 'Hosta (Plantain Lily)',
"wordOfFlower": "composure" wordOfFlower: 'composure'
}, },
{ {
"id": 78, id: 78,
"name": "Beautyberry (Callicarpa)", name: 'Beautyberry (Callicarpa)',
"wordOfFlower": "intelligence" wordOfFlower: 'intelligence'
}, },
{ {
"id": 79, id: 79,
"name": "Reed", name: 'Reed',
"wordOfFlower": "faith" wordOfFlower: 'faith'
}, },
{ {
"id": 80, id: 80,
"name": "Foxtail Millet", name: 'Foxtail Millet',
"wordOfFlower": "equality" wordOfFlower: 'equality'
}, },
{ {
"id": 81, id: 81,
"name": "Mint", name: 'Mint',
"wordOfFlower": "virtue" wordOfFlower: 'virtue'
}, },
{ {
"id": 82, id: 82,
"name": "Asparagus Fern", name: 'Asparagus Fern',
"wordOfFlower": "constancy" wordOfFlower: 'constancy'
}, },
{ {
"id": 83, id: 83,
"name": "Silver Grass (Miscanthus)", name: 'Silver Grass (Miscanthus)',
"wordOfFlower": "retirement" wordOfFlower: 'retirement'
}, },
{ {
"id": 84, id: 84,
"name": "Eucalyptus", name: 'Eucalyptus',
"wordOfFlower": "memories" wordOfFlower: 'memories'
}, },
{ {
"id": 85, id: 85,
"name": "Ivy (Hedera)", name: 'Ivy (Hedera)',
"wordOfFlower": "a steadfast heart" wordOfFlower: 'a steadfast heart'
}, },
{ {
"id": 86, id: 86,
"name": "Olive", name: 'Olive',
"wordOfFlower": "peace" wordOfFlower: 'peace'
}, },
{ {
"id": 87, id: 87,
"name": "Mock Orange (Pittosporum tobira)", name: 'Mock Orange (Pittosporum tobira)',
"wordOfFlower": "embrace" wordOfFlower: 'embrace'
}, },
{ {
"id": 88, id: 88,
"name": "Cherry Blossom", name: 'Cherry Blossom',
"wordOfFlower": "spiritual beauty" wordOfFlower: 'spiritual beauty'
}, },
{ {
"id": 89, id: 89,
"name": "Forsythia", name: 'Forsythia',
"wordOfFlower": "hope" wordOfFlower: 'hope'
}, },
{ {
"id": 90, id: 90,
"name": "Plum Blossom (Prunus mume)", name: 'Plum Blossom (Prunus mume)',
"wordOfFlower": "pure heart" wordOfFlower: 'pure heart'
}, },
{ {
"id": 91, id: 91,
"name": "Magnolia", name: 'Magnolia',
"wordOfFlower": "love of nature" wordOfFlower: 'love of nature'
}, },
{ {
"id": 92, id: 92,
"name": "Redbud (Cercis chinensis)", name: 'Redbud (Cercis chinensis)',
"wordOfFlower": "friendship" wordOfFlower: 'friendship'
}, },
{ {
"id": 93, id: 93,
"name": "Flowering Quince (Chaenomeles)", name: 'Flowering Quince (Chaenomeles)',
"wordOfFlower": "trust" wordOfFlower: 'trust'
} }
]; ];

View File

@@ -236,8 +236,7 @@ export function buildBouquetRationale(moodAnalysis, userInput, recipe) {
} }
if (cardMessage && mainFlower) { if (cardMessage && mainFlower) {
const messageRef = const messageRef = cardMessage.length <= 40 ? `your message, "${cardMessage}"` : 'your message';
cardMessage.length <= 40 ? `your message, "${cardMessage}"` : 'your message';
parts.push( parts.push(
`For ${messageRef}, ${mainFlower.name} (${mainFlower.wordOfFlower}) felt like the right fit.` `For ${messageRef}, ${mainFlower.name} (${mainFlower.wordOfFlower}) felt like the right fit.`
); );

View File

@@ -56,7 +56,8 @@ export function getFlowUserInput() {
const input = getFlowObject('userInput'); const input = getFlowObject('userInput');
if (!input) return {}; if (!input) return {};
const { notes: _notes, ...createOnly } = input; const createOnly = { ...input };
delete createOnly.notes;
return createOnly; return createOnly;
} }

View File

@@ -35,5 +35,4 @@ export const LANDING_CYCLE_HOLD_MS = 3000;
const lastStage = LANDING_GROWTH_STAGES[LANDING_GROWTH_STAGES.length - 1]; const lastStage = LANDING_GROWTH_STAGES[LANDING_GROWTH_STAGES.length - 1];
/** 4단계 reveal 완료 + hold 후 다음 사이클까지 */ /** 4단계 reveal 완료 + hold 후 다음 사이클까지 */
export const LANDING_CYCLE_MS = export const LANDING_CYCLE_MS = lastStage.delayMs + LANDING_STAGE_REVEAL_MS + LANDING_CYCLE_HOLD_MS;
lastStage.delayMs + LANDING_STAGE_REVEAL_MS + LANDING_CYCLE_HOLD_MS;

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,8 @@ function pointInPolygon(x, y, polygon) {
const yi = polygon[i].y; const yi = polygon[i].y;
const xj = polygon[j].x; const xj = polygon[j].x;
const yj = polygon[j].y; const yj = polygon[j].y;
const intersects = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi + Number.EPSILON) + xi; const intersects =
yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi + Number.EPSILON) + xi;
if (intersects) inside = !inside; if (intersects) inside = !inside;
} }
return inside; return inside;
@@ -68,11 +69,18 @@ function readJpegDimensions(buffer) {
* @param {string} mimeType * @param {string} mimeType
*/ */
export function readImageDimensions(buffer, mimeType) { export function readImageDimensions(buffer, mimeType) {
if (mimeType.includes('png') || (buffer[0] === 0x89 && buffer.toString('ascii', 1, 4) === 'PNG')) { if (
mimeType.includes('png') ||
(buffer[0] === 0x89 && buffer.toString('ascii', 1, 4) === 'PNG')
) {
return readPngDimensions(buffer); return readPngDimensions(buffer);
} }
if (mimeType.includes('jpeg') || mimeType.includes('jpg') || (buffer[0] === 0xff && buffer[1] === 0xd8)) { if (
mimeType.includes('jpeg') ||
mimeType.includes('jpg') ||
(buffer[0] === 0xff && buffer[1] === 0xd8)
) {
return readJpegDimensions(buffer); return readJpegDimensions(buffer);
} }

View File

@@ -99,12 +99,15 @@ export async function editBouquetImage(sourceImage, editPrompt, options = {}) {
const model = getImageModel(); const model = getImageModel();
/** @type {import('@google/generative-ai').Part[]} */ /** @type {import('@google/generative-ai').Part[]} */
const parts = [{ text: editPrompt }, { const parts = [
inlineData: { { text: editPrompt },
data: sourceImage.base64, {
mimeType: sourceImage.mimeType inlineData: {
data: sourceImage.base64,
mimeType: sourceImage.mimeType
}
} }
}]; ];
if (mask) { if (mask) {
parts.push( parts.push(

View File

@@ -107,8 +107,7 @@ export function mockApplyRecipeEdit(recipe, editPrompt) {
if (!label.toLowerCase().includes(fromToken)) return label; if (!label.toLowerCase().includes(fromToken)) return label;
const colorPrefix = label.match(/^(\w+)\s+/i)?.[1]; const colorPrefix = label.match(/^(\w+)\s+/i)?.[1];
const capitalizedTo = const capitalizedTo = toToken.charAt(0).toUpperCase() + toToken.slice(1).toLowerCase();
toToken.charAt(0).toUpperCase() + toToken.slice(1).toLowerCase();
if (colorPrefix && !fromToken.includes(' ')) { if (colorPrefix && !fromToken.includes(' ')) {
return `${colorPrefix} ${capitalizedTo}`; return `${colorPrefix} ${capitalizedTo}`;

View File

@@ -68,7 +68,9 @@ Rules:
- Budget should be ${budget}.`; - Budget should be ${budget}.`;
const result = await model.generateContent(prompt); const result = await model.generateContent(prompt);
return normalizeRecipeLists(/** @type {BouquetRecipe} */ (parseJsonFromText(result.response.text()))); return normalizeRecipeLists(
/** @type {BouquetRecipe} */ (parseJsonFromText(result.response.text()))
);
} }
/** /**
@@ -144,5 +146,7 @@ Rules:
- The updated recipe is the sole source of truth for the next bouquet image — every listed flower must be included in the image prompt.`; - The updated recipe is the sole source of truth for the next bouquet image — every listed flower must be included in the image prompt.`;
const result = await model.generateContent(prompt); const result = await model.generateContent(prompt);
return normalizeRecipeLists(/** @type {BouquetRecipe} */ (parseJsonFromText(result.response.text()))); return normalizeRecipeLists(
/** @type {BouquetRecipe} */ (parseJsonFromText(result.response.text()))
);
} }

View File

@@ -56,7 +56,10 @@ export async function POST({ request }) {
} }
if (!job.images?.primary) { if (!job.images?.primary) {
return json({ error: 'bouquet image is missing. Generate images first.', code: 'bad_request' }, 400); return json(
{ error: 'bouquet image is missing. Generate images first.', code: 'bad_request' },
400
);
} }
const priorRecipe = normalizeRecipeLists(job.recipe); const priorRecipe = normalizeRecipeLists(job.recipe);
@@ -75,11 +78,7 @@ export async function POST({ request }) {
const provider = getImageProvider(); const provider = getImageProvider();
const mask = const mask =
mode === 'area' && selection.length >= 3 mode === 'area' && selection.length >= 3
? buildAreaEditMask( ? buildAreaEditMask(sourceImage, selection, provider === 'gemini' ? 'gemini' : 'openai')
sourceImage,
selection,
provider === 'gemini' ? 'gemini' : 'openai'
)
: null; : null;
console.log( console.log(

View File

@@ -5,9 +5,7 @@
import Header from '$lib/components/ui/Header.svelte'; import Header from '$lib/components/ui/Header.svelte';
import Artwork from '$lib/components/ui/Artwork/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork/Artwork.svelte';
import ContextForm from '$lib/components/ui/create/ContextForm.svelte'; import ContextForm from '$lib/components/ui/create/ContextForm.svelte';
import FlowContinueBar, { import FlowContinueBar, { FLOW_CONTINUE_BUTTON } from '$lib/components/ui/FlowContinueBar.svelte';
FLOW_CONTINUE_BUTTON
} from '$lib/components/ui/FlowContinueBar.svelte';
import { import {
consumeDevCreateSnapshot, consumeDevCreateSnapshot,
deleteFlowKey, deleteFlowKey,

View File

@@ -3,9 +3,7 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import DescriptionCard from '$lib/components/ui/Artwork/DescriptionCard.svelte'; import DescriptionCard from '$lib/components/ui/Artwork/DescriptionCard.svelte';
import FlowContinueBar, { import FlowContinueBar, { FLOW_CONTINUE_BUTTON } from '$lib/components/ui/FlowContinueBar.svelte';
FLOW_CONTINUE_BUTTON
} from '$lib/components/ui/FlowContinueBar.svelte';
import Header from '$lib/components/ui/Header.svelte'; import Header from '$lib/components/ui/Header.svelte';
import { editImages, fetchJob, finalizeJob, toDataUrl } from '$lib/flowerFlow/api.js'; import { editImages, fetchJob, finalizeJob, toDataUrl } from '$lib/flowerFlow/api.js';
import { buildBriefBouquetTitle } from '$lib/flowerFlow/resolveRecipeFlowers.js'; import { buildBriefBouquetTitle } from '$lib/flowerFlow/resolveRecipeFlowers.js';
@@ -185,9 +183,7 @@
const afterImage = result.images?.primary ?? null; const afterImage = result.images?.primary ?? null;
generatedImage = afterImage; generatedImage = afterImage;
chatMessages = chatMessages.map((message) => chatMessages = chatMessages.map((message) =>
message.id === assistantMessageId message.id === assistantMessageId ? { ...message, status: 'done', afterImage } : message
? { ...message, status: 'done', afterImage }
: message
); );
saveFlow({ saveFlow({
editInstruction: instruction, editInstruction: instruction,
@@ -248,7 +244,7 @@
</script> </script>
{#snippet editableImageFrame(image, editable = false)} {#snippet editableImageFrame(image, editable = false)}
<div class="relative w-full max-w-44 sm:max-w-52 overflow-hidden bg-track ring-1 ring-black/5"> <div class="relative w-full max-w-44 overflow-hidden bg-track ring-1 ring-black/5 sm:max-w-52">
{#if image} {#if image}
<img <img
src={toDataUrl(image)} src={toDataUrl(image)}
@@ -339,8 +335,12 @@
<section <section
class="flex min-h-0 w-full shrink-0 flex-col border-b border-line px-6 py-6 lg:w-[44%] lg:border-r lg:border-b-0 lg:px-10 lg:py-8 lg:pb-12" class="flex min-h-0 w-full shrink-0 flex-col border-b border-line px-6 py-6 lg:w-[44%] lg:border-r lg:border-b-0 lg:px-10 lg:py-8 lg:pb-12"
> >
<div class="mx-auto flex min-h-0 w-full max-w-100 flex-1 flex-col items-center justify-center gap-6"> <div
<div class="w-full max-w-24 overflow-hidden bg-track shadow-sm ring-1 ring-black/5 sm:max-w-28 lg:max-w-75"> class="mx-auto flex min-h-0 w-full max-w-100 flex-1 flex-col items-center justify-center gap-6"
>
<div
class="w-full max-w-24 overflow-hidden bg-track shadow-sm ring-1 ring-black/5 sm:max-w-28 lg:max-w-75"
>
{#if loading} {#if loading}
<div class="aspect-[3/4] w-full animate-pulse bg-placeholder"></div> <div class="aspect-[3/4] w-full animate-pulse bg-placeholder"></div>
{:else if imageSrc} {:else if imageSrc}
@@ -359,9 +359,7 @@
</section> </section>
<section class="relative flex min-h-0 flex-1 flex-col overflow-hidden pb-44 lg:pb-8"> <section class="relative flex min-h-0 flex-1 flex-col overflow-hidden pb-44 lg:pb-8">
<div <div class="mx-auto flex min-h-0 w-full max-w-2xl flex-1 flex-col gap-4 px-6 py-5 lg:py-6">
class="mx-auto flex min-h-0 w-full max-w-2xl flex-1 flex-col gap-4 px-6 py-5 lg:py-6"
>
<div class="shrink-0"> <div class="shrink-0">
<p class="text-xs tracking-[0.2em] text-muted uppercase">Edit bouquet</p> <p class="text-xs tracking-[0.2em] text-muted uppercase">Edit bouquet</p>
<h2 class="mt-1 text-lg">Tell us how you want to refine it.</h2> <h2 class="mt-1 text-lg">Tell us how you want to refine it.</h2>
@@ -430,7 +428,9 @@
</p> </p>
{/if} {/if}
<div class="flex w-full items-center gap-2 rounded-full border border-pill bg-surface py-1.5 pr-1.5 pl-5"> <div
class="flex w-full items-center gap-2 rounded-full border border-pill bg-surface py-1.5 pr-1.5 pl-5"
>
<textarea <textarea
bind:value={prompt} bind:value={prompt}
rows="1" rows="1"

View File

@@ -6,7 +6,11 @@
import Artwork from '$lib/components/ui/Artwork/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork/Artwork.svelte';
import GenerationActivityFeed from '$lib/components/ui/generating/GenerationActivityFeed.svelte'; import GenerationActivityFeed from '$lib/components/ui/generating/GenerationActivityFeed.svelte';
import { buildRecipe, generateImages } from '$lib/flowerFlow/api.js'; import { buildRecipe, generateImages } from '$lib/flowerFlow/api.js';
import { createGenerationProgress, DEFAULT_ESTIMATED_MS, MOCK_ESTIMATED_MS } from '$lib/flowerFlow/generationProgress.js'; import {
createGenerationProgress,
DEFAULT_ESTIMATED_MS,
MOCK_ESTIMATED_MS
} from '$lib/flowerFlow/generationProgress.js';
import { createGeneratingArtworkCycle } from '$lib/flowerFlow/generatingArtworkCycle.js'; import { createGeneratingArtworkCycle } from '$lib/flowerFlow/generatingArtworkCycle.js';
import { import {
clearFlow, clearFlow,

View File

@@ -6,9 +6,7 @@
import Header from '$lib/components/ui/Header.svelte'; import Header from '$lib/components/ui/Header.svelte';
import Artwork from '$lib/components/ui/Artwork/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork/Artwork.svelte';
import MessageForm from '$lib/components/ui/message/MessageForm.svelte'; import MessageForm from '$lib/components/ui/message/MessageForm.svelte';
import FlowContinueBar, { import FlowContinueBar, { FLOW_CONTINUE_BUTTON } from '$lib/components/ui/FlowContinueBar.svelte';
FLOW_CONTINUE_BUTTON
} from '$lib/components/ui/FlowContinueBar.svelte';
import { skipDevImages } from '$lib/flowerFlow/devSeed.js'; import { skipDevImages } from '$lib/flowerFlow/devSeed.js';
import { import {
consumeDevMessageSnapshot, consumeDevMessageSnapshot,
@@ -32,9 +30,7 @@
const artworkVariant = $derived(hasMessage ? 'message1' : 'upload2'); const artworkVariant = $derived(hasMessage ? 'message1' : 'upload2');
const artworkTitle = $derived( const artworkTitle = $derived(hasMessage ? 'Your message' : ARTWORK_CARD_DEFAULTS.message.title);
hasMessage ? 'Your message' : ARTWORK_CARD_DEFAULTS.message.title
);
const artworkDescription = $derived( const artworkDescription = $derived(
hasMessage ? message.trim() : ARTWORK_CARD_DEFAULTS.message.description hasMessage ? message.trim() : ARTWORK_CARD_DEFAULTS.message.description

View File

@@ -5,12 +5,14 @@
import Header from '$lib/components/ui/Header.svelte'; import Header from '$lib/components/ui/Header.svelte';
import Artwork from '$lib/components/ui/Artwork/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork/Artwork.svelte';
import BouquetFlowerCarousel from '$lib/components/ui/result/BouquetFlowerCarousel.svelte'; import BouquetFlowerCarousel from '$lib/components/ui/result/BouquetFlowerCarousel.svelte';
import FlowContinueBar, { import FlowContinueBar, { FLOW_CONTINUE_BUTTON } from '$lib/components/ui/FlowContinueBar.svelte';
FLOW_CONTINUE_BUTTON
} from '$lib/components/ui/FlowContinueBar.svelte';
import { fetchJob, toDataUrl } from '$lib/flowerFlow/api.js'; import { fetchJob, toDataUrl } from '$lib/flowerFlow/api.js';
import { getFlowerImageSrc } from '$lib/flowerFlow/flowerImagePaths.js'; import { getFlowerImageSrc } from '$lib/flowerFlow/flowerImagePaths.js';
import { resolveRecipeFlowers, buildBouquetRationale, buildBriefBouquetTitle } from '$lib/flowerFlow/resolveRecipeFlowers.js'; import {
resolveRecipeFlowers,
buildBouquetRationale,
buildBriefBouquetTitle
} from '$lib/flowerFlow/resolveRecipeFlowers.js';
import { getFlowString } from '$lib/flowerFlow/session.js'; import { getFlowString } from '$lib/flowerFlow/session.js';
let loading = $state(true); let loading = $state(true);
@@ -63,7 +65,9 @@
/> />
<section class="relative flex min-h-0 flex-1 flex-col pb-[3.75rem] lg:overflow-hidden lg:pb-8"> <section class="relative flex min-h-0 flex-1 flex-col pb-[3.75rem] lg:overflow-hidden lg:pb-8">
<div class="flex min-h-0 flex-1 flex-col justify-center overflow-hidden px-6 py-6 lg:px-8 lg:py-8"> <div
class="flex min-h-0 flex-1 flex-col justify-center overflow-hidden px-6 py-6 lg:px-8 lg:py-8"
>
{#if loading} {#if loading}
<p class="text-sm text-muted">Loading result...</p> <p class="text-sm text-muted">Loading result...</p>
{:else if error} {:else if error}

View File

@@ -5,9 +5,7 @@
import Artwork from '$lib/components/ui/Artwork/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork/Artwork.svelte';
import MoodboardGrid from '$lib/components/ui/upload/MoodboardGrid.svelte'; import MoodboardGrid from '$lib/components/ui/upload/MoodboardGrid.svelte';
import SnsFeedUpload from '$lib/components/ui/upload/SnsFeedUpload.svelte'; import SnsFeedUpload from '$lib/components/ui/upload/SnsFeedUpload.svelte';
import FlowContinueBar, { import FlowContinueBar, { FLOW_CONTINUE_BUTTON } from '$lib/components/ui/FlowContinueBar.svelte';
FLOW_CONTINUE_BUTTON
} from '$lib/components/ui/FlowContinueBar.svelte';
import { analyzeMood } from '$lib/flowerFlow/api.js'; import { analyzeMood } from '$lib/flowerFlow/api.js';
import { import {
deleteFlowKey, deleteFlowKey,
@@ -61,12 +59,12 @@
}, },
character: { character: {
title: 'Their character', title: 'Their character',
description: 'A face, a gesture, a presence. Something in them is starting to take floral form.' description:
'A face, a gesture, a presence. Something in them is starting to take floral form.'
}, },
location: { location: {
title: 'A sense of place', title: 'A sense of place',
description: description: 'City grit or quiet coast. Where they belong roots the arrangement in memory.'
'City grit or quiet coast. Where they belong roots the arrangement in memory.'
} }
}; };