View Source
The actual code and article source behind this site. No minification. No transpilation. What you see is what runs.
| /* ════════════════════════════════════════════════════ |
| dispelled.ca — hand-crafted stylesheet |
| No framework. No build step. Just CSS. |
| ════════════════════════════════════════════════════ */ |
| :root { |
| --bg: #0c1929; |
| --bg-card: #132236; |
| --bg-nav: #091523; |
| --bg-hover: #1c3248; |
| --text: #ccdde8; |
| --text-muted: #6d95b0; |
| --text-dim: #3a5c75; |
| --primary: #2b9fd8; |
| --primary-light: #5ab8e8; |
| --border: #1c3248; |
| --border-light: #254560; |
| --slashdot: #026666; |
| --slashdot-bg: rgba(2, 102, 102, 0.18); |
| --slashdot-text: #2aacac; |
| --ars: #bf3c00; |
| --ars-bg: rgba(191, 60, 0, 0.18); |
| --ars-text: #e05828; |
| --hn: #ff6600; |
| --hn-bg: rgba(255, 102, 0, 0.18); |
| --hn-text: #ff8533; |
| --register: #cc0000; |
| --register-bg: rgba(204, 0, 0, 0.18); |
| --register-text: #e03333; |
| --phoronix: #e8941a; |
| --phoronix-bg: rgba(232, 148, 26, 0.18); |
| --phoronix-text: #f0aa3f; |
| --kernel: #557f9d; |
| --kernel-bg: rgba(85, 127, 157, 0.18); |
| --kernel-text: #8bb5d1; |
| --rpi: #bc1142; |
| --rpi-bg: rgba(188, 17, 66, 0.18); |
| --rpi-text: #e03368; |
| --eff: #3d7ab5; |
| --eff-bg: rgba(61, 122, 181, 0.18); |
| --eff-text: #5f9fd4; |
| --krebs: #7b3f6e; |
| --krebs-bg: rgba(123, 63, 110, 0.18); |
| --krebs-text: #a86598; |
| --fsf: #4a7c18; |
| --fsf-bg: rgba(74, 124, 24, 0.18); |
| --fsf-text: #71b82e; |
| --debian: #d70a53; |
| --debian-bg: rgba(215, 10, 83, 0.18); |
| --debian-text: #f0386e; |
| --freebsd: #ab1f28; |
| --freebsd-bg: rgba(171, 31, 40, 0.18); |
| --freebsd-text: #d94048; |
| --openbsd: #4d6b8a; |
| --openbsd-bg: rgba(77, 107, 138, 0.18); |
| --openbsd-text: #8eafd0; |
| --rain: #4a9eff; |
| } |
| /* ── Reset & base ──────────────────────────────────── */ |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
| html { font-size: 16px; scroll-behavior: smooth; } |
| body { |
| background-color: var(--bg); |
| color: var(--text); |
| font-family: 'Open Sans', -apple-system, system-ui, Helvetica, Arial, sans-serif; |
| line-height: 1.65; |
| min-height: 100vh; |
| display: flex; |
| flex-direction: column; |
| } |
| /* ── Fixed background image ────────────────────────── */ |
| /* Real elements (not pseudo-elements) so position:fixed works in all |
| browsers regardless of the body flex/grid formatting context. */ |
| .site-bg { |
| position: fixed; |
| inset: 0; |
| background-image: url('../img/bg.jpg'); |
| background-size: cover; |
| background-position: top left; |
| background-repeat: no-repeat; |
| opacity: .15; |
| z-index: 0; |
| pointer-events: none; |
| } |
| /* Gradient overlay — fades image out toward the bottom and right */ |
| .site-bg-fade { |
| position: fixed; |
| inset: 0; |
| background: |
| linear-gradient(to right, transparent 80%, var(--bg) 95%), |
| linear-gradient(to bottom, transparent 80%, var(--bg) 95%); |
| z-index: 1; |
| pointer-events: none; |
| } |
| h1, h2, h3, h4, h5, h6 { |
| font-family: 'Roboto Slab', Georgia, serif; |
| line-height: 1.3; |
| } |
| a { color: var(--primary); text-decoration: none; transition: color .15s; } |
| a:hover { color: var(--primary-light); text-decoration: underline; text-underline-offset: 3px; } |
| img { max-width: 100%; display: block; } |
| code, pre, .mono { |
| font-family: 'Roboto Mono', 'Courier New', monospace; |
| } |
| /* ── Layout ────────────────────────────────────────── */ |
| .site-wrapper { display: flex; flex-direction: column; min-height: 100vh; position: relative; z-index: 2; } |
| .container { |
| width: 100%; |
| max-width: 860px; |
| margin: 0 auto; |
| padding: 0 1.25rem; |
| } |
| main { flex: 1; padding: 2.5rem 0; } |
| /* ── Header ────────────────────────────────────────── */ |
| .site-header { |
| background: var(--bg-nav); |
| border-bottom: 1px solid var(--border); |
| position: sticky; |
| top: 0; |
| z-index: 100; |
| } |
| .site-header .container { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| height: 60px; |
| } |
| .site-logo { |
| font-family: 'Roboto Slab', serif; |
| font-size: 1.4rem; |
| font-weight: 700; |
| color: var(--text); |
| letter-spacing: -.01em; |
| display: flex; |
| align-items: center; |
| gap: .5rem; |
| } |
| .logo-tortoise { |
| height: 2.2rem; |
| width: 2.2rem; |
| object-fit: contain; |
| } |
| .site-logo span { color: var(--primary); } |
| .site-logo:hover { text-decoration: none; opacity: .9; } |
| /* ── Hamburger (CSS-only, no JS) ───────────────────── */ |
| /* The checkbox is invisible — it's the state machine */ |
| .nav-cb { |
| position: absolute; |
| opacity: 0; |
| width: 0; |
| height: 0; |
| pointer-events: none; |
| } |
| .nav-wrap { position: relative; } |
| .nav-toggle { |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| cursor: pointer; |
| color: var(--text-muted); |
| padding: .4rem; |
| border-radius: 4px; |
| transition: background .15s, color .15s; |
| user-select: none; |
| } |
| .nav-toggle:hover { background: var(--bg-hover); color: var(--text); } |
| .nav-toggle svg { display: block; width: 22px; height: 22px; } |
| /* Toggle between hamburger and X icons via checkbox state */ |
| .nav-toggle .icon-close { display: none; } |
| .nav-cb:checked ~ .nav-toggle .icon-close { display: block; } |
| .nav-cb:checked ~ .nav-toggle .icon-menu { display: none; } |
| /* ── Nav dropdown ──────────────────────────────────── */ |
| .nav-dropdown { |
| display: none; |
| position: absolute; |
| right: 0; |
| top: calc(100% + 8px); |
| background: var(--bg-card); |
| border: 1px solid var(--border-light); |
| border-radius: 8px; |
| min-width: 180px; |
| box-shadow: 0 10px 30px rgba(0,0,0,.45); |
| overflow: hidden; |
| z-index: 200; |
| } |
| /* Show nav when checkbox is checked */ |
| .nav-cb:checked ~ .nav-dropdown { display: block; } |
| .nav-dropdown a { |
| display: block; |
| padding: .65rem 1rem; |
| font-size: .875rem; |
| color: var(--text-muted); |
| transition: background .1s, color .1s; |
| } |
| .nav-dropdown a:hover { background: var(--bg-hover); color: var(--text); text-decoration: none; } |
| .nav-dropdown a.active { color: var(--primary); font-weight: 600; } |
| .header-right { |
| display: flex; |
| align-items: center; |
| gap: .5rem; |
| } |
| .version-switcher { |
| display: flex; |
| align-items: center; |
| border: 1px solid var(--border); |
| border-radius: .35rem; |
| overflow: hidden; |
| font-family: var(--font-mono, monospace); |
| font-size: .72rem; |
| line-height: 1; |
| } |
| .ver { |
| padding: .3rem .6rem; |
| text-decoration: none; |
| transition: background .15s, color .15s; |
| } |
| .ver-active { |
| background: color-mix(in srgb, var(--primary) 20%, transparent); |
| color: var(--primary); |
| font-weight: 600; |
| } |
| .ver-react { border-right: 1px solid var(--border); } |
| .ver-php { border-left: 1px solid var(--border); } |
| a.ver:not(.ver-active) { |
| color: color-mix(in srgb, var(--text-muted) 70%, transparent); |
| } |
| a.ver:not(.ver-active):hover { |
| background: var(--bg-hover); |
| color: var(--text-muted); |
| } |
| .nav-external::after { |
| content: ' ↗'; |
| font-size: .7em; |
| opacity: .45; |
| } |
| .nav-divider { |
| height: 1px; |
| background: var(--border); |
| margin: .4rem .8rem; |
| } |
| .nav-source { |
| font-family: var(--font-mono, monospace); |
| font-size: .75rem !important; |
| opacity: .6; |
| } |
| .nav-source:hover { opacity: 1; } |
| .nav-source.active { opacity: 1; color: var(--primary) !important; } |
| /* ── Page heading ──────────────────────────────────── */ |
| .page-title { font-size: 1.9rem; margin-bottom: 1.75rem; } |
| /* ── Feed header & filters ─────────────────────────── */ |
| .feed-header { |
| display: flex; |
| align-items: center; |
| flex-wrap: wrap; |
| gap: 1rem; |
| margin-bottom: 2rem; |
| } |
| .feed-header h1 { font-size: 1.9rem; } |
| .filter-bar { display: flex; gap: .4rem; flex-wrap: wrap; } |
| .filter-btn { |
| display: inline-block; |
| background: var(--bg-card); |
| border: 1px solid var(--border); |
| color: var(--text-muted); |
| font-size: .72rem; |
| font-family: inherit; |
| padding: .3rem .8rem; |
| border-radius: 999px; |
| cursor: pointer; |
| text-decoration: none; |
| transition: background .15s, color .15s, border-color .15s; |
| } |
| .filter-btn:hover { background: var(--bg-hover); color: var(--text); text-decoration: none; } |
| .filter-btn.active { |
| background: var(--primary); |
| border-color: var(--primary); |
| color: #fff; |
| font-weight: 600; |
| } |
| /* ── Feed timeline ─────────────────────────────────── */ |
| .feed-list { list-style: none; } |
| .feed-timeline { position: relative; } |
| .feed-timeline::before { |
| content: ''; |
| position: absolute; |
| left: 11px; |
| top: 6px; |
| bottom: 6px; |
| width: 1px; |
| background: var(--border); |
| } |
| @media (max-width: 600px) { |
| .feed-timeline::before { display: none; } |
| .feed-dot { display: none; } |
| .feed-item { padding-left: 0; } |
| } |
| .feed-item { |
| position: relative; |
| padding-left: 2.6rem; |
| padding-bottom: 2.25rem; |
| } |
| .feed-body { min-width: 0; } |
| .feed-dot { |
| position: absolute; |
| left: 0; |
| top: 6px; |
| width: 23px; |
| height: 23px; |
| border-radius: 50%; |
| border: 3px solid var(--bg); |
| } |
| .feed-dot.source-slashdot { background: var(--slashdot); } |
| .feed-dot.source-ars { background: var(--ars); } |
| .feed-dot.source-hn { background: var(--hn); } |
| .feed-dot.source-register { background: var(--register); } |
| .feed-dot.source-phoronix { background: var(--phoronix); } |
| .feed-dot.source-kernel { background: var(--kernel); } |
| .feed-dot.source-rpi { background: var(--rpi); } |
| .feed-dot.source-eff { background: var(--eff); } |
| .feed-dot.source-krebs { background: var(--krebs); } |
| .feed-dot.source-fsf { background: var(--fsf); } |
| .feed-dot.source-debian { background: var(--debian); } |
| .feed-dot.source-freebsd { background: var(--freebsd); } |
| .feed-dot.source-openbsd { background: var(--openbsd); } |
| .feed-item h2 { |
| font-size: 1.1rem; |
| font-weight: 700; |
| margin-bottom: .4rem; |
| line-height: 1.4; |
| } |
| .feed-item h2 a { color: rgba(204,221,232,.9); } |
| .feed-item h2 a:hover { color: var(--primary); text-decoration: none; } |
| .feed-item h2, |
| .feed-item h2 a, |
| .feed-desc { |
| overflow-wrap: anywhere; |
| } |
| .feed-meta { |
| display: flex; |
| align-items: center; |
| gap: .6rem; |
| flex-wrap: wrap; |
| margin-bottom: .5rem; |
| } |
| .source-badge { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .62rem; |
| letter-spacing: .09em; |
| text-transform: uppercase; |
| font-weight: 700; |
| padding: .18rem .5rem; |
| border-radius: 4px; |
| } |
| .source-badge.slashdot { background: var(--slashdot-bg); color: var(--slashdot-text); } |
| .source-badge.ars { background: var(--ars-bg); color: var(--ars-text); } |
| .source-badge.hn { background: var(--hn-bg); color: var(--hn-text); } |
| .source-badge.register { background: var(--register-bg); color: var(--register-text); } |
| .source-badge.phoronix { background: var(--phoronix-bg); color: var(--phoronix-text); } |
| .source-badge.kernel { background: var(--kernel-bg); color: var(--kernel-text); } |
| .source-badge.rpi { background: var(--rpi-bg); color: var(--rpi-text); } |
| .source-badge.eff { background: var(--eff-bg); color: var(--eff-text); } |
| .source-badge.krebs { background: var(--krebs-bg); color: var(--krebs-text); } |
| .source-badge.fsf { background: var(--fsf-bg); color: var(--fsf-text); } |
| .source-badge.debian { background: var(--debian-bg); color: var(--debian-text); } |
| .source-badge.freebsd { background: var(--freebsd-bg); color: var(--freebsd-text); } |
| .source-badge.openbsd { background: var(--openbsd-bg); color: var(--openbsd-text); } |
| .feed-time { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .74rem; |
| color: var(--text-muted); |
| } |
| .feed-desc { |
| background: var(--bg-card); |
| border: 1px solid var(--border); |
| border-radius: 6px; |
| padding: .8rem 1rem; |
| font-size: .875rem; |
| color: var(--text-muted); |
| line-height: 1.65; |
| } |
| /* ── Links pages ───────────────────────────────────── */ |
| .links-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); |
| gap: 2rem 2.5rem; |
| } |
| .link-section h2 { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .62rem; |
| font-weight: 400; |
| letter-spacing: .12em; |
| text-transform: uppercase; |
| color: var(--text-dim); |
| padding-bottom: .5rem; |
| border-bottom: 1px solid var(--border); |
| margin-bottom: .65rem; |
| } |
| .link-section ul { list-style: none; } |
| .link-section li { padding: .2rem 0; } |
| .link-section a { font-size: .875rem; } |
| /* ── J's page sections grid ────────────────────────── */ |
| .j-sections-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); |
| gap: 2rem 2.5rem; |
| } |
| .j-section h2 { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .62rem; |
| font-weight: 400; |
| letter-spacing: .12em; |
| text-transform: uppercase; |
| color: var(--text-dim); |
| border-bottom: 1px solid var(--border); |
| padding-bottom: .4rem; |
| margin-bottom: .6rem; |
| } |
| .j-section ul { list-style: none; } |
| .j-section li { padding: .2rem 0; } |
| .j-section a { font-size: .875rem; } |
| .link-note { font-size: .72rem; color: var(--text-dim); margin-left: .4rem; } |
| .agent-divider { |
| display: flex; |
| align-items: center; |
| gap: 1rem; |
| margin: 2.5rem 0; |
| } |
| .agent-divider::before, |
| .agent-divider::after { |
| content: ''; |
| flex: 1; |
| border-top: 1px solid var(--border); |
| opacity: .4; |
| } |
| .agent-divider span { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .62rem; |
| letter-spacing: .14em; |
| text-transform: uppercase; |
| color: var(--text-dim); |
| opacity: .6; |
| white-space: nowrap; |
| } |
| /* ── Weather widget ────────────────────────────────── */ |
| .weather-widget { |
| background: var(--bg-card); |
| border: 1px solid var(--border); |
| border-radius: 10px; |
| overflow: hidden; |
| margin-bottom: 2.25rem; |
| } |
| .weather-current { |
| display: flex; |
| flex-wrap: wrap; |
| align-items: center; |
| gap: 1.25rem; |
| padding: 1.25rem 1.5rem; |
| } |
| .weather-icon { font-size: 3rem; line-height: 1; } |
| .weather-main { flex: 1; min-width: 0; } |
| .weather-temp { |
| font-family: 'Roboto Slab', serif; |
| font-size: 2rem; |
| font-weight: 700; |
| } |
| .weather-feels { |
| font-size: .82rem; |
| color: var(--text-muted); |
| margin-left: .4rem; |
| } |
| .weather-condition { |
| font-size: .88rem; |
| font-weight: 600; |
| color: rgba(204,221,232,.8); |
| margin-top: .15rem; |
| } |
| .weather-location { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .7rem; |
| color: var(--text-muted); |
| margin-top: .25rem; |
| } |
| .weather-stats { display: flex; gap: 1.5rem; text-align: center; } |
| .weather-stat-value { font-size: .9rem; font-weight: 600; } |
| .weather-stat-label { font-family: 'Roboto Mono', monospace; font-size: .62rem; color: var(--text-muted); margin-top: .1rem; } |
| /* Forecast strip */ |
| .forecast-strip { |
| display: grid; |
| grid-template-columns: repeat(7, 1fr); |
| border-top: 1px solid var(--border); |
| } |
| .forecast-day { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| gap: .2rem; |
| padding: .6rem .2rem; |
| text-align: center; |
| border-right: 1px solid var(--border); |
| } |
| .forecast-day:last-child { border-right: none; } |
| .forecast-label { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .58rem; |
| letter-spacing: .06em; |
| text-transform: uppercase; |
| color: var(--text-muted); |
| } |
| .forecast-icon { font-size: 1.2rem; line-height: 1; } |
| .forecast-high { font-size: .78rem; font-weight: 600; } |
| .forecast-low { font-size: .68rem; color: var(--text-muted); } |
| .forecast-precip { font-family: 'Roboto Mono', monospace; font-size: .6rem; color: var(--rain); } |
| /* ── Footer ────────────────────────────────────────── */ |
| .site-footer { |
| background: var(--bg-card); |
| border-top: 1px solid var(--border); |
| padding: 2rem 0; |
| margin-top: auto; |
| } |
| .bandcamp-wrap { |
| max-width: 600px; |
| margin: 0 auto 1.25rem; |
| border-radius: 8px; |
| overflow: hidden; |
| border: 1px solid var(--border); |
| } |
| .footer-copy { |
| text-align: center; |
| font-family: 'Roboto Mono', monospace; |
| font-size: .7rem; |
| color: var(--text-dim); |
| line-height: 1.9; |
| } |
| /* ── View source ───────────────────────────────────── */ |
| .source-header { margin-bottom: 1.75rem; } |
| .source-subtitle { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .78rem; |
| color: var(--text-muted); |
| margin-top: .25rem; |
| } |
| .source-layout { |
| display: grid; |
| grid-template-columns: 200px 1fr; |
| gap: 1.5rem; |
| align-items: start; |
| } |
| /* Sidebar nav */ |
| .source-nav { |
| background: var(--bg-card); |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| max-height: calc(100vh - 100px); |
| overflow-y: auto; |
| overflow-x: hidden; |
| position: sticky; |
| top: 76px; |
| scrollbar-color: var(--border) var(--bg-card); |
| } |
| .source-nav-group { padding: .6rem 0; border-bottom: 1px solid var(--border); } |
| .source-nav-group:last-child { border-bottom: none; } |
| .source-nav-label { |
| display: block; |
| font-family: 'Roboto Mono', monospace; |
| font-size: .58rem; |
| letter-spacing: .1em; |
| text-transform: uppercase; |
| color: var(--text-dim); |
| padding: .2rem .85rem .4rem; |
| } |
| .source-nav-link { |
| display: block; |
| font-family: 'Roboto Mono', monospace; |
| font-size: .78rem; |
| color: var(--text-muted); |
| padding: .3rem .85rem; |
| text-decoration: none; |
| transition: background .1s, color .1s; |
| white-space: nowrap; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| } |
| .source-nav-link:hover { background: var(--bg-hover); color: var(--text); text-decoration: none; } |
| .source-nav-link.active { color: var(--primary); font-weight: 600; } |
| /* Code panel */ |
| .source-panel { |
| background: var(--bg-card); |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| overflow: hidden; |
| min-width: 0; |
| } |
| .source-toolbar { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| padding: .6rem 1rem; |
| border-bottom: 1px solid var(--border); |
| background: var(--bg-nav); |
| } |
| .source-filename { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .8rem; |
| color: var(--primary); |
| font-weight: 600; |
| } |
| .source-lines { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .7rem; |
| color: var(--text-dim); |
| } |
| .source-code-wrap { |
| overflow-x: auto; |
| padding: 1.25rem; |
| } |
| /* Source code table with line numbers */ |
| .source-table { |
| width: 100%; |
| border-collapse: collapse; |
| font-family: 'Roboto Mono', 'Courier New', monospace; |
| font-size: .8rem; |
| line-height: 1.65; |
| } |
| .source-table tr:hover .source-ln, |
| .source-table tr:hover .source-line { background: rgba(43, 159, 216, .06); } |
| .source-ln { |
| width: 1%; |
| min-width: 3rem; |
| padding: 0 1rem 0 .75rem; |
| text-align: right; |
| vertical-align: top; |
| color: var(--text-dim); |
| user-select: none; |
| border-right: 1px solid var(--border); |
| white-space: nowrap; |
| } |
| .source-line { |
| padding: 0 1.25rem; |
| vertical-align: top; |
| white-space: pre; |
| color: var(--text-muted); |
| } |
| /* PHP highlight_string spans inherit the table font */ |
| .source-line span { |
| font-family: 'Roboto Mono', 'Courier New', monospace !important; |
| font-size: .8rem !important; |
| } |
| @media (max-width: 640px) { |
| .source-layout { |
| grid-template-columns: 1fr; |
| gap: 1rem; |
| } |
| .source-nav { |
| position: static; |
| max-height: 14rem; |
| } |
| .source-toolbar { |
| align-items: flex-start; |
| gap: .5rem; |
| padding: .55rem .75rem; |
| } |
| .source-filename { |
| min-width: 0; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
| .source-lines { |
| flex-shrink: 0; |
| } |
| .source-code-wrap { |
| padding: .75rem .5rem; |
| } |
| .source-table { |
| width: max-content; |
| min-width: 100%; |
| font-size: .7rem; |
| } |
| .source-ln { |
| min-width: 2.5rem; |
| padding: 0 .65rem 0 .4rem; |
| } |
| .source-line { |
| padding: 0 .75rem; |
| } |
| .source-line span { |
| font-size: .7rem !important; |
| } |
| } |
| /* Footer source link */ |
| .footer-source-link { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .68rem; |
| color: var(--text-dim); |
| text-decoration: none; |
| transition: color .15s; |
| } |
| .footer-source-link:hover { color: var(--primary); text-decoration: none; } |
| /* ── Stocks ────────────────────────────────────────── */ |
| .stocks-note { |
| font-family: 'Roboto Mono', monospace; |
| font-size: .8rem; |
| color: var(--text-muted); |
| margin-bottom: 1.25rem; |
| } |
| .stocks-widget { |
| border-radius: 8px; |
| overflow: hidden; |
| border: 1px solid var(--border); |
| } |
| /* ── Shared page utilities ─────────────────────────────── */ |
| .page-title { font-family:'Roboto Slab',serif; font-size:2rem; font-weight:700; color:var(--fg); margin-bottom:1.5rem; } |
| .page-subtitle { font-family:'Roboto Mono',monospace; font-size:.85rem; color:var(--text-muted); margin-top:-.75rem; margin-bottom:1.5rem; } |
| .section-subtitle{ font-family:'Roboto Mono',monospace; font-size:.7rem; letter-spacing:.1em; text-transform:uppercase; color:var(--text-muted); border-bottom:1px solid var(--border); padding-bottom:.4rem; margin:2rem 0 1rem; } |
| .data-attr { font-family:'Roboto Mono',monospace; font-size:.7rem; color:var(--text-dim); margin-top:2rem; } |
| .page-header-row { display:flex; align-items:flex-start; justify-content:space-between; flex-wrap:wrap; gap:1rem; margin-bottom:1.5rem; } |
| .empty-msg { font-family:'Roboto Mono',monospace; font-size:.85rem; color:var(--text-muted); padding:3rem 0; text-align:center; } |
| /* ── Search bar ────────────────────────────────────────── */ |
| .search-form { display:flex; gap:.5rem; align-items:center; } |
| .search-input { |
| font-family:'Roboto Mono',monospace; |
| font-size:.8rem; |
| background:var(--card); |
| border:1px solid var(--border); |
| border-radius:999px; |
| color:var(--fg); |
| padding:.3rem .9rem; |
| width:160px; |
| outline:none; |
| } |
| .search-input:focus { border-color:var(--primary); } |
| .feed-header-row { display:flex; align-items:center; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:.75rem; } |
| /* ── Prose / About ─────────────────────────────────────── */ |
| .prose-block { max-width:640px; line-height:1.75; color:var(--text-muted); margin-bottom:2rem; } |
| .prose-block p { margin-bottom:1rem; } |
| .prose-block strong { color:var(--fg); } |
| .info-grid { display:grid; grid-template-columns:1fr 1fr; gap:.5rem; margin-bottom:2rem; } |
| @media(max-width:520px){ .info-grid { grid-template-columns:1fr; } } |
| .info-card { background:var(--card); border:1px solid var(--border); border-radius:6px; padding:.6rem 1rem; } |
| .info-label { font-family:'Roboto Mono',monospace; font-size:.65rem; letter-spacing:.08em; text-transform:uppercase; color:var(--text-muted); } |
| .info-value { font-size:.9rem; color:var(--fg); margin-top:.15rem; } |
| .source-list { list-style:none; columns:2; gap:1rem; } |
| .source-list li { font-family:'Roboto Mono',monospace; font-size:.85rem; color:var(--text-muted); padding:.2rem 0; } |
| .source-arrow { color:var(--primary); margin-right:.4rem; } |
| /* ── Links page ────────────────────────────────────────── */ |
| .links-section { margin-bottom:2rem; } |
| .links-grid { display:grid; grid-template-columns:1fr 1fr; gap:.5rem; } |
| @media(max-width:520px){ .links-grid { grid-template-columns:1fr; } } |
| .link-card { display:block; background:var(--card); border:1px solid var(--border); border-radius:6px; padding:.7rem 1rem; text-decoration:none; transition:border-color .15s; } |
| .link-card:hover { border-color:var(--primary); } |
| .link-label { font-size:.9rem; font-weight:600; color:var(--fg); } |
| .link-card:hover .link-label { color:var(--primary); } |
| .link-ext { opacity:.4; font-size:.75rem; } |
| .link-desc { font-size:.78rem; color:var(--text-muted); margin-top:.2rem; line-height:1.4; } |
| /* ── Weather page ──────────────────────────────────────── */ |
| .weather-error { color:var(--primary-light); font-family:'Roboto Mono',monospace; } |
| /* Current conditions */ |
| .wx-current { background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:1.5rem; display:flex; gap:2rem; flex-wrap:wrap; margin-bottom:1.5rem; align-items:flex-start; position:relative; } |
| .wx-hero { min-width:10rem; } |
| .wx-temp-block { display:flex; align-items:flex-end; gap:.6rem; } |
| .wx-temp { font-family:'Roboto Mono',monospace; font-size:4rem; font-weight:700; line-height:1; } |
| .wx-icon-lg { font-size:2.6rem; line-height:1; margin-bottom:.2rem; } |
| .wx-label { font-size:1rem; color:var(--text-muted); margin-top:.4rem; } |
| .wx-location { font-family:'Roboto Mono',monospace; font-size:.65rem; letter-spacing:.1em; text-transform:uppercase; color:var(--text-dim); margin-top:.2rem; } |
| .wx-current-source { max-width:25rem; font-family:'Roboto Mono',monospace; font-size:.6rem; line-height:1.55; color:var(--text-dim); margin-top:.65rem; } |
| .wx-current-source a { color:var(--primary-light); text-decoration:none; } |
| .wx-current-source a:hover { text-decoration:underline; } |
| .wx-radar-space { display:flex; align-items:center; justify-content:space-between; gap:1rem; background:var(--card); border:1px solid var(--border); border-radius:6px; padding:.7rem 1rem; margin:-.65rem 0 1.5rem; } |
| .wx-radar-label { font-family:'Roboto Mono',monospace; font-size:.65rem; letter-spacing:.1em; text-transform:uppercase; color:var(--text-dim); } |
| .wx-radar-link { font-family:'Roboto Mono',monospace; font-size:.75rem; color:var(--primary-light); text-decoration:none; } |
| .wx-radar-link:hover { color:var(--primary); text-decoration:underline; } |
| .wx-section-source { margin:-.35rem 0 .75rem; font-family:'Roboto Mono',monospace; font-size:.62rem; line-height:1.45; color:var(--text-dim); } |
| @media(max-width:600px){ .wx-radar-space { align-items:flex-start; flex-direction:column; gap:.35rem; } } |
| .wx-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:.6rem 1.5rem; flex:1; } |
| @media(max-width:600px){ .wx-grid { grid-template-columns:repeat(2,1fr); } } |
| .wx-stat { display:flex; flex-direction:column; gap:.1rem; } |
| .wx-stat-label { font-family:'Roboto Mono',monospace; font-size:.6rem; letter-spacing:.08em; text-transform:uppercase; color:var(--text-dim); } |
| .wx-stat-val { font-family:'Roboto Mono',monospace; font-size:.9rem; color:var(--text); } |
| /* Soil summary table */ |
| .wx-soil-summary { margin-bottom:.75rem; } |
| .wx-soil-now { border-collapse:collapse; font-size:.82rem; margin-bottom:.75rem; } |
| .wx-soil-now th { font-family:'Roboto Mono',monospace; font-size:.6rem; letter-spacing:.08em; text-transform:uppercase; color:var(--text-dim); padding:.3rem .8rem .3rem 0; border-bottom:1px solid var(--border); text-align:left; } |
| .wx-soil-now td { font-family:'Roboto Mono',monospace; padding:.25rem .8rem .25rem 0; border-bottom:1px solid var(--border-light); color:var(--text-muted); } |
| .wx-soil-now td:first-child { color:var(--text-dim); } |
| .wx-soil-now tr:last-child td { border-bottom:none; } |
| /* Section headings */ |
| .wx-section-title { font-family:'Roboto Mono',monospace; font-size:.75rem; letter-spacing:.12em; text-transform:uppercase; color:var(--text-muted); border-bottom:1px solid var(--border); padding-bottom:.4rem; margin:1.5rem 0 .75rem; } |
| /* Hourly table */ |
| .wx-hourly-scroll { max-width:100%; overflow-x:auto; margin-bottom:1.5rem; } |
| .wx-hourly-table { border-collapse:collapse; width:100%; min-width:480px; font-size:.8rem; } |
| .wx-hourly-table th { font-family:'Roboto Mono',monospace; font-size:.6rem; letter-spacing:.08em; text-transform:uppercase; color:var(--text-dim); padding:.35rem .6rem; text-align:left; border-bottom:1px solid var(--border); white-space:nowrap; } |
| .wx-hourly-table td { padding:.3rem .6rem; border-bottom:1px solid var(--border-light); white-space:nowrap; } |
| .wx-hourly-table tr:last-child td { border-bottom:none; } |
| .wx-mono { font-family:'Roboto Mono',monospace; } |
| .wx-precip-hi { color:var(--primary-light); } |
| /* 7-day forecast */ |
| .wx-forecast-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:.5rem; margin-bottom:1.5rem; } |
| @media(max-width:900px){ .wx-forecast-grid { grid-template-columns:repeat(4,1fr); } } |
| @media(max-width:480px){ .wx-forecast-grid { grid-template-columns:repeat(2,1fr); } } |
| .wx-forecast-card { background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:.75rem .5rem; } |
| .wx-fc-dow { font-family:'Roboto Mono',monospace; font-size:.7rem; font-weight:700; color:var(--text); margin-bottom:.05rem; } |
| .wx-fc-date { font-family:'Roboto Mono',monospace; font-size:.6rem; color:var(--text-dim); margin-bottom:.4rem; } |
| .wx-fc-icon { font-size:1.6rem; line-height:1.3; } |
| .wx-fc-label { font-size:.65rem; color:var(--text-muted); margin:.2rem 0 .4rem; min-height:2em; } |
| .wx-fc-temps { font-family:'Roboto Mono',monospace; font-size:.9rem; } |
| .wx-fc-feels { font-family:'Roboto Mono',monospace; font-size:.6rem; color:var(--text-dim); margin-bottom:.5rem; } |
| .wx-fc-detail { border-collapse:collapse; width:100%; font-size:.62rem; margin-top:.4rem; } |
| .wx-fc-detail td { padding:.15rem 0; border-bottom:1px solid var(--border-light); } |
| .wx-fc-detail td:first-child { color:var(--text-dim); font-family:'Roboto Mono',monospace; padding-right:.4rem; white-space:nowrap; } |
| .wx-fc-detail td:last-child { font-family:'Roboto Mono',monospace; color:var(--text); } |
| .wx-fc-detail tr:last-child td { border-bottom:none; } |
| /* UV colours */ |
| .uv-low { color:#7db85a; } |
| .uv-moderate { color:#f0aa3f; } |
| .uv-high { color:#e05828; } |
| .uv-veryhigh { color:#cc3333; } |
| .uv-extreme { color:#a05ab8; } |
| /* AQI colours */ |
| .aqi-good { color:#7db85a; } |
| .aqi-moderate { color:#f0aa3f; } |
| .aqi-sensitive { color:#e07a28; } |
| .aqi-unhealthy { color:#cc3333; } |
| .aqi-very { color:#a05ab8; } |
| .aqi-hazardous { color:#7e0023; } |
| /* AQI hero score */ |
| .wx-aqi-hero { justify-content:center; } |
| .wx-aqi-score { font-family:'Roboto Mono',monospace; font-size:3.5rem; font-weight:700; line-height:1; margin-bottom:.2rem; } |
| /* CAPE colours */ |
| .cape-stable { color:#7db85a; } |
| .cape-weak { color:#c5c54a; } |
| .cape-moderate { color:#f0aa3f; } |
| .cape-large { color:#e05828; } |
| .cape-extreme { color:#cc3333; } |
| /* Next good spray window callout */ |
| .wx-next-spray { display:flex; align-items:center; gap:1rem; flex-wrap:wrap; border-radius:8px; border:1px solid var(--border); padding:.65rem 1.1rem; margin-bottom:1rem; font-family:'Roboto Mono',monospace; font-size:.85rem; } |
| .wx-next-spray.spray-ideal, .wx-next-spray.spray-good { border-color:rgba(125,184,90,.35); background:rgba(125,184,90,.07); } |
| .wx-next-spray.spray-marginal { border-color:rgba(240,170,63,.3); background:rgba(240,170,63,.06); } |
| .wx-next-spray.spray-poor { border-color:rgba(204,51,51,.25); background:rgba(204,51,51,.05); } |
| .wx-next-spray-label { color:var(--text-dim); text-transform:uppercase; font-size:.7rem; letter-spacing:.05em; white-space:nowrap; } |
| .wx-next-spray-time { font-weight:700; font-size:1rem; } |
| .wx-next-spray-dur { color:var(--text-dim); font-size:.78rem; } |
| .wx-next-spray.spray-ideal .wx-next-spray-time { color:#7db85a; } |
| .wx-next-spray.spray-good .wx-next-spray-time { color:#a8c96a; } |
| .wx-next-spray.spray-marginal .wx-next-spray-time { color:#f0aa3f; } |
| .wx-next-spray.spray-poor .wx-next-spray-time { color:#cc3333; } |
| /* Spray window */ |
| .wx-spray-now { display:flex; align-items:flex-start; gap:1.5rem; background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:1rem 1.25rem; margin-bottom:.75rem; flex-wrap:wrap; } |
| .wx-spray-rating { font-family:'Roboto Mono',monospace; font-size:1.3rem; font-weight:700; min-width:10rem; padding-top:.1rem; } |
| .wx-spray-stats { display:flex; gap:1.5rem; flex-wrap:wrap; } |
| .spray-ideal { color:#7db85a; } |
| .spray-good { color:#a8c96a; } |
| .spray-marginal { color:#f0aa3f; } |
| .spray-poor { color:#cc3333; } |
| /* Delta T */ |
| .dt-ideal { color:#7db85a; } |
| .dt-good { color:#a8c96a; } |
| .dt-marginal { color:#f0aa3f; } |
| .dt-poor { color:#cc3333; } |
| /* Frost / freeze */ |
| .frost-risk { color:#7eb8e0; } |
| .frost-freeze { color:#a05ab8; font-weight:700; } |
| .wx-frost-card { border-color:#3a4a60; } |
| .wx-frost-clear { font-family:'Roboto Mono',monospace; font-size:.82rem; color:#7db85a; margin-bottom:1rem; } |
| .wx-frost-alert { font-family:'Roboto Mono',monospace; font-size:.85rem; color:#7eb8e0; background:rgba(126,184,224,.08); border:1px solid rgba(126,184,224,.25); border-radius:6px; padding:.5rem .8rem; margin-bottom:.75rem; } |
| .wx-freeze-alert { color:#a05ab8; background:rgba(160,90,184,.08); border-color:rgba(160,90,184,.25); } |
| /* Soil moisture */ |
| .moist-dry { color:#c5a84a; } |
| .moist-good { color:#7db85a; } |
| .moist-wet { color:#7eb8e0; } |
| .moist-sat { color:#a05ab8; } |
| /* Precipitation bar + summary */ |
| .wx-precip-summary { display:flex; gap:2rem; flex-wrap:wrap; margin-bottom:.75rem; } |
| .wx-precip-bar { height:8px; background:var(--primary); border-radius:3px; min-width:2px; } |
| .wx-precip-bar-fc { background:rgba(var(--primary-rgb,100,160,220),.45); } |
| .wx-precip-divider td { font-family:'Roboto Mono',monospace; font-size:.65rem; color:var(--text-dim); padding:.3rem 0; font-style:normal; } |
| /* Field conditions summary */ |
| .wx-field-summary { display:flex; gap:1.5rem; flex-wrap:wrap; background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:1rem 1.25rem; margin-bottom:.75rem; } |
| /* Spray timeline */ |
| .wx-spray-now--compact { padding:.6rem 1rem; } |
| .wx-spray-now--compact .wx-spray-rating { font-size:1.1rem; } |
| .wx-spray-timeline-wrap { margin-bottom:1rem; } |
| .wx-spray-timeline { display:flex; height:28px; border-radius:6px; overflow:hidden; gap:1px; margin-bottom:3px; } |
| .wx-spray-block { flex:1; } |
| .wx-spray-timeline-labels { display:flex; } |
| .wx-spray-tl-label { flex:1; font-family:'Roboto Mono',monospace; font-size:.6rem; color:var(--text-dim); white-space:nowrap; overflow:hidden; } |
| .wx-spray-tl-legend { display:flex; align-items:center; gap:.6rem; font-family:'Roboto Mono',monospace; font-size:.68rem; color:var(--text-dim); margin-top:.4rem; } |
| .wx-stl-dot { display:inline-block; width:10px; height:10px; border-radius:2px; } |
| /* 24h SVG chart */ |
| .wx-svg-wrap { margin-bottom:.75rem; border-radius:8px; overflow:hidden; } |
| /* Season GDD */ |
| .wx-gdd-summary { display:flex; align-items:center; gap:2rem; flex-wrap:wrap; background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:1rem 1.5rem; margin-bottom:1.25rem; } |
| .wx-gdd-total { display:flex; align-items:baseline; gap:.35rem; } |
| .wx-gdd-num { font-family:'Roboto Mono',monospace; font-size:2.8rem; font-weight:700; color:var(--primary); line-height:1; } |
| .wx-gdd-unit { font-family:'Roboto Mono',monospace; font-size:1rem; color:var(--text-dim); } |
| .wx-gdd-meta { display:flex; gap:1.5rem; flex-wrap:wrap; } |
| .wx-gdd-crop { font-family:'Roboto Mono',monospace; font-size:.75rem; text-transform:uppercase; letter-spacing:.08em; color:var(--text-dim); margin:.75rem 0 .4rem; } |
| .wx-gdd-stages { display:flex; flex-direction:column; gap:.3rem; margin-bottom:.5rem; } |
| .wx-gdd-stage { display:flex; align-items:center; gap:.75rem; font-family:'Roboto Mono',monospace; font-size:.8rem; padding:.3rem .6rem; border-radius:5px; } |
| .gdd-reached { background:rgba(125,184,90,.08); border-left:3px solid #7db85a; } |
| .gdd-future { background:var(--bg-card); border-left:3px solid var(--border); color:var(--text-dim); } |
| .gdd-current { background:rgba(125,184,90,.18); border-left:3px solid #7db85a; font-weight:700; } |
| .wx-gdd-stage-name { flex:0 0 12rem; } |
| .wx-gdd-stage-val { flex:0 0 7rem; color:var(--text-dim); font-size:.75rem; } |
| .wx-gdd-stage-rem { font-size:.75rem; color:var(--text-dim); } |
| .gdd-done { color:#7db85a; } |
| @media(max-width:480px) { |
| .wx-gdd-stage { flex-wrap:wrap; } |
| .wx-gdd-stage-rem { flex-basis:100%; } |
| } |
| /* ── GitHub page ───────────────────────────────────────── */ |
| .gh-list { display:flex; flex-direction:column; gap:.5rem; margin-bottom:1.5rem; } |
| .gh-card { display:block; background:var(--card); border:1px solid var(--border); border-radius:8px; padding:1.1rem 1.25rem; text-decoration:none; transition:border-color .15s; } |
| .gh-card:hover { border-color:var(--primary); } |
| .gh-card-inner { display:flex; align-items:flex-start; gap:1rem; justify-content:space-between; } |
| .gh-card-body { flex:1; min-width:0; } |
| .gh-name { font-family:'Roboto Mono',monospace; font-size:.95rem; font-weight:700; color:var(--primary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } |
| .gh-card:hover .gh-name { text-decoration:underline; } |
| .gh-desc { font-size:.85rem; color:var(--text-muted); margin-top:.3rem; line-height:1.5; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; } |
| .gh-meta { display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; margin-top:.5rem; } |
| .gh-lang { display:flex; align-items:center; gap:.35rem; font-family:'Roboto Mono',monospace; font-size:.75rem; color:var(--text-muted); } |
| .gh-lang-dot { width:10px; height:10px; border-radius:50%; flex-shrink:0; } |
| .gh-topic { font-family:'Roboto Mono',monospace; font-size:.65rem; padding:.15rem .5rem; border-radius:999px; background:var(--card-hover,rgba(255,255,255,.06)); color:var(--text-muted); } |
| .gh-stars { display:flex; align-items:center; gap:.3rem; font-family:'Roboto Mono',monospace; font-size:.85rem; color:#f5c542; white-space:nowrap; flex-shrink:0; } |
| /* ── Source download button ────────────────────────────── */ |
| .dl-btn { |
| display: inline-flex; align-items: center; gap: .4rem; |
| padding: .4rem .85rem; |
| border: 1px solid var(--border); border-radius: 6px; |
| font-family: var(--font-mono); font-size: .75rem; |
| color: var(--text-muted); text-decoration: none; |
| white-space: nowrap; |
| transition: color .15s, border-color .15s, background .15s; |
| } |
| .dl-btn:hover { color: var(--text); border-color: var(--primary); background: var(--bg-card); } |
| /* ── Articles / Categories ─────────────────────────────── */ |
| .breadcrumb { |
| font-family: var(--font-mono); font-size: .8rem; color: var(--text-muted); |
| margin-bottom: 1.25rem; display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; |
| } |
| .breadcrumb a { color: var(--text-muted); text-decoration: none; } |
| .breadcrumb a:hover { color: var(--primary); } |
| .breadcrumb span { color: var(--text-dim); } |
| .article-date { |
| font-family: var(--font-mono); font-size: .78rem; color: var(--text-muted); |
| margin-bottom: 1.5rem; |
| } |
| .article-content h1 { font-size: 1.6rem; margin: 0 0 1rem; color: var(--text); } |
| .article-content h2 { font-size: 1.2rem; margin: 1.75rem 0 .6rem; color: var(--text); border-bottom: 1px solid var(--border); padding-bottom: .3rem; } |
| .article-content h3 { font-size: 1rem; margin: 1.25rem 0 .4rem; color: var(--primary-light); } |
| .article-content p { line-height: 1.75; margin: 0 0 .9rem; color: var(--text); } |
| .article-content ul, .article-content ol { padding-left: 1.5rem; margin: 0 0 .9rem; color: var(--text); line-height: 1.75; } |
| .article-content li { margin-bottom: .3rem; } |
| .article-content code { |
| font-family: var(--font-mono); font-size: .83em; |
| background: var(--bg-card); border: 1px solid var(--border); |
| border-radius: 3px; padding: .1em .35em; color: var(--primary-light); |
| } |
| .article-content pre { |
| background: var(--bg-card); border: 1px solid var(--border); border-radius: 6px; |
| padding: 1rem 1.25rem; overflow-x: auto; margin: 0 0 1rem; |
| } |
| .article-content pre code { |
| background: none; border: none; padding: 0; |
| font-size: .83rem; color: var(--text); line-height: 1.6; |
| } |
| .article-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .25rem; } |
| .article-row { |
| display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; |
| padding: .65rem .85rem; background: var(--bg-card); border: 1px solid var(--border); |
| border-radius: 6px; transition: border-color .15s; |
| } |
| .article-row:hover { border-color: var(--primary); } |
| .article-row a { color: var(--text); text-decoration: none; font-size: .95rem; flex: 1; min-width: 0; } |
| .article-row a:hover { color: var(--primary); } |
| .article-row-date { font-family: var(--font-mono); font-size: .75rem; color: var(--text-muted); white-space: nowrap; flex-shrink: 0; } |
| .cat-section-heading { font-size: 1rem; font-family: var(--font-mono); color: var(--text-muted); text-transform: uppercase; letter-spacing: .08em; margin: 2rem 0 .75rem; font-weight: 600; } |
| .cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: .75rem; margin-top: .5rem; } |
| .cat-card { |
| display: block; background: var(--bg-card); border: 1px solid var(--border); |
| border-radius: 8px; padding: 1.1rem 1.25rem; text-decoration: none; |
| transition: border-color .15s; |
| } |
| .cat-card:hover { border-color: var(--primary); } |
| .cat-name { font-size: .95rem; font-weight: 600; color: var(--text); margin: 0 0 .3rem; } |
| .cat-count { font-family: var(--font-mono); font-size: .75rem; color: var(--text-muted); margin: 0; } |
dispelled