/* =========================================================
   Dylan Allison — front page
   Same look as the résumé (blueprint navy + hi-vis safety),
   lightly dressed for the season: the drawing, the glow in the
   corner and the season label change; everything else stays.
   ========================================================= */

@font-face {
  font-family: "Oswald"; font-style: normal; font-display: swap; font-weight: 200 700;
  src: url("/fonts/oswald-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url("/fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url("/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono"; font-style: normal; font-display: swap; font-weight: 100 800;
  src: url("/fonts/jetbrains-mono-latin.woff2") format("woff2");
}

:root {
  --bg: #0c1622;
  --surface: #16263a;
  --line: #2c4258;
  --line-soft: #1d3044;
  --text: #eef3f7;
  --text-soft: #b3c3d1;
  --muted: #71879c;
  --accent: #f7b500;      /* hi-vis yellow */
  --accent-2: #ff6b2c;    /* safety orange */
  --steel: #3a5670;       /* the drawing's lines */
  --steel-hot: #4a6a8c;   /* and its wires */

  --display: "Oswald", "Arial Narrow", sans-serif;
  --body: "Archivo", "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;
  --maxw: 1280px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  /* The season takes over the accent colour: the badge, menu underline,
     kicker, name, buttons, section numbers and links all follow it. The
     navy, the grid and the type stay the résumé's. */
  --season: #ff6b2c;
  --season-hi: #f7b500;
  --season-lo: #c2410c;
  --season-glow: rgba(255, 107, 44, 0.20);
  --season-glow-2: rgba(247, 181, 0, 0.10);
  --grid-line: rgba(255, 170, 110, 0.065);
  --name-fill: linear-gradient(100deg, #ffc23d 0%, #ff8a2c 45%, #ff6b2c 70%, #e0521c 100%);
  --accent: var(--season);
  /* The same season on light paper (the light look): darker, so it reads. */
  --season-ink: #c2410c;
  --name-fill-day: linear-gradient(100deg, #b45309 0%, #c2410c 55%, #9a3412 100%);
}
:root[data-season="winter"] {
  --season: #6fc2e8; --season-hi: #eef3f7; --season-lo: #3d8fbf;
  --season-glow: rgba(111, 194, 232, 0.20); --season-glow-2: rgba(200, 230, 250, 0.08);
  --grid-line: rgba(150, 205, 245, 0.075);
  --name-fill: linear-gradient(100deg, #ffffff 0%, #cfeaf8 40%, #6fc2e8 100%);
  --season-ink: #1d6f9e; --name-fill-day: linear-gradient(100deg, #0e4d73 0%, #1d6f9e 60%, #2b80b0 100%);
}
:root[data-season="spring"] {
  --season: #7fd18b; --season-hi: #f4a7c0; --season-lo: #4fae6a;
  --season-glow: rgba(127, 209, 139, 0.16); --season-glow-2: rgba(244, 167, 192, 0.10);
  --grid-line: rgba(150, 220, 160, 0.06);
  --name-fill: linear-gradient(100deg, #c7f0a0 0%, #7fd18b 55%, #f4a7c0 100%);
  --season-ink: #2f7d43; --name-fill-day: linear-gradient(100deg, #2f7d43 0%, #37874c 55%, #b5476b 100%);
}
:root[data-season="summer"] {
  --season: #f7b500; --season-hi: #ffe066; --season-lo: #ff6b2c;
  --season-glow: rgba(247, 181, 0, 0.22); --season-glow-2: rgba(255, 107, 44, 0.10);
  --grid-line: rgba(255, 210, 110, 0.065);
  --name-fill: linear-gradient(100deg, #ffe066 0%, #f7b500 50%, #ff6b2c 100%);
  --season-ink: #875c00; --name-fill-day: linear-gradient(100deg, #875c00 0%, #9a6400 50%, #c2410c 100%);
}
/* The light look (the switch in the header, shared with the photo site and the
   résumé): drafting paper, the season's colours darkened to read on it. The
   drawing keeps its night sky on a panel of its own (below). */
:root[data-theme="light"] {
  --bg: #f2f5f8; --surface: #e1e7ee; --line: #c9d3de; --line-soft: #dbe2ea;
  --text: #0c1622; --text-soft: #2f4255; --muted: #52657a;
  --accent: var(--season-ink);
  --grid-line: rgba(12, 22, 34, 0.05);
  --season-glow: color-mix(in srgb, var(--season) 14%, transparent);
  --season-glow-2: color-mix(in srgb, var(--season-hi) 10%, transparent);
  --name-fill: var(--name-fill-day);
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  background-color: var(--bg);
  background-image:
    radial-gradient(1300px 700px at 85% -5%, var(--season-glow), transparent 62%),
    radial-gradient(1000px 600px at -10% 105%, var(--season-glow-2), transparent 60%);
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--body);
  font-weight: 380;
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: 0.5;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 48px 48px;
}
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
::selection { background: var(--season); color: #14100a; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
main:focus { outline: none; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Paragraphs don't leave one word alone on their last line, and .nowrap keeps
   a phrase together (a date, "CC BY-NC-SA 4.0"). */
p, li { text-wrap: pretty; }
.nowrap { white-space: nowrap; }
/* Footer links are easier to tap than they look: the touch area reaches past
   the text a little. */
.site-footer a { position: relative; }
.site-footer a::after { content: ""; position: absolute; inset: -6px; }
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 50; padding: 10px 14px;
  background: var(--text); color: var(--bg); font: 500 0.8125rem/1 var(--mono);
}
.skip:focus { top: 12px; }

.container {
  position: relative; z-index: 2;
  width: 100%; max-width: var(--maxw); margin: 0 auto; padding-inline: var(--gutter);
}

/* ---------- header ---------- */
.masthead { position: relative; z-index: 3; }
.site-header { padding-block: 1.6rem 1rem; border-bottom: 1px solid var(--line-soft); }
.site-header .container { display: flex; align-items: center; justify-content: space-between; gap: 2rem; }
.brand {
  display: inline-flex; align-items: baseline; gap: 0.55rem; white-space: nowrap;
  font-family: var(--display); font-weight: 500; font-size: 1.1rem; letter-spacing: 0.03em; text-transform: uppercase;
}
.brand .mark {
  font: 500 0.72rem/1.4 var(--mono); letter-spacing: 0.18em; color: var(--accent);
  border: 1px solid var(--line); padding: 0.28rem 0.5rem; border-radius: 2px;
}
.nav {
  display: flex; gap: 1.75rem;
  font: 400 0.78rem/1.65 var(--mono); letter-spacing: 0.16em; text-transform: uppercase;
}
.nav a { position: relative; color: var(--text-soft); padding-bottom: 0.2rem; transition: color 220ms ease; }
.nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 1px; background: var(--accent);
  transition: right 280ms cubic-bezier(0.6, 0, 0.2, 1);
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--text); }
.nav a:hover::after, .nav a[aria-current="page"]::after { right: 0; }
.nav { align-items: center; }
/* Light/dark switch: a sun at night (switch to daylight), a moon in daylight. */
.theme {
  display: inline-grid; place-items: center; width: 34px; height: 34px; margin: -8px -9px -8px -0.6rem;
  padding: 0; border: 0; border-radius: 2px; background: none; color: var(--text-soft); cursor: pointer;
  transition: color 220ms ease;
}
.theme:hover { color: var(--accent); }
.theme svg { grid-area: 1 / 1; width: 16px; height: 16px; }
.theme .moon { display: none; }
:root[data-theme="light"] .theme .moon { display: block; }
:root[data-theme="light"] .theme .sun { display: none; }
@media (max-width: 560px) {
  .site-header .container { gap: 1rem; }
  .brand .name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .nav { gap: 1.1rem; letter-spacing: 0.1em; }
}
@media (max-width: 480px) {
  .nav { gap: 0.95rem; letter-spacing: 0.08em; }
}
/* Small phones: the badge shortens to the initials so the menu fits. */
@media (max-width: 400px) {
  .brand .mark .pg { display: none; }
  .site-header .container { gap: 0.75rem; }
  .nav { gap: 0.8rem; letter-spacing: 0.04em; }
}

/* Five menu links (Home · Photos · About · Résumé · Socials). As the screen
   narrows, the name gives way to the DA badge (the big name is right below
   on the photo site and the front page), then the badge drops its number,
   then the menu tightens, so it always fits on one line. */
@media (max-width: 720px) {
  .brand .name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (min-width: 561px) and (max-width: 640px) {
  .nav { gap: 1.1rem; letter-spacing: 0.1em; }
}
@media (max-width: 480px) {
  .brand .mark .pg { display: none; }
  .site-header .container { gap: 0.75rem; }
}
@media (max-width: 420px) {
  .nav { gap: 0.7rem; letter-spacing: 0; }
}
@media (max-width: 360px) {
  .nav { font-size: 0.68rem; gap: 0.55rem; }
}

.coord-strip {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.2rem 1rem;
  padding-block: 0.7rem; border-bottom: 1px solid var(--line-soft);
  font: 400 0.7rem/1.65 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted);
}
.coord-strip span { white-space: nowrap; }
.coord-strip .dot {
  display: inline-block; width: 6px; height: 6px; margin-right: 0.5rem; border-radius: 50%;
  background: var(--season); box-shadow: 0 0 8px var(--season); transform: translateY(-1px);
}
@media (max-width: 720px) { .coord-strip .mid { display: none; } }
@media (max-width: 420px) { .coord-strip { letter-spacing: 0.12em; } }

/* ---------- hero ---------- */
.hero {
  position: relative; overflow: hidden;
  padding-block: clamp(2rem, 5vw, 4rem) clamp(2.5rem, 5vw, 4rem);
}
.hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: clamp(2rem, 6vw, 5rem); align-items: center; }
@media (max-width: 880px) { .hero-grid { grid-template-columns: 1fr; } }
.kicker {
  display: inline-flex; align-items: center; gap: 0.7rem; margin: 0 0 1.6rem;
  font: 400 0.74rem/1.65 var(--mono); letter-spacing: 0.28em; text-transform: uppercase; color: var(--accent);
}
.kicker::before { content: ""; flex: none; width: 28px; height: 1px; background: var(--season); }
.hero h1 {
  margin: 0 0 1.6rem; color: var(--text);
  font-family: var(--display); font-weight: 500; font-size: clamp(3.4rem, 10vw, 8.4rem);
  line-height: 0.95; letter-spacing: 0.01em; text-transform: uppercase;
}
.hero h1 .second {
  display: block; width: fit-content; color: var(--accent); font-weight: 300;
  background: var(--name-fill); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
/* The season's name, huge and outlined like drafting letters, behind the
   drawing. It's sized to the drawing's width whatever the word's length. */
.season-word {
  position: absolute; right: 0; top: -0.14em; z-index: 0; pointer-events: none; user-select: none; white-space: nowrap;
  font: 600 clamp(7rem, 16vw, 18rem)/0.8 var(--display); letter-spacing: 0.01em; text-transform: uppercase;
  font-size: calc(124cqw / (var(--len, 4) * 0.52));
  color: transparent; -webkit-text-stroke: 1.5px color-mix(in srgb, var(--season) 45%, transparent);
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--season) 17%, transparent) 0 1px, transparent 1px 9px);
  -webkit-background-clip: text; background-clip: text;
}
@media (max-width: 880px) { .season-word { font-size: calc(104cqw / (var(--len, 4) * 0.52)); right: -0.02em; } }
.lede { max-width: 38ch; margin: 0 0 2.4rem; font-size: 1.18rem; line-height: 1.55; color: var(--text-soft); text-wrap: pretty; }
.cta-row { display: flex; gap: 1rem; flex-wrap: wrap; }
.btn {
  display: inline-flex; align-items: center; gap: 0.7rem; padding: 0.95rem 1.5rem;
  border: 1px solid var(--line); border-radius: 2px; background: transparent; color: var(--text);
  font: 400 0.78rem/1.65 var(--mono); letter-spacing: 0.18em; text-transform: uppercase;
  transition: background 240ms ease, border-color 240ms ease, color 240ms ease;
}
.btn .arrow { transition: transform 240ms cubic-bezier(0.6, 0, 0.2, 1); }
.btn:hover { background: var(--text); color: var(--bg); border-color: var(--text); }
.btn:hover .arrow { transform: translateX(4px); }
/* The main button keeps the bright season colour in both looks. */
.btn--primary { background: var(--season); border-color: var(--season); color: #14100a; }
.btn--primary:hover { background: var(--text); color: var(--bg); border-color: var(--text); }

.art { position: relative; container-type: inline-size; width: clamp(280px, 36vw, 460px); justify-self: end; }
.art .orbit, .art .edition-line { position: relative; z-index: 1; }
@media (max-width: 880px) { .art { justify-self: start; width: min(100%, 380px); } }
.orbit { width: 100%; aspect-ratio: 1; }
/* In the light look the drawing keeps its night sky: a navy panel behind it
   and the season's name, with the dark look's colours inside. */
:root[data-theme="light"] .art { isolation: isolate; overflow: hidden; }
:root[data-theme="light"] .art::before {
  content: ""; position: absolute; left: 0; top: 0; z-index: -1; width: 100%; aspect-ratio: 1; border-radius: 2px;
  background-color: #0c1622;
  background-image:
    radial-gradient(110% 70% at 75% 0%, color-mix(in srgb, var(--season) 16%, transparent), transparent 70%),
    linear-gradient(rgba(120, 160, 200, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(120, 160, 200, 0.06) 1px, transparent 1px);
  background-size: auto, 24px 24px, 24px 24px;
}
:root[data-theme="light"] .orbit, :root[data-theme="light"] .season-word {
  --bg: #0c1622; --line: #2c4258; --line-soft: #1d3044;
  --text: #eef3f7; --text-soft: #b3c3d1; --muted: #71879c; --accent: var(--season);
}
/* Under the drawing, the season it shows. It doubles as a quiet switch to the
   other seasons: it looks like plain text until it's pointed at. */
.edition-line {
  display: flex; align-items: center; gap: 0.7rem; margin: 0.8rem 0 0;
  font: 400 0.75rem/1.5 var(--mono); letter-spacing: 0.24em; text-transform: uppercase;
}
.edition-line::before { content: ""; flex: none; width: 28px; height: 1px; background: var(--season); }
.edition {
  font: inherit; letter-spacing: inherit; text-transform: inherit; text-align: left; color: var(--accent);
  margin: 0; padding: 0.3rem 0; border: 0; background: none; cursor: pointer;
  text-decoration: underline dotted transparent; text-underline-offset: 3px;
  transition: text-decoration-color 200ms ease;
}
.edition::after { content: " \21BB"; opacity: 0; transition: opacity 200ms ease; }
.edition:hover, .edition:focus-visible { text-decoration-color: currentColor; }
.edition:hover::after, .edition:focus-visible::after { opacity: 0.8; }

/* ---------- where to: the résumé and the photos ---------- */
.intro-strip { border-top: 1px solid var(--line-soft); padding-block: clamp(3rem, 6vw, 5rem); }
.intro-grid {
  display: grid; grid-template-columns: minmax(0, 220px) 1fr; align-items: start;
  gap: clamp(1.5rem, 4vw, 4rem); margin-bottom: clamp(2rem, 4vw, 3rem);
}
@media (max-width: 720px) { .intro-grid { grid-template-columns: 1fr; gap: 1rem; } }
.section-label { margin: 0; font: 400 0.72rem/1.65 var(--mono); letter-spacing: 0.24em; text-transform: uppercase; color: var(--muted); }
.section-label .num { color: var(--accent); margin-right: 0.55rem; }
.strip-text {
  margin: 0; max-width: 36ch; color: var(--text);
  font-family: var(--display); font-weight: 320; font-size: clamp(1.3rem, 2.4vw, 1.85rem); line-height: 1.4;
}
.vols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 1.5rem; }
.vol-card {
  display: flex; flex-direction: column; gap: 0.6rem; padding: 1.6rem 1.6rem 1.5rem;
  border: 1px solid var(--line); border-radius: 2px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  transition: border-color 240ms ease, transform 240ms ease;
}
.vol-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.vol-card .num { font: 400 0.72rem/1.65 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent); }
.vol-card h3 {
  margin: 0; font-family: var(--display); font-weight: 500; font-size: clamp(1.8rem, 3vw, 2.4rem);
  line-height: 1.05; letter-spacing: 0.02em; text-transform: uppercase;
}
.vol-card p { margin: 0; max-width: 46ch; color: var(--text-soft); font-size: 0.98rem; line-height: 1.6; }
.thumbs { display: flex; gap: 6px; height: clamp(64px, 9vw, 96px); margin-top: 0.4rem; overflow: hidden; }
.thumb { position: relative; flex-basis: 0; min-width: 0; background: var(--surface); overflow: hidden; }
.thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The Socials card's list of profiles (the page itself has the links). */
.handles { display: grid; margin-top: 0.4rem; font: 400 0.82rem/1.5 var(--mono); letter-spacing: 0.04em; color: var(--text-soft); }
.handles > span { display: flex; flex-wrap: wrap; column-gap: 0.9rem; padding-block: 0.45rem; border-top: 1px solid var(--line-soft); }
.handles > span:last-child { border-bottom: 1px solid var(--line-soft); }
.handles .site { min-width: 5.8rem; color: var(--text); font-size: 0.72rem; line-height: 1.7; letter-spacing: 0.16em; text-transform: uppercase; }
@media (max-width: 360px) { .handles > span { column-gap: 0.6rem; } .handles .site { min-width: 5rem; } }
.vol-card .go {
  display: inline-flex; align-items: center; gap: 0.6rem; margin-top: auto; padding-top: 0.8rem;
  font: 400 0.78rem/1.65 var(--mono); letter-spacing: 0.2em; text-transform: uppercase; color: var(--accent);
}
.vol-card .go .arrow { transition: transform 240ms cubic-bezier(0.6, 0, 0.2, 1); }
.vol-card:hover .go .arrow { transform: translateX(5px); }

/* ---------- footer ---------- */
.site-footer {
  margin-top: 3rem; padding-block: 2.5rem calc(2rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line-soft); text-align: center;
  font: 400 0.74rem/1.65 var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
}
.site-footer .container { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.7rem 1.6rem; }
@media (min-width: 700px) { .site-footer .container > * { white-space: nowrap; } }
@media (max-width: 560px) { .site-footer { letter-spacing: 0.09em; } .site-footer .container { gap: 0.6rem 1.1rem; } }
.site-footer a { color: var(--text-soft); border-bottom: 1px solid transparent; transition: color 240ms ease, border-color 240ms ease; }
.site-footer a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ---------- the drawing (tools/tower.py draws it) ---------- */
.pylon-svg { width: 100%; height: 100%; overflow: hidden; }
.pylon-svg .leg { stroke: var(--steel); stroke-width: 1.2; }
.pylon-svg .arm { stroke: var(--steel); stroke-width: 1.1; }
.pylon-svg .brace { stroke: var(--steel); stroke-width: 0.55; opacity: 0.7; }
.pylon-svg .string, .pylon-svg .disc { stroke: var(--accent-2); stroke-width: 1.1; }
.pylon-svg .disc { stroke-width: 0.9; }
.pylon-svg .wire { fill: none; stroke: var(--steel-hot); stroke-width: 0.9; }
.pylon-svg .gwire { fill: none; stroke: var(--steel); stroke-width: 0.7; }
.pylon-svg .clamp { fill: var(--accent-2); }
.pylon-svg .clamp-gw { fill: var(--steel); }
.pylon-svg .far { opacity: 0.55; }
.pylon-svg .span.back { opacity: 0.8; }
.pylon-svg .ground { stroke: var(--line); stroke-width: 0.8; }
.pylon-svg .ground.far { opacity: 0.5; }
/* The current: a short dash riding two of the conductors (tools/tower.py writes
   its keyframes at the end of this file). The second runs half a cycle behind. */
.pylon-svg .charge rect { fill: var(--accent); }
.pylon-svg .charge-1 { animation: charge-1 8s linear infinite; }
.pylon-svg .charge-2 { animation: charge-2 8s linear infinite -4s; }

/* Only this season's pieces show. */
.scene .season { display: none; }
:root[data-season="fall"] .scene .s-fall,
:root[data-season="winter"] .scene .s-winter,
:root[data-season="spring"] .scene .s-spring,
:root[data-season="summer"] .scene .s-summer { display: inline; }
/* The pieces that aren't showing don't animate either, and nothing in the
   drawing moves while it's scrolled out of sight (home.js marks it "still"). */
:root:not([data-season="fall"]) .scene .s-fall *,
:root:not([data-season="winter"]) .scene .s-winter *,
:root:not([data-season="spring"]) .scene .s-spring *,
:root:not([data-season="summer"]) .scene .s-summer *,
:root:not([data-holiday="halloween"]) .scene .h-halloween,
:root:not([data-holiday="halloween"]) .scene .h-halloween *,
:root:not([data-holiday="lights"]) .scene .h-lights * { animation: none; }
.scene.still, .scene.still * { animation-play-state: paused !important; }

/* Fall: harvest moon, geese heading south, leaves coming down. */
.scene .moon { fill: rgba(255, 107, 44, 0.08); stroke: #ff6b2c; stroke-width: 1.2; }
.scene .moon-mark { fill: none; stroke: rgba(255, 107, 44, 0.45); stroke-width: 0.8; }
.scene .geese use { fill: none; stroke: var(--text-soft); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.scene .geese { animation: migrate 46s linear infinite; animation-delay: -15s; }
.scene .lf-a { fill: #ff6b2c; }
.scene .lf-b { fill: #f7b500; }
.scene .lf-c { fill: #c2410c; }
.scene .vein { fill: none; stroke: rgba(12, 22, 34, 0.55); stroke-width: 0.8; }
.scene .pile use { opacity: 0.9; }
.scene .moon { filter: drop-shadow(0 0 10px rgba(255, 107, 44, 0.55)); }
.scene .pumpkin ellipse { fill: #e8641f; stroke: #8f300c; stroke-width: 0.9; }
.scene .pumpkin .rib { fill: none; stroke: #b2440f; stroke-width: 0.8; }
.scene .pumpkin .stem { fill: #6e8a3c; stroke: none; }
.scene .jack { fill: #ffd34d; filter: drop-shadow(0 0 3px rgba(255, 211, 77, 0.9)); animation: flicker 2.8s ease-in-out infinite; }
.scene .bat use { fill: #05080c; stroke: rgba(255, 150, 90, 0.85); stroke-width: 0.7; }
.scene .bat { animation: bat-fly var(--d, 9s) ease-in-out infinite alternate; animation-delay: var(--delay, 0s); transform: translate(var(--x), var(--y)); }
/* The wings flap from the bat's middle (its own 0,0). Moving a group, not the
   shape itself, lets the graphics card do it. */
.scene .bat .wing { transform-origin: 0 0; animation: flap 0.32s ease-in-out infinite alternate; }
.b1 { --x: 96px;  --y: 100px; --d: 9s;  --delay: -2s; }
.b2 { --x: 178px; --y: 150px; --d: 11s; --delay: -6s; }
.b3 { --x: 40px;  --y: 40px;  --d: 8s;  --delay: -4s; }
/* ...leaves resting on the arms, round bales and a corn shock in the field. */
.scene .bale { fill: #3b2a12; stroke: #d9a441; stroke-width: 1; }
.scene .bale-roll { fill: none; stroke: #b8862f; stroke-width: 0.7; }
.scene .stalk { fill: none; stroke: #c9a24a; stroke-width: 0.8; stroke-linecap: round; stroke-linejoin: round; }
.scene .stalk-leaf { fill: none; stroke: #a8873a; stroke-width: 0.9; stroke-linecap: round; }
.scene .twine { stroke: #c2410c; stroke-width: 1.6; }
/* October: a black cat on the hay, a web in the tower, a spider letting itself down. */
.scene .cat path, .scene .spider ellipse, .scene .spider circle { fill: #05080c; stroke: rgba(255, 150, 90, 0.85); stroke-width: 0.55; }
.scene .cat .tail { fill: none; stroke: #05080c; stroke-width: 1.7; stroke-linecap: round; }
.scene .cat .eye { fill: #ffd34d; stroke: none; filter: drop-shadow(0 0 1.5px rgba(255, 211, 77, 0.95)); animation: flicker 4s ease-in-out infinite; }
.scene .web { fill: none; stroke: rgba(238, 243, 247, 0.5); stroke-width: 0.4; }
.scene .spider .legs { fill: none; stroke: rgba(255, 150, 90, 0.85); stroke-width: 0.5; stroke-linejoin: round; }
.scene .thread { stroke: rgba(238, 243, 247, 0.6); stroke-width: 0.4; transform-box: fill-box; transform-origin: 50% 0; animation: thread 5s ease-in-out infinite alternate; }
.scene .dangle { animation: dangle 5s ease-in-out infinite alternate; }
.scene .hol { display: none; }
:root[data-season="fall"][data-holiday="halloween"] .scene .h-halloween,
:root[data-season="winter"][data-holiday="lights"] .scene .h-lights { display: inline; }
.scene .bulb { filter: drop-shadow(0 0 3px currentColor); animation: twinkle 1.8s ease-in-out infinite; }
.scene .l-red { fill: #ff5a5a; color: #ff5a5a; }
.scene .l-green { fill: #7fd18b; color: #7fd18b; }
.scene .l-gold { fill: #f7b500; color: #f7b500; }
.scene .l-blue { fill: #6fc2e8; color: #6fc2e8; }
.scene .tw1 { animation-delay: -0.4s; } .scene .tw2 { animation-delay: -0.8s; }
.scene .tw3 { animation-delay: -1.2s; } .scene .tw4 { animation-delay: -1.6s; }

/* Winter: a cold moon, snow on the crossarms, flakes coming down;
   in December, lights strung along the top ground wire and a star on the peak. */
.scene .moon.cold { fill: rgba(111, 194, 232, 0.08); stroke: #6fc2e8; }
.scene .star { fill: #ffd34d; filter: drop-shadow(0 0 4px rgba(255, 211, 77, 0.9)); animation: twinkle 2.4s ease-in-out infinite; }
.scene .snowcap { fill: none; stroke: #eef3f7; stroke-width: 2.2; stroke-linecap: round; opacity: 0.85; }
.scene .icicle { fill: none; stroke: #b9e2f5; stroke-width: 0.9; stroke-linejoin: round; }
.scene .snowbank { fill: none; stroke: #eef3f7; stroke-width: 1.6; opacity: 0.55; }
.scene .s-winter .drift circle { fill: #eef3f7; }
/* ...pines in the snow, a snowman in a hard hat, a cardinal on the steel. */
.scene .pine { fill: #0f2a1f; stroke: #3d7a52; stroke-width: 0.7; stroke-linejoin: round; }
.scene .pine-snow { fill: none; stroke: #eef3f7; stroke-width: 1.4; stroke-linecap: round; opacity: 0.9; }
.scene .trunk { fill: #4a3520; }
.scene .snow-ball { fill: #dfe9f1; stroke: #9fc6dc; stroke-width: 0.7; }
.scene .stick { fill: none; stroke: #8a6a3c; stroke-width: 1; stroke-linecap: round; }
.scene .scarf { fill: #ff6b2c; }
.scene .hardhat { fill: #f7b500; }
.scene .hardhat-rib { stroke: #b88700; stroke-width: 0.8; }
.scene .coal { fill: #1a2430; }
.scene .carrot { fill: #ff8a2c; }
.scene .cardinal > * { fill: #d8322b; }
.scene .cardinal .wing, .scene .cardinal .tail { fill: #a3241e; }
.scene .cardinal .mask { fill: #14080a; }
.scene .cardinal .beak { fill: #f39a3c; }
/* December: a wreath where the bracing crosses, presents at the foot. */
.scene .wreath { fill: none; stroke: #2f7a43; stroke-width: 3.4; }
.scene .wreath-fir { fill: none; stroke: #5fbf73; stroke-width: 3.4; stroke-dasharray: 1.2 2.2; }
.scene .berry { fill: #ff5a5a; }
.scene .bow { fill: #d8322b; }
.scene .gift, .scene .gift-lid { stroke: rgba(12, 22, 34, 0.55); stroke-width: 0.5; }
.scene .g-red { fill: #c62f2f; }
.scene .g-green { fill: #2f7a43; }
.scene .g-blue { fill: #3d7fb0; }
.scene .ribbon { fill: none; stroke: #f7b500; stroke-width: 1.1; stroke-linejoin: round; }

/* Spring: a passing shower and birds on the line. */
.scene .cloud { fill: rgba(179, 195, 209, 0.06); stroke: var(--text-soft); stroke-width: 1; opacity: 0.7; }
.scene .perch { fill: var(--text-soft); }
.scene .grass { fill: none; stroke: #7fd18b; stroke-width: 1.1; stroke-linejoin: round; }
.scene .s-spring .drift line { stroke: #6fc2e8; stroke-width: 1; stroke-linecap: round; opacity: 0.7; }
/* ...a rainbow behind the shower, an osprey on its nest, wildflowers. */
.scene .rainbow { opacity: 0.5; }
.scene .rainbow path { fill: none; stroke-width: 2.6; }
.scene .rb-red { stroke: #ff5a5a; }
.scene .rb-orange { stroke: #ff9a3c; }
.scene .rb-yellow { stroke: #ffe066; }
.scene .rb-green { stroke: #7fd18b; }
.scene .rb-blue { stroke: #6fc2e8; }
.scene .rb-violet { stroke: #b58cf0; }
.scene .nest { fill: #3a2a14; stroke: #8a6a3c; stroke-width: 0.6; }
.scene .sticks { fill: none; stroke: #a07c46; stroke-width: 0.8; stroke-linecap: round; }
.scene .osprey .back { fill: #6b4e30; }
.scene .osprey .chest, .scene .osprey .head { fill: #eef3f7; }
.scene .osprey .stripe { fill: none; stroke: #2a1c10; stroke-width: 0.8; stroke-linecap: round; }
.scene .osprey .hook { fill: #1a2430; }
.scene .stem { fill: none; stroke: #4fae6a; stroke-width: 0.8; stroke-linecap: round; }
.scene .fl-pink { fill: #f4a7c0; }
.scene .fl-gold { fill: #ffe066; }
.scene .fl-white { fill: #eef3f7; }
.scene .fl-violet { fill: #b58cf0; }

/* Summer: a big sun and heat coming off the ground. */
.scene .sun { fill: #f7b500; opacity: 0.9; }
.scene .sun-rays path { fill: none; stroke: #f7b500; stroke-width: 1.4; stroke-linecap: round; }
.scene .sun-rays { transform-origin: 112px 96px; animation: spin 80s linear infinite; }
.scene .shimmer { fill: none; stroke: #f7b500; stroke-width: 0.9; opacity: 0.35; animation: shimmer 3.2s ease-in-out infinite; }
.scene .shimmer.h2 { animation-delay: 1.1s; }
.scene .shimmer.h3 { animation-delay: 2.2s; }
/* ...palmettos, and an afternoon storm. Lightning takes the ground wire at the
   peak every so often: two quick flashes, then nothing for nine seconds. */
.scene .palm-trunk { fill: none; stroke: #8a6a3c; stroke-width: 2.4; stroke-linecap: round; }
.scene .palm-boot { fill: none; stroke: #5e4526; stroke-width: 0.8; }
.scene .frond { fill: none; stroke: #4fae6a; stroke-width: 1; stroke-linecap: round; }
.scene .thunderhead { fill: rgba(179, 195, 209, 0.07); stroke: var(--text-soft); stroke-width: 1; opacity: 0.7; }
.scene .thunderhead-line { fill: none; stroke: var(--text-soft); stroke-width: 0.7; opacity: 0.4; }
.scene .bolt {
  fill: none; stroke: #ffe066; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 4px rgba(255, 224, 102, 0.9)); opacity: 0; animation: strike 9s linear infinite 2s;
}

/* Things that come down (leaves, snow, rain). Each has its own lane and pace;
   with reduced motion they hold still where they're drawn. */
.scene .drift { animation: fall var(--d, 12s) linear infinite; animation-delay: var(--delay, 0s); transform: translate(var(--x), var(--y)) rotate(var(--r, 0deg)); }
.f1 { --x: 60px;  --y: 150px; --r: 40deg;  --d: 13s; --delay: -2s;  --sway: 22px; --spin: 300deg; }
.f2 { --x: 130px; --y: 230px; --r: 120deg; --d: 11s; --delay: -7s;  --sway: -18px; --spin: -260deg; }
.f3 { --x: 190px; --y: 80px;  --r: 200deg; --d: 15s; --delay: -11s; --sway: 26px; --spin: 340deg; }
.f4 { --x: 245px; --y: 300px; --r: 300deg; --d: 12s; --delay: -4s;  --sway: -24px; --spin: 280deg; }
.f5 { --x: 320px; --y: 190px; --r: 80deg;  --d: 14s; --delay: -9s;  --sway: 20px; --spin: -320deg; }
.f6 { --x: 365px; --y: 110px; --r: 160deg; --d: 12.5s; --delay: -1s; --sway: -16px; --spin: 300deg; }
.f7 { --x: 25px;  --y: 270px; --r: 260deg; --d: 16s; --delay: -13s; --sway: 18px; --spin: 260deg; }
.f8 { --x: 100px; --y: 40px;  --r: 30deg;  --d: 14s; --delay: -5s;  --sway: 28px; --spin: -300deg; }
.f9 { --x: 280px; --y: 250px; --r: 210deg; --d: 13s; --delay: -10s; --sway: -22px; --spin: 340deg; }
.f10 { --x: 220px; --y: 160px; --r: 140deg; --d: 17s; --delay: -15s; --sway: 24px; --spin: -280deg; }
.s1 { --x: 40px;  --y: 60px;  --d: 9s;  --delay: -1s; --sway: 8px; }
.s2 { --x: 95px;  --y: 210px; --d: 11s; --delay: -6s; --sway: -6px; }
.s3 { --x: 150px; --y: 130px; --d: 8s;  --delay: -3s; --sway: 10px; }
.s4 { --x: 205px; --y: 280px; --d: 10s; --delay: -8s; --sway: -8px; }
.s5 { --x: 260px; --y: 40px;  --d: 9.5s; --delay: -5s; --sway: 7px; }
.s6 { --x: 300px; --y: 240px; --d: 12s; --delay: -10s; --sway: -9px; }
.s7 { --x: 340px; --y: 160px; --d: 8.5s; --delay: -2s; --sway: 9px; }
.s8 { --x: 375px; --y: 300px; --d: 10.5s; --delay: -7s; --sway: -7px; }
.s9 { --x: 20px;  --y: 330px; --d: 11.5s; --delay: -4s; --sway: 6px; }
.r1 { --x: 60px;  --y: 140px; --d: 1.3s; --delay: -0.2s; --sway: -8px; }
.r2 { --x: 120px; --y: 200px; --d: 1.1s; --delay: -0.7s; --sway: -8px; }
.r3 { --x: 175px; --y: 90px;  --d: 1.4s; --delay: -1s;   --sway: -8px; }
.r4 { --x: 90px;  --y: 260px; --d: 1.2s; --delay: -0.4s; --sway: -8px; }
.r5 { --x: 40px;  --y: 60px;  --d: 1.5s; --delay: -0.9s; --sway: -8px; }
.r6 { --x: 150px; --y: 300px; --d: 1.25s; --delay: -0.5s; --sway: -8px; }
/* Rain falls out of the cloud only, and doesn't need to fill the sky. */
.s-spring .drift { --top: 118px; }

@keyframes fall {
  0%   { transform: translate(var(--x), var(--top, -20px)) rotate(0deg); opacity: 0; }
  8%   { opacity: 1; }
  50%  { transform: translate(calc(var(--x) + var(--sway, 0px)), 170px) rotate(calc(var(--spin, 0deg) / 2)); }
  90%  { opacity: 1; }
  100% { transform: translate(calc(var(--x) - var(--sway, 0px) / 3), 350px) rotate(var(--spin, 0deg)); opacity: 0; }
}
@keyframes migrate {
  from { transform: translate(140px, 0); }
  to   { transform: translate(-380px, 30px); }
}
@keyframes flicker { 0%, 100% { opacity: 1; } 40% { opacity: 0.75; } 55% { opacity: 0.95; } 70% { opacity: 0.6; } }
@keyframes flap { from { transform: scaleY(1); } to { transform: scaleY(0.78) translateY(1px); } }
@keyframes bat-fly { from { transform: translate(var(--x), var(--y)); } to { transform: translate(calc(var(--x) + 46px), calc(var(--y) - 22px)); } }
@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes shimmer { 0%, 100% { opacity: 0.1; transform: translateY(0); } 50% { opacity: 0.4; transform: translateY(-3px); } }
@keyframes thread { from { transform: scaleY(1); } to { transform: scaleY(1.3); } }
@keyframes dangle { from { transform: translateY(0); } to { transform: translateY(7.2px); } }
@keyframes strike { 0%, 90% { opacity: 0; } 90.6% { opacity: 1; } 91.6% { opacity: 0.15; } 92.4% { opacity: 1; } 94.5%, 100% { opacity: 0; } }

/* ---------- the season's weather, across the whole page ---------- */
.weather { position: fixed; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.p {
  position: absolute; left: var(--x); top: 0; width: var(--size); height: var(--size); opacity: var(--o);
  will-change: transform; animation: p-fall var(--d) linear infinite; animation-delay: var(--delay);
}
.p-leaf { border-radius: 0 100% 0 100%; background: #ff6b2c; }
.p-leaf::after {
  content: ""; position: absolute; left: 50%; top: 8%; width: 1px; height: 120%;
  background: rgba(12, 22, 34, 0.45); transform: rotate(-45deg); transform-origin: top;
}
.p-leaf.c1 { background: #f7b500; }
.p-leaf.c2 { background: #c2410c; }
.p-snow { border-radius: 50%; background: #f3f8fc; box-shadow: 0 0 6px rgba(238, 243, 247, 0.7); }
:root[data-theme="light"] .p-snow { background: #b9cbdb; box-shadow: 0 0 4px rgba(90, 120, 150, 0.35); }
.p-petal { height: calc(var(--size) * 0.72); border-radius: 150% 0 150% 0; background: #f4a7c0; }
.p-petal.c1 { background: #ffd6e4; }
.p-petal.c2 { background: #e98aab; }
.p-firefly {
  top: var(--y); border-radius: 50%; background: #ffe066; box-shadow: 0 0 10px 3px rgba(255, 214, 77, 0.55);
  animation: p-wander var(--d) ease-in-out infinite alternate, p-glow 2.6s ease-in-out infinite;
  animation-delay: var(--delay), var(--delay);
}
:root[data-theme="light"] .p-firefly { background: #e0a800; box-shadow: 0 0 8px 2px rgba(224, 168, 0, 0.4); }
@keyframes p-fall {
  0%   { transform: translate(0, -8vh) rotate(0deg); }
  25%  { transform: translate(var(--sway), 22vh) rotate(calc(var(--spin) * 0.25)); }
  50%  { transform: translate(calc(var(--sway) * -0.4), 50vh) rotate(calc(var(--spin) * 0.5)); }
  75%  { transform: translate(calc(var(--sway) * 0.7), 78vh) rotate(calc(var(--spin) * 0.75)); }
  100% { transform: translate(0, 108vh) rotate(var(--spin)); }
}
@keyframes p-wander {
  0%   { transform: translate(0, 0); }
  50%  { transform: translate(var(--sway), calc(var(--sway) * -0.5)); }
  100% { transform: translate(calc(var(--sway) * -0.6), calc(var(--sway) * 0.4)); }
}
@keyframes p-glow { 0%, 100% { opacity: 0.12; } 50% { opacity: var(--o); } }

/* ---------- entrance ---------- */
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
.reveal { opacity: 0; animation: rise 900ms cubic-bezier(0.2, 0.7, 0.2, 1) forwards; }
.reveal.d1 { animation-delay: 80ms; }
.reveal.d2 { animation-delay: 220ms; }
.reveal.d3 { animation-delay: 360ms; }
.reveal.d4 { animation-delay: 500ms; }
.reveal.d5 { animation-delay: 640ms; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .reveal { opacity: 1; }
  .scene .geese { transform: translate(-60px, 10px); }
  .scene .bolt { opacity: 0.85; }   /* the strike held still, no flashing */
  .p { top: var(--y); }
}

/* The charges' rides along the conductors (written by tools/tower.py). */
/* charges:begin */
@keyframes charge-1 {
  0% { transform: translate(130px, 266.5px) rotate(-8.7deg); }
  3.3% { transform: translate(149.8px, 263px) rotate(-11.1deg); }
  6.7% { transform: translate(169.6px, 258.7px) rotate(-13.5deg); }
  10% { transform: translate(188.8px, 253.7px) rotate(-15.8deg); }
  13.3% { transform: translate(208px, 247.8px) rotate(-18.1deg); }
  16.7% { transform: translate(227.2px, 241.2px) rotate(-20.2deg); }
  20% { transform: translate(245.8px, 233.9px) rotate(-22.3deg); }
  23.2% { transform: translate(263.8px, 226.2px) rotate(-24.2deg); }
  26.5% { transform: translate(281.8px, 217.7px) rotate(-26.1deg); }
  29.9% { transform: translate(299.8px, 208.5px) rotate(-27.9deg); }
  33.3% { transform: translate(318.6px, 201.3px) rotate(-11.4deg); }
  36.6% { transform: translate(338.1px, 197.2px) rotate(-12.4deg); }
  39.9% { transform: translate(357.5px, 192.7px) rotate(-13.5deg); }
  43.2% { transform: translate(377px, 187.9px) rotate(-14.5deg); }
  46.5% { transform: translate(396.4px, 182.7px) rotate(-15.5deg); }
  49.9% { transform: translate(415.8px, 177.1px) rotate(-16.6deg); }
  100% { transform: translate(415.8px, 177.1px) rotate(-16.6deg); }
}
@keyframes charge-2 {
  0% { transform: translate(86px, 286.5px) rotate(-6.9deg); }
  3.3% { transform: translate(105.9px, 283.5px) rotate(-10.1deg); }
  6.6% { transform: translate(125.4px, 279.5px) rotate(-13.3deg); }
  10% { transform: translate(144.9px, 274.3px) rotate(-16.3deg); }
  13.3% { transform: translate(164px, 268.2px) rotate(-19.2deg); }
  16.6% { transform: translate(182.6px, 261.2px) rotate(-22deg); }
  20% { transform: translate(201.1px, 253.2px) rotate(-24.6deg); }
  23.3% { transform: translate(219.3px, 244.4px) rotate(-27.1deg); }
  26.6% { transform: translate(238.3px, 240.2px) rotate(-10.3deg); }
  29.9% { transform: translate(257.9px, 236.4px) rotate(-11.7deg); }
  33.2% { transform: translate(277.5px, 232.1px) rotate(-13.1deg); }
  36.5% { transform: translate(297.1px, 227.3px) rotate(-14.5deg); }
  39.9% { transform: translate(316.7px, 222px) rotate(-15.8deg); }
  43.1% { transform: translate(335.4px, 216.5px) rotate(-17.1deg); }
  46.6% { transform: translate(355px, 210.2px) rotate(-18.5deg); }
  49.8% { transform: translate(373.8px, 203.7px) rotate(-19.7deg); }
  53.2% { transform: translate(392.5px, 196.7px) rotate(-20.9deg); }
  56.5% { transform: translate(411.3px, 189.3px) rotate(-22.2deg); }
  100% { transform: translate(411.3px, 189.3px) rotate(-22.2deg); }
}
/* charges:end */
