From 2d54c69fd8ba313b6889906107ff929e93b8f27a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 3 Oct 2026 10:11:20 +0000 Subject: [PATCH 1/2] Redesign the site with a modern space look New home page (big hero with a CSS Mars, live Mars clock, numbered pillars, featured archive tiles, topic list, support band), dark space headers on every inner page, line icons in place of emoji, a year-grouped activity timeline, a new footer, and self-hosted Space Grotesk and JetBrains Mono. Content, data files, languages and URLs are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01EZdfMMy2aM8X4PGqUv2p7N --- README.md | 2 +- assets/css/main.css | 525 +++++++++++++++++--------- assets/js/main.js | 25 ++ i18n/cn.yaml | 24 ++ i18n/en.yaml | 24 ++ layouts/404.html | 2 +- layouts/_default/list.html | 2 +- layouts/_default/single.html | 2 +- layouts/activities/list.html | 19 +- layouts/archives/list.html | 10 +- layouts/cities/list.html | 2 +- layouts/cities/single.html | 2 +- layouts/index.html | 116 ++++-- layouts/institutes/list.html | 2 +- layouts/partials/footer.html | 9 +- layouts/partials/icon.html | 25 ++ layouts/partials/page-hero.html | 5 +- static/fonts/OFL-jetbrains-mono.txt | 93 +++++ static/fonts/OFL-space-grotesk.txt | 93 +++++ static/fonts/jetbrains-mono-500.woff2 | Bin 0 -> 21832 bytes static/fonts/space-grotesk.woff2 | Bin 0 -> 22288 bytes 21 files changed, 755 insertions(+), 227 deletions(-) create mode 100644 layouts/partials/icon.html create mode 100644 static/fonts/OFL-jetbrains-mono.txt create mode 100644 static/fonts/OFL-space-grotesk.txt create mode 100644 static/fonts/jetbrains-mono-500.woff2 create mode 100644 static/fonts/space-grotesk.woff2 diff --git a/README.md b/README.md index 081edfa..7eb6619 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The site is self-contained: layouts, styles and data live in this repository (th | `i18n/` | Small UI strings (menu label, 404 text, ...) | | `layouts/` | Templates | | `assets/` | CSS and JS, minified and fingerprinted by Hugo at build time | -| `static/` | Files served as-is (images, video, favicons) | +| `static/` | Files served as-is (images, video, favicons, self-hosted fonts under `fonts/`) | ## Deploy diff --git a/assets/css/main.css b/assets/css/main.css index bfb0e9b..c5310b3 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -1,48 +1,115 @@ /* InterImm site styles. Hand-written, no framework. Colours are tokens on :root and switch with the - visitor's system light/dark preference. The home hero is always "space". */ + visitor's system light/dark preference. Anything with the `space` class + (home hero, page headers, the support band) is always dark. */ + +/* ---------- fonts (self-hosted, SIL OFL; see static/fonts) ---------- */ +@font-face { + font-family: "Space Grotesk"; + src: url("/fonts/space-grotesk.woff2") format("woff2"); + font-weight: 300 700; + font-display: swap; + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2190-2199, U+2212, U+2215; +} +@font-face { + font-family: "JetBrains Mono"; + src: url("/fonts/jetbrains-mono-500.woff2") format("woff2"); + font-weight: 500; + font-display: swap; + unicode-range: U+0000-00FF, U+2000-206F, U+2190-2199; +} /* ---------- tokens ---------- */ :root { color-scheme: light dark; - --bg: #f5f7fb; - --bg-alt: #e9eef7; + --bg: #f6f5f1; + --bg-alt: #eeece6; --surface: #ffffff; - --text: #121a2b; - --muted: #526078; - --border: #d3dbea; - --link: #1f4fd8; - --focus: #1f4fd8; - --accent: #f5b301; - --accent-hover: #ffc72e; - --accent-text: #1a1300; - --shadow: 0 1px 2px rgb(16 24 40 / 0.06), 0 10px 28px rgb(16 24 40 / 0.07); - - --space-bg: #070b18; - --space-text: #eef2ff; - --space-muted: #b6c2e4; - - --radius: 1rem; - --wrap: 72rem; - --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", - "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", - "Noto Color Emoji"; + --surface-2: #faf9f6; + --text: #15171d; + --muted: #5a6070; + --border: #e2dfd7; + --border-strong: #cfcac0; + --link: #b93d12; + --focus: #d0461a; + --accent: #ff6b3d; + --accent-hover: #ff855e; + --accent-text: #1c0700; + --accent-soft: rgb(255 107 61 / 0.12); + --shadow: 0 1px 2px rgb(20 20 30 / 0.05), 0 12px 32px rgb(20 20 30 / 0.06); + + --radius: 1.1rem; + --wrap: 76rem; + --cjk: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", "Source Han Sans SC"; + --emoji: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji"; + --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", var(--cjk), sans-serif, var(--emoji); + --font-display: "Space Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, var(--cjk), sans-serif, var(--emoji); + --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, var(--cjk), monospace; } +/* dark values, shared by the dark scheme and every `.space` block */ @media (prefers-color-scheme: dark) { :root { - --bg: #0b1020; - --bg-alt: #0f1730; - --surface: #141c33; - --text: #e8edf8; - --muted: #a3afc8; - --border: #26304d; - --link: #8fb4ff; - --focus: #8fb4ff; - --shadow: 0 1px 2px rgb(0 0 0 / 0.4), 0 10px 28px rgb(0 0 0 / 0.35); + --bg: #07090f; + --bg-alt: #0b0f18; + --surface: #0f141f; + --surface-2: #131a27; + --text: #e8ebf2; + --muted: #98a1b4; + --border: rgb(255 255 255 / 0.08); + --border-strong: rgb(255 255 255 / 0.16); + --link: #ff9b75; + --focus: #ff9b75; + --accent-soft: rgb(255 107 61 / 0.14); + --shadow: 0 1px 2px rgb(0 0 0 / 0.5), 0 16px 40px rgb(0 0 0 / 0.35); } - .brand-mark { filter: invert(1); } + .site-header .brand-mark, .site-footer .brand-mark { filter: invert(1); } +} + +.space { + --bg: #05070d; + --bg-alt: #0a0e17; + --surface: rgb(255 255 255 / 0.04); + --surface-2: rgb(255 255 255 / 0.07); + --text: #eef1f7; + --muted: #a3acc0; + --border: rgb(255 255 255 / 0.1); + --border-strong: rgb(255 255 255 / 0.2); + --link: #ff9b75; + --focus: #ff9b75; + color: var(--text); + position: relative; + isolation: isolate; + overflow: hidden; + background: + radial-gradient(60rem 32rem at 92% -10%, rgb(255 107 61 / 0.22), transparent 60%), + radial-gradient(48rem 36rem at -10% 110%, rgb(88 92 230 / 0.22), transparent 62%), + var(--bg); +} +/* starfield + faint coordinate grid, both static */ +.space::before, .space::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; } +.space::before { + opacity: 0.75; + background-image: + radial-gradient(1.2px 1.2px at 12% 22%, #fff, transparent), + radial-gradient(1px 1px at 31% 71%, #fff, transparent), + radial-gradient(1.5px 1.5px at 52% 14%, #fff, transparent), + radial-gradient(1px 1px at 68% 58%, #fff, transparent), + radial-gradient(1.2px 1.2px at 83% 33%, #fff, transparent), + radial-gradient(1px 1px at 93% 82%, #fff, transparent), + radial-gradient(1px 1px at 22% 92%, #fff, transparent), + radial-gradient(0.8px 0.8px at 44% 44%, #fff, transparent), + radial-gradient(0.8px 0.8px at 76% 8%, #fff, transparent); + background-size: 420px 340px; +} +.space::after { + background-image: + linear-gradient(rgb(255 255 255 / 0.035) 1px, transparent 1px), + linear-gradient(90deg, rgb(255 255 255 / 0.035) 1px, transparent 1px); + background-size: 64px 64px; + -webkit-mask-image: radial-gradient(ellipse at 70% 30%, #000, transparent 70%); + mask-image: radial-gradient(ellipse at 70% 30%, #000, transparent 70%); } /* ---------- base ---------- */ @@ -61,19 +128,24 @@ body { line-height: 1.7; color: var(--text); background: var(--bg); + -webkit-font-smoothing: antialiased; } main { flex: 1; } -h1, h2, h3 { line-height: 1.25; margin: 0 0 0.6em; text-wrap: balance; } +h1, h2, h3 { + font-family: var(--font-display); font-weight: 600; + line-height: 1.15; letter-spacing: -0.02em; margin: 0 0 0.6em; text-wrap: balance; +} p { margin: 0 0 1em; text-wrap: pretty; } img, video, svg { max-width: 100%; height: auto; } a { color: var(--link); text-underline-offset: 0.2em; } a:hover { text-decoration-thickness: 2px; } ul, ol { margin: 0 0 1em; } +::selection { background: var(--accent); color: var(--accent-text); } -:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 0.25rem; } +:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 0.3rem; } -.wrap { width: min(100% - 2rem, var(--wrap)); margin-inline: auto; } +.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; } .sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; @@ -89,169 +161,248 @@ ul, ol { margin: 0 0 1em; } .text-center { text-align: center; } +.kicker { + display: inline-flex; align-items: center; gap: 0.6rem; margin: 0 0 1rem; + font-family: var(--font-mono); font-size: 0.78rem; font-weight: 500; + letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); +} +.kicker::before { content: ""; width: 1.5rem; height: 1px; background: var(--accent); } +.kicker:has(.pulse)::before { display: none; } +.pulse { + width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--accent); + box-shadow: 0 0 0 0 rgb(255 107 61 / 0.6); animation: pulse 2.4s infinite; +} +@keyframes pulse { 70% { box-shadow: 0 0 0 0.6rem rgb(255 107 61 / 0); } 100% { box-shadow: 0 0 0 0 rgb(255 107 61 / 0); } } + +.icon { width: 1.5rem; height: 1.5rem; flex: none; } +.icon-emoji { display: inline-grid; place-items: center; font-size: 1.25rem; line-height: 1; } + /* ---------- header ---------- */ .site-header { position: sticky; top: 0; z-index: 50; - background: color-mix(in srgb, var(--bg) 86%, transparent); - -webkit-backdrop-filter: saturate(1.4) blur(12px); - backdrop-filter: saturate(1.4) blur(12px); + background: color-mix(in srgb, var(--bg) 78%, transparent); + -webkit-backdrop-filter: saturate(1.6) blur(14px); + backdrop-filter: saturate(1.6) blur(14px); border-bottom: 1px solid var(--border); } -.header-inner { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem 1rem; min-height: 3.75rem; padding-block: 0.5rem; } +.header-inner { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem 1.25rem; min-height: 4rem; padding-block: 0.5rem; } .brand { - display: inline-flex; align-items: center; gap: 0.6rem; - font-weight: 700; font-size: 1.1rem; color: var(--text); text-decoration: none; + display: inline-flex; align-items: center; gap: 0.65rem; + font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; letter-spacing: -0.01em; + color: var(--text); text-decoration: none; } -.brand-mark { border-radius: 0.4rem; } +.brand-mark { border-radius: 50%; } .site-nav { display: flex; flex: 1; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.25rem 1rem; } -.nav-list { display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem; list-style: none; margin: 0; padding: 0; } +.nav-list { display: flex; flex-wrap: wrap; align-items: center; gap: 0.1rem; list-style: none; margin: 0; padding: 0; } .nav-link, .dropdown > summary { display: inline-flex; align-items: center; gap: 0.4rem; - padding: 0.45rem 0.75rem; border-radius: 0.6rem; - color: var(--text); font-weight: 500; text-decoration: none; cursor: pointer; + padding: 0.4rem 0.8rem; border-radius: 999px; + color: var(--muted); font-size: 0.95rem; font-weight: 500; text-decoration: none; cursor: pointer; + transition: color 0.15s, background 0.15s; } -.nav-link:hover, .dropdown > summary:hover, .dropdown[open] > summary { background: var(--bg-alt); } -.nav-link[aria-current="page"], .dropdown[data-current] > summary { color: var(--link); font-weight: 600; } -.lang-link { border: 1px solid var(--border); } +.nav-link:hover, .dropdown > summary:hover, .dropdown[open] > summary { color: var(--text); background: var(--surface-2); } +.nav-link[aria-current="page"], .dropdown[data-current] > summary { color: var(--text); background: var(--accent-soft); } +.lang-link { border: 1px solid var(--border-strong); color: var(--text); } .dropdown { position: relative; } .dropdown > summary { list-style: none; } .dropdown > summary::-webkit-details-marker { display: none; } .dropdown > summary::after { - content: ""; width: 0.4em; height: 0.4em; margin-top: -0.2em; - border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); + content: ""; width: 0.35em; height: 0.35em; margin-top: -0.2em; + border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); } .dropdown-menu { - position: absolute; top: calc(100% + 0.4rem); left: 0; z-index: 60; + position: absolute; top: calc(100% + 0.5rem); left: 0; z-index: 60; min-width: min(19rem, 90vw); margin: 0; padding: 0.4rem; list-style: none; - background: var(--surface); border: 1px solid var(--border); border-radius: 0.8rem; box-shadow: var(--shadow); + background: var(--surface); border: 1px solid var(--border-strong); border-radius: 0.9rem; box-shadow: var(--shadow); } +@media (prefers-color-scheme: dark) { .dropdown-menu { background: #121826; } } .dropdown-menu a { - display: block; padding: 0.5rem 0.75rem; border-radius: 0.5rem; - color: var(--text); text-decoration: none; + display: block; padding: 0.5rem 0.75rem; border-radius: 0.55rem; + color: var(--text); font-size: 0.95rem; text-decoration: none; } -.dropdown-menu a:hover { background: var(--bg-alt); } +.dropdown-menu a:hover { background: var(--surface-2); } .dropdown-menu a[aria-current="page"] { color: var(--link); font-weight: 600; } .nav-toggle { - display: none; margin-left: auto; padding: 0.4rem; border: 1px solid var(--border); border-radius: 0.6rem; + display: none; margin-left: auto; padding: 0.45rem; border: 1px solid var(--border-strong); border-radius: 999px; background: transparent; color: var(--text); cursor: pointer; } -@media (max-width: 56rem) { +@media (max-width: 58rem) { .js .nav-toggle { display: inline-flex; } .js .site-nav { display: none; flex-basis: 100%; padding-bottom: 0.75rem; } .js .site-nav.is-open { display: flex; flex-direction: column; align-items: stretch; } .nav-list { flex-direction: column; align-items: stretch; } + .nav-link, .dropdown > summary { border-radius: 0.6rem; font-size: 1rem; } .nav-tools { flex-direction: row; flex-wrap: wrap; padding-top: 0.5rem; border-top: 1px solid var(--border); } .dropdown-menu { position: static; min-width: 0; margin: 0.2rem 0 0.4rem 0.75rem; box-shadow: none; } } -/* ---------- buttons, chips, pills ---------- */ +/* ---------- buttons, chips ---------- */ .btn { - display: inline-flex; align-items: center; justify-content: center; gap: 0.5ch; - padding: 0.55rem 1.15rem; border: 1px solid var(--border); border-radius: 999px; - background: var(--surface); color: var(--text); font: inherit; font-weight: 600; line-height: 1.4; - text-decoration: none; transition: background 0.15s, border-color 0.15s, transform 0.15s; + display: inline-flex; align-items: center; justify-content: center; gap: 0.6ch; + padding: 0.55rem 1.15rem; border: 1px solid var(--border-strong); border-radius: 999px; + background: var(--surface); color: var(--text); font: inherit; font-size: 0.95rem; font-weight: 600; line-height: 1.4; + white-space: nowrap; text-decoration: none; transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s; } -.btn:hover { border-color: var(--link); text-decoration: none; } +.btn:hover { border-color: var(--accent); } +.btn span { transition: transform 0.15s; } +.btn:hover span { transform: translateX(3px); } .btn-primary { background: var(--accent); border-color: transparent; color: var(--accent-text); } -.btn-primary:hover { background: var(--accent-hover); border-color: transparent; transform: translateY(-1px); } -.btn-lg { padding: 0.85rem 1.75rem; font-size: 1.15rem; } +.btn-primary:hover { background: var(--accent-hover); border-color: transparent; box-shadow: 0 8px 30px rgb(255 107 61 / 0.35); } +.btn-ghost { background: transparent; } +.btn-ghost:hover { background: var(--surface-2); border-color: var(--border-strong); } +.btn-lg { padding: 0.8rem 1.6rem; font-size: 1.05rem; } .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 0 0 1.25rem; padding: 0; } .chips li { - padding: 0.15rem 0.85rem; border: 1px solid currentColor; border-radius: 999px; - font-size: 0.9rem; line-height: 1.6; opacity: 0.85; + padding: 0.2rem 0.85rem; border: 1px solid var(--border-strong); border-radius: 999px; + background: var(--surface); color: var(--muted); font-size: 0.85rem; line-height: 1.6; } -.chips-small li { padding: 0.05rem 0.65rem; font-size: 0.8rem; color: var(--muted); border-color: var(--border); opacity: 1; } +.chips-small li { padding: 0.05rem 0.65rem; font-size: 0.78rem; } -.pills { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; list-style: none; margin: 0; padding: 0; } -.pills a { - display: inline-block; padding: 0.4rem 1rem; border: 1px solid var(--border); border-radius: 999px; - background: var(--surface); color: var(--text); text-decoration: none; transition: border-color 0.15s, transform 0.15s; -} -.pills a:hover { border-color: var(--link); color: var(--link); transform: translateY(-1px); } +.text-link { color: var(--text); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--accent); padding-bottom: 0.1rem; } +.text-link span { display: inline-block; transition: transform 0.15s; } +.text-link:hover span { transform: translateX(3px); } /* ---------- home hero ---------- */ -.hero { - position: relative; overflow: hidden; color: var(--space-text); - background: - radial-gradient(48rem 26rem at 88% -8%, rgb(255 122 69 / 0.28), transparent 62%), - radial-gradient(40rem 30rem at -5% 105%, rgb(99 102 241 / 0.32), transparent 62%), - var(--space-bg); +.hero { padding-bottom: clamp(2rem, 5vw, 3.5rem); } +.hero-inner { + display: grid; align-items: center; gap: 2.5rem 3rem; + grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); + min-height: min(44rem, calc(100svh - 9rem)); + padding-block: clamp(3rem, 8vw, 6rem) clamp(2rem, 5vw, 3.5rem); } -/* a cheap, static starfield: a few tiny radial gradients tiled */ -.hero::before { - content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0.7; - background-image: - radial-gradient(1.2px 1.2px at 12% 22%, #fff, transparent), - radial-gradient(1px 1px at 31% 71%, #fff, transparent), - radial-gradient(1.4px 1.4px at 52% 14%, #fff, transparent), - radial-gradient(1px 1px at 68% 58%, #fff, transparent), - radial-gradient(1.2px 1.2px at 83% 33%, #fff, transparent), - radial-gradient(1px 1px at 93% 82%, #fff, transparent), - radial-gradient(1px 1px at 22% 92%, #fff, transparent); - background-size: 360px 300px; +.hero h1 { + font-size: clamp(3rem, 1rem + 7.5vw, 6.75rem); font-weight: 700; + letter-spacing: -0.045em; line-height: 0.95; margin-bottom: 0.35em; + background: linear-gradient(180deg, #fff 30%, #ffc2a8 120%); + -webkit-background-clip: text; background-clip: text; color: transparent; } -.hero-inner { - position: relative; display: grid; align-items: center; gap: 2rem 3rem; - grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); - padding-block: clamp(3rem, 8vw, 6rem); +.hero h1:lang(zh) { letter-spacing: 0; line-height: 1.1; } +.hero .lede { max-width: 34rem; font-size: clamp(1.1rem, 1rem + 0.6vw, 1.4rem); color: var(--muted); margin-bottom: 1.5rem; } +.hero .chips { margin-bottom: 2rem; } +.hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0; } + +.hero-visual { position: relative; display: grid; justify-items: center; gap: 1.5rem; } +.planet-wrap { position: relative; width: min(100%, 24rem); aspect-ratio: 1; display: grid; place-items: center; } +.planet { + width: 62%; aspect-ratio: 1; border-radius: 50%; + background: + radial-gradient(circle at 64% 68%, rgb(80 20 6 / 0.3), transparent 9%), + radial-gradient(circle at 30% 60%, rgb(90 25 8 / 0.25), transparent 13%), + radial-gradient(ellipse 24% 8% at 40% 18%, rgb(255 236 225 / 0.35), transparent 70%), + radial-gradient(ellipse 40% 12% at 50% 44%, rgb(120 35 12 / 0.5), transparent 70%), + radial-gradient(ellipse 30% 9% at 58% 30%, rgb(255 210 180 / 0.25), transparent 70%), + radial-gradient(circle at 34% 30%, #ffc09a 0%, #f2703f 28%, #b63c1b 58%, #4a1307 88%); + box-shadow: + inset -2.2rem -1.4rem 3.5rem rgb(0 0 0 / 0.65), + inset 0.4rem 0.3rem 1rem rgb(255 220 200 / 0.25), + 0 0 6rem rgb(255 107 61 / 0.3); } -.hero h1 { font-size: clamp(2.4rem, 1.2rem + 5vw, 4.25rem); letter-spacing: -0.01em; margin-bottom: 0.3em; } -.hero .lede { font-size: clamp(1.1rem, 1rem + 0.6vw, 1.4rem); color: var(--space-muted); margin-bottom: 1.25rem; } -.hero .chips { margin-bottom: 1.75rem; } -.hero-art { justify-self: center; width: min(100%, 28rem); filter: drop-shadow(0 20px 40px rgb(0 0 0 / 0.45)); } - -@media (max-width: 52rem) { - .hero-inner { grid-template-columns: 1fr; text-align: center; } - .hero .chips { justify-content: center; } - .hero-art { grid-row: 1; width: min(70%, 18rem); } +.orbit { position: absolute; inset: 0; border: 1px solid rgb(255 255 255 / 0.12); border-radius: 50%; animation: spin 40s linear infinite; } +.orbit-2 { inset: 9%; border-style: dashed; border-color: rgb(255 255 255 / 0.08); animation-duration: 26s; animation-direction: reverse; } +.moon { position: absolute; top: 50%; left: -4px; width: 8px; height: 8px; margin-top: -4px; border-radius: 50%; background: #e9e4dc; box-shadow: 0 0 12px rgb(255 255 255 / 0.6); } +.moon-2 { left: auto; right: -3px; width: 6px; height: 6px; margin-top: -3px; background: #c9b8a6; } +@keyframes spin { to { transform: rotate(360deg); } } + +.readout { + display: grid; grid-template-columns: repeat(3, auto); gap: 0 1.5rem; margin: 0; + padding: 0.9rem 1.25rem; border: 1px solid var(--border); border-radius: 0.9rem; + background: rgb(10 14 23 / 0.6); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); } - -/* "latest" banner under the hero */ -.latest { background: var(--bg-alt); border-bottom: 1px solid var(--border); font-size: 0.95rem; } -.latest .wrap { display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 0.4rem 0.9rem; padding-block: 0.75rem; } +.readout dt { font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); white-space: nowrap; } +.readout dd { margin: 0; font-family: var(--font-mono); font-size: 1.05rem; font-variant-numeric: tabular-nums; color: var(--text); } +.readout div:first-child dd { color: #ffb08f; } + +.latest { + display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.9rem; + padding: 0.85rem 1.1rem; border: 1px solid var(--border); border-radius: 0.9rem; + background: var(--surface); color: var(--text); text-decoration: none; font-size: 0.95rem; + transition: border-color 0.15s, background 0.15s; +} +.latest:hover { border-color: var(--border-strong); background: var(--surface-2); } +.latest time { font-family: var(--font-mono); font-size: 0.82rem; color: var(--muted); font-variant-numeric: tabular-nums; } +.latest-title { flex: 1; min-width: 12rem; font-weight: 500; } +.latest-arrow { color: var(--accent); transition: transform 0.15s; } +.latest:hover .latest-arrow { transform: translateX(4px); } .badge { - padding: 0.05rem 0.7rem; border-radius: 999px; - background: var(--accent); color: var(--accent-text); font-size: 0.8rem; font-weight: 700; + padding: 0.1rem 0.6rem; border-radius: 999px; + background: var(--accent); color: var(--accent-text); + font-family: var(--font-mono); font-size: 0.7rem; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; } -.latest time { color: var(--muted); font-variant-numeric: tabular-nums; } -/* ---------- sections and cards ---------- */ -.section { padding-block: clamp(2.5rem, 6vw, 4.5rem); } -.section-alt { background: var(--bg-alt); } -.section-title { text-align: center; font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.1rem); margin-bottom: 1.5rem; } +@media (max-width: 54rem) { + .hero-inner { grid-template-columns: 1fr; min-height: 0; } + .hero-visual { grid-row: 1; } + .planet-wrap { width: min(70%, 15rem); } +} +@media (max-width: 30rem) { + .readout { grid-template-columns: 1fr 1fr; gap: 0.6rem 1.25rem; } + .readout div:last-child { grid-column: span 2; } +} -.card-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); } -.card-grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr)); } +/* ---------- sections ---------- */ +.section { padding-block: clamp(3.5rem, 8vw, 6rem); } +.section-alt { background: var(--bg-alt); border-block: 1px solid var(--border); } +.section-head { margin-bottom: clamp(1.75rem, 4vw, 2.75rem); } +.section-head-split { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1.25rem 2rem; } +.section-title { font-size: clamp(1.9rem, 1.2rem + 2.4vw, 3rem); margin-bottom: 0.4rem; } +.section-lede { max-width: 36rem; margin: 0; color: var(--muted); font-size: 1.1rem; } + +/* what we do: three numbered columns */ +.pillars { display: grid; gap: 2rem 3rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); } +.pillar { display: flex; flex-direction: column; padding-top: 1.5rem; border-top: 1px solid var(--border-strong); } +.pillar-num { margin: 0 0 1.5rem; font-family: var(--font-mono); font-size: 0.85rem; color: var(--accent); } +.pillar-title { font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); margin-bottom: 0.6rem; } +.pillar p { color: var(--muted); } +.pillar p:first-letter { text-transform: uppercase; } +.pillar-action { margin: auto 0 0; padding-top: 0.5rem; } + +/* tiles (archives and tools) */ +.bento { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 16.5rem), 1fr)); } +@media (min-width: 64rem) { + .section .bento:has(> :nth-child(6):last-child) { grid-template-columns: repeat(4, 1fr); } + .section .bento:has(> :nth-child(6):last-child) > :is(:first-child, :last-child) { grid-column: span 2; } +} +.tile { + position: relative; display: flex; flex-direction: column; + padding: 1.5rem; border: 1px solid var(--border); border-radius: var(--radius); + background: linear-gradient(180deg, var(--surface-2), var(--surface)); +} +.tile > :last-child { margin-bottom: 0; } +.tile-icon { + display: inline-grid; place-items: center; width: 2.75rem; height: 2.75rem; margin-bottom: 1.25rem; + border-radius: 0.75rem; background: var(--accent-soft); color: var(--accent); +} +.tile-title { font-size: 1.2rem; margin-bottom: 0.4rem; } +.tile p { color: var(--muted); font-size: 0.97rem; } +.tile .card-cta { color: var(--text); } +/* generic cards (inner pages) */ +.card-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); } .card { position: relative; display: flex; flex-direction: column; - padding: 1.5rem; background: var(--surface); border: 1px solid var(--border); - border-radius: var(--radius); box-shadow: var(--shadow); + padding: 1.5rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); } .card > :last-child { margin-bottom: 0; } .card-title { font-size: 1.25rem; margin-bottom: 0.5rem; } -.card-plain { box-shadow: none; } -.card-action { margin-top: auto; padding-top: 0.75rem; } -.card-icon { margin: 0 0 0.5rem; font-size: 2.25rem; line-height: 1; } -.card-cta { margin: auto 0 0; padding-top: 0.75rem; color: var(--link); font-weight: 600; } -.card-cta span { display: inline-block; transition: transform 0.15s; } -.card-wide { max-width: 52rem; margin-inline: auto; width: 100%; } +.card-cta { margin: auto 0 0; padding-top: 0.75rem; color: var(--link); font-size: 0.92rem; font-weight: 600; } +.card-cta span { display: inline-block; color: var(--accent); transition: transform 0.15s; } +.card-wide { max-width: 54rem; margin-inline: auto; width: 100%; } /* whole card is clickable through its title link */ -.card-link-wrap { transition: transform 0.15s, border-color 0.15s; } -.card-link-wrap:hover { transform: translateY(-2px); border-color: var(--link); } -.card-link-wrap:hover .card-cta span { transform: translateX(3px); } +.card-link-wrap { transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s; } +.card-link-wrap:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: var(--shadow); } +.card-link-wrap:hover .card-cta span { transform: translateX(4px); } .card-link { color: var(--text); text-decoration: none; } .card-link::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); } .card-link:focus-visible { outline: none; } -.card-link:focus-visible::after { outline: 3px solid var(--focus); outline-offset: 2px; } +.card-link:focus-visible::after { outline: 2px solid var(--focus); outline-offset: 3px; } .card-media { padding: 0; overflow: hidden; } .card-media .card-image { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--bg-alt); } @@ -261,76 +412,107 @@ ul, ol { margin: 0 0 1em; } .figure { margin: 1rem 0 0; padding: 1rem; background: #fff; border-radius: 0.75rem; text-align: center; } .figure img { max-height: 32rem; width: auto; margin-inline: auto; } -/* ---------- inner pages ---------- */ -.page-hero { - padding-block: clamp(2.5rem, 7vw, 4.5rem); text-align: center; - background: linear-gradient(180deg, var(--bg-alt), var(--bg)); - border-bottom: 1px solid var(--border); +/* research topics: numbered link rows */ +.topic-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr)); column-gap: 3rem; margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--border); } +.topic-list a { + display: flex; align-items: baseline; gap: 1rem; padding: 1rem 0.25rem; + border-bottom: 1px solid var(--border); color: var(--text); text-decoration: none; transition: color 0.15s, padding 0.2s; +} +.topic-num { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); } +.topic-name { flex: 1; font-family: var(--font-display); font-size: 1.1rem; font-weight: 500; } +.topic-arrow { color: var(--muted); transition: transform 0.2s, color 0.15s; } +.topic-list a:hover { color: var(--link); padding-left: 0.75rem; } +.topic-list a:hover .topic-arrow { color: var(--accent); transform: translate(2px, -2px); } + +/* support band */ +.support-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); border-top: 1px solid var(--border); } +.support-item { padding: 1.5rem 1.5rem 0.5rem 0; } +.support-item + .support-item { padding-left: 1.5rem; border-left: 1px solid var(--border); } +.support-item h3 { font-size: 1.2rem; margin-bottom: 0.5rem; } +.support-item p { color: var(--muted); font-size: 0.97rem; } +@media (max-width: 58rem) { + .support-item, .support-item + .support-item { padding: 1.25rem 0 0.25rem; border-left: 0; border-bottom: 1px solid var(--border); } } -.page-hero h1 { font-size: clamp(1.9rem, 1.2rem + 3vw, 3rem); margin-bottom: 0.3em; } -.page-hero .lede { max-width: 42rem; margin: 0 auto 1rem; color: var(--muted); font-size: 1.15rem; } -.page-hero .chips { justify-content: center; margin: 0.75rem 0 0; color: var(--muted); } + +/* ---------- inner pages ---------- */ +.page-hero { padding-block: clamp(3.5rem, 9vw, 6.5rem) clamp(2.5rem, 6vw, 4rem); border-bottom: 1px solid var(--border); } +.page-hero h1 { font-size: clamp(2.4rem, 1.4rem + 4vw, 4.25rem); letter-spacing: -0.035em; margin-bottom: 0.3em; } +.page-hero h1:lang(zh) { letter-spacing: 0; } +.page-hero .lede { max-width: 44rem; margin: 0 0 1rem; color: var(--muted); font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem); } +.page-hero .chips { margin: 1rem 0 0; } .prose { max-width: 46rem; } .prose > * { margin-inline: 0; } -.prose h2 { margin-top: 2em; font-size: 1.6rem; } -.prose h3 { margin-top: 1.6em; font-size: 1.25rem; } +.prose h2 { margin-top: 2em; font-size: 1.75rem; } +.prose h3 { margin-top: 1.6em; font-size: 1.3rem; } .prose img, .prose video { border-radius: 0.75rem; } -.prose-wide { max-width: 64rem; } +.prose-wide { max-width: 66rem; } .prose-wide > p, .prose-wide > h2, .prose-wide > h3, .prose-wide > ul, .prose-wide > ol { max-width: 46rem; margin-inline: auto; } .wrap.prose { margin-inline: auto; } :lang(zh) { line-height: 1.85; } -:lang(zh) .card p, :lang(zh) .timeline p { line-height: 1.75; } +:lang(zh) .tile p, :lang(zh) .card p, :lang(zh) .timeline p { line-height: 1.75; } /* about page: media + text side by side */ .split { display: grid; gap: 2rem 3rem; align-items: center; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); margin-top: 2rem; } .split-media { margin: 0; } -.split-media video { display: block; width: 100%; aspect-ratio: 16 / 9; background: #000; border-radius: var(--radius); box-shadow: var(--shadow); } -.lede-strong { padding-left: 1rem; border-left: 4px solid var(--accent); font-size: 1.2rem; font-weight: 700; } +.split-media video { display: block; width: 100%; aspect-ratio: 16 / 9; background: #000; border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); } +.lede-strong { padding-left: 1rem; border-left: 3px solid var(--accent); font-family: var(--font-display); font-size: 1.3rem; font-weight: 600; line-height: 1.4; } .embed { aspect-ratio: 16 / 9; min-height: 18rem; } -.embed iframe { width: 100%; height: 100%; border: 0; border-radius: var(--radius); background: var(--bg-alt); } +.embed iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-alt); } /* ---------- activity timeline ---------- */ -.timeline { position: relative; max-width: 46rem; margin: 0 auto; padding: 0 0 0 3.25rem; list-style: none; } -.timeline::before { content: ""; position: absolute; left: 1.2rem; top: 0.5rem; bottom: 0.5rem; width: 2px; background: var(--border); } -.timeline-item { position: relative; padding-bottom: 2.25rem; } +.timeline { position: relative; max-width: 50rem; margin: 0 auto; padding: 0 0 0 3.5rem; list-style: none; } +.timeline::before { content: ""; position: absolute; left: 1.3rem; top: 0.5rem; bottom: 0.5rem; width: 1px; background: linear-gradient(var(--accent), var(--border) 30%); } +.timeline-item { position: relative; padding-bottom: 2.5rem; } .timeline-item:last-child { padding-bottom: 0; } +.timeline-year { + margin: 0 0 1rem; font-family: var(--font-display); font-size: 2rem; font-weight: 700; letter-spacing: -0.03em; + line-height: 1; color: color-mix(in srgb, var(--muted) 55%, transparent); +} +.timeline-item:not(:first-child) .timeline-year { padding-top: 1rem; } .timeline-icon { - position: absolute; left: -3.25rem; top: 0; width: 2.5rem; height: 2.5rem; - display: grid; place-items: center; font-size: 1.25rem; - background: var(--surface); border: 2px solid var(--border); border-radius: 50%; + position: absolute; left: -3.5rem; width: 2.6rem; height: 2.6rem; + display: grid; place-items: center; color: var(--accent); + background: var(--bg); border: 1px solid var(--border-strong); border-radius: 50%; } -.timeline-date { margin: 0; color: var(--muted); font-size: 0.9rem; font-variant-numeric: tabular-nums; } -.timeline-title { margin: 0.1rem 0 0.35rem; font-size: 1.2rem; } -.timeline-title a { color: var(--text); text-decoration-color: var(--border); } -.timeline-title a:hover { color: var(--link); } -.timeline-item p:last-child { margin-bottom: 0; } +.timeline-icon .icon { width: 1.2rem; height: 1.2rem; } +.timeline-body { padding: 1.1rem 1.35rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); } +.timeline-date { margin: 0; font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); font-variant-numeric: tabular-nums; } +.timeline-title { margin: 0.2rem 0 0.35rem; font-size: 1.2rem; } +.timeline-title a { color: var(--text); text-decoration-color: var(--border-strong); } +.timeline-title a:hover { color: var(--link); text-decoration-color: currentColor; } +.timeline-body p:last-child { margin-bottom: 0; color: var(--muted); } /* ---------- image map (city plans) ---------- */ .imagemap { margin: 0 0 2rem; } -.imagemap-canvas { height: min(70vh, 34rem); border: 1px solid var(--border); border-radius: var(--radius); background: var(--space-bg); } +.imagemap-canvas { height: min(70vh, 34rem); border: 1px solid var(--border); border-radius: var(--radius); background: #05070d; } .imagemap figcaption { margin-top: 0.5rem; color: var(--muted); font-size: 0.9rem; text-align: center; } .map-pin { background: none; border: 0; } .map-pin svg { filter: drop-shadow(0 2px 3px rgb(0 0 0 / 0.5)); } .leaflet-popup-content { font-family: var(--font); line-height: 1.5; } -.leaflet-popup-content h3 { margin: 0 0 0.35rem; font-size: 1rem; color: #121a2b; } +.leaflet-popup-content h3 { margin: 0 0 0.35rem; font-size: 1rem; color: #15171d; } .leaflet-popup-content p { margin: 0 0 0.5rem; color: #2b364d; } -.leaflet-popup-content a { color: #1f4fd8; word-break: break-all; } +.leaflet-popup-content a { color: #b93d12; word-break: break-all; } /* ---------- footer ---------- */ -.site-footer { margin-top: 2rem; padding-block: 2.5rem 1.5rem; background: var(--bg-alt); border-top: 1px solid var(--border); color: var(--muted); font-size: 0.95rem; } -.footer-grid { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); } -.footer-col h2 { margin-bottom: 0.6rem; font-size: 1rem; color: var(--text); } +.site-footer { padding-block: 3.5rem 1.5rem; background: var(--bg-alt); border-top: 1px solid var(--border); color: var(--muted); font-size: 0.93rem; } +.footer-brand { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-bottom: 2rem; margin-bottom: 2rem; border-bottom: 1px solid var(--border); } +.footer-brand .kicker { margin: 0; } +.footer-grid { display: grid; gap: 2rem 3rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); } +.footer-col h2 { margin-bottom: 0.8rem; font-family: var(--font-mono); font-size: 0.75rem; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text); } .footer-col ul { margin: 0; padding: 0; list-style: none; } -.footer-col li { margin-bottom: 0.3rem; } -.footer-col a { color: var(--muted); } -.footer-col a:hover { color: var(--link); } -.footer-legal { margin: 2rem 0 0; padding-top: 1rem; border-top: 1px solid var(--border); font-size: 0.85rem; } +.footer-col li { margin-bottom: 0.35rem; } +.footer-col a { color: var(--muted); text-decoration: none; } +.footer-col a:hover { color: var(--link); text-decoration: underline; } +.footer-legal { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem; margin: 2.5rem 0 0; padding-top: 1.25rem; border-top: 1px solid var(--border); font-family: var(--font-mono); font-size: 0.78rem; } +.footer-legal a { color: var(--muted); text-decoration: none; } +.footer-legal a:hover { color: var(--link); } /* ---------- 404 ---------- */ -.not-found { min-height: 55vh; display: grid; place-items: center; background: none; border: 0; } -.not-found .code { margin: 0; font-size: clamp(4.5rem, 18vw, 10rem); font-weight: 800; line-height: 1; color: var(--accent); } +.not-found { min-height: 60vh; display: grid; place-items: center; text-align: center; border: 0; } +.not-found .lede { margin-inline: auto; } +.not-found .code { margin: 0; font-family: var(--font-display); font-size: clamp(5rem, 20vw, 11rem); font-weight: 700; letter-spacing: -0.06em; line-height: 1; color: var(--accent); } /* ---------- motion and print ---------- */ @media (prefers-reduced-motion: reduce) { @@ -339,7 +521,8 @@ ul, ol { margin: 0 0 1em; } } @media print { - .site-header, .site-footer, .skip-link, .latest { display: none; } - body { background: #fff; color: #000; } - .hero { background: none; color: #000; } + .site-header, .site-footer, .skip-link, .latest, .hero-visual { display: none; } + body, .space { background: #fff; color: #000; } + .space::before, .space::after { display: none; } + .hero h1 { color: #000; background: none; } } diff --git a/assets/js/main.js b/assets/js/main.js index b583b9d..2b15447 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -38,3 +38,28 @@ } }); })(); + +// Live Mars clock on the home page (NASA Mars24 algorithm, Allison & McEwen 2000). +(() => { + const el = document.querySelector('[data-mars-clock]'); + if (!el) return; + const mtc = el.querySelector('[data-mtc]'); + const msd = el.querySelector('[data-msd]'); + const utc = el.querySelector('[data-utc]'); + const TT_MINUS_UTC = 37 + 32.184; // TAI-UTC (leap seconds since 2017) + TT-TAI, in seconds + const pad = (n) => String(Math.floor(n)).padStart(2, '0'); + const hms = (hours) => { + const s = hours * 3600; + return `${pad(s / 3600)}:${pad((s % 3600) / 60)}:${pad(s % 60)}`; + }; + const tick = () => { + const now = Date.now(); + const jdTT = now / 86400000 + 2440587.5 + TT_MINUS_UTC / 86400; + const sol = (jdTT - 2405522.0028779) / 1.0274912517; + mtc.textContent = hms((((sol % 1) + 1) % 1) * 24); + msd.textContent = sol.toFixed(5); + utc.textContent = new Date(now).toISOString().slice(11, 19); + }; + tick(); + setInterval(tick, 1000); +})(); diff --git a/i18n/cn.yaml b/i18n/cn.yaml index 7cdbea8..ca81168 100644 --- a/i18n/cn.yaml +++ b/i18n/cn.yaml @@ -20,3 +20,27 @@ translation: 点击标记查看详情 - id: topics translation: 探索方向 +- id: hero_kicker + translation: 火星 · 伊希地 · 成立于 2062 +- id: about_us + translation: 关于我们 +- id: what_we_do + translation: 我们做什么 +- id: explore + translation: 档案与工具 +- id: explore_lede + translation: 关于地球之外生活的书籍、地图与工具,全部开源。 +- id: all_archives + translation: 全部档案 +- id: all_activities + translation: 全部活动 +- id: mars_time + translation: 火星协调时 MTC +- id: mars_sol + translation: 火星日序 MSD +- id: earth_time + translation: 地球 UTC +- id: clock_note + translation: 实时计算,基于 NASA Mars24 算法 +- id: back_to_top + translation: 回到顶部 diff --git a/i18n/en.yaml b/i18n/en.yaml index bb56b5c..72c0ab7 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -20,3 +20,27 @@ translation: Select a marker for details - id: topics translation: Explore topics +- id: hero_kicker + translation: Isidis, Mars · Est. 2062 +- id: about_us + translation: About us +- id: what_we_do + translation: What we do +- id: explore + translation: Archives and tools +- id: explore_lede + translation: Books, maps and calculators for life beyond Earth, all open source. +- id: all_archives + translation: All archives +- id: all_activities + translation: All activities +- id: mars_time + translation: Coordinated Mars Time +- id: mars_sol + translation: Mars Sol Date +- id: earth_time + translation: Earth UTC +- id: clock_note + translation: Live, computed with the NASA Mars24 algorithm +- id: back_to_top + translation: Back to top diff --git a/layouts/404.html b/layouts/404.html index 3fd3c82..84d90da 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -1,5 +1,5 @@ {{ define "main" }} -
+

{{ i18n "not_found_title" }}

diff --git a/layouts/_default/list.html b/layouts/_default/list.html index 1eeba93..881580b 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -1,5 +1,5 @@ {{ define "main" }} -{{ partial "page-hero.html" (dict "title" .Title "description" .Description) }} +{{ partial "page-hero.html" (dict "title" .Title "description" .Description "kicker" site.Title) }}
{{- with .Content }}
{{ . }}
{{ end }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 4b176c2..47bf585 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -1,5 +1,5 @@ {{ define "main" }} -{{ partial "page-hero.html" (dict "title" .Title "description" .Description "tags" .Params.tags) }} +{{ partial "page-hero.html" (dict "title" .Title "description" .Description "tags" .Params.tags "kicker" site.Title) }}
{{ .Content }} diff --git a/layouts/activities/list.html b/layouts/activities/list.html index b90511a..ec6c453 100644 --- a/layouts/activities/list.html +++ b/layouts/activities/list.html @@ -1,17 +1,22 @@ {{ define "main" }} {{- $d := index site.Data.activities site.Language.Lang -}} -{{ partial "page-hero.html" (dict "title" $d.title "description" $d.description) }} +{{ partial "page-hero.html" (dict "title" $d.title "description" $d.description "kicker" site.Title) }}
    + {{- $year := "" }} {{- range $d.list }} + {{- $y := substr .datetime 0 4 }}
  1. - -

    -

    - {{- if .link }}{{ .title | markdownify | emojify }}{{ else }}{{ .title | markdownify | emojify }}{{ end -}} -

    - {{- with .description }}

    {{ . }}

    {{ end }} + {{- if ne $y $year }}{{ $year = $y }}{{ end }} + {{ partial "icon.html" .icon }} +
    +

    +

    + {{- if .link }}{{ .title | markdownify | emojify }}{{ else }}{{ .title | markdownify | emojify }}{{ end -}} +

    + {{- with .description }}

    {{ . }}

    {{ end }} +
  2. {{- end }}
diff --git a/layouts/archives/list.html b/layouts/archives/list.html index 016c8d8..81975bc 100644 --- a/layouts/archives/list.html +++ b/layouts/archives/list.html @@ -1,13 +1,13 @@ {{ define "main" }} {{- $d := index site.Data.archives site.Language.Lang -}} -{{ partial "page-hero.html" (dict "title" $d.title "description" $d.description) }} +{{ partial "page-hero.html" (dict "title" $d.title "description" $d.description "kicker" site.Title) }}
-
+
{{- range $d.list }} -
{{- end }} -{{- with index site.Data.support site.Language.Lang }} +{{- with index site.Data.topics site.Language.Lang }}
-

{{ .title }}

-
+
+

{{ i18n "topics" }}

+
+
    + {{- range $i, $t := . }} +
  1. {{ .topic }}
  2. + {{- end }} +
+
+
+{{- end }} + +{{- with index site.Data.support site.Language.Lang }} +
+
+
+

{{ .title }}

+
+
{{- range .list }} -
-

{{ .title }}

+
+

{{ .title }}

{{ .content | markdownify }}

{{- end }} diff --git a/layouts/institutes/list.html b/layouts/institutes/list.html index c0f7cc2..e73cb9b 100644 --- a/layouts/institutes/list.html +++ b/layouts/institutes/list.html @@ -1,6 +1,6 @@ {{ define "main" }} {{- $d := index site.Data.institutes site.Language.Lang -}} -{{ partial "page-hero.html" (dict "title" $d.title "description" $d.description "tags" $d.tags) }} +{{ partial "page-hero.html" (dict "title" $d.title "description" $d.description "tags" $d.tags "kicker" site.Title) }}
{{- range $d.list }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index 1e8ee38..6837059 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -1,6 +1,13 @@ {{- $columns := index site.Data.footer site.Language.Lang -}}
+ {{- with $columns }} {{- end }} - +
diff --git a/layouts/partials/icon.html b/layouts/partials/icon.html new file mode 100644 index 0000000..0d3bb41 --- /dev/null +++ b/layouts/partials/icon.html @@ -0,0 +1,25 @@ +{{- /* Line icon for a data-file entry. Takes the entry's emoji `icon` and returns a matching SVG; unknown emoji are shown as-is. */ -}} +{{- $paths := dict + "📖" `` + "🪐" `` + "🏢" `` + "🏙️" `` + "🗺️" `` + "🕒" `` + "☀️" `` + "⭐" `` + "⏳" `` + "📡" `` + "🎫" `` + "🚀" `` + "🧭" `` + "🎓" `` + "🛰️" `` + "🎤" `` + "💬" `` +-}} +{{- with index $paths . -}} + +{{- else -}} + +{{- end -}} diff --git a/layouts/partials/page-hero.html b/layouts/partials/page-hero.html index 466b9ab..e55a9da 100644 --- a/layouts/partials/page-hero.html +++ b/layouts/partials/page-hero.html @@ -1,6 +1,7 @@ -{{- /* Expects a dict with title, and optionally description and tags. */ -}} -
+{{- /* Expects a dict with title, and optionally kicker, description and tags. */ -}} +
+ {{- with .kicker }}

{{ . }}

{{ end }}

{{ .title }}

{{- with .description }}

{{ . }}

{{ end }} {{- with .tags }} diff --git a/static/fonts/OFL-jetbrains-mono.txt b/static/fonts/OFL-jetbrains-mono.txt new file mode 100644 index 0000000..8f7ed67 --- /dev/null +++ b/static/fonts/OFL-jetbrains-mono.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) JetBrainsMono-Italic[wght].ttf: Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/fonts/OFL-space-grotesk.txt b/static/fonts/OFL-space-grotesk.txt new file mode 100644 index 0000000..d5666d7 --- /dev/null +++ b/static/fonts/OFL-space-grotesk.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/fonts/jetbrains-mono-500.woff2 b/static/fonts/jetbrains-mono-500.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..be878e68fa71bc1f08894c0882d07adbe485ef99 GIT binary patch literal 21832 zcmV)CK*GOwPew8T0RR91098l;5C8xG0O8O80954w0RR9100000000000000000000 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 S8#S~?xaXqu;tAo2S~9su2vSq{fi^hG zZr7Po<bZN1nCG8(eo2YFxpm6EjkW4twrGK&5SvIKZ@KfiGC0Oe>gfDx<6UNyd=d<_-sH z5Gi7*Z0{Bt3=zJhzA{C__caI=>12nAxN( zUYjTH26PDhv^x7bBvQ68B|asjlmw#!uw&zZN%Gm?<9X=3jXjfs*WuE;fQgu*n6zDs z$f4?%Du*xF=qI>q8!gN|gw3`6chD6x;3KXI#lB%AO?rc+cC(d!8Mh_0rl*m{DlS5sZ%YgWq%@^jMnm;+@9M6Mn?smkrG zYTy*@k~SS|P_!1bx~Ql>+5Ed%9F0lL72gkc2n{FnfRN>QQNix7$o_mqzMnkIU!F%U zA?GdUgS4*-bGT+X@cUQ!ZTSX?(u|pv5(5hD{$#}_Y9gFSH5JR48dbC!CT!6DRn0QF zVNJJhwqf-*tA;-x*Ry1WWqHq1u|f1J{sP?WrOPcVW-n2ke~@JLY+tuwO(jU4Ol@8! zE6V`y6Oxn!ywS_j%aZ15J)pgOMjw*%f6liuVC*f+reqPxo}NuUd64b4n1T0rsyvl^ zi3Y#lp2;M65_$aB&L79k%uf#f>y;~ItpDs3F4r@wLL;Ed%QTg>U2KEClPB?uMRb#f zd+=XcO0MN(8S?$TTmZeOMlEmCzoNf#6!J>u$A|va{r_72@1StLb!+(nb!FW=?4=`} zxp~?Prbfh9J~a%DR03^YZs4n`fcq=76utA_KtJv0>gr{kJ!yZ;0N$-STw$g7K#Cm8EH`>W92pCCvp0ybSw+htHe9EWFU#LaVv{egq~J<-(eW4^jmLo;pqhhJs|~aT;J`Z% z0BBvA$SGkKDLdbXu4znasmN7B7cLhLNj(ZJYpybnw!2r_8xn?e?+fvl)PK6KUcLVY$Z`~p6}c0f0gu5@A8>IiDe3BvYcYHAdSaSo z(fnRYerx`wZtK{PUpgJ zCTmomqkvzH84a2?6zeb*>`e@`wm3CLnY8sMxr?r}%{HBe=kXe*S>S1jR1>N~5wF*F z6`{I)k9YrEpJ1zXn~Y6 zbhO5LOLE;Kn-i_ni(RyGHN7lvO)B9HViq#u(3GBJv&*$ED)3J(lQ4)6CRSbT7^B@e zix2M;Nmo5B(Bf&wyivhfx5y?C3TLK?*Kd!>Iv6oNmI2ByIG=; zve-(dfml1kt(Ij^{CtO(#NsF%g{bvUdKM|Pt2#R(+Laa419=xHG%F(=otjmu^)4lZ2j;G7U)2tT2_1Q%*R6Hr$}Muc z+)9nnrOc4z6|2ijxV&AgSW(G1J5!RO&^ZB2m)7%zbuwAOuV!hn@q)Fs)|zmZI%HiL z>Brt;Pfj{Rj|VhTSt8HK5V`xgPi0J>p8gaUB!Bd=UT_t^i_m{u62}Y2vE}jci*ZZg z^+HP=jJ>^rzv2|a+vwYSgq8f2r<76~!k$xmKx4zsoo91x3?`9hcJ18thmFKwMt*Z* z=ZOs@8BS4Ot zl68FDvT&?37~};HOXOmc(WBRyJf@Nz`_rZX1AkAvOa1IPe;I#iSG(1H z{TDOX@&J1Pl*AbCd<+aBV-@GeV(0ZfpAm2JdG#)MO?YGPYfH!GEZ{=C`5exC9>iVX zY^MIUSlD0IxmtcAy8=gYms(>SCIj$t?IaP{vRd zm~X?wWqby+qO7cf$>0NtlF#JNW7;JNlSY%Kq*M9g%#Sj&K5Xvm%UPMPggWu0Imjg` zVOW=1YL)`Y6J@{6*$)o9KrWPT|J$CKaU<=igIQFlgN@hH-Yw2ObYmM@h=Vt|{jj{* zUfQpNciPQx1Sk||zMPr$(u0m?WyW7Bb_8XAZkyjCl^}U-n)-yS%mZC8ar78(J8RmH zKej&mZ2e||9@7gp*B|uOdq?0dVs?pHq+sgju;y+t%gxtl3WHUAR|Ef&5G1jtUoI1a zx4(e0kH_0bDcH|F&h8@R$Jp#xKB)`LjkGLSuUa^$aBUwgWeuOxY}i)5mCyI^-Cgap z>I*CrF1t^oL&Bjsr19UbTNm3{z|>OHJzL{j;gdosZxxY2wq4rdOSvfsg;=A9+SX0(a7NK;mUctdG)Qn zl5_XO9=F2}FzL}`=qP?Uv+AeNaHVcWJKSmRE_cSg@5=W)>#zs2EHmX>K}BWZr+^(h zI2Zy&HPdgimEf$*hR;NHDjXF4v?U4PHjqc*$;TVsPbsjkICf_*+7fVb zoBQWAMl#Zx`wL5A>(choL{x>V!kRiSsQb6V58ua^uVA6?&Rf;}&m=dFNaErS2hQAM@3LRs z69&DvxmCRt;q>~KEAK*qC;O#oAvSM0XQD;$vM=`zHj>+;><60&WneSh>Jl>-6a=U{ZC}H z2S$M$$>cG`D6195b0RA-J5@+fm$q(1i}-qc!Nrcr=;boji=qf!S#fy-VZ9Npdu3}G z;3FQ=bG}j0*C6WwhE72wk;k+iifUCIqbL!LAPDopB-Evbs7lcyl|eJ1&TK(6K&?2U zjrw-`4j3P{mM_R-E1HWMqKz5{Ud+-Dcw!B}&qBQb3F|#bLyd=ON$r-JObuYV4=um} zz$$apt64-xgG2I3W=Pv2R)= zlPaVLN>>9eJO5)psK-&)z40dyB}Nx}I_ZOmbkLhYjrH07p5)MQ(5t2Hj=D6W?~b z)pNbk_q^sx$6Yx6pB~$D`-Dvyq6~S4mTDU5XNa{NDQnX=4gyBzR{ zr#|eGZTbdpG@*n@`Fa4D(H?#F>IfW{K z_B}x5`j6I?ND6hjjm8o#gH=uR2(<^*W`}P^j>xY@wH{aF#i1s0&5y$RW07~Yc_j>s z#e!I>Hs`vFf$ehTHjAQ;?D7r1Yx;K5(I$L zeMM?`jngu2o|l{_b$?xrYUOg49&Q-wfWDgx?@c^4KyR$NE>o=E>EE&Ik`Ee3 z15AvIaEuX@+H;7J*qsn4E@C0Nno@zlV+KPrh~W!E6|_rW+|?fMOqn$_*`5HH93i97 z*ieH!uWqCz(xGP0a6F`haLJooU?Jha%?@qVVYWUnH?niBF|ZoU@y}?+d>FAZ4IEie zAs}gpVi1u63nFK#sZ279rS_lua8`$e%aGKjLGUp3%*HI5+IuDm*67)rK=r^=^fo8#CMo+ZQL*zH-8Nu<%Z0VD%3itGrC7WzNDyvhh6QkMNT zBmF7yxyS!Hg^yXYvQi66IiIR_98^?X zNkOE?B|!>p_VPYp4PnVuB-A8@nW48CIj_9oNHsmwBbuKCoB&2!opu`V-7`V#&T=~@ za0cLVtkv355-D69a8Jh!S=(J{*cKFHI5N-k&LWCZd66BrGkhzFi#*{8l~Dj= zo^TL5J;hYf&Ooi52%<*|9h3eu0Fh(X9a~LltevEgl1O#L0snOBSo;egyu<0$`T~N^ z@IuY4N=xl-tdT{Dq}PCP^o3YeY^Na&W%h=_#dZRM|I5szM1=?yAFAV!x8Ys3i4&Y` zs2MsomPvI<+)8WT4GqbrQw&{A7MNBLo58Ue?gd|UNQ8X?{tT*6QU(lCDRQ9myp4wy zw5y#h0a|8gY@lT1hR23Fb6t?=q{f;HC|?}&rTO#}e9E5yQ#nEs?GGB#A^d6X^Zg^A z5%tR_p7Nn4yaJ%ImwQoo2i9P?=$8Za8cIFc` zTqcjQ=I14QwpVGc>shIgbR%+}%49{IR1A83$qo$XVCn#unTseFoxTFpvLTUu6O|W1 z4llGBDRx{G5C`ou;(cBt125l3V0eZT55rDx+`1u`>Rz|z>7qzOUPn>O0__Z&%jsZ4 zW~f3@bGZlOygJ*)_Z(~u*xz?>78Mv%8NS*#8+dAev9iXLWy-3y4*TtDO>(@b?G7VO zF{{f_YHP5RS>Ae>5}uH><>3rAb5g=$c)vDSFfs|N-vn8_DM&J@>Cw&XVk(mXm))eW z8mZ!44^y7_PkBEd$7AJ)QV2Y8C<@gj$3Zo#b-qOB=Hzu|bKRmnf_11QU6$iYJ#tM)&sjN12$wz)M_ztS-ehV zv0|bZlL}rz8;4OzU>i4UeSLDd$gO0`Qj57ZD~wMkT#)@=nz^Tt_$B%Znqw%>cL@(FY<|awP>1XQWM**9uW+ zKt1MZg+U-cP*yOVaINZ{IsNAHvjmkS_`w1z98M547eXl3f`Gtt5@mziS2OZ7-F0P} zP(&#-M8pm#<^Th zyUfY}o|TBzy)o1!Po!n-p;znn$WG{GnkaLvPKB6wsO(vlM?A(ewG?UkyTX$g2A^%x zJ;iK-bPc0$xp3;Fb>_ep$3dF#RMukS~vz-2R9^LQg0mPo5b3E?x7?&hfz6aW6*4Rfbo zC9wV=R6vNmgcVpi7TDqB?{M{M-sgO|-GiOA(4scdOWV0F=^90Z*W-lfReG5awfi|A z0M12{>hJ$d{e#*%n7< zD&nOLo_fmIh~2>0B*x0AftoxT10j8Nqw>kegSN)7Oh%TSD!kaLhYr6_)5g8r2Rv!C z=g@Ud&AJtqLd@$BTqs}|tbf?X=(HwLR4#gKZeGK9feG-iF~-hB*Uqy%4CJ2F_sWBT zeZsSxGHmn^bWSjlptwBk>#e~Te|#rK=o^M!(K6IVVt|k%-Pl!SHwKb;gqyYUkD|CbK~D)hoJP(!uqiR2`B z-1tT50qI22ys1RpvvZ5RrZ2SnpO;Z+fXYm_02O6 z2@JKH>+=C}xKz8STsai)x$YrrI9^>j=$Bm6urp+dG^vEqL#oEzxa9}6BZ9;hfXre7 z?iZIaBwcGgCzS0pL=nMY@Kk`|sG3o!s$y(Qn|-EDk8HDV{`wO~sfXhd7Pu2^((m;2 zKl~j_;xC}yluF`W>%wtFD*_od-sTS@ zUVI6#lO#ATGs%NE1Dj<7QD|&csaevdYtwDpSQTIdTJY3UWuX-l*0pE#Lj%{vLnM}t zvjcI*%F01-zcUIN5|lDLo17JP@O=XqpCr|N{4;#C%+g<)OuD_Hd zOZ}gCPy}sRXw;f@1MN*AjoSf+K{{CLhuu75FwRmI1TQQ=9$4frboqzXP)-R`e9JS^ zajs_=qJ?aO&X^ulO}-;Gnf$oi_5Gxn_#mf}3Oj_SMPFq%i0()8;z}}@n|Hby#+kY2 zhee+Q8VQT@`7=aAg3O71`m8=A4ZAO#tOG~eA%V(T;1Uo#Osrzo$GnjBXIo4_ZI+pl z;8jBc_S|WG96VZ(SAX6V&>8fZ1I+GDLxv-;|47YlePb>r!ID_zpw%{iAVMHwh%l7) z9!$2M$k}nlD^Ir=43Gc-bV`R&1_H4b+Cl5FQXdSZdSe7GzgAv+>V|%afB^KuBOfg( zcvp4VwERQ7Q$cuH>*AX^oxb<%2T^{E;SeDxr*Zq@b_ZexY+LFS@wjQr3UnFoPBeW0M_U@2Af3@D>jQdB0A+zRAN#XofX!m|y@gza?=YI?V z6r&Jb_g~)yD$WJa9PCL@}bCm?ig%Ju~n1H878S6*H&_SwHF-Lb-uj_a(5jH7g= zBIrjIU?t;ul;I0aTZq^kr*4L86P8zU9mt6)jC&+iU0PUJT8b*<_sDDSNe}fK zE5i07M%zQ1b)4dtB=AmmE-r_F6U2ze1m$fQocX`&2g?YT;w+c?Enm1^`#M(&rIKkr zNj(gceq5io3euLr>GjSq0&IV_!1_sjli_hY+a*RXF9VG^!wN_kn&Y}`1kH%W;@FRC zbF^Mq2vI#Q^0z(i)LgEB>oVj0Z)}3V4C7e4cINzm*fEgmS_mv3y;7|S{t6}SV}30;~IpuI8I86<(QtAv0+TT0_AxOHY7(lDzA!&@{9=? z3dVdI4XRwJ>jXj^;-5N8?v*ghsV>EQQ(W zR)%fm&-N_#s5{%a2=2%cl}hao&ru&<9uowy56XpOy9xk|<7~X#n*w*ENzwYzTD^y0 zBU&I@G+Mv63*6oah*dTatwuGif+U)-Y7E<|{nF|wgF!Z`X&ZW+p|mW!y?d26fL3CB zWM=s7lcX{k${~KgKjyb91<=y>t3C22)*Xq+muc1=%o_hb#Q3}CsNd>-rap@ zvW&xEt4XG3{nq4qn}D>^%HF{YX`}J0*1_kBD_^gy{t}m$*RsoPLg-rh)o*>}A6Odm z?)*ampq$~Q1TE8QX@^j0q5S(|M`3ioNpM`ZO-2Hpee4rI`dc#zUVkS{ zDophmMd^-WgY)N=>t+dd3(jW|b6X<<)S@v2y^%6UW;Pnsm6kFFqtTrrvkj{|dIXm6 z%F%|llLc+ioWgV2a;4JqxZo?y0h4(#W0FyWm0Ks)O#v#?ngxVn3;}|e>w1_x-L?4* ziNL1@HI+nRmM4u6xjI-IKUr=v2*I_wax^}g8gXjyl44UaIFS5zbCJkMUY zkvo|LoCl%I0;+|;&Xx{hjVc71 zBn2&P(5#r(SNPGCXe3c&>Y1vIg#@9bR+@1W$JSMuM%CUUKwAyU(VS>fG;!o0DAmn}3SkK~i zZp%?k4V423bi@@jFCjZ$u)TIb&x@~g=o}+cIW+WTC1_=DvRBAF( zal_LQbhD1NM+&vYw0Uf!E4*r3VO)s&7f3%PFesATKFFbp*2oZXQ%3k~VdWl_L2-V{ zRo~|u@*v0wG`v$|&icC+_lt_V#WT?`G^zlna34#(h4eTa3B|~_&D|qbz)6|e7~C)P zxUCmMBT}Aa6uVYU5vQe|)v6JvGpdx+FG0r;E{u3aF>^gZL2*lBl@TrIj%Y(+VCBbd zq#`$O_ap>kDZ$S^*|y{O)O+??c#4z-U76Bk8&M16xO$V%=YiVaqcKK}R6m7}=U1p+ zJgm$#mBz5>aA-=bP4f^HSvN1pq}Syc?h$lDP#tT5*Qv5g)W_z)lo=7BRpi0&;89~c zn;}ZJ_8iLnKX#$SWMcX5BnWcaU7nPb7u4u}{T=a;(W^gpp{AxNwiD>A%2@#lM&Zs{ ziagUCgfQC+Ub)wgvb@T(UnnY6Rgzq>JDSg0#5fA!07J%WfH44h%vz-YPc+v7aB|Zo z#avIrFc?Oru77B5R#}2Tj*tL8K-M zC>-!~rxX=VNU6EdttjBepDR97RRQWFUG<^&To4#6)0LMAYQ09smMEq|v_M~pbyc~o zaRrq>8o1VE3+C6rJkq53_IbI7K)yiCpYvtjK{s#_>lm9;`($ z`YYOrH0)JrgSqyPIa~#uXxP_mEP*ROWjDCkkmL><%oduu-UV_0MDJc}2o@6auT9ye z;L-8h2Y2hkba@eG^`cCnN^dL+UEK);s_dsiQZ`D^<*ls1SYE{Bz?$3!*Jlh)%p9%O zFe}v<630U2-QVlQ1g~nvyw5O!pD`hhnSZKjAWq!iK{W>%HADF)nYNt{Fyse!P6Y=D z?^)0^SmgiI4}FL6S)4f9Guv~{7wjDmE%eVpt_?f5S{62g>*Kn4{Ra2cL5HtuS3#nJ zC@9XTJ!_rj_kntd&5kI;^L_5&+o|WDdv_0GmACTm(z{!aRkd>Ta_{v*3um~wzJ4!A z&ucYz3|3RJaRlrn>ioEhEcENYdVf;&O{4^r3Bj?E?<*$#$S=Y0G|{QQ;yVEZDd zrg)n8JgDv%uOc`egI^*4?oA0b5OJCCyw=dQ`l?8bn^#$y#`l>y|JU$lK1jaYN?OwH zV&eftkbFH~&d*z23fc((?kl(dXwT0Gs-(64(ZH>%4RF6YsL#~4%MWc^=Nkw|lQ_0i zG|($4jLmcjw-I+L6_c7EY6RP6RO-2@=XyBf2KOj~iPT?Q=i8I>Mc`?v;({hlLNcd` z%sCJt8ExKx!q)BtATMyTl44ANwZP^^kzs?bp{7vt!hpR=x}cZ zgDi{YIUJPS*Ur@dys|REm*5pRS3~n-*N7vHF^7=xoyz^_@CH$ov8;}yEk-1ivIL6N z(jB<KDBx-ttq9J)S@~#hchlW-W$xAKPW( z>0LdVbF!Ysd2wnu8KkfBZ#9eEmsfntR^LASd z+l7w@{CFTAtO9t^VBL&OicMo6g+9%9++IXBYfhP<5f_CZB3-o{081auy?^<+%xUzoNq)V@<1ik3LNH9+rhisWcu`#Z;P2gOd}APS*%8P zlEJkB3NI0p2i~PqYYm5pD^r73$<& zuJ$kz(B~}&j+*`E2&}G%A%+Gfhca64r`rL2ZMnPCUpJ>wI5jg6j?ixb?ncp_E=s|5 z#%MhT7#VgC1P>c8hki@$IbUv_ZoR@Cm_%<*0%-}P`6LH$w8a38<SFcA)+Imr0z6j8jT0rhI z&0QgVVJ)v`ag4p>Zr>3}x0_7e&liUbBMphTuoc?1&4g#Q)Pm%cK?ANCNG$xN(;Ym*PAJsZ4l2tx1r65z18tL^&vjVGdAlBN3ToY>-`EYBey zS*eAfAhckZJQP-IEC;xfBS~aDS0kK3hd{uuMK+ZYJ?U2mOsxVaIazkZXuW||^0m`B z-UE|iIY^AK%u690G<*+DZ;aX2x`zNc80t~Aj1FiIJj;e0pECreY1_8wB>}UlKGV7Z zk5$2wH8U4!X$Qi%6oaa|j62Gq-Z}r$047tyN1V$9k;Dpvyzx+c0Vt%UyU7q27VKKE zXPOPg$JY;tUHx}|O?#iK)435RtTc(j__M`!p9d;Is7l(YX&DO7#3n^H&T$0(7hw5L^|(5dnbL^!gtp|Nf<6d zt(~p`Y^=0UkoL?rlNtma(H0DhV4P(PP(1mb6Z&CsS%{sKpHt1w+G>TM6&nNwzD#eG zS3q!wwFJzp(GY>nuvKXw5NyfR9prMZ$!hhg1Z40upp?FMtUwqHxFq%xeFoe1IzhJ@ zTi3Xq`n4kk4?;aV;hyh&|Eos>#>GeP|NeKrbYsLJToUm*lPDYPudC^f%hR9chnWl+ znL_Gr5*bEDT%-ciB6^yL7W*& z(o&6F+uRxmSuGYJPA0@jE9Z5&)6T6OZJc3DfV?7H+qBh`X~HXj14q#aTvNNpqd@`n z1y$+pYbj;zYhzi-?Xv`WK$Td}>k=-Lsl9f~PtV5n<$g>aG>aCXcx-KaR zKwilXxsS{I6O!ww+-7D!1+O#^%~{RdWZB5f1`&`!7%QCPPcyF8nhvAm&r|=S6t`Ak;l~U#2X}hDDV28qhW`ybc`;H*E}6w$SU*m1zq*b}BajpV3phRF@cv z7!jh*^_S5Um6^*HYk>>P!u=u|^@v+hZcj82imuND%{L=lWqoh)~WS%!r#2bIZp|;2Q-hhEh1CzUW#ydIm-&W)@a9b`DOy zAP7mrP(YRHUDvAPJL12cI(lg`)C(d~@Yc#V(g{QkI%K~C&bz>i2Lq#RczWSkxyt3b8}fDZmI62J(#a;f6>}@n+4tV*Dy&mf zM9cxbe5a3YJ$m))GhmKE^UO8hLJJ(U#}uP1GGvUmj(Tr}l_r{OnyID}J3(TCg~mHh z>YJ~=Q~BVd!^})9=E>A(#5md3yW_5z?s@2u)6RSkpwkSk3u%w8PX6LC+LszKnUg8ui+K37$7Nnab^7vp)a=jl0EgnD4+}{4?m5{0 z-kEP4;)Eu)a@sa(NvQnqtQ%ewTU6MffuSc`i!E literal 0 HcmV?d00001 From 0fb6809dcd1a1830c1014b9b6531eee7cee44fda Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 3 Oct 2026 10:47:27 +0000 Subject: [PATCH 2/2] Publish the design as a shared kit at interimm.org/kit/ Splits the shared part of the stylesheet (tokens, fonts, header, footer, buttons, cards, page headers) into assets/kit/interimm.css, moves the header behaviour into assets/kit/interimm.js, and publishes both at stable URLs together with nav.cn.json / nav.en.json generated from the menu and footer data. Other InterImm sites link these instead of copying them, and interimm.js can fill their header and footer from the live menu. Adds a style guide at /kit/ and kit/README.md. The main site looks the same. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01EZdfMMy2aM8X4PGqUv2p7N --- README.md | 3 +- assets/css/main.css | 376 +----------------- assets/js/main.js | 41 -- assets/kit/interimm.css | 373 +++++++++++++++++ assets/kit/interimm.js | 113 ++++++ kit/README.md | 67 ++++ layouts/index.html | 2 +- layouts/partials/head.html | 2 + layouts/partials/kit.html | 41 ++ layouts/partials/scripts.html | 4 + static/{ => kit}/fonts/OFL-jetbrains-mono.txt | 0 static/{ => kit}/fonts/OFL-space-grotesk.txt | 0 .../{ => kit}/fonts/jetbrains-mono-500.woff2 | Bin static/{ => kit}/fonts/space-grotesk.woff2 | Bin static/kit/index.html | 140 +++++++ 15 files changed, 752 insertions(+), 410 deletions(-) create mode 100644 assets/kit/interimm.css create mode 100644 assets/kit/interimm.js create mode 100644 kit/README.md create mode 100644 layouts/partials/kit.html rename static/{ => kit}/fonts/OFL-jetbrains-mono.txt (100%) rename static/{ => kit}/fonts/OFL-space-grotesk.txt (100%) rename static/{ => kit}/fonts/jetbrains-mono-500.woff2 (100%) rename static/{ => kit}/fonts/space-grotesk.woff2 (100%) create mode 100644 static/kit/index.html diff --git a/README.md b/README.md index 7eb6619..d5087cb 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ The site is self-contained: layouts, styles and data live in this repository (th | `i18n/` | Small UI strings (menu label, 404 text, ...) | | `layouts/` | Templates | | `assets/` | CSS and JS, minified and fingerprinted by Hugo at build time | -| `static/` | Files served as-is (images, video, favicons, self-hosted fonts under `fonts/`) | +| `assets/kit/`, `static/kit/` | The shared InterImm kit (styles, fonts, header and footer) that other InterImm sites link from interimm.org/kit/. See [kit/README.md](kit/README.md) | +| `static/` | Files served as-is (images, video, favicons) | ## Deploy diff --git a/assets/css/main.css b/assets/css/main.css index c5310b3..4db0dc3 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -1,273 +1,6 @@ -/* InterImm site styles. - Hand-written, no framework. Colours are tokens on :root and switch with the - visitor's system light/dark preference. Anything with the `space` class - (home hero, page headers, the support band) is always dark. */ - -/* ---------- fonts (self-hosted, SIL OFL; see static/fonts) ---------- */ -@font-face { - font-family: "Space Grotesk"; - src: url("/fonts/space-grotesk.woff2") format("woff2"); - font-weight: 300 700; - font-display: swap; - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2190-2199, U+2212, U+2215; -} -@font-face { - font-family: "JetBrains Mono"; - src: url("/fonts/jetbrains-mono-500.woff2") format("woff2"); - font-weight: 500; - font-display: swap; - unicode-range: U+0000-00FF, U+2000-206F, U+2190-2199; -} - -/* ---------- tokens ---------- */ -:root { - color-scheme: light dark; - - --bg: #f6f5f1; - --bg-alt: #eeece6; - --surface: #ffffff; - --surface-2: #faf9f6; - --text: #15171d; - --muted: #5a6070; - --border: #e2dfd7; - --border-strong: #cfcac0; - --link: #b93d12; - --focus: #d0461a; - --accent: #ff6b3d; - --accent-hover: #ff855e; - --accent-text: #1c0700; - --accent-soft: rgb(255 107 61 / 0.12); - --shadow: 0 1px 2px rgb(20 20 30 / 0.05), 0 12px 32px rgb(20 20 30 / 0.06); - - --radius: 1.1rem; - --wrap: 76rem; - --cjk: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", "Source Han Sans SC"; - --emoji: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji"; - --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", var(--cjk), sans-serif, var(--emoji); - --font-display: "Space Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, var(--cjk), sans-serif, var(--emoji); - --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, var(--cjk), monospace; -} - -/* dark values, shared by the dark scheme and every `.space` block */ -@media (prefers-color-scheme: dark) { - :root { - --bg: #07090f; - --bg-alt: #0b0f18; - --surface: #0f141f; - --surface-2: #131a27; - --text: #e8ebf2; - --muted: #98a1b4; - --border: rgb(255 255 255 / 0.08); - --border-strong: rgb(255 255 255 / 0.16); - --link: #ff9b75; - --focus: #ff9b75; - --accent-soft: rgb(255 107 61 / 0.14); - --shadow: 0 1px 2px rgb(0 0 0 / 0.5), 0 16px 40px rgb(0 0 0 / 0.35); - } - .site-header .brand-mark, .site-footer .brand-mark { filter: invert(1); } -} - -.space { - --bg: #05070d; - --bg-alt: #0a0e17; - --surface: rgb(255 255 255 / 0.04); - --surface-2: rgb(255 255 255 / 0.07); - --text: #eef1f7; - --muted: #a3acc0; - --border: rgb(255 255 255 / 0.1); - --border-strong: rgb(255 255 255 / 0.2); - --link: #ff9b75; - --focus: #ff9b75; - color: var(--text); - position: relative; - isolation: isolate; - overflow: hidden; - background: - radial-gradient(60rem 32rem at 92% -10%, rgb(255 107 61 / 0.22), transparent 60%), - radial-gradient(48rem 36rem at -10% 110%, rgb(88 92 230 / 0.22), transparent 62%), - var(--bg); -} -/* starfield + faint coordinate grid, both static */ -.space::before, .space::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; } -.space::before { - opacity: 0.75; - background-image: - radial-gradient(1.2px 1.2px at 12% 22%, #fff, transparent), - radial-gradient(1px 1px at 31% 71%, #fff, transparent), - radial-gradient(1.5px 1.5px at 52% 14%, #fff, transparent), - radial-gradient(1px 1px at 68% 58%, #fff, transparent), - radial-gradient(1.2px 1.2px at 83% 33%, #fff, transparent), - radial-gradient(1px 1px at 93% 82%, #fff, transparent), - radial-gradient(1px 1px at 22% 92%, #fff, transparent), - radial-gradient(0.8px 0.8px at 44% 44%, #fff, transparent), - radial-gradient(0.8px 0.8px at 76% 8%, #fff, transparent); - background-size: 420px 340px; -} -.space::after { - background-image: - linear-gradient(rgb(255 255 255 / 0.035) 1px, transparent 1px), - linear-gradient(90deg, rgb(255 255 255 / 0.035) 1px, transparent 1px); - background-size: 64px 64px; - -webkit-mask-image: radial-gradient(ellipse at 70% 30%, #000, transparent 70%); - mask-image: radial-gradient(ellipse at 70% 30%, #000, transparent 70%); -} - -/* ---------- base ---------- */ -*, *::before, *::after { box-sizing: border-box; } - -html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; } - -body { - margin: 0; - min-height: 100vh; - min-height: 100dvh; - display: flex; - flex-direction: column; - font-family: var(--font); - font-size: 1.0625rem; - line-height: 1.7; - color: var(--text); - background: var(--bg); - -webkit-font-smoothing: antialiased; -} -main { flex: 1; } - -h1, h2, h3 { - font-family: var(--font-display); font-weight: 600; - line-height: 1.15; letter-spacing: -0.02em; margin: 0 0 0.6em; text-wrap: balance; -} -p { margin: 0 0 1em; text-wrap: pretty; } -img, video, svg { max-width: 100%; height: auto; } -a { color: var(--link); text-underline-offset: 0.2em; } -a:hover { text-decoration-thickness: 2px; } -ul, ol { margin: 0 0 1em; } -::selection { background: var(--accent); color: var(--accent-text); } - -:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 0.3rem; } - -.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; } - -.sr-only { - position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; - overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; -} - -.skip-link { - position: absolute; left: 1rem; top: -4rem; z-index: 100; - padding: 0.6rem 1rem; border-radius: 0.6rem; - background: var(--accent); color: var(--accent-text); font-weight: 600; text-decoration: none; -} -.skip-link:focus { top: 1rem; } - -.text-center { text-align: center; } - -.kicker { - display: inline-flex; align-items: center; gap: 0.6rem; margin: 0 0 1rem; - font-family: var(--font-mono); font-size: 0.78rem; font-weight: 500; - letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); -} -.kicker::before { content: ""; width: 1.5rem; height: 1px; background: var(--accent); } -.kicker:has(.pulse)::before { display: none; } -.pulse { - width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--accent); - box-shadow: 0 0 0 0 rgb(255 107 61 / 0.6); animation: pulse 2.4s infinite; -} -@keyframes pulse { 70% { box-shadow: 0 0 0 0.6rem rgb(255 107 61 / 0); } 100% { box-shadow: 0 0 0 0 rgb(255 107 61 / 0); } } - -.icon { width: 1.5rem; height: 1.5rem; flex: none; } -.icon-emoji { display: inline-grid; place-items: center; font-size: 1.25rem; line-height: 1; } - -/* ---------- header ---------- */ -.site-header { - position: sticky; top: 0; z-index: 50; - background: color-mix(in srgb, var(--bg) 78%, transparent); - -webkit-backdrop-filter: saturate(1.6) blur(14px); - backdrop-filter: saturate(1.6) blur(14px); - border-bottom: 1px solid var(--border); -} -.header-inner { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem 1.25rem; min-height: 4rem; padding-block: 0.5rem; } - -.brand { - display: inline-flex; align-items: center; gap: 0.65rem; - font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; letter-spacing: -0.01em; - color: var(--text); text-decoration: none; -} -.brand-mark { border-radius: 50%; } - -.site-nav { display: flex; flex: 1; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.25rem 1rem; } -.nav-list { display: flex; flex-wrap: wrap; align-items: center; gap: 0.1rem; list-style: none; margin: 0; padding: 0; } - -.nav-link, .dropdown > summary { - display: inline-flex; align-items: center; gap: 0.4rem; - padding: 0.4rem 0.8rem; border-radius: 999px; - color: var(--muted); font-size: 0.95rem; font-weight: 500; text-decoration: none; cursor: pointer; - transition: color 0.15s, background 0.15s; -} -.nav-link:hover, .dropdown > summary:hover, .dropdown[open] > summary { color: var(--text); background: var(--surface-2); } -.nav-link[aria-current="page"], .dropdown[data-current] > summary { color: var(--text); background: var(--accent-soft); } -.lang-link { border: 1px solid var(--border-strong); color: var(--text); } - -.dropdown { position: relative; } -.dropdown > summary { list-style: none; } -.dropdown > summary::-webkit-details-marker { display: none; } -.dropdown > summary::after { - content: ""; width: 0.35em; height: 0.35em; margin-top: -0.2em; - border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); -} -.dropdown-menu { - position: absolute; top: calc(100% + 0.5rem); left: 0; z-index: 60; - min-width: min(19rem, 90vw); margin: 0; padding: 0.4rem; list-style: none; - background: var(--surface); border: 1px solid var(--border-strong); border-radius: 0.9rem; box-shadow: var(--shadow); -} -@media (prefers-color-scheme: dark) { .dropdown-menu { background: #121826; } } -.dropdown-menu a { - display: block; padding: 0.5rem 0.75rem; border-radius: 0.55rem; - color: var(--text); font-size: 0.95rem; text-decoration: none; -} -.dropdown-menu a:hover { background: var(--surface-2); } -.dropdown-menu a[aria-current="page"] { color: var(--link); font-weight: 600; } - -.nav-toggle { - display: none; margin-left: auto; padding: 0.45rem; border: 1px solid var(--border-strong); border-radius: 999px; - background: transparent; color: var(--text); cursor: pointer; -} - -@media (max-width: 58rem) { - .js .nav-toggle { display: inline-flex; } - .js .site-nav { display: none; flex-basis: 100%; padding-bottom: 0.75rem; } - .js .site-nav.is-open { display: flex; flex-direction: column; align-items: stretch; } - .nav-list { flex-direction: column; align-items: stretch; } - .nav-link, .dropdown > summary { border-radius: 0.6rem; font-size: 1rem; } - .nav-tools { flex-direction: row; flex-wrap: wrap; padding-top: 0.5rem; border-top: 1px solid var(--border); } - .dropdown-menu { position: static; min-width: 0; margin: 0.2rem 0 0.4rem 0.75rem; box-shadow: none; } -} - -/* ---------- buttons, chips ---------- */ -.btn { - display: inline-flex; align-items: center; justify-content: center; gap: 0.6ch; - padding: 0.55rem 1.15rem; border: 1px solid var(--border-strong); border-radius: 999px; - background: var(--surface); color: var(--text); font: inherit; font-size: 0.95rem; font-weight: 600; line-height: 1.4; - white-space: nowrap; text-decoration: none; transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s; -} -.btn:hover { border-color: var(--accent); } -.btn span { transition: transform 0.15s; } -.btn:hover span { transform: translateX(3px); } -.btn-primary { background: var(--accent); border-color: transparent; color: var(--accent-text); } -.btn-primary:hover { background: var(--accent-hover); border-color: transparent; box-shadow: 0 8px 30px rgb(255 107 61 / 0.35); } -.btn-ghost { background: transparent; } -.btn-ghost:hover { background: var(--surface-2); border-color: var(--border-strong); } -.btn-lg { padding: 0.8rem 1.6rem; font-size: 1.05rem; } - -.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 0 0 1.25rem; padding: 0; } -.chips li { - padding: 0.2rem 0.85rem; border: 1px solid var(--border-strong); border-radius: 999px; - background: var(--surface); color: var(--muted); font-size: 0.85rem; line-height: 1.6; -} -.chips-small li { padding: 0.05rem 0.65rem; font-size: 0.78rem; } - -.text-link { color: var(--text); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--accent); padding-bottom: 0.1rem; } -.text-link span { display: inline-block; transition: transform 0.15s; } -.text-link:hover span { transform: translateX(3px); } +/* interimm.org page styles. The shared tokens, header, footer, buttons, cards + and page headers live in the kit (assets/kit/interimm.css); this file only + holds layouts used by the main site's own pages. */ /* ---------- home hero ---------- */ .hero { padding-bottom: clamp(2rem, 5vw, 3.5rem); } @@ -346,13 +79,11 @@ ul, ol { margin: 0 0 1em; } .readout div:last-child { grid-column: span 2; } } -/* ---------- sections ---------- */ -.section { padding-block: clamp(3.5rem, 8vw, 6rem); } -.section-alt { background: var(--bg-alt); border-block: 1px solid var(--border); } -.section-head { margin-bottom: clamp(1.75rem, 4vw, 2.75rem); } -.section-head-split { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1.25rem 2rem; } -.section-title { font-size: clamp(1.9rem, 1.2rem + 2.4vw, 3rem); margin-bottom: 0.4rem; } -.section-lede { max-width: 36rem; margin: 0; color: var(--muted); font-size: 1.1rem; } +/* home: featured archive tiles, two of them wide */ +@media (min-width: 64rem) { + .bento-featured:has(> :nth-child(6):last-child) { grid-template-columns: repeat(4, 1fr); } + .bento-featured:has(> :nth-child(6):last-child) > :is(:first-child, :last-child) { grid-column: span 2; } +} /* what we do: three numbered columns */ .pillars { display: grid; gap: 2rem 3rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); } @@ -363,55 +94,6 @@ ul, ol { margin: 0 0 1em; } .pillar p:first-letter { text-transform: uppercase; } .pillar-action { margin: auto 0 0; padding-top: 0.5rem; } -/* tiles (archives and tools) */ -.bento { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 16.5rem), 1fr)); } -@media (min-width: 64rem) { - .section .bento:has(> :nth-child(6):last-child) { grid-template-columns: repeat(4, 1fr); } - .section .bento:has(> :nth-child(6):last-child) > :is(:first-child, :last-child) { grid-column: span 2; } -} -.tile { - position: relative; display: flex; flex-direction: column; - padding: 1.5rem; border: 1px solid var(--border); border-radius: var(--radius); - background: linear-gradient(180deg, var(--surface-2), var(--surface)); -} -.tile > :last-child { margin-bottom: 0; } -.tile-icon { - display: inline-grid; place-items: center; width: 2.75rem; height: 2.75rem; margin-bottom: 1.25rem; - border-radius: 0.75rem; background: var(--accent-soft); color: var(--accent); -} -.tile-title { font-size: 1.2rem; margin-bottom: 0.4rem; } -.tile p { color: var(--muted); font-size: 0.97rem; } -.tile .card-cta { color: var(--text); } - -/* generic cards (inner pages) */ -.card-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); } -.card { - position: relative; display: flex; flex-direction: column; - padding: 1.5rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); -} -.card > :last-child { margin-bottom: 0; } -.card-title { font-size: 1.25rem; margin-bottom: 0.5rem; } -.card-cta { margin: auto 0 0; padding-top: 0.75rem; color: var(--link); font-size: 0.92rem; font-weight: 600; } -.card-cta span { display: inline-block; color: var(--accent); transition: transform 0.15s; } -.card-wide { max-width: 54rem; margin-inline: auto; width: 100%; } - -/* whole card is clickable through its title link */ -.card-link-wrap { transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s; } -.card-link-wrap:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: var(--shadow); } -.card-link-wrap:hover .card-cta span { transform: translateX(4px); } -.card-link { color: var(--text); text-decoration: none; } -.card-link::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); } -.card-link:focus-visible { outline: none; } -.card-link:focus-visible::after { outline: 2px solid var(--focus); outline-offset: 3px; } - -.card-media { padding: 0; overflow: hidden; } -.card-media .card-image { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--bg-alt); } -.card-media .card-body { padding: 1.25rem 1.5rem 1.5rem; } - -.stack { display: grid; gap: 1.5rem; } -.figure { margin: 1rem 0 0; padding: 1rem; background: #fff; border-radius: 0.75rem; text-align: center; } -.figure img { max-height: 32rem; width: auto; margin-inline: auto; } - /* research topics: numbered link rows */ .topic-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr)); column-gap: 3rem; margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--border); } .topic-list a { @@ -434,24 +116,6 @@ ul, ol { margin: 0 0 1em; } .support-item, .support-item + .support-item { padding: 1.25rem 0 0.25rem; border-left: 0; border-bottom: 1px solid var(--border); } } -/* ---------- inner pages ---------- */ -.page-hero { padding-block: clamp(3.5rem, 9vw, 6.5rem) clamp(2.5rem, 6vw, 4rem); border-bottom: 1px solid var(--border); } -.page-hero h1 { font-size: clamp(2.4rem, 1.4rem + 4vw, 4.25rem); letter-spacing: -0.035em; margin-bottom: 0.3em; } -.page-hero h1:lang(zh) { letter-spacing: 0; } -.page-hero .lede { max-width: 44rem; margin: 0 0 1rem; color: var(--muted); font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem); } -.page-hero .chips { margin: 1rem 0 0; } - -.prose { max-width: 46rem; } -.prose > * { margin-inline: 0; } -.prose h2 { margin-top: 2em; font-size: 1.75rem; } -.prose h3 { margin-top: 1.6em; font-size: 1.3rem; } -.prose img, .prose video { border-radius: 0.75rem; } -.prose-wide { max-width: 66rem; } -.prose-wide > p, .prose-wide > h2, .prose-wide > h3, .prose-wide > ul, .prose-wide > ol { max-width: 46rem; margin-inline: auto; } -.wrap.prose { margin-inline: auto; } -:lang(zh) { line-height: 1.85; } -:lang(zh) .tile p, :lang(zh) .card p, :lang(zh) .timeline p { line-height: 1.75; } - /* about page: media + text side by side */ .split { display: grid; gap: 2rem 3rem; align-items: center; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); margin-top: 2rem; } .split-media { margin: 0; } @@ -495,34 +159,12 @@ ul, ol { margin: 0 0 1em; } .leaflet-popup-content p { margin: 0 0 0.5rem; color: #2b364d; } .leaflet-popup-content a { color: #b93d12; word-break: break-all; } -/* ---------- footer ---------- */ -.site-footer { padding-block: 3.5rem 1.5rem; background: var(--bg-alt); border-top: 1px solid var(--border); color: var(--muted); font-size: 0.93rem; } -.footer-brand { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-bottom: 2rem; margin-bottom: 2rem; border-bottom: 1px solid var(--border); } -.footer-brand .kicker { margin: 0; } -.footer-grid { display: grid; gap: 2rem 3rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); } -.footer-col h2 { margin-bottom: 0.8rem; font-family: var(--font-mono); font-size: 0.75rem; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text); } -.footer-col ul { margin: 0; padding: 0; list-style: none; } -.footer-col li { margin-bottom: 0.35rem; } -.footer-col a { color: var(--muted); text-decoration: none; } -.footer-col a:hover { color: var(--link); text-decoration: underline; } -.footer-legal { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem; margin: 2.5rem 0 0; padding-top: 1.25rem; border-top: 1px solid var(--border); font-family: var(--font-mono); font-size: 0.78rem; } -.footer-legal a { color: var(--muted); text-decoration: none; } -.footer-legal a:hover { color: var(--link); } - /* ---------- 404 ---------- */ .not-found { min-height: 60vh; display: grid; place-items: center; text-align: center; border: 0; } .not-found .lede { margin-inline: auto; } .not-found .code { margin: 0; font-family: var(--font-display); font-size: clamp(5rem, 20vw, 11rem); font-weight: 700; letter-spacing: -0.06em; line-height: 1; color: var(--accent); } -/* ---------- motion and print ---------- */ -@media (prefers-reduced-motion: reduce) { - html { scroll-behavior: auto; } - *, *::before, *::after { transition: none !important; animation: none !important; } -} - @media print { - .site-header, .site-footer, .skip-link, .latest, .hero-visual { display: none; } - body, .space { background: #fff; color: #000; } - .space::before, .space::after { display: none; } + .latest, .hero-visual { display: none; } .hero h1 { color: #000; background: none; } } diff --git a/assets/js/main.js b/assets/js/main.js index 2b15447..fb3503a 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,44 +1,3 @@ -// Progressive enhancement for the site header. Without JavaScript the menu is -// simply always visible and the dropdowns are native
elements. -(() => { - const toggle = document.querySelector('.nav-toggle'); - const nav = document.getElementById('site-nav'); - const dropdowns = Array.from(document.querySelectorAll('.dropdown')); - - const setMenu = (open) => { - toggle.setAttribute('aria-expanded', String(open)); - nav.classList.toggle('is-open', open); - }; - - if (toggle && nav) { - toggle.addEventListener('click', () => { - setMenu(toggle.getAttribute('aria-expanded') !== 'true'); - }); - } - - const closeDropdowns = (except) => { - dropdowns.forEach((d) => { if (d !== except) d.open = false; }); - }; - - // One dropdown open at a time; close on outside click and on Escape. - dropdowns.forEach((d) => { - d.addEventListener('toggle', () => { if (d.open) closeDropdowns(d); }); - }); - document.addEventListener('click', (e) => { - if (!e.target.closest('.dropdown')) closeDropdowns(); - }); - document.addEventListener('keydown', (e) => { - if (e.key !== 'Escape') return; - const open = dropdowns.find((d) => d.open); - closeDropdowns(); - if (open) open.querySelector('summary').focus(); - else if (toggle && toggle.getAttribute('aria-expanded') === 'true') { - setMenu(false); - toggle.focus(); - } - }); -})(); - // Live Mars clock on the home page (NASA Mars24 algorithm, Allison & McEwen 2000). (() => { const el = document.querySelector('[data-mars-clock]'); diff --git a/assets/kit/interimm.css b/assets/kit/interimm.css new file mode 100644 index 0000000..bece0f9 --- /dev/null +++ b/assets/kit/interimm.css @@ -0,0 +1,373 @@ +/* InterImm kit: the shared look of every InterImm site. + + Source of truth: InterImm/interimm.github.io (branch `hugo`), assets/kit/. + Published at https://interimm.org/kit/interimm.css with its fonts and + https://interimm.org/kit/interimm.js. Other sites link those URLs instead of + copying them, so they pick up changes automatically. See kit/README.md. + + Hand-written, no framework. Colours are tokens on :root and switch with the + visitor's system light/dark preference. Anything with the `space` class is + always dark. Keep changes additive: other sites depend on these class names. */ + +/* ---------- fonts (self-hosted, SIL OFL; see static/kit/fonts) ---------- */ +@font-face { + font-family: "Space Grotesk"; + src: url("fonts/space-grotesk.woff2") format("woff2"); + font-weight: 300 700; + font-display: swap; + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2190-2199, U+2212, U+2215; +} +@font-face { + font-family: "JetBrains Mono"; + src: url("fonts/jetbrains-mono-500.woff2") format("woff2"); + font-weight: 500; + font-display: swap; + unicode-range: U+0000-00FF, U+2000-206F, U+2190-2199; +} + +/* ---------- tokens ---------- */ +:root { + color-scheme: light dark; + + --bg: #f6f5f1; + --bg-alt: #eeece6; + --surface: #ffffff; + --surface-2: #faf9f6; + --text: #15171d; + --muted: #5a6070; + --border: #e2dfd7; + --border-strong: #cfcac0; + --link: #b93d12; + --focus: #d0461a; + --accent: #ff6b3d; + --accent-hover: #ff855e; + --accent-text: #1c0700; + --accent-soft: rgb(255 107 61 / 0.12); + --shadow: 0 1px 2px rgb(20 20 30 / 0.05), 0 12px 32px rgb(20 20 30 / 0.06); + + --radius: 1.1rem; + --wrap: 76rem; + --cjk: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", "Source Han Sans SC"; + --emoji: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji"; + --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", var(--cjk), sans-serif, var(--emoji); + --font-display: "Space Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, var(--cjk), sans-serif, var(--emoji); + --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, var(--cjk), monospace; +} + +/* dark values, shared by the dark scheme and every `.space` block */ +@media (prefers-color-scheme: dark) { + :root { + --bg: #07090f; + --bg-alt: #0b0f18; + --surface: #0f141f; + --surface-2: #131a27; + --text: #e8ebf2; + --muted: #98a1b4; + --border: rgb(255 255 255 / 0.08); + --border-strong: rgb(255 255 255 / 0.16); + --link: #ff9b75; + --focus: #ff9b75; + --accent-soft: rgb(255 107 61 / 0.14); + --shadow: 0 1px 2px rgb(0 0 0 / 0.5), 0 16px 40px rgb(0 0 0 / 0.35); + } + .site-header .brand-mark, .site-footer .brand-mark { filter: invert(1); } +} + +.space { + --bg: #05070d; + --bg-alt: #0a0e17; + --surface: rgb(255 255 255 / 0.04); + --surface-2: rgb(255 255 255 / 0.07); + --text: #eef1f7; + --muted: #a3acc0; + --border: rgb(255 255 255 / 0.1); + --border-strong: rgb(255 255 255 / 0.2); + --link: #ff9b75; + --focus: #ff9b75; + color: var(--text); + position: relative; + isolation: isolate; + overflow: hidden; + background: + radial-gradient(60rem 32rem at 92% -10%, rgb(255 107 61 / 0.22), transparent 60%), + radial-gradient(48rem 36rem at -10% 110%, rgb(88 92 230 / 0.22), transparent 62%), + var(--bg); +} +/* starfield + faint coordinate grid, both static */ +.space::before, .space::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; } +.space::before { + opacity: 0.75; + background-image: + radial-gradient(1.2px 1.2px at 12% 22%, #fff, transparent), + radial-gradient(1px 1px at 31% 71%, #fff, transparent), + radial-gradient(1.5px 1.5px at 52% 14%, #fff, transparent), + radial-gradient(1px 1px at 68% 58%, #fff, transparent), + radial-gradient(1.2px 1.2px at 83% 33%, #fff, transparent), + radial-gradient(1px 1px at 93% 82%, #fff, transparent), + radial-gradient(1px 1px at 22% 92%, #fff, transparent), + radial-gradient(0.8px 0.8px at 44% 44%, #fff, transparent), + radial-gradient(0.8px 0.8px at 76% 8%, #fff, transparent); + background-size: 420px 340px; +} +.space::after { + background-image: + linear-gradient(rgb(255 255 255 / 0.035) 1px, transparent 1px), + linear-gradient(90deg, rgb(255 255 255 / 0.035) 1px, transparent 1px); + background-size: 64px 64px; + -webkit-mask-image: radial-gradient(ellipse at 70% 30%, #000, transparent 70%); + mask-image: radial-gradient(ellipse at 70% 30%, #000, transparent 70%); +} + +/* ---------- base ---------- */ +*, *::before, *::after { box-sizing: border-box; } + +html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; } + +body { + margin: 0; + min-height: 100vh; + min-height: 100dvh; + display: flex; + flex-direction: column; + font-family: var(--font); + font-size: 1.0625rem; + line-height: 1.7; + color: var(--text); + background: var(--bg); + -webkit-font-smoothing: antialiased; +} +main { flex: 1; } + +h1, h2, h3 { + font-family: var(--font-display); font-weight: 600; + line-height: 1.15; letter-spacing: -0.02em; margin: 0 0 0.6em; text-wrap: balance; +} +p { margin: 0 0 1em; text-wrap: pretty; } +img, video, svg { max-width: 100%; height: auto; } +a { color: var(--link); text-underline-offset: 0.2em; } +a:hover { text-decoration-thickness: 2px; } +ul, ol { margin: 0 0 1em; } +::selection { background: var(--accent); color: var(--accent-text); } + +:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 0.3rem; } + +.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; } + +.sr-only { + position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; + overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; +} + +.skip-link { + position: absolute; left: 1rem; top: -4rem; z-index: 100; + padding: 0.6rem 1rem; border-radius: 0.6rem; + background: var(--accent); color: var(--accent-text); font-weight: 600; text-decoration: none; +} +.skip-link:focus { top: 1rem; } + +.text-center { text-align: center; } + +.kicker { + display: inline-flex; align-items: center; gap: 0.6rem; margin: 0 0 1rem; + font-family: var(--font-mono); font-size: 0.78rem; font-weight: 500; + letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); +} +.kicker::before { content: ""; width: 1.5rem; height: 1px; background: var(--accent); } +.kicker:has(.pulse)::before { display: none; } +.pulse { + width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--accent); + box-shadow: 0 0 0 0 rgb(255 107 61 / 0.6); animation: pulse 2.4s infinite; +} +@keyframes pulse { 70% { box-shadow: 0 0 0 0.6rem rgb(255 107 61 / 0); } 100% { box-shadow: 0 0 0 0 rgb(255 107 61 / 0); } } + +.icon { width: 1.5rem; height: 1.5rem; flex: none; } +.icon-emoji { display: inline-grid; place-items: center; font-size: 1.25rem; line-height: 1; } + +/* ---------- header ---------- */ +.site-header { + position: sticky; top: 0; z-index: 50; + background: color-mix(in srgb, var(--bg) 78%, transparent); + -webkit-backdrop-filter: saturate(1.6) blur(14px); + backdrop-filter: saturate(1.6) blur(14px); + border-bottom: 1px solid var(--border); +} +.header-inner { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem 1.25rem; min-height: 4rem; padding-block: 0.5rem; } + +.brand { + display: inline-flex; align-items: center; gap: 0.65rem; + font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; letter-spacing: -0.01em; + color: var(--text); text-decoration: none; +} +.brand-mark { border-radius: 50%; } + +.site-nav { display: flex; flex: 1; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.25rem 1rem; } +.nav-list { display: flex; flex-wrap: wrap; align-items: center; gap: 0.1rem; list-style: none; margin: 0; padding: 0; } + +.nav-link, .dropdown > summary { + display: inline-flex; align-items: center; gap: 0.4rem; + padding: 0.4rem 0.8rem; border-radius: 999px; + color: var(--muted); font-size: 0.95rem; font-weight: 500; text-decoration: none; cursor: pointer; + transition: color 0.15s, background 0.15s; +} +.nav-link:hover, .dropdown > summary:hover, .dropdown[open] > summary { color: var(--text); background: var(--surface-2); } +.nav-link[aria-current="page"], .dropdown[data-current] > summary { color: var(--text); background: var(--accent-soft); } +.lang-link { border: 1px solid var(--border-strong); color: var(--text); } + +.dropdown { position: relative; } +.dropdown > summary { list-style: none; } +.dropdown > summary::-webkit-details-marker { display: none; } +.dropdown > summary::after { + content: ""; width: 0.35em; height: 0.35em; margin-top: -0.2em; + border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); +} +.dropdown-menu { + position: absolute; top: calc(100% + 0.5rem); left: 0; z-index: 60; + min-width: min(19rem, 90vw); margin: 0; padding: 0.4rem; list-style: none; + background: var(--surface); border: 1px solid var(--border-strong); border-radius: 0.9rem; box-shadow: var(--shadow); +} +@media (prefers-color-scheme: dark) { .dropdown-menu { background: #121826; } } +.dropdown-menu a { + display: block; padding: 0.5rem 0.75rem; border-radius: 0.55rem; + color: var(--text); font-size: 0.95rem; text-decoration: none; +} +.dropdown-menu a:hover { background: var(--surface-2); } +.dropdown-menu a[aria-current="page"] { color: var(--link); font-weight: 600; } + +.nav-toggle { + display: none; margin-left: auto; padding: 0.45rem; border: 1px solid var(--border-strong); border-radius: 999px; + background: transparent; color: var(--text); cursor: pointer; +} + +@media (max-width: 58rem) { + .js .nav-toggle { display: inline-flex; } + .js .site-nav { display: none; flex-basis: 100%; padding-bottom: 0.75rem; } + .js .site-nav.is-open { display: flex; flex-direction: column; align-items: stretch; } + .nav-list { flex-direction: column; align-items: stretch; } + .nav-link, .dropdown > summary { border-radius: 0.6rem; font-size: 1rem; } + .nav-tools { flex-direction: row; flex-wrap: wrap; padding-top: 0.5rem; border-top: 1px solid var(--border); } + .dropdown-menu { position: static; min-width: 0; margin: 0.2rem 0 0.4rem 0.75rem; box-shadow: none; } +} + +/* ---------- buttons, chips ---------- */ +.btn { + display: inline-flex; align-items: center; justify-content: center; gap: 0.6ch; + padding: 0.55rem 1.15rem; border: 1px solid var(--border-strong); border-radius: 999px; + background: var(--surface); color: var(--text); font: inherit; font-size: 0.95rem; font-weight: 600; line-height: 1.4; + white-space: nowrap; text-decoration: none; transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s; +} +.btn:hover { border-color: var(--accent); } +.btn span { transition: transform 0.15s; } +.btn:hover span { transform: translateX(3px); } +.btn-primary { background: var(--accent); border-color: transparent; color: var(--accent-text); } +.btn-primary:hover { background: var(--accent-hover); border-color: transparent; box-shadow: 0 8px 30px rgb(255 107 61 / 0.35); } +.btn-ghost { background: transparent; } +.btn-ghost:hover { background: var(--surface-2); border-color: var(--border-strong); } +.btn-lg { padding: 0.8rem 1.6rem; font-size: 1.05rem; } + +.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 0 0 1.25rem; padding: 0; } +.chips li { + padding: 0.2rem 0.85rem; border: 1px solid var(--border-strong); border-radius: 999px; + background: var(--surface); color: var(--muted); font-size: 0.85rem; line-height: 1.6; +} +.chips-small li { padding: 0.05rem 0.65rem; font-size: 0.78rem; } + +.text-link { color: var(--text); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--accent); padding-bottom: 0.1rem; } +.text-link span { display: inline-block; transition: transform 0.15s; } +.text-link:hover span { transform: translateX(3px); } + +/* ---------- sections ---------- */ +.section { padding-block: clamp(3.5rem, 8vw, 6rem); } +.section-alt { background: var(--bg-alt); border-block: 1px solid var(--border); } +.section-head { margin-bottom: clamp(1.75rem, 4vw, 2.75rem); } +.section-head-split { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1.25rem 2rem; } +.section-title { font-size: clamp(1.9rem, 1.2rem + 2.4vw, 3rem); margin-bottom: 0.4rem; } +.section-lede { max-width: 36rem; margin: 0; color: var(--muted); font-size: 1.1rem; } + +/* tiles (archives and tools) */ +.bento { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 16.5rem), 1fr)); } +.tile { + position: relative; display: flex; flex-direction: column; + padding: 1.5rem; border: 1px solid var(--border); border-radius: var(--radius); + background: linear-gradient(180deg, var(--surface-2), var(--surface)); +} +.tile > :last-child { margin-bottom: 0; } +.tile-icon { + display: inline-grid; place-items: center; width: 2.75rem; height: 2.75rem; margin-bottom: 1.25rem; + border-radius: 0.75rem; background: var(--accent-soft); color: var(--accent); +} +.tile-title { font-size: 1.2rem; margin-bottom: 0.4rem; } +.tile p { color: var(--muted); font-size: 0.97rem; } +.tile .card-cta { color: var(--text); } + +/* generic cards (inner pages) */ +.card-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); } +.card { + position: relative; display: flex; flex-direction: column; + padding: 1.5rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); +} +.card > :last-child { margin-bottom: 0; } +.card-title { font-size: 1.25rem; margin-bottom: 0.5rem; } +.card-cta { margin: auto 0 0; padding-top: 0.75rem; color: var(--link); font-size: 0.92rem; font-weight: 600; } +.card-cta span { display: inline-block; color: var(--accent); transition: transform 0.15s; } +.card-wide { max-width: 54rem; margin-inline: auto; width: 100%; } + +/* whole card is clickable through its title link */ +.card-link-wrap { transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s; } +.card-link-wrap:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: var(--shadow); } +.card-link-wrap:hover .card-cta span { transform: translateX(4px); } +.card-link { color: var(--text); text-decoration: none; } +.card-link::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); } +.card-link:focus-visible { outline: none; } +.card-link:focus-visible::after { outline: 2px solid var(--focus); outline-offset: 3px; } + +.card-media { padding: 0; overflow: hidden; } +.card-media .card-image { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--bg-alt); } +.card-media .card-body { padding: 1.25rem 1.5rem 1.5rem; } + +.stack { display: grid; gap: 1.5rem; } +.figure { margin: 1rem 0 0; padding: 1rem; background: #fff; border-radius: 0.75rem; text-align: center; } +.figure img { max-height: 32rem; width: auto; margin-inline: auto; } + +/* ---------- inner pages ---------- */ +.page-hero { padding-block: clamp(3.5rem, 9vw, 6.5rem) clamp(2.5rem, 6vw, 4rem); border-bottom: 1px solid var(--border); } +.page-hero h1 { font-size: clamp(2.4rem, 1.4rem + 4vw, 4.25rem); letter-spacing: -0.035em; margin-bottom: 0.3em; } +.page-hero h1:lang(zh) { letter-spacing: 0; } +.page-hero .lede { max-width: 44rem; margin: 0 0 1rem; color: var(--muted); font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem); } +.page-hero .chips { margin: 1rem 0 0; } + +.prose { max-width: 46rem; } +.prose > * { margin-inline: 0; } +.prose h2 { margin-top: 2em; font-size: 1.75rem; } +.prose h3 { margin-top: 1.6em; font-size: 1.3rem; } +.prose img, .prose video { border-radius: 0.75rem; } +.prose-wide { max-width: 66rem; } +.prose-wide > p, .prose-wide > h2, .prose-wide > h3, .prose-wide > ul, .prose-wide > ol { max-width: 46rem; margin-inline: auto; } +.wrap.prose { margin-inline: auto; } +:lang(zh) { line-height: 1.85; } +:lang(zh) .tile p, :lang(zh) .card p, :lang(zh) .timeline p { line-height: 1.75; } + +/* ---------- footer ---------- */ +.site-footer { padding-block: 3.5rem 1.5rem; background: var(--bg-alt); border-top: 1px solid var(--border); color: var(--muted); font-size: 0.93rem; } +.footer-brand { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-bottom: 2rem; margin-bottom: 2rem; border-bottom: 1px solid var(--border); } +.footer-brand .kicker { margin: 0; } +.footer-grid { display: grid; gap: 2rem 3rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); } +.footer-col h2 { margin-bottom: 0.8rem; font-family: var(--font-mono); font-size: 0.75rem; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text); } +.footer-col ul { margin: 0; padding: 0; list-style: none; } +.footer-col li { margin-bottom: 0.35rem; } +.footer-col a { color: var(--muted); text-decoration: none; } +.footer-col a:hover { color: var(--link); text-decoration: underline; } +.footer-legal { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem; margin: 2.5rem 0 0; padding-top: 1.25rem; border-top: 1px solid var(--border); font-family: var(--font-mono); font-size: 0.78rem; } +.footer-legal a { color: var(--muted); text-decoration: none; } +.footer-legal a:hover { color: var(--link); } + +/* ---------- motion and print ---------- */ +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + *, *::before, *::after { transition: none !important; animation: none !important; } +} + +@media print { + .site-header, .site-footer, .skip-link { display: none; } + body, .space { background: #fff; color: #000; } + .space::before, .space::after { display: none; } +} diff --git a/assets/kit/interimm.js b/assets/kit/interimm.js new file mode 100644 index 0000000..2a60b8c --- /dev/null +++ b/assets/kit/interimm.js @@ -0,0 +1,113 @@ +// InterImm kit: shared header and footer for every InterImm site. +// +// Source of truth: InterImm/interimm.github.io (branch `hugo`), assets/kit/. +// Published at https://interimm.org/kit/interimm.js. See kit/README.md. +// +// 1. On a page that marks its header with `data-interimm-header` (and its +// footer with `data-interimm-footer`), it replaces them with the current +// interimm.org menu and footer, read from nav..json next to this +// script. The page's own markup stays as the fallback if that fails. +// 2. On every page it wires up the header menu: the mobile toggle and one +// dropdown open at a time. Without JavaScript the menu is simply always +// visible and the dropdowns are native
elements. +(() => { + document.documentElement.classList.add('js'); + const script = document.currentScript; + const base = script ? new URL('.', script.src) : new URL('/kit/', location.href); + + const esc = (s) => String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]); + + const GITHUB_ICON = ''; + const MENU_ICON = ''; + + const renderHeader = (nav, current) => { + const link = (item) => `${esc(item.name)}`; + const items = nav.menu.map((item) => { + if (item.children && item.children.length) { + const open = item.children.some((c) => c.id === current) ? ' data-current' : ''; + return ``; + } + return `
{{ i18n "all_archives" }}
-
+