/* =============================================================
   HALLOWEEN SKIN — seasonal, temporary.
   Loaded after custom.css / sec-tty.css. Overrides the design
   tokens and adds a few spooky extras. Zero new dependencies.

   TO REVERT THE SITE:
   1. Delete this file and js/halloween.js (the clickable spider).
   2. Remove the <link href="/css/halloween.css"> line and the
      <script src="/js/halloween.js"> line (both carry a "seasonal skin"
      comment) from template.html, sponsor/template.html,
      about/index.html and colophon/index.html.
   3. In colophon/index.html also remove the css/halloween.css line in
      the dpkg block and the "Right now it is wearing a Halloween skin"
      paragraph, or the colophon will describe a skin that is gone.
   4. js/sec-tty.js needs no change: the boo / trick / treat commands
      and the seasonal boot line switch themselves off when this
      stylesheet is not linked. Removing the SPOOKY block is optional.
   Keep the token refactor in css/custom.css and css/sec-tty.css; it is
   visually a no-op without this file and makes future skins cheap.
   If the skin was its own git commit, `git revert <sha>` does all of it.
   ============================================================= */

/* ─── 1. TOKENS ─────────────────────────────────────────────── */
:root {
    /* Ground: purple-black instead of blue-black */
    --secdsm-bg:        #070409;
    --secdsm-surface:   #0e0a14;
    --secdsm-surface-2: #16101f;
    --secdsm-ink:       #070409;
    --secdsm-panel:     #0e0a14;
    --secdsm-paper:     #070409;
    --secdsm-bg-rgb:    7, 4, 9;
    --secdsm-map-bg:    #0a0710;

    /* Text stays near-neutral so paragraphs remain readable */
    --secdsm-white: #f3ebf7;
    --secdsm-text:  #cfc5d6;
    --secdsm-muted: #736580;
    --secdsm-line:        rgba(214, 190, 255, 0.08);
    --secdsm-line-bright: rgba(214, 190, 255, 0.16);

    /* Primary accent: cyan → pumpkin */
    --secdsm-cyan:        #ff7a1a;
    --secdsm-cyan-rgb:    255, 122, 26;
    --secdsm-cyan-dim:    rgba(255, 122, 26, 0.10);
    --secdsm-cyan-glow:   rgba(255, 122, 26, 0.22);
    --secdsm-cyan-bright: #ff9640;

    /* Secondary: magenta → violet */
    --secdsm-magenta:     #a63dff;
    --secdsm-magenta-rgb: 166, 61, 255;
    --secdsm-magenta-dim: rgba(166, 61, 255, 0.12);

    /* Toxic green stays — it owns the terminal now */
    --secdsm-green:     #39ff14;
    --secdsm-green-rgb: 57, 255, 20;
    --secdsm-green-dim: rgba(57, 255, 20, 0.10);

    /* Timestamps / kickers: amber → bone */
    --secdsm-amber:     #e9dcc3;
    --secdsm-amber-rgb: 233, 220, 195;
    --secdsm-amber-dim: rgba(233, 220, 195, 0.10);

    --secdsm-alert-info-text:   #ffb27a;
    --secdsm-alert-danger-text: #d9adff;

    /* Legacy aliases */
    --secdsm-teal:   #ff7a1a;
    --secdsm-red:    #a63dff;
    --secdsm-yellow: #e9dcc3;
}

/* ─── 2. HERO — cobweb + fog ────────────────────────────────── */
.secdsm-hero {
    background:
        radial-gradient(ellipse 60% 50% at 15% 60%, rgba(var(--secdsm-magenta-rgb), 0.12) 0%, transparent 70%),
        radial-gradient(ellipse 50% 40% at 85% 25%, rgba(var(--secdsm-cyan-rgb), 0.09) 0%, transparent 60%),
        radial-gradient(ellipse 40% 60% at 50% 90%, rgba(var(--secdsm-green-rgb), 0.04) 0%, transparent 50%),
        var(--secdsm-bg);
}

/* Cobweb, top-right corner. Inline SVG, no request. Six spokes from the
   corner every 18°; rings at r=38/74/112/152 are chains of quadratic
   curves whose control points sit 10% closer to the corner so the strands
   sag between spokes; the outer frame at r=200 joins the spoke tips with
   straight strands. js/halloween.js walks the spider along this exact
   geometry, so keep the two in sync if you redraw it. */
.secdsm-hero {
    /* Web width drives the spider's position too (js/halloween.js). */
    --secdsm-web-w: min(44vw, 420px);
}

