/* MTM2.COM — the interior skin.
 *
 * The database pages, details, login and upload. The front door has its own
 * light skin; the contrast between the two is deliberate and original.
 *
 * Built from Design's mockups (_design/mockups/, Tracks turn 4a) as a
 * stylesheet rather than the inline styles the mockups carry — those are how a
 * mockup is made, not how a site ships. Same values, one place to change them.
 *
 * The legacy class names at the bottom (.header1, .header2, .detail, .offset,
 * .nf) are kept working deliberately, so pages can move over one at a time
 * instead of in one flip. stylesdefault.css remains for pages not yet moved.
 */

/* Space Mono, self-hosted.
 *
 * Design sets every small label in it -- 385 places across the ten mockups, at
 * 10 to 30px, in both weights -- so it is the labelling face for the site, not
 * an accent on one page.
 *
 * Served from here rather than linked from Google: no third-party request on
 * every page load, no visitor IPs handed to Google, nothing to fail if Google
 * is slow or blocked, and Cloudflare caches it at the edge like any other
 * file. Two files, 33KB together, and only the latin subset -- the labels are
 * ASCII, and unicode-range below keeps a browser from fetching them at all
 * for text they cannot serve.
 *
 * Space Mono is under the SIL Open Font License 1.1, which permits this;
 * the licence travels with the files in fonts/OFL.txt.
 *
 * font-display: swap matches Design's &display=swap -- a label shows in the
 * page font immediately and swaps when the font lands, rather than sitting
 * invisible.
 */
@font-face {
    font-family: 'Space Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url(fonts/spacemono-400.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: 'Space Mono';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url(fonts/spacemono-700.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;
}

/* Archivo and Source Sans 3, self-hosted -- MTMG's headings and reading face.
 *
 * Design's turns 21-22: Archivo for headings and small labels, Source Sans 3
 * for body copy, replacing 13px Arial in the MTMG reading column. Neither is
 * Arial and neither will date.
 *
 * Same reasoning as Space Mono above, and the same rule: nothing is linked
 * from Google. The mockups load them from fonts.googleapis.com, which is how
 * a mockup is made, not how this site ships.
 *
 * BOTH ARE VARIABLE FONTS, which is why there are three files and not five.
 * Google's own css2 output hands back the identical URL for Archivo 500, 600
 * and 700 -- one file carrying the whole wght axis. Declaring the range here
 * rather than three static faces is the honest description of that file, and
 * it means a weight Design has not used yet costs nothing to reach for. The
 * ranges are the real axis limits: the fonts.googleapis.com API answers 200
 * for wght\@100..900 on Archivo and wght\@200..900 on Source Sans 3, and 400
 * for anything wider.
 *
 * Latin subset only, as above -- MTMG is English. 66 KB for all three.
 *
 * Archivo is SIL OFL 1.1 (Omnibus-Type), Source Sans 3 is SIL OFL 1.1
 * (Adobe). Both licences travel with the files, in fonts/OFL-archivo.txt and
 * fonts/OFL-sourcesans3.txt beside Space Mono's fonts/OFL.txt.
 *
 * NOTHING CONSUMES THESE YET. The faces are here and named below; applying
 * them to the MTMG chrome is the facelift itself, one page at a time.
 */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url(fonts/archivo-var.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: 'Source Sans 3';
    font-style: normal;
    font-weight: 200 900;
    font-display: swap;
    src: url(fonts/sourcesans3-var.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: 'Source Sans 3';
    font-style: italic;
    font-weight: 200 900;
    font-display: swap;
    src: url(fonts/sourcesans3-var-italic.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;
}

:root {
    --bg:        #000000;   /* with the MTMGbg tile over it */
    --bar:       #000000;   /* the site header — solid, the one hard band */
    --bar-soft:  #050505;   /* the controls row — barely darker than the tile */
    --panel:     #0A0A0A;   /* inputs, footer bar */
    --ink:       #FFFF00;   /* body text — the original's yellow */
    --link:      #C0C0C0;
    /* One step down from --link, and now used only for the search
     * placeholder: it has to read as "nothing typed yet" against the text you
     * type over it. Everything else that used to be muted -- the control
     * labels, the footer bars, the cross-archive label -- uses --link, so the
     * page has one grey rather than two that look like a mistake. It is also
     * still on the two filter labels, which name a control rather than saying
     * anything and sit a step back from the value under them -- Design has
     * them that way too. */
    --muted:     #808080;
    --rule:      #404040;   /* hairlines */
    --rule-soft: #303030;
    --navy:      #000080;   /* header2 in the original */
    --navy-deep: #191970;   /* header1 */
    --on-navy:   #F5F5F5;

    --font: Arial, Helvetica, sans-serif;
    /* The small control labels. Design's face, self-hosted above.
     * Arial is the fallback while it loads and if it ever fails. */
    --font-label: 'Space Mono', ui-monospace, Consolas, monospace;
    /* MTMG's two faces, waiting to be used. Arial leads the fallbacks for
     * the same reason: it is what the section has always been set in, so a
     * failed font load looks like the old page rather than like nothing. */
    --font-head: 'Archivo', Arial, Helvetica, sans-serif;
    --font-body: 'Source Sans 3', Arial, Helvetica, sans-serif;
}

body {
    margin: 0;
    background: var(--bg) url(MTMGbg.gif) repeat;
    color: var(--ink);
    font: 13px/1.45 var(--font);
}

a, a:visited { color: var(--link); }
/* Deliberate departure from the original, per Design: its hover was #0000FF,
 * which is unreadable on black. */
a:hover    { color: var(--ink); }

/* ---------------------------------------------------------------- header -- */

/* The bands.
 *
 * Only the site header is solid. Everything below it sits on the tiled field,
 * and the horizontal structure comes from the NAVY bars — the summary and the
 * table header — with the footer bar closing the page.
 *
 * Two corrections got here. First pass: everything transparent, so nothing
 * banded at all. Second: header, title bar and quick-links all solid, which
 * overshot — it walled off the top third of the page and left the navy bars
 * with nothing to contrast against. Design has one solid bar at the top and
 * lets the tile carry the rest. */
.site-head {
    background: var(--bar);
}

.site-head,
.page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 12px 18px;
    border-bottom: 1px solid var(--rule);
}

.site-head__brand { display: flex; align-items: center; gap: 12px; }
.site-head__brand img { display: block; }
/* Silver, like the nav links beside it -- and :visited is in the selector on
 * purpose.
 *
 * This rule used to say `color: var(--ink)` and the wordmark was yellow. It
 * was yellow only until you had been to the front door: `a, a:visited` above
 * is (0,1,1) and a lone class is (0,1,0), so once the link was visited the
 * generic rule won and repainted it silver. The colour therefore depended on
 * the reader's browsing history -- yellow to a first-time visitor, silver to
 * everyone who had been here before -- which is why the site owner and I saw
 * two different headers on the same URL, and why getComputedStyle disagreed
 * with the screen: browsers deliberately report the UNVISITED colour for
 * :visited, so the console said yellow while the pixels were silver.
 *
 * Silver is also the right answer rather than just the observed one. It is
 * what the forum header has always shown (`.site-head a` there is (0,1,1) and
 * beats the wordmark rule outright, so that one was never yellow at all), and
 * it leaves pure #FFFF00 meaning only "where you are" -- the active nav item,
 * the active area, the active page. The wordmark is not a location.
 *
 * :visited is named explicitly so the colour no longer changes with history.
 */
.site-head__wordmark,
.site-head__wordmark:visited {
    font-size: 20px;
    font-weight: bold;
    letter-spacing: 0.01em;
    color: var(--link);
    text-decoration: none;
}
/* Yellow on hover, the same as every other link in the bar. */
.site-head__wordmark:hover { color: var(--ink); }

.site-nav { display: flex; align-items: center; gap: 18px; }
.site-nav a { text-decoration: none; }
.site-nav .is-active {
    color: var(--ink);
    border-bottom: 2px solid var(--ink);
    padding-bottom: 2px;
}

/* The header on a narrow screen.
 *
 * Brand, six nav links and the sign-in button come to about 600px and neither
 * row could wrap, so every page on the site scrolled sideways on a phone -- the
 * body inherited the header's width and the content underneath was dragged out
 * with it. Nothing here is a phone-specific layout: the same three groups, told
 * they may take a second line.
 *
 * The nav goes full width and last. Brand and sign-in are the two things worth
 * having on the first line -- one says where you are, the other is the only
 * action in the bar -- and six links do not fit beside them at any size worth
 * targeting. `order` rather than reordering the markup, because the source
 * order is the right reading order and the tab order with it. */
@media (max-width: 720px) {
    .site-head,
    .page-head {
        flex-wrap: wrap;
        gap: 10px 14px;
        padding: 10px 12px;
    }
    .site-nav {
        order: 3;
        width: 100%;
        flex-wrap: wrap;
        gap: 8px 14px;
    }
    /* The two row-2 groups behave the same way: the title keeps the first line
     * and the search drops under it at full width rather than being crushed. */
    .page-head__tools { width: 100%; }
    .page-head__tools .search { flex: 1; }
    .page-head__tools .search input { width: 100%; min-width: 0; }
}

.btn {
    display: inline-block;
    color: var(--link);
    text-decoration: none;
    font-size: 12px;
    border: 1px solid var(--rule);
    padding: 7px 13px;
    background: transparent;
    cursor: pointer;
}
.btn:hover { color: var(--ink); border-color: var(--ink); }

.btn--primary {
    color: var(--on-navy);
    font-weight: bold;
    background: var(--navy);
}
.btn--primary:hover { color: #FFFFFF; }

/* ------------------------------------------------------------ page head -- */

.page-head__title { font-size: 17px; font-weight: bold; }
.page-head__tools { display: flex; align-items: center; gap: 10px; }
/* The action beside the search box, brought up with it. .btn is 12px
 * everywhere and stays there; this is the one in this row.
 *
 * The line-height is stated for the same reason .filter__buttons and .pager
 * state theirs. .btn is inline-block and inherits the body's 1.45, so its
 * height tracks the face while the search box's tracks its input -- 30 against
 * 33 at the old sizes, and the type rise pushed that to 32 against 36. Setting
 * the line and dropping the vertical padding puts it on the box's 32 exactly,
 * which is a thing this row never actually had. */
.page-head__tools .btn { font-size: 14px; padding: 0 13px; line-height: 30px; }

.search {
    display: flex;
    align-items: center;
    border: 1px solid var(--rule);
    background: var(--panel);
}
.search input {
    background: transparent;
    border: 0;
    color: var(--ink);
    font: 14px var(--font);
    padding: 7px 9px;
    width: 210px;
}
.search input::placeholder { color: var(--muted); }
.search input:focus { outline: 1px solid var(--rule); }
/* Navy, per Design turn 12a. The one filled control in the row, so the eye
 * lands on it without hunting -- and it matches the .btn--primary action in
 * the header rather than inventing a third button style. */
.search button {
    color: var(--on-navy);
    font: bold 13px var(--font);
    padding: 7px 13px;
    border: 0;
    background: var(--navy);
    cursor: pointer;
}
.search button:hover { color: #FFFFFF; background: var(--navy-deep); }

/* --------------------------------------------------------- quick links -- */

/* The bracket row under the page head. Same punctuation as the closing bar in
 * .sectionfoot, but no background: that band is what ends the page, and giving
 * this one the same fill would make the page look finished before the listing
 * had started. */
.quicklinks {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 0;
    padding: 10px 18px;
    border-bottom: 1px solid var(--rule);
    /* 14, not the 12 it opened at. This row is navigation -- Malibu350's
     * shots, the HOF archive, garage settings, the forum -- and it was set
     * a point BELOW the body text, which is backwards for something meant
     * to be clicked. */
    font-size: 14px;
    color: var(--muted);
}
.quicklinks a         { text-decoration: none; padding: 0 8px; }
.quicklinks a:hover   { color: var(--ink); }
.quicklinks .bracket  { padding: 0 8px; }

/* --------------------------------------------------------- filter bar --- */
/* Design's turn 4a consolidates the four stacked filter forms into one row. */

.filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 14px 22px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--rule);
    background: var(--bar-soft);   /* barely darker than the tile, per 12a */
}

/* The tracks bar carries more than fits on one line -- six controls and then
 * the whole alphabet -- so it stacks: controls, a hairline, letters. */
.filters--stack { flex-direction: column; align-items: stretch; gap: 14px; }
.filters__row   { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px 22px; }
.filters__row--letters {
    align-items: center;
    gap: 4px;
    border-top: 1px solid #202020;
    padding-top: 12px;
}
/* Something pinned to the right of the controls row — "Also by this maker",
 * and the like. */
/* The label stays grey and only the link is yellow, so the yellow marks the
 * thing you can act on rather than the whole phrase. */
.filters__aside { margin-left: auto; font-size: 14px; color: var(--link); }
.filters__aside a,
.filters__aside a:visited { color: var(--ink); }
.filters__aside a:hover   { color: #FFFFFF; }
.filter { display: flex; flex-direction: column; gap: 5px; }
/* The two control labels keep the darker grey, as Design has them. They name
 * the control rather than saying anything, so they sit a step back from the
 * value underneath -- the one place on the page where the dimmer grey is
 * doing a job rather than looking like a mistake. */
.filter__label {
    font: 11px var(--font-label);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted);
}
.filter select,
.filter input {
    background: var(--panel);
    color: var(--ink);
    border: 1px solid var(--rule);
    font: 14px var(--font);
    padding: 6px 8px;
}

/* "My build" is picked out in yellow, label and border both.
 *
 * It is the one control in the row that describes the visitor rather than the
 * archive, and the only one whose answer changes what the other rows mean
 * rather than which rows appear. Design turn 4b gives it the accent; without
 * it the control that reframes the whole page looks like a fifth way to sort. */
.filter--mine .filter__label { color: var(--ink); }
.filter--mine select         { border-color: var(--ink); }

/* Takes the rest of the line, so its hint has somewhere to sit. */
.filter--wide { flex: 1; min-width: 200px; }

/* A pair of buttons standing in for a control, in a row of dropdowns.
 *
 * Design draws these taller than the selects beside them and lets the row
 * bottom-align, which puts their labels 16px above every other label -- the
 * one row on the page where the eye cannot read the labels straight across.
 * Matching the select height instead lines the labels up and costs nothing.
 *
 * The wrapper carries no padding of its own now; that was the other half of
 * the 45px. */
/* 32px is what a select comes to here, measured, now the face is 14px rather
 * than the 12 this rule was first written against -- 30px then, 32px now, and
 * the two numbers below have to move with it or the row goes back to the
 * misalignment the paragraph above describes. Matching by padding alone lands
 * within a pixel or two, close enough to look like a mistake rather than a
 * choice, so the height is stated and the label centred inside it.
 * 30 is 32 less the 1px border either side. */
.filter__buttons      { display: flex; align-items: center; gap: 10px; height: 32px; }
.filter__buttons .btn { padding: 0 13px; line-height: 30px; }
.filter__hint    { color: var(--muted); font-size: 12px; }

/* A button that is the current setting. Navy fill, as the header action uses,
 * so "on" reads the same way everywhere. */
.btn--on {
    background: var(--navy-deep);
    color: var(--on-navy);
    border-color: var(--rule);
}
.btn--on:hover { color: #FFFFFF; }

/* A–Z as a click strip rather than a form. */
.letters { display: flex; flex-wrap: wrap; gap: 4px; }
.letters a {
    text-decoration: none;
    font-size: 14px;
    padding: 4px 7px;
    border: 1px solid var(--rule-soft);
}
.letters a:hover      { border-color: var(--rule); color: var(--ink); }
.letters .is-active   { color: var(--ink); border-color: var(--ink); }

/* --------------------------------------------------------------- table -- */

/* The listing block does not run to the page edge.
 *
 * Design turn 12a wraps the summary, the table and the footer bar in
 * padding: 16px 18px 24px, so the navy bands stop short of both sides and the
 * whole listing reads as one object sitting on the tiled field rather than as
 * stripes painted across the window. The bars above it -- the site header and
 * the controls row -- stay full width on purpose: those are page chrome, and
 * the contrast between the two is what makes the listing look placed.
 *
 * 18px, not the 8 it measures at in a screenshot of the mockup: the mockup
 * canvas carries 56px of its own padding and is scaled down to fit. */
.listing { padding: 16px 18px 24px; }

/* The listing table scrolls inside this block rather than dragging the document
 * sideways with it. Before, the body took the table's width and every row of
 * the page -- site header included -- sat wider than the screen.
 *
 * NOT scoped to phones, though that is where it is worst. The eight-column
 * track listing needs about 890px and the maker page needs 1,014 (it carries a
 * "Filed as" column the others do not), so a 1,000px desktop window overflows
 * on the maker page too. A width-conditional rule would leave that broken.
 * Unconditional costs nothing: a table that fits produces no scrollbar.
 *
 * The columns are already at their minimums and hiding any of them loses data
 * the page exists to show, so scrolling is the honest answer rather than a
 * narrow-screen layout that quietly drops information.
 *
 * On .listing rather than the table because tracks, trucks and the maker page
 * all share this wrapper -- one rule instead of a markup change in three files.
 * Safe as a block formatting context: the only sticky element on the site is
 * .mtmg-nav, which is in the MTMG chrome and never inside a listing. */
.listing { overflow-x: auto; }

/* The summary is a band too, not loose text.
 *
 * Design's turn 12a puts it in the navy bar above the table -- "62 tracks by
 * Malibu350, 1999 to 2007. Sorted by date and desc." Left on the tiled
 * background it is the one line on the page competing with the watermark,
 * which is exactly where you least want that: it is the line explaining why
 * the row count is what it is. */
/* The whole line is yellow, not white with yellow highlights: it is the one
 * sentence explaining why the rows below are the rows below, and on navy the
 * yellow is what the eye goes to first.
 *
 * A second line -- the alias list -- stays white on purpose. It is reference
 * detail rather than something to act on, and keeping both lines yellow would
 * flatten the difference. */
.summary {
    background: var(--navy);
    color: var(--ink);
    text-align: center;
    padding: 9px 18px;
    font-size: 14px;
    border-bottom: 1px solid var(--rule);
}
.summary strong { color: var(--ink); font-weight: bold; }

/* Yellow through every state. A sort link that greyed out once used would be
 * dimmest exactly where the reader has already shown interest. */
.summary a,
.summary a:visited { color: var(--ink); }
.summary a:hover   { color: #FFFFFF; }

.summary__also        { color: var(--on-navy); }
.summary__also strong { color: var(--on-navy); font-weight: normal; }

/* The bar that closes a listing.
 *
 * Turn 12a: "Showing 9 of 62 · ◉ name opens the details pop-up, otherwise it
 * asks you to log in · the thumbnail opens the full screenshot" on the left,
 * Prev / Next on the right.
 *
 * Worth copying for its own sake: it puts the count, the legend for the row
 * markers, and the pager in one place, so a reader who wonders what a symbol
 * means finds the answer without leaving the page. The existing pager prints
 * a bare "1-100 of 4,641" and explains nothing. */
.tablefoot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding: 10px 18px;
    border-top: 1px solid var(--rule);
    background: var(--panel);
    font-size: 14px;
    color: var(--link);
}
.tablefoot__pager { display: flex; gap: 8px; }

/* The same controls at the head of the listing.
 *
 * On tracks it takes the free end of the letters row, which is where the eye
 * already is after picking a letter. On a maker page there is no free end --
 * that is where "Also by this maker" sits -- so the pager takes the right and
 * pushes the aside left of it. Only when there is more than one page, so most
 * maker pages never see it and keep the room. */
.pager            { display: flex; align-items: center; gap: 8px; }

/* Who does the pushing depends on what else is in the row.
 *
 * On the letters row the pager is the only thing on the right, so it takes the
 * free space itself. On the maker bar the aside already claims it, and the
 * pager simply follows on the aside's right -- giving both an auto margin
 * would split the slack between them and open two equal gaps that look like an
 * accident rather than a layout. */
.filters__row--letters .pager--top { margin-left: auto; }
.pager__count     { color: var(--muted); font-size: 13px; white-space: nowrap; }
.pager .btn       { padding: 0 13px; line-height: 30px; }

/* .btn is 12px everywhere and stays there -- it is also the sign-in, upload,
 * popup and J-Viewer button. Only the two that sit in this furniture come up
 * to meet it. */
.filters .btn,
.pager .btn,
.tablefoot .btn   { font-size: 14px; }
.tablefoot__pager .is-disabled {
    color: var(--rule);
    border-color: var(--rule-soft);
    pointer-events: none;
}

/* ---------------------------------------------------------- listing rows -- */
/*
 * Design lays these out with CSS grid. A real <table> is used here instead:
 * this is tabular data with a header row and sortable columns, so the table
 * carries meaning a grid of divs does not — column headers announced with each
 * cell by a screen reader, and the rest of the site is tables already. The
 * visual result is the same.
 */

table.rows { width: 100%; border-collapse: collapse; }

/* So the min-widths below mean what Design's grid means.
 *
 * Design lays the listing out as a CSS grid, where a track of 88px is 88px on
 * screen. A table cell measures min-width against its content box, so with
 * 10px of padding either side every column came out 20px wider than the number
 * it was given. border-box puts the padding back inside the figure. */
.rows th, .rows td { box-sizing: border-box; }

/* The type scale in this table, and why it can afford to be this big.
 *
 * The listing used to read at the 13px body size with 12px headers, which
 * put it four points under the MTMG pages next door -- come off a Traxx
 * article at 17px and the database felt like fine print.
 *
 * The room was there for free. A row is 66px tall and the THUMBNAIL sets
 * that, not the text: 51px of picture plus padding. Measured across the
 * 100-row page at 13, 14, 15, 16 and 17px, the table stayed 1214px wide,
 * no column moved, nothing clipped, and total height stayed 6631px. So
 * every point up to about 17 costs nothing -- no taller page, no sideways
 * scroll, no squeeze on the J-Viewer column.
 *
 * 15 rather than 17: the picture column is what makes this free, and a
 * 68px-wide thumbnail beside 17px text starts to look like the wrong one
 * of the two is the subject. */
.rows th {
    background: var(--navy-deep);
    color: var(--on-navy);
    text-align: left;
    font-weight: bold;
    font-size: 13px;
    padding: 7px 10px;
}
.rows td {
    font-size: 15px;
    padding: 7px 10px;
    border-bottom: 1px solid var(--rule-soft);
    vertical-align: middle;
}
/* Size reads in the body grey, not the yellow. It is a fact about the file,
 * the same kind of thing as the date beside it, and in yellow it pulled more
 * attention than the title of the track it belongs to. */
.rows td.num, .rows th.num { text-align: right; }
.rows th.num, .rows td.num { min-width: 90px; }

/* Trucks carry a download count and tracks do not show one. 72px per Design
 * turn 7a, and narrower than the other numeric column because it holds a
 * count rather than a size with a unit on it. */
.rows th.dl, .rows td.dl   { min-width: 72px; }
.rows td.num               { color: var(--link); }

/* Two groups, per Design turn 12a: the picture and the title hold the left,
 * the rest sits over on the right, and the slack falls in the gap between.
 *
 * The title column takes the width so the gap lands there. Without it the
 * table shares spare space evenly across all seven columns and the right-hand
 * group drifts inward instead of staying against the page edge. 100% is not
 * literal -- a table caps it at whatever is left once the others have what
 * they need.
 *
 * Inside that group the values still read LEFT, under their own headings.
 * Ranging them right as well was tried and it is too hard a right: each value
 * ends up flush against the next column with the whitespace behind it, so the
 * eye has nothing to run down. Only Size is right, because it is a number and
 * numbers line up on their units. The min-widths are what hold the columns
 * apart -- without them each shrinks to its longest value and the group jams
 * into the corner.
 *
 * Ranging the title right was tried too, and it is wrong for a different
 * reason: titles run from "Big Whiskey" to "MTM1TRUXnTRAX(MTM1GAME.POD)", so
 * a right edge gives a column of links a ragged left one, and a wrapped title
 * pushes its marker onto a line of its own.
 */
.rows th.name,    .rows td.name    { text-align: left; width: 100%; }
/* Widths straight from Design turn 12a, whose listing grid is
 *
 *     88px  1fr  196px  132px  100px  90px  86px
 *     Pic   Track  Filed as  Type/Revue  Date  Size  J-Viewer
 *
 * min-width rather than width, and set on the header as well as the cell. A
 * table in auto layout treats width on a td as a suggestion and will overrule
 * it -- the title column asking for 100% wins, and everything else collapses
 * toward its longest word. That is what squeezed the J-Viewer column to 69px
 * and left its button looking untouched after its padding had already been
 * corrected. A minimum is not negotiable in the same way. */
.rows th.maker,   .rows td.maker   { text-align: left; min-width: 196px; }
.rows th.type,    .rows td.type    { text-align: left; min-width: 132px; }
.rows th.date,    .rows td.date,
.rows th.laptime, .rows td.laptime { text-align: left; min-width: 100px; white-space: nowrap; }

/* A date is one thing and reads as one. Left to wrap it splits into "2007-" /
 * "10-01", which costs a line of row height on every row and makes a
 * fixed-width value look like an accident. Type/Revue may still wrap --
 * "Straight-a-way" does so in the mockup too. */
/* .quiet is a colour, not a size.
 *
 * It was doing both, which shrank the maker column to 11px along with the
 * date. Design only ever drops the date: its rows are 13px throughout and the
 * date cell is the single override. A maker is a name someone looks for and
 * often clicks, so it reads at the same size as the title it sits beside; a
 * date is a fact you glance at, and can afford to be smaller. */
.rows .quiet    { color: var(--link); }
/* The date alone, not everything shaped like one. A lap time is a result --
 * the thing garage display exists to show -- and shrinking it to timestamp
 * size because it happens to want the same width and nowrap was the same
 * mistake .quiet was making one column over. */
.rows td.date   { font-size: 12px; }

.rows th.pic, .rows td.pic { min-width: 88px; }
.rows td.pic { padding: 6px 9px; }
.rows td.pic img { display: block; border: 1px solid var(--rule); }
/* A missing picture keeps the shape of one: Design turn 12a draws a dashed
 * frame at thumbnail size rather than dropping the words into the gap. Rows
 * stay the same height whether or not there is an image, so the column does
 * not stagger -- which is why it is a box and not just paler text. */
.rows .pic--none {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 68px;
    height: 51px;
    border: 1px dashed var(--rule-soft);
    color: var(--muted);
    font-size: 11px;
}

/* The ◉ beside a name: this one opens the details pop-up. Explained in the
 * footer bar rather than left as a mystery glyph. */
.rows .marker { color: var(--link); font-size: 13px; cursor: help; }

/* The "Revue" half of Type/Revue.
 *
 * A type that was written up on the forum IS the link, as in the original.
 * What is different is the colour: there the link was yellow like every other
 * type, so an underline was the only thing separating a reviewed track from an
 * unreviewed one. Here it also drops to the link grey, which is the signal the
 * rest of the page already uses, so the column reads at a glance -- yellow is
 * just a type, grey and underlined has something to read behind it. */
.rows .revue       { color: var(--link); text-decoration: underline; }
.rows .revue:hover { color: var(--ink); }

/* The build badge, Design turns 4a and 9a: yellow, black text, hard against
 * the name it belongs to.
 *
 * Design states the rule with it -- "nothing is marked unless it needs more
 * than the original game, so 4,000 legacy entries stay clean and the exception
 * stands out". A badge on every row would say nothing; on 2 rows in 5,287 it
 * says everything, which is why it can afford to be the loudest thing in the
 * table.
 *
 * It disappears once the row is dimmed. At that point the visitor has told us
 * their build, the whole row is already saying "not for you", and the exact
 * requirement has moved to the size column -- a yellow flag fighting a greyed
 * row would just be two answers to the same question. */
.rows .badge {
    background: var(--ink);
    color: #000000;
    font-size: 10px;
    font-weight: bold;
    padding: 2px 5px;
    margin-left: 7px;
    white-space: nowrap;
}
.rows td.name { line-height: 1.4; }

/* An item that needs a newer build says so where its size would go, per turn
 * 4b — labelled, not hidden. */
.rows .needs { color: var(--link); font-size: 12px; white-space: nowrap; }

.rows th.viewer { text-align: center; white-space: nowrap; }
/* The J-Viewer button, at Design turn 12a's measurements: padding 6px 4px on
 * an 11px face, filling the width of its cell.
 *
 * The two states are not the same weight, which is the part worth keeping.
 * Load is the live action and takes the brighter border and text; Log in asks
 * for something you cannot do yet, so it sits a step back on both. Fifty rows
 * of identical bright buttons down the right of a page you are not signed in
 * to would be fifty invitations to a dead end. */
.rows th.viewer, .rows td.viewer { min-width: 86px; }
.rows td.viewer { text-align: center; padding: 4px 8px; }
.rows td.viewer .btn {
    display: block;
    background: var(--panel);
    font-size: 12px;
    padding: 6px 4px;
}
.rows td.viewer .btn--load  { border-color: var(--rule);      color: var(--link); }
.rows td.viewer .btn--login { border-color: var(--rule-soft); color: var(--muted); }
.rows td.viewer .btn:hover  { color: var(--ink); border-color: var(--rule); }

/* ------------------------------------------------------------- legacy --- */
/* Class names the un-migrated pages still use. Same values as
 * stylesdefault.css so a half-migrated site stays coherent. */

.nf { color: var(--link); }

table.detail { border: 1px solid var(--rule); }
.detail td   { border-width: 1px; }
td.offset    { color: var(--link); background-color: #202020; }

.header1 td { color: var(--on-navy); text-align: center; background-color: var(--navy-deep); border-bottom-width: 0; }
.header2 td { color: var(--ink);     text-align: center; background-color: var(--navy);      border-bottom-width: 0; }
.header3 td { border-bottom-width: 0; }

li { list-style-type: circle; }

/* ------------------------------------------------------- section footer -- */
/* The bracket nav the archive pages have always ended with -- Rumbles, Drags,
 * Races and so on. Splitting the maker page per archive took it out of the one
 * listing that had none, so it is shared now rather than pasted into each page
 * as it was before.
 *
 * Design turn 12a makes it a solid black bar the full width of the window,
 * with a hairline above it, and that is what makes it read as the end of the
 * page rather than as more links: the header opens with the same band, so the
 * two bracket the listing between them. Left on the tiled field it just looked
 * like a stray line of text after the table.
 *
 * The brackets and the pipes take the dimmer grey and the links the page grey,
 * so the punctuation holds the shape without competing with what you can click.
 */
/* 14 because .quicklinks is 14. The rule up there describes these two as the
 * same punctuation at opposite ends of the page, and a bracket row that opens
 * at one size and closes at another stops reading as a pair. */
.sectionfoot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 4px 0;
    padding: 12px 18px;
    border-top: 1px solid var(--rule);
    background: var(--bar);
    font-size: 14px;
    color: var(--muted);
}
.sectionfoot a          { color: var(--link); text-decoration: none; padding: 0 8px; }
.sectionfoot a:visited  { color: var(--link); }
.sectionfoot a:hover    { color: var(--ink); }
.sectionfoot .bracket   { padding: 0 8px; }
/* The page you are already on: named, not linked. */
.sectionfoot .is-here   { color: var(--ink); padding: 0 8px; }


/* ------------------------------------------------------- build marking --- */
/* Turn 4b. Told which build someone is on, a row they cannot open is dimmed
 * rather than dropped: knowing a track exists, and what it would take to run
 * it, is the point -- that is the whole reason the Community Patch tiers are
 * in the schema. The size column says what it needs instead of how big it is,
 * because at that moment the requirement is the useful fact.
 *
 * Hiding them outright is one click away for anyone who disagrees. */
.rows tr.is-dim td            { background: #060606; border-bottom-color: var(--rule-soft); }
.rows tr.is-dim td,
.rows tr.is-dim a             { color: #6E6E6E; }
.rows tr.is-dim img           { opacity: 0.45; }
.rows tr.is-dim .needs        { color: var(--muted); }
.rows tr.is-dim a:hover       { color: var(--link); }


/* ------------------------------------------------------------ list card -- */
/* The saved list's own description, above the table it filtered to. */
.listcard {
    border: 1px solid var(--rule);
    background: var(--panel);
    padding: 10px 14px;
    margin-bottom: 12px;
    font-size: 14px;
}
/* 16, between the 17 the page title takes and the 15 of the table below. The
 * list's name is what the whole page is showing, but it is not the page's own
 * name -- that is still "Tracks" in the bar above. */
.listcard__name  { color: var(--ink); font-weight: bold; font-size: 16px; }
/* The description is stored markup -- paragraphs, bullets and links, written
 * when the lists were made. It is rendered through the whitelist in
 * _inc/richtext.php, so these are the tags that can actually turn up. The
 * defaults would give it browser margins built for a white page, so it gets
 * spacing that suits a small dark card. */
.listcard__desc          { color: var(--link); margin-top: 6px; line-height: 1.55; }
.listcard__desc p        { margin: 8px 0 0; }
.listcard__desc p:first-child { margin-top: 0; }
.listcard__desc ul       { margin: 6px 0; padding-left: 20px; }
.listcard__desc li       { list-style-type: square; margin: 2px 0; }
.listcard__desc a        { color: var(--ink); }
.listcard__desc a:hover  { color: #FFFFFF; }
.listcard__links { margin-top: 6px; color: var(--muted); font-size: 13px; }

.tablefoot__count { color: var(--muted); align-self: center; }

/* ------------------------------------------------------- details pop-up -- */
/* Design turns 5a and 5b. This runs inside a 1000x600 featherlight iframe, so
 * it is a whole page with no site header: you are already somewhere, looking
 * at one thing, and a nav bar inside a pop-up would only offer ways to break
 * out of it. */

.popup-body { margin: 0; }
.popup {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.popup__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 11px 16px;
    background: var(--navy-deep);
    color: var(--on-navy);
}
.popup__title    { font-size: 17px; font-weight: bold; }
.popup__by       { font-weight: normal; color: var(--on-navy); }
.popup__by a     { color: var(--ink); }
.popup__id       { font: 12px var(--font-label); letter-spacing: 0.1em; color: var(--on-navy); white-space: nowrap; }

/* Detail on the left, picture and the download on the right. */
.popup__body {
    display: grid;
    grid-template-columns: 1fr 274px;
    flex: 1;
    min-height: 0;
}
.popup__main  { padding: 0 0 16px; }
.popup__side  { padding: 12px 16px; border-left: 1px solid var(--rule); }
.popup__empty { padding: 16px; }

/* The facts. A label column and a value column, the labels on their own
 * ground so the eye can run down them without a rule to follow. */
.facts { display: grid; grid-template-columns: 104px 1fr; }
.fact__label {
    padding: 7px 12px;
    background: #202020;
    color: var(--link);
    border-bottom: 1px solid #000000;
    font-size: 14px;
}
.fact__value {
    padding: 7px 12px;
    border-bottom: 1px solid var(--rule-soft);
    font-size: 15px;
}
.facts .quiet { color: var(--link); font-size: 14px; }

/* Other work by the same maker, two across so eight fit without scrolling. */
.moreby        { padding: 16px 12px 0; }
.moreby__head  { font-size: 13px; color: var(--muted); margin-bottom: 8px; }
.moreby__head a { color: var(--ink); }
.moreby__list  { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 14px; font-size: 14px; }

.popup__shot    { display: block; width: 100%; height: auto; border: 1px solid var(--rule); }
.popup__caption { font-size: 12px; color: var(--muted); text-align: center; padding: 5px 0 0; }
.popup__noshot  {
    border: 1px dashed var(--rule-soft);
    color: var(--muted);
    font-size: 12px;
    text-align: center;
    padding: 32px 0;
}

/* The one thing the pop-up is for. */
.cta          { display: flex; flex-direction: column; gap: 9px; margin-top: 14px; }
.cta__go      { text-align: center; }
.cta__why     { font-size: 14px; color: var(--link); }
.cta__aside   { font-size: 12px; color: var(--muted); }

/* Said once, plainly, next to the download rather than in place of it -- the
 * requirement is a warning, not a refusal. See tracks.php on why minbuild
 * cannot be treated as a verdict. */
.buildnote {
    border: 1px solid var(--ink);
    background: var(--panel);
    padding: 10px 12px;
    margin-top: 14px;
    font-size: 14px;
}
.buildnote__head { color: var(--ink); font-weight: bold; margin-bottom: 4px; }
.buildnote__body { color: var(--link); line-height: 1.45; margin-bottom: 6px; }

/* The same box, borrowed onto MTMG reading pages, where it is a full-width
 * banner over 17px prose rather than a note in the download sidebar. The two
 * still want different numbers even now the sidebar has come up to 14: 14 is
 * right beside .cta__why and still short of a 17px reading measure, so MTMG
 * keeps its own 16. */
.mtmg--type .buildnote       { font-size: 16px; padding: 12px 14px; }
.mtmg--type .buildnote__body { line-height: 1.55; }

/* The download block is the same borrowing, and the same correction.
 *
 * cpod26/index.php is the one MTMG page built with .cta, because it is a
 * download page we wrote rather than a 2002 fragment. In the tracks sidebar
 * .cta__why is 12px and .cta__aside 11px, which is right in a narrow column
 * beside a button. On a 17px reading page they came out as fine print: the
 * site owner could not read the line about the forum thread.
 *
 * The 1px step between them is kept, so the aside is still the quieter of the
 * two -- 16 and 15 rather than 12 and 11. The sidebar is untouched. */
.mtmg--type .cta__why   { font-size: 16px; line-height: 1.55; }
.mtmg--type .cta__aside { font-size: 15px; line-height: 1.55; }

.popup__foot {
    padding: 9px 16px;
    border-top: 1px solid var(--rule);
    background: var(--bar);
    font-size: 12px;
    color: var(--muted);
}

/* ---------------------------------------------------- the pop-up frame --- */
/* Featherlight's own box, sized for details.php.
 *
 * This lived inline in tracks.php and was lost when that page was rebuilt, so
 * the details pop-up opened at featherlight's default size instead of the
 * 1000x600 the page is laid out for. It belongs here rather than in one page:
 * tracks.php, maker.php and details.php itself all open pop-ups now, and
 * three copies would be three chances to drift.
 *
 * The original comment is worth keeping -- it explains why a pop-up at all:
 * "workaround for the awful old window.open which doesn't work correctly on
 * multiple monitors".
 */
.featherlight-iframe .featherlight-content {
    width: 1000px;
    height: 600px;
    max-width: 90%;    /* keeps it responsive on small screens */
}
.featherlight-iframe iframe {
    width: 100% !important;
    height: 100% !important;
}

/* The JS viewers want the room, and 1000x600 is not it.
 *
 * That size belongs to details.php, which is laid out for it -- a picture, a
 * facts column and a download button. The track and truck viewers are a 3D
 * viewport with a control panel down one side and a minimap in the corner, and
 * at 1000x600 the viewport is the smallest thing on screen.
 *
 * Applied through featherlight's `variant`, which copies the name onto the
 * container, so the Load links opt in with
 * data-featherlight-variant="fl-viewer" and nothing else changes. One rule for
 * both viewers: they have the same shape and the same problem.
 *
 * Sized in viewport units rather than pixels. A fixed box would be too big on a
 * laptop and would still waste half a large monitor, and this is the one pop-up
 * where the extra space is the point. featherlight's own content style carries
 * margin-left/right of 5% and max-height 95%, so 90vw is the practical ceiling
 * anyway -- these numbers sit just inside it rather than fighting it. */
.featherlight-iframe.fl-viewer .featherlight-content {
    width: 1600px;
    height: 1000px;
    max-width: 90vw;
    max-height: 90vh;
}

/* ------------------------------------------------------------- sign in -- */

/* Turns 6a and 6b. Two treatments of one form.
 *
 * 6a is the page you reach on purpose: 620px, tiled like the rest of the
 * interior, hairline border, rhino and wordmark at the top.
 *
 * 6b is the same form reached by clicking a download while signed out. Design
 * gives it a different weight deliberately -- narrower, solid black rather than
 * tiled, edged in yellow rather than grey, and headed by a navy-deep bar. It
 * reads as an interruption to something you were doing, which is exactly what
 * it is, and the yellow edge is the one place on the site that border colour is
 * used to mean "this is the thing to deal with".
 *
 * The action button is YELLOW here, not the navy .btn--primary the listings
 * use. That is Design's call and it is the right one: on a page whose only
 * purpose is one button, the button should be the brightest thing on it. */

.signin-page {
    display: flex;
    justify-content: center;
    padding: 48px 18px;
}

.signin {
    width: 620px;
    max-width: 100%;
    border: 1px solid var(--rule);
    background: var(--bg) url(MTMGbg.gif) repeat;
}

.signin--download {
    width: 540px;
    border-color: var(--ink);
    background: var(--bar);      /* solid: no tile behind the interruption */
}

/* 6a's masthead — the one solid band, matching .site-head elsewhere. */
.signin__head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--rule);
    background: var(--bar);
}
.signin__head img   { display: block; }
.signin__title      { font-size: 20px; font-weight: bold; }

/* 6b's title bar. */
.signin__bar {
    background: var(--navy-deep);
    color: var(--on-navy);
    padding: 10px 16px;
    font-size: 14px;
    font-weight: bold;
}

.signin__body {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 22px 24px 26px;
}
.signin--download .signin__body { gap: 16px; padding: 18px 20px 20px; }

.signin__say {
    margin: 0;
    font-size: 15px;
    line-height: 1.7;
    color: var(--link);
}
/* Prose links inside the sign-in panel are yellow rather than link-grey: there
 * are only three of them and each one is a place to go next. */
.signin__say a,
.signin__forum a,
.signin__why a { color: var(--ink); text-decoration: none; }
.signin__say a:hover,
.signin__forum a:hover,
.signin__why a:hover { text-decoration: underline; }

/* -- what you were trying to download (6b) -- */

.signin__item {
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid var(--rule);
    background: var(--panel);
    padding: 10px;
}
.signin__item img     { display: block; border: 1px solid var(--rule); }
.signin__item div     { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.signin__item strong  { font-size: 15px; }
.signin__item span    { font-size: 13px; color: var(--link); }

/* -- the form -- */

.signin__form {
    display: flex;
    flex-direction: column;
    gap: 13px;
    margin: 0;
}
.signin--download .signin__form { gap: 10px; }

.signin__field { display: flex; flex-direction: column; gap: 6px; }
.signin__field span { font-size: 13px; color: var(--link); }

.signin__form input[type="text"],
.signin__form input[type="password"] {
    background: var(--panel);
    border: 1px solid var(--rule);
    color: var(--ink);
    font: 14px var(--font);
    padding: 10px 11px;
    outline: none;
}
.signin--download .signin__form input[type="text"],
.signin--download .signin__form input[type="password"] { padding: 9px 11px; }

.signin__form input::placeholder { color: var(--muted); }
/* The border is the focus ring: an outline would sit outside the 1px hairline
 * and read as a second box. */
.signin__form input:focus { border-color: var(--ink); }

/* AUTOFILL, which paints over all of the above.
 *
 * Pick a saved name from the browser's dropdown and Chrome marks the field
 * :-webkit-autofill and fills it with its own near-white background. That is
 * not a colour the page can set: `background` is ignored on an autofilled
 * field, which is why nothing in this stylesheet explained the symptom. It
 * then sticks until the field is edited, so the box stays bright -- reported
 * as the username going white and staying there, and only sometimes, because
 * it only happens when there is a saved name to pick.
 *
 * The inset box-shadow is the way through: shadows ARE honoured, so a 1000px
 * inset one repaints the whole box in --panel behind the browser's fill.
 * -webkit-text-fill-color for the text, since `color` is overridden too, and
 * caret-color so the cursor does not vanish against it.
 *
 * :hover, :focus and :active are listed because the fill is re-applied on each
 * of those states; one selector alone loses it again the moment you click in.
 *
 * TWO SEPARATE RULES, not one list. A selector a browser does not understand
 * invalidates the ENTIRE comma-separated group it appears in -- so pairing the
 * unprefixed `:autofill` with the prefixed one would drop both on any browser
 * that knows only `-webkit-autofill`, which is precisely the older browser most
 * likely to need this. Split, each stands or falls alone. */
.signin__form input:-webkit-autofill,
.signin__form input:-webkit-autofill:hover,
.signin__form input:-webkit-autofill:focus,
.signin__form input:-webkit-autofill:active {
    -webkit-box-shadow: 0 0 0 1000px var(--panel) inset;
            box-shadow: 0 0 0 1000px var(--panel) inset;
    -webkit-text-fill-color: var(--ink);
    caret-color: var(--ink);
}
/* The standard form. Firefox tints rather than repainting, and its tint is a
 * filter, so that is what has to be cleared there. */
.signin__form input:autofill,
.signin__form input:autofill:hover,
.signin__form input:autofill:focus,
.signin__form input:autofill:active {
    box-shadow: 0 0 0 1000px var(--panel) inset;
    caret-color: var(--ink);
    filter: none;
}

.signin__keep {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: var(--link);
    padding-top: 2px;
    cursor: pointer;
}
.signin__keep input { margin: 0; cursor: pointer; }

.signin__go {
    display: block;
    width: 100%;
    text-align: center;
    background: var(--ink);
    color: #000000;
    border: 0;
    font: bold 14px var(--font);
    padding: 11px 12px;
    cursor: pointer;
}
.signin--download .signin__go { font-size: 13px; padding: 10px 12px; }
.signin__go:hover { background: #FFFFFF; }

/* -- what failed, and where to go -- */

/* auth.php returns one message whatever went wrong, so this never has to carry
 * a list. Yellow-on-panel with a yellow edge, which is the same vocabulary as
 * the 6b border: something for you to deal with. */
.signin__error {
    margin: 0;
    border: 1px solid var(--ink);
    background: var(--panel);
    padding: 10px 12px;
    font-size: 14px;
    line-height: 1.6;
}

.signin__forum {
    display: flex;
    flex-direction: column;
    gap: 9px;
    border-top: 1px solid var(--rule);
    padding-top: 16px;
    font-size: 14px;
    color: var(--link);
}

.signin__after {
    margin: 0;
    font-size: 12px;
    line-height: 1.7;
    color: #999999;
}
.signin__after a { color: var(--link); text-decoration: none; }
.signin__after a:hover { color: var(--ink); text-decoration: underline; }

.signin__why {
    border: 1px solid var(--rule);
    background: var(--panel);
    padding: 13px 14px;
    font-size: 14px;
    line-height: 1.7;
    color: var(--link);
}
.signin__why span { color: var(--ink); }

/* ------------------------------------------------------------- upload -- */

/* Turns 6c and 6d. The two uploaders differ only in their field list, so they
 * share every class here and neither carries any styling of its own.
 *
 * Both were still on the 1999 stylesdefault.css until now: a 480px centred
 * <table class=detail> with right-aligned label cells. That layout is why the
 * grid below is 96px + 1fr with the labels right-aligned -- it is the same
 * shape, which is the shape people who upload here have used for twenty-odd
 * years. Only the skin changed. */

.upload-page {
    display: flex;
    justify-content: center;
    padding: 40px 18px;
}

.upload {
    width: 640px;
    max-width: 100%;
    border: 1px solid var(--rule);
    background: var(--bg) url(MTMGbg.gif) repeat;
}

.upload__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--rule);
    background: var(--bar);
}
.upload__brand { display: flex; align-items: center; gap: 12px; }
.upload__brand img { display: block; }
.upload__title { font-size: 19px; font-weight: bold; }

/* Account state, wherever it appears. See `.who` in the shared section below --
 * the uploader header, the site header and the details panel all say who you
 * are the same way, because they are all saying the same thing. */

.upload__body {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 18px 20px 24px;
}

.upload__intro {
    border: 1px solid var(--rule);
    background: var(--panel);
    padding: 13px 15px;
    font-size: 14px;
    line-height: 1.75;
    color: var(--link);
}
.upload__intro div { padding-top: 8px; }
.upload__intro a { color: var(--ink); text-decoration: none; }
.upload__intro a:hover { text-decoration: underline; }

/* -- fields -- */

.upload__fields { display: flex; flex-direction: column; gap: 13px; }

.upload__row {
    display: grid;
    grid-template-columns: 96px 1fr;
    align-items: center;
    gap: 12px;
}
/* The label column is a fixed 96px and the labels are right-aligned into it,
 * so wrapping is the thing to watch. Measured against the real seven -- Track
 * Name, Truck Name, Maker, Type, Requires, Zip File, Picture -- nothing wraps
 * until 18px, where the two Name labels break. 13 has room to spare; it stays
 * a step under the 14px input it names rather than being held there. */
.upload__row > span {
    font-size: 13px;
    color: var(--link);
    text-align: right;
}

.upload__row input[type="text"],
.upload__row select {
    background: var(--panel);
    border: 1px solid var(--rule);
    color: var(--ink);
    font: 14px var(--font);
    padding: 8px 10px;
    outline: none;
    width: 100%;
    box-sizing: border-box;
}
.upload__row input[type="text"]:focus,
.upload__row select:focus { border-color: var(--ink); }

/* The file inputs.
 *
 * Design draws these as a bordered "Choose file" button with the chosen
 * filename beside it. ::file-selector-button gets exactly that from the real
 * control, so there is no hidden input, no label-as-button, and no JavaScript
 * keeping a filename span in sync -- the browser already does all of it, and
 * the keyboard and screen-reader behaviour stays the browser's. */
.upload__row input[type="file"] {
    font: 14px var(--font);
    color: #999999;
    width: 100%;
}
.upload__row input[type="file"]::file-selector-button {
    border: 1px solid var(--rule);
    background: var(--panel);
    color: var(--link);
    font: 14px var(--font);
    padding: 7px 12px;
    margin-right: 10px;
    cursor: pointer;
}
.upload__row input[type="file"]::file-selector-button:hover {
    color: var(--ink);
    border-color: var(--ink);
}

/* Un-choosing a file.
 *
 * A file input can be pointed at a different file but never emptied, and the
 * picture is the optional one of the two -- so someone who attaches one and
 * then thinks better of it had no way back short of reloading the form and
 * retyping everything.
 *
 * The button is created by upload.js, not written into the markup, because it
 * cannot work without JavaScript. With the script blocked nothing appears and
 * the form behaves exactly as it did.
 */
.upload__file {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;        /* so a long filename shrinks instead of pushing the × out */
}
.upload__file input[type="file"] {
    min-width: 0;
    flex: 1;
}

.upload__clear {
    flex: none;
    width: 24px;
    height: 24px;
    line-height: 1;
    border: 1px solid var(--rule);
    background: var(--panel);
    color: var(--link);
    font: 15px/1 var(--font);
    cursor: pointer;
    padding: 0;
}
.upload__clear:hover {
    color: var(--ink);
    border-color: var(--ink);
}
.upload__clear[hidden] { display: none; }

/* -- which build it needs -- */

/* Yellow-edged, because it is the one field on the form that nothing else can
 * supply. Everything above it can be corrected later from the row itself; this
 * one is a fact about the file that only the person uploading knows.
 *
 * Deliberately NOT pre-filled by inspecting the zip. A pod can reference
 * models and textures from a pre-existing pod -- "podzipping" -- so the absence
 * of a .png proves nothing, and a .png that ships alongside a matching .raw is
 * a pod carrying both formats, which runs on the original game. A scanner would
 * have to be right about all three cases and would get less accurate as the
 * CP3 pool grows. Asking outright is both simpler and more honest. */
.upload__build {
    border: 1px solid var(--ink);
    background: var(--panel);
    padding: 14px 15px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.upload__build .upload__row > span { color: var(--ink); }
.upload__build select {
    background: var(--bar-soft);
    border-color: var(--ink);
}

.upload__hint {
    font-size: 13px;
    line-height: 1.7;
    color: var(--link);
    border-top: 1px solid var(--rule-soft);
    padding-top: 11px;
}
.upload__hint code {
    font: 12.5px var(--font-label);
    color: var(--ink);
}
.upload__note {
    font-size: 12px;
    line-height: 1.7;
    color: #999999;
}
.upload__note code { font: 12px var(--font-label); }

.upload__go {
    display: block;
    width: 100%;
    text-align: center;
    background: var(--ink);
    color: #000000;
    border: 0;
    font: bold 14px var(--font);
    padding: 11px 12px;
    cursor: pointer;
}
.upload__go:hover { background: #FFFFFF; }

/* -- the dots -- */

/* Kept, and kept working. The original marched ten GIFs from blue to purple
 * while the file went up, driven by a setTimeout walking document.images[] by
 * numeric index -- which broke the moment any other image appeared above them
 * on the page. Same effect, addressed by id instead. */
.upload__foot {
    border-top: 1px solid var(--rule);
    padding-top: 14px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    align-items: center;
    font-size: 13px;
    color: var(--link);
}
.upload__dots { display: flex; align-items: center; gap: 7px; }
.upload__dots img { display: block; }
.upload__thanks { color: #999999; }

/* -- the result page -- */

.upload__result {
    border: 1px solid var(--rule);
    background: var(--panel);
    padding: 14px 15px;
    font-size: 15px;
    line-height: 1.8;
}
.upload__result dl { margin: 0; display: grid; grid-template-columns: 96px 1fr; gap: 4px 12px; }
.upload__result dt { color: var(--link); font-size: 13px; text-align: right; }
.upload__result dd { margin: 0; word-break: break-all; }

/* Something went wrong and the file is not stored. Same vocabulary as the
 * sign-in error and the 6b border: yellow edge means deal with this. */
.upload__bad {
    border: 1px solid var(--ink);
    background: var(--panel);
    padding: 13px 15px;
    font-size: 14px;
    line-height: 1.7;
}

.upload__again {
    display: flex;
    gap: 10px;
    justify-content: center;
}

/* ---------------------------------------------------------------- who -- */

/* "signed in as ..." — the one treatment for account state.
 *
 * Design never draws a signed-in header: every mockup shows the Log in button,
 * because that is the state a visitor arrives in. But it does settle how
 * account state reads wherever it does appear -- Space Mono at 10px in #999,
 * in the Track Details panel (turn 5b) and in both uploader headers (6c, 6d).
 * So that is what this is, and the site header uses it too rather than
 * inventing a third size for the same sentence.
 *
 * Quiet on purpose. It is a status line, not a control -- but the sign-out
 * link inside it is underlined and always present, because a remembered login
 * that lasts thirty days has to have a visible way out on every page. That was
 * the condition for having remember-me at all.
 */
.who {
    font: 10px var(--font-label);
    color: #999999;
}
.who a { color: #999999; text-decoration: underline; }
.who a:hover { color: var(--ink); }
/* ----------------------------------------------------------------- mtmg -- */

/* Design's turns 8a, 8b and 11a-11d. One skin for all six.
 *
 * MTMG kept its own look for twenty-odd years -- silver menu links that go
 * white on navy, #848884 group headings, circle bullets -- and Design keeps
 * every one of those rather than repainting the section in the listings'
 * palette. They are already the right family: site.css took --navy and the
 * yellow from here in the first place. So this is the same section, re-laid
 * out, not a different one.
 *
 * What changes is the layout. It was a two-column <table class=page> assembled
 * from head.dat + menu.dat + a fragment, valid only once concatenated. It is a
 * grid now, and the "you are here" marker -- which the old markup could only
 * express by editing one of 35 copies of the menu -- is a class.
 */

/* Row 2: the guild banner and where you are. */
.mtmg-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 18px 24px;
    border-bottom: 1px solid var(--rule);
}
.mtmg-head img { display: block; max-width: 100%; height: auto; }
.mtmg-crumb {
    font: 11px var(--font-label);
    color: #848884;
    white-space: nowrap;
}

.mtmg {
    display: grid;
    grid-template-columns: 244px 1fr;
}

/* -- the menu -- */

/* Sticky, because these are tutorials read top to bottom and the menu is how
 * you get to the next page in a series. It was in a table cell before, so it
 * scrolled away and you went back up for it.
 *
 * min-height:0 with overflow-y:auto is what lets a 79-link menu (traxx) scroll
 * inside itself rather than forcing the page taller than the viewport, which
 * would defeat the stickiness.
 */
.mtmg-nav {
    border-right: 1px solid var(--rule);
    padding: 20px 18px 30px;
    display: flex;
    flex-direction: column;
    gap: 18px;
    position: sticky;
    top: 0;
    align-self: start;
    max-height: 100vh;
    min-height: 0;
    overflow-y: auto;
}

.mtmg-nav__group { display: flex; flex-direction: column; gap: 6px; }

/* #848884 is the legacy DT colour, kept. */
.mtmg-nav__head { color: #848884; font-size: 13px; }

/* A collapsible group.
 *
 * <details>/<summary> rather than a scripted accordion: it is the element for
 * the job, it works with JavaScript off, it is keyboard operable, and screen
 * readers announce expanded/collapsed without any ARIA of ours. traxx has 17
 * groups and 79 links -- without this, every tutorial page carries all 79 in
 * the margin, which is what Design's 8b collapses away.
 *
 * The default marker is removed and replaced by Design's count-and-triangle on
 * the right, because the count is the useful part: it says how much is behind
 * the heading before you spend a click on it.
 */
details.mtmg-nav__group > summary {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    cursor: pointer;
    list-style: none;          /* Firefox */
}
details.mtmg-nav__group > summary::-webkit-details-marker { display: none; }
details.mtmg-nav__group > summary:hover { color: #FFFFFF; }

.mtmg-nav__count { color: #999999; font-size: 11px; white-space: nowrap; }

/* The triangle turns to point down when the group is open, which is the one
 * thing the count alone cannot say. */
details[open] > summary .mtmg-nav__count { transform: rotate(90deg); }
.mtmg-nav__count { display: inline-block; transform-origin: 0.42em 0.52em; }

.mtmg-nav ul {
    list-style-type: circle;
    color: gray;              /* the bullet, not the text */
    margin: 0;
    padding-left: 17px;
}
.mtmg-nav li { margin-bottom: 4px; }

.mtmg-nav a {
    color: silver;
    text-decoration: none;
    font-size: 12px;
}
/* The original hover, unchanged: white on navy, no underline. */
.mtmg-nav a:hover {
    color: #FFFFFF;
    background: var(--navy);
}

/* You are here. The one thing the old menus could not say without being
 * copied and edited -- which is why there were 35 of them. */
.mtmg-nav a.is-here {
    color: #FFFFFF;
    background: var(--navy);
    padding: 1px 5px;
}

/* -- the content -- */

/* min-width:0 so a wide fragment scrolls inside its own column instead of
 * stretching the grid: these pages are full of 2002 markup with fixed-width
 * tables and screenshots, and one of them must not widen the page. */
.mtmg-body {
    padding: 22px 24px 32px;
    min-width: 0;
    overflow-x: auto;
}
.mtmg-title {
    font-size: 21px;
    font-weight: bold;
    margin: 0 0 20px;
}

/* The fragments are 2002 HTML and carry their own <font>, <center> and tables.
 * Rather than fight all of it, only the things that would actually break the
 * new layout are corrected. */
.mtmg-body img { max-width: 100%; height: auto; }
.mtmg-body table { max-width: 100%; }

/* -- the closing strip -- */

.mtmg-foot {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 26px;
    align-items: baseline;
    padding: 14px 24px;
    border-top: 1px solid var(--rule);
    background: var(--bar);
    font-size: 12px;
}
.mtmg-foot__head { color: #848884; }
.mtmg-foot a { color: silver; text-decoration: underline; }
.mtmg-foot a:hover { color: var(--ink); }

/* One column on a narrow screen. The menu stops being sticky first -- a
 * full-height sticky menu above the content is worse than no menu. */
@media (max-width: 860px) {
    .mtmg { grid-template-columns: 1fr; }
    .mtmg-nav {
        position: static;
        max-height: none;
        border-right: 0;
        border-bottom: 1px solid var(--rule);
    }
}



/* ------------------------------------------------- mtmg, turn 22 (read) -- */

/* Design's turns 21-22, the reading treatment. It applies to the 211 pages
 * that read top to bottom -- see _inc/mtmg-kinds.php for the list and how it
 * was arrived at -- and to nothing else. Galleries, tables and landings keep
 * the full-width layout, which is the site owner's rule as much as Design's:
 * a thumbnail grid wants every pixel and a table is already spending the width
 * on columns.
 *
 * WHY THE COLUMN NARROWS. MTMG ran body text the full width of the content
 * cell: 1021px at a 1280 viewport, about 157 characters. Comfortable is 45-75.
 * That is the single biggest reason the section is hard to read, and it is
 * free to fix.
 *
 * AND IT IS NOT A MODERN IMPOSITION. mtmg/about.php opens with
 * <table align="center" width="640"> -- somebody capped and centred the measure
 * in 2002, and it is the one page in the section that still reads well. Ninety
 * of the 331 pages cap their measure somehow; nine of those centre it. This
 * restores what the careful pages already did and the rest never got.
 *
 * THE LEFTOVER WIDTH IS SPLIT, not pushed to one edge. Design put it all in an
 * empty track at the right; the site owner asked for symmetric gaps with the
 * column centred, which reads as a margin on both sides rather than as a page
 * that has slid left. The rail, when it lands, stays pinned right.
 */

/* THE TYPE, on every page built out of 2002 markup.
 *
 * Split from the measure because they are different decisions. about.php
 * already caps and centres its own measure at 640 and looks right, so it is
 * a gallery and keeps its layout -- but it was still 13px Arial in #FFFF00,
 * because the whole treatment hung off one class. Reading type is an
 * improvement to any page carrying <font> tags; the narrow column is a
 * layout choice only prose wants.
 *
 * 34 pages take this without the measure: the picture walls, the 2002
 * reference tables, the template steps. The three pages we built ourselves --
 * utilities, inventory and models/browse -- take neither, because they have
 * their own typography already.
 *
 * Prose pages carry BOTH classes, so every rule below reaches them too. */
.mtmg--type .mtmg-body {
    font: 17px/1.68 var(--font-body);
    color: #E6DFC8;
}

.mtmg--read .mtmg-body {
    /* 780 of column less 34 of padding either side leaves 712px of text.
     *
     * Design asked for 540 -- about 75 characters, the textbook figure -- and
     * on the real pages it read as too narrow. This number is not a
     * compromise between the two, it is the house measure: ~traxx runs a 780px
     * container and ~binedit 760, both of them pages we built and both
     * settled. A section sitting between those two should not be a third
     * width.
     *
     * Wider than the textbook wants, about 96 characters at 17px -- but less
     * than two thirds of the 157 characters MTMG ran before, which was the
     * actual complaint.
     *
     * border-box so 780 means 780. Without it the padding is added on top and
     * the column comes out 848 wide -- this file sets no global box-sizing, so
     * every max-width here has to say it. */
    box-sizing: border-box;
    max-width: 780px;
    /* justify-self, NOT margin:0 auto. A grid item defaults to
     * justify-self:stretch, and a stretched item ignores auto margins --
     * they computed to 0 and the column sat hard against the menu with all
     * the empty space on the right, which is the one arrangement the site
     * owner asked not to have. */
    justify-self: center;
    /* ...and width, because justify-self:center also shrink-wraps. The
     * 780 above is only a cap, so a page whose widest thing is a 450px
     * table settled at 518 while the page beside it sat at 780 --
     * binedit/firstadvice against binedit/pageone. Measured across the
     * 277 reading pages: 255 already reached the cap by having a long
     * paragraph in them, and 22 did not. This is what makes the measure
     * one number instead of an accident of content. */
    width: 100%;
    padding: 30px 34px 44px;
    /* The base rule sets overflow-x:auto to stop a wide 2002 fragment
     * dragging the grid wider. Nothing in this column exceeds it any more --
     * see the picture cap below -- so there is nothing to scroll and a
     * scrollbar here would only ever be a rounding artefact. */
    overflow: visible;
}

/* Yellow stops being the text colour and becomes the heading colour.
 *
 * #FFFF00 on #000000 measures 19.6:1 -- the highest two colours can reach --
 * and yellow is the most luminous hue, so it blooms at reading size. Softening
 * it is the fix rather than a compromise. Pure #FFFF00 now means one thing
 * only, "where you are", and appears on three markers: the active item in the
 * site bar, and the active area and page in the left menu. */
.mtmg--type .mtmg-title {
    font: 700 31px/1.15 var(--font-head);
    letter-spacing: -0.01em;
    color: #F2CE4B;
    margin: 0 0 18px;
    padding-bottom: 14px;
    border-bottom: 1px solid #33312C;
}

/* A FRAGMENT'S OWN <h1> IS A PAGE TITLE.
 * 33 pages carry one -- all ten Cowpod pages, the 21 C-Pod26 pages, the FTP
 * and Daemon Tools pages. They are ours, written with real heading elements
 * rather than the 2002 <center><font size="+3"> idiom, so nothing styled them
 * and they fell back to the browser default: 34px Source Sans in body
 * parchment. Same rank as every other page title, so the same 32px Archivo
 * gold.
 *
 * Cowpod puts three lines in its title -- <h1>Cowpod 1.0.3</h1> then two <h2>
 * for the tagline and the section -- followed by an <hr>. The adjacency chain
 * catches exactly that shape and gives the rule the hairline every other page
 * title has. C-Pod26 and the rest are H1 + P and take only the first rule. */
.mtmg--type .mtmg-body > h1 {
    font: 700 32px/1.15 var(--font-head);
    letter-spacing: -0.01em;
    color: #F2CE4B;
    text-align: left;
    margin: 0 0 4px;
}
/* ...and the hairline every other page title carries. The <center> title block
 * gets it from a border 130 lines up; an <h1> page got nothing, so the 21
 * C-Pod26 pages opened with a title and then straight into text.
 *
 * ONLY when the <h1> opens the page. misc/ftp and misc/daemontools have a
 * <center> title block AND an <h1> under it as their first section heading --
 * giving that one a border drew a second full-width rule two lines below the
 * first. :first-child is what tells a page title from a heading that happens
 * to be an h1. */
.mtmg--type .mtmg-body > .mtmg-kicker + h1,
.mtmg--type .mtmg-body > h1:first-child {
    margin-bottom: 20px;
    padding-bottom: 14px;
    border-bottom: 1px solid #33312C;
}
/* A three-line title -- <h1>, a tagline, the section -- keeps the rule under
 * the LAST line, not the first. Cowpod draws it on that last line; Kmaster's
 * pages have their nav directly below, and its own border-bottom is the
 * hairline there, so bordering the <h1> as well drew two lines four rows
 * apart. Either way the <h1> does not carry it. */
.mtmg--type .mtmg-body > .mtmg-kicker + h1:has(+ h2 + h2),
.mtmg--type .mtmg-body > h1:has(+ h2 + h2) {
    margin-bottom: 4px;
    padding-bottom: 0;
    border-bottom: 0;
}
.mtmg--type .mtmg-body > h1 + h2 + h2:has(+ hr) {
    padding-bottom: 14px;
    border-bottom: 1px solid #33312C;
    margin-bottom: 20px;
}
.mtmg--type .mtmg-body > h1 + h2,
.mtmg--type .mtmg-body > h1 + h2 + h2 {
    font: 700 24px/1.25 var(--font-head);
    color: #F2CE4B;
    text-align: left;
    margin: 0;
}
/* Cowpod's own <hr> steps aside now that the h2 above carries the border.
 *
 * It was being restyled into the hairline, but it is <hr width="50%"> and the
 * attribute survives a border swap: it measured 356px against a 712px measure,
 * which is what the site owner saw as Cowpod's line being much shorter than
 * everyone else's. Hidden, exactly as the <hr> inside a <center> title block
 * is hidden, and for the same reason. */
.mtmg--type .mtmg-body > h1 + h2 + h2 + hr { display: none; }

.mtmg--type .mtmg-body h2,
.mtmg--type .mtmg-body h3 {
    /* 24px: the size a section heading renders at everywhere else in MTMG,
     * where the rank is written as <font size="+2"> or as the strong/span
     * idiom. 21 was a number I picked in isolation, and it left our own
     * pages a step smaller than the 2002 ones beside them. */
    font: 700 24px/1.25 var(--font-head);
    color: #F2CE4B;
    margin: 28px 0 9px;
}
.mtmg--type .mtmg-body h3 { font-size: 20px; }
.mtmg--type .mtmg-body h2:first-child { margin-top: 0; }

/* The headings that are not headings.
 *
 * Most of MTMG marks a heading with <font size="+2"> rather than <h2> -- 672
 * of them across the section, against 26 pages carrying real heading elements.
 * Rewriting 200 fragments to fix that is a different project; styling the tag
 * costs four rules and gives the section a visible hierarchy today.
 *
 * MEASURED, because I had this backwards first: <font size="+N"> is ABSOLUTE,
 * not relative. +1 renders 18px, +2 24px and +3 32px no matter what the parent
 * is set to -- the legacy sizes map to keyword sizes off the browser default,
 * not off the inherited size. So they do not scale with the new 17px base, and
 * +1 in particular stops reading as a heading beside it (18 against 17). That
 * is why +1 gets a size of its own here and the other two keep theirs. */
.mtmg--type .mtmg-body font[size="+1"],
.mtmg--type .mtmg-body font[size="+2"],
.mtmg--type .mtmg-body font[size="+3"] {
    font-family: var(--font-head);
    font-weight: 700;
    color: #F2CE4B;
    line-height: 1.25;
}
.mtmg--type .mtmg-body font[size="+1"] { font-size: 20px; }

/* A THIRD way of writing a heading, and the last one in the section.
 *
 * <p><strong><em><span style="font-size: medium">Heading<br></span></em>
 * </strong> -- what a late-2000s WYSIWYG editor emits, so it appears on the
 * pages written after the <font> era: the three community-patch pages, the
 * three renderer pages and cdaudio. 17 headings over 7 pages, and they were
 * the only ones left reading as italic body text while everything around them
 * had become gold Archivo.
 *
 * The full chain is the selector, not just span[style*=medium]: dxtory.php
 * has one of those spans that is NOT a heading, and a loose rule would have
 * turned a line of prose into one.
 *
 * font-style:normal is doing real work -- the italic is inherited from the
 * <em>, and a heading that stays italic still does not look like the others.
 * display:block gives it the line to itself that the trailing <br> was
 * faking. */
/* SAME IDIOM, NESTED THE OTHER WAY ROUND.
 * <strong style="font-size: medium"><em>Heading</em></strong> -- the style on
 * the <strong> instead of on a <span> inside it. The same editor emits both,
 * apparently depending on how the author selected the text, and this one is
 * the commoner of the two: 44 against 17, across the same seven pages. The
 * site owner named four it had missed on one page alone -- How to install?,
 * Before and After Gallery, Known issues, Patch history.
 *
 * A reminder that finding one shape of a thing is not finding the thing. */
.mtmg--type .mtmg-body strong[style*="font-size: medium"],
.mtmg--type .mtmg-body strong > em > span[style*="font-size: medium"] {
    display: block;
    font-family: var(--font-head);
    /* !important, and it is the only one in this file.
     * The size lives in a style ATTRIBUTE -- style="font-size: medium" --
     * and an inline declaration beats any selector a stylesheet can write.
     * Everything else here applied and the heading still came out at 16px,
     * medium's value, so it read as bold gold body text. The alternative is
     * editing seven fragments to strip an attribute, which is a worse trade
     * than one exception. */
    /* 24px, matching <font size="+2"> -- the size every other section
     * heading in MTMG lands on. 21 was picked to match .mtmg-body h2 and it
     * left the community patch pages visibly smaller than cnr, portforward
     * and helpfile beside them. Same rank, same size. */
    font-size: 24px !important;
    font-weight: 700;
    font-style: normal;
    line-height: 1.25;
    color: #F2CE4B;
    margin: 26px 0 9px;
}
/* The <br> inside it was the only thing separating heading from body. */
/* The italic is on a nested <em> in this shape, so normalising the outer
   element is not enough. */
.mtmg--type .mtmg-body strong[style*="font-size: medium"] em { font-style: normal; }
.mtmg--type .mtmg-body strong[style*="font-size: medium"] br,
.mtmg--type .mtmg-body strong > em > span[style*="font-size: medium"] br { display: none; }

/* Links inside the reading column.
 *
 * Underlined, which they are not elsewhere on the site: in a wall of running
 * text a colour change alone is weak, and these pages are full of links that
 * matter -- the next lesson, the file being described. The offset keeps the
 * rule off the descenders. */
.mtmg--type .mtmg-body a,
.mtmg--type .mtmg-body a:visited {
    color: silver;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.mtmg--type .mtmg-body a:hover { color: #FFFFFF; }

.mtmg--type .mtmg-body li {
    color: #E6DFC8;
    font-size: 17px;
    line-height: 1.68;
}

/* THE PAGE'S OWN TITLE BLOCK, made to match ours.
 *
 * 165 of the 295 treated pages open with <center><font size="+3">Title</font>
 * <br><font size="+2">(Subtitle)</font><hr width="47%"></center>. That is a
 * page title written the only way 2002 had, and it is the same thing
 * .mtmg-title is on the pages that pass a heading to the renderer.
 *
 * It was rendering two different ways. On a reading page the <center> rule
 * left-aligns the words but cannot move the <hr>, which keeps its own auto
 * margins and stays centred -- so the rule floated in from the left, under a
 * title that had moved. On a type-only page like about.php nothing moved and
 * the whole block stayed centred. Two page kinds, two headers.
 *
 * So the block is treated as the title it is: left, with the hairline
 * .mtmg-title already uses. The <hr> goes -- a 47%% rule is standing in for a
 * border, and the border does the job properly at any width.
 *
 * ONLY the leading one. The other 444 <hr> tags in the section are dividers
 * inside the text, and their short centred rules are the original design. */
/* A build note may stand in front of it.
 * Five pages open with <div class="buildnote"> -- the two archived community
 * patch pages, both renderer wrappers and the ISO page -- because we put a
 * "this is superseded" banner above the original title. :first-child then
 * matches nothing and those pages lost their header entirely. Same shape as
 * the lightbox <link> that used to sit inside the reading column: something
 * legitimate arrives before the content and a positional selector misses. */
/* WHERE YOU ARE, in words, over the title.
 *
 * Design's turn 22 panel puts "TRAXX / TRACK MAKING" here. The banner
 * row's breadcrumb already names the area; the group is the part neither
 * it nor the page title says, and it is the group the sidebar has open.
 *
 * This element is load-bearing beyond its own type: the title block below
 * is selected through it rather than through :first-child, because it now
 * stands in front of every title in the section. */
.mtmg-kicker {
    font: 11px/1.4 var(--font-label);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    /* the banner breadcrumb grey, so the two lines that say where you are
       agree with each other. Design draws both at #9A958A; the crumb has
       shipped at #848884 since turn 8a and is the one already on screen. */
    color: #848884;
    padding-bottom: 6px;
}
/* The separator is not a word, so it does not take the letterspacing that
   pushes the words apart -- it would otherwise drift right of centre. */
.mtmg-kicker span { letter-spacing: 0; padding: 0 2px; }

/* THE SUBTITLE IS QUIET, and the name is the loud one.
 *
 * Design draws the line under a page name at 17px in a warm grey, not at
 * 24px in gold -- "Making Tracks" then "Page One", one shouting and one
 * not. Ours had both in #F2CE4B at 24, so the subtitle competed with the
 * name instead of sitting under it.
 *
 * SCOPED TO THE TITLE BLOCK, and that is the whole difficulty. <font
 * size="+2"> is the commonest heading tag in the section -- 459 of them --
 * and only 236 are subtitles. The other 223 are section headings inside the
 * text, which are gold and stay gold. The selector has to name the four
 * shapes a title block takes rather than the tag.
 *
 * Cowpod runs three lines, so both of its lower two go quiet. Keyed on the
 * <hr> that closes its title, because binedit/extract is <h1> followed by a
 * section heading and must not be caught. */
.mtmg--type .mtmg-body > .mtmg-kicker + center font[size="+2"],
.mtmg--type .mtmg-body > .mtmg-kicker + .buildnote + center font[size="+2"],
.mtmg--type .mtmg-body > .buildnote + center font[size="+2"],
.mtmg--type .mtmg-body > center:first-child font[size="+2"],
.mtmg--type .mtmg-body > h1 + h2:has(+ h2),
.mtmg--type .mtmg-body > h1 + h2 + h2 {
    font-size: 17px;
    font-weight: 500;
    color: #9A958A;
}

.mtmg--type .mtmg-body > .mtmg-kicker + center,
.mtmg--type .mtmg-body > .mtmg-kicker + .buildnote + center,
.mtmg--type .mtmg-body > .buildnote + center,
.mtmg--type .mtmg-body > center:first-child {
    display: block;
    text-align: left;
    border-bottom: 1px solid #33312C;
    padding-bottom: 14px;
    margin-bottom: 20px;
}
.mtmg--type .mtmg-body > .mtmg-kicker + center hr,
.mtmg--type .mtmg-body > .mtmg-kicker + .buildnote + center hr,
.mtmg--type .mtmg-body > .buildnote + center hr,
.mtmg--type .mtmg-body > center:first-child hr { display: none; }

/* THE ERRORS PAGES: the title moves to the content, not the other way.
 *
 * Those nine keep their 2002 composition -- an index of links and 57 error
 * screenshots, all centred inside a 600px table. Left-aligning the title
 * against a page margin put it 300px from the text it names, and narrowing
 * the whole page to the reading column was tried and the site owner
 * preferred the original.
 *
 * So the title block takes the container's width and centring, and its own
 * text stays left. Its left edge then lands exactly on the table's. 600px
 * is hard-coded because every page in the set is <table width="600"> --
 * checked, all nine. */
.mtmg--titleblock .mtmg-body > .mtmg-kicker + center,
.mtmg--titleblock .mtmg-body > center:first-child {
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
}
/* A page whose content is one centred container: the container goes flush
   left, so it lines up with the title and the hairline above it instead of
   floating in the middle of its own column. about.php's 640px table is the
   case -- narrower than the 712px measure, so nothing is squeezed. */
/* Both shapes of centred container: a table that is a direct child (about.php)
   and one wrapped in a <center> (templates/index.php). The <center> is already
   left-aligned on a reading page, so the table inside it has no business
   staying centred. */
/* .mtmg--flush is doubled in the selector to raise specificity.
   The general table rule -- .mtmg--read .mtmg-body table { margin: auto } --
   ties this at (0,2,1) and sits 130 lines LATER, so it won on order and the
   flush did nothing on the pages whose container is a direct child rather
   than wrapped in a <center>. templates/note and 11advanced stayed 64px in
   while their fifteen siblings moved. */
.mtmg--flush.mtmg--flush .mtmg-body > table,
.mtmg--flush.mtmg--flush .mtmg-body > center > table { margin-left: 0; margin-right: auto; }

/* A key list: two columns that are a term and its meaning, not a grid of
 * data. The 2002 markup leans on the cell padding alone -- 1px, plus 2px
 * of border-spacing -- so the longest key lands 4px from its own dash and
 * Ctrl+mouseclick reads as one run-on word. The gap goes on the first
 * column only, so the meanings still start on one line.
 *
 * Opt-in by class rather than on table.note: .note is inert 2002 markup on
 * 78 pages and nothing in this file styles it, so giving it a padding here
 * would move 78 pages to fix one. */
.mtmg-body table.keys td:first-child { padding-right: 20px; }

/* A run of picture boxes needs air between them.
 *
 * traxx/psptxt stacks six of these -- Step 1, 2, 3 twice over -- each a 212px
 * bordered box holding one screenshot and its caption. The 2002 author had no
 * way to put a gap between two blocks, so he typed a line of dots between them
 * and let the line box do it: <center>...</center>, worth 29px. The dots are
 * gone; the 29px was doing real work and is what this replaces, because
 * without it the boxes butt into each other and read as one tall table.
 *
 * On the boxes, not on table.note -- .note is inert 2002 markup on 78 pages,
 * three of them on this page alone (the 60% and 70% note paragraphs and the
 * 202px pair), and none of those wants a margin. */
.mtmg-body table.stepbox { margin-bottom: 26px; }



/* A <blockquote> wrapped round the whole page is not a quotation.
 *
 * 22 of the 261 reading pages open with one -- cnr.php and rnr.php among
 * them -- and it is a 2002 indent, not a citation. The browser gives
 * blockquote 40px of margin each side, which cost those pages 80px of
 * measure and pushed the body 40px right of its own heading, so the text
 * neither lined up with the title nor got the width the column was widened
 * to give it. The site owner spotted both at once.
 *
 * Only a wrapper is flattened: a direct child of the column, or of the
 * <center> that is itself a direct child. A blockquote further in is quoting
 * something and keeps its indent. */
.mtmg--read .mtmg-body > blockquote,
.mtmg--read .mtmg-body > center > blockquote {
    margin-left: 0;
    margin-right: 0;
}

/* <center> around a paragraph.
 *
 * 178 of the 211 use <center>, and 76 of those centre a real block of running
 * text -- one of them 5,873 words. Centred prose is hard to read at any
 * measure and worse at a narrow one, because every line starts in a different
 * place. So text goes back to the left and the things <center> was actually
 * being used to position -- pictures and tables -- are re-centred by hand.
 * That is the same principle as the rest of this file: correct only what
 * breaks the new layout, and leave the 2002 markup alone otherwise. */
.mtmg--read .mtmg-body center { text-align: left; }
/* A picture that was the only thing in a <center> was being centred by the
   text-align it just lost, so it gets it back explicitly. Tables and other
   images are centred by the overhang rule below.

   :has(> img) IS LOAD-BEARING. Without it this matched every link directly
   inside a <center>, and MTMG is full of pipe navigations written that way --
   [ Intro | UI | Sorting | ... ] on all ten Cowpod pages, the template
   walkthroughs, 594 links over 56 pages. Every one of them became a block and
   the nav turned into a vertical list with its separators stranded down the
   left margin. The site owner found it on Cowpod, whose nav we had just
   finished getting right.

   If :has() were ever unavailable the picture simply sits left instead of
   centred, which is the harmless half of the trade. */
.mtmg--read .mtmg-body center > a:has(> img) { display: block; text-align: center; }

/* PICTURES STOP AT THE TEXT. (They used to hang past it.)
 *
 * A figure was allowed to exceed the measure, on the reasoning that a 540px
 * column is right for prose and wrong for a 700px screenshot. The idea was
 * that it would grow symmetrically, half each side, and the --bleed budget was
 * quartered rather than halved so that even a one-sided overhang would fit.
 *
 * It never grew symmetrically. auto margins cannot centre a box wider than its
 * container -- they resolve to 0 and -N, so every over-wide figure sat on the
 * text's left edge and hung off the right. The quartering was a workaround for
 * that, not a fix, and the file said so two hundred lines up while claiming
 * symmetry here.
 *
 * In practice four figures in the whole section were ever wide enough to use
 * it: 101px on the Community Patch masthead, then 69, 56 and 46. The site
 * owner: "it is literally the only one" that shows, "might as well" make it
 * general. So the cap is the measure, --bleed is gone, and a wide picture is
 * scaled to the column like every other. */
/* width:max-content, not auto. A table carrying width="100%" resolves that
   against the column and so never wants to be wider than it -- with width:auto
   it shrink-to-fits and the overhang is never used. Asking for its natural
   unwrapped width, capped below, is what actually lets a dense table spend the
   extra room. Measured: with auto, the widest figure across all 261 pages was
   exactly 540, which is the column -- nothing overhung at all. */
/* Every picture may EXCEED the measure without being squeezed to it. */
.mtmg--read .mtmg-body img {
    max-width: 100%;
    height: auto;
}

/* Only a FIGURE is centred and allowed to hang.
 *
 * Applying the centring to every <img> was wrong and the pages said so: MTMG
 * is full of 19-25px toolbar icons sitting inline in a sentence -- "click the
 * [icon] button" -- and left:50% threw them half a paragraph to the right, off
 * the page, taking the horizontal scrollbar with them. traxx/component.php has
 * nine pictures and five of them are that kind.
 *
 * A figure is a picture that stands alone: a direct child of the column, the
 * only thing in its paragraph, or inside the <center> the 2002 author wrapped
 * it in. An icon with words either side of it is none of those, and :only-child
 * is what tells them apart without asking the markup to be rewritten. */
/* Centred with auto margins, NOT with left:50% and a translate.
 *
 * That technique offsets an element from where it already sits, not from the
 * column, so it only happens to centre things that begin at the left edge. On
 * an inline icon mid-sentence it threw a 25px picture 356px to the right, off
 * the page. traxx/component.php showed it: Toolcomp.gif landed at x=1242 in a
 * column ending at 1145.
 *
 * display:block plus auto margins is what actually centres a box in its
 * container. It cannot centre one that does not fit -- that is why the
 * overhang above is gone rather than being made symmetric with a transform:
 * with nothing wider than the column, auto margins are exactly right and the
 * inline-icon trap the paragraph above describes stays shut. */
.mtmg--read .mtmg-body > img,
.mtmg--read .mtmg-body > a > img,
.mtmg--read .mtmg-body p > img:only-child,
.mtmg--read .mtmg-body p > a:only-child > img,
.mtmg--read .mtmg-body center > img,
.mtmg--read .mtmg-body center > a > img {
    display: block;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
}

/* ...unless the page has already put everything else against the left edge.
 *
 * On traxx/Kboard the heading, the rule under it and the key list all sit at
 * the text edge, so a centred 611px picture in a 712px measure landed 51px in
 * and was the one thing out of line. It keeps the auto margin on the right, so
 * it still cannot be dragged wider than the column.
 *
 * A class on the picture rather than a change to the rule above: centring a
 * standalone figure is right on the other 272 reading pages and none of them
 * has been looked at for this. Same reason .mtmg--flush is not extended to
 * images here -- that would move all 56 pages carrying it, to line up one. */
/* .flush is doubled to raise specificity, the same trick .mtmg--flush uses
 * above. The figure rule has four selectors and they do not score alike:
 * `center > img` is (0,2,2) and a single .flush beat it, but
 * `p > img:only-child` is (0,3,2) -- :only-child counts as a class -- and won,
 * so binedit/toolbar's strip stayed centred at 197px while Kboard's picture
 * moved. Doubling makes it (0,4,1), which clears both. */
.mtmg--read .mtmg-body img.flush.flush { margin-left: 0; margin-right: auto; }

/* A navy header row is yellow on navy, as it always was.
 *
 * The 53 header rows given #000080 across the section were left to inherit the
 * page's parchment, which is quiet against navy. C-Pod26's own tables never
 * did: .header2 has always been var(--ink), and --ink is #FFFF00, "the
 * original's yellow". The site owner found those while reading and preferred
 * them -- easier to read, and a nod to the 2002 look without shouting.
 *
 * This does spend #FFFF00 a second time. The rule elsewhere in this file is
 * that pure yellow means "where you are" and nothing else, so that is worth
 * knowing: it now also means "this row is a table's heading". The two never
 * appear in the same place -- one is chrome, one is inside a table -- and the
 * owner made the call knowing the first one.
 *
 * Keyed on the attribute rather than a class because that attribute IS the
 * change: every one of these rows was given bgcolor="#000080" by hand, page by
 * page, and none of them carries a link that would fight the colour. */
.mtmg--type .mtmg-body tr[bgcolor="#000080"] td { color: #FFFF00; }

/* TABLES KEEP THE WIDTH THEIR AUTHOR GAVE THEM, and do not overhang.
 *
 * They were briefly set to width:max-content so a dense table could spend the
 * overhang. That was wrong, and traxx/menufile.php showed it: most tables in
 * MTMG are not data at all, they are single-cell note boxes -- <table border
 * cols="1" width="450" class="note"> wrapped round a paragraph -- and
 * max-content means "as wide as you are allowed", so every one of them blew
 * out to the 813px cap and protruded past the prose it was annotating. That
 * page has nine tables and eight of them are single-cell.
 *
 * So no width is set here at all. The 450 in the markup is a presentational
 * hint the browser honours, and these authors chose their widths carefully --
 * about.php has capped and centred its measure at 640 since 2002. max-width
 * only stops one running past the column.
 *
 * Pictures still overhang: an image has an intrinsic size, so it takes the
 * room it actually needs rather than all the room on offer. A table asked for
 * max-content will always take everything. That asymmetry is the point. */
.mtmg--read .mtmg-body table {
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
}
/* ANYTHING INSIDE A TABLE CELL is laying out that cell, not presenting itself,
   so it stays exactly where it was put. Without this, left:50% is measured
   against the cell rather than the column: on traxx/component.php a 25px
   inline icon was thrown to x=1242 on a 1265px page and made the whole
   document scroll sideways. Found by measuring every figure on all 261 pages
   against the menu edge and the page edge. */
.mtmg--read .mtmg-body :is(td, th) :is(img, table),
.mtmg--read .mtmg-body table table {
    position: static;
    left: auto;
    transform: none;
    width: auto;
    max-width: 100%;
}


/* -- the chrome, on every MTMG page and not only the read ones -- */

/* Group labels in the menu and the closing strip. Archivo, small, letterspaced
 * and uppercase, which is what turns a word sitting above a list into a label
 * for it. The colour is untouched: #848884 is the legacy DT grey and the site
 * owner's preference is that the chrome keeps its original greys. */
.mtmg-nav__head,
.mtmg-foot__head {
    font: 600 11px/1.4 var(--font-head);
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: #848884;
}

/* Collapsed groups sit close together, per Design 22a and the site owner.
 *
 * The menu spaces its groups 18px apart, which is right for an OPEN group --
 * a heading with a list of links under it needs air above it to read as a
 * heading. A run of collapsed groups is not that: it is a list of one-line
 * labels, and 18px between single lines turns a compact index into a ladder.
 * Traxx has seventeen of them.
 *
 * Negative margin against the flex gap rather than a smaller gap everywhere,
 * because only the collapsed-next-to-collapsed case is wrong -- 18 less 11
 * leaves the 7px Design draws. Anything beside an open group keeps its air. */
.mtmg-nav > details:not([open]) + details:not([open]) { margin-top: -11px; }
/* And the group itself carries a 6px flex gap that a COLLAPSED group still
   pays. The hidden <ul> is not display:none -- display:flex on the <details>
   overrides how the browser would normally hide it -- so it stays a flex item
   and the gap before it counts, making a one-line label 21px tall instead of
   15. That 6px was the whole difference between our spacing and Design's:
   pitch 28 against 22. Nothing to space when nothing is showing. */
details.mtmg-nav__group:not([open]) { gap: 0; }

/* 12px was set for a menu beside 13px text. Beside a 17px column it reads as
 * fine print, and this is the section's primary navigation. */
.mtmg-nav a { font-size: 14px; }

/* You are here, in pure yellow -- one of the three places that colour is now
 * allowed to mean anything. It was white on navy, which said "selected" but
 * not "this is the page you are reading". */
.mtmg-nav a.is-here { color: #FFFF00; }

.mtmg-foot { font-size: 13px; }
/* The underline goes. A flat row of a dozen links is a navigation strip, and
 * underlining every one of them turns it into a hedge. */
.mtmg-foot a { text-decoration: none; }
.mtmg-foot a:hover { text-decoration: underline; }

@media (max-width: 860px) {
    /* Nothing to centre once the column is the whole width. */
    .mtmg--read .mtmg-body { max-width: none; padding: 22px 18px 32px; }
}


/* ------------------------------------------------------------- models -- */

/* Design's turn 19a: one browser over six archives, replacing 99 hand-written
 * pages -- 29 of which existed only to hold a LIMIT offset, so a category was
 * split across up to seven pages on boundaries that meant nothing and shifted
 * whenever a model was added in the middle. */

.models-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: 16px;
}
.models-head h1 { font-size: 21px; font-weight: bold; margin: 0 0 3px; }
.models-head__sub { font-size: 12px; color: var(--link); }

.models-search {
    display: flex;
    align-items: center;
    border: 1px solid var(--rule);
    background: var(--panel);
    margin: 0;
}
.models-search input {
    background: transparent;
    border: 0;
    color: var(--ink);
    font: 13px var(--font);
    padding: 8px 11px;
    width: 224px;
    max-width: 40vw;
    outline: none;
}
.models-search input::placeholder { color: var(--muted); }
.models-search button {
    color: var(--link);
    background: var(--navy-deep);
    border: 0;
    border-left: 1px solid var(--rule);
    font: 11px var(--font);
    padding: 8px 12px;
    cursor: pointer;
}
.models-search button:hover { color: #FFFFFF; }

/* -- the filter panel -- */

.models-filter {
    border: 1px solid var(--rule);
    background: var(--bar-soft);
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 11px;
    margin-bottom: 14px;
}
.models-filter__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 7px;
}
.models-filter__row--split {
    border-top: 1px solid #202020;
    padding-top: 10px;
}
.models-filter__label {
    font: 10px var(--font-label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #999999;
    padding-right: 4px;
}
/* Per page and the pager travel together on the right. Given separate auto
 * margins they split the slack into two gaps that read as an accident, and on a
 * narrow row the pager wrapped to the left of a new line -- the opposite corner
 * from where it belongs. */
.models-filter__right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
    justify-content: flex-end;
}
.models-filter__per {
    display: flex;
    align-items: center;
    gap: 7px;
}

/* Buttons, matching the listings' filter row: the chosen one is filled navy,
 * the rest are outlined. Same vocabulary as tracks.php, deliberately -- this is
 * the same kind of control doing the same job. */
.models-filter a:not(.btn),
.models-filter .is-on:not(.btn) {
    font-size: 12px;
    padding: 5px 11px;
    border: 1px solid var(--rule);
    text-decoration: none;
}
.models-filter a:not(.btn) { color: var(--link); background: var(--panel); }
.models-filter a:not(.btn):hover { color: var(--ink); border-color: var(--ink); }
.models-filter .is-on { color: var(--on-navy); background: var(--navy-deep); }

/* -- what you are looking at -- */

.models-summary {
    background: var(--navy);
    color: var(--ink);
    padding: 9px 12px;
    font-size: 13px;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 14px;
}
.models-summary__count { font-size: 12px; color: var(--link); }

.models-empty { font-size: 13px; color: var(--link); }
.models-empty a { color: var(--ink); }

/* -- the models -- */

/* auto-fill rather than Design's fixed repeat(3, 1fr): the sidebar is 244px and
 * these pages are read at every width from a laptop to a large monitor, so a
 * hard three columns is either cramped or wasteful depending on the screen. */
.models-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
    gap: 14px;
}

.models-card {
    border: 1px solid var(--rule);
    background: var(--bar-soft);
    display: flex;
    flex-direction: column;
}
.models-card:hover { border-color: var(--rule); }

/* contain, not cover: these are photographs of models against a background, and
 * cropping one to fill a box can cut the model out of its own picture. */
.models-card__pic {
    display: block;
    border-bottom: 1px solid var(--rule);
    background: var(--panel);
}
.models-card__pic img {
    display: block;
    width: 100%;
    height: 132px;
    object-fit: contain;
}

.models-card__body {
    padding: 10px 12px 11px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}
.models-card__top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}
.models-card__top a,
.models-card__top > span:first-child {
    color: var(--ink);
    text-decoration: none;
    font-size: 14px;
    font-weight: bold;
    min-width: 0;
    overflow-wrap: anywhere;
}
.models-card__top a:hover { text-decoration: underline; }

/* Which archive it came from. Small and outlined -- it is a fact about the
 * model, not a thing to click. */
.models-card__src {
    font-size: 10px;
    color: var(--link);
    border: 1px solid var(--rule);
    padding: 1px 5px;
    white-space: nowrap;
    flex: none;
}

.models-card__desc { font-size: 11px; color: var(--link); line-height: 1.5; }

.models-card__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 11px;
    color: #999999;
    padding-top: 4px;
    border-top: 1px solid #202020;
}
.models-card__foot a { color: var(--link); text-decoration: none; }
.models-card__foot a:hover { color: var(--ink); }

.models-pager {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 18px;
    margin-top: 18px;
    font-size: 12px;
    color: var(--link);
}
.models-pager a { color: var(--link); }
.models-pager a:hover { color: var(--ink); }

/* Which shelf a search result sits on. Only rendered while searching -- inside
 * a category every card would say the same thing. Two badges is possible and
 * correct: one model in the archive is on two shelves. */
.models-card__cats {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 1px;
}
.models-card__cats a {
    font: 10px var(--font-label);
    color: var(--on-navy);
    background: var(--navy);
    text-decoration: none;
    padding: 1px 6px;
}
.models-card__cats a:hover { color: var(--ink); }

/* The section's own thanks, from the landing page this browser replaces. Small
 * and at the foot -- it is history rather than navigation, and losing it with
 * the page would have been the easy thing to do. */
.models-credit {
    margin: 22px 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--rule-soft);
    font-size: 11px;
    line-height: 1.7;
    color: #999999;
}
.models-credit a { color: var(--link); }
.models-credit a:hover { color: var(--ink); }

/* The pager sits at the far right of the view-controls row, after Per page. */
.models-filter .pager--top { margin-left: 14px; }

/* The divider belongs between two rows, not above the first one. Seven of the
 * seventeen categories live in a single archive, so their Game row is dropped
 * -- it could only have said "All 1 / Custom" -- which leaves Sort as the only
 * row, and its top border reading as a line to nowhere. */
.models-filter__row--split:first-child {
    border-top: 0;
    padding-top: 0;
}

/* ----------------------------------------------------------- tourneys -- */

/* Design's turns 14a, 14b and 14c. The scoring layout -- five rounds, a total,
 * ordered by finish with the winner emphasised -- is kept as it was: it reads
 * well already and the people who use these pages have read it that way for
 * years. What changed around it is the chrome and the load. */

/* -- one event's result -- */

/* The event name above its table.
 *
 * Centred and stacked, because the name and the date are both what the event
 * IS -- a right-aligned date reads as metadata about something else.
 *
 * NO BACKGROUND. It had a navy bar briefly, matching the panels and the table
 * head, and that was one navy block too many: with a filled table directly
 * under it and a navy header row inside that, the page turned into stacked
 * bands. The tile is quiet enough behind a single line of large text -- it was
 * the ruled rows underneath that needed a solid ground, not this. */
.tourney-head {
    padding: 0 0 12px;
    text-align: center;
}
.tourney-head__name {
    font-size: 19px;
    font-weight: bold;
    color: var(--ink);
}
.tourney-head__date {
    font-size: 12px;
    color: var(--link);
    padding-top: 3px;
}

.tourney-none { font-size: 13px; color: var(--link); }

/* The five rounds are fixed-width so the columns line up down the table, and
 * the name takes whatever is left. Grid rather than a table because each row is
 * a single element that can carry the winner's treatment as a whole.
 *
 * Solid, not the tile showing through -- the same call as the record panels.
 * Design leaves these transparent and on a mockup that reads fine, because
 * there is no tile in the picture. On the page there is: a repeating watermark
 * behind every row, with a rule under each one, is two patterns and a grid
 * competing in the same space. The table fills, so the tile frames it instead.
 */
.scores {
    display: block;
    background: var(--bar-soft);
    border: 1px solid var(--rule);
}

.scores__head,
.scores__row {
    display: grid;
    grid-template-columns: 1fr 78px 78px 78px 78px 78px 96px;
    align-items: center;
}
.scores__head {
    background: var(--navy-deep);
    color: var(--on-navy);
    font-size: 12px;
    font-weight: bold;
}
.scores__head > div,
.scores__row > div { padding: 8px 10px; }

.scores__head > div:not(:first-child),
.scores__row > div:not(.scores__name) { text-align: center; }

.scores__row {
    border-bottom: 1px solid var(--rule);
    font-size: 13px;
    color: var(--link);
}
.scores__row:last-child { border-bottom: 0; }
.scores__name a { color: var(--link); text-decoration: none; }
.scores__name a:hover { color: var(--ink); text-decoration: underline; }

/* The finishing position, ahead of the name and deliberately quieter than it --
 * it labels the row rather than being the thing you came to read. */
.scores__pos { font-size: 11px; color: #999999; }

/* The winner. A yellow rule under the row and the name in italic yellow, which
 * is how the original marked it -- kept, because it is legible at a glance and
 * costs no colour the page was not already spending. */
/* Lighter than the rows around it now that they are filled too -- the yellow
 * rule alone did the work when everything else was tile. */
.scores__row.is-winner {
    border-bottom-color: var(--ink);
    background: #131313;
    color: var(--ink);
}
.scores__row.is-winner > div { font-weight: bold; font-style: italic; }
.scores__row.is-winner .scores__name a { color: var(--ink); }
.scores__row.is-winner .scores__pos { color: #999999; font-weight: normal; font-style: normal; }

.scores__points { color: var(--ink); }

/* On a narrow screen the five round columns are what has to give: the name and
 * the total are the parts you can still read something from. */
@media (max-width: 720px) {
    .scores__head,
    .scores__row { grid-template-columns: 1fr 52px 52px 52px 52px 52px 64px; }
    .scores__head > div,
    .scores__row > div { padding: 7px 5px; font-size: 12px; }
}

/* -- the tourney filter bar -- */

/* Same vocabulary as the listings' filter row: the chosen one filled navy, the
 * rest outlined. Two rows -- what you are looking at, then how it is ordered --
 * separated by a hairline, exactly as the tracks bar separates its controls
 * from its alphabet. */
.tourney-filters .filters__row { align-items: center; gap: 7px; }
.tourney-filters .filters__row--sort {
    border-top: 1px solid #202020;
    padding-top: 12px;
}
.tourney-filters .filter__label { padding-right: 4px; }

.tourney-filters a,
.tourney-filters .is-on {
    font-size: 12px;
    padding: 5px 11px;
    border: 1px solid var(--rule);
    text-decoration: none;
    white-space: nowrap;
}
.tourney-filters a { color: var(--link); background: var(--panel); }
.tourney-filters a:hover { color: var(--ink); border-color: var(--ink); }
.tourney-filters .is-on { color: var(--on-navy); background: var(--navy-deep); }
/* The event count rides along with the season but should not compete with it. */
.tourney-filters a .quiet { color: var(--muted); }

.tourney-summary {
    background: var(--navy);
    color: var(--ink);
    padding: 9px 12px;
    font-size: 13px;
    margin-bottom: 14px;
}

/* The breadcrumb back to the table, in the page title. */
.page-head__title .crumb { color: var(--muted); padding: 0 4px; }
.page-head__title a { color: var(--link); text-decoration: none; }
.page-head__title a:hover { color: var(--ink); }

/* The zoomed player's profile link, in the same title. Secondary to the
 * player's own name -- normal weight and smaller, same idea as .rows .quiet
 * on the listings, so it reads as a door to more, not a second heading. */
/* UNDERLINED, and in the link colour rather than --muted.
 *
 * This sat at the end of a breadcrumb -- "Tracks > Fila . profile" -- in grey,
 * at the same weight as the crumbs, with text-decoration: none. So the one
 * word on the line that goes somewhere looked exactly like the two that do
 * not, and the site owner's verdict on finding it was "I was never gonna
 * notice that". They were right: it was a link only in the markup.
 *
 * Underline because that is what this site already does when it wants a link
 * read as a link inside other text -- see .rows .revue. The crumbs themselves
 * stay undecorated, so the underline is now the thing that separates "where
 * you are" from "where you can go". */
.page-head__title .profile-link {
    font-size: 12px;
    font-weight: normal;
    color: var(--link);
    text-decoration: underline;
    margin-left: 6px;
}
.page-head__title .profile-link:hover { color: var(--ink); }

/* -- the season table (14b) and a player's events (14c) -- */

.scores__head--table,
.scores__row--table { grid-template-columns: 46px 1fr 84px 84px 84px 84px 92px; }

.scores__head--events,
.scores__row--events { grid-template-columns: 1fr 128px 96px 96px; }

/* The rank column sits ahead of the name and is quieter than it, the same
 * relationship the finishing position has on a result. */
.scores__rank {
    font-size: 11px;
    color: #999999;
    text-align: right !important;
}

/* Whichever column the table is ordered by. Design marks it, and it is worth
 * marking: five numeric columns look alike, and the one that explains the row
 * order should not have to be inferred from the filter bar. */
.is-sorted { color: var(--ink); font-weight: bold; }

/* -- a player's record (14c) -- */

/* Two columns: the two finish breakdowns stack on the left, the summary sits
 * beside them. Not three equal columns -- the finishes are the same kind of
 * thing as each other and a different kind from the summary, and stacking them
 * says so. */
.rec {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    align-items: start;
    gap: 16px;
    margin-bottom: 18px;
}
.rec__col { display: flex; flex-direction: column; gap: 16px; }

/* Solid, not the tile showing through.
 *
 * Design leaves these panels transparent, and on a mockup that is fine. On the
 * real page the MTMG tile runs behind them, and a tile behind a bordered box
 * full of ruled rows is three patterns competing in one small space. The panel
 * fills instead, so the tile frames the content rather than showing through it,
 * and the rules inside have a plain ground to sit on. */
.rec__panel {
    border: 1px solid var(--rule);
    background: var(--panel);
}

/* A navy bar with yellow on it, which is Design 14c and is what the rest of the
 * site already does -- the listing header, the summary line above a result, the
 * table head. A panel heading in plain yellow read as a different vocabulary on
 * a page that had no need of one. */
.rec__head {
    background: var(--navy);
    color: var(--ink);
    padding: 8px 12px;
    font-size: 13px;
    font-weight: bold;
}
.rec__line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 13px;
    color: var(--link);
    padding: 7px 12px;
    border-bottom: 1px solid #202020;
}
.rec__line:last-child { border-bottom: 0; }
.rec__line > span:last-child { color: var(--ink); white-space: nowrap; }

/* The count is the evidence and the share is the reading, so the fraction is
 * the brighter of the two and the percentage trails it. */
.rec__pct { color: var(--link); padding-left: 5px; font-weight: normal; }

/* A note under a panel rather than a row in it -- it is a sentence, not a
 * measurement, and giving it a value column would misrepresent it. */
.rec__note {
    font-size: 12px;
    line-height: 1.6;
    color: #999999;
    padding: 9px 12px 0;
}

@media (max-width: 720px) {
    .scores__head--table,
    .scores__row--table { grid-template-columns: 38px 1fr 46px 60px 52px 40px 52px; }
    .scores__head--events,
    .scores__row--events { grid-template-columns: 1fr 88px 60px 60px; }
}

/* Each event on the season list, separated so the tables do not run together. */
.tourney-event { margin-bottom: 26px; }
.tourney-event:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------ replays -- */

/* Design's turn 15a. Eleven videos and no database.
 *
 * The point of the rebuild is what is NOT here: eleven <iframe>s. Each card
 * shows the video's own still from img.youtube.com and creates the player only
 * when someone clicks it, so the page costs one image each instead of eleven
 * connections to YouTube on every load. */

.replays__say {
    font-size: 13px;
    line-height: 1.7;
    color: var(--link);
    max-width: 760px;
    margin: 0 auto 18px;
    text-align: center;
}
.replays__none { font-size: 13px; color: var(--link); text-align: center; }
.replays__none a { color: var(--ink); }

/* Sized so a card is worth looking at.
 *
 * Design lays these out as repeat(3, 1fr) on a 1280px page, which is about
 * 400px a card -- the still is the whole point, and below roughly that you
 * cannot tell one dirt track from another. auto-fill with a 400px floor keeps
 * that size and still reflows: three across at 1280, more on a wide monitor
 * rather than the eight tiny ones a 300px floor was packing in.
 */
.replays {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
    gap: 16px;
}

.replay {
    border: 1px solid var(--rule);
    background: var(--bar-soft);
}

/* 16/9 so the poster and the player that replaces it are the same size and the
 * grid does not jump when one becomes the other. */
.replay__poster,
.replay__frame {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 0;
    border-bottom: 1px solid var(--rule);
    background: #000000;
}
.replay__poster { position: relative; }
/* hqdefault is 4:3 with the video letterboxed inside it, so cover crops the
 * bars away rather than showing black above and below the still. */
.replay__poster img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.replay__play {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 34px;
    color: #FFFFFF;
    text-shadow: 0 0 14px rgba(0, 0, 0, 0.9);
    opacity: 0.82;
}
.replay__poster:hover .replay__play { opacity: 1; color: var(--ink); }

.replay__body { padding: 10px 12px 11px; }
.replay__title { font-size: 14px; font-weight: bold; color: var(--ink); }

.replay__meta {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 11px;
    color: #999999;
    padding-top: 4px;
}
.replay__meta a { color: var(--link); }
.replay__meta a:hover { color: var(--ink); }
.replay__by { color: #999999; }

/* ------------------------------------------------------- kmaster tools -- */

/* Design's turns 16a to 16e. Four of Kmaster's tools, one page each plus a
 * landing page.
 *
 * The row between them is the only way from one to the next -- kmaster/menu.dat
 * lists "Kmaster's Utilities" once and does not name the tools -- so it moves
 * out of the <center> block it lived in and becomes navigation proper, in the
 * same bracket vocabulary the archive footers use. */

.kmaster-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 0;
    /* 16px, not the 12 this was written at.
     * 12 was right beside 13px body text and is tiny beside 17 -- the site
     * owner's word. Cowpod's equivalent strip is plain links inheriting the
     * body size, so this wants to be close to it; 16 is as near as it gets
     * while these seven long labels still fit two lines in the 712px measure.
     * At 17 they take three. */
    font-size: 16px;
    padding: 0 0 16px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 18px;
}
.kmaster-nav a          { color: var(--link); text-decoration: none; padding: 0 8px; }
.kmaster-nav a:hover    { color: var(--ink); }
.kmaster-nav .is-here   { color: var(--ink); padding: 0 8px; }

/* WHERE YOU ARE, inside an in-page menu.
 *
 * Kmaster's row does this already -- the current page is plain text rather
 * than a link to itself, in pure #FFFF00 -- and the site owner asked for it
 * across the other two in-page menus. It reads well precisely because the
 * body no longer uses that yellow: turn 22 moved reading text to parchment
 * and headings to #F2CE4B, which left pure yellow free to mean one thing.
 * The site nav and the sidebar already use it that way; this is the same
 * marker one level down.
 *
 * Scoped to .mtmg-body so it cannot reach .mtmg-nav a.is-here in the sidebar,
 * which is white-on-navy and a different signal. */
.mtmg-body .is-here { color: #FFFF00; }
.kmaster-nav .bracket   { color: var(--link); padding: 0 8px; }
.kmaster-nav .sep       { color: var(--rule); }

/* .util__say is a 720px block with margin 0 -- inheriting text-align:center
 * centres its words INSIDE a box still pinned to the left, which is why the
 * subtitle and the row count sat off to one side while everything around
 * them was centred. The auto margins centre the box itself. */

/* The pages themselves: a heading, a paragraph, a list of features or
 * limitations, repeated. The old markup did headings with <font size="+2"> and
 * lists with "- item<br>", so both are real elements now and the spacing comes
 * from the stylesheet rather than from stacked <br>s. */
.mtmg-body h2 {
    font-size: 17px;
    font-weight: bold;
    color: var(--ink);
    margin: 26px 0 8px;
}
.mtmg-body h2:first-child { margin-top: 0; }

.mtmg-body ul {
    margin: 0 0 4px;
    padding-left: 18px;
    list-style-type: square;
    color: var(--rule);          /* the marker; the text sets its own colour */
}
.mtmg-body li {
    color: var(--link);
    font-size: 13px;
    line-height: 1.6;
    margin-bottom: 3px;
}

/* ---------------------------------------------------- mtmg utilities -- */

/* Design's turn 17a. Forty-six downloads doing four different jobs.
 *
 * The source was three stacked tables with nothing tying them together, and the
 * generations mixed into the first: Winpod32 marked "(recommended version!)"
 * with plain Winpod nineteen rows above it, and Traxx three times over. So the
 * grouping carries the information the alphabetical list could not. */

/* The page title and its search, the row every other section has. This page
 * had no title of its own -- it went straight from the guild banner into a
 * paragraph, so nothing on screen said what you were looking at. */
.util__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    /* Ruled above and below, so the title and its search read as one band the
     * way .page-head does elsewhere. Pulled out to the full width of the body
     * with negative margins -- the band spans the column, the padding puts the
     * words back where the content sits. */
    margin: -22px -24px 22px;
    padding: 14px 24px;
    border-top: 1px solid var(--rule);
    border-bottom: 1px solid var(--rule);
}
.util__bar h1 {
    font-size: 21px;
    font-weight: bold;
    color: var(--ink);
    margin: 0;
}

.util__say {
    font-size: 13px;
    line-height: 1.7;
    color: var(--link);
    max-width: 720px;
    margin: 0 0 24px;
}
.util__say b { color: var(--ink); }

.util { margin-bottom: 28px; }
.util:last-child { margin-bottom: 0; }

.util__head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 2px;
}
.util__head h2 {
    font-size: 17px;
    font-weight: bold;
    color: var(--ink);
    margin: 0;
}
/* What the group means, beside the name rather than under it -- these headings
 * need a qualifier to be useful ("Legacy" alone reads as "broken") and a
 * qualifier that needs its own line reads as body copy. */
.util__note { font-size: 12px; color: #999999; }
.util__count {
    margin-left: auto;
    font: 11px var(--font-label);
    color: var(--muted);
}

.util__rows { display: block; }

/* Name, description, size. The size is last and narrow because it is the least
 * of the three -- the source put it inside the name, in brackets, which is why
 * every row read "Winpod32 (78k)" before the eye reached the description. */
.util__row {
    display: grid;
    grid-template-columns: 268px 1fr 90px;
    align-items: baseline;
    border-bottom: 1px solid var(--rule);
    font-size: 13px;
}
.util__row > div { padding: 8px 12px; }
.util__row:last-child { border-bottom: 0; }

/* The column header, navy, the same bar the listings and the tourney tables
 * use. Without it the first row of a group had nothing above it saying which
 * column was which -- and the size column in particular is unreadable as a
 * bare number in the right margin. */
.util__row--head {
    background: var(--navy-deep);
    color: var(--on-navy);
    font-size: 12px;
    font-weight: bold;
    border-bottom: 0;
}
.util__row--head > div:last-child { text-align: right; }

.util__name a { color: var(--ink); text-decoration: none; }
.util__name a:hover { text-decoration: underline; }
/* Says what the link is, not how big it is -- these three point at a page. */
.util__islink { font-size: 11px; color: #999999; padding-left: 4px; }

.util__desc { color: var(--link); line-height: 1.55; }
.util__size { color: #999999; text-align: right; white-space: nowrap; font-size: 12px; }

.util__also {
    font-size: 12px;
    line-height: 1.7;
    color: var(--link);
    margin: 14px 0 0;
    padding: 12px 14px;
    border: 1px solid var(--ink);
    background: var(--panel);
}
.util__also a { color: var(--ink); }
/* It was one sentence; it is now four short paragraphs, because it has to
 * name six programs and say which two of them are alternatives to rows in
 * the table above. Tight leading between them so it still reads as one
 * aside and not as a section. */
.util__also p { margin: 0 0 9px; }
.util__also p:last-child { margin-bottom: 0; }

@media (max-width: 640px) {
    .util__row { grid-template-columns: 1fr 70px; }
    /* The description drops under the name rather than being squeezed to a
     * column too narrow to read. */
    .util__desc { grid-column: 1 / -1; padding-top: 2px; }
}

/* "1.5.12 is newer." -- the pointer to a current version, on the rows the
 * source says are superseded. Yellow because it is the one thing on a legacy
 * row that changes what you do next: everything else on the row describes the
 * program, this says do not take it. */
.util__newer { color: var(--ink); }

/* ----------------------------------------------------------- inventory -- */

/* Turn 18a. The 2004 index of the download folders, which is mostly a list of
 * things that are gone. In the original a lost file was pink italic text with
 * its link commented out -- indistinguishable from a styling quirk. Here the
 * three states are marked, counted and filterable, and a missing row carries
 * the one action that can fix it. */

/* The ask, and the reason the page exists. Yellow border because it is the
 * only thing on the page that is addressed to the reader rather than
 * describing a file -- the same weight .util__also has, turned up one step. */
.inv__ask {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px 20px;
    border: 1px solid var(--ink);
    background: var(--panel);
    padding: 14px 16px;
    margin: 0 0 22px;
}
.inv__ask-say {
    font-size: 12px;
    line-height: 1.7;
    color: var(--link);
    max-width: 760px;
}
.inv__ask-say b { display: block; font-size: 14px; color: var(--ink); margin-bottom: 4px; }

/* The count on a filter chip. Dimmer than the label so the row reads as words
 * first and numbers second. */
.inv__tally { color: var(--muted); }
.btn--on .inv__tally { color: var(--on-navy); }

/* The four source files, which is the only loss on this page that is final.
 * Everything else is a program somebody somewhere may still have on a disk. */
.inv__lost {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 24px;
    border: 1px solid var(--rule);
    background: var(--bar-soft);
    padding: 12px 15px;
    margin: 0 0 22px;
    font-size: 12px;
    color: var(--link);
}
.inv__lost b { color: var(--ink); }

/* A filename quoted in running text. */
.inv__file { font: 11.5px var(--font-label); color: var(--link); }

.inv { margin-bottom: 26px; }
.inv:last-of-type { margin-bottom: 0; }

.inv__head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 2px;
}
.inv__head h2 {
    font: bold 15px var(--font-label);
    color: var(--ink);
    margin: 0;
}
.inv__head .btn { margin-left: auto; padding: 4px 10px; }

/* Mark, file, description, action. The mark column is narrow and first because
 * it is what the eye scans down -- the whole page is a question about which
 * rows are which. */
.inv__row {
    display: grid;
    grid-template-columns: 30px 300px 1fr 118px;
    align-items: baseline;
    border-bottom: 1px solid var(--rule-soft);
    font-size: 13px;
}
.inv__row > div { padding: 8px 10px; }
.inv__row:last-child { border-bottom: 0; }
/* The header row carries .util__row--head as well, which supplies the navy
 * fill and the right-aligned last column; nothing extra is needed here. */

/* Filled for a file that is there, hollow for one that is not. A shape rather
 * than a colour, so the state survives being printed, being read by someone
 * who cannot separate the greys, and being glanced at. */
.inv__mark { color: var(--muted); font-size: 11px; }
.inv__row:not(.inv__row--gone) .inv__mark,
.inv__mark--here { color: var(--ink); }

.inv__name { font: 12px var(--font-label); word-break: break-all; }
.inv__name a { color: var(--ink); text-decoration: none; }
.inv__name a:hover { text-decoration: underline; }
/* A missing name is not a link and should not look like one. Dimmed rather
 * than struck through: the file is not cancelled, it is wanted. */
.inv__row--gone .inv__name { color: var(--link); }

.inv__desc { color: var(--link); line-height: 1.55; }

/* On the shelf, but the 2004 index never knew about it. Not a fourth state --
 * the file is there like any other -- so it is a tag on the row rather than a
 * different mark in the margin. */
.inv__tag {
    font: 10px var(--font-label);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
    border: 1px solid var(--rule-soft);
    padding: 1px 5px;
    white-space: nowrap;
}

.inv__star { color: var(--ink); font-size: 11px; }

/* Size for a file that is here; the one thing you can do about one that is
 * not. Right-aligned so the column reads as a single answer to "have it?". */
.inv__act { text-align: right; color: var(--muted); font-size: 12px; white-space: nowrap; }
.inv__send,
.inv__send:visited {
    color: var(--ink);
    text-decoration: none;
    font-size: 12px;
    border: 1px solid var(--ink);
    padding: 3px 10px;
}
.inv__send:hover { color: #000000; background: var(--ink); }

.inv__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px 16px;
    border-top: 1px solid var(--rule);
    margin-top: 22px;
    padding-top: 13px;
    font-size: 12px;
    color: var(--link);
}
.inv__foot .inv__tag { text-transform: none; letter-spacing: 0; }
.inv__by { color: var(--muted); font-size: 11px; }

.inv__also {
    font-size: 12px;
    line-height: 1.9;
    color: var(--link);
    margin: 14px 0 0;
}

@media (max-width: 720px) {
    /* Mark and name stay on the first line with the action; the description
     * drops under them rather than being squeezed to a column too narrow to
     * read, the same way the utilities rows fold. */
    .inv__row { grid-template-columns: 30px 1fr 96px; }
    .inv__desc { grid-column: 2 / -1; padding-top: 0; }
    .inv__row.util__row--head > div:nth-child(3) { display: none; }
}

/* The search sits in the filter row rather than up in the title bar, because
 * on this page it is a filter: it narrows the same list that Show and Folder
 * narrow, and the three read as one control strip. (Utilities keeps its search
 * in the title bar -- there the list is short and ungrouped, and there is no
 * filter row for it to join.) */
/* Takes the free end of the row, and shrinks rather than wraps: at 22 folder
 * names in the select plus four Show chips the row is within about ten pixels
 * of full, so a fixed-width search drops to a second line on the default
 * window and looks like it belongs to something else. */
.inv__search      { margin-left: auto; flex: 1 1 180px; max-width: 300px; }
.inv__search input { width: 100%; min-width: 0; }

/* ------------------------------------------------------- stock settings -- */

/* settings.php. Three sections, one per difficulty class, each a navy-headed
 * .rows table -- the same shape the utilities groups and the tourney tables
 * use, so a page Design never drew still reads as part of the site.
 *
 * Modelled on .util__head rather than inventing a third heading style: the
 * qualifier beside the name is doing the same job there and here, saying what
 * the section holds before you read it. Rookie has three lap times and no
 * setups at all, and that has to be legible from the heading. */
.stock { margin-bottom: 26px; }
.stock:last-of-type { margin-bottom: 0; }

.stock__head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 2px;
}
.stock__head h2 {
    font-size: 17px;
    font-weight: bold;
    color: var(--ink);
    margin: 0;
}

/* The Garage cell carries a title spelling the shorthand out -- "1400 ms" is
 * opaque until somebody tells you it means 1400 gears, medium tyres, soft
 * suspension. The dotted underline is the only hint that hovering says more. */
.stock .num span[title] {
    border-bottom: 1px dotted var(--rule);
    cursor: help;
}

/* A label whose value is a short list, one entry per line.
 *
 * The pod list on a multi-pod download used to carry <br> in the database;
 * migration 020 took it out and left newlines, so the value is plain text that
 * escapes like any other label and the browser draws the breaks. pre-line, not
 * pre: runs of spaces still collapse, which is what keeps the old &nbsp;
 * padding from reappearing as gaps. */
.fact__lines { white-space: pre-line; }

/* ------------------------------------------------------------- profiles -- */

/* Lists, profiles and the account page. Turn 20.
 *
 * Deliberately thin: a list renders in the archive's own .rows table, so it
 * looks like the listing it came from rather than like a new kind of page. */
.plist { margin-bottom: 26px; }

/* Section rhythm for things that are NOT a .plist.
 *
 * .plist carries the 26px, so anything standing between two sections without
 * being one butts straight against the next heading. Two turned up: the New
 * list form on a profile, and the "signed in as" bar on account.php.
 *
 * One utility rather than a modifier per element. The first version of this
 * was .filters--section, which would have wanted a .summary--section beside it
 * the moment the second case appeared -- two names for one measurement, and a
 * third the next time. The class says what it does, so it reads the same
 * wherever it lands.
 *
 * Deliberately NOT applied by a selector like `.listing > .summary`, which
 * would catch every standalone summary on the site: on list.php the count line
 * is a direct child of .listing and sits immediately above its own table, where
 * 26px would push a heading away from the thing it heads. This is opt-in
 * because the answer differs per case. */
.section-gap { margin-bottom: 26px; }

/* A confirmation's single action, on the same axis as the question it answers.
 *
 * .summary above and below it is centred text, so a left-aligned button between
 * them reads as belonging to neither. The listings' .filters bar is left-
 * aligned for good reason -- it holds a row of controls that scan left to right
 * -- but one button answering one question is not that. */
.confirm { text-align: center; padding: 16px 18px; }

/* The shareable profile address. Rendered as text you select and copy rather
 * than behind a copy button: a button needs the clipboard API and a fallback
 * for when it is refused, and the whole point of this line is that the URL is
 * short enough to read and retype if it comes to that.
 *
 * user-select: all so one click takes the whole thing -- a URL with a query
 * string is exactly what double-click-to-select-a-word gets wrong. */
.share-url {
    font: 12px var(--font-label);
    color: var(--ink);
    background: var(--bar-soft);
    border: 1px solid var(--rule);
    padding: 1px 6px;
    user-select: all;
}
/* Borrows .vis -- same 11px label chip as the visibility switches, so a control
 * that does something on click looks like the other controls that do something
 * on click. Only the gap is new; it is inserted by script directly after the
 * URL and would otherwise touch it. */
.share-copy { margin-left: 8px; }
.plist__head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 2px;
}
.plist__head h2 { font-size: 17px; font-weight: bold; color: var(--ink); margin: 0; }

/* The visibility badge. Navy when public, because it is the state worth
 * noticing -- "Only me" is the default and should sit back. */
.vis {
    font: 11px var(--font-label);
    padding: 2px 8px;
    border: 1px solid var(--rule);
    text-decoration: none;
    color: var(--link);
    /* A <button> gets the arrow cursor by default, not the hand -- so this
     * offered no hover feedback whatsoever. In the list table that is
     * survivable: the buttons sit under a "Who can see it" heading, in their
     * own column, and the column says what they are.
     *
     * On account.php the same control sits INLINE inside a sentence -- "your
     * tournament record is visible to [only you]" -- where a transparent 11px
     * grey-bordered chip with no pointer reads as part of the prose. The site
     * owner could not find it at all, and it was the only way to turn that
     * record on. */
    cursor: pointer;
    /* And a <button> with no background paints the BROWSER'S default, which on
     * a black site is a pale grey box that matches nothing else on the page --
     * .btn above sets `background: transparent` for exactly this reason and
     * .vis simply never did. It showed up worst on the navy summary bar beside
     * the share URL, where the site owner said the control was hard to read as
     * a control at all.
     *
     * --bar-soft rather than transparent: on a black row it is within five
     * values of the background, so the border does the work exactly as it does
     * for .btn -- but on the navy .summary bar it reads as a dark chip beside
     * the dark URL chip, and the two look like one control and its label
     * instead of a hole punched in the bar. */
    background: var(--bar-soft);
}
.vis--public { background: var(--navy-deep); color: var(--on-navy); border-color: var(--rule); }
/* Hover LAST, after .vis--public.
 *
 * The two are the same specificity, so whichever comes second wins. With hover
 * written first, .vis--public overrode both of its declarations and the navy
 * "Everyone" buttons had no hover feedback whatsoever -- the state that most
 * needs it, since those are the ones already carrying a filled background and
 * so looking least like something you can press.
 *
 * The state is carried by colour alone, so hover has to move something or a
 * control that already looks like a label keeps feeling like one. --ink on navy
 * is the site's own high-contrast pair, so this reads in both states. */
.vis:hover { border-color: var(--link); color: var(--ink); }

/* ---------------------------------------------------------------------------
   The tourneys landing: two archives offered side by side.

   The section had one front door while it had one kind of tournament behind
   it. It has two now, and they are not variants -- a rumble is five rounds
   scored out of ten, a race is a placing in a room and a points score on a
   scale that moves. Each card carries the shape of its archive and its last
   result, because the choice is easier to make with a real result in front of
   you than from a pair of labels.
   ------------------------------------------------------------------------ */
.choose {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}
.choose__card {
    display: block;
    background: var(--bar-soft);
    border: 1px solid var(--rule);
    padding: 16px 18px 14px;
    text-decoration: none;
    color: var(--link);
}
.choose__card:hover { border-color: var(--ink); }
.choose__title {
    font-size: 19px;
    font-weight: bold;
    color: var(--ink);
}
.choose__count {
    font-size: 12px;
    padding-top: 3px;
}
.choose__blurb {
    font-size: 13px;
    padding: 8px 0 0;
}

/* The last result, set apart from the card's own description by a rule rather
   than by a second panel -- a box inside a box is one border too many at this
   size. */
.choose__latest {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--rule);
}
.choose__event { font-size: 14px; font-weight: bold; color: var(--ink); }
.choose__date  { font-size: 12px; padding-bottom: 6px; }
.choose__row   { font-size: 13px; padding: 2px 0; }
.choose__pos   { font-size: 11px; color: #999999; display: inline-block; min-width: 30px; }
.choose__who   { color: var(--link); }

.choose__go {
    padding-top: 12px;
    font-size: 13px;
    color: var(--ink);
}
.choose__card:hover .choose__go { text-decoration: underline; }

@media (max-width: 720px) {
    .choose { grid-template-columns: 1fr; }
}

/* The fan formats: Cops N Robbers and Race 'n' Rumble, under the two cards.
   The same filled panel as the cards, so it reads as part of the landing, but
   one line each and no podium -- the owner calls them "two fan made ways of
   playing the original game", and a third and fourth card would have ranked
   them beside the two main archives. */
.fan {
    margin-top: 14px;
    background: var(--bar-soft);
    border: 1px solid var(--rule);
    padding: 12px 18px;
    color: var(--link);   /* the cards' text colour, not the listing's yellow */
}
.fan__head  { font-size: 14px; font-weight: bold; color: var(--ink); }
.fan__blurb { font-size: 12px; padding: 2px 0 0; }
.fan__row   { font-size: 13px; padding: 8px 0 0; }
/* Yellow, as the cards' own titles are: in the panel's grey they read as
   flavour text rather than as the way in. The owner, 2026-09-26: "the titles
   (that are clickable too) of the formats should be yellow as well." */
.fan__row a { font-weight: bold; color: var(--ink); text-decoration: none; }
.fan__row a:hover { text-decoration: underline; }
.fan__count { font-size: 12px; color: #8A8A8A; padding-left: 6px; }

/* A race's round count is the event's, not a constant: she ran three rounds
   some Sundays and six others, then a semi, a final or a run-off. So the
   columns come from the page as --stages rather than from here. */
.scores--race.scores .scores__head,
.scores--race.scores .scores__row {
    grid-template-columns: 1fr repeat(var(--stages, 4), 78px) 96px;
}
@media (max-width: 720px) {
    .scores--race.scores .scores__head,
    .scores--race.scores .scores__row {
        grid-template-columns: 1fr repeat(var(--stages, 4), 52px) 64px;
    }
}

/* The series cards carry a points column the landing's two do not, so the row
   becomes a three-part line rather than a label and a name. */
.choose--series { grid-template-columns: 1fr 1fr; }
.choose--series .choose__row {
    display: grid;
    grid-template-columns: 30px 1fr 44px;
}
.choose__pts { text-align: right; color: var(--ink); }

/* The list of weeks under a series table: a run of links, not a paragraph. */
.tourney-summary--after { padding-top: 12px; }
/* A line under the summary that qualifies it -- the rumbles' all-time total
   adding two scorings. Quieter than the summary, which is the fact. */
.tourney-summary__note { font-size: 12px; color: #8A8A8A; padding-top: 4px; }
.tourney-summary--after a { text-decoration: none; }
.tourney-summary--after a:hover { text-decoration: underline; }

@media (max-width: 720px) {
    .choose--series { grid-template-columns: 1fr; }
}

/* The room a placing happened in, sat quietly after it.
 *
 * She split a field of twelve into four rooms of three, so a 1st is first of
 * that room and not of the field. The number has to be there or the grid reads
 * as one race; it has to be quiet or it competes with the placing, which is
 * what you actually came to read. Grey, smaller, and lifted -- the same
 * relationship a footnote mark has to its word. */
.scores__room {
    font-size: 9px;
    color: #8A8A8A;
    vertical-align: super;
    padding-left: 2px;
    font-style: normal;
    font-weight: normal;
}
.scores__row.is-winner .scores__room { color: #8A8A8A; }

/* Rooms as rooms: who raced whom, which the results grid cannot say.
 *
 * One block per round, one line per room. Deliberately plainer than the grid
 * above it -- this is the detail you drop into after reading the result, not a
 * second table competing with the first. */
.rooms {
    margin-top: 18px;
    /* FILLED, not the tile showing through -- the same call the results table
     * makes a few rules above, and for the same reason. A repeating watermark
     * behind every line, with a hairline under each one, is two patterns
     * competing in the same space, and the handles lose. The site owner, seeing
     * it: "the names are fighting the backdrop image". The block fills, so the
     * tile frames it instead of sitting behind it. */
    background: var(--bar-soft);
    border: 1px solid var(--rule);
}
.rooms__head {
    font-size: 13px;
    font-weight: bold;
    color: var(--ink);
    padding: 12px 12px 4px;
}
/* The first round heading is already inside the panel's top edge, so it does
   not need the gap that separates it from the round above. */
.rooms__head:first-child { padding-top: 10px; }
.rooms__row {
    display: grid;
    grid-template-columns: 62px 1fr;
    font-size: 13px;
    color: var(--link);
    border-bottom: 1px solid var(--rule);
    padding: 5px 12px;
}
.rooms__row:last-child { border-bottom: 0; }
.rooms__label { color: #8A8A8A; font-size: 12px; }
.rooms__who a { color: var(--link); text-decoration: none; }
.rooms__who a:hover { color: var(--ink); text-decoration: underline; }
.rooms__place { color: #8A8A8A; font-size: 11px; padding-right: 4px; }
.rooms__sep { color: var(--rule); padding: 0 6px; }

@media (max-width: 720px) {
    .rooms__row { grid-template-columns: 1fr; }
    .rooms__label { padding-bottom: 2px; }
}

/* The week columns of a series table are links to their events. Inheriting the
   header's colour rather than the page's link colour: they sit inside a navy
   bar where a yellow link would read as a warning rather than as a way in. */
.scores__head a { color: inherit; text-decoration: none; }
.scores__head a:hover { text-decoration: underline; }

/* An event heading that is a link stays the heading it was. */
.tourney-head__name a { color: inherit; text-decoration: none; }

/* A special event: bonus points and no racing, so a name and a score and
   nothing between them. Its own grid, because repeat(0, ...) for zero rounds
   is invalid and would drop the race grid's whole declaration. */
.scores--bonus.scores .scores__head,
.scores--bonus.scores .scores__row { grid-template-columns: 1fr 96px; }
@media (max-width: 720px) {
    .scores--bonus.scores .scores__head,
    .scores--bonus.scores .scores__row { grid-template-columns: 1fr 64px; }
}
.tourney-head__note { font-size: 12px; color: var(--muted); margin-top: 4px; }

/* A line under a results table: the red lantern, when one was given. A strip
   on the table's own ground, joined to its foot -- bare on the page it sat on
   the tiled backdrop, which is what the rooms panel had to be taken off too. */
.scores-note {
    font-size: 12px;
    color: var(--link);
    background: var(--bar-soft);
    border: 1px solid var(--rule);
    border-top: 0;
    padding: 8px 10px;
}
.tourney-head__name a:hover { text-decoration: underline; }
