/* ========================================================================== CTAO Science Portal — design tokens per the official CTAO Brand Guidelines (April 2024): colors D.2, typography D.3 (Inter body / Space Grotesk display), flash D.4. All look-and-feel lives in the tokens below; WCAG 2.1 AA contrast. Light theme only (brand is light-first; navy bands carry the dark identity). System rules (spacing / elevation / surfaces / motion): see DESIGN.md. ========================================================================== */ :root { color-scheme: light; /* Brand palette — hex values straight from the brand book */ --galaxy: #00004a; /* Galaxy Blue — headings, header/footer bands */ --cherenkov: #00e4d8; /* Cherenkov Blue — accents, flash, CTAs; NOT for small text on light */ --moon: #f5f5f5; /* Moon Gray — surfaces */ --azure: #007aff; /* Cosmic Azure — brand hyperlink hue (large/UI only on light) */ --indigo: #00009c; /* Interestellar Indigo — gradient depth */ /* Derived, WCAG-adjusted */ --text: #101228; /* near-Galaxy body ink */ --muted: #46536a; --border: #e2e5ee; --link: #0057c2; /* Cosmic Azure darkened to pass AA (4.5:1) for body links */ --on-galaxy-muted: #c7cde9; --tint-cherenkov: color-mix(in srgb, var(--cherenkov) 16%, transparent); /* chip/badge fill */ --cherenkov-hover: color-mix(in oklab, var(--cherenkov), var(--galaxy) 12%); /* CTA hover state */ --ico-ext: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"%3E%3Cpath d="M7 17 17 7M9 7h8v8" fill="none" stroke="black" stroke-width="2.5"/%3E%3C/svg%3E'); /* Type & layout */ --font-body: "Inter", "Inter Fallback", Arial, system-ui, sans-serif; /* BRAND D.3.1 */ --font-display: "Space Grotesk", var(--font-body); /* BRAND D.3.2 — headlines only */ /* ctao.org uses generous rounding (15/30/60px tokens) and pill buttons */ --radius: 16px; --radius-pill: 999px; --maxw: 1120px; /* Fluid spacing scale (ctao.org rhythm: sections breathe, mobile stays compact). Every section / container / card padding sits on this scale — no ad-hoc values. */ --gutter: clamp(18px, 4vw, 28px); /* page side padding */ --space-s: 12px; --space-m: 20px; --space-l: clamp(24px, 2vw + 16px, 40px); --space-xl: clamp(40px, 3vw + 24px, 72px); /* section rhythm */ --space-band: clamp(48px, 5vw + 28px, 96px); /* hero / auth band padding */ /* Elevation — navy-tinted; the ONLY two shadows allowed in this codebase */ --shadow-ambient: 0 1px 2px rgba(0, 0, 74, 0.05), 0 4px 14px rgba(0, 0, 74, 0.07); --shadow-lifted: 0 4px 10px rgba(0, 0, 74, 0.08), 0 18px 44px rgba(0, 0, 74, 0.18); /* Nebula glow (BRAND D.5) — one stack for hero + auth bands, static AND animated. Alphas are contrast ceilings (DESIGN.md): Cherenkov ≤.38, Azure ≤.35 keep the Cherenkov subtitle/eyebrow ≥4.5:1 even with a blob core right under the text. Cherenkov and Azure cores sit in opposite corners — cores never meet. */ --nebula: radial-gradient(52% 58% at 78% 76%, rgba(0, 228, 216, 0.38), transparent 66%), radial-gradient(46% 52% at 12% 18%, rgba(0, 122, 255, 0.33), transparent 64%), radial-gradient(75% 85% at 40% 55%, rgba(0, 0, 156, 0.8), transparent 72%); } /* Self-hosted brand fonts — latin subset, variable weight, swap + metric-matched fallback */ @font-face { font-family: "Inter"; font-weight: 400 700; font-display: swap; src: url("/fonts/inter-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: "Space Grotesk"; font-weight: 500 700; font-display: swap; src: url("/fonts/space-grotesk-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: "Inter Fallback"; src: local("Arial"); size-adjust: 107%; ascent-override: 90.2%; descent-override: 22.48%; line-gap-override: 0%; } /* Screen-reader-only utility (visually hidden, still announced) */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; } * { box-sizing: border-box; } html { -webkit-text-size-adjust: 100%; scroll-padding-top: 84px; /* sticky header + anchor jumps */ } body { margin: 0; font-family: var(--font-body); background: #fff; color: var(--text); line-height: 1.65; min-height: 100dvh; } h1, h2 { font-family: var(--font-display); letter-spacing: -0.01em; } h1, h2, h3, .hero p { text-wrap: balance; } .prose p, .desc { text-wrap: pretty; } /* Inline SVG icons — stroke inherits currentColor */ .ico { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; flex: none; } a { color: var(--link); text-decoration: underline; text-underline-offset: 3px; } a:hover { color: var(--indigo); } /* Placeholder links ( without href) don't pretend to be clickable */ a:not([href]) { text-decoration: none; cursor: default; } img { max-width: 100%; height: auto; display: block; } /* Visible keyboard focus everywhere (WCAG 2.4.7) */ :focus-visible { outline: 2px solid var(--azure); outline-offset: 2px; } /* Skip link — first tab stop, hidden until focused (WCAG 2.4.1) */ .skip { position: absolute; left: 16px; top: -52px; z-index: 20; background: var(--galaxy); color: #fff; text-decoration: none; padding: 10px 16px; border-radius: 0 0 var(--radius) var(--radius); } .skip:focus { top: 0; } /* Safety net: even third-party/UA leftovers never move for reduced-motion users */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; } } .container { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); } /* Surface rhythm: white (editorial) → Moon Gray (service/utility bands) → Galaxy (hero/footer) */ .band--moon { background: var(--moon); } /* Flash — the REAL brand star (BRAND D.4): inline SVG path lifted from the official logo, never a CSS approximation. Budget: one accent per view; static. */ .flash { width: 12px; height: 12px; color: var(--cherenkov); flex: none; } /* Header — Galaxy Blue band, reverse (white) logo per BRAND B.1.2 */ .site-header { background: var(--galaxy); position: sticky; top: 0; z-index: 10; } .nav { display: flex; align-items: center; gap: 4px; min-height: 64px; flex-wrap: nowrap; } .nav > nav { display: flex; align-items: center; gap: 4px; } /* Header tiers (one row, always): full nav >1024px; sub-brand only >1100px; disclosure menu (native
/, CSS-only) at ≤1024px */ @media (max-width: 1100px) { .brand .brand-sub { display: none; } } @media (max-width: 360px) { .nav { padding: 0 14px; } .brand img { height: 20px; } .nav .login-mock { padding: 8px 14px; } } .menu { display: none; } .menu .i-close { display: none; } .menu[open] .i-menu { display: none; } .menu[open] .i-close { display: block; } @media (max-width: 1024px) { .nav > nav, .nav > a.navlink { display: none; } .menu { display: block; } .menu summary { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 10px; margin-left: 6px; color: #fff; font-weight: 500; cursor: pointer; list-style: none; white-space: nowrap; } .menu summary::-webkit-details-marker { display: none; } .menu nav { position: absolute; left: 0; right: 0; top: 100%; display: flex; flex-direction: column; padding: 6px var(--gutter) 14px; background: var(--galaxy); border-top: 1px solid rgba(255, 255, 255, 0.15); box-shadow: var(--shadow-lifted); } .menu nav a { display: flex; align-items: center; min-height: 44px; color: #fff; font-weight: 500; text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, 0.12); } .menu nav a:last-child { border-bottom: 0; } .menu nav a[aria-current="page"] { color: var(--cherenkov); } } .brand { display: flex; align-items: center; gap: 10px; margin-right: 10px; } .brand img { height: 26px; width: auto; } .brand .brand-sub { color: var(--cherenkov); font-size: 0.78rem; font-weight: 500; border-left: 1px solid rgba(255,255,255,0.25); padding-left: 10px; } .nav .spacer { flex: 1; } .nav a.navlink { color: var(--on-galaxy-muted); font-weight: 500; font-size: 0.95rem; padding: 10px 10px; text-decoration: none; border-bottom: 2px solid transparent; } .nav a.navlink:hover { color: #fff; } .nav a.navlink[aria-current="page"] { color: #fff; border-bottom-color: var(--cherenkov); } .nav a.navlink--edit { color: #fff; border: 1px solid rgba(255,255,255,0.35); border-radius: var(--radius-pill); padding: 7px 16px; margin-left: 6px; } .nav a.navlink--edit:hover { border-color: var(--cherenkov); color: var(--cherenkov); } /* AAI sign-in entry — leads to the /login mock page */ .nav .login-mock { color: var(--galaxy); background: var(--cherenkov); font: inherit; font-weight: 600; border: 0; border-radius: var(--radius-pill); padding: 8px 18px; margin-left: 6px; text-decoration: none; white-space: nowrap; } .nav .login-mock:hover { background: var(--cherenkov-hover); color: var(--galaxy); } /* Tap targets ≥44px (WCAG 2.5.5); inline-flex keeps the active bottom border */ .nav a.navlink, .nav .login-mock, .nav a.navlink--edit { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; } .navlink--edit .ico { width: 15px; height: 15px; } /* External-link marker — SVG arrow via mask, inherits currentColor */ .external::after { content: ""; display: inline-block; width: 0.72em; height: 0.72em; margin-left: 3px; background: currentColor; -webkit-mask: var(--ico-ext) center / contain no-repeat; mask: var(--ico-ext) center / contain no-repeat; } /* Hero — navy band with a nebula glow (BRAND D.5). The static gradient below is the reduced-motion fallback; with motion allowed, the glow moves to an animated pseudo-layer (see the motion block at the end of this file). */ .hero-band { background: var(--nebula), var(--galaxy); color: #fff; padding: var(--space-band) 0; position: relative; overflow: hidden; } .hero { position: relative; } /* content above the animated nebula layer */ .hero h1 { font-size: clamp(2rem, 6vw, 3.6rem); margin: 0 0 10px; line-height: 1.12; font-weight: 700; } .hero p { color: var(--cherenkov); font-size: 1.08rem; max-width: 62ch; margin: 0; } /* subtitle per BRAND D.3.4 */ .eyebrow { color: var(--on-galaxy-muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.14em; font-size: 0.72rem; margin-bottom: 8px; } /* Search fields — large pill input with inline magnifier; real GET form to /search */ .hero-search, .search-form { position: relative; display: flex; gap: 8px; max-width: 560px; } .hero-search { margin-top: var(--space-m); } .search-ico { position: absolute; left: 16px; top: 50%; translate: 0 -50%; color: var(--muted); pointer-events: none; } .hero-search input, .search-form input { flex: 1; min-width: 0; font: inherit; color: var(--text); background: #fff; border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 13px 18px 13px 44px; } .hero-search input:focus, .search-form input:focus { border-color: var(--azure); } /* Live suggestions under the hero search — plain links, Tab-accessible */ .suggest { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 5; list-style: none; margin: 0; padding: 6px; text-align: left; background: #fff; border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-lifted); } .suggest:empty { display: none; } .suggest li { display: flex; align-items: center; gap: var(--space-s); padding: 0 12px; border-radius: calc(var(--radius) - 8px); } .suggest li:hover { background: var(--moon); } .suggest a { flex: 1; display: flex; align-items: center; min-height: 44px; color: var(--text); font-weight: 500; font-size: 0.94rem; text-decoration: none; } .suggest::after { content: "↵ Enter — all results"; display: block; margin-top: 4px; padding: 8px 12px 2px; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.78rem; } /* Section header row (h2 + optional "All news →" link) */ .section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-s); margin: var(--space-l) 0 var(--space-m); } .section-head:first-child { margin-top: 0; } .section-head h2 { margin: 0; color: var(--galaxy); font-size: clamp(1.3rem, 2.5vw, 1.6rem); } .more { font-weight: 600; text-decoration: none; white-space: nowrap; } .more:hover { text-decoration: underline; } /* Responsive 1/2/3-column grid (news cards + service tiles); container for @container */ .grid { display: grid; gap: var(--space-m); grid-template-columns: 1fr; container-type: inline-size; } @media (min-width: 640px) { .grid { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 940px) { .grid { grid-template-columns: repeat(3, 1fr); } } /* Subgrid: cover/cat/title/desc/meta rows align across each card row */ @supports (grid-template-rows: subgrid) { .grid > .card:not(.card--featured, .tile) { display: grid; grid-template-rows: subgrid; grid-row: span 5; gap: 0; } .grid > .card:not(.card--featured, .tile) .body { display: grid; grid-template-rows: subgrid; grid-row: span 4; gap: 10px; } } /* News cards — image + category + clamped title/description +