.secdsm-hero::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: var(--secdsm-web-w);
    aspect-ratio: 1;
    pointer-events: none;
    opacity: 0.26;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200' fill='none' stroke='%23e9dcc3' stroke-width='0.9' stroke-linecap='round' stroke-linejoin='round'><path d='M200 0V200M200 0L138.2 190.2M200 0L82.4 161.8M200 0L38.2 117.6M200 0L9.8 61.8M200 0H0'/><path d='M200 38Q194.7 33.8 188.3 36.1Q184.5 30.5 177.7 30.7Q175.8 24.2 169.3 22.3Q169.5 15.5 163.9 11.7Q166.2 5.3 162 0'/><path d='M200 74Q189.6 65.8 177.1 70.4Q169.8 59.3 156.5 59.9Q152.9 47.1 140.1 43.5Q140.7 30.2 129.6 22.9Q134.2 10.4 126 0'/><path d='M200 112Q184.3 99.6 165.4 106.5Q154.2 89.8 134.1 90.6Q128.7 71.3 109.4 65.9Q110.2 45.8 93.5 34.6Q100.4 15.7 88 0'/><path d='M200 152Q178.7 135.2 153 144.6Q137.9 121.9 110.6 123Q103.3 96.7 77 89.4Q78.1 62.1 55.4 47Q64.8 21.3 48 0'/><path d='M200 200L138.2 190.2L82.4 161.8L38.2 117.6L9.8 61.8L0 0' stroke-width='1.1'/></svg>");
}

/* The spider. A real <button> injected by js/halloween.js so it can be
   clicked; hangs from the outer ring where the second spoke meets it
   (138.2, 190.2 in the web's 200×200 space). Click: scurries up the
   thread, waits, drops back with a bounce. */
.secdsm-spider {
    --secdsm-spider-w: calc(var(--secdsm-web-w) * 0.12);
    --secdsm-thread:   calc(var(--secdsm-web-w) * 0.22);
    /* Anchor in the web's 200×200 unit space; js/halloween.js moves these
       when the spider goes for a walk. --secdsm-move is the transition
       time for one leg of a walk (0 when idle so resizes are instant). */
    --secdsm-ax: 138.2;
    --secdsm-ay: 190.2;
    --secdsm-move: 0s;
    position: absolute;
    z-index: 2;
    top: calc(var(--secdsm-web-w) * var(--secdsm-ay) / 200);
    right: calc(var(--secdsm-web-w) * (200 - var(--secdsm-ax)) / 200 - var(--secdsm-spider-w) / 2);
    width: var(--secdsm-spider-w);
    height: calc(var(--secdsm-thread) + var(--secdsm-spider-w) * 24 / 28);
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--secdsm-amber);
    opacity: 0.6;
    cursor: pointer;
    transform-origin: 50% 0;
    transition:
        opacity 0.2s,
        top   var(--secdsm-move) linear,
        right var(--secdsm-move) linear;
    -webkit-tap-highlight-color: transparent;
}

/* Behind the hero content (used while hiding behind the Next Run card).
   The hero is its own stacking context so the fog can sit at -1 and the
   spider at 0 stays above the web but under the card. */
.secdsm-hero { isolation: isolate; }
.secdsm-hero::after { z-index: -1; }
.secdsm-spider.is-behind { z-index: 0; }

/* Zero-size probe: JS reads its width to learn the rendered web size */
.secdsm-web-probe {
    position: absolute;
    top: 0;
    left: 0;
    width: var(--secdsm-web-w);
    height: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Bigger hit area than the drawing, mostly for thumbs */
.secdsm-spider::after {
    content: "";
    position: absolute;
    inset: -12px -14px -14px;
}

.secdsm-spider:hover,
.secdsm-spider:focus-visible { opacity: 0.95; }

.secdsm-spider:focus-visible {
    outline: 1px solid var(--secdsm-cyan);
    outline-offset: 6px;
    border-radius: 2px;
}

.secdsm-spider-thread {
    position: absolute;
    top: 0;
    left: 50%;
    width: 1px;
    height: var(--secdsm-thread);
    background: currentColor;
    opacity: 0.7;
    transform-origin: 50% 0;
    transition: height var(--secdsm-move) ease-in-out;
}

.secdsm-spider-body {
    position: absolute;
    top: var(--secdsm-thread);
    left: 0;
    width: 100%;
    height: auto;
    display: block;
    overflow: visible;   /* legs poke past the viewBox mid-flail */
    transform-origin: 50% 40%;
    transition: top var(--secdsm-move) ease-in-out, transform 0.25s ease-out;
}

/* The spin reaction is a rotateY, so give it a little depth */
.secdsm-spider { perspective: 160px; }

.secdsm-spider-eyes {
    fill: var(--secdsm-bg);
    transition: transform 0.12s ease-out;
}

/* Reduced motion: no scurry animation, the spider just retreats up the
   thread for a moment and reappears. */
.secdsm-spider.is-startled .secdsm-spider-body { transform: translateY(calc(-1 * var(--secdsm-thread))); }
.secdsm-spider.is-startled .secdsm-spider-thread { transform: scaleY(0.02); }

/* Ground fog drifting across the bottom of the hero. */
.secdsm-hero::after {
    content: "";
    position: absolute;
    left: -20%;
    right: -20%;
    bottom: -10%;
    height: 55%;
    pointer-events: none;
    background:
        radial-gradient(ellipse 45% 60% at 20% 100%, rgba(var(--secdsm-magenta-rgb), 0.14), transparent 70%),
        radial-gradient(ellipse 50% 55% at 60% 100%, rgba(233, 220, 195, 0.06), transparent 70%),
        radial-gradient(ellipse 40% 50% at 90% 100%, rgba(var(--secdsm-green-rgb), 0.06), transparent 70%);
    filter: blur(28px);
}

/* Keep hero content above the web and fog on every page. The home hero's
   .secdsm-hero-layout already has this; the about and sponsor hero grids
   have no position of their own and would otherwise sit under the pseudo-
   elements, which paint after in-flow content. */
.secdsm-hero > .container { position: relative; z-index: 1; }

/* ─── 3. THE MEMORABLE THING — neon title flicker ──────────── */
.secdsm-display-accent {
    -webkit-text-stroke: 2px var(--secdsm-cyan);
    text-shadow:
        0 0 12px rgba(var(--secdsm-cyan-rgb), 0.45),
        0 0 60px rgba(var(--secdsm-cyan-rgb), 0.30);
}

@media (prefers-reduced-motion: no-preference) {
    .secdsm-display-accent {
        animation: secdsm-neon-flicker 11s linear 0.8s infinite;
    }

    .secdsm-hero::after {
        animation: secdsm-fog-drift 38s ease-in-out infinite alternate;
    }

    /* Fired by the `trick` console command: body gets .secdsm-glitch for ~1.4s */
    body.secdsm-glitch .secdsm-shell {
        animation: secdsm-glitch 1.4s steps(2, jump-none) 1;
    }

    /* Spider idles with a slow sway on its thread; a click runs it up. */
    .secdsm-spider {
        animation: secdsm-spider-sway 7s ease-in-out infinite alternate;
    }
    .secdsm-spider.is-startled .secdsm-spider-body {
        transform: none;
        animation: secdsm-spider-run 1.8s cubic-bezier(0.3, 0.9, 0.3, 1) 1 both;
    }
    .secdsm-spider.is-startled .secdsm-spider-thread {
        transform: none;
        animation: secdsm-spider-thread 1.8s cubic-bezier(0.3, 0.9, 0.3, 1) 1 both;
    }
    .secdsm-spider.is-startled .secdsm-spider-legs,
    .secdsm-spider.is-bungee .secdsm-spider-legs {
        animation: secdsm-spider-legs 0.12s linear 6 alternate;
        transform-origin: 50% 45%;
    }
    .secdsm-spider.is-nervous .secdsm-spider-legs {
        animation: secdsm-spider-legs 0.1s linear 4 alternate;
        transform-origin: 50% 45%;
    }

    /* Crawling (walk / hide excursions): legs go, sway stops */
    .secdsm-spider.is-walking { animation: none; }
    .secdsm-spider.is-walking .secdsm-spider-legs {
        animation: secdsm-spider-legs 0.14s linear infinite alternate;
        transform-origin: 50% 45%;
    }

    /* Bungee: drops well past its rest point, thread stretches, bounces back */
    .secdsm-spider.is-bungee .secdsm-spider-body {
        animation: secdsm-spider-bungee 2.2s cubic-bezier(0.34, 1.4, 0.4, 1) 1 both;
    }
    .secdsm-spider.is-bungee .secdsm-spider-thread {
        animation: secdsm-spider-bungee-thread 2.2s cubic-bezier(0.34, 1.4, 0.4, 1) 1 both;
    }

    /* Spin: twirls on the thread; legs flail; the whole web wobbles */
    .secdsm-spider.is-spinning .secdsm-spider-body {
        animation: secdsm-spider-spin 1.6s ease-in-out 1 both;
        transform-origin: 50% 0;
    }
    .secdsm-spider.is-spinning .secdsm-spider-legs {
        animation: secdsm-spider-legs 0.08s linear 14 alternate;
        transform-origin: 50% 45%;
    }
    .secdsm-hero.is-shaken::before {
        animation: secdsm-web-shake 0.65s ease-out 1;
        transform-origin: 100% 0;
    }

    /* Peek: an unprompted little dip and climb, every 30–60s */
    .secdsm-spider.is-peeking .secdsm-spider-body {
        animation: secdsm-spider-peek 1.8s ease-in-out 1 both;
    }
    .secdsm-spider.is-peeking .secdsm-spider-thread {
        animation: secdsm-spider-peek-thread 1.8s ease-in-out 1 both;
    }
}

@keyframes secdsm-spider-bungee {
    0%   { transform: translateY(0); }
    10%  { transform: translateY(calc(var(--secdsm-thread) * -0.08)); }
    38%  { transform: translateY(calc(var(--secdsm-thread) * 1.7)); }
    58%  { transform: translateY(calc(var(--secdsm-thread) * 0.55)); }
    72%  { transform: translateY(calc(var(--secdsm-thread) * 1.05)); }
    84%  { transform: translateY(calc(var(--secdsm-thread) * 0.75)); }
    100% { transform: translateY(0); }
}

@keyframes secdsm-spider-bungee-thread {
    0%   { transform: scaleY(1); }
    10%  { transform: scaleY(0.92); }
    38%  { transform: scaleY(2.7); }
    58%  { transform: scaleY(1.55); }
    72%  { transform: scaleY(2.05); }
    84%  { transform: scaleY(1.75); }
    100% { transform: scaleY(1); }
}

@keyframes secdsm-spider-spin {
    0%   { transform: rotateY(0) translateY(0); }
    15%  { transform: rotateY(0) translateY(calc(var(--secdsm-spider-w) * -0.15)); }
    75%  { transform: rotateY(1080deg) translateY(0); }
    88%  { transform: rotateY(1060deg) translateY(calc(var(--secdsm-spider-w) * 0.1)); }
    100% { transform: rotateY(1080deg) translateY(0); }
}

@keyframes secdsm-web-shake {
    0%   { transform: rotate(0) scale(1); }
    20%  { transform: rotate(-1.4deg) scale(1.01); }
    45%  { transform: rotate(1.1deg) scale(0.995); }
    70%  { transform: rotate(-0.5deg) scale(1.004); }
    100% { transform: rotate(0) scale(1); }
}

@keyframes secdsm-spider-peek {
    0%   { transform: translateY(0); }
    45%  { transform: translateY(calc(var(--secdsm-thread) * 0.4)); }
    60%  { transform: translateY(calc(var(--secdsm-thread) * 0.38)); }
    100% { transform: translateY(0); }
}

@keyframes secdsm-spider-peek-thread {
    0%   { transform: scaleY(1); }
    45%  { transform: scaleY(1.4); }
    60%  { transform: scaleY(1.38); }
    100% { transform: scaleY(1); }
}

@keyframes secdsm-spider-sway {
    from { transform: rotate(-2.5deg); }
    to   { transform: rotate(2.5deg); }
}

/* Runs up (0–22%), hides at the top (22–58%), drops (58–80%), bounces
   past the rest point and settles (80–100%). */
@keyframes secdsm-spider-run {
    0%   { transform: translateY(0); }
    6%   { transform: translateY(calc(var(--secdsm-thread) * 0.06)) skewX(6deg); }
    22%  { transform: translateY(calc(-1 * var(--secdsm-thread))) skewX(0); }
    58%  { transform: translateY(calc(-1 * var(--secdsm-thread))); }
    80%  { transform: translateY(calc(var(--secdsm-spider-w) * 0.34)); }
    88%  { transform: translateY(calc(var(--secdsm-spider-w) * -0.12)); }
    94%  { transform: translateY(calc(var(--secdsm-spider-w) * 0.06)); }
    100% { transform: translateY(0); }
}

@keyframes secdsm-spider-thread {
    0%   { transform: scaleY(1); }
    6%   { transform: scaleY(1.06); }
    22%  { transform: scaleY(0.02); }
    58%  { transform: scaleY(0.02); }
    80%  { transform: scaleY(1.34); }
    88%  { transform: scaleY(0.88); }
    94%  { transform: scaleY(1.06); }
    100% { transform: scaleY(1); }
}

@keyframes secdsm-spider-legs {
    from { transform: skewX(-9deg) scaleX(1.06); }
    to   { transform: skewX(9deg)  scaleX(0.94); }
}

@keyframes secdsm-neon-flicker {
    0%, 100% { opacity: 1; }
    2%   { opacity: 0.35; text-shadow: none; }
    3%   { opacity: 1; }
    5%   { opacity: 0.55; }
    6%   { opacity: 1; }
    6.6% { opacity: 0.2; text-shadow: none; }
    7%   { opacity: 1; }
    58%  { opacity: 1; }
    59%  { opacity: 0.3; text-shadow: none; }
    60%  { opacity: 1; }
    61%  { opacity: 0.7; }
    62%  { opacity: 1; }
}

@keyframes secdsm-fog-drift {
    from { transform: translateX(-4%) scaleY(1); }
    to   { transform: translateX(4%)  scaleY(1.12); }
}

@keyframes secdsm-glitch {
    0%   { transform: none; filter: none; }
    10%  { transform: translate(-8px, 2px) skewX(-2deg); filter: hue-rotate(90deg) saturate(2.5); }
    20%  { transform: translate(6px, -3px); filter: none; }
    30%  { transform: none; filter: invert(1) hue-rotate(180deg); }
    40%  { transform: translate(-3px, 0) skewX(3deg); filter: none; }
    55%  { transform: translate(5px, 2px); filter: hue-rotate(-70deg) contrast(1.6); }
    70%  { transform: none; filter: none; }
    82%  { transform: translate(-2px, 1px); filter: saturate(3); }
    100% { transform: none; filter: none; }
}

/* ─── 4. TERMINAL — green phosphor ──────────────────────────── */
sec-tty {
    color: #c9ffc2;
    background:
        radial-gradient(ellipse 120% 80% at 50% 0%, rgba(var(--secdsm-green-rgb), 0.05), transparent 60%),
        var(--secdsm-surface);
    box-shadow:
        0 0 0 1px rgba(var(--secdsm-green-rgb), 0.18),
        0 0 40px rgba(var(--secdsm-green-rgb), 0.06),
        0 24px 80px rgba(0, 0, 0, 0.55);
}

.tty-head .dot {
    background: var(--secdsm-green);
    box-shadow: 0 0 10px rgba(var(--secdsm-green-rgb), 0.55);
}

.tty-out,
.tty-out .out,
.tty-out pre.box { color: #a9ea9f; }
.tty-out .echo b,
.tty-out pre.box b { color: #dfffd9; }
.tty-out .echo .p,
.tty-input .p {
    color: var(--secdsm-green);
    text-shadow: 0 0 8px rgba(var(--secdsm-green-rgb), 0.45);
}
.tty-out pre.box em { color: var(--secdsm-cyan); }
.tty-out .ok  { color: var(--secdsm-amber); }
.tty-out .err { color: var(--secdsm-cyan); }
.tty-input {
    background:
        linear-gradient(to top, rgba(var(--secdsm-green-rgb), 0.07), transparent 80%),
        var(--secdsm-surface);
}
.tty-input input { color: #dfffd9; caret-color: var(--secdsm-green); }
.tty-out::-webkit-scrollbar-thumb:hover { background: var(--secdsm-green); }
.secdsm-tty-headline .secdsm-tty-prompt { color: var(--secdsm-green); }

/* ─── 5. SMALL SEASONAL TOUCHES ─────────────────────────────── */
/* "Next Run" badge reads as live, not just accented */
.secdsm-badge-running {
    border-color: var(--secdsm-green);
    background: var(--secdsm-green-dim);
    color: var(--secdsm-green);
    box-shadow: 0 0 12px var(--secdsm-green-dim);
}

/* Sponsor logos keep their white tiles for legibility — untouched on purpose. */

/* Feature talks glow violet on the schedule */
.secdsm-badge-feature { text-shadow: 0 0 10px rgba(var(--secdsm-magenta-rgb), 0.45); }

/* Slightly heavier scanlines, like a CRT in a dark room */
body.home::before {
    background: repeating-linear-gradient(
        0deg,
        transparent 0px,
        transparent 3px,
        rgba(0, 0, 0, 0.13) 3px,
        rgba(0, 0, 0, 0.13) 4px
    );
}

@media (prefers-reduced-motion: reduce) {
    .secdsm-display-accent { animation: none; }
    .secdsm-hero::after { animation: none; }
}

@media (max-width: 767px) {
    .secdsm-hero { --secdsm-web-w: 60vw; }
    .secdsm-hero::before { opacity: 0.16; }
    /* Shorter thread on phones so it doesn't dangle into the hero copy */
    .secdsm-spider {
        --secdsm-spider-w: calc(var(--secdsm-web-w) * 0.15);
        --secdsm-thread:   calc(var(--secdsm-web-w) * 0.12);
    }
}
