3: CSS
Phlo has its own compact CSS syntax: no semicolons, no braces required for single rules, and $variables that compile to CSS custom properties. In this chapter you give the poll a dark card layout and a small theme, in a dedicated style file.
3.1: A style file
Style can live in any .phlo file, but a dedicated file keeps things tidy. Create poll.style.phlo:
<style ns=app>
body {
margin: 0
background: #0d0f12
font-family: system-ui, sans-serif
}
main.poll {
max-width: 560px
margin: 8vh auto
padding: 0 24px
}
</style>
The ns=app namespace tells the build which bundle this CSS belongs to; everything in the app namespace is compiled into www/app.css, which view() links automatically. ns=app is also the default, but writing it out keeps larger apps readable.
Reload http://localhost/poll: centered column, dark background. The build ran automatically on the request and regenerated app.css.
3.2: One declaration per line
The CSS parser treats every line as one complete declaration, and the colon does double duty as both selector nesting and property separator:
.card {
background: #16181d
border-radius: 12px
padding: 24px
margin-bottom: 16px
}
h1: margin: 0 0 24px
.card: p: line-height: 1.6em
h1: margin: 0 0 24px is a complete rule on one line. .card: p: ... nests: it compiles to .card p { line-height: 1.6em; }. Never wrap a value across lines unless you end the property line with a bare : or end each continuation line with a comma; anything else is a build error.
Add the .card block and the h1 line to poll.style.phlo and reload: the buttons now sit in a card.
3.3: Theme variables
$name in a style block becomes the CSS custom property --name, and every place you use it becomes var(--name). Define the theme once in :root and use it everywhere. This is the full poll.style.phlo for the rest of the tutorial:
<style ns=app>
:root {
$text: #f4f4f5
$surface: #16181d
$primary: #ff4a00
$border: #2a2e36
$muted: #9aa0aa
}
body {
margin: 0
background: #0d0f12
color: $text
font-family: system-ui, sans-serif
}
main.poll {
max-width: 560px
margin: 8vh auto
padding: 0 24px
}
h1: margin: 0 0 24px
.card {
background: $surface
border: 1px solid $border
border-radius: 12px
padding: 24px
margin-bottom: 16px
}
form: display: inline
button {
background: $primary
color: $text
border: none
border-radius: 8px
padding: 10px 18px
margin-right: 8px
cursor: pointer
}
</style>
Five variables carry the whole theme: $text, $surface, $primary, $border, and $muted (you use $muted in the next chapter for the vote counts). Want a light theme later? Change five lines in :root.
3.4: Check the output
Look at what the compiler produced:
docker run --rm -v $(pwd)/app:/app ghcr.io/q-ainl/phlo cat /app/www/app.css
You see regular CSS: :root { --text: #f4f4f5; ... }, button { background: var(--primary); ... }. Phlo writes the semicolons, the braces, and the var() wrappers; you write one declaration per line.
Reload http://localhost/poll: a dark card with the question and four orange buttons. The page looks like a poll now. It just cannot count yet.