/* ============================================================
   Leaderboard-only additions on top of main.css (copied as-is from
   the course site). Colours, type and spacing come from main.css's
   tokens only — add a token there rather than a literal here.
   ============================================================ */

/* ============================================================
   Header, page shell and footer from the student blog
   (cs2680-blog/assets/css/blog.css, copied as-is), so the
   leaderboard wears the blog's bar: the MadSys mark and the site's
   own name instead of the SEAS lockup, which moves to the footer.
   ============================================================ */

/* ------------------------------------------------------------
   Page shell
   course.css lays the page out as ordinary blocks, which leaves
   the footer floating in the middle of the window on a short page
   -- the author index and the tag index are both one screen with
   a dozen pills on it. The body becomes a column tall enough to
   fill the viewport and the content between header and footer
   takes up the slack, so the footer is always on the bottom edge
   and never above it.
   ------------------------------------------------------------ */

body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    /* dvh follows the mobile browser's collapsing address bar; vh above is
       the fallback for anything that does not know the unit. */
    min-height: 100dvh;
}

.container.page {
    flex: 1 0 auto;
}

.site-footer {
    flex-shrink: 0;
}

/* ------------------------------------------------------------
   Header brand
   The course site's header is the SEAS lockup and nothing else,
   which is exactly why this one cannot be. The blog leads with the
   MadSys mark -- the same drawing both sites use as their favicon --
   and its own name, with the course code and term as the small line
   underneath. Same white bar, same crimson rule, different thing
   standing on it.

   It is also the one element that has to hold together from a
   1200px desktop bar down to a 320px phone, beside a hamburger.
   Nothing here is hidden on the way down; the mark and the two
   lines of type step down together.
   ------------------------------------------------------------ */

.site-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    margin-right: auto;
    padding: 11px 0;
    color: inherit;
    text-decoration: none;
}

.site-brand:hover,
.site-brand:focus {
    color: inherit;
    text-decoration: none;
}

/* The mark is a hexagon, not a tile, so the corner radius and the box-shadow
   that framed the old square are gone; a drop-shadow filter follows the real
   silhouette instead. */
/* The lab mark is an outline, not a solid shape, so it carries no shadow --
   a drop-shadow on a 19/585 stroke reads as a printing error. It lifts on
   hover and nothing more. */
.brand-mark {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    transition: transform 0.2s ease;
}

.site-brand:hover .brand-mark {
    transform: translateY(-1px);
}

.brand-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.brand-name {
    font-family: 'Open Sans', sans-serif;
    font-size: 1.3rem;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.005em;
    color: var(--crimson);
    white-space: nowrap;
    transition: color 0.15s ease;
}

.site-brand:hover .brand-name {
    color: var(--crimson-bright);
}

.brand-sub {
    font-family: 'Open Sans', sans-serif;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.site-brand:focus-visible {
    outline: 2px solid var(--crimson);
    outline-offset: 3px;
    border-radius: var(--r-sm);
}

/* The brand and the toggler share one row on a phone; neither may push the
   other off it, so the brand shrinks and the toggler does not. */
.site-header .navbar-toggler {
    flex-shrink: 0;
}

@media (max-width: 575px) {
    .site-brand {
        gap: 9px;
        padding: 9px 0;
    }

    .brand-mark {
        width: 38px;
        height: 38px;
    }

    .brand-name {
        font-size: 1.12rem;
    }

    .brand-sub {
        font-size: 0.64rem;
        letter-spacing: 0.08em;
    }
}

@media (max-width: 380px) {
    .brand-mark {
        width: 34px;
        height: 34px;
    }

    .brand-name {
        font-size: 1.02rem;
    }

    .navbar-toggler {
        padding: 6px 8px;
    }

    .navbar-toggler-icon {
        width: 1.2em;
        height: 1.2em;
    }
}

.navbar-nav .nav-link {
    white-space: nowrap;
}

/* The assignment switcher (header.js): a button that looks like the links beside it. */
.navbar-nav .assignment-toggle {
    background: none;
    border: 0;
    font: inherit;
}

/* ------------------------------------------------------------
   Collapsed menu
   Below 992px the links become a drop-down panel. Bootstrap leaves
   them as bare inline text; these rules give the panel one row per
   link and the same crimson current-page fill the bar uses.
   ------------------------------------------------------------ */

@media (max-width: 991.98px) {
    .navbar-collapse {
        margin: 0 calc(-1 * var(--s3)) var(--s2);
        padding: var(--s2) var(--s3) var(--s3);
        border-top: 1px solid var(--border-soft);
    }

    .navbar-nav {
        margin-left: 0;
        gap: 2px;
    }

    .navbar-nav .nav-item {
        width: 100%;
    }

    .navbar-nav .nav-link {
        padding: 11px 12px !important;
        border-radius: var(--r-sm);
    }
}

/* ------------------------------------------------------------
   Footer additions
   The SEAS lockup moved here when the header took the blog's own
   brand, and the pages the four-item menu leaves out are listed
   beside the menu's own, so the navigation bar is a shortcut and
   never the only way in.
   ------------------------------------------------------------ */

.footer-seas {
    display: inline-block;
    border-bottom: none !important;
    margin-bottom: var(--s4);
}

.footer-seas img {
    height: 54px;
    width: auto;
    opacity: 0.85;
    transition: opacity 0.15s ease;
}

.footer-seas:hover img {
    opacity: 1;
}

.footer-nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--s2) var(--s4);
    margin-bottom: var(--s4);
    padding-bottom: var(--s4);
    border-bottom: 1px solid var(--border-soft);
}

.footer-nav a {
    font-family: 'Open Sans', sans-serif;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-2);
    border-bottom: none;
}

.footer-nav a:hover {
    color: var(--crimson-bright);
    border-bottom: none;
}

@media (max-width: 575px) {
    .footer-seas img {
        height: 44px;
    }
}

/* --- navbar: login / logout -------------------------------- */

.nav-auth {
    display: flex;
    align-items: center;
    margin-left: var(--s3);
}

.nav-user {
    display: inline-flex;
    align-items: center;
    gap: var(--s3);
    font-family: 'Open Sans', sans-serif;
    color: var(--ink-3);
}

/* the logged-in name: a menu (Change password) */
.nav-user-name {
    font: inherit;
    color: var(--ink-3);
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

.nav-user-name:hover,
.nav-user-name[aria-expanded="true"] {
    color: var(--crimson);
}

.nav-user .dropdown-menu {
    font-family: 'Open Sans', sans-serif;
    font-size: 0.95rem;
}

.nav-user .dropdown-item:active {
    background: var(--crimson);
}

.nav-user[hidden],
.btn-auth[hidden],
.nav-item[hidden] {
    display: none !important;
}

.btn-auth {
    font-family: 'Open Sans', sans-serif;
    font-size: 1rem;
    color: var(--crimson);
    background: var(--bg);
    border: 1px solid var(--crimson);
    border-radius: var(--r-sm);
    padding: 6px 16px;
    text-decoration: none;
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-auth:hover {
    color: var(--on-crimson);
    background: var(--crimson);
    text-decoration: none;
}

@media (max-width: 991.98px) {
    .nav-auth {
        margin: var(--s2) 0 var(--s3);
        padding: 0 12px;          /* in line with the menu links above (11px 12px) */
    }
}

/* --- buttons and forms ------------------------------------- */

.btn-crimson {
    font-size: 1rem;
    font-weight: 600;
    color: var(--on-crimson);
    background: var(--crimson);
    border: 1px solid var(--crimson);
    border-radius: var(--r-sm);
    padding: 8px 22px;
    cursor: pointer;
    transition: background 0.2s ease;
}

.btn-crimson:hover:not(:disabled) {
    background: var(--crimson-dark);
}

.btn-crimson:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* the same size as .btn-crimson, outlined: crimson border and text on white */
.btn-outline-crimson {
    display: inline-block;
    font-size: 1rem;
    font-weight: 600;
    color: var(--crimson);
    background: var(--bg);
    border: 1px solid var(--crimson);
    border-radius: var(--r-sm);
    padding: 8px 22px;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.2s ease;
}

.btn-outline-crimson:hover {
    color: var(--crimson-dark);
    background: var(--crimson-050);
    text-decoration: none;
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s3);
}

.form-alt-link {
    color: var(--crimson);
}

.form-card {
    max-width: 560px;
    margin: var(--s5) auto 0;
    padding: var(--s6);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
}

.form-card.narrow {
    max-width: 400px;
}

.form-field {
    margin-bottom: var(--s5);
}

.form-field label {
    display: block;
    font-weight: 600;
    color: var(--ink-2);
    margin-bottom: var(--s2);
}

.form-field .hint {
    font-size: 0.9rem;
    color: var(--ink-3);
    margin-top: var(--s1);
}

.form-field input[type="text"],
.form-field input[type="email"],
.form-field input[type="password"] {
    width: 100%;
    padding: 8px var(--s3);
    font-size: 1rem;
    color: var(--ink);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
}

.form-field input:focus {
    outline: none;
    border-color: var(--crimson);
    box-shadow: 0 0 0 3px var(--crimson-100);
}

/* --- zip drop zone ----------------------------------------- */

.dropzone {
    display: block;
    padding: var(--s6) var(--s4);
    text-align: center;
    color: var(--ink-3);
    background: var(--surface);
    border: 2px dashed var(--border-strong);
    border-radius: var(--r);
    cursor: pointer;
    transition: all 0.15s ease;
}

.dropzone:hover,
.dropzone.dragover {
    color: var(--crimson);
    background: var(--crimson-050);
    border-color: var(--crimson);
}

.dropzone .dropzone-main {
    font-size: 1.05rem;
    font-weight: 600;
}

.dropzone .dropzone-file {
    margin-top: var(--s2);
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 0.95rem;
    word-break: break-all;
}

.dropzone input[type="file"] {
    display: none;
}

/* --- status messages --------------------------------------- */

.status {
    margin-top: var(--s4);
    padding: var(--s3) var(--s4);
    border-radius: var(--r-sm);
    border: 1px solid transparent;
}

.status:empty {
    display: none;
}

.status.error {
    color: var(--crimson-dark);
    background: var(--crimson-050);
    border-color: var(--crimson-200);
}

.status.ok {
    color: var(--green);
    background: var(--green-050);
    border-color: var(--green-200);
}

.status.info {
    color: var(--ink-2);
    background: var(--surface);
    border-color: var(--border);
}

/* submit page: how many submissions a new upload would wait behind */
.queue-banner {
    max-width: 560px;
    margin: var(--s5) auto 0;
    padding: var(--s3) var(--s4);
    color: var(--ink-2);
    background: var(--blue-050);
    border: 1px solid var(--blue-200);
    border-radius: var(--r-sm);
}

.queue-banner b {
    color: var(--blue);
}

.queue-banner + .form-card {
    margin-top: var(--s4);
}

/* submit page: what goes in the zip (src/ and engine/), folded under the field's label */
.format-help {
    margin-bottom: var(--s3);
    color: var(--ink-2);
    font-size: 0.92rem;
}

.format-help summary {
    cursor: pointer;
    color: var(--crimson);
    font-weight: 600;
    margin-bottom: var(--s2);
}

.format-help pre {
    font-size: 0.8rem;
    line-height: 1.45;
    margin-bottom: var(--s2);
    overflow-x: auto;
}

/* the catalog's model ids and the a4-models path are long unbroken words: they wrap rather than widen the page */
.format-help li code {
    overflow-wrap: anywhere;
}

.format-help ul {
    padding-left: 1.2em;
    margin-bottom: var(--s2);
}

.format-help li {
    margin-bottom: var(--s1);
}

/* submit page: every problem of a refused zip, under the error */
.status ul.violations {
    margin: var(--s2) 0 0;
    padding-left: 1.2em;
}

.status ul.violations li {
    margin-bottom: var(--s1);
    word-break: break-word;
}

/* submit page: today's gradings toward the daily cap, above the Submit button */
.gradings-line {
    margin-bottom: var(--s4);
    color: var(--ink-2);
}

.gradings-line.out b {
    color: var(--crimson-dark);
}

.gradings-line .of {
    font-size: 0.92rem;
}

/* --- tables ------------------------------------------------ */

.board-table td.rank,
.board-table th.rank {
    width: 4.5em;
    text-align: center;
}

.board-table td.num,
.board-table th.num {
    text-align: right;
}

.board-table td.empty {
    text-align: center;
    color: var(--ink-3);
    padding: var(--s6) var(--s3);
}

.badge-pending {
    display: inline-block;
    font-size: 0.85rem;
    color: var(--amber);
    background: var(--amber-050);
    border: 1px solid var(--amber-200);
    border-radius: 999px;
    padding: 1px 10px;
}

.board-note {
    text-align: center;
    color: var(--ink-3);
    margin-top: var(--s3);
}

/* --- leaderboard card (layout after cachecompetition.com/leaderboard) --- */

:root {
    /* medal colours for ranks 1-3 */
    --gold: #C7932E;
    --silver: #7C7C82;
    --bronze: #AD6B45;
}

.board-card {
    margin-top: var(--s6);
    padding: 28px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: 0 12px 38px rgba(20, 22, 26, 0.10);
}

.board-card .board-title {
    font-size: 32px;
    font-weight: 700;
    color: var(--ink);
    margin: 0 0 var(--s4);
}

.board-card .board-refreshed {
    color: var(--ink-3);
    margin: 0 0 var(--s5);
}

table.board {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}

table.board th,
table.board td {
    padding: var(--s4);
    text-align: left;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

table.board td:nth-child(2) {
    white-space: normal;   /* long names wrap; everything else stays on one line */
}

table.board th {
    background: var(--crimson-050);
    color: var(--ink);
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

table.board tbody tr:hover td {
    background: var(--surface);
}

table.board td.empty {
    text-align: center;
    color: var(--ink-3);
    padding: var(--s6) var(--s4);
}

.board-rank {
    font-weight: 700;
    color: var(--crimson);
}

.board-rank.rank-1 { color: var(--gold); }
.board-rank.rank-2 { color: var(--silver); }
.board-rank.rank-3 { color: var(--bronze); }
.board-rank.pending { color: var(--ink-4); }

.board-score {
    font-weight: 700;
    font-size: 1.05rem;
}

.board-card .board-note {
    text-align: left;
    margin: var(--s4) 0 0;
}

@media (max-width: 575px) {
    .board-card {
        padding: var(--s4);
    }

    .board-card .board-title {
        font-size: 24px;
    }
}

/* main.css frames every .table-responsive; inside the card the card is the frame */
.board-card .table-responsive {
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

/* the logged-in person's own best, below the top 10 */
table.board tr.board-me-label td {
    padding: var(--s5) var(--s4) var(--s2);
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--crimson);
    border-bottom: 2px solid var(--crimson-200);
    background: var(--bg) !important;
}

table.board tr.board-me td {
    background: var(--crimson-050);
}

/* "Your best submission", and on the right whether the baseline is reached (any one submission of all 26 tasks
   that solved at least BASELINE_SOLVED tasks in at most BASELINE_TIME_S end to end; kept for good) */
table.board tr.board-me-label .board-me-head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--s2) var(--s3);
}

/* the skyline (index.html, public/skyline.js), under the leaderboard: an inline SVG at the box's width, its
   tooltip on top of it */
.skyline-plot {
    position: relative;
    width: 100%;
    min-height: 320px;
}

.skyline-plot svg {
    display: block;
    max-width: 100%;
}

.skyline-plot .skyline-hit {
    cursor: pointer;
}

.skyline-plot .skyline-hit:focus {
    outline: none;
    stroke: var(--ink);
    stroke-width: 2;
}

.skyline-tip {
    position: absolute;
    z-index: 2;
    max-width: min(340px, 100%);
    padding: var(--s2) var(--s3);
    font-size: 0.92rem;
    line-height: 1.4;
    color: var(--ink);
    background: var(--bg);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    box-shadow: 0 6px 18px rgba(20, 22, 26, 0.12);
    pointer-events: none;
}

.skyline-tip[hidden] {
    display: none;
}

/* the legend above it: large swatches, labels in ink; a click hides or shows a group */
.skyline-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s2) var(--s5);
    margin: 0 0 var(--s3);
}

.skyline-legend button,
.skyline-legend .legend-you {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font: inherit;
    font-size: 1.05rem;
    color: var(--ink);
    background: none;
    border: 0;
    padding: 2px 0;
}

.skyline-legend button {
    cursor: pointer;
}

.skyline-legend button.off {
    opacity: 0.35;
}

.skyline-legend .swatch {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    flex: none;
}

.skyline-legend .swatch.ring {
    border: 3px solid var(--crimson);
}

.badge-baseline {
    display: inline-block;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: none;
    border: 1px solid;
    border-radius: 999px;
    padding: 1px 10px;
}

.badge-baseline.ok { color: var(--green); background: var(--green-050); border-color: var(--green-200); }
.badge-baseline.no { color: var(--crimson-dark); background: var(--crimson-050); border-color: var(--crimson-200); }

table.board tr.board-me:hover td {
    background: var(--crimson-100);
}

/* --- grading results --------------------------------------- */

.of {
    color: var(--ink-3);
    font-weight: 400;
}

.muted {
    color: var(--ink-4);
}

.badge-status {
    display: inline-block;
    font-size: 0.85rem;
    border-radius: 999px;
    padding: 1px 10px;
    border: 1px solid;
}

.badge-queued,
.badge-unranked,
.badge-canceled { color: var(--ink-3); background: var(--surface); border-color: var(--border); }
/* a warning: a worker waiting or busy with something else, an audit's suspicious verdict */
.badge-warn { color: var(--amber); background: var(--amber-050); border-color: var(--amber-200); }
.badge-running { color: var(--blue); background: var(--blue-050); border-color: var(--blue-200); }
.badge-best,
.badge-done { color: var(--green); background: var(--green-050); border-color: var(--green-200); }
.badge-error,
.badge-failed,
.badge-timeout { color: var(--crimson-dark); background: var(--crimson-050); border-color: var(--crimson-200); }

.btn-tasks {
    font-size: 0.9rem;
    color: var(--crimson);
    background: var(--bg);
    border: 1px solid var(--crimson-200);
    border-radius: var(--r-sm);
    padding: 2px 10px;
    white-space: nowrap;
    cursor: pointer;
}

.btn-tasks:hover {
    background: var(--crimson-050);
}

.history-table tr.detail-row > td {
    background: var(--surface);
    padding: var(--s3) var(--s4);
}

/* under a submission being graded: how far it has got (updated every 2 minutes), one line on
   the right, a little smaller than the rows of finished ones */
.history-table tr.progress-row > td {
    font-size: 0.92rem;
    color: var(--ink-2);
    padding-top: 6px;
    padding-bottom: 6px;
}

.history-table .progress-line {
    text-align: right;
}

.history-table .copy-total {
    font-size: 0.85rem;
    color: var(--ink-3);
}

.grade-error {
    margin: 0;
    white-space: pre-wrap;
    font-family: var(--font-mono);
    font-size: 0.85rem;
}

table.task-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--bg);
    font-variant-numeric: tabular-nums;
}

table.task-table th,
table.task-table td {
    padding: 6px var(--s3);
    border-bottom: 1px solid var(--border);
    text-align: left;
}

table.task-table th {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--ink-3);
}

table.task-table .num {
    text-align: right;
}

.ok-mark { color: var(--green); font-weight: 700; }
.no-mark { color: var(--ink-4); }
.task-table .reason { color: var(--ink-3); font-size: 0.92em; }

.form-field input[type="number"] {
    width: 10em;
    padding: 8px var(--s3);
    font-size: 1rem;
    color: var(--ink);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
}

.form-field label .optional {
    font-weight: 400;
    color: var(--ink-3);
}

/* --- Past submissions (history.html): a grading's phase, timeline and failure ------ */

/* how long it has been in its phase, after its badge */
.phase-since {
    color: var(--ink-3);
    font-size: 0.9rem;
    white-space: nowrap;
}

/* the timeline: queued, claimed, engine ready, agent over, finished; each with its time and how long after the one
   before */
ol.timeline {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s2) var(--s5);
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.9rem;
    color: var(--ink-2);
}

ol.timeline li {
    margin: 0;
    padding-left: 16px;
    position: relative;
}

ol.timeline li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.45em;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--green);
}

ol.timeline li.todo {
    color: var(--ink-4);
}

ol.timeline li.todo::before {
    background: none;
    border: 2px solid var(--border-strong);
}

ol.timeline li.now::before {
    background: var(--blue);
}

ol.timeline .tl-label {
    font-weight: 700;
    color: var(--ink);
}

ol.timeline li.todo .tl-label {
    color: var(--ink-4);
    font-weight: 600;
}

ol.timeline .tl-gap {
    color: var(--ink-3);
}

.detail-block + .detail-block {
    margin-top: var(--s3);
}

.detail-block .engine-line {
    font-size: 0.9rem;
    color: var(--ink-2);
    overflow-wrap: anywhere;
}

.history-table tr.detail-row .progress-line {
    margin-top: var(--s2);
}

/* On a phone the table scrolls sideways; what a detail row says (the timeline, the failure, the tasks) stays in view
   at the width of the screen instead of scrolling away with it. */
@media (max-width: 767.98px) {
    .history-table tr.detail-row > td > * {
        position: sticky;
        left: var(--s4);
        max-width: calc(100vw - 64px);
    }

    .history-table .progress-line {
        text-align: left;
    }
}

/* On a phone, Past submissions leaves out the upload time (the timeline has it) and the file name, so the state of
   a grading and its Cancel button fit on the screen without scrolling the table sideways. */
@media (max-width: 575.98px) {
    .history-table .col-when,
    .history-table .col-file {
        display: none;
    }
}

/* a failed grading: its fixed failure text, and for a failure before the engine was ready the end of the startup
   log, folded */
.failure-box {
    margin: 0;
    white-space: normal;
}

.failure-box details {
    margin-top: var(--s2);
}

.failure-box summary {
    cursor: pointer;
    font-weight: 600;
}

.failure-box pre {
    margin: var(--s2) 0 0;
    max-height: 28rem;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--ink);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: var(--s2) var(--s3);
}

/* --- the development site (SITE_ENV=dev; src/worker.js page() puts it on every page) --- */

.dev-banner {
    padding: 6px var(--s4);
    text-align: center;
    font-size: 0.95rem;
    color: var(--ink);
    background: var(--amber-200);
    border-bottom: 2px solid var(--amber);
}

.dev-banner b {
    font-weight: 700;
}
