Flying Stable Design Guide¶
Design decisions and patterns established during the UI redesign session (2026-03-31).
Branding¶
App name: Flying Stable (Pegasus/pony theme for the Django desktop starter)
Logo: Custom Pegasus SVG, single-color, inline in the topnav using CSS
currentColorSections: “My Ponies” (CRUD demo), “Stable Routines” (background tasks demo)
Item statuses: Grazing (backlog), Galloping (active), Show Ready (done)
Form labels: Name, Personality, Status
Themed messages: “Your pony needs a name.”, “Do you know nothing about your pony?”, “Release All Ponies”, “Starts a simulated stable routine for the pony crew”, “No routines underway. Start a routine to see the stable crew at work.”
Color System¶
All colors are CSS custom properties defined in :root in app.css. No hardcoded hex values outside :root.
Token |
Value |
Usage |
|---|---|---|
|
|
Primary teal, table headers, edit actions |
|
|
Nav links, logo, focus rings, active states |
|
|
Page header background, title color in tables |
|
|
Topnav and footer background |
|
|
Primary action buttons (amber-orange, tuned to match header image) |
|
|
Hover state for primary buttons |
|
|
Delete/destructive actions (pinkish-red, deliberately not aggressive) |
|
|
Hover state for danger elements |
|
|
Galloping status badge |
|
|
Galloping badge text |
|
|
Page background |
|
|
Panel/card background |
|
|
Primary text |
|
|
Secondary/muted text |
|
|
Borders and separators |
Layout Structure¶
+--[ Topnav (dark) ]------------------------------------------+
| Logo FLYING STABLE My Ponies Routines [Button] |
+--[ 2px teal-bright border ]----------------------------------+
+--[ Page Header (teal-dark, 30vh, optional bg image) ]--------+
| Centered H1 |
+--------------------------------------------------------------+
+--[ Panel (white card, 1.5rem padding) ]------------------+
| [hint text] [Action Button] |
|----------------------------------------------------------|
| [HEADER BAR - full width gray background] |
| Name Status Personality Updated |
|----------------------------------------------------------|
| Content rows with indented separators |
+----------------------------------------------------------+
+--[ Footer (dark, sticky) ]-----------------------------------+
| Desktop Django Starter 2026 |
+--------------------------------------------------------------+
Key measurements¶
Topnav padding:
0.75rem 1.25remPage header:
min-height: 30vh, H1 font-size:clamp(3.5rem, 9vw, 5rem)Panel padding:
1.5rem, bottom:2.25remPanel toolbar: negative margin to span full panel width,
1.5rempadding top and bottomTable: full panel width via negative margins, cell padding
1rem, first/last cell padding1.5remLogo:
4remwithmargin: -1rem 0to extend beyond topnavFont: Play (Google Fonts, weights 400 and 700 only)
Design Patterns¶
Empty States¶
Centered SVG illustration with descriptive text below. Both illustrations follow the same visual language:
Opacity layers: 0.18 (back element), 0.35 (middle), 0.6 (front)
Accent circle (bottom-right): r=36, stroke opacity 0.2, symbol fill opacity 0.35
My Ponies: Stacked document icons with X-in-circle
Stable Routines: Three interlocking gears with play-in-circle
Illustration CSS width: 280px (items), 235px (tasks, with
margin-top: -1rem)
Status Badges¶
Inline colored badges with matching text and background:
Grazing: gray text on light gray (
rgba(0,0,0,0.06))Galloping: amber text on light amber (
rgba(212,148,10,0.12))Show Ready: teal text on light teal (
rgba(16,141,130,0.1))
Delete Modal¶
In-page overlay instead of separate page. Fetch-based POST with CSRF token from cookie. Accessible: role="dialog", aria-modal="true", Escape key closes, focus lands on cancel button.
Form Validation¶
Custom client-side validation with novalidate on the form. Inline tooltip appears below the field with:
Warning triangle SVG icon
Pink background (
rgba(194,75,90,0.08))Small upward-pointing connector triangle
justify-self: startto prevent full-width stretchDisappears on input
Table Rows¶
Row separators use
::afterpseudo-elements, indented1.5remfrom both sidesLast row has no separator
Header bar spans full panel width with gray background (
--bg-page)vertical-align: topon all cellsTitle column:
max-width: 14rem, bold,--teal-darkcolorNotes column: muted color,
max-width: 20rem, truncated to 20 wordsDate column: right-aligned, date and time on separate lines
Actions: Edit (pencil) + Delete (X-in-circle) icons, 16px, muted gray, colored on hover
Header Background Images¶
Per-page via {% block header_class %} in base template. Use CSS background-image with a semi-transparent overlay for text readability:
background-image: linear-gradient(rgba(10, 84, 78, 0.3), rgba(10, 84, 78, 0.3)), url('...');
background-size: cover;
background-position: 20% 45%;
Development Tooling¶
Auto-Reload¶
django-browser-reload is configured in local.py only. CSS changes trigger automatic browser reload. Template changes may need Cmd+Shift+R.
Screenshots¶
Playwright is available for automated screenshots:
from playwright.sync_api import sync_playwright
# Use wait_until='domcontentloaded' (not 'networkidle' — browser-reload SSE blocks it)
page.goto('http://127.0.0.1:8000', wait_until='domcontentloaded')
page.wait_for_timeout(1000)
page.screenshot(path='/tmp/screenshot.png')
SVG Optimization¶
svgo is available via Homebrew for optimizing SVG files.
Splash Screen¶
Available at /splash/ and now wired into Electron startup. Standalone HTML with:
Breathing logo animation
Three bouncing dots
“Saddling up…” status text
Dark background, teal-bright color scheme
Reused by Electron during backend startup before the main window is ready
Still separate from Tauri’s shell-local splash window and Positron’s current startup flow