diff options
Diffstat (limited to '')
32 files changed, 7438 insertions, 0 deletions
diff --git a/assets/css/fonts.css b/assets/css/fonts.css new file mode 100644 index 0000000..26ddd8a --- /dev/null +++ b/assets/css/fonts.css @@ -0,0 +1,229 @@ +/* ========================================================================== + Font Declarations + Separated from site.css for faster initial CSS parsing. + ========================================================================== */ + +/* --- Inter (Google Fonts, self-hosted woff2) --- */ + +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* --- JetBrains Mono (self-hosted; CSP-safe) --- */ +@font-face { + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/assets/fonts/jetbrains-mono-400.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/assets/fonts/jetbrains-mono-700.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* --- Source Code Pro (legacy fallback, self-hosted) --- */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400 700; + font-display: swap; + src: url(/assets/fonts/source-code-pro-latin.woff2) format('woff2'); +} + +/* --- Anonymous Pro (Google Fonts, external) --- */ +@import url('https://fonts.googleapis.com/css2?family=Anonymous+Pro:ital,wght@0,400;0,700;1,400;1,700&display=swap'); diff --git a/assets/css/inline-attrs.css b/assets/css/inline-attrs.css new file mode 100644 index 0000000..2dce580 --- /dev/null +++ b/assets/css/inline-attrs.css @@ -0,0 +1,31 @@ +.s1da9facb4d{margin:0;} +.s6e250fe32e{border:none;border-top:1px solid #caa;margin:1rem 0;} +.s2a2536eebb{margin: 15px 0;} +.sd078564312{border:1px solid #ffd; display:block; margin-bottom:6px;} +.sd82634530e{background: transparent; + border:1px solid transparent; + color:#3a2a00; + padding:10px; + width:100%; + border-radius:4px;} +.sefd85b92cb{display: flex; flex-direction: column; gap: 20px;} +.s0b3fba4969{border: 1px solid var(--border); border-radius: var(--r);} +.see3e7269f8{height:700px; border: 1px solid var(--border); border-radius: var(--r);} +.s9572e08b37{width:150px;opacity:0.7;} +.se7f7a3d62d{border:1px solid var(--border);border-radius:var(--r);padding:var(--space-md);background:var(--bg);overflow:auto;} +.s06eeebc88f{max-width: 100%; height: auto;} +.s386d82bd1c{height:1100px;} +.s7e8ca45906{font-size: 50px;} +.s0667eb5585{max-width:160px;border:1px solid var(--border);border-radius:var(--r);background:var(--bg);} +.sed328f664c{min-height:360px;} +.s63501a3337{border:1px solid var(--border);border-radius:var(--r);background:var(--bg);} +.saf481e1471{width:100%;max-width:560px;height:315px;border:1px solid var(--border);border-radius:var(--r);} +.sb83d4c5326{max-width:720px;margin:0 auto;border:1px solid var(--border);border-radius:var(--r);background:var(--bg);} +.sd1a2ffa0b4{text-align:center;margin-top:var(--space-md);} +.sdac4fe6c9b{text-align:center;} +.sfed215d685{max-width:420px;margin:0 auto;border:1px solid var(--border);border-radius:var(--r);background:var(--bg);} +.s16a8a8b00c{overflow:auto;} +.s473e6bbfeb{width:100%;border-collapse:collapse;} +.sf2e940dbbf{text-align:left;border-bottom:1px solid var(--border);padding:8px;} +.s6f279abaab{padding:8px;border-bottom:1px dotted var(--border);} +.s44cd1236df{padding:8px;} diff --git a/assets/css/nav.css b/assets/css/nav.css new file mode 100644 index 0000000..e89f92d --- /dev/null +++ b/assets/css/nav.css @@ -0,0 +1,474 @@ +/* ========================================================================== + nav.css — header-only styles for the shared cross-site nav (nav.js). + + This is a SCOPED subset of site.css: only the design tokens + header / menu + / language-dropdown rules. It deliberately omits site.css's base element + rules (body, p, a, h*, input, button, section…) so dropping the shared nav + onto a sibling site does NOT restyle that site's own content. + + Keep header-related rules here in sync with site.css. See nav.js. + ========================================================================== */ + +/* ---- Design tokens (from site.css :root). Scoped to the header (all nav + elements are descendants) so we never clobber a host site's own CSS vars. ---- */ +header.site-header { + --bg: #000000; + --ink: #8b0000; + --muted: #8b0000; + --accent: #a00000; + --gold: #8b0000; + --border: #3a0000; + --shadow: rgba(0, 0, 0, .40); + --glow-color: 160, 0, 0; + --glow-strong: + 0 0 0 1px rgba(var(--glow-color), .55), + 0 0 6px rgba(var(--glow-color), .65), + 0 0 18px rgba(var(--glow-color), .55), + 0 0 48px rgba(var(--glow-color), .35), + inset 0 0 12px rgba(var(--glow-color), .18); + --r: 6px; + --wrap: 960px; + --space-xs: 0.25rem; + --space-sm: 0.5rem; + --space-md: 0.75rem; + --space-lg: 1rem; + --space-xl: 1.35rem; + --space-2xl: 1.75rem; + --fs-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.85rem); + --fs-sm: clamp(0.8rem, 0.75rem + 0.25vw, 0.9rem); + --fs-lg: clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem); + --fs-xl: clamp(1.05rem, 1rem + 0.25vw, 1.15rem); +} + +/* Header should always look like www (Inter), not inherit the host body font. */ +header.site-header { + font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; + line-height: 1.6; +} + +.header-button:hover, +.header-button:focus-visible, +#menu-toggle:hover, +#menu-toggle:focus-visible { + text-shadow: none; +} + +/* ---- Header ---- */ +header.site-header { + background: var(--bg); + border-bottom: 1px solid var(--border); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; +} + +/* Offset the host page so the fixed header doesn't overlap its content. */ +body:has(header.site-header) { + padding-top: var(--site-header-height, 76px); +} + +.header-inner { + max-width: var(--wrap); + margin: 0 auto; + padding: var(--space-md) var(--space-lg); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-lg); + flex-wrap: wrap; +} + +.brand { + display: flex; + align-items: center; + gap: var(--space-md); + min-width: 240px; +} + +.logo { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--r); +} + +.logo img { + height: 48px; + width: 48px; + object-fit: contain; + border: 2px solid var(--border); + border-radius: var(--r); + transition: border-color .25s ease, box-shadow .35s ease, transform .35s ease; +} + +header.site-header .logo:hover img, +header.site-header .logo:focus-visible img { + border-color: rgba(var(--glow-color), .9); + box-shadow: var(--glow-strong); + animation: logo-pulse 2.4s ease-in-out infinite; +} + +@keyframes logo-pulse { + 0%, 100% { + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .55), + 0 0 6px rgba(var(--glow-color), .65), + 0 0 18px rgba(var(--glow-color), .55), + 0 0 48px rgba(var(--glow-color), .35), + inset 0 0 12px rgba(var(--glow-color), .18); + } + 50% { + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .8), + 0 0 10px rgba(var(--glow-color), .9), + 0 0 28px rgba(var(--glow-color), .75), + 0 0 64px rgba(var(--glow-color), .5), + inset 0 0 18px rgba(var(--glow-color), .28); + } +} + +@media (prefers-reduced-motion: reduce) { + header.site-header .logo:hover img, + header.site-header .logo:focus-visible img { + animation: none; + } +} + +.brand-text { + display: flex; + flex-direction: column; + line-height: 1.2; +} + +.brand-text strong { + font-size: var(--fs-lg); + color: var(--gold); + letter-spacing: .2px; +} + +.brand-text span { + font-size: var(--fs-sm); + color: var(--muted); +} + +.header-controls { + display: flex; + align-items: center; + gap: var(--space-sm); +} + +.header-button { + font-size: var(--fs-sm); + border: 1px solid var(--border); + padding: 4px 8px; + border-radius: var(--r); + color: var(--gold); + text-decoration: none; + background: var(--bg); + cursor: pointer; + font-family: inherit; + display: inline-flex; + align-items: center; + justify-content: center; + transition: background .15s, color .15s, border-color .15s, box-shadow .25s; +} + +.header-button:hover { + background: var(--accent); + color: var(--ink); + border-color: rgba(var(--glow-color), .9); + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .4), + 0 0 12px rgba(var(--glow-color), .55), + 0 0 28px -4px rgba(var(--glow-color), .4); +} + +nav.site-nav[hidden], +.lang-menu[hidden] { + display: none !important; +} + +.header-icon-button { + width: 36px; + min-width: 36px; + height: 36px; + padding: 0; + font-size: 1.05rem; + line-height: 1; +} + +.visually-hidden { + position: absolute !important; + width: 1px; height: 1px; + padding: 0; margin: -1px; + overflow: hidden; clip: rect(0, 0, 0, 0); + white-space: nowrap; border: 0; +} + +.protocol-pills { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 5px; +} + +.protocol-pill { + --protocol-accent: var(--accent); + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 5px 10px; + border: 1px solid var(--protocol-accent); + border-radius: 999px; + background: rgba(var(--glow-color), .06); + color: var(--protocol-accent); + font-family: "JetBrains Mono", "IBM Plex Mono", "Fira Code", "Source Code Pro", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 0.88rem; + font-weight: 700; + line-height: 1.15; + letter-spacing: 0; + box-shadow: inset 0 0 10px rgba(var(--glow-color), .08); +} + +.protocol-pill:hover, +.protocol-pill:focus-visible { + background: var(--protocol-accent); + color: #050000; + text-shadow: none; + box-shadow: + 0 0 0 1px var(--protocol-accent), + 0 0 16px color-mix(in srgb, var(--protocol-accent) 65%, transparent); +} + +.protocol-pill--gemini { --protocol-accent: #2fd7b5; } +.protocol-pill--gopher { --protocol-accent: #d8a735; } +.protocol-pill--tor { --protocol-accent: #a579d6; } +.protocol-pill--i2p { --protocol-accent: #ff7b2c; } + +/* ---- Menu ---- */ +.menu-wrapper { + position: relative; +} + +#menu-toggle { + width: 44px; + height: 44px; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 22px; + line-height: 1; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + color: var(--ink); + padding: 0; + transition: transform .25s ease, background .15s, color .15s, border-color .15s, box-shadow .25s; +} + +#menu-toggle:hover { + background: var(--accent); + color: var(--ink); + border-color: rgba(var(--glow-color), .9); + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .4), + 0 0 14px rgba(var(--glow-color), .6), + 0 0 32px -4px rgba(var(--glow-color), .4); +} + +#menu-toggle.active { + transform: rotate(90deg); + background: var(--bg); + color: var(--ink); + border-color: var(--border); +} + +#menu-toggle.active:hover { + background: var(--accent); + color: var(--ink); + border-color: var(--accent); +} + +nav.site-nav { + position: absolute; + right: 0; + top: calc(100% + var(--space-xs)); + background: var(--bg); + border: 1px solid var(--ink); + border-radius: var(--r); + padding: var(--space-md) var(--space-md); + min-width: 200px; + box-shadow: 0 10px 22px var(--shadow); + z-index: 1200; + max-height: calc(100vh - 80px); + overflow-y: auto; +} + +nav.site-nav ul { + list-style: none; + margin: 0; + padding: 0; +} + +nav.site-nav li { + margin: var(--space-sm) 0; +} + +nav.site-nav a { + display: block; + padding: var(--space-xs) var(--space-xs); + transition: background .15s, color .15s; + color: var(--gold); + font-size: var(--fs-xl); + margin: 0; + text-decoration: none; +} + +nav.site-nav a:hover { + background: var(--accent); + color: var(--ink); +} + +nav.site-nav .nav-section { + margin-bottom: var(--space-sm); +} + +nav.site-nav .nav-section:last-child { + margin-bottom: 0; +} + +nav.site-nav .nav-section+.nav-section { + border-top: 1px solid var(--border); + padding-top: var(--space-sm); +} + +nav.site-nav .nav-label { + font-size: var(--fs-xs); + font-weight: 600; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.5px; + margin-bottom: var(--space-xs); + padding: var(--space-xs); +} + +/* ---- Language dropdown ---- */ +.lang { + position: relative; +} + +.lang-toggle-wrapper { + display: inline-block; +} + +.lang-menu { + position: absolute; + right: 0; + top: calc(100% + var(--space-xs)); + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--r); + box-shadow: 0 10px 22px var(--shadow); + min-width: 160px; + padding: var(--space-sm); + z-index: 1200; +} + +.lang-menu a { + display: block; + padding: var(--space-sm) var(--space-sm); + color: var(--gold); + text-decoration: none; + transition: background .15s; +} + +.lang-menu a:hover { + background: var(--accent); + color: var(--ink); +} + +/* ---- Light-mode header (driven by body.light-mode from site.js) ---- */ +body.light-mode header.site-header { + --bg: #fff8f1; + --ink: #2a1212; + --muted: #7a4545; + --accent: #8b0000; + --gold: #8b0000; + --border: #e8c8c8; + --shadow: rgba(139, 0, 0, .12); + --glow-color: 139, 0, 0; + background: rgba(255, 248, 241, .96); +} + +body.light-mode .header-button, +body.light-mode #menu-toggle, +body.light-mode nav.site-nav, +body.light-mode .lang-menu { + --bg: #fff8f1; + --ink: #2a1212; + --muted: #7a4545; + --accent: #8b0000; + --gold: #8b0000; + --border: #e8c8c8; + background: #ffffff; +} + +body.light-mode .header-button:hover, +body.light-mode #menu-toggle:hover, +body.light-mode nav.site-nav a:hover, +body.light-mode .lang-menu a:hover { + background: #8b0000; + color: #ffffff; + text-shadow: none; +} + +body.light-mode .protocol-pill { + background: #ffffff; +} + +body.light-mode .protocol-pill:hover, +body.light-mode .protocol-pill:focus-visible { + color: #ffffff; +} + +/* ---- Responsive (header only) ---- */ +@media (max-width: 720px) { + .header-inner { gap: var(--space-sm); } + .brand { min-width: 0; flex: 1 1 auto; } + .header-controls { + flex-wrap: wrap; + justify-content: flex-end; + gap: var(--space-sm); + row-gap: var(--space-xs); + } + .protocol-pills { + order: 4; + flex-basis: 100%; + justify-content: flex-end; + } + #lang-toggle { white-space: nowrap; } +} + +@media (max-width: 600px) { + .brand-text span { display: none; } +} + +@media (max-width: 520px) { + .header-inner { position: relative; padding: var(--space-sm) var(--space-md); } + nav.site-nav { min-width: 200px; max-width: calc(100vw - 2 * var(--space-md)); } + .lang-menu { right: auto; left: 0; max-width: calc(100vw - 32px); } + .header-button { padding: 4px 6px; } + .header-icon-button { width: 34px; min-width: 34px; height: 34px; padding: 0; } + .protocol-pills { justify-content: flex-start; } + .protocol-pill { min-height: 32px; padding-inline: 9px; font-size: 0.82rem; } +} + +@media (max-width: 380px) { + .header-button { font-size: var(--fs-xs); padding: 3px 5px; } +} + +@media (prefers-reduced-motion: reduce) { + #menu-toggle.active { transform: none; } +} diff --git a/assets/css/pages/404.css b/assets/css/pages/404.css new file mode 100644 index 0000000..7939cc1 --- /dev/null +++ b/assets/css/pages/404.css @@ -0,0 +1,12 @@ +/* Minimal fallback if CSS fails to load */ + body{margin:0;background:#ffd;color:#000;font-family:system-ui,Segoe UI,Arial,sans-serif;line-height:1.6;} + .wrap{max-width:960px;margin:0 auto;padding:1.35rem 1rem 2.5rem;} + .card{border:1px solid #caa;border-radius:6px;padding:1rem;background:#ffd;} + .top{display:flex;gap:12px;align-items:center;margin-bottom:1rem;} + .top img{width:48px;height:48px;border:2px solid #000;border-radius:6px;} + .top a:hover img{border-color:#d22;} + a{color:#d22;text-decoration:none;transition:0.1s;} + a:hover{background:#d22;color:#000 !important;} + .muted{color:#333;font-size:.9rem;} + .links{margin:1rem 0 0 0;} + .links a{display:inline-block;margin:0 .25rem .5rem 0;padding:2px 4px;border-radius:4px;} diff --git a/assets/css/pages/50x.css b/assets/css/pages/50x.css new file mode 100644 index 0000000..cc573de --- /dev/null +++ b/assets/css/pages/50x.css @@ -0,0 +1,9 @@ +body{margin:0;background:#ffd;color:#000;font-family:system-ui,Segoe UI,Arial,sans-serif;line-height:1.6;} + .wrap{max-width:960px;margin:0 auto;padding:1.35rem 1rem 2.5rem;} + .card{border:1px solid #caa;border-radius:6px;padding:1rem;background:#ffd;} + .top{display:flex;gap:12px;align-items:center;margin-bottom:1rem;} + .top img{width:48px;height:48px;border:2px solid #000;border-radius:6px;} + .top a:hover img{border-color:#d22;} + a{color:#d22;text-decoration:none;transition:0.1s;} + a:hover{background:#d22;color:#000 !important;} + .muted{color:#333;font-size:.9rem;} diff --git a/assets/css/pages/admin.css b/assets/css/pages/admin.css new file mode 100644 index 0000000..6262433 --- /dev/null +++ b/assets/css/pages/admin.css @@ -0,0 +1,392 @@ +/* Unified admin panel — terminal theme helpers */ + +.admin-tabs { + display: flex; + flex-wrap: wrap; + gap: var(--space-xs); + margin: 0 0 var(--space-lg); + border-bottom: 1px solid var(--border); +} + +.admin-tabs a { + padding: var(--space-sm) var(--space-md); + border: 1px solid var(--border); + border-bottom: none; + border-radius: var(--r) var(--r) 0 0; + color: var(--muted); + font-weight: 700; +} + +.admin-tabs a.active { + color: var(--ink); + border-color: var(--accent); + background: #0a0000; +} + +.admin-flash { + padding: var(--space-sm) var(--space-md); + border-radius: var(--r); + margin-bottom: var(--space-md); + border: 1px solid var(--border); +} + +.admin-flash.ok { border-color: #2e7d32; } +.admin-flash.err { border-color: var(--accent); } + +.admin-cols { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-lg); + align-items: start; +} + +@media (max-width: 800px) { + .admin-cols { grid-template-columns: 1fr; } +} + +.panel { + border: 1px solid var(--border); + border-radius: var(--r); + margin-bottom: var(--space-md); +} + +.panel-head { + padding: var(--space-sm) var(--space-md); + border-bottom: 1px solid var(--border); + font-size: var(--fs-xs); + text-transform: uppercase; + letter-spacing: .07em; + color: var(--muted); +} + +.panel-body { padding: var(--space-md); } + +.admin-field { margin-bottom: var(--space-md); } + +.admin-field label { + display: block; + margin-bottom: 4px; + font-size: var(--fs-sm); +} + +.admin-field input, +.admin-field textarea, +.admin-field select { + width: 100%; + box-sizing: border-box; + background: #050000; + border: 1px solid var(--border); + color: #d00000; + padding: 10px; + border-radius: var(--r); + font: inherit; +} + +.md-toolbar { + display: flex; + flex-wrap: wrap; + gap: 4px; + margin-bottom: 6px; +} + +.md-toolbar button { + padding: 6px 10px; + font-size: var(--fs-xs); +} + +#md-preview { + background: #050000; + border: 1px solid var(--border); + border-radius: var(--r); + padding: 12px; + min-height: 200px; + overflow: auto; + line-height: 1.6; +} + +.admin-list { + list-style: none; + padding: 0; + margin: 0; +} + +.admin-item { + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-sm) var(--space-md); + margin-bottom: var(--space-sm); +} + +.admin-item small { + color: var(--muted); + font-family: monospace; +} + +.inline-form { display: inline; } + +.admin-checks { + display: flex; + flex-direction: column; + gap: 6px; + margin: 0 0 var(--space-md); +} + +.admin-checks label { + font-size: var(--fs-sm); +} + +.admin-motd-actions { + display: flex; + flex-wrap: wrap; + gap: var(--space-sm); + margin: 0 0 var(--space-md); +} + +.motd-xmpp-preview { + margin: 0; + white-space: pre-wrap; + overflow-wrap: anywhere; + font-family: var(--font-mono, ui-monospace, monospace); + font-size: var(--fs-sm); + line-height: 1.55; + color: var(--ink); +} + +.type-badge { + font-family: monospace; + padding: 1px 7px; + border: 1px solid var(--border); + border-radius: var(--r); + color: var(--muted); +} + +table.admin-table { + width: 100%; + border-collapse: collapse; +} + +table.admin-table th, +table.admin-table td { + border: 1px solid var(--border); + padding: 6px 8px; + text-align: left; + vertical-align: top; + font-size: var(--fs-sm); +} + +.ratio-wrap { + position: relative; + padding-top: 56.25%; +} + +.ratio-wrap iframe { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + border: 0; + border-radius: var(--r); +} + +.preview-panel img, +.preview-panel video, +.preview-panel audio { + max-width: 100%; + border-radius: var(--r); + display: block; +} + +/* Utility replacements for residual inline styles */ +.admin-section-title { + font-size: var(--fs-lg); + margin: var(--space-2xl) 0 var(--space-md); +} + +.admin-section-label { + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: .07em; + color: var(--muted); + margin: var(--space-xl) 0 var(--space-sm); +} + +.admin-stack-gap { + margin-bottom: var(--space-2xl); +} + +.admin-inline-note { + font-size: var(--fs-sm); + color: var(--accent); +} + +.admin-search-input { + padding: 8px; + background: #050000; + border: 1px solid var(--border); + color: #d00000; + border-radius: var(--r); +} + +body.light-mode .admin-tabs a.active { + background: #fff4f4; +} + +body.light-mode .admin-field input, +body.light-mode .admin-field textarea, +body.light-mode .admin-field select, +body.light-mode #md-preview, +body.light-mode .admin-search-input { + background: #fff; + color: #2a1212; +} + +/* ---- Traffic analytics ---- */ +.traffic-live-bar { + display: flex; + align-items: center; + gap: 0.4rem; + margin: 0 0 var(--space-md); + font-family: var(--font-mono, ui-monospace, monospace); + font-size: var(--fs-xs); + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--muted); +} +.traffic-live-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: #39ff14; + box-shadow: 0 0 8px rgba(57, 255, 20, 0.7); + animation: traffic-live-pulse 1.6s ease-in-out infinite; +} +.traffic-live-bar--ok .traffic-live-dot { + background: #39ff14; +} +.traffic-live-bar--err .traffic-live-dot { + background: #ff4d4d; + box-shadow: 0 0 8px rgba(255, 77, 77, 0.55); + animation: none; +} +.traffic-live-bar--err #traffic-live-status { + color: #ff6b6b; +} +@keyframes traffic-live-pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.45; transform: scale(0.85); } +} +body.light-mode .traffic-live-dot { + background: #1a7a12; + box-shadow: none; +} +body.light-mode .traffic-live-bar--err .traffic-live-dot { + background: #c0392b; +} + +.traffic-kpi-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + gap: var(--space-sm); + margin: 0 0 var(--space-lg); +} +.traffic-kpi-val.traffic-kpi-flash { + animation: traffic-kpi-pop 0.55s ease; +} +@keyframes traffic-kpi-pop { + 0% { transform: scale(1); } + 35% { transform: scale(1.12); filter: brightness(1.35); } + 100% { transform: scale(1); } +} +.traffic-kpi { + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md); + background: #0a0000; + text-align: center; +} +.traffic-kpi-val { + display: block; + font-family: var(--font-mono, ui-monospace, monospace); + font-size: 1.6rem; + font-weight: 700; + color: #39ff14; + text-shadow: 0 0 8px rgba(57, 255, 20, .25); + line-height: 1.2; +} +.traffic-kpi-label { + display: block; + margin-top: 4px; + font-size: var(--fs-xs); + text-transform: uppercase; + letter-spacing: .06em; + color: var(--muted); +} +.traffic-kpi--bots { + border-color: rgba(255, 159, 26, 0.45); +} +.traffic-kpi--bots .traffic-kpi-val { + color: #ff9f1a; + text-shadow: 0 0 8px rgba(255, 159, 26, .3); +} +.traffic-row--bot { + opacity: 0.78; +} +.traffic-badge--bot { + background: rgba(255, 159, 26, 0.18); + color: #ff9f1a; + border: 1px solid rgba(255, 159, 26, 0.4); +} +body.light-mode .traffic-kpi--bots .traffic-kpi-val { + color: #a65c00; + text-shadow: none; +} +body.light-mode .traffic-badge--bot { + background: rgba(166, 92, 0, 0.1); + color: #a65c00; + border-color: rgba(166, 92, 0, 0.35); +} +.traffic-chart-panel .panel-body { + padding-bottom: var(--space-sm); +} +.traffic-chart { + display: block; + width: 100%; + max-width: 100%; + height: auto; + background: #050000; + border: 1px solid var(--border); + border-radius: var(--r); +} +.traffic-chart-legend { + display: flex; + flex-wrap: wrap; + gap: 1rem; + margin-top: var(--space-sm); + font-size: var(--fs-xs); + color: var(--muted); + font-family: var(--font-mono, ui-monospace, monospace); +} +.traffic-swatch { + display: inline-block; + width: 12px; + height: 12px; + border-radius: 2px; + margin-right: 4px; + vertical-align: -1px; +} +.traffic-swatch--hits { background: #39ff14; box-shadow: 0 0 6px rgba(57,255,20,.4); } +.traffic-swatch--uniq { background: #5b9dff; box-shadow: 0 0 6px rgba(91,157,255,.35); } +.traffic-swatch--bots { background: #ff9f1a; box-shadow: 0 0 6px rgba(255,159,26,.4); } +.traffic-chart-row { margin-bottom: var(--space-md); } +body.light-mode .traffic-swatch--bots { background: #a65c00; box-shadow: none; } + +body.light-mode .traffic-kpi { + background: #f8fbfd; +} +body.light-mode .traffic-kpi-val { + color: #1a7a12; + text-shadow: none; +} +body.light-mode .traffic-chart { + background: #f4f7fa; +} diff --git a/assets/css/pages/articles-2023-04-10.css b/assets/css/pages/articles-2023-04-10.css new file mode 100644 index 0000000..1818de4 --- /dev/null +++ b/assets/css/pages/articles-2023-04-10.css @@ -0,0 +1 @@ +kbd{ border:1px solid var(--border); border-radius:4px; padding:0 6px; background: #fff; } diff --git a/assets/css/pages/articles-2023-04-10_jp.css b/assets/css/pages/articles-2023-04-10_jp.css new file mode 100644 index 0000000..1818de4 --- /dev/null +++ b/assets/css/pages/articles-2023-04-10_jp.css @@ -0,0 +1 @@ +kbd{ border:1px solid var(--border); border-radius:4px; padding:0 6px; background: #fff; } diff --git a/assets/css/pages/articles-2023-04-10_zh.css b/assets/css/pages/articles-2023-04-10_zh.css new file mode 100644 index 0000000..1818de4 --- /dev/null +++ b/assets/css/pages/articles-2023-04-10_zh.css @@ -0,0 +1 @@ +kbd{ border:1px solid var(--border); border-radius:4px; padding:0 6px; background: #fff; } diff --git a/assets/css/pages/articles-runescape.css b/assets/css/pages/articles-runescape.css new file mode 100644 index 0000000..1818de4 --- /dev/null +++ b/assets/css/pages/articles-runescape.css @@ -0,0 +1 @@ +kbd{ border:1px solid var(--border); border-radius:4px; padding:0 6px; background: #fff; } diff --git a/assets/css/pages/articles-runescape_jp.css b/assets/css/pages/articles-runescape_jp.css new file mode 100644 index 0000000..1818de4 --- /dev/null +++ b/assets/css/pages/articles-runescape_jp.css @@ -0,0 +1 @@ +kbd{ border:1px solid var(--border); border-radius:4px; padding:0 6px; background: #fff; } diff --git a/assets/css/pages/articles-runescape_zh.css b/assets/css/pages/articles-runescape_zh.css new file mode 100644 index 0000000..1818de4 --- /dev/null +++ b/assets/css/pages/articles-runescape_zh.css @@ -0,0 +1 @@ +kbd{ border:1px solid var(--border); border-radius:4px; padding:0 6px; background: #fff; } diff --git a/assets/css/pages/bookmarks.css b/assets/css/pages/bookmarks.css new file mode 100644 index 0000000..7cb6ccf --- /dev/null +++ b/assets/css/pages/bookmarks.css @@ -0,0 +1,85 @@ +.bookmarks-title { + margin-bottom: var(--space-md); +} + +.tree { + list-style-type: none; + padding-left: 0; + margin: 0; +} + +.tree ul { + list-style-type: none; + padding-left: 28px; + margin: 5px 0; +} + +.tree li { + margin: 4px 0; + position: relative; +} + +.tree summary { + display: flex; + align-items: center; + cursor: pointer; + padding: 8px 12px; + transition: background-color 0.2s ease; + font-weight: 600; + outline: none; + user-select: none; + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--r); +} + +.tree summary:hover { + background-color: #2a1010; + border-color: var(--accent); +} + +.tree summary::-webkit-details-marker { + display: none; +} + +.tree summary::before { + content: ">"; + color: var(--ink); + margin-right: 10px; + font-size: 1rem; + transition: all 0.2s ease; + width: 20px; + text-align: left; + font-weight: 700; +} + +.tree details[open]>summary::before { + content: ">"; + transform: rotate(90deg); +} + +.tree a { + color: var(--ink); + text-decoration: none; + display: inline-flex; + align-items: center; + padding: 6px 6px; + border-radius: 4px; +} + +.tree a:hover { + background: var(--accent); + color: #000 !important; +} + + +.tree .navbar-file a { + color: var(--muted); +} + +.tree .navbar-file a::before { + content: "->"; + color: var(--muted); + margin-right: 10px; + font-size: 0.9rem; +}
\ No newline at end of file diff --git a/assets/css/pages/changelog.css b/assets/css/pages/changelog.css new file mode 100644 index 0000000..18633fd --- /dev/null +++ b/assets/css/pages/changelog.css @@ -0,0 +1,25 @@ +.changelog-list{ list-style: none; padding: 0; margin: 0; } + +.changelog-entry{ + padding: var(--space-md) 0; + border-bottom: 1px dotted rgba(0,0,0,.25); +} + +.changelog-entry:last-child{ border-bottom: none; } + +.changelog-entry time{ font-weight: 700; color: var(--ink); white-space: nowrap; display: block; margin-bottom: var(--space-xs); } + +.changelog-entry .text{ color: var(--muted); } + +.changelog-more{ + display: inline-block; + margin-top: var(--space-xs); + font-size: 13px; + white-space: nowrap; +} + +hr { + border: none; + border-top: 1px dotted var(--border); + margin: var(--space-lg) 0; +} diff --git a/assets/css/pages/collection.css b/assets/css/pages/collection.css new file mode 100644 index 0000000..8f3c81a --- /dev/null +++ b/assets/css/pages/collection.css @@ -0,0 +1,290 @@ +/* ========================================================================== + Game collection catalog + Layout pattern: personal small-web inventory (photo | name :: model | specs) + Visual system: SillyLaird crimson / mono — not a third-party theme clone. + ========================================================================== */ + +body.gc-page { + font-family: var(--font-mono); +} + +.gc-wrap { + max-width: 52rem; +} + +/* Big centered page title (catalog feel, site colors) */ +.gc-title { + font-family: var(--font-mono); + font-size: clamp(1.75rem, 1.2rem + 3vw, 2.75rem); + font-weight: 700; + text-align: center; + color: var(--ink); + letter-spacing: 0.02em; + margin: var(--space-md) 0 var(--space-sm); + line-height: 1.15; +} + +/* COMPUTERS / PHONES ⁜ WISHLIST style menu */ +.gc-menu { + text-align: center; + margin: 0 0 var(--space-2xl); + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--muted); + line-height: 1.8; +} + +.gc-menu a { + color: var(--muted); + text-decoration: none; + padding: 0 2px; +} + +.gc-menu a:hover, +.gc-menu a:focus-visible { + color: var(--accent-bright); +} + +.gc-menu a.gc-menu-active, +.gc-menu a#gc-main { + color: var(--ink); + font-style: italic; +} + +.gc-menu-sep { + margin: 0 1px; + color: var(--muted); +} + +.gc-menu-diamond { + margin: 0 0.45rem; + color: var(--border); + font-style: normal; +} + +.gc-page-blurb { + text-align: center; + color: var(--muted); + font-size: var(--fs-sm); + margin: 0 auto var(--space-xl); + max-width: 34rem; +} + +.gc-count { + text-align: center; + color: var(--muted); + font-size: var(--fs-xs); + margin: 0 0 var(--space-lg); + text-transform: uppercase; + letter-spacing: 0.08em; +} + +/* Table-like catalog stack (centered inventory) */ +.gc-catalog { + display: table; + width: 100%; + margin: 0 auto; + border-collapse: separate; + border-spacing: 0 var(--space-md); +} + +.gc-row { + display: table-row; +} + +.gc-pic, +.gc-body { + display: table-cell; + vertical-align: middle; +} + +.gc-pic { + width: 1%; + padding-right: var(--space-lg); + white-space: nowrap; +} + +.gc-pic a { + display: inline-block; + line-height: 0; +} + +.gc-pic img { + display: block; + width: auto; + max-width: 13rem; + max-height: 10rem; + height: auto; + border: 1px solid var(--border); + background: var(--surface-deep); +} + +.gc-pic-empty { + width: 10rem; + height: 7rem; + border: 1px dashed var(--border); + background: + radial-gradient(ellipse at 30% 20%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 55%), + var(--surface-deep); + color: var(--muted); + display: flex; + align-items: center; + justify-content: center; + font-size: var(--fs-sm); + letter-spacing: 0.18em; + text-transform: uppercase; + opacity: 0.85; +} + +.gc-body { + width: 99%; + padding: 2px 0; +} + +/* Large display name: left :: right */ +.gc-name { + font-family: var(--font-mono); + font-size: clamp(1.15rem, 1rem + 0.9vw, 1.65rem); + font-weight: 700; + color: var(--gold); + margin: 0 0 var(--space-xs); + line-height: 1.2; + word-break: break-word; +} + +.gc-name a { + color: inherit; + text-decoration: none; +} + +.gc-name a:hover, +.gc-name a:focus-visible { + color: var(--accent-bright); + text-decoration: underline; +} + +.gc-colon { + color: var(--muted); + font-weight: 400; + margin: 0 0.28em; +} + +.gc-note { + margin: 0 0 var(--space-xs); + font-size: var(--fs-sm); + color: var(--muted); + font-style: italic; +} + +.gc-note em { + font-style: italic; +} + +/* Inline “icon + value” specs (like arch / cpu / ram lines) */ +.gc-specs { + margin: 0; + font-size: var(--fs-sm); + color: var(--ink); + line-height: 1.7; +} + +.gc-spec { + display: inline; + white-space: nowrap; + margin-right: 0.65rem; +} + +.gc-spec-ico { + display: inline-block; + min-width: 1.1em; + text-align: center; + font-size: 0.75em; + font-weight: 700; + color: var(--bg); + background: var(--ink); + border-radius: 2px; + padding: 0 0.28em; + margin-right: 0.25em; + vertical-align: 0.05em; + line-height: 1.35; +} + +.gc-spec-val { + color: var(--ink); +} + +a.gc-spec-val { + color: var(--accent-bright); + text-decoration: none; +} + +a.gc-spec-val:hover, +a.gc-spec-val:focus-visible { + text-decoration: underline; +} + +.gc-empty { + text-align: center; + color: var(--muted); + font-size: var(--fs-sm); + border: 1px dashed var(--border); + padding: var(--space-xl); + margin: var(--space-lg) auto; + max-width: 28rem; +} + +.gc-footer-hint { + text-align: center; + margin: var(--space-2xl) 0 var(--space-md); + font-size: var(--fs-xs); + color: var(--muted); +} + +.gc-footer-hint a { + color: var(--muted); +} + +/* Mobile: stack photo above body (table → block) */ +@media (max-width: 640px) { + .gc-catalog, + .gc-row, + .gc-pic, + .gc-body { + display: block; + width: 100%; + } + + .gc-row { + margin-bottom: var(--space-xl); + padding-bottom: var(--space-lg); + border-bottom: 1px solid var(--border); + } + + .gc-pic { + padding-right: 0; + margin-bottom: var(--space-sm); + } + + .gc-pic img, + .gc-pic-empty { + max-width: 100%; + width: min(100%, 16rem); + } + + .gc-spec { + display: inline-block; + margin-bottom: 0.15rem; + } +} + +/* Light mode: keep readable contrast */ +body.light-mode .gc-spec-ico { + color: #fff; + background: var(--ink); +} + +body.light-mode .gc-pic img, +body.light-mode .gc-pic-empty { + background: #f6f0f0; +} diff --git a/assets/css/pages/computers.css b/assets/css/pages/computers.css new file mode 100644 index 0000000..2b0ff38 --- /dev/null +++ b/assets/css/pages/computers.css @@ -0,0 +1,102 @@ +.machine{ + border: 1px solid var(--ink); + padding: var(--space-md); + margin-top: var(--space-md); + background: var(--bg); +} + +.machine-info{ font-size: var(--fs-base); } + +.machine-title{ + color: var(--gold); + font-weight: 700; + font-size: var(--fs-lg); + margin-bottom: var(--space-xs); +} + +.machine--notes { + border-color: color-mix(in srgb, var(--accent-cyan) 42%, var(--border)); + background: linear-gradient(90deg, color-mix(in srgb, var(--accent-cyan) 7%, var(--bg)), var(--bg) 45%); +} + +.colon-nav { + font-size: var(--fs-base); + margin-top: var(--space-sm); +} + +.colon-nav strong { + color: var(--gold); +} + +.machine-row { + display: flex; + gap: var(--space-md); + align-items: flex-start; + flex-wrap: wrap; +} + +.machine-row .machine-thumb { + flex: 0 0 auto; + width: 96px; + height: 96px; + object-fit: contain; + border: 1px solid var(--border); + background: var(--bg); + padding: var(--space-xs); +} + +.machine-row .machine-facts { + flex: 1 1 240px; +} + +.machine-title--sub { + margin-top: var(--space-sm); +} + +.placeholder-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: var(--space-md); +} + +.placeholder-box { + border: 1px dashed var(--border); + border-radius: var(--r); + padding: var(--space-md); + text-align: center; + color: var(--muted); + font-size: var(--fs-sm); + min-height: 120px; + display: flex; + align-items: center; + justify-content: center; +} + +.rs-shot { + margin: 0; + border: 1px solid var(--border); + border-radius: var(--r); + overflow: hidden; + background: var(--bg); +} + +.rs-shot img { + display: block; + width: 100%; + height: auto; +} + +.rs-shot figcaption { + padding: var(--space-xs) var(--space-sm); + font-size: var(--fs-sm); +} + +.rs-era-banner { + display: block; + width: 100%; + max-height: 220px; + object-fit: cover; + border: 1px solid var(--border); + border-radius: var(--r); + margin: var(--space-sm) 0 var(--space-md); +} diff --git a/assets/css/pages/guestbook-form.css b/assets/css/pages/guestbook-form.css new file mode 100644 index 0000000..8ff7d9f --- /dev/null +++ b/assets/css/pages/guestbook-form.css @@ -0,0 +1,58 @@ +body { + background: #0a0a0a !important; + margin: 0; + padding: 10px; + font-family: "JetBrains Mono", "IBM Plex Mono", "Fira Code", "Source Code Pro", monospace; + color: #e0e0e0 !important; + overflow-y: auto; + overflow-x: hidden; + -ms-overflow-style: none; + scrollbar-width: none; +} +body::-webkit-scrollbar { + width: 0; + height: 0; +} + +form { + max-width: 900px; + margin: 0 auto 20px; + background: #0a0a0a !important; +} + +form input, +form textarea { + background: #111 !important; + border: 1px solid #333 !important; + color: #e0e0e0 !important; + font: inherit; + box-sizing: border-box; + margin-bottom: 10px; + width: 100%; + padding: 8px; +} + +form input::placeholder, +form textarea::placeholder { + color: #666 !important; +} + +form input:focus, +form textarea:focus { + outline: none; + border-color: #ff4444 !important; +} + +form button { + background: #ff4444 !important; + border: none !important; + padding: 12px 18px; + border-radius: 4px; + cursor: pointer; + font: inherit; + color: #fff !important; + font-weight: bold; +} +form button:hover { + background: #cc0000 !important; +} diff --git a/assets/css/pages/guestbook_jp.css b/assets/css/pages/guestbook_jp.css new file mode 100644 index 0000000..c4da6e4 --- /dev/null +++ b/assets/css/pages/guestbook_jp.css @@ -0,0 +1,79 @@ +.anonymous { + color: var(--accent) !important; +} + +.error { + color: var(--accent); +} + +.captcha { + font-weight: 700; + font-size: 20px; +} + +form { + display: grid; + gap: var(--space-sm); + max-width: 640px; +} + +label { + font-weight: 600; +} + +input[type="text"], +textarea { + width: 100%; + padding: 10px; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + color: var(--accent) !important; + font: inherit; +} + +textarea { + min-height: 120px; + resize: vertical; +} + +.btn-row { + display: flex; + gap: var(--space-sm); + flex-wrap: wrap; +} + +button { + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + padding: 8px 12px; + cursor: pointer; + font: inherit; +} + +button:hover { + background: #fdd; + border-color: var(--accent); +} + +.entry { + border-top: 1px dotted rgba(0, 0, 0, .25); + padding-top: var(--space-md); + margin-top: var(--space-md); +} + +.entry h4 { + margin: 0 0 var(--space-xs) 0; +} + +.entry p { + margin: 0; + color: var(--muted); +} + +#captcha-canvas { + border: 1px solid var(--border); + border-radius: var(--r); + background: #fff; +}
\ No newline at end of file diff --git a/assets/css/pages/guestbook_zh.css b/assets/css/pages/guestbook_zh.css new file mode 100644 index 0000000..c4da6e4 --- /dev/null +++ b/assets/css/pages/guestbook_zh.css @@ -0,0 +1,79 @@ +.anonymous { + color: var(--accent) !important; +} + +.error { + color: var(--accent); +} + +.captcha { + font-weight: 700; + font-size: 20px; +} + +form { + display: grid; + gap: var(--space-sm); + max-width: 640px; +} + +label { + font-weight: 600; +} + +input[type="text"], +textarea { + width: 100%; + padding: 10px; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + color: var(--accent) !important; + font: inherit; +} + +textarea { + min-height: 120px; + resize: vertical; +} + +.btn-row { + display: flex; + gap: var(--space-sm); + flex-wrap: wrap; +} + +button { + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + padding: 8px 12px; + cursor: pointer; + font: inherit; +} + +button:hover { + background: #fdd; + border-color: var(--accent); +} + +.entry { + border-top: 1px dotted rgba(0, 0, 0, .25); + padding-top: var(--space-md); + margin-top: var(--space-md); +} + +.entry h4 { + margin: 0 0 var(--space-xs) 0; +} + +.entry p { + margin: 0; + color: var(--muted); +} + +#captcha-canvas { + border: 1px solid var(--border); + border-radius: var(--r); + background: #fff; +}
\ No newline at end of file diff --git a/assets/css/pages/hitcounter.css b/assets/css/pages/hitcounter.css new file mode 100644 index 0000000..1c52da1 --- /dev/null +++ b/assets/css/pages/hitcounter.css @@ -0,0 +1,7 @@ +.counter { + display: grid; + gap: var(--space-sm); + justify-items: center; + text-align: center; + } + .big { font-size: 3rem; font-weight: 800; color: var(--gold); } diff --git a/assets/css/pages/journal-index.css b/assets/css/pages/journal-index.css new file mode 100644 index 0000000..02e8c42 --- /dev/null +++ b/assets/css/pages/journal-index.css @@ -0,0 +1,3 @@ +.entry { margin: var(--space-md) 0; } + .entry time { font-weight: 700; color: var(--ink); } + .entry p { margin: var(--space-xs) 0 0 0; color: var(--muted); } diff --git a/assets/css/pages/journal-index_jp.css b/assets/css/pages/journal-index_jp.css new file mode 100644 index 0000000..02e8c42 --- /dev/null +++ b/assets/css/pages/journal-index_jp.css @@ -0,0 +1,3 @@ +.entry { margin: var(--space-md) 0; } + .entry time { font-weight: 700; color: var(--ink); } + .entry p { margin: var(--space-xs) 0 0 0; color: var(--muted); } diff --git a/assets/css/pages/journal-index_zh.css b/assets/css/pages/journal-index_zh.css new file mode 100644 index 0000000..02e8c42 --- /dev/null +++ b/assets/css/pages/journal-index_zh.css @@ -0,0 +1,3 @@ +.entry { margin: var(--space-md) 0; } + .entry time { font-weight: 700; color: var(--ink); } + .entry p { margin: var(--space-xs) 0 0 0; color: var(--muted); } diff --git a/assets/css/pages/links.css b/assets/css/pages/links.css new file mode 100644 index 0000000..d0a6c8b --- /dev/null +++ b/assets/css/pages/links.css @@ -0,0 +1,22 @@ +.buttons img { image-rendering: auto; } + .buttons a { padding: 0; background: transparent; } + .buttons a:hover { background: transparent; } +/* Link hub: card-based grouping. Mirrors .start-here inset card. */ +.link-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); + gap: var(--space-md); + margin: var(--space-md) 0 var(--space-lg); +} +.link-card { + border: 1px solid var(--border); + border-left: 3px solid var(--accent); + border-radius: var(--r); + padding: var(--space-md) var(--space-lg); + background: linear-gradient(180deg, rgba(var(--glow-color), .04), transparent 70%); +} +.link-card-title { margin: 0 0 var(--space-sm) !important; font-size: var(--fs-lg); } +.link-card-list { + list-style: none; padding: 0; margin: 0; + display: grid; gap: var(--space-xs); line-height: 1.5; +} diff --git a/assets/css/pages/links_jp.css b/assets/css/pages/links_jp.css new file mode 100644 index 0000000..d0a6c8b --- /dev/null +++ b/assets/css/pages/links_jp.css @@ -0,0 +1,22 @@ +.buttons img { image-rendering: auto; } + .buttons a { padding: 0; background: transparent; } + .buttons a:hover { background: transparent; } +/* Link hub: card-based grouping. Mirrors .start-here inset card. */ +.link-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); + gap: var(--space-md); + margin: var(--space-md) 0 var(--space-lg); +} +.link-card { + border: 1px solid var(--border); + border-left: 3px solid var(--accent); + border-radius: var(--r); + padding: var(--space-md) var(--space-lg); + background: linear-gradient(180deg, rgba(var(--glow-color), .04), transparent 70%); +} +.link-card-title { margin: 0 0 var(--space-sm) !important; font-size: var(--fs-lg); } +.link-card-list { + list-style: none; padding: 0; margin: 0; + display: grid; gap: var(--space-xs); line-height: 1.5; +} diff --git a/assets/css/pages/links_zh.css b/assets/css/pages/links_zh.css new file mode 100644 index 0000000..d0a6c8b --- /dev/null +++ b/assets/css/pages/links_zh.css @@ -0,0 +1,22 @@ +.buttons img { image-rendering: auto; } + .buttons a { padding: 0; background: transparent; } + .buttons a:hover { background: transparent; } +/* Link hub: card-based grouping. Mirrors .start-here inset card. */ +.link-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); + gap: var(--space-md); + margin: var(--space-md) 0 var(--space-lg); +} +.link-card { + border: 1px solid var(--border); + border-left: 3px solid var(--accent); + border-radius: var(--r); + padding: var(--space-md) var(--space-lg); + background: linear-gradient(180deg, rgba(var(--glow-color), .04), transparent 70%); +} +.link-card-title { margin: 0 0 var(--space-sm) !important; font-size: var(--fs-lg); } +.link-card-list { + list-style: none; padding: 0; margin: 0; + display: grid; gap: var(--space-xs); line-height: 1.5; +} diff --git a/assets/css/pages/motd.css b/assets/css/pages/motd.css new file mode 100644 index 0000000..8a30bad --- /dev/null +++ b/assets/css/pages/motd.css @@ -0,0 +1,51 @@ +/* MOTD — same inner-page language as Computers / Journal / ChangeLog. */ + +.motd-current { + border: 1px solid var(--ink); + padding: var(--space-md); + margin-top: var(--space-md); + background: var(--bg); +} + +.motd-heading { + color: var(--gold); + font-weight: 700; + font-size: var(--fs-lg); + margin: 0 0 var(--space-xs); +} + +.motd-current .muted { + margin: 0; +} + +.motd-body { + margin: var(--space-sm) 0 0; + white-space: pre-wrap; + overflow-wrap: anywhere; + max-width: 68ch; + line-height: 1.65; +} + +.entry { + margin: var(--space-md) 0; +} + +.entry time { + font-weight: 700; + color: var(--ink); + display: block; + margin-bottom: var(--space-xs); +} + +.entry p { + margin: 0; + color: var(--muted); + white-space: pre-wrap; + overflow-wrap: anywhere; + max-width: 68ch; +} + +.entry p strong { + color: var(--ink); + margin-right: 0.35em; +} diff --git a/assets/css/pages/mstartpage-index.css b/assets/css/pages/mstartpage-index.css new file mode 100644 index 0000000..02f0e9b --- /dev/null +++ b/assets/css/pages/mstartpage-index.css @@ -0,0 +1,341 @@ +:root { + --main-text-color: #ddd; + --border-color: var(--border, #2a1010); + --search-input-color: black; + --link-color: #FF0000; + --background-color: #000; + --menu-background: #111; +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + height: 100%; + background-color: var(--background-color); + font-family: 'Source Code Pro', "MS Gothic", IPAMonaGothic, IPAGothic, "BIZ UDGothic", HGGothicM, "Noto Sans Mono CJK JP", "Noto Sans Mono", monospace; + font-size: 14px; + color: var(--main-text-color); + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); + overflow-x: hidden; +} + +a { + color: var(--link-color); + background-color: transparent; + text-decoration: none; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); +} + +a:hover { + text-decoration: underline; +} + +/* Layout Overrides for Unified Header */ +.header-inner { + margin: 0 !important; + /* Left aligned */ + padding-left: 10px !important; +} + +/* Main menu fallback (if any) */ +.main-menu {} + +.main-menu.show { + display: flex; +} + +.main-menu a { + padding: 10px; + border-bottom: 1px solid #333; +} + +.main-menu a:last-child { + border-bottom: none; +} + +/* Search box */ +.search-container { + width: 100%; + padding: 10px; + background-color: var(--background-color); + margin-bottom: 15px; +} + +.search-form { + display: flex; + flex-direction: column; +} + +.search-input { + color: var(--link-color); + background-color: #3A3A3A; + border: 1px solid var(--link-color); + padding: 12px; + margin-bottom: 10px; + text-align: center; + border-radius: 4px; + font-size: 16px; + /* Larger for touch */ +} + +input[type="submit"] { + color: var(--link-color); + background-color: black; + padding: 12px; + border: 1px solid var(--link-color); + cursor: pointer; + border-radius: 4px; + font-weight: bold; + font-size: 16px; +} + +/* Content sections */ +.content-section { + margin-bottom: 20px; + padding: 0 10px; +} + +.section-title { + color: var(--link-color); + font-size: 1.2em; + border-bottom: 1px solid var(--border-color); + padding-bottom: 5px; + margin-bottom: 10px; +} + +.link-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 10px; +} + +.link-item { + padding: 10px; + background-color: #1a1a1a; + border: 1px solid #333; + border-radius: 4px; + text-align: center; +} + +/* Gallery items for mobile */ +.gallery-container { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 15px; + padding: 10px; +} + +.gallery-item { + border: 2px ridge var(--border-color); + border-radius: 4px; + overflow: hidden; +} + +.gallery-item:hover { + border: 2px ridge var(--link-color); +} + +.gallery-item img { + width: 100%; + height: auto; + display: block; +} + +.gallery-desc { + padding: 8px; + text-align: center; + font-size: 0.9em; + color: var(--link-color); + background-color: #1a1a1a; +} + +/* Date and time */ +.datetime { + padding: 10px; + text-align: center; + margin: 15px 0; +} + +#realtime-date, +#realtime-clock { + color: var(--link-color); + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); + margin: 5px 0; +} + +/* Footer */ +.footer { + padding: 15px; + text-align: center; + border-top: 1px solid #333; + margin-top: 20px; +} + +.footer-links { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 10px; +} + +.footer-links a { + padding: 5px; +} + +/* Collapsible sections */ +.collapsible { + background-color: #1a1a1a; + color: var(--link-color); + cursor: pointer; + padding: 12px; + width: 100%; + border: 1px solid var(--border-color); + text-align: left; + outline: none; + font-size: 1em; + font-weight: bold; + margin-bottom: 5px; + border-radius: 4px; +} + +.active, +.collapsible:hover { + background-color: #222; +} + +.collapsible-content { + padding: 0 10px; + display: none; + overflow: hidden; + background-color: #1a1a1a; + margin-bottom: 10px; + border-radius: 0 0 4px 4px; +} + +/* XXX Verification Modal */ +.xxx-modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.9); + z-index: 1000; + justify-content: center; + align-items: center; +} + +.xxx-modal-content { + background-color: var(--menu-background); + padding: 20px; + border-radius: 8px; + border: 2px solid var(--link-color); + text-align: center; + max-width: 90%; + width: 350px; +} + +.xxx-logo { + width: 80px; + height: 80px; + margin: 0 auto 15px; + background-color: #333; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + font-size: 24px; + color: var(--link-color); + border: 2px solid var(--link-color); +} + +.xxx-buttons { + display: flex; + justify-content: space-between; + margin-top: 20px; +} + +.xxx-button { + padding: 10px 20px; + border: none; + border-radius: 4px; + cursor: pointer; + font-weight: bold; +} + +.xxx-confirm { + background-color: var(--link-color); + color: white; +} + +.xxx-deny { + background-color: #f44336; + color: white; +} + +/* XXX Section */ +.xxx-section { + margin: 20px 0; + text-align: center; +} + +.xxx-toggle { + padding: 12px 20px; + background-color: #333; + color: var(--link-color); + border: 1px solid var(--link-color); + border-radius: 4px; + cursor: pointer; + font-weight: bold; + margin-bottom: 15px; +} + +.xxx-list { + position: fixed; + bottom: 20px; + right: 20px; + background-color: var(--menu-background); + border: 1px solid var(--link-color); + border-radius: 8px; + padding: 10px; + max-width: 200px; + display: none; + z-index: 999; +} + +.xxx-list-title { + color: var(--link-color); + font-weight: bold; + margin-bottom: 8px; + text-align: center; + border-bottom: 1px solid #444; + padding-bottom: 5px; +} + +.xxx-list-item { + margin: 5px 0; + text-align: center; +} + +/* Responsive adjustments */ +@media (min-width: 768px) { + body { + font-size: 16px; + max-width: 800px; + margin: 0 auto; + } + + .link-grid { + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + } + + .gallery-container { + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); + } +}
\ No newline at end of file diff --git a/assets/css/pages/vinyls.css b/assets/css/pages/vinyls.css new file mode 100644 index 0000000..ecf8b4b --- /dev/null +++ b/assets/css/pages/vinyls.css @@ -0,0 +1,14 @@ +.vinyl-grid{ + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: var(--space-md); + margin-top: var(--space-md); +} + +.vinyl-grid img{ + width: 100%; + height: auto; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); +} diff --git a/assets/css/scroll-to-top.css b/assets/css/scroll-to-top.css new file mode 100644 index 0000000..e538251 --- /dev/null +++ b/assets/css/scroll-to-top.css @@ -0,0 +1,162 @@ +/* ========================================================================== + scroll-to-top.css — floating "back to top" control + Loaded by assets/js/scroll-to-top.js on www and sibling *.sillylaird.ca hosts. + Self-contained so sibling pages that do not load site.css still look right. + Selectors are more specific than site.css's `a:hover` so the global link + glow / scale does not leak onto the control. + ========================================================================== */ + +a.scroll-to-top { + --stt-bg: var(--bg, #000000); + --stt-ink: var(--gold, #8b0000); + --stt-border: var(--border, #3a0000); + --stt-hover: var(--accent-cyan, #8b0000); + position: fixed; + right: max(0.85rem, env(safe-area-inset-right, 0px)); + bottom: max(1.1rem, env(safe-area-inset-bottom, 0px)); + z-index: 10050; + box-sizing: border-box; + width: 2.75rem; + height: 2.75rem; + margin: 0; + padding: 0.2rem 0 0.15rem; + display: inline-flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.05rem; + border: 1px solid var(--stt-border); + border-radius: 6px; + background: var(--stt-bg); + color: var(--stt-ink); + font-family: "JetBrains Mono", "IBM Plex Mono", "Source Code Pro", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 0.58rem; + font-weight: 700; + letter-spacing: 0.14em; + line-height: 1; + text-decoration: none; + text-transform: uppercase; + text-shadow: none; + box-shadow: + 0 0 0 1px rgba(160, 0, 0, .18), + 0 0 14px -2px rgba(160, 0, 0, .4), + inset 0 0 10px rgba(160, 0, 0, .12); + opacity: 0; + visibility: hidden; + pointer-events: none; + transform: translateY(10px); + transition: + opacity .2s ease, + visibility .2s ease, + transform .2s ease, + color .15s ease, + border-color .15s ease, + box-shadow .25s ease, + background-color .15s ease; + touch-action: manipulation; + -webkit-tap-highlight-color: transparent; +} + +a.scroll-to-top.is-visible { + opacity: 1; + visibility: visible; + pointer-events: auto; + transform: none; +} + +a.scroll-to-top .scroll-to-top-caret { + font-size: 0.85rem; + letter-spacing: 0; + line-height: 1; + transform: translateY(1px); +} + +a.scroll-to-top .scroll-to-top-label { + font-size: 0.52rem; + letter-spacing: 0.16em; +} + +a.scroll-to-top:hover, +a.scroll-to-top:focus-visible { + background: var(--stt-bg); + color: var(--stt-hover); + text-decoration: none; + text-shadow: + 0 0 6px rgba(255, 0, 0, .85), + 0 0 14px rgba(139, 0, 0, .45); + border-color: rgba(255, 0, 0, .75); + border-radius: 6px; + transform: none; + box-shadow: + 0 0 0 1px rgba(255, 0, 0, .45), + 0 0 16px rgba(139, 0, 0, .4), + 0 0 32px -6px rgba(139, 0, 0, .35), + inset 0 0 10px rgba(139, 0, 0, .08); +} + +a.scroll-to-top:focus-visible { + outline: 2px solid var(--stt-hover); + outline-offset: 2px; +} + +a.scroll-to-top:active { + transform: translateY(1px); +} + +/* Light theme — www uses body.light-mode; blog uses data-blog-theme */ +body.light-mode a.scroll-to-top, +html[data-blog-theme="light"] a.scroll-to-top { + --stt-bg: #fff8f1; + --stt-ink: #8b0000; + --stt-border: #e8c8c8; + --stt-hover: #5a0000; + box-shadow: + 0 1px 0 rgba(255, 255, 255, .95) inset, + 0 8px 22px rgba(139, 0, 0, .16); +} + +body.light-mode a.scroll-to-top:hover, +body.light-mode a.scroll-to-top:focus-visible, +html[data-blog-theme="light"] a.scroll-to-top:hover, +html[data-blog-theme="light"] a.scroll-to-top:focus-visible { + background: #ffffff; + color: #5a0000; + text-shadow: none; + border-color: #8b0000; + box-shadow: + 0 0 0 1px rgba(139, 0, 0, .35), + 0 8px 22px rgba(139, 0, 0, .22); +} + +/* When the visit-counter has no footer to live in, it docks bottom-right. + Lift it so the two chips do not sit on top of each other. */ +body.has-scroll-to-top #site-visit-counter[data-stt-docked="1"] { + bottom: 4.65rem; +} + +@media (max-width: 520px) { + a.scroll-to-top { + width: 2.55rem; + height: 2.55rem; + right: max(0.65rem, env(safe-area-inset-right, 0px)); + bottom: max(0.85rem, env(safe-area-inset-bottom, 0px)); + } +} + +@media (prefers-reduced-motion: reduce) { + a.scroll-to-top, + a.scroll-to-top.is-visible, + a.scroll-to-top:hover, + a.scroll-to-top:focus-visible, + a.scroll-to-top:active { + transition: none; + transform: none; + } +} + +@media print { + a.scroll-to-top, + .footer-back-to-top { + display: none !important; + } +} diff --git a/assets/css/site.css b/assets/css/site.css new file mode 100644 index 0000000..f71e2d7 --- /dev/null +++ b/assets/css/site.css @@ -0,0 +1,4854 @@ +/* ========================================================================== + site.css — SillyLaird global stylesheet + Sections: Variables, Reset, Layout, Typography, Header, Navigation, + Components, Pages, Footer, Utilities, Responsive, Theme + ========================================================================== */ + +/* ========================================================================== + 1. Variables + ========================================================================== */ +:root { + --bg: #000000; + --surface-deep: #050505; + --ink: #8b0000; + --muted: #a87070; + --accent: #a00000; + --accent-bright: #ff1a1a; + --gold: #8b0000; + --border: #3a0000; + --shadow: rgba(0, 0, 0, .40); + --neon-cyan: #ff1a1a; + --neon-green: #39ff14; + --accent-cyan: #8b0000; + --accent-pink: #a00000; + --accent-magenta: #8b0000; + --accent-purple: #5a0000; + --font-mono: "JetBrains Mono", "IBM Plex Mono", "Fira Code", "Source Code Pro", ui-monospace, SFMono-Regular, "Cascadia Code", Menlo, Consolas, monospace; + --lh-body: 1.72; + --lh-comfort: 1.88; + --font-prose: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino, "Times New Roman", serif; + --link-glow: 255, 0, 0; + --btn-glow: 139, 0, 0; + + /* Crimson glow stack — layered for atmospheric depth */ + --glow-color: 160, 0, 0; + --glow-soft: + 0 0 0 1px rgba(var(--glow-color), .18), + 0 0 12px -2px rgba(var(--glow-color), .35), + 0 0 36px -8px rgba(var(--glow-color), .25); + --glow-strong: + 0 0 0 1px rgba(var(--glow-color), .55), + 0 0 6px rgba(var(--glow-color), .65), + 0 0 18px rgba(var(--glow-color), .55), + 0 0 48px rgba(var(--glow-color), .35), + inset 0 0 12px rgba(var(--glow-color), .18); + + --wrap: 960px; + --r: 6px; + + /* Unified spacing scale */ + --space-xs: 0.25rem; + --space-sm: 0.5rem; + --space-md: 0.75rem; + --space-lg: 1rem; + --space-xl: 1.35rem; + --space-2xl: 1.75rem; + --space-3xl: 2.5rem; + + /* Fluid typography scale (clamp: min, preferred, max) */ + --fs-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.85rem); + --fs-sm: clamp(0.8rem, 0.75rem + 0.25vw, 0.9rem); + --fs-base: clamp(0.9rem, 0.85rem + 0.25vw, 1rem); + --fs-lg: clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem); + --fs-xl: clamp(1.05rem, 1rem + 0.25vw, 1.15rem); + --fs-2xl: clamp(1.3rem, 1.15rem + 0.75vw, 1.5rem); + --fs-3xl: clamp(1.5rem, 1.3rem + 1vw, 1.8rem); +} + +/* ========================================================================== + 2. Reset + ========================================================================== */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + margin: 0; +} + +/* ========================================================================== + 3. Base / Typography + ========================================================================== */ +body { + font-family: "Inter", system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; + line-height: var(--lh-body); + background: var(--bg); + color: var(--ink); + font-size: var(--fs-base); + overflow-x: hidden; + transition: background-color .35s ease, color .35s ease; +} + +body.theme-transitioning, +body.theme-transitioning *, +body.theme-transitioning *::before, +body.theme-transitioning *::after { + transition: background-color .35s ease, color .35s ease, border-color .35s ease, box-shadow .35s ease !important; +} + +p { + margin: var(--space-sm) 0; + line-height: 1.6; +} + +p:first-child { + margin-top: 0; +} + +p:last-child { + margin-bottom: 0; +} + +img { + max-width: 100%; + height: auto; + display: block; +} + +video { + display: block; +} + +a { + color: var(--accent); + text-decoration: none; + transition: color .15s ease, background .15s ease, text-shadow .25s ease, box-shadow .25s ease; +} + +a:hover, +a:focus-visible { + background: color-mix(in srgb, var(--accent-cyan) 18%, var(--accent)); + color: #ffd0d0; + text-shadow: + 0 0 4px rgba(var(--link-glow), .95), + 0 0 12px rgba(var(--link-glow), .7), + 0 0 24px rgba(var(--link-glow), .45); + box-shadow: + 0 0 0 1px rgba(var(--link-glow), .55), + 0 0 10px rgba(var(--link-glow), .5), + 0 0 24px -4px rgba(var(--link-glow), .4); + border-radius: 2px; + transform: scale(1.02); +} + +/* External links get a persistent subtle glow as an affordance */ +a[href^="http"]:not([href*="sillylaird.ca"]):hover, +a[href^="https"]:not([href*="sillylaird.ca"]):focus-visible { + text-shadow: + 0 0 6px rgba(var(--glow-color), 1), + 0 0 16px rgba(var(--glow-color), .75), + 0 0 32px rgba(var(--glow-color), .5); +} + +/* Buttons styled as links shouldn't pick up the link box-shadow halo on top of their own */ +.header-button:hover, +.header-button:focus-visible, +#menu-toggle:hover, +#menu-toggle:focus-visible { + text-shadow: none; +} + +h1 { + margin: 0 0 var(--space-md) 0; + color: var(--gold); + font-weight: 700; + font-size: var(--fs-2xl); + letter-spacing: .2px; + line-height: 1.2; +} + +h2 { + margin: 0 0 var(--space-md) 0; + color: var(--gold); + font-size: var(--fs-xl); + font-weight: 800; + letter-spacing: .1px; + line-height: 1.3; +} + +blockquote { + margin: var(--space-md) 0 0 0; + padding-left: var(--space-md); + border-left: 3px solid var(--border); + color: var(--muted); + font-style: italic; + font-size: var(--fs-sm); + line-height: 1.6; +} + +.muted { + color: var(--muted); + font-size: var(--fs-sm); +} + +.footer-colophon { + max-width: 46rem; + margin: var(--space-sm) auto 0; + color: var(--muted); + font-size: var(--fs-xs); +} + +/* Comic Sans headers (intentional retro style) */ +h1 { + font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; + font-size: clamp(1.5rem, 1.3rem + 1vw, 1.875rem); + padding-left: 40px; +} + +pre { + font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; + font-size: 12px; + padding-left: 40px; +} + +/* ========================================================================== + 4. Accessibility + ========================================================================== */ +.skip-link { + position: absolute; + left: -999px; + top: 0; + background: var(--bg); + border: 1px solid var(--border); + padding: .5rem .75rem; + border-radius: var(--r); + z-index: 2000; +} + +.skip-link:focus { + left: 1rem; + top: 1rem; +} + +:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +/* ========================================================================== + 5. Layout + ========================================================================== */ +.wrap { + max-width: var(--wrap); + margin: 0 auto; + padding: var(--space-xl) var(--space-lg) var(--space-3xl); +} + +.stack { + display: flex; + flex-direction: column; + gap: var(--space-xl); +} + +.stack-small { + display: flex; + flex-direction: column; + gap: var(--space-sm); +} + +section { + position: relative; + margin: var(--space-xl) 0; + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-lg); + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .06), transparent 70%), + var(--bg); + box-shadow: var(--glow-soft); + transition: box-shadow .35s ease, border-color .35s ease, transform .2s ease; +} + +section:focus-within { + border-color: rgba(var(--glow-color), .28); +} + +.site-status-row { + display: flex; + flex-wrap: wrap; + gap: var(--space-sm); + align-items: center; + color: var(--muted); + font-size: var(--fs-sm); +} + +.home-status-row { + margin: 0 0 var(--space-md); +} + +.site-status-row span, +.site-status-row a { + display: inline-flex; + align-items: center; + min-height: 28px; + border: 1px solid var(--border); + border-radius: var(--r); + padding: 2px var(--space-sm); + background: #070000; +} + +.footer-status-row { + justify-content: center; +} + +.featured-links { + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: var(--space-sm); + margin: calc(-1 * var(--space-sm)) 0 var(--space-xl); +} + +.featured-links a { + min-height: 42px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-sm); + background: #070000; + text-align: center; + font-size: var(--fs-sm); + font-weight: 700; +} + +#contact { + padding: var(--space-md); +} + +#contact blockquote, +#contact .audio-wrap { + margin-top: var(--space-sm); +} + +#contact .contact-list { + margin-top: var(--space-sm); +} + +section:hover { + border-color: rgba(var(--glow-color), .55); + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .35), + 0 0 18px -4px rgba(var(--glow-color), .45), + 0 0 48px -8px rgba(var(--glow-color), .30); +} + +/* ========================================================================== + 6. Header + ========================================================================== */ +header.site-header, +footer.site-footer { + background: var(--bg); + border-bottom: 1px solid var(--border); +} + +header.site-header { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; +} + +body:has(header.site-header) { + padding-top: var(--site-header-height, 76px); +} + +.header-inner { + max-width: var(--wrap); + margin: 0 auto; + padding: var(--space-md) var(--space-lg); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-lg); + flex-wrap: wrap; +} + +.brand { + display: flex; + align-items: center; + gap: var(--space-md); + min-width: 240px; +} + +.logo { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--r); +} + +.logo img { + height: 48px; + width: 48px; + object-fit: contain; + border: 2px solid var(--border); + border-radius: var(--r); + transition: border-color .25s ease, box-shadow .35s ease, transform .35s ease; +} + +header.site-header .logo:hover img, +header.site-header .logo:focus-visible img { + border-color: rgba(var(--glow-color), .9); + box-shadow: var(--glow-strong); + animation: logo-pulse 2.4s ease-in-out infinite; +} + +@keyframes logo-pulse { + 0%, 100% { + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .55), + 0 0 6px rgba(var(--glow-color), .65), + 0 0 18px rgba(var(--glow-color), .55), + 0 0 48px rgba(var(--glow-color), .35), + inset 0 0 12px rgba(var(--glow-color), .18); + } + 50% { + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .8), + 0 0 10px rgba(var(--glow-color), .9), + 0 0 28px rgba(var(--glow-color), .75), + 0 0 64px rgba(var(--glow-color), .5), + inset 0 0 18px rgba(var(--glow-color), .28); + } +} + +@media (prefers-reduced-motion: reduce) { + header.site-header .logo:hover img, + header.site-header .logo:focus-visible img { + animation: none; + } +} + +.brand-text { + display: flex; + flex-direction: column; + line-height: 1.2; +} + +.brand-text strong { + font-size: var(--fs-lg); + color: var(--gold); + letter-spacing: .2px; +} + +.brand-text span { + font-size: var(--fs-sm); + color: var(--muted); +} + +.header-controls { + display: flex; + align-items: center; + gap: var(--space-md); +} + +.header-button { + font-size: var(--fs-sm); + border: 1px solid var(--border); + padding: 4px 8px; + border-radius: var(--r); + color: var(--gold); + text-decoration: none; + background: var(--bg); + cursor: pointer; + font-family: inherit; + display: inline-flex; + align-items: center; + justify-content: center; + transition: background .15s, color .15s, border-color .15s, box-shadow .25s; +} + +.header-button:hover { + background: var(--accent); + color: var(--ink); + border-color: rgba(var(--glow-color), .9); + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .4), + 0 0 12px rgba(var(--glow-color), .55), + 0 0 28px -4px rgba(var(--glow-color), .4); +} + +/* ========================================================================== + 7. Navigation Menu + ========================================================================== */ +.menu-wrapper { + position: relative; +} + +#menu-toggle { + width: 44px; + height: 44px; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 22px; + line-height: 1; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + color: var(--ink); + padding: 0; +} + +#menu-toggle { + transition: transform .25s ease, background .15s, color .15s, border-color .15s, box-shadow .25s; +} + +#menu-toggle:hover { + background: var(--accent); + color: var(--ink); + border-color: rgba(var(--glow-color), .9); + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .4), + 0 0 14px rgba(var(--glow-color), .6), + 0 0 32px -4px rgba(var(--glow-color), .4); +} + +#menu-toggle.active { + transform: rotate(90deg); + background: var(--bg); + color: var(--ink); + border-color: var(--border); +} + +#menu-toggle.active:hover { + background: var(--accent); + color: var(--ink); + border-color: var(--accent); +} + +nav.site-nav { + position: absolute; + right: 0; + top: calc(100% + var(--space-xs)); + background: var(--bg); + border: 1px solid var(--ink); + border-radius: var(--r); + padding: var(--space-md) var(--space-md); + min-width: 200px; + box-shadow: 0 10px 22px var(--shadow); + z-index: 1200; + max-height: calc(100vh - 80px); + overflow-y: auto; +} + +nav.site-nav ul { + list-style: none; + margin: 0; + padding: 0; +} + +nav.site-nav li { + margin: var(--space-sm) 0; +} + +nav.site-nav a { + display: block; + padding: var(--space-xs) var(--space-xs); + transition: background .15s, color .15s; + color: var(--gold); + font-size: var(--fs-xl); + margin: 0; +} + +nav.site-nav a:hover { + background: var(--accent); + color: var(--ink); +} + +nav.site-nav .nav-section { + margin-bottom: var(--space-sm); +} + +nav.site-nav .nav-section:last-child { + margin-bottom: 0; +} + +nav.site-nav .nav-section+.nav-section { + border-top: 1px solid var(--border); + padding-top: var(--space-sm); +} + +nav.site-nav .nav-label { + font-size: var(--fs-xs); + font-weight: 600; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.5px; + margin-bottom: var(--space-xs); + padding: var(--space-xs); +} + +/* Language dropdown */ +.lang { + position: relative; +} + +.lang-toggle-wrapper { + display: inline-block; +} + +.lang-menu { + position: absolute; + right: 0; + top: calc(100% + var(--space-xs)); + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--r); + box-shadow: 0 10px 22px var(--shadow); + min-width: 160px; + padding: var(--space-sm); + z-index: 1200; +} + +.lang-menu a { + display: block; + padding: var(--space-sm) var(--space-sm); + color: var(--gold); + transition: background .15s; +} + +.lang-menu a:hover { + background: var(--accent); + color: var(--ink); +} + +/* ========================================================================== + 8. Components — Cards, Lists, Tiles, Embeds + ========================================================================== */ + +/* Changelog */ +.changelog-title { + color: var(--gold); + margin-bottom: var(--space-sm); +} + +.changelog-date { + font-size: var(--fs-3xl); + font-weight: 700; + color: var(--muted); + margin: var(--space-sm) 0 var(--space-lg) 0; + line-height: 1.1; +} + +/* Video */ +.video-wrap { + margin: var(--space-md) 0 0 0; +} + +.video-wrap video { + width: 100%; + height: auto; + max-height: 80vh; + background: #000; + border: 1px solid var(--border); + border-radius: var(--r); +} + +/* Contact list */ +.contact-list { + list-style: none; + padding: 0; + margin: var(--space-md) 0 0 0; +} + +.contact-list li { + margin: var(--space-sm) 0; + line-height: 1.6; +} + +.contact-address { + font-style: normal; +} + +/* Iframe loading overlay */ +.iframe-clip { + position: relative; +} + +.iframe-clip iframe { + position: relative; + z-index: 1; +} + +.iframe-clip.is-loading::before { + content: "loading..."; + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba(2, 2, 2, 0.94); + color: var(--neon-green); + font-family: var(--font-mono); + font-size: var(--fs-sm); + text-shadow: 0 0 8px rgba(57, 255, 20, .45); + z-index: 2; +} + +.iframe-clip.is-loading::after { + content: "_"; + position: absolute; + top: 50%; + left: calc(50% + 2.8em); + transform: translateY(-50%); + color: var(--accent-cyan); + font-family: var(--font-mono); + font-size: var(--fs-sm); + font-weight: 700; + animation: retro-cursor-blink 1s step-end infinite; + z-index: 3; +} + +@keyframes retro-cursor-blink { + 50% { opacity: 0; } +} + +/* Friends grid */ +.friends-list { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); + gap: var(--space-lg); + margin: var(--space-lg) 0 0 0; + padding: 0; + list-style: none; +} + +.friends-list a { + display: flex; + align-items: center; + justify-content: center; + min-height: 44px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + background: var(--surface-deep); + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-sm) var(--space-md); + color: var(--accent); + transition: + background .2s ease, + color .2s ease, + border-color .2s ease, + box-shadow .25s ease, + transform .2s ease; +} + +.friends-list a:hover, +.friends-list a:focus-visible { + background: color-mix(in srgb, var(--accent-cyan) 14%, var(--accent)); + color: #ffd0d0; + border-color: var(--accent-cyan); + transform: translateY(-2px) scale(1.03); + box-shadow: + inset 0 0 16px rgba(var(--link-glow), .12), + 0 0 0 1px rgba(var(--link-glow), .45), + 0 0 14px rgba(var(--link-glow), .35); +} + +.network-subsection .friends-list a:hover, +.network-subsection .friends-list a:focus-visible { + background: color-mix(in srgb, var(--section-neon) 16%, var(--bg)); + border-color: var(--section-neon); + color: #ffd0d0; + box-shadow: + inset 0 0 18px rgba(var(--section-glow), .14), + 0 0 0 1px rgba(var(--section-glow), .5), + 0 0 16px rgba(var(--section-glow), .38); +} + +/* Tiles */ +.tile-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: var(--space-lg); + list-style: none; + padding: 0; + margin: var(--space-lg) 0 0 0; +} + +.tile-grid a { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + max-width: 100%; + box-sizing: border-box; + height: 64px; + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-sm); + transition: background .15s, border-color .15s, box-shadow .15s; +} + +.tile-grid a:hover { + background: var(--accent); + color: var(--ink); + border-color: var(--accent); + box-shadow: 0 1px 0 var(--accent) inset; +} + +.tile-grid img { + width: 100%; + height: 100%; + object-fit: contain; + aspect-ratio: auto; +} + +/* Reserve tile box height to avoid CLS regardless of intrinsic img dims. */ +.tile-grid li.tile--wide a { + aspect-ratio: 5 / 2; +} + +.tile-grid a:has(.vendor-logo):not(:hover), +.tile-grid a.vendor-link:not(:hover) { + background: transparent; + border-color: #5a0000; +} +.tile-grid .vendor-logo { + padding: 8px; + box-sizing: border-box; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} +.tile-grid .vendor-logo svg { + max-width: 70%; + max-height: 70%; + width: auto; + height: auto; + display: block; +} + +.tile-grid li.tile--wide a { + height: 128px; +} + +.tile-grid--three { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} +.tile-grid--three li.tile--wide { + grid-column: auto; +} +@media (max-width: 640px) { + .tile-grid--three { + grid-template-columns: 1fr; + } +} + +/* Embeds */ +.embed-frame { + display: block; + width: 100%; + border: 1px solid var(--border); + border-radius: var(--r); + background: #000; + margin: var(--space-md) 0 0 0; +} + +.guestbook-form-frame { + height: 450px; + min-height: 450px; +} + +.iframe-clip { + position: relative; + overflow: hidden; + border-radius: var(--r); + border: 1px solid var(--border); + background: #000; +} + +.iframe-clip>iframe { + display: block; + width: 100%; + height: 100%; + border: 0; + background: #000; + color-scheme: dark; +} +.guestbook-form-frame { + height: 500px; + min-height: 500px; +} + +#guestbook-comments-iframe { + height: 500px; + width: 100%; + border: 0; + background: #000; + color-scheme: dark; +} + +#guestbook-form-iframe { + height: 500px; + width: 100%; + border: 0; + background: #000; + color-scheme: dark; +} + +.changelog-frame { + min-height: 360px; +} + +/* Audio */ +.audio-wrap { + margin: var(--space-md) 0 0 0; +} + +audio { + width: 100%; + max-width: 400px; +} + +/* Forms */ +form { + display: flex; + flex-direction: column; + gap: var(--space-md); +} + +label { + display: block; + font-size: var(--fs-sm); + font-weight: 600; + color: var(--gold); +} + +input[type="text"], +input[type="email"], +input[type="url"], +input[type="password"], +input[type="search"], +textarea, +select { + width: 100%; + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-sm) var(--space-md); + color: var(--ink); + font-family: inherit; + font-size: var(--fs-base); + transition: border-color .15s, box-shadow .15s; +} + +input:focus, +textarea:focus, +select:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 2px rgba(139, 0, 0, 0.2); +} + +textarea { + resize: vertical; + min-height: 100px; +} + +input::placeholder, +textarea::placeholder { + color: var(--muted); + opacity: 0.6; +} + +button[type="submit"], +button.button-primary { + background: var(--accent); + color: #e0e0e0; + border: 1px solid var(--accent); + padding: var(--space-sm) var(--space-lg); + border-radius: var(--r); + cursor: pointer; + font-weight: 700; + font-family: inherit; + font-size: var(--fs-base); + transition: background .15s, transform .1s; +} + +button[type="submit"]:hover, +button.button-primary:hover { + background: var(--ink); + color: var(--bg); +} + +button:not(.logo):not(.reset-button):not(.header-button):not([type="submit"]):not(.button-primary) { + background: var(--bg); + color: var(--ink); + border: 1px solid var(--border); + padding: var(--space-sm) var(--space-lg); + border-radius: var(--r); + cursor: pointer; + font-family: inherit; + transition: background .15s, color .15s; +} + +button:not(.logo):not(.reset-button):not(.header-button):not([type="submit"]):not(.button-primary):hover { + background: var(--accent); + color: #e0e0e0; +} + +button[type="submit"]:active { + transform: translateY(1px); +} + +.stack { + display: flex; + flex-direction: column; + gap: var(--space-md); +} + +.field-group { + display: block; + width: 100%; +} + +/* Guestbook Specific */ +.captcha-wrap { + display: flex; + flex-direction: column; + gap: var(--space-sm); + align-items: flex-start; +} + +.captcha-img { + border-radius: var(--r); + border: 1px solid var(--border); + background: var(--bg); +} + +.guestbook-entry { + background: var(--bg); + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md); + margin-bottom: var(--space-md); + transition: border-color .15s, box-shadow .15s; +} + +.guestbook-entry:hover { + border-color: var(--accent); +} + +.guestbook-entry:last-child { + margin-bottom: 0; +} + +.guestbook-entry strong { + color: var(--gold); + display: block; + font-size: var(--fs-sm); + margin-bottom: var(--space-xs); +} + +.guestbook-entry time { + display: block; + font-size: var(--fs-xs); + color: var(--muted); + margin-bottom: var(--space-sm); +} + +.guestbook-entry p { + margin: 0; + line-height: 1.6; + font-family: inherit; + color: var(--ink) !important; +} + +.anonymous { + color: var(--ink) !important; +} + +/* Blog + changelog lists */ +#blog-list, +#changelog-list { + margin: var(--space-md) 0 0 0; +} + +#blog-list>div:first-child, +#changelog-list>div:first-child { + margin-bottom: var(--space-md); +} + +#blog-list ol, +#changelog-list ol { + margin: var(--space-md) 0 0 0; + padding-left: var(--space-xl); +} + +#blog-list li, +#changelog-list li { + margin: 0 0 var(--space-md) 0; + line-height: 1.6; +} + +#blog-list .muted, +#changelog-list .muted { + font-size: var(--fs-sm); + margin-top: var(--space-xs); +} + +#blog-list .blog-more { + margin-top: var(--space-xs); +} + +#changelog-list .changelog-body { + margin-top: var(--space-xs); + white-space: pre-line; +} + +#changelog-list time { + color: var(--accent); +} + +/* Reset Button */ +.reset-button { + font-size: var(--fs-sm); + border: 1px solid var(--border); + padding: 4px 8px; + border-radius: var(--r); + color: var(--ink); + background: var(--bg); + cursor: pointer; + font-family: inherit; + display: inline-flex; + align-items: center; + justify-content: center; + transition: background .15s, color .15s, border-color .15s; +} + +.reset-button:hover { + background: var(--accent); + color: var(--ink); + border-color: var(--accent); +} + +.category-block { + margin: var(--space-xl) 0; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--bg); + overflow: hidden; +} + +.category-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--space-md) var(--space-lg); + border-bottom: 1px solid var(--border); + background: rgba(139, 0, 0, 0.05); +} + +.category-header h2 { + margin: 0; + font-size: var(--fs-xl); +} + +.category-content { + padding: var(--space-lg); +} + +.mini-button { + padding: 4px 12px; + font-size: var(--fs-xs); + background: var(--bg); + border: 1px solid var(--border); + color: var(--ink); + border-radius: var(--r); + cursor: pointer; + transition: background 0.2s; +} + +.mini-button:hover { + background: var(--accent); + color: var(--ink); +} + +/* Last.fm Widget */ +.lastfm-inner-box { + border: 1px solid var(--border); + padding: var(--space-md); + background: rgba(139, 0, 0, 0.03); + border-radius: var(--r); + box-shadow: inset 0 2px 4px rgba(0,0,0,0.3); +} + +.lastfm-link-hint { + font-size: var(--fs-xs); + text-align: left; + margin-top: var(--space-md); + padding-top: var(--space-xs); + border-top: 1px dotted var(--border); +} + +.lastfm-text-list { + list-style: none; + padding: 0; + margin: 0; +} + +.lastfm-text-list li { + margin-bottom: var(--space-xs); + line-height: 1.4; +} + +.lastfm-text-list li strong { + color: var(--accent); +} + +.lastfm-track { + display: flex; + align-items: center; + gap: var(--space-md); + padding: var(--space-sm); + border: 1px solid var(--border); + border-radius: var(--r); + background: rgba(139, 0, 0, 0.05); + width: 100%; + transition: background 0.2s, transform 0.2s; + text-decoration: none; + min-height: 80px; +} + +.lastfm-track:hover { + background: rgba(139, 0, 0, 0.1); + transform: translateY(-2px); + border-color: var(--accent); +} + +.lastfm-image-wrap { + flex-shrink: 0; + width: 64px; + height: 64px; + border-radius: var(--r); + overflow: hidden; + border: 1px solid var(--border); +} + +.lastfm-image-wrap img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.lastfm-info { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + min-width: 0; /* Prevents overflow */ +} + +.lastfm-status { + font-size: var(--fs-xs); + text-transform: uppercase; + letter-spacing: 1px; + color: var(--muted); + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 2px; +} + +.lastfm-status.is-playing { + color: var(--gold); +} + +.lastfm-status.is-playing::after { + content: ""; + width: 8px; + height: 8px; + background: var(--gold); + border-radius: 50%; + display: inline-block; + animation: pulse-red 1.5s infinite; +} + +@keyframes pulse-red { + 0% { box-shadow: 0 0 0 0 rgba(178, 34, 34, 0.7); } + 70% { box-shadow: 0 0 0 6px rgba(178, 34, 34, 0); } + 100% { box-shadow: 0 0 0 0 rgba(178, 34, 34, 0); } +} + +.lastfm-title { + font-weight: 700; + color: var(--gold); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: var(--fs-lg); +} + +.lastfm-artist { + font-size: var(--fs-sm); + color: var(--ink); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.lastfm-error-msg { + display: none; + font-size: var(--fs-xs); + color: var(--muted); + padding: var(--space-md); + border: 1px dashed var(--border); + border-radius: var(--r); + text-align: center; + width: 100%; +} + +/* ========================================================================== + 9. Page-specific (from legacy style.css) + ========================================================================== */ +.button1 { + background-color: black; + font-family: Comic Sans MS; + font-weight: 300; +} + +.member { + float: left; + width: calc(20% - 2%); + margin: 1% 1% 45px 1%; +} + +.name { + bottom: 0px; +} + +.member img { + width: 50%; + display: block; +} + +ul.flowxl { + display: flex; + flex-wrap: wrap; + padding: 0; +} + +ul.flowxl>li { + list-style-type: none; + text-align: center; + width: var(--xiconsize); + min-width: var(--xiconsize); + max-width: var(--xiconsize); + max-height: calc(var(--xiconsize) + 60px); + padding: 2px; + margin: 0.125rem; + overflow: hidden; + font-size: 1rem; + line-height: 1; +} + +ul.flowxl>li>a { + display: block; + line-height: 1; + font-size: 1.2rem; +} + +ul.flowxl li>a>img, +ul.flowxl li>img { + display: block; + border-radius: 9px; + width: auto; + max-width: var(--xiconsize); + max-height: var(--xiconsize); + overflow: hidden; + margin-left: auto; + margin-right: auto; +} + +ul.flowxl li>a>img[src$=".svg"] { + max-width: 170px; + max-height: 170px; +} + +.country-img { + height: 12.5rem; + width: 250px; + object-fit: contain; + max-width: 100%; +} + +.countries { + flex-wrap: wrap; + gap: 10px; + justify-content: center; +} + +.vpn-logo { + width: 200px; + max-width: 100%; + height: auto; + object-fit: contain; +} + +/* ========================================================================== + 10. Footer + ========================================================================== */ +footer.site-footer { + position: relative; + border-top: 1px solid var(--border); + border-bottom: none; +} + +footer.site-footer::after { + content: ''; + display: block; + height: 4px; + background: + repeating-linear-gradient( + 90deg, + transparent, + transparent 3px, + rgba(var(--link-glow), .25) 3px, + rgba(var(--link-glow), .25) 4px + ), + linear-gradient(90deg, var(--neon-green), var(--accent-cyan), var(--accent-purple), var(--accent-pink)); + opacity: 0.45; + box-shadow: 0 -1px 12px rgba(var(--link-glow), .15); +} + +.site-footer .footer-inner::after { + content: '> connection closed — EOF_'; + display: block; + margin-top: var(--space-md); + padding-top: var(--space-sm); + border-top: 1px dashed color-mix(in srgb, var(--border) 70%, transparent); + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.06em; + color: var(--muted); + opacity: 0.5; + animation: footer-cursor-hint 2.5s step-end infinite; +} + +@keyframes footer-cursor-hint { + 50% { opacity: 0.35; } +} + +.footer-inner { + max-width: var(--wrap); + margin: 0 auto; + padding: var(--space-lg) var(--space-lg) var(--space-2xl); + color: var(--muted); + font-size: var(--fs-sm); + line-height: 1.6; +} + +.badge { + display: inline-flex; + margin-top: var(--space-sm); + border-radius: var(--r); + padding: var(--space-xs); + border: 1px solid var(--border); + background: #2a0000; + transition: border-color .15s; +} + +.badge:hover { + border-color: var(--accent); +} + +.eff-badge { + background: #000000 !important; + border-color: #4a0000 !important; + box-shadow: none !important; +} + +.tile-grid a.eff-badge:hover, +.tile-grid a.eff-badge:focus-visible { + background: #000000 !important; + border-color: #a00000 !important; + box-shadow: none !important; +} + +.eff-badge:focus-visible { + outline: 2px solid #2a52ff !important; +} + +.tile-grid a.eff-badge:hover img, +.tile-grid a.eff-badge:focus-visible img { + box-shadow: none !important; +} + +.eff-badge img { + opacity: .95; + filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .55)); +} + +body.light-mode .eff-badge { + background: #ffffff !important; + border-color: #78c8ff !important; + box-shadow: + 0 0 0 1px rgba(120, 200, 255, .25), + 0 0 16px rgba(120, 200, 255, .32); +} + +body.light-mode .tile-grid a.eff-badge:hover, +body.light-mode .tile-grid a.eff-badge:focus-visible, +body.light-mode .badge.eff-badge:hover, +body.light-mode .badge.eff-badge:focus-visible { + background: var(--accent) !important; + border-color: var(--accent) !important; +} + +body.light-mode .eff-badge img { + content: url("/assets/img/rib_bar_wh.png"); + filter: drop-shadow(0 1px 0 rgba(0, 38, 64, .35)); +} + +.badge.eff-badge img { + width: 150px; + max-width: 100%; + height: auto; + aspect-ratio: 572 / 120; +} + +.tile-grid .eff-badge img { + width: 100%; + height: 100%; + object-fit: contain; +} + +/* ========================================================================== + 11. Responsive + ========================================================================== */ + +/* Long URLs / emails / quotes never blow out the viewport */ +.contact-list, +.contact-list a, +blockquote, +.lastfm-link-hint, +.vibe-preview-link, +#blog-list a, +#changelog-list a { + overflow-wrap: anywhere; + word-break: break-word; +} + +/* Tables become horizontally scrollable rather than overflowing */ +table { + display: block; + max-width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +/* Long <pre> blocks wrap on narrow screens */ +pre { + white-space: pre-wrap; + word-break: break-word; +} + +/* Tablet: fix tile-grid gaps */ +@media (min-width: 601px) and (max-width: 900px) { + .tile-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .friends-list { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 720px) { + /* Header: let controls wrap cleanly under brand */ + .header-inner { + gap: var(--space-sm); + } + + .brand { + min-width: 0; + flex: 1 1 auto; + } + + .header-controls { + flex-wrap: wrap; + justify-content: flex-end; + gap: var(--space-sm); + row-gap: var(--space-xs); + } + + /* Tighten the language button's label so it fits next to the others */ + #lang-toggle { + white-space: nowrap; + } +} + +@media (max-width: 600px) { + .wrap { + padding: var(--space-lg) var(--space-md) var(--space-2xl); + } + + section { + padding: var(--space-md); + } + + /* h1 / pre had a 40px left indent that wastes space on phones */ + h1, + pre { + padding-left: 0; + } + + .home-status-row { + margin-left: 0; + } + + .featured-links { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .tile-grid { + display: flex; + flex-direction: column; + align-items: center; + } + + .tile-grid li { + margin-bottom: 1rem; + text-align: center; + width: 100%; + } + + .tile-grid a { + width: 100%; + } + + .contact-list { + padding-left: 20px; + } + + .friends-list { + display: flex; + flex-direction: column; + gap: 10px; + } + + /* Hide the subtitle line on tight screens so the brand fits on one line */ + .brand-text span { + display: none; + } + + /* Iframes: drop the desktop fixed heights so they're not absurd on phones */ + .guestbook-form-frame, + #guestbook-form-iframe, + #guestbook-comments-iframe { + height: 420px; + min-height: 420px; + } +} + +@media (max-width: 520px) { + header.site-header { + position: fixed; + top: 0; + left: 0; + right: 0; + } + + .header-inner { + position: relative; + padding: var(--space-sm) var(--space-md); + } + + nav.site-nav { + min-width: 200px; + max-width: calc(100vw - 2 * var(--space-md)); + } + + .lang-menu { + right: auto; + left: 0; + max-width: calc(100vw - 32px); + } + + #menu-toggle { + display: inline-flex; + transition: transform .25s ease; + } + + #menu-toggle.active { + transform: rotate(90deg); + } + + /* Last.fm row: stack image + info if title would clip */ + .lastfm-track { + gap: var(--space-sm); + } + + .lastfm-image-wrap { + width: 48px; + height: 48px; + } + + /* Header buttons: keep tap targets but trim padding */ + .header-button { + padding: 4px 6px; + } +} + +@media (max-width: 380px) { + /* Very narrow phones: shrink header buttons further so all wrap cleanly */ + .header-button { + font-size: var(--fs-xs); + padding: 3px 5px; + } +} + +@media (prefers-reduced-motion: reduce) { + * { + transition: none !important; + scroll-behavior: auto !important; + } + + #menu-toggle.active { + transform: none; + } +} + +/* ========================================================================== + 12. Theme: High Contrast (dark) + ========================================================================== */ +[data-theme="high-contrast"] { + --bg: #000000; + --ink: #ffffff; + --muted: #ccc; + --accent: #ff0000; + --gold: #ff4d4d; + --border: #fff; + --shadow: rgba(255, 255, 255, .12); +} + +[data-theme="high-contrast"] a { + color: #ff0000; + text-decoration: underline; +} + +[data-theme="high-contrast"] a:hover { + background: #ff0000; + color: #000; +} + +[data-theme="high-contrast"] nav.site-nav a { + color: #fff; +} + +[data-theme="high-contrast"] .friends-list a { + color: #ff0000; +} + +/* ========================================================================== + 13. Theme: Light Mode + ========================================================================== */ +body.light-mode { + --bg: #fff8f1; + --surface: #fffdf9; + --surface-soft: #faf3ea; + --surface-tint: #f5ebe0; + --ink: #2a1212; + --muted: #7a4545; + --accent: #8b0000; + --gold: #8b0000; + --border: #d9c9b8; + --shadow: rgba(92, 72, 52, .12); + --glow-color: 139, 0, 0; + --link-glow: 139, 0, 0; + --btn-glow: 139, 0, 0; + --glow-soft: + 0 1px 0 rgba(255, 255, 255, .95) inset, + 0 8px 26px rgba(139, 0, 0, .12); + --glow-strong: + 0 0 0 1px rgba(var(--glow-color), .45), + 0 10px 30px rgba(139, 0, 0, .18); + color-scheme: light; + background: #fff8f1; +} + +body.light-mode header.site-header, +body.light-mode footer.site-footer, +body.light-mode .header-search { + background: rgba(255, 248, 241, .96); +} + +body.light-mode section, +body.light-mode .category-block, +body.light-mode .guestbook-entry, +body.light-mode .captcha-img { + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .18), transparent 72%), + var(--surface); +} + +body.light-mode .site-status-row span, +body.light-mode .site-status-row a, +body.light-mode .featured-links a, +body.light-mode .friends-list a, +body.light-mode .tile-grid a, +body.light-mode .header-button, +body.light-mode #menu-toggle, +body.light-mode nav.site-nav, +body.light-mode .lang-menu, +body.light-mode input[type="text"], +body.light-mode input[type="email"], +body.light-mode input[type="url"], +body.light-mode input[type="password"], +body.light-mode input[type="search"], +body.light-mode textarea, +body.light-mode select, +body.light-mode button:not(.logo):not(.reset-button):not(.header-button):not([type="submit"]):not(.button-primary), +body.light-mode .reset-button, +body.light-mode .mini-button { + background: var(--surface); +} + +body.light-mode .category-header, +body.light-mode .lastfm-inner-box, +body.light-mode .lastfm-track { + background: var(--surface-soft); +} + +body.light-mode .lastfm-track:hover, +body.light-mode .featured-links a:hover, +body.light-mode .friends-list a:hover, +body.light-mode .tile-grid a:hover, +body.light-mode .header-button:hover, +body.light-mode #menu-toggle:hover, +body.light-mode nav.site-nav a:hover, +body.light-mode .lang-menu a:hover, +body.light-mode button:not(.logo):not(.reset-button):not(.header-button):not([type="submit"]):not(.button-primary):hover, +body.light-mode .reset-button:hover, +body.light-mode .mini-button:hover, +body.light-mode a:hover, +body.light-mode a:focus-visible { + background: var(--accent); + color: #ffffff; + text-shadow: none; +} + +body.light-mode button[type="submit"], +body.light-mode button.button-primary { + color: #ffffff; +} + +body.light-mode button[type="submit"]:hover, +body.light-mode button.button-primary:hover { + color: #ffffff; +} + +body.light-mode .badge { + background: var(--surface-tint); +} + +body.light-mode .video-wrap video, +body.light-mode .embed-frame, +body.light-mode .iframe-clip, +body.light-mode .iframe-clip>iframe, +body.light-mode #guestbook-comments-iframe, +body.light-mode #guestbook-form-iframe { + background: var(--surface); + color-scheme: light; +} + +body.light-mode .iframe-clip.is-loading::before { + background: rgba(248, 253, 255, 0.92); +} + +body.light-mode .tile-grid a:has(.vendor-logo):not(:hover), +body.light-mode .tile-grid a.vendor-link:not(:hover) { + background: var(--surface); + border-color: var(--border); +} + +body.light-mode .unified-search, +body.light-mode .search-engine-toggle, +body.light-mode .search-engine-menu, +body.light-mode .unified-search .unified-search-input { + background: var(--surface); +} + +body.light-mode .search-engine-toggle:hover, +body.light-mode .search-engine-menu li:hover, +body.light-mode .search-engine-menu li[aria-selected="true"] { + background: var(--accent); + color: #ffffff; +} + +body.light-mode .unified-search .unified-search-input::placeholder { + color: rgba(85, 113, 127, 0.72); +} +.guestbook-error { color: var(--ink) !important; margin-bottom: 20px; } + +.vibe-preview-media { max-width: 100%; } +.vibe-preview-audio { width: 100%; } +.vibe-audio-full { width: 100%; } +.vibe-preview-link { font-size: var(--fs-sm); font-family: monospace; color: var(--accent); word-break: break-all; } + +/* ========================================================================== + Global Header Search (unified search w/ engine picker) + ========================================================================== */ +.header-search { + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); + background: var(--bg); + padding: var(--space-sm) var(--space-lg); + width: 100%; +} + +.header-search-inner { + max-width: var(--wrap); + margin: 0 auto; + width: 100%; +} + +.gh-search-form { + width: 100%; + margin: 0; +} + +.header-search .unified-search { + display: flex; + align-items: stretch; + width: 100%; + max-width: none; + margin: 0; +} + +.unified-search { + display: flex; + align-items: stretch; + width: 100%; + max-width: 584px; + margin: 0 auto; + border: 1px solid var(--border); + border-radius: var(--r); + background: #000; + position: relative; + transition: box-shadow .25s ease, border-color .25s ease; +} + +.unified-search:hover, +.unified-search:focus-within { + border-color: rgba(var(--glow-color), .8); + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .35), + 0 0 14px rgba(var(--glow-color), .55), + 0 0 36px -6px rgba(var(--glow-color), .35); +} + +.search-engine-picker { + position: relative; + display: flex; +} + +.search-engine-toggle { + background: #000; + color: var(--ink); + border: none; + border-right: 1px solid var(--border); + font-family: inherit; + font-weight: bold; + font-size: 0.95rem; + padding: 0 14px; + cursor: pointer; + min-width: 60px; + transition: background .15s, color .15s; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; +} + +.search-engine-toggle:hover { + background: var(--accent); + color: #000; +} + +.search-engine-caret { + font-size: 0.7rem; + opacity: 0.8; +} + +.search-engine-menu { + position: absolute; + top: calc(100% + 2px); + left: 0; + min-width: 200px; + margin: 0; + padding: 0; + list-style: none; + background: #000; + border: 1px solid rgba(var(--glow-color), .7); + border-radius: var(--r); + z-index: 1300; + text-align: left; + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .35), + 0 0 18px rgba(var(--glow-color), .55), + 0 10px 28px var(--shadow); +} + +.search-engine-menu[hidden] { + display: none; +} + +.search-engine-menu li { + padding: 8px 12px; + color: var(--ink); + cursor: pointer; + font-family: inherit; + font-size: 0.9rem; + display: flex; + align-items: center; + gap: 10px; + border-bottom: 1px solid var(--border); +} + +.search-engine-menu li:last-child { + border-bottom: none; +} + +.search-engine-menu li:hover, +.search-engine-menu li[aria-selected="true"] { + background: var(--accent); + color: #000; +} + +.search-engine-menu .engine-icon { + font-weight: bold; + min-width: 28px; + text-align: center; +} + +.unified-search .unified-search-input { + border: none; + border-radius: 0; + max-width: none; + flex: 1; + width: auto; + margin: 0; + padding: 8px 12px; + background: #000; + color: var(--ink); + font-family: inherit; + font-size: 0.95rem; + outline: none; + text-align: left; +} + +.unified-search .unified-search-input::placeholder { + color: rgba(139, 0, 0, 0.55); +} + +.unified-search .unified-search-input:focus { + box-shadow: none; +} + +@media (max-width: 600px) { + .header-search { padding: var(--space-xs) var(--space-sm); } + .search-engine-toggle { min-width: 52px; padding: 0 10px; font-size: 0.85rem; } + /* >=16px stops iOS Safari auto-zooming (and reflowing) the page on focus */ + .unified-search .unified-search-input { font-size: 16px; padding: 7px 10px; } +} + +/* ========================================================================== + Mobile nav drawer (<=600px) + Turn the absolute dropdown into a full-height right-edge sheet with + a backdrop, larger tap targets, and a body scroll lock while open. + ========================================================================== */ +@media (max-width: 600px) { + /* Hide redundant/secondary header buttons; primary nav lives in the drawer */ + .header-controls > a.header-button { + display: none; + } + /* Keep brand-text legible but tighten on narrow screens */ + .brand-text span { display: none; } + + .header-controls { + gap: var(--space-xs); + } + + /* Bigger, easier-to-hit hamburger */ + #menu-toggle { + width: 48px; + height: 48px; + font-size: 26px; + } + + /* Convert dropdown into right-edge sheet */ + nav.site-nav { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: auto; + width: min(86vw, 360px); + max-width: none; + min-width: 0; + max-height: 100vh; + max-height: 100dvh; + height: 100vh; + height: 100dvh; /* exclude mobile toolbar so bottom nav items aren't hidden */ + border-radius: 0; + border: 0; + border-left: 1px solid var(--ink); + padding: calc(var(--space-md) + 56px) var(--space-md) var(--space-lg); + overflow-y: auto; + overscroll-behavior: contain; + transform: translateX(100%); + transition: transform .25s ease; + z-index: 1300; + box-shadow: -8px 0 24px var(--shadow); + } + + nav.site-nav:not([hidden]) { + transform: translateX(0); + } + + /* Closed drawers should be truly hidden; opening is immediate, then the + sheet transform handles the visible state. */ + nav.site-nav[hidden] { + display: none !important; + pointer-events: none; + transform: translateX(100%); + } + + nav.site-nav a { + font-size: 1.05rem; + padding: 12px 10px; + border-radius: 6px; + } + + nav.site-nav li { + margin: 2px 0; + } + + /* Backdrop using ::before on body when menu is open */ + body:has(#menu-toggle[aria-expanded="true"])::before { + content: ""; + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.55); + z-index: 1250; + backdrop-filter: blur(2px); + animation: vibe-backdrop-in .2s ease; + } + + /* Lock body scroll while drawer open */ + body:has(#menu-toggle[aria-expanded="true"]) { + overflow: hidden; + } + + @keyframes vibe-backdrop-in { + from { opacity: 0; } + to { opacity: 1; } + } +} + +@media (max-width: 600px) and (prefers-reduced-motion: reduce) { + nav.site-nav { transition: none; } + body:has(#menu-toggle[aria-expanded="true"])::before { animation: none; } +} + +/* ========================================================================== + Polish: subtle hovers + typography rhythm + ========================================================================== */ +html { + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + font-feature-settings: "kern" 1, "liga" 1, "calt" 1; +} + +/* Breathing room between top-level sections */ +main.wrap.stack > section { + margin-bottom: var(--space-2xl); +} +main.wrap.stack > section:last-child { + margin-bottom: 0; +} + +/* Better paragraph rhythm and measure */ +main p { + line-height: 1.65; + max-width: 68ch; +} +main p + p { + margin-top: var(--space-sm); +} + +/* Heading micro-spacing: more above, tight below */ +main section > h2 { + margin-top: var(--space-lg); + margin-bottom: var(--space-sm); + scroll-margin-top: 80px; +} +main section > h2 + p, +main section > h2 + .muted { + margin-top: 0; +} + +/* Anchored section targets briefly glow */ +main section:target > h2 { + text-shadow: + 0 0 6px rgba(var(--glow-color), .8), + 0 0 18px rgba(var(--glow-color), .4); +} + +/* List items: subtle hover lift */ +.friends-list li, +.recent-list li { + transition: transform .15s ease, padding-left .15s ease; +} +.friends-list li:hover, +.recent-list li:hover { + transform: translateX(2px); +} + +.recent-list { + list-style: decimal; + padding-left: 1.5em; + margin: var(--space-sm) 0 0; +} +.recent-list li { + margin: var(--space-sm) 0; + line-height: 1.5; +} +.recent-list li > .muted { + font-size: 0.85em; + margin-top: 2px; +} +.recent-list li > div:not(.muted) { + margin-top: 2px; + opacity: 0.9; +} +.recent-list li > .changelog-more { + display: inline-block; + margin-top: 4px; + font-size: 0.85em; + white-space: nowrap; +} + +/* Tile-grid images: gentle scale + glow on hover */ +.tile-grid li { + transition: transform .2s ease; +} +.tile-grid a img, +.tile-grid a .vendor-logo { + transition: transform .2s ease, filter .2s ease, box-shadow .2s ease; +} +.tile-grid a:hover img, +.tile-grid a:focus-visible img, +.tile-grid a:hover .vendor-logo, +.tile-grid a:focus-visible .vendor-logo { + transform: translateY(-2px); + filter: brightness(1.08); + box-shadow: 0 6px 18px -6px rgba(var(--glow-color), .6); +} +/* Tile hover should not inherit the global link halo */ +.tile-grid a:hover, +.tile-grid a:focus-visible { + background: transparent; + text-shadow: none; + box-shadow: none; + transform: translateY(-2px) scale(1.03); +} + +.network-subsection .tile-grid a:hover, +.network-subsection .tile-grid a:focus-visible { + border-color: var(--section-neon); + box-shadow: + inset 0 0 20px rgba(var(--section-glow), .12), + 0 0 0 1px rgba(var(--section-glow), .45), + 0 0 18px rgba(var(--section-glow), .32) !important; +} + +.network-subsection#games .tile-grid a:hover, +.network-subsection#games .tile-grid a:focus-visible { + --section-neon: var(--neon-green); + --section-glow: 57, 255, 20; +} + +/* Featured nav links: tighter, more clickable */ +.featured-links { + gap: var(--space-md) var(--space-lg); +} +.featured-links a { + transition: transform .15s ease, color .15s ease, background .15s ease, box-shadow .25s ease; +} +.featured-links a:hover, +.featured-links a:focus-visible { + transform: translateY(-1px); +} + +/* Contact list: a touch more breathing room */ +.contact-list li { + margin: 4px 0; + line-height: 1.55; +} + +/* Blockquote: pull-quote feel */ +blockquote { + padding: var(--space-sm) var(--space-md); + border-radius: 4px; + background: rgba(var(--glow-color), .04); +} + +/* Network section: combined Friends + Games + Countries + Sponsors */ +.network-section .network-subsection { + margin-top: var(--space-2xl); + padding: var(--space-lg) var(--space-md) var(--space-xl); + border-top: 1px dashed var(--border); + border-radius: var(--r); + background: linear-gradient(180deg, rgba(var(--glow-color), .03), transparent 85%); +} + +.network-section .network-subsection:first-of-type { + margin-top: var(--space-md); + padding-top: var(--space-md); + border-top: 0; +} + +.network-section .network-subsection .tile-grid, +.network-section .network-subsection .friends-groups { + margin-top: var(--space-md); +} + +.network-subsection#friends { --section-neon: var(--accent-cyan); --section-glow: var(--link-glow); } +.network-subsection#games { --section-neon: var(--neon-green); --section-glow: 57, 255, 20; } +.network-subsection#countries { --section-neon: var(--accent-purple); --section-glow: 179, 136, 255; } +.network-subsection#buttons { --section-neon: var(--accent-pink); --section-glow: 255, 45, 149; } + +.network-subsection .network-subtitle::before { + content: '▸ '; + color: var(--section-neon, var(--gold)); + text-shadow: 0 0 8px color-mix(in srgb, var(--section-neon, var(--gold)) 50%, transparent); +} + +.network-subtitle { + margin: 0 0 var(--space-md); + font-size: 1.05rem; + font-weight: 700; + color: var(--gold); + letter-spacing: 0.3px; + scroll-margin-top: 80px; + text-shadow: 0 0 10px rgba(var(--glow-color), .25); +} + +/* Friends section: grouped columns */ +.friends-groups { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + gap: var(--space-2xl) var(--space-xl); + margin-top: var(--space-md); +} +.friends-group-title { + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 1px; + opacity: 0.7; + margin: 0 0 var(--space-xs); + font-weight: 600; +} +.friends-group .friends-list { + margin: 0; + padding-left: 1.1em; +} + +/* Recent updates block under the welcome paragraph */ +.home-recent-updates { + margin-top: var(--space-lg); + padding: var(--space-md) var(--space-lg); + border: 1px solid var(--border); + border-radius: 6px; + background: rgba(var(--glow-color), .04); +} +.home-recent-updates-title { + margin: 0 0 var(--space-sm); + font-size: var(--fs-md, 1rem); + text-transform: uppercase; + letter-spacing: 0.8px; + opacity: 0.8; +} +.home-recent-updates .recent-list { + margin: 0; +} +.home-recent-updates .recent-list strong { + font-weight: 600; +} + +/* Code inline rhythm */ +code, kbd, samp, pre { + font-family: var(--font-mono); + font-feature-settings: "calt" 1, "liga" 1; + font-size: 0.92em; +} + +@media (prefers-reduced-motion: reduce) { + .friends-list li, + .recent-list li, + .featured-links a, + .tile-grid li, + .tile-grid a img, + .tile-grid a .vendor-logo { + transition: none; + transform: none !important; + } +} + +/* ========================================================================== + 2026-05 polish pass: visual hierarchy, vibe container, mobile tap targets + ========================================================================== */ + +/* NOTE: every <section> is already a bordered card (see global `section` + rule), so no extra dividers/borders are needed here — that would double the + border. Just give the vibe embed a little depth. */ +.vibe-section > h2 { + margin-top: 0; +} +.vibe-embed { + box-shadow: 0 8px 24px -8px rgba(0, 0, 0, .6); +} + +/* Last.fm / radio fallback links should read as real links, not muted noise. */ +#lastfm-list a, +#radio-nowplaying a { + font-weight: 600; +} + +/* Mobile: larger spacing + tap targets so the link-dense layout is usable + on small screens (feedback: cramped on mobile). */ +@media (max-width: 600px) { + .featured-links a, + nav.site-nav a { + min-height: 44px; + display: flex; + align-items: center; + } + .contact-list a { + min-height: 44px; + display: inline-flex; + align-items: center; + } + .contact-list li { + margin: var(--space-sm) 0; + line-height: 1.5; + } +} + +/* ========================================================================== + 2026-05 polish pass 2: items 6-13 + ========================================================================== */ + +/* Screen-reader-only utility (#13 accessibility). */ +.visually-hidden { + position: absolute !important; + width: 1px; height: 1px; + padding: 0; margin: -1px; + overflow: hidden; clip: rect(0, 0, 0, 0); + white-space: nowrap; border: 0; +} + +/* (#9) Typography: slightly larger base on desktop + clearer heading weight + hierarchy so headings differ at a glance. */ +@media (min-width: 900px) { + body { font-size: clamp(1rem, 0.95rem + 0.25vw, 1.06rem); } +} +main p, main li { line-height: 1.7; } +main h1 { font-weight: 800; letter-spacing: -0.01em; } +main h2 { font-weight: 700; } +main h3, main h4 { font-weight: 600; } + +/* (#8) "Where to start" + site search. */ +.start-here { + border: 1px solid var(--border); + border-left: 3px solid var(--accent); + border-radius: var(--r); + padding: var(--space-md) var(--space-lg); + margin: var(--space-md) 0 var(--space-lg); + background: linear-gradient(180deg, rgba(var(--glow-color), .04), transparent 70%); +} +.start-here-title { margin-top: 0 !important; font-size: var(--fs-xl); } +.start-here-list { + list-style: none; padding: 0; margin: 0 0 var(--space-md); + display: grid; gap: var(--space-xs); +} +.start-here-list li { line-height: 1.5; } + +.site-search { display: flex; align-items: stretch; gap: 0; flex-wrap: wrap; } +.site-search input[type="search"] { + flex: 1 1 12rem; min-width: 0; + padding: var(--space-sm) var(--space-md); + border: 1px solid var(--accent); background: #000; color: var(--ink, #eee); + font: inherit; +} +.site-search .header-button { border-radius: 0; } + +/* Search engine picker (mirrors /startpage/, scoped vars for site.css). */ +.search-engine-picker { position: relative; display: flex; } +.search-engine-toggle { + background: #000; color: var(--accent); border: 1px solid var(--accent); + border-right: none; font-family: inherit; font-weight: bold; font-size: 1rem; + padding: 0 14px; cursor: pointer; min-width: 58px; + display: inline-flex; align-items: center; justify-content: center; gap: 6px; + transition: .15s; +} +.search-engine-toggle:hover { background: var(--accent); color: #000; } +.search-engine-caret { font-size: 0.7rem; opacity: 0.8; } +.search-engine-menu { + position: absolute; top: calc(100% + 2px); left: 0; min-width: 180px; + margin: 0; padding: 0; list-style: none; background: #000; + border: 1px solid var(--accent); border-radius: var(--r); z-index: 50; + text-align: left; box-shadow: 0 0 10px rgba(var(--glow-color), .4); +} +.search-engine-menu[hidden] { display: none; } +.search-engine-menu li { + padding: 8px 12px; color: var(--accent); cursor: pointer; + font-family: inherit; font-size: 0.9rem; display: flex; align-items: center; gap: 10px; +} +.search-engine-menu li:hover, +.search-engine-menu li[aria-selected="true"] { background: var(--accent); color: #000; } +.search-engine-menu .engine-icon { font-weight: bold; min-width: 1.6em; } + +/* (#11) YouTube facade — fills the 16:9 .vibe-embed, click to load. */ +.vibe-facade { + position: absolute; inset: 0; width: 100%; height: 100%; + display: flex; flex-direction: column; align-items: center; justify-content: center; + gap: var(--space-sm); cursor: pointer; border: 0; + color: var(--neon-green); font-family: var(--font-mono); text-align: center; + background: + radial-gradient(ellipse at 50% 38%, rgba(var(--link-glow), .1), transparent 58%), + radial-gradient(ellipse at 50% 100%, rgba(255, 45, 149, .08), transparent 55%), + linear-gradient(180deg, #0c0000 0%, #020000 100%); + transition: filter .2s ease, box-shadow .25s ease; + box-shadow: inset 0 0 0 1px rgba(var(--link-glow), .18); +} +.vibe-facade::before { + content: '▌ VIDEO // STANDBY'; + position: absolute; + top: var(--space-sm); + left: var(--space-md); + font-size: 0.68rem; + letter-spacing: 0.12em; + color: var(--accent-cyan); + opacity: 0.75; + text-shadow: 0 0 8px rgba(var(--link-glow), .35); +} +.vibe-facade:hover, .vibe-facade:focus-visible { + filter: brightness(1.12); + outline: none; + box-shadow: + inset 0 0 0 1px rgba(var(--link-glow), .45), + 0 0 20px rgba(var(--link-glow), .22); +} +.vibe-facade-play { + font-size: 1.65rem; line-height: 1; color: var(--accent-cyan); + width: 68px; height: 68px; display: flex; align-items: center; justify-content: center; + border-radius: 50%; + border: 2px solid var(--accent-cyan); + background: rgba(0, 0, 0, .72); + box-shadow: + 0 0 16px rgba(var(--link-glow), .45), + 0 0 32px rgba(255, 45, 149, .18), + inset 0 0 14px rgba(var(--link-glow), .12); + transition: transform .2s ease, box-shadow .25s ease; +} +.vibe-facade:hover .vibe-facade-play, +.vibe-facade:focus-visible .vibe-facade-play { + transform: scale(1.06); + box-shadow: + 0 0 22px rgba(var(--link-glow), .55), + 0 0 40px rgba(224, 64, 251, .28), + inset 0 0 18px rgba(var(--link-glow), .18); +} +.vibe-facade-text { + font-weight: 700; + color: #ffd0d0; + text-shadow: 0 0 10px rgba(var(--link-glow), .25); +} +.vibe-facade-text small { + display: block; + font-weight: 400; + color: var(--muted); + font-size: .78em; + margin-top: 4px; +} +/* Pause overlay: same menu, dimmed so the paused frame shows behind it. */ +.vibe-facade-paused { + z-index: 2; + background: + radial-gradient(circle at 50% 45%, rgba(255,0,0,.18), transparent 60%), + rgba(0,0,0,.55); +} +.vibe-facade-paused[hidden] { display: none; } +/* Compact pause overlay for the (short) native audio control bar. */ +.vibe-audio-wrap { position: relative; } +.vibe-facade-compact { + flex-direction: row; + gap: var(--space-xs); + border-radius: 6px; +} +.vibe-facade-compact .vibe-facade-play { + width: 34px; height: 34px; font-size: 1.2rem; +} +.vibe-facade-compact .vibe-facade-text { font-size: .9em; } +.vibe-facade-compact .vibe-facade-text small { display: none; } + +/* Curated link panel (xahlee.info .lpanelxl style), shown on non-home pages. + Docks fixed on the RIGHT (≥1101px) so startpage/search chrome on the left + stay clear. --lpanel-w / --lpanel-inset live on body for startpage overrides. */ +body:has(.lpanelxl) { + --lpanel-w: 13.75rem; /* ~220px */ + --lpanel-inset: calc(var(--lpanel-w) + (2 * var(--space-lg))); +} +.lpanelxl { + margin: var(--space-2xl) 0 0; + padding: var(--space-md); + max-width: 22rem; + border: 1px solid var(--border); + border-radius: 6px; + background: linear-gradient(180deg, rgba(var(--glow-color), .10), var(--bg)); + font-size: var(--fs-sm); + box-sizing: border-box; +} +.lpanelxl h3 { + margin: 0 0 var(--space-sm); + padding-bottom: var(--space-xs); + font-size: var(--fs-sm); + font-family: var(--font-mono); + text-transform: uppercase; + letter-spacing: 0.08em; + font-weight: 700; + color: var(--gold, var(--accent)); + border-bottom: 1px solid var(--border); +} +.lpanelxl ul { list-style: none; margin: 0; padding: 0; } +.lpanelxl li + li { border-top: 1px dotted var(--border); } +.lpanelxl a { + display: block; + padding: 0.4rem 0.35rem; + color: var(--accent); + text-decoration: none; + line-height: 1.35; + font-family: var(--font-mono); +} +.lpanelxl a:hover, .lpanelxl a:focus-visible { + background: rgba(160, 0, 0, .15); + text-decoration: underline; + outline: none; +} +.emojixl { font-size: 1.15em; font-style: normal; } + +/* Light-mode polish to match blog.sillylaird.ca's Explore box. */ +body.light-mode .lpanelxl { + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .18), transparent 72%), + var(--surface); + border-color: var(--border); + box-shadow: 0 8px 26px rgba(139, 0, 0, .12); +} +body.light-mode .lpanelxl h3 { + color: var(--gold); + border-bottom-color: var(--border); +} +body.light-mode .lpanelxl li + li { border-top-color: var(--border); } +body.light-mode .lpanelxl a { color: var(--accent); } +body.light-mode .lpanelxl a:hover { background: var(--accent); color: #ffffff; } + +/* Dock Explore as a fixed RIGHT sidebar (≥1101px). Below that, in-flow above footer. */ +@media (min-width: 1101px) { + .lpanelxl { + position: fixed; + top: calc(var(--site-header-height, 76px) + var(--space-md)); + right: var(--space-lg); + left: auto; + width: var(--lpanel-w); + max-width: none; + margin: 0; + max-height: calc(100vh - var(--site-header-height, 76px) - (2 * var(--space-md))); + overflow-y: auto; + overflow-x: hidden; + scrollbar-width: thin; + z-index: 50; + } + + /* Collapse the empty in-flow wrapper that only holds the fixed panel. */ + body:has(.lpanelxl) .wrap:has(> .lpanelxl:only-child) { + margin: 0; + padding: 0; + max-width: none; + height: 0; + overflow: visible; + } + + /* Keep main content left-aligned; reserve space on the right for the rail. + Homepage has no .lpanelxl (uses .home-sidebar instead). */ + body:has(.lpanelxl) main#main, + body:has(.lpanelxl) main.wrap { + margin-left: 0; + margin-right: var(--lpanel-inset); + max-width: calc(100% - var(--lpanel-inset)); + box-sizing: border-box; + } + body:has(.lpanelxl) footer.site-footer { + margin-left: 0; + margin-right: var(--lpanel-inset); + } + body:has(.lpanelxl) footer.site-footer .footer-inner { + margin-left: auto; + margin-right: 0; + } + body:has(.lpanelxl) header.site-header { + margin-left: 0; + margin-right: var(--lpanel-inset); + } + body:has(.lpanelxl) header.site-header .header-inner, + body:has(.lpanelxl) .header-search-inner { + margin-left: auto; + margin-right: 0; + } +} + +/* Mid laptops: slightly tighter rail so content still breathes. */ +@media (min-width: 1101px) and (max-width: 1280px) { + body:has(.lpanelxl) { --lpanel-w: 12.5rem; } +} + +/* (#12) Footer personality. */ +.footer-quote { + margin: var(--space-sm) 0 0; padding: var(--space-xs) var(--space-md); + border-left: 2px solid var(--accent); font-style: italic; opacity: .9; + min-height: 1.5em; +} +.footer-joke { margin-top: var(--space-xs); font-size: var(--fs-sm); opacity: .7; } +.footer-back-to-top { + margin: 0 0 var(--space-sm); + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.08em; +} +.footer-back-to-top a { + color: var(--muted); +} +.footer-back-to-top a:hover, +.footer-back-to-top a:focus-visible { + color: var(--accent-cyan); +} + +/* Floating control: full rules live in scroll-to-top.css (loaded by the + network-wide script). These overrides exist so site.css's global `a:hover` + glow/scale cannot leak onto the button while that file is in flight. */ +a.scroll-to-top:hover, +a.scroll-to-top:focus-visible { + background: var(--bg); + color: var(--accent-cyan); + text-decoration: none; + transform: none; + border-radius: var(--r); +} +.footer-badges { + display: flex; flex-wrap: wrap; gap: var(--space-sm); + align-items: center; margin-top: var(--space-sm); +} +.own-button img { + image-rendering: pixelated; border: 1px solid var(--border); + transition: transform .15s ease, box-shadow .15s ease; +} +.own-button:hover img { + transform: translateY(-2px); + box-shadow: 0 4px 12px -4px rgba(var(--glow-color), .7); +} + +/* Homepage Blog + Changelog — two columns side by side (stacks on narrow screens). */ +.updates-groups { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: var(--space-lg) var(--space-xl); + margin-top: var(--space-sm); +} + +.updates-group > h3.network-subtitle { margin-top: 0; } + +/* 2026-06: Last.fm "Music" nested inside the Current Vibe card. */ +.vibe-music { + margin-top: var(--space-lg); + padding-top: var(--space-md); + border-top: 1px solid var(--border); +} +.vibe-music > h3.network-subtitle { margin-top: 0; } + +/* 2026-06: structural homepage pass. */ +nav.site-nav[hidden], +.lang-menu[hidden] { + display: none !important; +} + +.header-controls { + gap: var(--space-sm); +} + +.header-icon-button { + width: 36px; + min-width: 36px; + height: 36px; + padding: 0; + font-size: 1.05rem; + line-height: 1; + transition: + background .2s ease, + color .2s ease, + border-color .2s ease, + box-shadow .25s ease, + transform .2s ease; +} + +.header-icon-button:hover, +.header-icon-button:focus-visible { + transform: scale(1.06); +} + +.protocol-pills { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 5px; +} + +.protocol-pill { + --protocol-accent: var(--accent); + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 5px 10px; + border: 1px solid var(--protocol-accent); + border-radius: 999px; + background: rgba(var(--glow-color), .06); + color: var(--protocol-accent); + font-family: var(--font-mono); + font-size: 0.88rem; + font-weight: 700; + line-height: 1.15; + letter-spacing: 0.02em; + box-shadow: inset 0 0 10px rgba(var(--glow-color), .08); + transition: + background .2s ease, + color .2s ease, + border-color .2s ease, + box-shadow .25s ease, + transform .15s ease; +} + +.protocol-pill:hover, +.protocol-pill:focus-visible { + background: var(--protocol-accent); + color: #050000; + text-shadow: none; + transform: translateY(-1px); + box-shadow: + 0 0 0 1px var(--protocol-accent), + 0 0 16px color-mix(in srgb, var(--protocol-accent) 65%, transparent); +} + +.protocol-pill--gemini { --protocol-accent: #2fd7b5; } +.protocol-pill--gopher { --protocol-accent: #d8a735; } +.protocol-pill--tor { --protocol-accent: #a579d6; } +.protocol-pill--i2p { --protocol-accent: #ff7b2c; } + +.protocol-pill--gemini::before { content: '◇ '; opacity: .85; } +.protocol-pill--gopher::before { content: '🕳 '; font-size: .9em; } +.protocol-pill--tor::before { content: '◈ '; opacity: .85; } +.protocol-pill--i2p::before { content: '◎ '; opacity: .85; } + +.home-wrap { + max-width: min(1180px, calc(100vw - 2rem)); + padding-bottom: var(--space-lg); +} + +/* Homepage footer: align the footer-inner with the main content column + (offset past the left sidebar) so it starts/ends where the page content does. + Below 1100px the home-layout stacks, so footer already lines up. */ +@media (min-width: 1101px) { + body:has(.home-wrap) footer.site-footer .footer-inner, + body:has(.home-wrap) header.site-header .header-inner, + body:has(.home-wrap) .header-search-inner { + max-width: min(1180px, calc(100vw - 2rem)); + padding-left: calc(220px + var(--space-lg) + var(--space-xl)); + padding-right: var(--space-lg); + } +} + +.home-layout { + display: grid; + grid-template-columns: minmax(180px, 220px) minmax(0, 1fr); + gap: var(--space-xl); + align-items: start; +} + +.home-content { + min-width: 0; +} + +.home-content section, +.home-content [id] { + scroll-margin-top: calc(var(--site-header-height, 76px) + var(--space-lg)); +} + +.home-sidebar { + position: sticky; + top: calc(var(--site-header-height, 76px) + var(--space-lg)); + max-height: calc(100vh - var(--site-header-height, 76px) - (2 * var(--space-lg))); + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: color-mix(in srgb, var(--border) 80%, transparent) transparent; + opacity: 1; + font-size: var(--fs-sm); + color: var(--ink); + display: flex; + flex-direction: column; + gap: var(--space-md); +} + +.home-sidebar::-webkit-scrollbar { + width: 6px; +} + +.home-sidebar::-webkit-scrollbar-thumb { + background: color-mix(in srgb, var(--border) 85%, transparent); + border-radius: 3px; +} + +.home-side-nav { + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md) var(--space-md) var(--space-sm); + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .07), transparent 72%), + color-mix(in srgb, var(--bg) 88%, #1a0000); + box-shadow: var(--glow-soft); +} + +.home-side-nav h2 { + margin: 0 0 var(--space-sm); + padding-bottom: var(--space-xs); + border-bottom: 1px solid color-mix(in srgb, var(--border) 80%, transparent); + font-family: var(--font-mono); + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.08em; + font-weight: 700; + color: var(--gold); + opacity: 1; +} + +.home-side-nav a { + display: block; + padding: 0.45rem 0.4rem; + margin: 0 -0.25rem; + border-radius: calc(var(--r) - 2px); + border-top: 0; + color: var(--ink); + font-size: var(--fs-sm); + font-family: var(--font-mono); + line-height: 1.35; + text-decoration: none; + transition: background 0.12s ease, color 0.12s ease; +} + +.home-side-nav a + a { + border-top: 1px solid color-mix(in srgb, var(--border) 45%, transparent); +} + +.home-side-nav a:hover, +.home-side-nav a:focus-visible { + background: color-mix(in srgb, var(--accent) 18%, transparent); + color: var(--accent-bright, var(--accent)); + outline: none; +} + +.home-side-nav a:first-of-type { + border-top: 0; +} + +.home-sidebar-widget, +.home-vibe-widget, +.home-changelog-widget { + margin-top: 0; + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md); + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .1), transparent 72%), + #080000; + box-shadow: var(--glow-soft); + font-size: var(--fs-sm); +} + +.home-sidebar-widget h3, +.home-vibe-widget h3, +.home-changelog-widget h3 { + margin: 0 0 var(--space-sm); + padding-bottom: var(--space-xs); + border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent); + font-family: var(--font-mono); + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.06em; + font-weight: 700; + color: var(--gold); +} + +.home-sidebar-widget p, +.home-vibe-widget p, +.home-changelog-widget p { + margin: 0 0 var(--space-sm); + color: color-mix(in srgb, var(--ink) 88%, var(--muted)); + font-family: var(--font-prose, inherit); + font-size: var(--fs-sm); + line-height: 1.55; + max-height: none; + overflow: visible; +} + +.home-sidebar-widget a, +.home-vibe-widget a, +.home-changelog-widget a { + display: inline-block; + font-weight: 700; + color: var(--accent-bright, var(--accent)); + line-height: 1.4; +} + +.home-sidebar-widget a:hover, +.home-vibe-widget a:hover, +.home-changelog-widget a:hover { + text-decoration: underline; +} + +.home-sidebar-widget time, +.home-vibe-widget time, +.home-changelog-widget time { + display: block; + margin-top: var(--space-sm); + font-family: var(--font-mono); + font-size: var(--fs-xs); + color: var(--muted); + opacity: 1; + letter-spacing: 0.02em; +} + +.start-card-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: var(--space-sm); +} + +.start-card { + min-height: 132px; + display: grid; + grid-template-rows: auto auto 1fr; + gap: 3px; + align-content: start; + padding: var(--space-md); + border: 1px solid var(--border); + border-radius: var(--r); + background: + linear-gradient(180deg, rgba(var(--glow-color), .05), transparent 70%), + #050000; + color: var(--accent); + transition: transform .2s ease, border-color .2s ease, box-shadow .25s ease; + box-shadow: var(--glow-soft); +} + +.start-card:hover, +.start-card:focus-visible { + transform: translateY(-2px) scale(1.03); + background: #070000; + color: #e0e0e0; + border-color: var(--card-accent, var(--accent)); + text-shadow: none; + box-shadow: + inset 0 0 24px color-mix(in srgb, var(--card-accent, var(--accent)) 18%, transparent), + 0 0 0 1px color-mix(in srgb, var(--card-accent, var(--accent)) 50%, transparent), + 0 0 16px color-mix(in srgb, var(--card-accent, var(--accent)) 40%, transparent), + 0 8px 28px -8px rgba(0, 0, 0, .65); +} + +.start-card--now { --card-accent: var(--neon-cyan); } +.start-card--blog { --card-accent: var(--accent-bright); } +.start-card--journal { --card-accent: var(--neon-green); } +.start-card--gaming { --card-accent: #c77dff; } +.start-card--projects { --card-accent: var(--accent-pink); } + +.start-card--now, +.start-card--blog, +.start-card--journal, +.start-card--gaming, +.start-card--projects { + border-color: color-mix(in srgb, var(--card-accent) 35%, var(--border)); +} + +.start-card--now:hover, +.start-card--blog:hover, +.start-card--journal:hover, +.start-card--gaming:hover, +.start-card--projects:hover { + border-color: var(--card-accent); + box-shadow: + 0 0 0 1px color-mix(in srgb, var(--card-accent) 55%, transparent), + 0 0 12px color-mix(in srgb, var(--card-accent) 45%, transparent), + 0 0 28px color-mix(in srgb, var(--card-accent) 25%, transparent); +} + +.start-card-icon { + font-family: var(--font-mono); + font-size: 1.35rem; + line-height: 1; + color: var(--card-accent, var(--gold)); + text-shadow: 0 0 8px color-mix(in srgb, var(--card-accent, var(--gold)) 50%, transparent); +} + +.start-card strong { + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.4px; +} + +.start-card span:last-child { + font-size: var(--fs-sm); + color: var(--muted); + line-height: 1.35; +} + +.contact-darkweb { + margin-top: var(--space-sm); + border-top: 1px dotted var(--border); + padding-top: var(--space-sm); +} + +.contact-darkweb summary { + cursor: pointer; + color: var(--accent); + font-family: var(--font-mono); + font-size: var(--fs-sm); +} + +.contact-list--compact { + margin-top: var(--space-xs); +} + +.contact-list--compact li { + font-size: var(--fs-sm); +} + +.country-links .country-card { + flex-direction: column; + gap: var(--space-xs); + font-weight: 700; +} + +.country-links .country-emoji { + display: block; + height: 2.25rem; + width: auto; + border-radius: 3px; + /* Keep light flags (Japan) visible on light surfaces */ + box-shadow: 0 0 0 1px color-mix(in srgb, currentColor 25%, transparent); +} + +.network-section .network-subsection { + border-top-style: solid; +} + +body.light-mode .protocol-pill { + background: #ffffff; +} + +body.light-mode .protocol-pill:hover, +body.light-mode .protocol-pill:focus-visible { + color: #ffffff; +} + +body.light-mode .home-side-nav, +body.light-mode .home-sidebar-widget, +body.light-mode .home-vibe-widget, +body.light-mode .home-changelog-widget, +body.light-mode .home-protocol-nav, +body.light-mode .start-card { + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .16), transparent 72%), + var(--surface); +} + +body.light-mode .home-side-nav a { + color: var(--ink); +} + +body.light-mode .home-side-nav a:hover, +body.light-mode .home-side-nav a:focus-visible { + background: color-mix(in srgb, var(--accent) 12%, transparent); + color: var(--accent); +} + +body.light-mode .home-sidebar-widget p, +body.light-mode .home-vibe-widget p, +body.light-mode .home-changelog-widget p { + color: color-mix(in srgb, var(--ink) 92%, var(--muted)); +} + +@media (max-width: 1100px) { + .home-wrap { + max-width: var(--wrap); + } + + .home-layout { + display: block; + } + + .home-sidebar { + position: static; + max-height: none; + overflow: visible; + margin: var(--space-lg) 0; + gap: var(--space-md); + } + + .home-side-nav { + display: flex; + flex-wrap: wrap; + gap: var(--space-xs) var(--space-sm); + align-items: center; + padding: var(--space-md); + } + + .home-side-nav h2 { + margin: 0 var(--space-sm) 0 0; + padding-bottom: 0; + border-bottom: 0; + width: 100%; + } + + .home-side-nav a { + border-top: 0; + padding: 0.35rem 0.55rem; + margin: 0; + border: 1px solid color-mix(in srgb, var(--border) 70%, transparent); + border-radius: var(--r); + background: color-mix(in srgb, var(--bg) 70%, transparent); + } + + .home-side-nav a + a { + border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent); + } +} + +@media (max-width: 900px) { + .protocol-pills { + order: 4; + flex-basis: 100%; + justify-content: flex-end; + } + + .start-card-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 600px) { + .header-icon-button { + width: 34px; + min-width: 34px; + height: 34px; + } + + .protocol-pills { + justify-content: flex-start; + } + + .protocol-pill { + min-height: 32px; + padding-inline: 9px; + font-size: 0.82rem; + } + + .start-card-grid { + grid-template-columns: 1fr; + } + + .start-card { + min-height: 0; + } +} + +/* ========================================================================== + 2026-07: visual polish pass — hero, textures, badges, panels + ========================================================================== */ + +/* Subtle ambient texture (CSS-only, no image budget hit). */ +body::before { + content: ''; + pointer-events: none; + position: fixed; + inset: 0; + z-index: -1; + opacity: 0.55; + background: + radial-gradient(ellipse 120% 80% at 50% -15%, rgba(160, 0, 0, .07), transparent 52%), + radial-gradient(ellipse 85% 65% at 100% 100%, rgba(var(--link-glow), .035), transparent 48%), + radial-gradient(ellipse 75% 55% at 0% 85%, rgba(179, 136, 255, .045), transparent 42%); +} + +body.light-mode::before { + opacity: 0.5; + background: + radial-gradient(ellipse at 15% 0%, rgba(210, 180, 140, .18), transparent 50%), + radial-gradient(ellipse at 85% 100%, rgba(139, 0, 0, .08), transparent 45%), + repeating-linear-gradient( + -4deg, + transparent, + transparent 3px, + rgba(120, 90, 60, .04) 3px, + rgba(120, 90, 60, .04) 4px + ); +} + +/* Section titles with accent underline */ +.section-accent-title { + position: relative; + padding-bottom: var(--space-sm); + margin-bottom: var(--space-md) !important; + font-size: var(--fs-2xl); + font-weight: 800; + letter-spacing: 0.02em; + text-shadow: + 0 0 14px rgba(var(--glow-color), .35), + 0 1px 0 rgba(0, 0, 0, .75); +} + +.section-accent-title::after { + content: ''; + display: block; + width: 0; + height: 3px; + margin-top: var(--space-xs); + border-radius: 2px; + background: linear-gradient(90deg, var(--neon-green), var(--accent-cyan), var(--accent-magenta)); + box-shadow: 0 0 10px color-mix(in srgb, var(--neon-green) 50%, transparent); + transition: width .55s cubic-bezier(.4, 0, .2, 1), box-shadow .35s ease; +} + +.section-accent-title.is-drawn::after { + width: 3.5rem; + animation: neon-underline-pulse 3.5s ease-in-out infinite; +} + +.section-accent-title:hover::after, +.section-accent-title:focus-within::after { + width: 5.5rem; + box-shadow: + 0 0 8px color-mix(in srgb, var(--neon-green) 55%, transparent), + 0 0 18px color-mix(in srgb, var(--accent-cyan) 45%, transparent); +} + +/* Panel heading underlines (sidebar Index / Alt nets / Current vibe / Changelog, + and the .lpanelxl panels) used to be a flat red rule. They now carry the same + green -> red bar as .section-accent-title / .network-subtitle, expanding on + hover. The faint full-width divider stays underneath, matching how + .network-subtitle pairs a dotted border with its bar. */ +.home-side-nav h2, +.home-sidebar-widget h3, +.home-vibe-widget h3, +.home-changelog-widget h3, +.home-protocol-nav h3, +.lpanelxl h3 { + position: relative; +} + +.home-side-nav h2::after, +.home-sidebar-widget h3::after, +.home-vibe-widget h3::after, +.home-changelog-widget h3::after, +.home-protocol-nav h3::after, +.lpanelxl h3::after { + content: ''; + display: block; + width: 2.5rem; + height: 2px; + margin-top: var(--space-xs); + border-radius: 1px; + background: linear-gradient(90deg, var(--neon-green), var(--accent-cyan), var(--accent-magenta)); + box-shadow: 0 0 8px color-mix(in srgb, var(--neon-green) 45%, transparent); + transition: width .5s cubic-bezier(.4, 0, .2, 1), box-shadow .35s ease; +} + +.home-side-nav:hover h2::after, +.home-sidebar-widget:hover h3::after, +.home-vibe-widget:hover h3::after, +.home-changelog-widget:hover h3::after, +.home-protocol-nav:hover h3::after, +.lpanelxl:hover h3::after { + width: 4.5rem; + box-shadow: + 0 0 8px color-mix(in srgb, var(--neon-green) 55%, transparent), + 0 0 18px color-mix(in srgb, var(--accent-cyan) 45%, transparent); +} + +@keyframes neon-underline-pulse { + 0%, 100% { + box-shadow: 0 0 8px color-mix(in srgb, var(--neon-green) 45%, transparent); + } + 50% { + box-shadow: + 0 0 12px color-mix(in srgb, var(--accent-cyan) 55%, transparent), + 0 0 22px color-mix(in srgb, var(--accent-magenta) 25%, transparent); + } +} + +body.light-mode .section-accent-title::after, +body.light-mode .network-subtitle::after { + background: linear-gradient(90deg, var(--accent), #5eb8d9); + box-shadow: none; +} + +body.light-mode .home-side-nav h2::after, +body.light-mode .home-sidebar-widget h3::after, +body.light-mode .home-vibe-widget h3::after, +body.light-mode .home-changelog-widget h3::after, +body.light-mode .home-protocol-nav h3::after, +body.light-mode .lpanelxl h3::after { + background: linear-gradient(90deg, var(--accent), #5eb8d9); + box-shadow: none; +} + +/* Homepage hero */ +.home-hero { + position: relative; + margin-bottom: var(--space-lg); + padding: var(--space-lg) var(--space-xl); + border-radius: var(--r); + border: 1px solid color-mix(in srgb, var(--border) 65%, transparent); + background: var(--surface-deep); + overflow: hidden; +} + +.home-hero::before { + content: ''; + pointer-events: none; + position: absolute; + inset: 0; + border-radius: inherit; + z-index: 0; + opacity: 0.55; + background: + radial-gradient(ellipse 115% 85% at 50% 48%, transparent 38%, rgba(0, 0, 0, .5) 100%), + repeating-radial-gradient(circle at 17% 29%, rgba(255, 255, 255, .018) 0 1px, transparent 1px 3px), + repeating-radial-gradient(circle at 73% 61%, rgba(var(--link-glow), .012) 0 1px, transparent 1px 4px); +} + +.home-hero::after { + content: ''; + pointer-events: none; + position: absolute; + inset: 0; + border-radius: inherit; + background: radial-gradient(ellipse at center, transparent 42%, rgba(0, 0, 0, .62) 100%); + z-index: 0; +} + +.home-hero > * { + position: relative; + z-index: 1; +} + +.home-hero-brand { + display: flex; + align-items: flex-start; + gap: var(--space-lg); + margin-bottom: var(--space-md); +} + +.home-hero-avatar-wrap { + position: relative; + flex-shrink: 0; + line-height: 0; +} + +.home-hero-avatar { + display: block; + width: 72px; + height: 72px; + max-width: 72px; + object-fit: contain; + border: 2px solid color-mix(in srgb, var(--accent-cyan) 35%, var(--border)); + border-radius: var(--r); + background: #070000; + image-rendering: pixelated; + box-shadow: + 0 0 0 1px rgba(var(--glow-color), .35), + 0 0 6px rgba(var(--link-glow), .55), + 0 0 16px rgba(224, 64, 251, .35), + 0 0 32px rgba(var(--glow-color), .45), + 0 0 48px -8px rgba(179, 136, 255, .25), + inset 0 0 14px rgba(var(--link-glow), .12); + filter: drop-shadow(0 0 4px rgba(var(--link-glow), .35)); + animation: avatar-idle-pulse 2.2s ease-in-out infinite; + transition: transform .25s ease, box-shadow .35s ease, border-color .25s ease, filter .25s ease; +} + +@keyframes avatar-idle-pulse { + 0%, 100% { + filter: drop-shadow(0 0 4px rgba(var(--link-glow), .32)) brightness(1); + } + 50% { + filter: drop-shadow(0 0 9px rgba(224, 64, 251, .42)) brightness(1.06) hue-rotate(8deg); + } +} + +.home-hero-brand:hover .home-hero-avatar, +.home-hero-avatar-wrap:hover .home-hero-avatar { + transform: translateY(-2px) rotate(-2deg) scale(1.04); + border-color: var(--accent-cyan); + filter: drop-shadow(0 0 8px rgba(var(--link-glow), .6)); + animation: avatar-glitch .45s steps(2) 1; + box-shadow: + 0 0 0 1px rgba(var(--link-glow), .65), + 0 0 10px rgba(var(--link-glow), .75), + 0 0 22px rgba(224, 64, 251, .5), + 0 0 40px rgba(var(--glow-color), .55), + 0 0 60px -6px rgba(179, 136, 255, .4), + inset 0 0 20px rgba(var(--link-glow), .18); +} + +.home-hero-text { + min-width: 0; + flex: 1; +} + +.home-hero h1 { + padding-left: 0; + margin-bottom: var(--space-xs); + font-weight: 800; + text-shadow: + 0 0 12px rgba(var(--glow-color), .45), + 0 0 28px rgba(179, 136, 255, .2), + 0 1px 0 rgba(0, 0, 0, .8); + transition: text-shadow .25s ease; +} + +.home-hero h1:hover { + animation: title-glitch .4s steps(2) 1; + text-shadow: + 0 0 14px rgba(var(--link-glow), .5), + 0 0 24px rgba(224, 64, 251, .35), + 2px 0 0 rgba(255, 45, 149, .5), + -2px 0 0 rgba(var(--link-glow), .5); +} + +.home-tagline { + margin: 0; + font-family: var(--font-mono); + font-size: var(--fs-base); + font-weight: 600; + color: var(--neon-green); + letter-spacing: 0.04em; + min-height: 1.6em; + text-shadow: 0 0 10px rgba(57, 255, 20, .28); +} + +.home-tagline-text { + display: inline; + animation: tagline-glitch-in .85s ease-out both; + animation-delay: .25s; +} + +.home-tagline-text::after { + content: '█'; + margin-left: 3px; + font-size: .92em; + animation: tagline-cursor 1s step-end infinite; + color: var(--accent-cyan); + text-shadow: 0 0 8px rgba(var(--link-glow), .65); +} + +@keyframes tagline-cursor { + 0%, 49% { opacity: 1; } + 50%, 100% { opacity: 0; } +} + +@keyframes tagline-glitch-in { + 0% { + opacity: 0; + transform: translateX(-6px); + filter: hue-rotate(60deg) saturate(1.4); + } + 25% { + opacity: .85; + transform: translateX(3px); + } + 45% { + transform: translateX(-2px); + filter: none; + } + 100% { + opacity: 1; + transform: none; + } +} + +@keyframes avatar-glitch { + 0%, 100% { clip-path: inset(0 0 0 0); } + 33% { clip-path: inset(12% 0 58% 0); filter: hue-rotate(25deg) drop-shadow(0 0 8px rgba(var(--link-glow), .6)); } + 66% { clip-path: inset(48% 0 8% 0); filter: hue-rotate(-15deg) drop-shadow(0 0 8px rgba(var(--link-glow), .6)); } +} + +@keyframes title-glitch { + 0%, 100% { transform: none; } + 25% { transform: translate(-2px, 1px); } + 50% { transform: translate(2px, -1px); } + 75% { transform: translate(-1px, 0); } +} + +body.light-mode .home-tagline { + color: var(--accent); +} + +body.light-mode .home-tagline-text::after { + color: #8b0000; +} + +.home-welcome { + max-width: 62ch; +} + +.home-content > section > p, +.home-content .muted { + max-width: 65ch; +} + +.home-content > section + section { + margin-top: var(--space-2xl); +} + +/* Start cards — larger icons in badge circles */ +.start-card-grid { + gap: var(--space-md); +} + +.start-card { + min-height: 148px; + padding: var(--space-lg); + gap: var(--space-xs); +} + +.start-card-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + font-size: 1.35rem; + border-radius: 50%; + background: color-mix(in srgb, var(--card-accent, var(--gold)) 12%, transparent); + border: 1px solid color-mix(in srgb, var(--card-accent, var(--gold)) 35%, var(--border)); + text-shadow: none; + transition: transform .2s ease, box-shadow .25s ease; +} + +.start-card:hover .start-card-icon, +.start-card:focus-visible .start-card-icon { + transform: scale(1.08); + box-shadow: 0 0 14px color-mix(in srgb, var(--card-accent, var(--gold)) 45%, transparent); +} + +.start-card strong { + font-size: var(--fs-base); +} + +/* Updates panels — card + timeline feel */ +.updates-panel { + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md) var(--space-lg); + background: + linear-gradient(180deg, rgba(var(--glow-color), .05), transparent 65%), + #050000; + box-shadow: var(--glow-soft); + transition: border-color .25s ease, box-shadow .25s ease; +} + +.updates-panel:hover { + border-color: rgba(var(--glow-color), .35); +} + +.updates-panel--changelog .recent-list li { + border-left-color: var(--neon-cyan); +} + +body.light-mode .updates-panel { + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .14), transparent 72%), + var(--surface); +} + +.home-content .recent-list li { + margin: var(--space-md) 0; + padding: var(--space-sm) var(--space-md); + padding-left: var(--space-md); + border-left: 3px solid var(--accent); + border-radius: 0 var(--r) var(--r) 0; + background: rgba(var(--glow-color), .04); + transition: transform .15s ease, background .15s ease, border-color .15s ease; +} + +.home-content .recent-list li:hover { + transform: translateX(4px); + background: rgba(var(--glow-color), .08); + border-left-color: var(--neon-green); +} + +/* Guestbook card panels */ +.guestbook-panels { + gap: var(--space-lg); +} + +.guestbook-panel { + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md); + background: + linear-gradient(180deg, rgba(var(--glow-color), .04), transparent 70%), + #050000; + box-shadow: var(--glow-soft); +} + +.guestbook-panel-head { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: var(--space-sm); + margin-bottom: var(--space-sm); + padding-bottom: var(--space-sm); + border-bottom: 1px dashed var(--border); +} + +.guestbook-panel-title { + margin: 0; + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.6px; + color: var(--gold); +} + +body.light-mode .guestbook-panel, +body.light-mode .updates-panel { + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .12), transparent 72%), + var(--surface); +} + +/* Unified link-badge styling for friends + countries */ +.friends-list a, +.country-links .country-card, +.tile-grid a { + border-radius: var(--r); + transition: + background .2s ease, + color .2s ease, + border-color .2s ease, + box-shadow .25s ease, + transform .2s ease; +} + +.friends-list a:hover, +.friends-list a:focus-visible, +.country-links .country-card:hover, +.country-links .country-card:focus-visible { + transform: translateY(-2px); + box-shadow: + 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent), + 0 4px 14px -4px rgba(var(--glow-color), .55); +} + +.country-links .country-card { + min-height: 96px; + background: + linear-gradient(180deg, rgba(var(--glow-color), .06), transparent 70%), + var(--bg); +} + +body.light-mode .country-links .country-card { + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .14), transparent 72%), + var(--surface); +} + +/* Network grids — uniform scan-friendly layout */ +.network-section .tile-grid { + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: var(--space-md); +} + +.network-section .tile-grid--three { + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); +} + +.network-subtitle { + font-size: var(--fs-lg); + padding-bottom: var(--space-xs); + border-bottom: 1px dotted var(--border); + position: relative; +} + +.network-subtitle::after { + content: ''; + display: block; + width: 0; + height: 2px; + margin-top: var(--space-xs); + border-radius: 1px; + /* Same green -> red sweep as .section-accent-title, so every expanding bar on + the page reads as one family. The lead stop is always --neon-green: the + per-subsection --section-neon values for friends (--accent-cyan #8b0000), + countries (--accent-purple #5a0000) and buttons (--accent-pink #a00000) are + all dark reds, so leading with them left those three bars red-only. */ + background: linear-gradient(90deg, var(--neon-green), var(--accent-cyan), var(--accent-magenta)); + box-shadow: 0 0 8px color-mix(in srgb, var(--neon-green) 45%, transparent); + transition: width .5s cubic-bezier(.4, 0, .2, 1), box-shadow .35s ease; +} + +.network-subtitle.is-drawn::after { + width: 4.5rem; +} + +.network-subtitle:hover::after, +.network-subtitle:focus-within::after { + width: 6.5rem; + box-shadow: + 0 0 8px color-mix(in srgb, var(--neon-green) 55%, transparent), + 0 0 18px color-mix(in srgb, var(--accent-cyan) 45%, transparent); +} + +/* Footer small-web badge */ +.footer-smallweb { + margin: var(--space-sm) 0 0; + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.04em; + color: var(--muted); + opacity: 0.85; +} + +.footer-smallweb::before { + content: '◈ '; + color: var(--neon-cyan); +} + +body.light-mode .footer-smallweb::before { + color: var(--accent); +} + +/* Light mode: stronger link contrast on protocol pills */ +body.light-mode .protocol-pill { + background: var(--surface); + color: color-mix(in srgb, var(--protocol-accent) 85%, #2a1212); + border-color: color-mix(in srgb, var(--protocol-accent) 55%, var(--border)); +} + +@media (prefers-reduced-motion: reduce) { + .home-tagline-text::after { + animation: none; + } + + .home-hero-brand:hover .home-hero-avatar, + .home-hero-avatar-wrap:hover .home-hero-avatar, + .start-card:hover .start-card-icon, + .protocol-pill:hover, + .header-icon-button:hover { + transform: none; + animation: none; + } +} + +@media (max-width: 600px) { + .home-hero { + padding: var(--space-md) var(--space-lg); + } + + .home-hero-brand { + flex-direction: column; + align-items: center; + text-align: center; + } + + .home-hero-avatar { + width: min(64px, 20vw); + height: min(64px, 20vw); + max-width: 64px; + object-fit: contain; + } + + .home-hero h1 { + font-size: var(--fs-xl); + } + + .home-tagline-text { + white-space: normal; + } +} + +/* ========================================================================== + 2026-07 polish pass — comfort spacing, retro loaders, terminal cursor + ========================================================================== */ + +/* Comfortable line spacing toggle (site-wide + startpage) */ +.header-icon-button.comfort-toggle { + width: 36px; + min-width: 36px; + height: 36px; + padding: 0; + font-size: 1rem; + line-height: 1; +} + +.comfort-toggle { + padding: 5px 10px; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--surface-deep, #050505); + color: var(--accent); + font-family: var(--font-mono); + font-size: 0.78rem; + font-weight: 600; + line-height: 1.2; + cursor: pointer; + transition: + background .2s ease, + color .2s ease, + border-color .2s ease, + box-shadow .25s ease, + transform .15s ease; +} + +.comfort-toggle:hover, +.comfort-toggle:focus-visible { + background: var(--accent); + color: #ffd0d0; + outline: none; + transform: scale(1.04); + box-shadow: 0 0 12px rgba(var(--link-glow), .35); +} + +.comfort-toggle[aria-pressed="true"] { + border-color: var(--neon-green); + color: var(--neon-green); + box-shadow: 0 0 12px rgba(57, 255, 20, .28); +} + +body.comfort-spacing, +body.startpage-comfort { + line-height: var(--lh-comfort); +} + +body.comfort-spacing p, +body.comfort-spacing .home-content section > p, +body.comfort-spacing .home-welcome, +body.comfort-spacing .card-body, +body.startpage-comfort .card-body { + line-height: var(--lh-comfort); +} + +body.comfort-spacing .friends-list, +body.comfort-spacing .card-links, +body.startpage-comfort .card-links { + gap: calc(var(--space-lg) + 4px); +} + +body.comfort-spacing .friends-list a, +body.comfort-spacing .card-links a, +body.startpage-comfort .card-links a { + line-height: 1.7; + padding-block: 6px; +} + +body.light-mode .comfort-toggle { + background: var(--surface); + color: var(--accent); + border-color: var(--border); +} + +body.light-mode .comfort-toggle:hover { + background: var(--accent); + color: #fff; +} + +body.light-mode .comfort-toggle[aria-pressed="true"] { + color: #1a6b8f; + border-color: var(--accent); +} + +/* Retro terminal loading indicator */ +.retro-loading { + font-family: var(--font-mono); + font-size: var(--fs-sm); + color: var(--neon-green); + text-shadow: 0 0 6px rgba(57, 255, 20, .4); +} + +.retro-loading::after { + content: '_'; + margin-left: 2px; + color: var(--accent-cyan); + animation: retro-cursor-blink 1s step-end infinite; +} + +/* Button / pill hover — magenta glow (distinct from link cyan) */ +button:hover, +button:focus-visible, +.header-button:hover, +.header-button:focus-visible, +.reset-button:hover, +.reset-button:focus-visible, +.button-primary:hover, +.button-primary:focus-visible, +.mini-button:hover, +.mini-button:focus-visible, +.protocol-pill:hover, +.protocol-pill:focus-visible { + box-shadow: + 0 0 0 1px rgba(var(--btn-glow), .5), + 0 0 14px rgba(var(--btn-glow), .45), + 0 0 28px -6px rgba(var(--btn-glow), .3); +} + +.protocol-pill:hover, +.protocol-pill:focus-visible { + transform: translateY(-2px) scale(1.04); +} + +/* Dark mode: deeper terminal atmosphere */ +body:not(.light-mode)::before { + opacity: 0.45; + background: + repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.09) 0, + rgba(0, 0, 0, 0.09) 1px, + transparent 1px, + transparent 3px + ); +} + +/* Network section: even grid columns, more breathing room */ +.network-section .tile-grid { + grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); + gap: var(--space-lg); +} + +.network-section .tile-grid--three { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +@media (max-width: 720px) { + .network-section .tile-grid--three { + grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); + } +} + +/* Vibe / YouTube embed loading overlay */ +.vibe-embed { + position: relative; +} + +.vibe-embed.is-loading::before { + content: "loading..."; + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba(2, 2, 2, 0.92); + color: var(--neon-green); + font-family: var(--font-mono); + font-size: var(--fs-sm); + text-shadow: 0 0 8px rgba(57, 255, 20, .45); + z-index: 2; +} + +.vibe-embed.is-loading::after { + content: "_"; + position: absolute; + top: 50%; + left: calc(50% + 2.8em); + transform: translateY(-50%); + color: var(--accent-cyan); + font-family: var(--font-mono); + font-weight: 700; + animation: retro-cursor-blink 1s step-end infinite; + z-index: 3; +} + +body.light-mode .vibe-embed.is-loading::before { + background: rgba(255, 248, 241, 0.94); + color: var(--accent); + text-shadow: none; +} + +/* Terminal block cursor on fine-pointer devices */ +@media (hover: hover) and (pointer: fine) { + a, + button, + summary, + .start-card, + .protocol-pill, + .comfort-toggle, + .header-button, + .reset-button, + .ctx-item, + .search-engine-menu li, + label[for], + input[type="checkbox"], + input[type="radio"], + select { + cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='20' viewBox='0 0 16 20'%3E%3Crect x='6' y='0' width='4' height='14' fill='%23ff1a1a'/%3E%3Crect x='4' y='14' width='8' height='4' fill='%238b0000'/%3E%3C/svg%3E") 8 10, pointer; + } +} + +/* Light mode: soft paper grain (no scanlines). */ +body.light-mode::after { + content: ''; + pointer-events: none; + position: fixed; + inset: 0; + z-index: -2; + opacity: 0.35; + background: + radial-gradient(ellipse at 20% 10%, rgba(210, 180, 140, .12), transparent 55%), + radial-gradient(ellipse at 80% 90%, rgba(139, 0, 0, .06), transparent 50%); + animation: none; +} + +/* Start cards: persistent inner edge glow */ +.start-card { + box-shadow: + var(--glow-soft), + inset 0 0 0 1px rgba(var(--glow-color), .08); +} + +.start-card strong { + text-shadow: 0 0 8px rgba(var(--glow-color), .2); +} + +body.light-mode .home-hero { + background: + radial-gradient(ellipse at 20% 0%, rgba(139, 0, 0, .12), transparent 55%), + radial-gradient(ellipse at 80% 100%, rgba(210, 180, 140, .1), transparent 50%), + var(--surface); + border-color: var(--border); +} + +body.light-mode .home-hero::after { + background: radial-gradient(ellipse at center, transparent 50%, rgba(92, 72, 52, .08) 100%); +} + +body.light-mode .home-hero h1 { + text-shadow: 0 1px 0 rgba(255, 255, 255, .8); +} + +body.light-mode .section-accent-title { + text-shadow: none; +} + +/* ========================================================================== + 2026-07 content & UX pass — widgets, search, tiles, easter egg + ========================================================================== */ + +.header-button--startpage { + font-weight: 700; + border-color: color-mix(in srgb, var(--accent-cyan) 45%, var(--border)); + color: var(--accent-cyan); +} + +.header-button--startpage:hover, +.header-button--startpage:focus-visible { + background: color-mix(in srgb, var(--accent-cyan) 18%, var(--accent)); + color: #ffd0d0; +} + +.nav-link--featured { + font-weight: 700; + color: var(--accent-cyan) !important; +} + +.site-search-hits { + list-style: none; + margin: var(--space-xs) 0 0; + padding: 0; + width: 100%; + max-width: none; + border: 1px solid var(--border); + border-radius: var(--r); + background: var(--surface-deep, #050505); + box-shadow: var(--glow-soft); + overflow: hidden; +} + +.site-search-hits li a { + display: block; + padding: 8px 12px; + border-top: 1px dotted var(--border); +} + +.site-search-hits li:first-child a { + border-top: 0; +} + +.media-widgets { + display: grid; + gap: var(--space-md); + margin-bottom: var(--space-md); +} + +@media (min-width: 640px) { + .media-widgets { + grid-template-columns: 1fr 1fr; + } +} + +.lastfm-now-widget, +.radio-now-widget { + border: 1px solid var(--border); + border-radius: var(--r); + padding: var(--space-md); + background: linear-gradient(180deg, rgba(var(--glow-color), .05), transparent 70%), var(--surface-deep, #050505); + min-height: 5.5rem; +} + +.lastfm-track--featured { + margin: 0; +} + +.media-subheading { + margin: var(--space-md) 0 var(--space-xs); + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--gold); +} + +.media-profile-link { + margin-bottom: var(--space-sm); +} + +.guestbook-panel--comments { + order: -1; +} + +.guestbook-comments-inline { + gap: var(--space-sm); + max-height: 28rem; + overflow-y: auto; +} + +.guestbook-panel--form summary { + cursor: pointer; + font-weight: 700; + color: var(--gold); + padding: var(--space-sm) 0; +} + +.guestbook-panel--form[open] summary { + margin-bottom: var(--space-sm); +} + +.tile-grid--labeled .tile-card { + flex-direction: column; + gap: var(--space-xs); + min-height: 7.5rem; + padding: var(--space-sm); + background: var(--surface-deep, #050505); +} + +.tile-grid--labeled .tile-label { + font-family: var(--font-mono); + font-size: var(--fs-xs); + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--accent-cyan); +} + +.tile-card--game:hover .tile-label { + color: var(--neon-green); +} + +.tile-card--button:hover .tile-label { + color: var(--accent-pink); +} + +.network-subsection#games .tile-card { + border-color: color-mix(in srgb, var(--neon-green) 25%, var(--border)); +} + +.network-subsection#buttons .tile-card { + border-color: color-mix(in srgb, var(--accent-pink) 25%, var(--border)); +} + +.home-hero-avatar-wrap { + border: 0; + padding: 0; + background: transparent; + cursor: pointer; + border-radius: var(--r); +} + +.home-hero-avatar-wrap.is-lain-pulse .home-hero-avatar { + animation: avatar-glitch .5s steps(2) 1; +} + +.lain-toast { + position: fixed; + left: 50%; + bottom: 1.5rem; + transform: translateX(-50%) translateY(12px); + z-index: 10001; + padding: 10px 16px; + border: 1px solid var(--accent-cyan); + border-radius: var(--r); + background: rgba(2, 2, 2, .92); + color: var(--neon-green); + font-family: var(--font-mono); + font-size: var(--fs-sm); + box-shadow: 0 0 18px rgba(var(--link-glow), .35); + opacity: 0; + pointer-events: none; + transition: opacity .25s ease, transform .25s ease; +} + +.lain-toast.is-visible { + opacity: 1; + transform: translateX(-50%) translateY(0); +} + +.site-visit-counter { + margin: var(--space-sm) 0 0; + font-family: var(--font-mono); + font-size: var(--fs-xs); + letter-spacing: 0.08em; + color: var(--muted); +} + +.site-visit-counter-digits { + color: var(--neon-green); + text-shadow: 0 0 6px rgba(57, 255, 20, .35); +} + +body.light-mode .site-search-hits, +body.light-mode .lastfm-now-widget, +body.light-mode .radio-now-widget { + background: var(--surface); +} + +@media (max-width: 600px) { + .header-controls > a.header-button--startpage { + display: inline-flex !important; + font-size: 0.78rem; + padding-inline: 8px; + } +} + +/* ========================================================================== + 2026-07 polish pass II — glows, BBS guestbook, placeholders + ========================================================================== */ + +.mono-terminal { + font-family: var(--font-mono); + font-feature-settings: "calt" 1, "liga" 1, "zero" 1; + font-variant-ligatures: contextual; +} + +.home-tagline, +.protocol-pill, +.tile-label, +.footer-smallweb, +.site-visit-counter, +.retro-loading, +.guestbook-entry strong, +.network-subtitle, +code, +pre, +kbd { + font-feature-settings: "calt" 1, "liga" 1, "zero" 1; + font-variant-ligatures: contextual; +} + +#theme-toggle { + transition: box-shadow .35s ease, transform .15s ease, background .2s ease; +} + +#theme-toggle:hover, +#theme-toggle:focus-visible { + box-shadow: + 0 0 10px rgba(255, 200, 80, .5), + 0 0 22px rgba(255, 45, 149, .28); +} + +body.light-mode #theme-toggle { + box-shadow: 0 0 8px rgba(160, 0, 0, .32); +} + +body.light-mode .home-hero-avatar { + filter: sepia(.12) contrast(1.04) saturate(.92); + animation: avatar-idle-pulse-light 2.4s ease-in-out infinite; +} + +@keyframes avatar-idle-pulse-light { + 0%, 100% { filter: sepia(.12) contrast(1.04) saturate(.92); } + 50% { filter: sepia(.06) contrast(1.08) saturate(1.05) hue-rotate(-6deg); } +} + +body.light-mode .home-hero-brand:hover .home-hero-avatar, +body.light-mode .home-hero-avatar-wrap:hover .home-hero-avatar { + filter: contrast(1.1) drop-shadow(0 0 6px rgba(47, 111, 145, .45)); + animation: none; +} + +.protocol-pill { + box-shadow: + inset 0 0 10px rgba(var(--glow-color), .08), + 0 0 0 0 transparent; +} + +.protocol-pill:hover, +.protocol-pill:focus-visible { + box-shadow: + 0 0 0 1px var(--protocol-accent), + 0 0 8px color-mix(in srgb, var(--protocol-accent) 55%, transparent), + 0 0 16px color-mix(in srgb, var(--protocol-accent) 35%, transparent); +} + +.lastfm-now-widget, +.radio-now-widget { + transition: border-color .2s ease, box-shadow .25s ease; +} + +.lastfm-now-widget:hover, +.lastfm-now-widget:focus-within, +.radio-now-widget:hover, +.radio-now-widget:focus-within { + border-color: color-mix(in srgb, var(--accent-cyan) 55%, var(--border)); + box-shadow: + 0 0 8px rgba(var(--link-glow), .32), + inset 0 0 14px rgba(var(--link-glow), .06); +} + +.lastfm-track:hover, +.lastfm-track:focus-visible { + box-shadow: 0 0 8px rgba(var(--link-glow), .22); +} + +.guestbook-comments-inline .guestbook-entry { + border-left: 3px solid var(--accent-cyan); + background: + linear-gradient(135deg, rgba(var(--link-glow), .04), transparent 55%), + repeating-linear-gradient( + -3deg, + transparent, + transparent 4px, + rgba(255, 255, 255, .012) 4px, + rgba(255, 255, 255, .012) 5px + ), + var(--bg); + font-family: var(--font-mono); +} + +.guestbook-comments-inline .guestbook-entry strong { + font-family: var(--font-mono); + letter-spacing: 0.04em; + text-transform: uppercase; + font-size: var(--fs-xs); + color: var(--accent-cyan); + text-shadow: 0 0 6px rgba(var(--link-glow), .25); +} + +.guestbook-comments-inline .guestbook-entry time { + font-family: var(--font-mono); + font-size: 0.72rem; + opacity: 0.75; +} + +.guestbook-comments-inline .guestbook-entry:hover { + border-color: var(--accent-cyan); + box-shadow: + 0 0 8px rgba(var(--link-glow), .28), + inset 0 0 0 1px rgba(var(--link-glow), .12); +} + +.guestbook-comments-inline .guestbook-entry p { + font-family: inherit; + color: var(--ink) !important; +} + +.footer-heart { + display: inline-block; + color: var(--accent-pink); + text-shadow: 0 0 8px rgba(255, 45, 149, .45); + animation: footer-heart-pulse 1.8s ease-in-out infinite; +} + +@keyframes footer-heart-pulse { + 0%, 100% { transform: scale(1); opacity: 1; } + 35% { transform: scale(1.12); opacity: .92; } + 55% { transform: scale(.96) translateX(1px); opacity: .85; filter: hue-rotate(20deg); } + 70% { transform: scale(1.04); opacity: 1; } +} + +.home-content > section + section { + position: relative; +} + +.home-content > section + section::before { + content: ''; + display: block; + height: 1px; + margin: calc(-1 * var(--space-xl)) 0 var(--space-xl); + background: linear-gradient( + 90deg, + transparent, + rgba(var(--link-glow), .22) 20%, + rgba(57, 255, 20, .18) 50%, + rgba(224, 64, 251, .15) 80%, + transparent + ); + opacity: 0; + transform: scaleX(0); + transform-origin: left center; + transition: opacity .4s ease, transform .55s cubic-bezier(.4, 0, .2, 1); +} + +.home-content > section.is-drawn + section::before, +.home-content > section + section.is-drawn::before { + opacity: 1; + transform: scaleX(1); +} + +body.light-mode .guestbook-comments-inline .guestbook-entry { + background: + linear-gradient(135deg, rgba(139, 0, 0, .07), transparent 55%), + repeating-linear-gradient( + -3deg, + transparent, + transparent 4px, + rgba(92, 72, 52, .04) 4px, + rgba(92, 72, 52, .04) 5px + ), + var(--surface); + border-left-color: color-mix(in srgb, var(--accent) 55%, #8b0000); +} + +body.light-mode .guestbook-comments-inline .guestbook-entry strong { + color: color-mix(in srgb, var(--accent) 80%, #3a0000); + text-shadow: none; +} + +@media (max-width: 600px) { + .home-wrap { + max-width: calc(100vw - 1rem); + padding-left: var(--space-sm); + padding-right: var(--space-sm); + } + + .home-sidebar { + margin: var(--space-md) 0; + } + + .home-side-nav { + padding: var(--space-sm); + gap: var(--space-xs) var(--space-sm); + } + + .network-section .tile-grid, + .network-section .tile-grid--three { + gap: var(--space-sm); + } + + .guestbook-comments-inline { + max-height: 22rem; + } +} + +@media (prefers-reduced-motion: reduce) { + .section-accent-title::after, + .retro-loading::after, + .iframe-clip.is-loading::after, + .home-tagline-text, + .home-tagline-text::after, + .site-footer .footer-inner::after, + .footer-heart, + .home-hero-avatar { + animation: none; + } + + .section-accent-title.is-drawn::after, + .network-subtitle.is-drawn::after { + width: 3.5rem; + } + + /* Panel heading bars: keep them at rest, no grow-on-hover. */ + .home-side-nav h2::after, + .home-sidebar-widget h3::after, + .home-vibe-widget h3::after, + .home-changelog-widget h3::after, + .home-protocol-nav h3::after, + .lpanelxl h3::after, + .home-side-nav:hover h2::after, + .home-sidebar-widget:hover h3::after, + .home-vibe-widget:hover h3::after, + .home-changelog-widget:hover h3::after, + .home-protocol-nav:hover h3::after, + .lpanelxl:hover h3::after { + width: 2.5rem; + transition: none; + } + + .network-subtitle:hover::after, + .network-subtitle:focus-within::after { + width: 4.5rem; + transition: none; + } + + .home-hero h1:hover, + .home-hero-brand:hover .home-hero-avatar, + .home-hero-avatar-wrap:hover .home-hero-avatar { + animation: none; + } + + a:hover, + a:focus-visible, + .tile-grid a:hover, + .friends-list a:hover, + .start-card:hover { + transform: none; + } +} + +/* ========================================================================== + 2026-07 polish pass III — prose, protocol nav, mobile accordions + ========================================================================== */ + +.muted { + line-height: var(--lh-body); +} + +.home-content .muted, +#blog-list .muted, +#changelog-list .muted, +.recent-list .muted { + color: var(--muted); + opacity: 0.92; +} + +body.light-mode .home-content .muted, +body.light-mode #blog-list .muted, +body.light-mode #changelog-list .muted { + color: var(--muted); + opacity: 1; +} + +.home-content > section + section { + margin-top: var(--space-3xl); +} + +.home-content > section + section::before { + margin: calc(-1 * var(--space-3xl) + var(--space-lg)) 0 var(--space-lg); +} + +#blog-list, +#blog-list li, +#blog-list p, +#changelog-list li, +.updates-panel .recent-list li, +.updates-panel .recent-list p, +.start-card span:not(.start-card-icon) { + font-family: var(--font-prose); + line-height: var(--lh-comfort); +} + +#blog-list h3, +#blog-list strong, +.updates-panel h3, +.updates-panel .network-subtitle, +.section-accent-title, +.network-subtitle, +.start-card strong { + font-family: var(--font-mono); +} + +/* Sidebar protocol navigation */ +.home-protocol-nav { + margin-top: 0; + padding: var(--space-md); + border: 1px solid var(--border); + border-radius: var(--r); + background: + radial-gradient(ellipse at top, rgba(var(--glow-color), .07), transparent 72%), + color-mix(in srgb, var(--bg) 88%, #1a0000); + box-shadow: var(--glow-soft); +} + +.home-protocol-nav h3 { + margin: 0 0 var(--space-sm); + padding-bottom: var(--space-xs); + border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent); + font-family: var(--font-mono); + font-size: var(--fs-sm); + text-transform: uppercase; + letter-spacing: 0.06em; + font-weight: 700; + color: var(--gold); +} + +.protocol-pills--sidebar { + flex-direction: column; + align-items: stretch; + gap: 8px; +} + +.protocol-pills--sidebar .protocol-pill { + justify-content: center; + min-height: 36px; + font-size: var(--fs-sm); + font-weight: 600; +} + +/* Network subsections — collapsible on mobile */ +.network-collapsible > .network-subsection-summary { + list-style: none; + cursor: pointer; +} + +.network-collapsible > .network-subsection-summary::-webkit-details-marker { + display: none; +} + +.network-collapsible > .network-subsection-summary::marker { + content: ''; +} + +.network-collapsible > .network-subsection-summary { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: var(--space-sm); +} + +.network-collapsible > .network-subsection-summary .network-subtitle { + flex: 1; + margin-bottom: 0; +} + +.network-collapsible > .network-subsection-summary::after { + content: '▼'; + flex-shrink: 0; + margin-top: 0.35rem; + font-size: 0.65rem; + opacity: 0.55; + transition: transform .2s ease; +} + +.network-collapsible[open] > .network-subsection-summary::after { + transform: rotate(180deg); +} + +.network-collapsible > .network-subsection-body { + margin-top: var(--space-md); +} + +.network-subsection#friends .friends-list a { + display: inline-block; + padding: 5px 10px; + margin: 2px 0; + border: 1px solid color-mix(in srgb, var(--section-neon, var(--border)) 25%, var(--border)); + border-radius: var(--r); + background: linear-gradient(180deg, rgba(var(--section-glow, var(--glow-color)), .06), transparent 80%); +} + +body.light-mode .vibe-facade { + color: var(--accent); + background: + radial-gradient(ellipse at 50% 38%, rgba(139, 0, 0, .12), transparent 58%), + linear-gradient(180deg, #f5ebe0, var(--surface)); + box-shadow: inset 0 0 0 1px var(--border); +} + +body.light-mode .vibe-facade::before { + color: var(--accent); + text-shadow: none; +} + +body.light-mode .vibe-facade-play { + color: var(--accent); + border-color: var(--accent); + background: var(--surface); + box-shadow: 0 4px 16px var(--shadow); +} + +body.light-mode .vibe-facade-text { + color: var(--ink); + text-shadow: none; +} + +@media (min-width: 601px) { + .network-collapsible > .network-subsection-summary { + pointer-events: none; + cursor: default; + } + + .network-collapsible > .network-subsection-summary::after { + display: none; + } +} + +@media (max-width: 600px) { + .home-protocol-nav { + display: none; + } + + .network-collapsible { + padding: var(--space-md); + } + + .network-collapsible:not([open]) > .network-subsection-body { + display: none; + } +} diff --git a/assets/css/skeleton.css b/assets/css/skeleton.css new file mode 100644 index 0000000..9e86e6c --- /dev/null +++ b/assets/css/skeleton.css @@ -0,0 +1,63 @@ +/* ========================================================================== + skeleton.css — Skeleton loading placeholders + Shimmering blocks that match the dark aesthetic of the site. + ========================================================================== */ + +@keyframes skeleton-shimmer { + 0% { background-position: -200px 0; } + 100% { background-position: calc(200px + 100%) 0; } +} + +.skeleton-line { + display: block; + height: 0.9em; + margin: var(--space-sm, 0.5rem) 0; + border-radius: var(--r, 6px); + background: linear-gradient( + 90deg, + var(--border, #2a1010) 0px, + #3a1818 40px, + var(--border, #2a1010) 80px + ); + background-size: 200px 100%; + animation: skeleton-shimmer 1.4s ease-in-out infinite; +} + +.skeleton-line:first-child { width: 60%; } +.skeleton-line:nth-child(2) { width: 80%; } +.skeleton-line:nth-child(3) { width: 45%; } +.skeleton-line:nth-child(4) { width: 70%; } + +.skeleton-block { + display: block; + height: 3rem; + margin: var(--space-sm, 0.5rem) 0; + border-radius: var(--r, 6px); + background: linear-gradient( + 90deg, + var(--border, #2a1010) 0px, + #3a1818 40px, + var(--border, #2a1010) 80px + ); + background-size: 200px 100%; + animation: skeleton-shimmer 1.4s ease-in-out infinite; +} + +/* High-contrast theme skeleton */ +[data-theme="high-contrast"] .skeleton-line, +[data-theme="high-contrast"] .skeleton-block { + background: linear-gradient( + 90deg, + #ddd 0px, + #eee 40px, + #ddd 80px + ); + background-size: 200px 100%; +} + +@media (prefers-reduced-motion: reduce) { + .skeleton-line, + .skeleton-block { + animation: none; + } +} |
