@import "tailwindcss"; /* Petal design tokens — soft, warm, bubbly stationery aesthetic. Defined in @theme so they generate Tailwind utilities (bg-bg, text-plum, rounded-card, font-ui, etc.). See petal-spec.md → Design System. */ @theme { /* Palette */ --color-bg: #FDF6F0; /* warm cream canvas */ --color-surface: #FFFFFF; /* card/panel surfaces */ --color-surface-alt: #FFF0F5; /* rose-tinted alt surface */ --color-border: #F0E0EB; /* soft pink-grey border */ --color-plum: #3D2E39; /* warm dark plum text (not harsh black) */ --color-muted: #9B8CA3; /* muted lavender-grey */ --color-accent: #E8A0BF; /* soft rose — primary interactive */ --color-accent-hover: #D98AAF;/* deeper rose on hover */ /* Suggestion type colors */ --color-mint: #A8D8C8; /* grammar */ --color-peach: #F4B8A0; /* phrasing */ --color-lavender: #C5B4E8; /* idiom */ --color-sky: #A8CCE8; /* clarity */ --color-honey: #CE9B4F; /* voice */ --color-success: #8FCFA8; /* saved / accepted */ /* Typography */ --font-ui: "Nunito", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; --font-body: "Lora", Georgia, serif; --font-mono: "JetBrains Mono", ui-monospace, monospace; /* Shape language */ --radius-card: 16px; --radius-modal: 24px; --radius-pill: 999px; --radius-input: 12px; /* Soft, warm, lifted shadow */ --shadow-soft: 0 4px 20px rgba(180, 130, 160, 0.12); } html, body, #root { height: 100%; } body { margin: 0; background: var(--color-bg); color: var(--color-plum); font-family: var(--font-ui); -webkit-font-smoothing: antialiased; } /* Gentle, consistent motion across interactive elements */ button, a, input { transition: all 200ms ease; } /* Editor body — serif Lora for prose, warm plum ink, roomy line height. The title and headings use the Nunito UI face for contrast. */ .petal-prose { font-family: var(--font-body); font-size: 1.125rem; line-height: 1.75; color: var(--color-plum); } .petal-prose > * + * { margin-top: 0.9em; } .petal-prose h1, .petal-prose h2, .petal-prose h3 { font-family: var(--font-ui); font-weight: 800; line-height: 1.3; } .petal-prose h1 { font-size: 1.6em; } .petal-prose h2 { font-size: 1.3em; } .petal-prose h3 { font-size: 1.1em; } .petal-prose ul, .petal-prose ol { padding-left: 1.4em; } .petal-prose ul { list-style: disc; } .petal-prose ol { list-style: decimal; } .petal-prose a { color: var(--color-accent-hover); text-decoration: underline; } .petal-prose blockquote { border-left: 3px solid var(--color-border); padding-left: 1em; color: var(--color-muted); font-style: italic; } .petal-prose code { font-family: var(--font-mono); font-size: 0.9em; background: var(--color-surface-alt); padding: 0.1em 0.35em; border-radius: 6px; } /* Placeholder shown on the empty first paragraph (Tiptap Placeholder ext). */ .petal-prose p.is-editor-empty:first-child::before { content: attr(data-placeholder); color: var(--color-muted); float: left; height: 0; pointer-events: none; } /* --- Suggestion decorations ------------------------------------------------- Inline highlights anchored by string at render time (not stored marks). Each type gets a soft underline in its palette color; hovering opens its card. */ .petal-suggestion { border-bottom: 2px solid transparent; border-radius: 2px; cursor: pointer; transition: background 200ms ease; /* gentle fade + slight upward float as decorations appear */ animation: petal-suggestion-in 260ms ease both; } .petal-suggestion:hover { background: var(--color-surface-alt); } .petal-suggestion-grammar { border-bottom-color: var(--color-mint); } .petal-suggestion-phrasing { border-bottom-color: var(--color-peach); } .petal-suggestion-idiom { border-bottom-color: var(--color-lavender); } .petal-suggestion-clarity { border-bottom-color: var(--color-sky); } .petal-suggestion-voice { border-bottom-color: var(--color-honey); } @keyframes petal-suggestion-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } .petal-suggestion-card { animation: petal-suggestion-in 200ms ease both; } /* --- Spell check ------------------------------------------------------------ Browser-side nspell flags misspellings with a soft rose wavy underline (a gentler take on the classic red squiggle, to fit the pastel palette). Like the suggestion layer these are ProseMirror decorations, never stored marks. Clicking a flagged word opens its MisspellCard with corrections. */ .petal-misspelling { cursor: pointer; text-decoration: underline wavy var(--color-accent); text-decoration-skip-ink: none; text-underline-offset: 2px; } .petal-misspelling:hover { background: var(--color-surface-alt); border-radius: 2px; } .petal-misspell-card { animation: petal-suggestion-in 200ms ease both; } /* --- Accept confetti -------------------------------------------------------- A tiny CSS-only burst played where a suggestion is accepted: four colored dots spray up-and-out, then fade. No JS animation — each dot reads its direction from --dx/--dy custom properties set inline. (Spec → Signature.) */ .petal-confetti { width: 0; height: 0; } .petal-confetti-dot { position: absolute; left: 0; top: 0; width: 7px; height: 7px; border-radius: var(--radius-pill); animation: petal-confetti 680ms cubic-bezier(0.2, 0.7, 0.3, 1) forwards; } @keyframes petal-confetti { 0% { transform: translate(0, 0) scale(0.3); opacity: 0; } 18% { opacity: 1; } 100% { transform: translate(var(--dx), var(--dy)) scale(1); opacity: 0; } } /* --- Distraction-free mode --------------------------------------------------- The doc-list sidebar slides left and collapses to zero width; the editor canvas (centered, max-width) re-centers into the full pane. Width + transform animate together for a smooth slide. (Spec → Distraction-free mode.) */ .petal-sidebar { width: 260px; overflow: hidden; transition: width 280ms ease, transform 280ms ease, opacity 200ms ease; } .petal-sidebar-hidden { width: 0; transform: translateX(-24px); opacity: 0; pointer-events: none; } /* --- Companion kitten ------------------------------------------------------- The cozy corner mascot. Gently bobs while awake, settles and sways slowly while napping; its speech bubble pops in; little zzz drift up when asleep. */ .petal-companion { animation: petal-bob 3.2s ease-in-out infinite; transition: transform 200ms ease; } .petal-companion:hover { transform: translateY(-2px) scale(1.04); } .petal-companion-sleep { animation: petal-bob-slow 5s ease-in-out infinite; } @keyframes petal-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } } @keyframes petal-bob-slow { 0%, 100% { transform: translateY(0) rotate(-1deg); } 50% { transform: translateY(-2px) rotate(1deg); } } .petal-bubble { animation: petal-bubble-in 240ms cubic-bezier(0.2, 0.8, 0.3, 1.2) both; transform-origin: bottom right; } @keyframes petal-bubble-in { from { opacity: 0; transform: translateY(6px) scale(0.92); } to { opacity: 1; transform: translateY(0) scale(1); } } .petal-zzz { top: 6px; right: 14px; font-weight: 800; font-size: 1.1rem; animation: petal-zzz 2.4s ease-in-out infinite; } @keyframes petal-zzz { 0% { opacity: 0; transform: translateY(0) scale(0.8); } 30% { opacity: 0.9; } 100% { opacity: 0; transform: translateY(-14px) scale(1.1); } } /* Blinking caret in the Ask Petal bubble while awaiting the first token. */ .petal-chat-caret { animation: petal-breathe 1s ease-in-out infinite; color: var(--color-accent); } /* Breathing rose dot shown in the StatusBar while a checkpoint runs. */ .petal-checkpoint-dot { animation: petal-breathe 2s ease-in-out infinite; } @keyframes petal-breathe { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }