@font-face {
    font-family: "SidStationC64";
    src: url("../assets/fonts/SidStationC64.woff2") format("woff2");
    font-display: swap;
}

/* Every text colour here clears WCAG AA (4.5:1) against every background it is
   actually painted on, with the tightest pairing at 4.80. The constraint that
   shapes the palette is --screen, the lighter panel behind .alt sections and the
   hero: text that reads comfortably on --bg has far less room on --screen, so
   that is the pairing to re-check before changing any of these. */
:root {
    --bg: #2e2a63;
    --screen: #463ea4;
    --panel: #383382;
    --fg: #c2bef1;
    /* Borders only. Too dark for text, which is what --muted is for. */
    --dim: #6461bd;
    /* Footer text. Safe on --bg (4.92) and nowhere else: it drops to 3.22 on
       --screen, so do not reach for it inside an .alt section. */
    --muted: #9c9ad6;
    --hot: #ffffff;
    /* Decoration: button fill, card rules. Fails as text on --screen at 3.46. */
    --teal: #3cb8a6;
    /* The same teal lifted until it passes on --screen. Link text only. */
    --link: #72d4c4;
    --red: #e0655f;
    --sand: #d9a441;
}

* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
    /* Clears the pinned nav, so a jump to #modulation or #tabs does not land the
       heading underneath it. Generous enough to cover the nav wrapping to two
       lines on a narrow screen, since CSS cannot read its height. */
    scroll-padding-top: 76px;
}

/* The smooth scroll above animates a whole page of travel on every .toc link,
   which is the kind of movement that triggers motion sickness. Honour the
   system setting and jump instead. The scroll-padding still applies either way,
   so the landing position does not change, only how it is reached. */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--fg);
    font-family:
        system-ui,
        -apple-system,
        "Segoe UI",
        Roboto,
        sans-serif;
    font-size: 17px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

.pixel {
    font-family: "SidStationC64", "Courier New", monospace;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.2;
    color: var(--hot);
}

a {
    color: var(--link);
}
a:hover {
    color: var(--hot);
}

.wrap {
    max-width: 1024px;
    margin: 0 auto;
    padding: 0 24px;
}

/* Skip link, the first focusable thing in the body on every page. Without it a
   keyboard or screen reader user pays the Menu button plus six nav links on
   every page before reaching anything specific to it (WCAG 2.4.1).

   Moved off screen rather than hidden with display:none or visibility:hidden,
   either of which would take it out of the tab order and leave nothing to
   focus. Fixed rather than absolute, so it is still in the viewport if focus
   reaches it after a scroll: absolute would place it relative to the document
   and put it back above the top of the page. The z-index clears the nav, which
   is 10 and sticky, and would otherwise paint over it. --hot on --panel is
   10.69:1, styled off --panel and --dim like the Menu button and every other
   field on the site. */
.skip {
    position: fixed;
    left: 12px;
    top: -60px;
    z-index: 20;
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    font-size: 12px;
    letter-spacing: 0.05em;
    color: var(--hot);
    background: var(--panel);
    border: 2px solid var(--dim);
    padding: 10px 16px;
    text-decoration: none;
}
.skip:focus {
    top: 12px;
}
/* main carries tabindex="-1" purely so the skip link lands focus there in every
   browser, rather than only moving the scroll position. It is never in the tab
   order itself, so a ring around the whole page body would only ever appear as
   a side effect of following the link. */
main:focus {
    outline: none;
}

/* Site navigation, above the hero on every page, so any page is one click from
   anywhere. --fg on --bg is 7.33:1.

   It stays pinned to the top of the viewport. Sticky rather than fixed: it is the
   first element in the body, so it pins from the start either way, but sticky
   keeps its place in the flow, which means no spacer under it and nothing to get
   wrong when the links wrap to a second line on a narrow screen. The z-index is
   needed because the hero that follows is a positioned element and would
   otherwise paint over it.

   The bottom edge is --dim (the palette's border tone) rather than --panel, and
   there is no shadow. Pinned, the bar keeps its --bg fill over whatever scrolls
   under it, and --bg on a normal section is the same colour at 1.00, so the edge
   is the only thing marking where the bar ends: --panel manages 1.21 against the
   body and disappears, where --dim is 2.45 there and 1.60 over the hero. A
   shadow was tried here and read as a stripe, since the site is otherwise flat
   and the h1's drop shadow only works because it sits on letterforms. */
.topnav {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--bg);
    border-bottom: 2px solid var(--dim);
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    font-size: 12px;
    letter-spacing: 0.05em;
}
.topnav .wrap {
    padding-top: 13px;
    padding-bottom: 13px;
}
/* Spread across the same .wrap the text and screenshots use, so the first and
   last link sit flush with the content edges either side. The gap becomes a
   minimum rather than the actual spacing, and still sets the row gap if a link
   ever wraps. */
.topnav .navlinks {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 6px 20px;
}
.topnav a {
    color: var(--fg);
    text-decoration: none;
}
.topnav a:hover,
.topnav a:focus-visible,
.topnav a[aria-current="page"] {
    color: var(--hot);
}

/* The Menu button. Hidden by default, and revealed only inside the narrow-screen
   query below, and there only when scripting is on: .js is set inline in each
   page's head so the swap happens before first paint rather than as a flash of
   the wide layout. With JS off nothing here applies and the links stay a plain
   wrapping row, which is what the site did before the button existed. Styled off
   --panel and --dim like every other field on the site (--fg on --panel is
   6.07:1). */
.navtoggle {
    display: none;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: var(--fg);
    background: var(--panel);
    border: 2px solid var(--dim);
    padding: 8px 14px;
    cursor: pointer;
}
.navtoggle:hover,
.navtoggle[aria-expanded="true"] {
    color: var(--hot);
}

/* Six links stop fitting on one line at about 1017px, where space-between starts
   spreading a half-empty second row. Below that they collapse behind the button.
   The .98 keeps a fractional viewport width, which browser zoom produces, from
   landing in the gap between the two layouts.

   That figure is measured rather than guessed, and it moves whenever a link is
   added or renamed: the nav font is a monospace at 12px with 0.05em of letter
   spacing, so a label costs 12.6px per character, and the row costs the labels
   plus 20px per gap. Six labels come to 969px, which is why .wrap is 1024 (976
   of content) and why this query sits at 969 + 48 of padding. */
@media (max-width: 1016.98px) {
    .js .navtoggle {
        display: block;
    }
    .js .navlinks {
        display: none;
    }
    /* Open: a stacked list under the button. Column, so space-between has nothing
       to spread, and the padding gives each link a comfortable tap target. */
    .js .navlinks.open {
        display: flex;
        flex-direction: column;
        gap: 0;
        padding-top: 6px;
    }
    .js .navlinks.open a {
        padding: 10px 0;
    }
}

/* Hero */
.hero {
    background: var(--screen);
    border-bottom: 4px solid var(--bg);
    padding: 88px 0 72px;
    text-align: center;
    position: relative;
    overflow: hidden;
}
.hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.06) 0 2px, rgba(0, 0, 0, 0) 2px 4px);
    pointer-events: none;
}
.hero h1 {
    font-family: "SidStationC64", "Courier New", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: clamp(34px, 7vw, 66px);
    letter-spacing: 0.03em;
    margin: 0 0 10px;
    text-shadow: 0 3px 0 rgba(0, 0, 0, 0.25);
}
.hero .tag {
    color: #ddd9ff;
    font-size: clamp(16px, 2.4vw, 21px);
    margin: 0 auto 30px;
    max-width: 620px;
}
.badges {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
    margin-bottom: 30px;
}
.badge {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    font-size: 12px;
    color: var(--fg);
    border: 2px solid var(--dim);
    padding: 5px 10px;
    letter-spacing: 0.05em;
}
.hero .fineprint {
    color: #cbc7f2;
    font-size: 13px;
    margin: 16px 0 0;
}

.btn {
    display: inline-block;
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    font-size: 15px;
    letter-spacing: 0.05em;
    padding: 13px 22px;
    text-decoration: none;
    border: 2px solid var(--teal);
    color: var(--bg);
    background: var(--teal);
    margin: 6px;
}
.btn:hover {
    background: var(--hot);
    border-color: var(--hot);
    color: var(--bg);
}
.btn.ghost {
    background: transparent;
    color: var(--fg);
    border-color: var(--dim);
}
.btn.ghost:hover {
    color: var(--hot);
    border-color: var(--hot);
    background: transparent;
}
/* Star and follow, kept smaller than the row above so the Download button stays
   the one thing the eye lands on first. */
.social {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 14px;
}
.btn.small {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    padding: 8px 14px;
    margin: 0;
}
.btn.small svg {
    width: 14px;
    height: 14px;
    flex: none;
    fill: currentColor;
}

/* Sections */
section {
    padding: 62px 0;
}
section h2 {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: clamp(22px, 4vw, 32px);
    margin: 0 0 8px;
}
/* No max-width here, nor on .shot p or .steps. Text runs to the same edge as the
   screenshots and cards, which are .wrap wide, so every block on a page shares one
   left and right edge. Change .wrap to change the measure, not these. */
.lead {
    color: var(--fg);
}
.lead.spaced {
    margin-top: 26px;
}

/* On this page. The five article pages each run five to seven sections deep, so
   their h2s scroll well out of reach and the section anchors they already carry
   were only findable by reading the source. Not on the landing page, where the
   hero's Download button is what should be reached first, and not on the 404,
   which is a list of links already.

   No panel fill or card border: the list sits between the hero and the first
   h2, where a second filled block would read as another section rather than as
   a way into the one below. The rule down the left is the same idiom as pre.
   Jump targets already land clear of the pinned nav, from scroll-padding-top on
   html, so there is nothing to add per anchor here. */
.toc {
    padding: 46px 0 0;
}
/* --hot is 12.90:1 on --bg. Sized like a .card h3 rather than a section h2, so
   the label does not compete with the headings it lists. */
.toc h2 {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: 15px;
    letter-spacing: 0.05em;
    margin: 0 0 14px;
}
.toc ol {
    margin: 0;
    padding: 2px 0 2px 24px;
    border-left: 3px solid var(--dim);
}
.toc li {
    margin-bottom: 7px;
}
/* 7.33:1 on --bg, which is the only background these sit on: every page's first
   section is a plain one, so the list is never painted on --screen. */
.toc a {
    color: var(--link);
}

/* Feature cards */
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
    margin-top: 34px;
}
.card {
    background: var(--panel);
    padding: 22px 24px;
    border-top: 4px solid var(--teal);
}
.card.v2 {
    border-top-color: var(--red);
}
.card.v3 {
    border-top-color: var(--sand);
}
.card h3 {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: 15px;
    margin: 0 0 14px;
}
.card ul {
    margin: 0;
    padding-left: 18px;
}
.card li {
    margin-bottom: 9px;
}

/* Download cards. The same block as the feature cards, so they inherit the
   --panel fill, the coloured top rule and the three-across grid that collapses
   to one on a narrow screen. What differs is that each ends in a button, and
   carries prose rather than a list, so the spacing is set here instead of by
   .card ul. */
#download .card p {
    margin: 0 0 14px;
}
/* The file names are long and unbroken: the Linux one is 41 characters, which
   at this size is wider than a card at the grid's 260px minimum. Nothing in a
   file name is a break opportunity to a browser, not even the hyphens, so
   without this it would simply overflow the card. #ddd9ff is 7.86:1 on
   --panel, the same code colour the install table uses. */
#download .card code {
    color: #ddd9ff;
    font-size: 14px;
    overflow-wrap: anywhere;
}
/* .btn carries 6px of margin for the hero, where buttons sit side by side. In a
   card it is the last thing in the box and needs no side margin. */
#download .card .btn {
    margin: 2px 0 0;
}

/* Tabs / screenshots */
.shot {
    margin-top: 46px;
}
.shot h3 {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: 18px;
    margin: 0 0 6px;
}
.shot p {
    margin: 0 0 16px;
}
.shot img {
    width: 100%;
    height: auto;
    display: block;
    border: 3px solid var(--panel);
    background: var(--screen);
}

.alt {
    background: var(--screen);
}

/* Install */
.steps {
    margin: 26px 0 0;
    padding-left: 20px;
}
.steps li {
    margin-bottom: 14px;
}
.paths {
    margin: 26px 0 0;
    border-collapse: collapse;
    font-size: 15px;
}
.paths th,
.paths td {
    text-align: left;
    padding: 7px 22px 7px 0;
    border-bottom: 1px solid var(--dim);
}
.paths th {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: 13px;
    font-weight: normal;
}
.paths td code {
    color: #ddd9ff;
}
#install h3 {
    font-family: "SidStationC64", monospace;
    text-transform: uppercase;
    color: var(--hot);
    font-size: 18px;
    margin: 34px 0 6px;
}

/* Build */
pre {
    background: #221f4d;
    color: #d7d3ff;
    padding: 18px 20px;
    overflow-x: auto;
    border-left: 4px solid var(--teal);
    font-family: "SF Mono", Menlo, Consolas, monospace;
    font-size: 15px;
    line-height: 1.55;
}
code {
    font-family: "SF Mono", Menlo, Consolas, monospace;
}

/* Footer */
footer {
    background: var(--bg);
    border-top: 4px solid var(--panel);
    padding: 40px 0;
    text-align: center;
    color: var(--muted);
    font-size: 15px;
}
footer .pixel {
    font-size: 14px;
    color: var(--fg);
}
/* The brand line is a standalone heading rather than a link inside a sentence,
   so it carries no underline at rest. It gets one on hover and on keyboard
   focus, so it is never colour alone that marks it as a link. */
footer .pixel a {
    color: inherit;
    text-decoration: none;
}
footer .pixel a:hover,
footer .pixel a:focus-visible {
    color: var(--hot);
    text-decoration: underline;
}
footer a {
    color: var(--fg);
}
