diff --git a/.tmp/2026-09-03-css-polish/__probe.html b/.tmp/2026-09-03-css-polish/__probe.html new file mode 100644 index 0000000..a71364a --- /dev/null +++ b/.tmp/2026-09-03-css-polish/__probe.html @@ -0,0 +1,21 @@ + + + +probe + + diff --git a/.tmp/2026-09-03-css-polish/after/art6-390.png b/.tmp/2026-09-03-css-polish/after/art6-390.png new file mode 100644 index 0000000..b68c977 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/art6-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/art6.png b/.tmp/2026-09-03-css-polish/after/art6.png new file mode 100644 index 0000000..5fce24b Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/art6.png differ diff --git a/.tmp/2026-09-03-css-polish/after/artwomen-1280.png b/.tmp/2026-09-03-css-polish/after/artwomen-1280.png new file mode 100644 index 0000000..0fe9cb4 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/artwomen-1280.png differ diff --git a/.tmp/2026-09-03-css-polish/after/artwomen-390.png b/.tmp/2026-09-03-css-polish/after/artwomen-390.png new file mode 100644 index 0000000..c3d1cb1 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/artwomen-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/artwomen.png b/.tmp/2026-09-03-css-polish/after/artwomen.png new file mode 100644 index 0000000..9e09c64 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/artwomen.png differ diff --git a/.tmp/2026-09-03-css-polish/after/dashboard-480.png b/.tmp/2026-09-03-css-polish/after/dashboard-480.png new file mode 100644 index 0000000..1b66b9f Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/dashboard-480.png differ diff --git a/.tmp/2026-09-03-css-polish/after/dashboard.png b/.tmp/2026-09-03-css-polish/after/dashboard.png new file mode 100644 index 0000000..b8c6b57 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/dashboard.png differ diff --git a/.tmp/2026-09-03-css-polish/after/hdr-640.png b/.tmp/2026-09-03-css-polish/after/hdr-640.png new file mode 100644 index 0000000..82611e1 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/hdr-640.png differ diff --git a/.tmp/2026-09-03-css-polish/after/home-390.png b/.tmp/2026-09-03-css-polish/after/home-390.png new file mode 100644 index 0000000..7c98577 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/home-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/home.png b/.tmp/2026-09-03-css-polish/after/home.png new file mode 100644 index 0000000..3d9d078 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/home.png differ diff --git a/.tmp/2026-09-03-css-polish/after/lead-1025.png b/.tmp/2026-09-03-css-polish/after/lead-1025.png new file mode 100644 index 0000000..8e5f8b1 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/lead-1025.png differ diff --git a/.tmp/2026-09-03-css-polish/after/lead-1440.png b/.tmp/2026-09-03-css-polish/after/lead-1440.png new file mode 100644 index 0000000..8b507a7 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/lead-1440.png differ diff --git a/.tmp/2026-09-03-css-polish/after/lead-640.png b/.tmp/2026-09-03-css-polish/after/lead-640.png new file mode 100644 index 0000000..82611e1 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/lead-640.png differ diff --git a/.tmp/2026-09-03-css-polish/after/lead-700.png b/.tmp/2026-09-03-css-polish/after/lead-700.png new file mode 100644 index 0000000..d83b1c1 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/lead-700.png differ diff --git a/.tmp/2026-09-03-css-polish/after/lead-768.png b/.tmp/2026-09-03-css-polish/after/lead-768.png new file mode 100644 index 0000000..55182d5 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/lead-768.png differ diff --git a/.tmp/2026-09-03-css-polish/after/lead-940.png b/.tmp/2026-09-03-css-polish/after/lead-940.png new file mode 100644 index 0000000..2fcaa97 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/lead-940.png differ diff --git a/.tmp/2026-09-03-css-polish/after/login-390.png b/.tmp/2026-09-03-css-polish/after/login-390.png new file mode 100644 index 0000000..2530593 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/login-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/login.png b/.tmp/2026-09-03-css-polish/after/login.png new file mode 100644 index 0000000..ff92b03 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/login.png differ diff --git a/.tmp/2026-09-03-css-polish/after/news-1025.png b/.tmp/2026-09-03-css-polish/after/news-1025.png new file mode 100644 index 0000000..9f43ee7 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/news-1025.png differ diff --git a/.tmp/2026-09-03-css-polish/after/news-1100.png b/.tmp/2026-09-03-css-polish/after/news-1100.png new file mode 100644 index 0000000..96586f3 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/news-1100.png differ diff --git a/.tmp/2026-09-03-css-polish/after/news-390.png b/.tmp/2026-09-03-css-polish/after/news-390.png new file mode 100644 index 0000000..61b95b4 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/news-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/news-768.png b/.tmp/2026-09-03-css-polish/after/news-768.png new file mode 100644 index 0000000..d531589 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/news-768.png differ diff --git a/.tmp/2026-09-03-css-polish/after/news.png b/.tmp/2026-09-03-css-polish/after/news.png new file mode 100644 index 0000000..0762c84 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/news.png differ diff --git a/.tmp/2026-09-03-css-polish/after/nf-390.png b/.tmp/2026-09-03-css-polish/after/nf-390.png new file mode 100644 index 0000000..9ac8665 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/nf-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/nf.png b/.tmp/2026-09-03-css-polish/after/nf.png new file mode 100644 index 0000000..9c79cf7 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/nf.png differ diff --git a/.tmp/2026-09-03-css-polish/after/pag-360.png b/.tmp/2026-09-03-css-polish/after/pag-360.png new file mode 100644 index 0000000..41fe496 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/pag-360.png differ diff --git a/.tmp/2026-09-03-css-polish/after/privacy-390.png b/.tmp/2026-09-03-css-polish/after/privacy-390.png new file mode 100644 index 0000000..3d293bb Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/privacy-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/privacy.png b/.tmp/2026-09-03-css-polish/after/privacy.png new file mode 100644 index 0000000..4e2f337 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/privacy.png differ diff --git a/.tmp/2026-09-03-css-polish/after/proposals-390.png b/.tmp/2026-09-03-css-polish/after/proposals-390.png new file mode 100644 index 0000000..f27e216 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/proposals-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/proposals.png b/.tmp/2026-09-03-css-polish/after/proposals.png new file mode 100644 index 0000000..c0c9f9e Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/proposals.png differ diff --git a/.tmp/2026-09-03-css-polish/after/search-390.png b/.tmp/2026-09-03-css-polish/after/search-390.png new file mode 100644 index 0000000..0e88265 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/search-390.png differ diff --git a/.tmp/2026-09-03-css-polish/after/search.png b/.tmp/2026-09-03-css-polish/after/search.png new file mode 100644 index 0000000..37638eb Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/search.png differ diff --git a/.tmp/2026-09-03-css-polish/after/support-360.png b/.tmp/2026-09-03-css-polish/after/support-360.png new file mode 100644 index 0000000..538ea76 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/support-360.png differ diff --git a/.tmp/2026-09-03-css-polish/after/support.png b/.tmp/2026-09-03-css-polish/after/support.png new file mode 100644 index 0000000..88f1742 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/after/support.png differ diff --git a/.tmp/2026-09-03-css-polish/before/art6-390-pagination.png b/.tmp/2026-09-03-css-polish/before/art6-390-pagination.png new file mode 100644 index 0000000..d33a0f4 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/art6-390-pagination.png differ diff --git a/.tmp/2026-09-03-css-polish/before/art6-390-tall.png b/.tmp/2026-09-03-css-polish/before/art6-390-tall.png new file mode 100644 index 0000000..a963510 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/art6-390-tall.png differ diff --git a/.tmp/2026-09-03-css-polish/before/art6-390.png b/.tmp/2026-09-03-css-polish/before/art6-390.png new file mode 100644 index 0000000..b68c977 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/art6-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/art6-pagination.png b/.tmp/2026-09-03-css-polish/before/art6-pagination.png new file mode 100644 index 0000000..776e66c Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/art6-pagination.png differ diff --git a/.tmp/2026-09-03-css-polish/before/art6-tall.png b/.tmp/2026-09-03-css-polish/before/art6-tall.png new file mode 100644 index 0000000..776e66c Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/art6-tall.png differ diff --git a/.tmp/2026-09-03-css-polish/before/art6.png b/.tmp/2026-09-03-css-polish/before/art6.png new file mode 100644 index 0000000..5fce24b Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/art6.png differ diff --git a/.tmp/2026-09-03-css-polish/before/artwomen-1280.png b/.tmp/2026-09-03-css-polish/before/artwomen-1280.png new file mode 100644 index 0000000..0fe9cb4 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/artwomen-1280.png differ diff --git a/.tmp/2026-09-03-css-polish/before/artwomen-390.png b/.tmp/2026-09-03-css-polish/before/artwomen-390.png new file mode 100644 index 0000000..797cf85 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/artwomen-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/artwomen.png b/.tmp/2026-09-03-css-polish/before/artwomen.png new file mode 100644 index 0000000..9e09c64 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/artwomen.png differ diff --git a/.tmp/2026-09-03-css-polish/before/dashboard-480.png b/.tmp/2026-09-03-css-polish/before/dashboard-480.png new file mode 100644 index 0000000..efb72b3 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/dashboard-480.png differ diff --git a/.tmp/2026-09-03-css-polish/before/dashboard.png b/.tmp/2026-09-03-css-polish/before/dashboard.png new file mode 100644 index 0000000..d701792 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/dashboard.png differ diff --git a/.tmp/2026-09-03-css-polish/before/hdr-1025.png b/.tmp/2026-09-03-css-polish/before/hdr-1025.png new file mode 100644 index 0000000..e79e781 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/hdr-1025.png differ diff --git a/.tmp/2026-09-03-css-polish/before/hdr-1100.png b/.tmp/2026-09-03-css-polish/before/hdr-1100.png new file mode 100644 index 0000000..f504322 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/hdr-1100.png differ diff --git a/.tmp/2026-09-03-css-polish/before/hdr-1200.png b/.tmp/2026-09-03-css-polish/before/hdr-1200.png new file mode 100644 index 0000000..5221b80 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/hdr-1200.png differ diff --git a/.tmp/2026-09-03-css-polish/before/hdr-640.png b/.tmp/2026-09-03-css-polish/before/hdr-640.png new file mode 100644 index 0000000..755281e Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/hdr-640.png differ diff --git a/.tmp/2026-09-03-css-polish/before/home-390.png b/.tmp/2026-09-03-css-polish/before/home-390.png new file mode 100644 index 0000000..0341a0d Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/home-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/home.png b/.tmp/2026-09-03-css-polish/before/home.png new file mode 100644 index 0000000..8fe4d3d Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/home.png differ diff --git a/.tmp/2026-09-03-css-polish/before/login-390.png b/.tmp/2026-09-03-css-polish/before/login-390.png new file mode 100644 index 0000000..98ba9b6 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/login-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/login.png b/.tmp/2026-09-03-css-polish/before/login.png new file mode 100644 index 0000000..cc99bdf Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/login.png differ diff --git a/.tmp/2026-09-03-css-polish/before/news-390.png b/.tmp/2026-09-03-css-polish/before/news-390.png new file mode 100644 index 0000000..61b95b4 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/news-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/news-768.png b/.tmp/2026-09-03-css-polish/before/news-768.png new file mode 100644 index 0000000..a554b2f Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/news-768.png differ diff --git a/.tmp/2026-09-03-css-polish/before/news.png b/.tmp/2026-09-03-css-polish/before/news.png new file mode 100644 index 0000000..75576f2 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/news.png differ diff --git a/.tmp/2026-09-03-css-polish/before/nf-390.png b/.tmp/2026-09-03-css-polish/before/nf-390.png new file mode 100644 index 0000000..e52751f Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/nf-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/nf.png b/.tmp/2026-09-03-css-polish/before/nf.png new file mode 100644 index 0000000..656c64f Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/nf.png differ diff --git a/.tmp/2026-09-03-css-polish/before/pag-360.png b/.tmp/2026-09-03-css-polish/before/pag-360.png new file mode 100644 index 0000000..136255f Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/pag-360.png differ diff --git a/.tmp/2026-09-03-css-polish/before/pag-390.png b/.tmp/2026-09-03-css-polish/before/pag-390.png new file mode 100644 index 0000000..fc1bc51 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/pag-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/pag-480.png b/.tmp/2026-09-03-css-polish/before/pag-480.png new file mode 100644 index 0000000..fb89836 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/pag-480.png differ diff --git a/.tmp/2026-09-03-css-polish/before/privacy-390.png b/.tmp/2026-09-03-css-polish/before/privacy-390.png new file mode 100644 index 0000000..f29e97c Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/privacy-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/privacy.png b/.tmp/2026-09-03-css-polish/before/privacy.png new file mode 100644 index 0000000..25f3d21 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/privacy.png differ diff --git a/.tmp/2026-09-03-css-polish/before/proposals-390.png b/.tmp/2026-09-03-css-polish/before/proposals-390.png new file mode 100644 index 0000000..8665aa9 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/proposals-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/proposals.png b/.tmp/2026-09-03-css-polish/before/proposals.png new file mode 100644 index 0000000..c1c5a52 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/proposals.png differ diff --git a/.tmp/2026-09-03-css-polish/before/search-390.png b/.tmp/2026-09-03-css-polish/before/search-390.png new file mode 100644 index 0000000..a432562 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/search-390.png differ diff --git a/.tmp/2026-09-03-css-polish/before/search.png b/.tmp/2026-09-03-css-polish/before/search.png new file mode 100644 index 0000000..37638eb Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/search.png differ diff --git a/.tmp/2026-09-03-css-polish/before/support-360.png b/.tmp/2026-09-03-css-polish/before/support-360.png new file mode 100644 index 0000000..130af12 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/support-360.png differ diff --git a/.tmp/2026-09-03-css-polish/before/support.png b/.tmp/2026-09-03-css-polish/before/support.png new file mode 100644 index 0000000..2f2818e Binary files /dev/null and b/.tmp/2026-09-03-css-polish/before/support.png differ diff --git a/.tmp/2026-09-03-css-polish/probe/frame390.png b/.tmp/2026-09-03-css-polish/probe/frame390.png new file mode 100644 index 0000000..7e6cfb1 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/probe/frame390.png differ diff --git a/.tmp/2026-09-03-css-polish/probe/new-390x2000.png b/.tmp/2026-09-03-css-polish/probe/new-390x2000.png new file mode 100644 index 0000000..a3f6aa3 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/probe/new-390x2000.png differ diff --git a/.tmp/2026-09-03-css-polish/probe/new-390x900.png b/.tmp/2026-09-03-css-polish/probe/new-390x900.png new file mode 100644 index 0000000..3bc8f3b Binary files /dev/null and b/.tmp/2026-09-03-css-polish/probe/new-390x900.png differ diff --git a/.tmp/2026-09-03-css-polish/probe/old-390x900.png b/.tmp/2026-09-03-css-polish/probe/old-390x900.png new file mode 100644 index 0000000..3bc8f3b Binary files /dev/null and b/.tmp/2026-09-03-css-polish/probe/old-390x900.png differ diff --git a/.tmp/2026-09-03-css-polish/probe/p390-scroll.png b/.tmp/2026-09-03-css-polish/probe/p390-scroll.png new file mode 100644 index 0000000..b56f0c9 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/probe/p390-scroll.png differ diff --git a/.tmp/2026-09-03-css-polish/probe/p500.png b/.tmp/2026-09-03-css-polish/probe/p500.png new file mode 100644 index 0000000..f8cae89 Binary files /dev/null and b/.tmp/2026-09-03-css-polish/probe/p500.png differ diff --git a/.tmp/2026-09-03-css-polish/shoot.sh b/.tmp/2026-09-03-css-polish/shoot.sh new file mode 100755 index 0000000..86ee267 --- /dev/null +++ b/.tmp/2026-09-03-css-polish/shoot.sh @@ -0,0 +1,45 @@ +#!/bin/zsh +# Screenshot helper for the CSS polish pass. $1 = output dir (before|after) +# Narrow widths go through dist/__probe.html (a fixed-width iframe): headless +# Chrome clamps --window-size below ~500px, so 360/390/480 shots would silently +# be 500px-wide renders cropped to the window. +set -e +CH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +OUT="$(cd "$(dirname "$0")" && pwd)/$1" +mkdir -p "$OUT" +cp "$(dirname "$0")/__probe.html" "$ROOT/dist/__probe.html" +shot() { # name url w h + "$CH" --headless=new --disable-gpu --hide-scrollbars --window-size=$3,$4 \ + --screenshot="$OUT/$1.png" "$2" >/dev/null 2>&1 +} +wide() { shot "$1" "http://localhost:4330$2" $3 $4; } # name path w h +narrow() { # name path w h (h = iframe height) + shot "$1" "http://localhost:4330/__probe.html?w=$3&h=$4&p=$2" $(($3 + 20)) $(($4 + 10)) +} +W='/news/ctao-and-cabildo-of-la-palma-organise-women-of-ctao-2026' +wide home "/" 1440 2600 +narrow home-390 "/" 390 2200 +wide news "/news" 1440 2600 +narrow news-390 "/news" 390 2400 +wide news-768 "/news" 768 2200 +wide art6 "/news/6" 1440 2600 +narrow art6-390 "/news/6" 390 2600 +wide artwomen "$W" 1440 2600 +narrow artwomen-390 "$W" 390 2600 +wide artwomen-1280 "$W" 1280 2000 +wide search "/search?q=lst" 1440 2000 +narrow search-390 "/search?q=lst" 390 1800 +wide support "/support" 1440 1800 +narrow support-360 "/support" 360 1500 +wide privacy "/pages/privacy" 1440 1400 +narrow privacy-390 "/pages/privacy" 390 1500 +wide nf "/404-nonexistent" 1440 1200 +narrow nf-390 "/404-nonexistent" 390 1300 +wide proposals "/proposals" 1440 1600 +narrow proposals-390 "/proposals" 390 1700 +wide dashboard "/dashboard" 1440 1600 +narrow dashboard-480 "/dashboard" 480 1900 +wide login "/login" 1440 1200 +narrow login-390 "/login" 390 1100 +echo "shots in $OUT" diff --git a/DESIGN.md b/DESIGN.md index c281ca5..0a4990c 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,337 +1,32 @@ -# CTAO Science Portal — design system +# Design handoff -Single source of truth for look-and-feel. All values live as tokens in -`src/styles/global.css`; this file states the rules. Brand basis: CTAO Brand -Guidelines (Apr 2024) + techniques observed on ctao.org (photography-led hero, -nebula motion, generous spacing, 15/30/60 rounding, quiet-fade hovers). -No frameworks, no JS for presentation. +All styling lives in **`src/styles/global.css`** — design tokens in `:root` +(colors, type scale, spacing, radius, shadows, `--header-h`) + plain-CSS +components below them. No frameworks, no preprocessors, no runtime JS for +presentation. Pages are `.astro` templates (plain HTML). -## Color tokens (brand-fixed — never add hues) +## Brand (official: CTAO Brand Guidelines, April 2024 — PDF in the project docs) -| Token | Value | Use | -|---|---|---| -| `--galaxy` | `#00004A` | Headings, header/footer bands, hero scrim | -| `--cherenkov` | `#00E4D8` | ONLY: primary CTA, flash, hero subtitle, logo cluster (+ functional: ``, TOC active rule). Never small text on light bg | -| `--moon` | `#F5F5F5` | Utility surfaces (bands, neutral hovers) | -| `--azure` | `#007AFF` | Focus rings and field-focus borders ONLY (no hover borders) | -| `--indigo` | `#00009C` | Gradient depth, link hover | -| `--text` / `--muted` / `--border` / `--link` | derived | Body ink; `--link #0057C2` is azure darkened to pass AA | +- Colors: Galaxy Blue `#00004A`, Cherenkov Blue `#00E4D8`, Moon Gray + `#F5F5F5`, Cosmic Azure `#007AFF` (links/focus), Interstellar Indigo + `#00009C`. Cherenkov is an ACCENT (brand book rations it — currently: + primary CTA, hero subtitle, logo flash); it fails AA as text on white. +- Type: **Inter** for everything, **Space Grotesk** (weight 500) only for + communicative headlines (h1/h2). Sizes come from the `--fs-*` scale. +- Logo files in `public/brand/`; always "CTAO", min 100px wide, no effects. -Accent discipline: Cherenkov is rationed to the four brand moments above. -Status pills, category/date chips and metadata are plain muted text — the -label carries the meaning, not the chrome. +## Practical notes (the non-obvious ones) -## Typography - -| Role | Font | Rule | -|---|---|---| -| h1, h2 | Space Grotesk (`--font-display`) | Headlines ONLY (brand D.3.2), weight **500** (D.3.4 regular/medium), letter-spacing −0.025em, line-height 1.1 | -| Everything else | Inter (`--font-body`) | Includes h3+ (weight 600), cards, UI | -| Exception: `.card--featured h3` | Space Grotesk | The news-lead card IS a communicative headline (D.3.2 role, not outline level) — weight 500, `--fs-xl` | -| Exception: `.panel-title` (h2) | Inter | Panel titles are UI labels, not headlines — weight 600, `--fs-l`. These are the ONLY two exceptions | - -Type scale — the ONLY font sizes in the codebase (no ad-hoc rem values): - -| Token | Value | Use | -|---|---|---| -| `--fs-xs` | 0.8125rem | Meta, badges, labels, eyebrow, dates | -| `--fs-s` | 0.9rem | Secondary text, nav, forms, footer, TOC | -| (base) | 1rem | Body, line-height 1.5 (1.65 only on `.prose`; 1.55 `.standfirst`; 1.45 cards/footer) | -| `--fs-l` | 1.125rem | Card titles, standfirst, panel titles, hero subtitle | -| `--fs-xl` | 1.5rem | Prose h2, featured title, auth h1 | -| `--fs-h2` | clamp(1.75–2.5rem) | Section heads, article headlines (news titles run long — full `--fs-h1` would fill the viewport) | -| `--fs-h1` | clamp(2.25–3.5rem) | Short page heads only ("News & Announcements") | -| `--fs-display` | clamp(2.5–4.75rem) | Home hero only | - -Font tokens end with a generic (`sans-serif`); use them bare — -`var(--font-body), sans-serif` doubles the generic. - -Font loading (prevents any navigation blink): BOTH families are inlined as -base64 `data:` URIs inside the render-blocking `global.css` — no separate -font fetch exists, so there is no swap window and no font flash between -navigations. Metric-matched Arial fallbacks (`Inter Fallback`, -`Space Grotesk Fallback` — size-adjust/ascent/descent computed from the real -font metrics, capsize method) cover only the pre-CSS paint. The standalone -`public/fonts/*.woff2` files are referenced ONLY by -`public/admin/preview.css` (CMS entry preview) — they look unused but aren't. - -## Spacing scale (fluid; mobile ≈ min, desktop ≈ max) - -| Token | Value | Use | -|---|---|---| -| `--gutter` | `clamp(18px, 4vw, 28px)` | Container/menu side padding | -| `--space-s` | `12px` | Chip gaps, small stacks | -| `--space-m` | `24px` | Card/panel padding, grid gaps | -| `--space-l` | `24–40px` | Article top, meta/cover margins, featured body | -| `--space-xl` | `clamp(56px, 7vw, 120px)` | Section rhythm: every `.page` block, footer top | -| `--space-band` | `clamp(72px, 10vw, 160px)` | Hero/auth band + landing-head padding | - -Rule: section/container/card padding comes from this table — no ad-hoc px. -Prose-internal margins (h2/p/blockquote) are content-local and stay as written. - -## Radius & elevation - -Radius: `--radius 16px` (cards/panels), `--radius-pill` (buttons, chips, inputs). - -Only two shadows exist, both Galaxy-tinted, tuned soft/large/low-alpha -(2025/26 elevation convention: big blur, single-digit alpha at rest): - -| Token | Use | -|---|---| -| `--shadow-ambient` | Resting cards, panels, search rows | -| `--shadow-lifted` | Hover/focus cards, dropdowns (suggest, menu, search row), auth card | - -Never write a literal `box-shadow`; compose focus rings as -`0 0 0 2px var(--azure), var(--shadow-lifted)`. - -## Surfaces - -ONE surface per page — surface differentiation is by page archetype, never a -mid-page seam (consistency heuristic: a surface change must read as deliberate -system, not "why is this one gray?"): - -- **Editorial pages** (`/news`, articles, static pages, home news section) are - white — reading surfaces. -- **Utility/app pages** (`/search`, `/proposals`, `/dashboard`, `/support`) - are `.band--moon` from the landing head down to the footer — the app canvas - against which borderless white cards/panels pop (standard app-vs-editorial - surface split; home's Services section uses the same Moon band). -- `/` and `/login` own the navy bands (photo hero / nebula). - -Cards and panels are always white; ON MOON they are borderless (white-on-moon -separates by itself), on white they keep the hairline. Chrome is -single-signal: hover = the elevate gesture (shadow + 2px lift as ONE motion); -no hover borders, no cover zoom. - -## Motion policy (CSS-only, Apple-tier restraint) - -ctao.org drifts looping nebula videos under Galaxy vignettes; our translation: - -1. **Hero glow (home)** — the photo hero keeps its scrimmed photograph; a - `--nebula-glow` layer (Cherenkov .30 / Azure .28, no indigo over - photography) drifts above it inside the `.band-bg` clip frame: 16s - alternate, transform-only, clearly perceptible within ~10s. `.band-bg` - (first child of the band) owns `overflow: hidden` — NEVER put overflow on - the band itself (it would clip the search-suggest dropdown). -2. **Auth nebula (/login)** — the full `--nebula` stack (Cherenkov .38 / - Azure .33 / Indigo .80), same 16s drifting layer; static gradient is the - reduced-motion fallback. -3. **Whole-page ambient** — `.has-ambient::before`: fixed brand-hue wash - (Cherenkov .16 / Azure .12 / Indigo .10) drifting on a 36s alternate - cycle. Opt-in via ``: **home only**. Body text NEVER sits on - a moving gradient — cards, panels and bands are solid layers above it. -4. One-shot hero `rise` stagger; unified hover system (below). -5. **CSS scroll-driven effects** (2026 pass; `animation-timeline`, no JS — - "no scroll-triggered motion" below means no JS/observer motion): card - reveal on viewport entry (`view()`, entry 0–35%), header shadow fading in - over the first 80px of scroll, article reading-progress bar (2px Cherenkov - under the header — functional navigation state, same budget line as the - TOC scrollspy). All behind `@supports (animation-timeline: view())`, - compositor-only (the header shadow animates a pseudo-element's OPACITY, - never box-shadow in keyframes), auto-killed by the reduce block. -6. Micro-interactions: nav underline-grow (2px white rule, `scaleX` 0→1 on - hover, held on `aria-current`) and 1px press-down on `.btn`/navlink - `:active`. Nothing else. - -**One hover language** (mid-pass audit: hovers were inconsistent per element; -ctao.org uses a single quiet-fade token — we do the same): every interactive -element transitions color/background/border/shadow on `--dur: 0.25s` + -`--ease: ease-out` — buttons and links fade, cards/search rows elevate -(shadow + 2px lift), pagination fills Moon. No width/layout animation. - -Rules: -- ALL `animation`/`transition` declarations live inside the single - `@media (prefers-reduced-motion: no-preference)` block at the end of - global.css; the `reduce` block additionally force-disables everything. -- NO cross-document view transitions (`@view-transition`). The root crossfade - snapshots the incoming page at its first render opportunity — on slow - networks that is a half-parsed page, so every navigation read as a - full-page blink (the diagnosed symptom); scrolled→top navigations crossfade - two unrelated frames even when it works. Navigation feel comes from static - HTML + Astro prefetch, not from animating the swap. -- Animate `transform`/`opacity` only (compositor-only); never - background-position/box-shadow in keyframes. No `will-change`. No - `filter: blur` on large layers and no `background-attachment: fixed` - (broken on iOS). No JS, no scroll-triggered motion. -- If an effect calls attention to itself as an effect, cut it. - -## Photographic hero (home) - -Image-led hero per brand D.6 (photography theme: the project): LST-1 under -the night sky, copied from the content library to `public/brand/hero.jpg` -(NEVER link `public/uploads` directly — that directory is content-synced). -Text safety comes from `--hero-scrim` (Galaxy, `to right`: -.84 → .76 @52% → .44 @78% → .26); ≤640px a flat .80 scrim replaces it (text -spans the full width on mobile). The logo never sits on the photograph — it -stays in the header bar (B.1.2 satisfied by construction). - -Computed worst-case contrast over photo + scrim + drifting glow (glow fringe -α .15 Cherenkov / core .28 Azure over the text zone; Cherenkov core is pinned -≥80% band width by the blob geometry + drift range): - -- Small-text zone (eyebrow/subtitle/CTA labels, ≤52% band width): white - 7.68:1 · Cherenkov subtitle 4.79:1 · eyebrow `#C7CDE9` 4.88:1 (all ≥4.5). -- Display h1 zone (≤72% band width): white ≥5.20:1 (large text needs 3.0). -- Mobile flat scrim: white 8.47:1 · subtitle 5.28:1 · eyebrow 5.38:1. - -Recompute (script kept in the session scratchpad pattern: composite scrim → -glow → WCAG luminance per pixel) if the photo, scrim stops, glow alphas or -blob positions change. - -## WCAG 2.1 AA notes (computed, worst-case animation frames) - -- Photo hero: see table above. Auth nebula over Galaxy: white 7.9:1, - Cherenkov subtitle 4.9:1 at the worst blob frame; Cherenkov/Azure CORES stay - in opposite corners. Ceilings: nebula ≤ .38 Cherenkov / ≤ .35 Azure; glow - ≤ .30/.28; wash ≤ .16/.12/.10 — recompute if any alpha or placement changes. -- Translucent header (`color-mix` 88% Galaxy + backdrop blur, solid fallback - via `@supports`): worst underlying content (white) → bar ≈ rgb(31,31,96); - white text 14.8:1, muted nav `#C7CDE9` 9.4:1, Cherenkov sub-brand 9.2:1. -- On Moon: `--link` 6.1:1, `--muted` 7.1:1, `--text` 16.9:1. Ambient wash - worst overlap: `--link` 5.3:1, `--muted` 6.2:1. -- Focus visible everywhere; tap targets ≥ 44px; skip link first. - -## Article TOC pattern - -Rendered only when ≥3 h2/h3. Two renderings of the same list (only one ever -displayed), both in the quiet Stripe/Apple-docs voice — muted small links, -Galaxy on hover, no heavy box: - -- `