View Source

The actual code behind this page. No minification. No transpilation. What you see is what runs.

↓ Download PHP edition
style.css 860 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;
--lwn: #5c8a3c;
--lwn-bg: rgba(92, 138, 60, 0.18);
--lwn-text: #7db85a;
--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;
--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-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-lwn { background: var(--lwn); }
.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-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-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.lwn { background: var(--lwn-bg); color: var(--lwn-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); }
 
.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;
}
 
@media (max-width: 640px) {
.source-layout { grid-template-columns: 1fr; }
}
 
/* Sidebar nav */
.source-nav {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
position: sticky;
top: 76px;
}
 
.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;
}
 
/* 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-current { background:var(--card); border:1px solid var(--border); border-radius:8px; padding:1.5rem; display:flex; align-items:flex-start; justify-content:space-between; gap:2rem; flex-wrap:wrap; margin-bottom:2rem; }
.weather-location{ font-family:'Roboto Mono',monospace; font-size:.7rem; letter-spacing:.12em; text-transform:uppercase; color:var(--text-muted); margin-bottom:.25rem; }
.weather-temp-row{ display:flex; align-items:flex-end; gap:.75rem; }
.weather-temp { font-family:'Roboto Mono',monospace; font-size:4.5rem; font-weight:700; color:var(--fg); line-height:1; }
.weather-icon-lg { font-size:3rem; line-height:1; margin-bottom:.25rem; }
.weather-condition{ font-size:1.1rem; color:var(--text-muted); margin-top:.5rem; }
.weather-details { font-family:'Roboto Mono',monospace; font-size:.85rem; color:var(--text-muted); line-height:2; text-align:right; }
.weather-details strong { color:var(--fg); }
.weather-forecast{ display:grid; grid-template-columns:repeat(7,1fr); gap:.4rem; margin-bottom:1.5rem; }
@media(max-width:480px){ .weather-forecast { grid-template-columns:repeat(4,1fr); } }
.forecast-day { background:var(--card); border:1px solid var(--border); border-radius:6px; padding:.5rem .25rem; text-align:center; }
.forecast-dow { font-family:'Roboto Mono',monospace; font-size:.65rem; color:var(--text-muted); margin-bottom:.2rem; }
.forecast-icon { font-size:1.4rem; line-height:1.4; }
.forecast-high { font-family:'Roboto Mono',monospace; font-size:.85rem; font-weight:700; color:var(--fg); }
.forecast-low { font-family:'Roboto Mono',monospace; font-size:.75rem; color:var(--text-muted); }
.forecast-precip { font-family:'Roboto Mono',monospace; font-size:.65rem; color:var(--primary-light); }
 
/* ── 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); }