View Source

The actual code and article source behind this site. No minification. No transpilation. What you see is what runs.

↓ Download PHP edition
style.css 1138 lines
/* ════════════════════════════════════════════════════
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; }