/* Haboon Works — shared styles for every page. */

:root {
  color-scheme: dark;
  --ground: #131519;
  --surface: #1c1f25;
  --line: #2d3139;
  --text: #e7e1d4;
  --text-soft: #cfc9bd;
  --muted: #9b968b;
  --brass: #c9a05a;
  --brass-dim: #8a6d3d;
  --blood: #7d2b22;
  --f-stamp: "Stardos Stencil", "Courier New", monospace;
  --f-game: "Cinzel", "Trajan Pro", Georgia, serif;
  --f-body: "Hanken Grotesk", "Segoe UI", system-ui, sans-serif;
  --f-mono: "JetBrains Mono", Consolas, "Courier New", monospace;
  --wrap: 1180px;
}
* { box-sizing: border-box; }
/* The page colour lives on <html> only, so the ember canvas (fx.js) can sit between it and the
   content; <body> stays transparent. The two glows sit on a fixed layer of their own, under the
   embers: a fixed background on <html> would repaint the whole page on every frame of a scroll. */
html { color: var(--text); background: var(--ground); }
body::before {
  content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(1400px 720px at 78% -260px, rgba(201,160,90,.085), transparent 65%),
    radial-gradient(1000px 700px at -12% 112%, rgba(125,43,34,.09), transparent 60%);
}
body { margin: 0; font: 17px/1.6 var(--f-body); -webkit-font-smoothing: antialiased; }
img { max-width: 100%; }
[hidden] { display: none !important; }
a { color: inherit; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
h1, h2, h3 { text-wrap: balance; margin: 0; }
p { margin: 0; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 28px; }
.label { font: 500 12px/1.3 var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.t-dreadmarch, .t-last-muster, .t-hollow { font-family: var(--f-game); letter-spacing: .03em; }

/* ——— Top bar ——— */
.bar { border-bottom: 1px solid var(--line); }
.bar .wrap { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding-top: 18px; padding-bottom: 18px; flex-wrap: wrap; }
.mark { font: 700 26px/1 var(--f-stamp); letter-spacing: .08em; text-transform: uppercase; text-decoration: none; display: flex; align-items: baseline; gap: .35em; }
.mark span { color: var(--brass); }
nav { display: flex; gap: 28px; flex-wrap: wrap; }
nav a { font: 500 13px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; text-decoration: none; color: var(--muted); padding: 6px 0; border-bottom: 1px solid transparent; }
nav a:hover { color: var(--text); border-color: var(--brass-dim); }
nav a[aria-current="page"] { color: var(--text); border-color: var(--brass); }

/* ——— Buttons ——— */
.btn { display: inline-block; font: 600 14px/1 var(--f-body); letter-spacing: .02em; text-decoration: none; padding: 12px 16px; border: 1px solid var(--brass); background: var(--brass); color: #16130d; cursor: pointer; }
.btn:hover { background: #d8b273; }
.btn.ghost { background: transparent; color: var(--text); border-color: var(--line); }
.btn.ghost:hover { border-color: var(--brass-dim); }

/* ——— Page openers ——— */
.opening { padding: 72px 0 52px; }
.opening .wrap { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 48px; align-items: end; }
.opening h1 { font: 700 clamp(56px, 9vw, 116px)/.86 var(--f-stamp); text-transform: uppercase; letter-spacing: .02em; }
.opening h1 .w { display: block; color: var(--brass); }
.lede { font-size: 20px; line-height: 1.55; max-width: 36ch; }
.lede + .label { margin-top: 18px; }

.page-head { padding: 64px 0 40px; border-bottom: 1px solid var(--line); }
.page-head .wrap { display: grid; gap: 18px; }
.page-head h1 { font: 700 clamp(48px, 7vw, 88px)/.9 var(--f-stamp); text-transform: uppercase; letter-spacing: .02em; }
.page-head .lede { color: var(--text-soft); max-width: 52ch; }
.prose { max-width: 72ch; display: grid; gap: 14px; }
.prose h2 { font: 700 24px/1.15 var(--f-stamp); text-transform: uppercase; letter-spacing: .03em; margin-top: 26px; }
.prose p, .prose li { color: var(--text-soft); font-size: 16px; }
.prose ul { margin: 0; padding-left: 22px; display: grid; gap: 8px; }
.prose a { color: var(--brass); }

/* ——— Section heads ——— */
section.block { padding: 72px 0 0; }
.head { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 32px; align-items: baseline; margin-bottom: 32px; }
.head h2 { font: 700 40px/1.05 var(--f-stamp); text-transform: uppercase; letter-spacing: .03em; }
.head p { grid-column: 2; max-width: 60ch; color: var(--muted); margin-top: 12px; }
.head .more { grid-column: 2; justify-self: start; margin-top: 4px; font: 500 13px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--brass); text-decoration: none; }
.head .more:hover { text-decoration: underline; }

/* ——— Works index cards ——— */
.works-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.work-card { display: grid; grid-template-rows: auto 1fr; border: 1px solid var(--line); background: var(--surface); text-decoration: none; color: inherit; transition: border-color .2s; }
a.work-card:hover { border-color: var(--brass-dim); }
.work-card .cover { position: relative; overflow: hidden; aspect-ratio: 16 / 9; background: #0c0d10; }
.work-card .cover img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .6s ease; }
a.work-card:hover .cover img { transform: scale(1.04); }
.work-card .body { display: grid; gap: 10px; align-content: start; padding: 20px 22px 22px; }
.work-card .row { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.work-card h2, .work-card h3 { font-size: 34px; line-height: 1.05; }
.work-card p { color: var(--text-soft); font-size: 15px; max-width: 48ch; }
.work-card .go { font: 500 13px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--brass); margin-top: 6px; }
.work-card.empty { background: transparent; border-style: dashed; }
.work-card.empty .cover { display: grid; place-items: center; background: repeating-linear-gradient(135deg, transparent 0 14px, rgba(255,255,255,.025) 14px 28px); }
.work-card.empty .cover span { font: 700 64px/1 var(--f-stamp); color: var(--line); }
.work-card.empty h3 { font: 700 30px/1.05 var(--f-stamp); text-transform: uppercase; color: var(--muted); letter-spacing: .03em; }
.work-card.empty p { color: var(--muted); }

.no { font: 700 15px/1 var(--f-stamp); letter-spacing: .12em; color: var(--brass); }
.work-card.empty .no { color: var(--brass-dim); }
.status { font: 500 11px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; padding: 5px 8px; border: 1px solid var(--line); color: var(--muted); white-space: nowrap; }
.status.dev { border-color: var(--blood); color: #d9a097; background: rgba(125,43,34,.18); }
.status.soon { border-color: var(--brass-dim); color: var(--brass); background: rgba(201,160,90,.1); }

/* ——— Work page ——— */
.crumbs { padding: 22px 0 0; }
.crumbs a { font: 500 12px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--text); }
.work-top { padding: 20px 0 0; }
.plate { position: relative; border: 1px solid var(--line); overflow: hidden; background: #0c0d10; }
.plate > img { display: block; width: 100%; aspect-ratio: 16 / 8; object-fit: cover; object-position: 50% 40%; filter: saturate(.92); }
.plate::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(10,11,13,0) 45%, rgba(10,11,13,.72) 100%); pointer-events: none; }
.tag {
  position: absolute; z-index: 1; right: 32px; bottom: 32px; width: min(380px, calc(100% - 64px));
  background: var(--ground); border: 1px solid var(--brass-dim);
  box-shadow: 0 0 0 5px var(--ground), 0 0 0 6px var(--line), 0 24px 48px rgba(0,0,0,.5);
  transform: rotate(-1deg); animation: stamp .7s cubic-bezier(.2,.9,.3,1.2) both;
}
@keyframes stamp { from { transform: rotate(-3deg) scale(1.04); opacity: .55; } to { transform: rotate(-1deg) scale(1); opacity: 1; } }
.tag-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 18px; border-bottom: 1px dashed var(--line); }
.tag-body { padding: 18px 18px 20px; display: grid; gap: 10px; }
.tag h1 { font: 700 38px/1 var(--f-game); letter-spacing: .03em; }
.tag .genre { font: 600 13px/1 var(--f-game); letter-spacing: .28em; text-transform: uppercase; color: var(--muted); }
.tag p { font-size: 15px; line-height: 1.5; color: var(--text-soft); }
.specs { display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1px dashed var(--line); }
.specs div { padding: 12px 18px; display: grid; gap: 2px; }
.specs div + div { border-left: 1px dashed var(--line); }
.specs b { font: 700 24px/1 var(--f-stamp); font-variant-numeric: tabular-nums; }
.specs span { font: 400 11px/1.3 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.work-actions { display: flex; flex-wrap: wrap; gap: 12px; padding: 14px 18px 18px; border-top: 1px dashed var(--line); }

.fact-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border: 1px solid var(--line); border-top: 0; }
.fact-strip div { padding: 16px 20px; display: grid; gap: 4px; }
.fact-strip div + div { border-left: 1px solid var(--line); }
.fact-strip dd { margin: 0; }

.shots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.shots figure { margin: 0; display: grid; gap: 10px; }
.shots .frame { overflow: hidden; border: 1px solid var(--line); }
.shots img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; transition: transform .5s ease; }
.shots figure:hover img { transform: scale(1.04); }
.shots figcaption { display: flex; justify-content: space-between; gap: 12px; font: 400 12px/1.3 var(--f-mono); letter-spacing: .06em; color: var(--muted); }
.shots figcaption b { font-weight: 500; color: var(--text); }
.shots.quad { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.shots .frame.top img { object-position: 50% 0; }

.route { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }
.route li { border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 16px 16px 18px; display: grid; gap: 6px; align-content: start; }
.route .stages { font: 400 11px/1 var(--f-mono); letter-spacing: .08em; color: var(--muted); font-variant-numeric: tabular-nums; }
.route .zone { font: 600 17px/1.2 var(--f-game); letter-spacing: .02em; }
.route .note { font-size: 13px; line-height: 1.4; color: var(--muted); }
.route .rift { grid-column: 1 / -1; display: flex; gap: 20px; align-items: baseline; flex-wrap: wrap; background: linear-gradient(90deg, rgba(125,43,34,.22), transparent 70%); }
.route .rift .zone { font-size: 22px; }

/* ——— Downloads ——— */
.downloads { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.dl { border: 1px solid var(--line); background: var(--surface); padding: 22px; display: flex; flex-direction: column; gap: 10px; }
.dl:hover { border-color: var(--brass-dim); }
.dl .plat { font: 700 26px/1 var(--f-stamp); text-transform: uppercase; letter-spacing: .04em; }
.dl .meta { font: 400 11px/1.4 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.dl p { font-size: 14px; line-height: 1.5; color: var(--text-soft); }
.dl .btn { align-self: start; margin-top: auto; }
.dl.pending { border-style: dashed; background: transparent; }
.dl.pending .plat { color: var(--muted); }
.dl-foot { margin-top: 20px; font-size: 14px; color: var(--muted); max-width: 70ch; }
.dl-foot a { color: var(--brass); }
.beta-note { border: 1px solid var(--brass-dim); border-left: 4px solid var(--brass); background: var(--surface); padding: 16px 20px; margin-bottom: 20px; max-width: 80ch; }
.beta-note b { color: var(--brass); }
.beta-note p { margin: 6px 0 0; font-size: 14px; line-height: 1.5; color: var(--text-soft); }
.beta-note a { color: var(--brass); }
.downloads.packs, .downloads.pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pager { margin-top: 72px; border-top: 1px solid var(--line); }
.pager .wrap { display: flex; justify-content: space-between; gap: 24px; padding-top: 28px; padding-bottom: 8px; flex-wrap: wrap; }

/* ——— Log ——— */
.log { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.log li { display: grid; grid-template-columns: 220px minmax(0, 1fr) auto; gap: 32px; padding: 22px 0; border-bottom: 1px solid var(--line); align-items: baseline; }
.log h3 { font: 600 19px/1.35 var(--f-body); }
.log p { color: var(--muted); font-size: 15px; margin-top: 6px; max-width: 62ch; }
.log .kind { display: grid; gap: 6px; }
.log .kind a, .log .kind b { font: 500 11px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--brass); text-decoration: none; font-weight: 500; }
.log .kind a:hover { text-decoration: underline; }
.filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }
.filters button { font: 500 12px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); background: transparent; border: 1px solid var(--line); padding: 9px 12px; cursor: pointer; }
.filters button:hover { color: var(--text); }
.filters button[aria-pressed="true"] { color: #16130d; background: var(--brass); border-color: var(--brass); }

/* ——— Contact ——— */
.channels { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.channels li { display: grid; grid-template-columns: 220px minmax(0, 1fr) auto; gap: 32px; padding: 26px 0; border-bottom: 1px solid var(--line); align-items: baseline; }
.channels h2 { font: 700 26px/1.1 var(--f-stamp); text-transform: uppercase; letter-spacing: .03em; }
.channels p { color: var(--text-soft); max-width: 56ch; }
.channels a.mail { font: 500 15px/1.2 var(--f-mono); color: var(--brass); text-decoration: none; border-bottom: 1px solid var(--brass-dim); padding-bottom: 3px; white-space: nowrap; }
.channels a.mail:hover { border-color: var(--brass); }
.checklist { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); border: 1px solid var(--line); }
.checklist li { padding: 18px; display: grid; gap: 6px; align-content: start; }
.checklist li + li { border-left: 1px solid var(--line); }
.checklist b { font-weight: 600; }
.checklist span { font-size: 14px; color: var(--muted); line-height: 1.45; }

.signup { margin-top: 72px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--surface); }
.signup .wrap { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px; padding-top: 48px; padding-bottom: 48px; align-items: center; }
.signup h2 { font: 700 44px/1 var(--f-stamp); text-transform: uppercase; }
.signup h2 + p { margin-top: 12px; color: var(--muted); max-width: 44ch; }
form { display: grid; gap: 10px; }
.field { display: flex; }
input[type=email] { flex: 1; min-width: 0; font: 400 16px/1 var(--f-body); color: var(--text); background: var(--ground); border: 1px solid var(--line); border-right: 0; padding: 14px 16px; }
input::placeholder { color: #6f6b63; }
form .label { text-transform: none; letter-spacing: .02em; font-size: 12px; }

/* ——— Footer ——— */
footer { margin-top: 88px; border-top: 1px solid var(--line); }
.signup + footer, .pager + footer { margin-top: 0; }
footer .wrap { display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap; padding-top: 28px; padding-bottom: 40px; }
footer .mark { font-size: 18px; }
footer nav a { font-size: 12px; }

/* ——— Small screens ——— */
@media (max-width: 900px) {
  .wrap { padding: 0 18px; }
  .mark { font-size: 20px; }
  nav { gap: 18px; }
  .opening { padding: 44px 0 32px; }
  .opening h1 { font-size: clamp(44px, 15vw, 96px); }
  .page-head { padding: 44px 0 28px; }
  .page-head h1 { font-size: clamp(40px, 13vw, 72px); }
  .head h2, .signup h2 { font-size: 32px; }
  .opening .wrap, .signup .wrap, .works-grid { grid-template-columns: 1fr; }
  .head { grid-template-columns: 1fr; gap: 10px; }
  .head p, .head .more { grid-column: 1; }
  .plate > img { aspect-ratio: 4 / 3; }
  .plate::after { display: none; }
  .tag { position: relative; right: auto; bottom: auto; width: auto; margin: -64px 16px 16px; }
  .fact-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fact-strip div:nth-child(3) { border-left: 0; }
  .fact-strip div:nth-child(n+3) { border-top: 1px solid var(--line); }
  .shots, .shots.quad { grid-template-columns: 1fr; }
  .downloads, .downloads.packs, .downloads.pair { grid-template-columns: 1fr; }
  .route { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .log li, .channels li { grid-template-columns: 1fr; gap: 8px; }
  .checklist { grid-template-columns: 1fr; }
  .checklist li + li { border-left: 0; border-top: 1px solid var(--line); }
}
@media (prefers-reduced-motion: reduce) {
  .tag { animation: none; }
  .shots img, .work-card .cover img { transition: none; }
}

/* Home and expandable game catalogue. */
.home-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
.home-feature { display: grid; grid-template-columns: 1.4fr 1fr; border: 1px solid var(--line); background: var(--surface); text-decoration: none; }
.home-feature:hover { border-color: var(--brass); }
.home-feature > img { width: 100%; height: 100%; object-fit: cover; }
.home-feature .body { padding: 36px; display: grid; gap: 20px; align-content: center; justify-items: start; }
.home-feature h2 { font-size: clamp(28px, 3vw, 42px); }
.home-feature p, .home-links p, .future-note p { color: var(--text-soft); }
.home-feature .go { color: var(--brass); }
.home-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; }
.home-links > a { display: grid; align-content: start; gap: 14px; text-decoration: none; padding-top: 24px; border-top: 1px solid var(--line); }
.home-links > a:hover { border-color: var(--brass); }
.home-links h2 { font-size: 23px; }
.catalogue-toolbar { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 24px; }
.catalogue-toolbar .filters { margin: 0; }
.works-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); }
.work-card .row { flex-wrap: wrap; }
.work-card .body { grid-template-rows: auto auto 1fr auto auto; }
.catalogue-empty { border: 1px dashed var(--line); padding: 36px; color: var(--text-soft); }
.future-note { margin-top: 40px; padding: 32px; border: 1px dashed var(--line); display: grid; justify-items: start; gap: 14px; }
.future-note h2 { font: 700 32px/1.1 var(--f-stamp); }
nav a[aria-current="true"] { color: var(--text); border-color: var(--brass); }
@media (max-width: 700px) {
  .home-feature, .home-links { grid-template-columns: 1fr; }
  .home-feature .body { padding: 24px; }
  .home-feature > img { aspect-ratio: 16 / 9; }
  .future-note { padding: 24px; }
}

/* Hall of Legends: the live Steam leaderboards (leaderboard.js). .hall is the script's root;
   .hall-box is the bordered table; .hall-toolbar holds the two .filters rows on the full page. */
.hall-toolbar { display: grid; gap: 10px; margin-bottom: 20px; }
.hall-toolbar .filters { margin: 0; }
.hall-box { border: 1px solid var(--line); background: var(--surface); }
.hall-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px 24px; flex-wrap: wrap; padding: 18px 20px 14px; border-bottom: 1px solid var(--line); }
.hall-head h2 { font: 700 26px/1.1 var(--f-game); letter-spacing: .03em; }
.hall-head .blurb { font-size: 14px; color: var(--muted); max-width: 60ch; }
.hall-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.hall-table th { text-align: left; font: 500 11px/1.3 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); padding: 10px 20px; border-bottom: 1px solid var(--line); }
.hall-table td { padding: 10px 20px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.hall-table tbody tr:last-child td { border-bottom: 0; }
.hall-table tbody tr:hover td { background: rgba(201,160,90,.05); }
.hall-table .rank { width: 72px; font: 700 20px/1 var(--f-stamp); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hall-table th.rank { font: 500 11px/1.3 var(--f-mono); }
.hall-table tbody tr:nth-child(-n+3) .rank { color: var(--brass); }
.hall-table td.player { min-width: 0; }
.hall-table .who { display: flex; align-items: center; gap: 12px; min-width: 0; }
.hall-table .ava { display: block; width: 32px; height: 32px; flex: none; border: 1px solid var(--line); background: #0c0d10 repeating-linear-gradient(135deg, transparent 0 4px, rgba(255,255,255,.03) 4px 8px); object-fit: cover; }
.hall-table .name { text-decoration: none; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hall-table .name:hover { color: var(--brass); text-decoration: underline; }
.hall-table .tagid { font: 400 12px/1 var(--f-mono); color: var(--muted); letter-spacing: .06em; }
.hall-table .score { text-align: right; font: 500 16px/1 var(--f-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hall-table th.score { text-align: right; width: 132px; }
.hall-state { display: grid; gap: 8px; justify-items: start; padding: 28px 20px 30px; color: var(--text-soft); }
.hall-state b { font: 700 22px/1.15 var(--f-stamp); text-transform: uppercase; letter-spacing: .03em; color: var(--brass); }
.hall-state p { font-size: 15px; color: var(--muted); max-width: 60ch; }
.hall-state:empty { display: none; }
.hall-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px 24px; flex-wrap: wrap; padding: 14px 20px; border-top: 1px solid var(--line); }
.hall-foot .label { text-transform: none; letter-spacing: .04em; font-size: 12px; }
.hall-foot .btn { margin-left: auto; }
.hall-page .dl-foot { margin-top: 24px; }
@media (max-width: 900px) {
  .hall-table th, .hall-table td { padding: 10px 14px; }
  .hall-table .rank { width: 56px; font-size: 17px; }
  .hall-table th.score { width: 92px; }
  .hall-table .ava { width: 28px; height: 28px; }
  .hall-head, .hall-state, .hall-foot { padding-left: 14px; padding-right: 14px; }
}

/* HaboonUI (works/haboonui.html): the title, and the changelog's bullet lists inside .log rows. */
.t-haboonui { font-family: var(--f-game); letter-spacing: .03em; }
.t-haboon-orbs { font-family: var(--f-game); letter-spacing: .03em; }
/* Keep the square Haboon Orbs wordmark visible inside the catalogue's wide cover. */
.work-card .cover-orbs img { object-fit: contain; }
/* Its plate's logo sits left of centre: the phone crop (4:3) follows it. The plate is 16:8, so wide screens don't crop. */
.plate > img.plate-orbs { object-position: 15% 40%; }
.changelog ul { list-style: square; margin: 10px 0 0; padding-left: 20px; display: grid; gap: 6px; max-width: 72ch; }
.log.changelog ul li { display: list-item; padding: 0; border: 0; font-size: 15px; line-height: 1.5; color: var(--text-soft); }
.changelog ul li::marker { color: var(--brass-dim); }
.changelog ul b { color: var(--text); font-weight: 600; }

/* Feedback (feedback.html): the form, sent by site-worker/feedback.js, and notes beside it. */
.feedback { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 56px; align-items: start; }
.feedback-form { gap: 22px; }
.feedback-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.feedback-field { display: grid; gap: 8px; }
.feedback-field select, .feedback-field textarea, .feedback-field input { width: 100%; font: 400 16px/1.5 var(--f-body); color: var(--text); background: var(--ground); border: 1px solid var(--line); padding: 12px 14px; border-radius: 0; }
.feedback-field select { appearance: none; padding-right: 40px; cursor: pointer; background-image: linear-gradient(45deg, transparent 50%, var(--brass) 50%), linear-gradient(135deg, var(--brass) 50%, transparent 50%); background-position: calc(100% - 20px) 50%, calc(100% - 15px) 50%; background-size: 5px 5px; background-repeat: no-repeat; }
.feedback-field textarea { resize: vertical; min-height: 220px; font: 400 14px/1.55 var(--f-mono); }
.feedback-field input[type=email] { border-right: 1px solid var(--line); }
.feedback-field select:focus-visible, .feedback-field textarea:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
.feedback-field .hint { font-size: 13px; color: var(--muted); }
.feedback-trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.feedback-check:empty { display: none; }
.feedback-send { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.feedback-send .btn { padding: 14px 28px; }
.feedback-send .btn:disabled { opacity: .5; cursor: default; }
.feedback-status { font-size: 15px; color: var(--text-soft); }
.feedback-status[data-tone="ok"] { color: #9fcf8f; }
.feedback-status[data-tone="bad"] { color: #e09a85; }
.feedback-notes { display: grid; gap: 28px; border-left: 1px solid var(--line); padding-left: 32px; }
.feedback-notes h2 { font: 700 22px/1.1 var(--f-stamp); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 8px; }
.feedback-notes p { font-size: 15px; color: var(--text-soft); }
.feedback-notes code { font: 500 14px var(--f-mono); color: var(--text); }
.feedback-notes a.mail { color: var(--brass); text-decoration: none; border-bottom: 1px solid var(--brass-dim); overflow-wrap: anywhere; }
@media (max-width: 900px) {
  .feedback { grid-template-columns: 1fr; gap: 40px; }
  .feedback-pair { grid-template-columns: 1fr; }
  .feedback-notes { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 28px; }
}

/* Full release notes expand without JavaScript, including inside workshop posts. */
.release-details { margin-top: 16px; max-width: 76ch; }
.release-details summary { color: var(--brass); cursor: pointer; font-weight: 600; padding: 8px 0; }
.release-details summary:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
.release-details h4 { margin: 24px 0 8px; font-size: 17px; }
.release-details p { max-width: none; }
.release-details code { font-size: .9em; overflow-wrap: anywhere; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   Motion and extras (boot.js, fx.js). boot.js flags <html> before the first paint:
   .js always; .motion, or .calm under reduced motion or calm mode; .vt / .vt-fallback; .intro
   on the first page of a visit. Only .motion hides anything, and boot.js drops it if fx.js
   never runs, so every page still reads without JavaScript.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
:root {
  --ink: #0b0c0f;
  --brass-hi: #f1d59b;
  --ease-out: cubic-bezier(.2,.7,.2,1);
  --ease-io: cubic-bezier(.7,0,.2,1);
}
::selection { background: rgba(201,160,90,.38); color: #fff; }
html { scrollbar-color: var(--brass-dim) var(--ground); }
.js { scroll-padding-top: 96px; scrollbar-gutter: stable; }
.motion { scroll-behavior: smooth; }
main, footer { overflow-x: clip; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ——— Page transitions ———
   Cross-document view transitions: the new page opens as an iris from the click point (--vt-x,
   --vt-y, set by boot.js), the old one sinks away, the header holds still and a work's art morphs
   from its card to its page ("art", named by boot.js). Other browsers get the curtain.
   Keep them short and moving from the first frame (ease-out, not ease-in-out): the page is ready
   in well under a tenth of a second, so a slow start reads as the site lagging. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
::view-transition-old(root) { animation: vt-sink .35s var(--ease-out) both; }
::view-transition-new(root) { animation: vt-iris .45s var(--ease-out) both; }
@keyframes vt-sink { to { transform: scale(.94); opacity: .3; filter: brightness(.6); } }
@keyframes vt-iris {
  from { clip-path: circle(0% at var(--vt-x, 50%) var(--vt-y, 40%)); }
  to { clip-path: circle(150% at var(--vt-x, 50%) var(--vt-y, 40%)); }
}
.vt .bar { view-transition-name: bar; }
::view-transition-group(bar) { animation-duration: .45s; animation-timing-function: var(--ease-out); }
::view-transition-old(bar) { display: none; }
::view-transition-new(bar) { animation: none; }
::view-transition-group(art) { animation-duration: .55s; animation-timing-function: var(--ease-out); }
::view-transition-old(art), ::view-transition-new(art) { width: 100%; height: 100%; object-fit: cover; animation-duration: .55s; }
::view-transition-old(art):only-child { animation: vt-fade .25s ease both; }
::view-transition-new(art):only-child { animation: vt-art-in .55s var(--ease-out) both; }
@keyframes vt-fade { to { opacity: 0; } }
@keyframes vt-art-in { from { opacity: 0; transform: scale(1.05); } }

.curtain {
  position: fixed; inset: 0; z-index: 9997; background: var(--ink); pointer-events: none;
  transform: translateY(101%); transition: transform .26s var(--ease-out);
  box-shadow: 0 -2px 0 var(--brass), 0 -40px 80px rgba(201,160,90,.22);
}
.curtain.on { transform: none; pointer-events: auto; }
html.curtain-in::before {
  content: ""; position: fixed; inset: 0; z-index: 9997; pointer-events: none; background: var(--ink);
  box-shadow: 0 2px 0 var(--brass), 0 40px 80px rgba(201,160,90,.22);
  animation: curtain-up .45s var(--ease-out) forwards;
}
@keyframes curtain-up { to { transform: translateY(-101%); } }

/* ——— Intro: lighting the forge, once per visit ——— */
html.intro { overflow: hidden; }
html.intro::before { content: ""; position: fixed; inset: 0; z-index: 9998; background: var(--ink); }
.intro { position: fixed; inset: 0; z-index: 9999; display: grid; place-items: center; }
.intro.open { pointer-events: none; }
.intro-half { position: absolute; left: 0; right: 0; height: 50.5%; background: var(--ink); transition: transform 1s var(--ease-io); }
.intro-half.top { top: 0; }
.intro-half.bot { bottom: 0; }
.intro-half.top::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; opacity: 0; transition: opacity .2s;
  background: linear-gradient(90deg, transparent, var(--brass-hi), transparent); box-shadow: 0 0 24px 2px rgba(241,213,155,.6);
}
.intro.lit .intro-half.top::after { opacity: 1; }
.intro.open .intro-half.top { transform: translateY(-101%); }
.intro.open .intro-half.bot { transform: translateY(101%); }
.intro-core { position: relative; display: grid; gap: 18px; justify-items: center; transition: opacity .45s, transform 1s var(--ease-io); }
.intro.open .intro-core { opacity: 0; transform: scale(1.1); }
.intro-mark { font: 700 clamp(40px, 8vw, 92px)/.9 var(--f-stamp); letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; font-kerning: none; transition: text-shadow .3s; }
.intro-mark .w { color: var(--brass); }
.intro-mark .ch { display: inline-block; animation: ch-stamp .7s var(--ease-out) both; animation-delay: calc(80ms + var(--i) * 70ms); }
.intro.quick .intro-mark .ch { animation-duration: .45s; animation-delay: calc(var(--i) * 28ms); }
.intro.lit .intro-mark { text-shadow: 0 0 46px rgba(241,213,155,.55); }
.intro-bar { width: min(340px, 70vw); height: 1px; background: rgba(201,160,90,.18); overflow: hidden; }
.intro-bar i { display: block; height: 100%; transform: scaleX(0); transform-origin: left; background: linear-gradient(90deg, var(--brass-dim), var(--brass-hi)); }
.intro-meta { width: min(340px, 70vw); display: flex; justify-content: space-between; gap: 16px; font: 500 11px/1 var(--f-mono); letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
.intro-pct { color: var(--brass); font-variant-numeric: tabular-nums; }

/* ——— Embers, sparks, grain ——— */
.embers { position: fixed; inset: 0; z-index: -1; width: 100%; height: 100%; pointer-events: none; }
.sparks { position: fixed; inset: 0; z-index: 10001; width: 100%; height: 100%; pointer-events: none; }
.motion body::after {
  content: ""; position: fixed; inset: -64px; z-index: 9400; pointer-events: none; opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 1.4s steps(5) infinite;
}
@keyframes grain {
  0%, 100% { transform: translate(0, 0); } 20% { transform: translate(-40px, 24px); } 40% { transform: translate(28px, -46px); }
  60% { transform: translate(-58px, -12px); } 80% { transform: translate(44px, 34px); }
}

/* ——— Header: sticky, tucks away on the way down, shows the scroll as a brass line ——— */
.js .bar { position: sticky; top: 0; z-index: 60; transition: translate .45s var(--ease-io); }
/* The backing fades in as a layer of its own. Fading the bar's own colour, border and shadow
   instead repaints the bar, and the page under it, on every frame of the fade. The blur stays on
   the bar: inside it, the layer would only see the bar (its view-transition name walls it off). */
.js .bar.scrolled { -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.js .bar::before {
  content: ""; position: absolute; inset: 0 0 -1px; z-index: -1; pointer-events: none; opacity: 0; transition: opacity .3s;
  background: rgba(15,16,20,.78); border-bottom: 1px solid rgba(201,160,90,.22); box-shadow: 0 12px 34px -20px rgba(0,0,0,.95);
}
.js .bar.scrolled::before { opacity: 1; }
.js .bar.tuck { translate: 0 -100%; }
.js .bar::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, var(--brass-dim), var(--brass-hi)); box-shadow: 0 0 10px rgba(241,213,155,.45);
  transform: scaleX(var(--progress, 0)); transform-origin: left;
}
/* Scroll timelines (most browsers now) let the graphics card move things with the scroll, with no
   script running each frame: this line, the home dial's turn and a project plate's drift. Where
   there are none, fx.js sets --progress, --spin and the plate's translate instead. */
@supports (animation-timeline: scroll()) {
  .js .bar::after { animation: read-line linear both; animation-timeline: scroll(root); }
  .motion .orrery { animation: orrery-turn linear both; animation-timeline: scroll(root); animation-range: 0 1000px; }
  /* The timeline is the plate's, not the image's: the plate clips its image, and that makes it the
     image's nearest scroller, which never moves. */
  .motion .plate { view-timeline: --plate block; }
  .motion .plate > img { animation: plate-drift linear both; animation-timeline: --plate; animation-range: exit; }
}
@keyframes read-line { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes orrery-turn { to { rotate: 60deg; } }
@keyframes plate-drift { to { translate: 0 22%; } }
.fx-bar .wrap { justify-content: flex-start; }
.fx-bar nav { margin-left: auto; }
.glide nav { position: relative; }
.glide nav a, .glide nav a:hover, .glide nav a[aria-current] { border-color: transparent; }
.glider { position: absolute; left: 0; top: 0; height: 1px; pointer-events: none; opacity: 0; background: var(--brass); box-shadow: 0 0 10px rgba(201,160,90,.8); }
.glider.ready { transition: transform .45s var(--ease-out), width .45s var(--ease-out), opacity .3s; }
.kbar-chip {
  display: inline-flex; align-items: center; gap: 10px; padding: 7px 8px 7px 11px; cursor: pointer;
  font: 500 12px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
  background: rgba(255,255,255,.02); border: 1px solid var(--line);
  transition: color .2s, border-color .2s, translate .35s var(--ease-out);
}
.kbar-chip:hover { color: var(--text); border-color: var(--brass-dim); }
.kbar-chip svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.kbar-chip kbd { font: 500 10px/1 var(--f-mono); letter-spacing: .06em; padding: 3px 5px; border: 1px solid var(--line); color: var(--brass); }
@media (max-width: 900px) {
  .js { scroll-padding-top: 124px; }
  .fx-bar .kbar-chip { order: 1; margin-left: auto; padding: 8px; }
  .fx-bar .kbar-chip span, .fx-bar .kbar-chip kbd { display: none; }
  .fx-bar nav { order: 2; margin-left: 0; flex-basis: 100%; }
}

/* ——— Entrances ———
   Blocks wait at opacity 0 until fx.js's observer adds .in and plays their rise. Keep this list
   in step with REVEAL in fx.js. .rv-off (set by fx.js if a part of it fails) shows everything. */
.motion:not(.rv-off) :is(
  .page-head .wrap > :not(h1), .opening .wrap > div, .head, .catalogue-toolbar, .work-card, .future-note,
  .home-feature, .home-links > a, .fact-strip, .shots figure, .dl, .dl-foot, .beta-note, .route li, .log > li,
  .wrap > .filters, .channels li, .checklist li, .signup .wrap > *, .hall-toolbar, .hall-box, .prose > *,
  .feedback-form, .feedback-notes > *, .pager .wrap > *, .lost > *
):not(.in) { opacity: 0; }
.motion:not(.rv-off) :is(.opening, .page-head) h1:not(.split):not(.forged) { visibility: hidden; }
.js :is(.opening, .page-head) h1 { font-kerning: none; }
.split .ch { display: inline-block; }
.split:not(.go) .ch { opacity: 0; }
.split.go .ch { animation: ch-stamp .8s var(--ease-out) both; animation-delay: calc(60ms + var(--i) * var(--step, 40ms)); }
@keyframes ch-stamp {
  0% { opacity: 0; transform: translateY(.3em) scale(1.5) rotate(4deg); filter: blur(10px); }
  55% { opacity: 1; filter: blur(0); text-shadow: 0 0 28px rgba(241,213,155,.9); }
  100% { opacity: 1; transform: none; filter: none; text-shadow: none; }
}
.motion .head .label::before {
  content: ""; display: inline-block; width: 22px; height: 1px; margin-right: 10px; vertical-align: middle;
  background: var(--brass); transform: scaleX(0); transform-origin: left; transition: transform .8s .25s var(--ease-out);
}
.motion .head.in .label::before { transform: none; }
.motion img.fade { opacity: 0; }
.motion img.fade.loaded { opacity: 1; transition: opacity .8s ease, transform .6s ease; }

/* ——— Cursor (fine pointers, fx.js) ———
   The pointer is the system's own, drawn as a brass dot, so it moves the instant the mouse does
   however busy the page is. fx.js only keeps the ring on it and shows labels beside it. */
.has-cursor {
  --cur: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Ccircle cx='10' cy='10' r='7.5' fill='%23f1d59b' fill-opacity='.16'/%3E%3Ccircle cx='10' cy='10' r='3.3' fill='%23f1d59b' stroke='%2316130d' stroke-width='1.2'/%3E%3C/svg%3E") 10 10;
}
.has-cursor, .has-cursor * { cursor: var(--cur), auto !important; }
.has-cursor :is(a, button, summary, label, [role="button"], [data-cursor]),
.has-cursor :is(a, button, summary, label, [role="button"], [data-cursor]) * { cursor: var(--cur), pointer !important; }
.has-cursor :is(input, textarea, select, [contenteditable], iframe) { cursor: auto !important; }
.has-cursor :is(input[type=text], input[type=email], textarea) { cursor: text !important; }
.cursor { position: fixed; left: 0; top: 0; z-index: 10002; pointer-events: none; opacity: 0; transition: opacity .3s; }
.cursor.on { opacity: 1; }
.cursor.field { opacity: 0; }
.cursor-ring { position: fixed; left: 0; top: 0; width: 36px; height: 36px; margin: -18px 0 0 -18px; will-change: transform; transition: translate .3s var(--ease-out); }
.cursor-ring::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; border: 1px solid rgba(201,160,90,.75);
  transition: transform .35s var(--ease-out), background-color .3s, border-color .3s;
}
.cursor.hot .cursor-ring::before { transform: scale(1.7); background: rgba(201,160,90,.1); border-color: var(--brass-hi); }
/* A label rides beside the pointer, not under it, so the dot never covers the word. */
.cursor.labeled .cursor-ring { translate: 44px 40px; }
.cursor.labeled .cursor-ring::before { transform: scale(2.1); background: rgba(201,160,90,.94); border-color: transparent; box-shadow: 0 8px 22px -8px rgba(0,0,0,.8); }
.cursor.press .cursor-ring::before { transform: scale(.75); }
.cursor.hot.press .cursor-ring::before { transform: scale(1.4); }
.cursor.labeled.press .cursor-ring::before { transform: scale(1.9); }
.cursor-label {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%; white-space: nowrap; opacity: 0; transition: opacity .2s;
  font: 600 10px/1 var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: #16130d;
}
.cursor.labeled .cursor-label { opacity: 1; transition-delay: .08s; }

/* ——— Surfaces: tilt, spotlight and a border that lights up under the pointer ——— */
.spot { position: relative; }
.spot::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .35s;
  background: radial-gradient(520px circle at var(--mx, 50%) var(--my, 50%), rgba(201,160,90,.11), transparent 42%);
}
/* While lit, the glow is a layer of its own: following the pointer redraws only the glow, not the
   card with its picture and text under it. */
.spot.lit::after { opacity: 1; will-change: opacity; }
/* Only the card under the pointer carries the tilt; the rest stay untransformed, so a page's cards
   don't each start an (invisible) transition as fx.js marks them on arrival. */
.motion .tilt { transition: transform .6s var(--ease-out), border-color .25s, box-shadow .4s; }
.motion .tilt.lit { transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); transition: transform .12s linear, border-color .25s, box-shadow .4s; }
.tilt::before {
  content: ""; position: absolute; inset: -1px; z-index: 2; padding: 1px; pointer-events: none; opacity: 0; transition: opacity .35s;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(241,213,155,.85), transparent 60%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
}
.tilt.lit::before { opacity: 1; will-change: opacity; }
.js a.work-card:hover, .js .home-feature:hover, .js .dl:hover { box-shadow: 0 34px 70px -34px rgba(0,0,0,.95), 0 0 46px -24px rgba(201,160,90,.45); }

/* Buttons: a glint crosses on hover; the filled ones glow. */
.js .btn { position: relative; overflow: hidden; transition: background-color .25s, border-color .25s, color .25s, box-shadow .35s, translate .35s var(--ease-out); }
.js .btn::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; transform: translateX(-120%); transition: transform .75s var(--ease-out);
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.5) 50%, transparent 70%);
}
.js .btn.ghost::after { background: linear-gradient(105deg, transparent 30%, rgba(201,160,90,.28) 50%, transparent 70%); }
.js .btn:hover::after { transform: translateX(120%); }
.js .btn:not(.ghost):hover { box-shadow: 0 12px 34px -12px rgba(201,160,90,.7), inset 0 0 0 1px rgba(255,244,220,.35); }

/* Work cards: a glint across the cover and HUD corners closing in on hover. */
.js .work-card .cover::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; transform: translateX(-100%); transition: transform 1.1s var(--ease-out);
  background: linear-gradient(115deg, transparent 35%, rgba(241,213,155,.22) 50%, transparent 65%); mix-blend-mode: screen;
}
.js a.work-card:hover .cover::after { transform: translateX(100%); }
.js .work-card .cover::before {
  content: ""; position: absolute; inset: 16px; z-index: 1; pointer-events: none; opacity: 0; transition: opacity .3s, inset .45s var(--ease-out);
  --c: rgba(241,213,155,.9);
  background:
    linear-gradient(var(--c), var(--c)) left top / 18px 1px no-repeat, linear-gradient(var(--c), var(--c)) left top / 1px 18px no-repeat,
    linear-gradient(var(--c), var(--c)) right top / 18px 1px no-repeat, linear-gradient(var(--c), var(--c)) right top / 1px 18px no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / 18px 1px no-repeat, linear-gradient(var(--c), var(--c)) left bottom / 1px 18px no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom / 18px 1px no-repeat, linear-gradient(var(--c), var(--c)) right bottom / 1px 18px no-repeat;
}
.js a.work-card:hover .cover::before { opacity: 1; inset: 10px; }
.js a.work-card:hover .no { color: var(--brass-hi); }

/* Status badges: a live dot while in development, a sheen on what is coming. Everything that loops
   on the site animates transform, opacity or filter only, which the graphics card runs without the
   page redrawing; a looping colour, shadow or background would repaint on every frame. */
.status.dev::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 7px; border-radius: 50%; background: #e0604f; vertical-align: 1px; }
.motion .status.dev::before { animation: rec 1.6s ease-in-out infinite; }
@keyframes rec { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.7); } }
.motion .status.soon { position: relative; overflow: hidden; }
.motion .status.soon::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; transform: translateX(-100%);
  background: linear-gradient(100deg, transparent 20%, rgba(241,213,155,.32) 50%, transparent 80%);
  animation: badge-sheen 3.6s linear infinite;
}
@keyframes badge-sheen { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }

/* ——— Page heads: a blueprint grid and one scan line on arrival ——— */
.js .page-head { position: relative; isolation: isolate; overflow: clip; }
.js .page-head::before, .js .opening::before {
  content: ""; position: absolute; inset: 0; z-index: -2; pointer-events: none;
  background-image: linear-gradient(rgba(201,160,90,.065) 1px, transparent 1px), linear-gradient(90deg, rgba(201,160,90,.065) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 70% 100% at 85% 0%, #000 0%, transparent 72%); mask-image: radial-gradient(ellipse 70% 100% at 85% 0%, #000 0%, transparent 72%);
}
/* The line is drawn at the top of a box as tall as its parent, and the box slides down: a transform,
   so the arriving page is never laid out again for it. */
.motion .page-head::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent, var(--brass-hi), transparent) 0 0 / 100% 1px no-repeat;
  animation: scan 1.8s .35s var(--ease-io) both;
}
@keyframes scan { 0% { transform: none; opacity: 0; } 15% { opacity: .85; } 100% { transform: translateY(100%); opacity: 0; } }

/* ——— Home: the orrery, the forged title, the readout and the ticker ——— */
.opening { position: relative; isolation: isolate; overflow: clip; }
.js .opening::before { background-size: 64px 64px; -webkit-mask-image: radial-gradient(ellipse 60% 85% at 78% 50%, #000 0%, transparent 75%); mask-image: radial-gradient(ellipse 60% 85% at 78% 50%, #000 0%, transparent 75%); }
.orrery {
  position: absolute; z-index: -1; right: -6%; top: 50%; width: min(760px, 72vw); aspect-ratio: 1; margin-top: calc(min(760px, 72vw) / -2);
  pointer-events: none; opacity: .75;
  translate: var(--px) var(--py); rotate: var(--spin); transition: translate 1s var(--ease-out), rotate 1s var(--ease-out);
  -webkit-mask-image: radial-gradient(circle closest-side, #000 60%, transparent 100%); mask-image: radial-gradient(circle closest-side, #000 60%, transparent 100%);
}
/* fx.js sets these on .orrery alone. Registered as not inherited, so a change doesn't restyle the
   rings under it on every pointer move. */
@property --px { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --py { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --spin { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.o-spin, .orrery svg { position: absolute; inset: 0; }
.orrery svg { display: block; width: 100%; height: 100%; overflow: visible; }
.motion .o-spin { will-change: transform; }
.motion .o-slow { animation: spin 140s linear infinite; }
.motion .o-rev { animation: spin 100s linear infinite reverse; }
.motion .o-mid { animation: spin 70s linear infinite; }
.motion .o-fast { animation: spin 26s linear infinite reverse; }
.o-line { fill: none; stroke: rgba(201,160,90,.26); }
.o-ticks { fill: none; stroke: rgba(201,160,90,.34); stroke-width: 8; stroke-dasharray: 1 8.84; }
.o-ticks.major { stroke: rgba(241,213,155,.6); stroke-width: 16; stroke-dasharray: 1.5 87.1; }
.o-text { font: 500 13px var(--f-mono); fill: rgba(207,201,189,.5); }
.o-brass { fill: none; stroke: rgba(201,160,90,.55); stroke-width: 1.2; }
.o-node { fill: var(--brass-hi); stroke: rgba(241,213,155,.22); stroke-width: 9; }
.o-dash { fill: none; stroke: rgba(201,160,90,.32); stroke-dasharray: 2 10; }
.o-arc { fill: none; stroke: var(--brass); stroke-width: 2; stroke-linecap: round; }
.o-cross { fill: none; stroke: rgba(201,160,90,.35); }
.o-gem { fill: rgba(201,160,90,.14); stroke: var(--brass-hi); }
.o-sweep {
  position: absolute; inset: 9%; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 285deg, rgba(201,160,90,.2) 352deg, rgba(241,213,155,.55) 360deg);
  -webkit-mask: radial-gradient(closest-side, transparent 30%, #000 31%, #000 99%, transparent 100%); mask: radial-gradient(closest-side, transparent 30%, #000 31%, #000 99%, transparent 100%);
}
.motion .o-sweep { animation: spin 7s linear infinite; }
.calm .o-sweep { display: none; }
.motion .opening h1.forged .w {
  width: fit-content; color: transparent; -webkit-background-clip: text; background-clip: text; background-size: 300% 100%;
  background-image: linear-gradient(100deg, var(--brass) 0 38%, var(--brass-hi) 47%, #fff4dc 50%, var(--brass-hi) 53%, var(--brass) 62% 100%);
  background-position: 100% 0;
}
/* The sheen sweeps the forged title now and then (fx.js home()), rather than as a loop that would
   repaint the title on every frame even while it waits between sweeps. */
.readout { display: none; }
.js .readout { display: block; min-height: 44px; margin-top: 26px; }
.readout-link { display: inline-grid; gap: 6px; text-decoration: none; opacity: 0; transition: opacity .6s; }
.readout.on .readout-link { opacity: 1; }
.readout .rd-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font: 500 11px/1.3 var(--f-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.readout .live { display: inline-flex; align-items: center; gap: 8px; color: var(--brass); }
.readout .live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--brass); }
.motion .readout .live::before { animation: rec 1.8s ease-in-out infinite; }
.readout .rd-title { font: 500 15px/1.4 var(--f-body); color: var(--text); }
.readout-link:hover .rd-title { color: var(--brass); text-decoration: underline; text-underline-offset: 3px; }
.ticker { display: none; }
.js .ticker {
  display: block; height: 46px; overflow: hidden; border-block: 1px solid var(--line); background: rgba(12,13,16,.55);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.ticker-track { display: flex; width: max-content; height: 100%; align-items: center; opacity: 0; transition: opacity .8s; }
.ticker.on .ticker-track { opacity: 1; }
.motion .ticker-track { animation: ticker 40s linear infinite; }
.js:not(.motion) .ticker-track { padding-left: 8%; }
.ticker:hover .ticker-track { animation-play-state: paused; }
.ticker-run { display: flex; align-items: center; gap: 28px; padding-right: 28px; }
@keyframes ticker { to { transform: translateX(-50%); } }
.tk { display: inline-flex; align-items: baseline; gap: 12px; white-space: nowrap; font: 500 11px/1 var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.tk b { font-weight: 500; color: var(--brass-dim); }
.tk em { font: 600 15px/1 var(--f-game); font-style: normal; letter-spacing: .04em; text-transform: none; color: var(--text); }
.tk i { font-style: normal; }
.tk i.dev { color: #d9a097; }
.tk i.soon { color: var(--brass); }
.tk-sep { color: var(--brass-dim); font-size: 10px; }
@media (max-width: 900px) {
  .orrery { width: 128vw; right: -58vw; margin-top: -64vw; opacity: .45; }
}

/* ——— Lists and pages ——— */
.filters button .n { margin-left: 8px; font-size: 10px; opacity: .6; }
.log > li:target { box-shadow: -16px 0 0 -13px var(--brass); }
.motion .log > li:target { animation: target-glow 2.4s .4s ease-out both; }
@keyframes target-glow { 0%, 30% { background: rgba(201,160,90,.1); } 100% { background: transparent; } }
.motion .plate > img { scale: 1.06; }
.motion .plate::before {
  content: ""; position: absolute; inset: -10px 0 0; z-index: 1; pointer-events: none; opacity: 0;
  background:
    linear-gradient(90deg, transparent, var(--brass-hi), transparent) 0 10px / 100% 1px no-repeat,
    linear-gradient(transparent, rgba(241,213,155,.22) 50%, transparent) 0 0 / 100% 21px no-repeat;
  animation: scan 2s .55s var(--ease-io) both;
}
.specs b.inf { color: var(--brass); }
.motion .specs b.inf { display: inline-block; text-shadow: 0 0 16px rgba(241,213,155,.4); animation: inf-glow 3s ease-in-out infinite; }
/* Only brightness pulses: a filter that spreads pixels (blur, drop-shadow) can't run off the page. */
@keyframes inf-glow { 50% { filter: brightness(1.45); } }
.js .shots .frame { cursor: zoom-in; }
.js .shots .frame:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
.motion .route .rift { position: relative; overflow: hidden; isolation: isolate; }
.motion .route .rift::before {
  content: ""; position: absolute; z-index: -1; left: 50%; top: 50%; width: 140%; aspect-ratio: 1; translate: -50% -50%; pointer-events: none;
  background: conic-gradient(from 0deg, transparent, rgba(125,43,34,.42), transparent 28%, rgba(201,160,90,.12), transparent 58%, rgba(125,43,34,.36), transparent);
  animation: spin 16s linear infinite;
}
.motion .route .rift .zone { text-shadow: 0 0 16px rgba(241,213,155,.35); animation: inf-glow 4s ease-in-out infinite; }
.mail-row { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.copy {
  font: 500 10px/1 var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); cursor: pointer;
  background: transparent; border: 1px solid var(--line); padding: 6px 8px; transition: color .2s, border-color .2s;
}
.copy:hover { color: var(--brass); border-color: var(--brass-dim); }

/* ——— 404: Hold the gate (404.html, gate.js) ——— */
.lost { display: grid; gap: 28px; }
.gate { position: relative; display: grid; gap: 12px; }
.gate canvas { display: block; width: 100%; height: clamp(300px, 44vw, 440px); border: 1px solid var(--line); background: #0c0d11; touch-action: manipulation; user-select: none; }
.gate-hud { display: flex; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap; }
.gate-hud b { font-weight: 500; color: var(--brass); letter-spacing: .1em; }
.gate-card {
  position: absolute; left: 50%; top: calc(clamp(300px, 44vw, 440px) / 2); translate: -50% -50%; width: min(440px, calc(100% - 32px));
  display: grid; gap: 12px; justify-items: start; padding: 24px; background: rgba(19,21,25,.93); border: 1px solid var(--brass-dim);
  box-shadow: 0 30px 80px -30px #000, 0 0 60px -30px rgba(201,160,90,.5);
}
.gate-card b { font: 700 28px/1.05 var(--f-stamp); letter-spacing: .03em; text-transform: uppercase; color: var(--brass); }
.gate-card p { font-size: 15px; color: var(--text-soft); }
.lost-ways { display: flex; flex-wrap: wrap; gap: 12px; }

/* ——— Search palette ——— */
html.kbar-open, html.lb-lock { overflow: hidden; }
.kbar {
  position: fixed; inset: 0; z-index: 9500; display: grid; justify-items: center; align-items: start; padding: min(14vh, 120px) 16px 16px;
  background: rgba(8,9,11,.62); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  opacity: 0; visibility: hidden; transition: opacity .25s, visibility 0s .25s;
}
.kbar.on { opacity: 1; visibility: visible; transition: opacity .25s; }
.kbar-panel {
  width: min(640px, 100%); max-height: min(72vh, 640px); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden;
  background: linear-gradient(180deg, rgba(36,39,46,.97), rgba(22,24,29,.98)); border: 1px solid var(--brass-dim);
  box-shadow: 0 0 0 1px rgba(0,0,0,.5), 0 40px 120px -20px rgba(0,0,0,.85), 0 0 90px -30px rgba(201,160,90,.45);
  transform: translateY(-10px) scale(.97); transition: transform .35s var(--ease-out);
}
.kbar.on .kbar-panel { transform: none; }
.kbar-top { display: flex; align-items: center; gap: 12px; padding: 16px 18px; border-bottom: 1px solid var(--line); }
.kbar-top svg { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--brass); stroke-width: 1.6; stroke-linecap: round; }
.kbar-top input { flex: 1; min-width: 0; background: transparent; border: 0; outline: 0; padding: 0; color: var(--text); font: 400 18px/1.3 var(--f-body); }
.kbar kbd { font: 500 11px/1 var(--f-mono); color: var(--muted); border: 1px solid var(--line); border-bottom-width: 2px; padding: 3px 6px; }
.kbar-list { list-style: none; margin: 0; padding: 8px; overflow: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--brass-dim) transparent; }
.kbar-group { padding: 14px 12px 6px; font: 500 11px/1 var(--f-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--brass-dim); }
.kbar-list [role="option"] { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 16px; padding: 10px 12px; cursor: pointer; border-left: 2px solid transparent; }
.kbar-list [aria-selected="true"] { background: rgba(201,160,90,.1); border-left-color: var(--brass); }
.kbar-t { grid-column: 1; font: 500 15px/1.35 var(--f-body); color: var(--text); }
.kbar-t mark { background: none; color: var(--brass-hi); text-decoration: underline; text-underline-offset: 3px; }
.kbar-s { grid-column: 1; font-size: 13px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kbar-g { grid-column: 2; grid-row: 1 / span 2; align-self: center; font: 500 11px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
[aria-selected="true"] .kbar-g { color: var(--brass); }
.kbar-empty { padding: 22px 12px; color: var(--muted); font-size: 15px; }
.kbar-foot { display: flex; flex-wrap: wrap; gap: 18px; padding: 10px 18px; border-top: 1px solid var(--line); font-size: 12px; color: var(--muted); }
.kbar-foot kbd { margin-right: 3px; }
@media (max-width: 700px) { .kbar { padding-top: 12px; } .kbar-foot { display: none; } }

/* ——— Screenshot viewer ——— */
.lightbox {
  position: fixed; inset: 0; z-index: 9600; display: grid; grid-template-columns: 64px minmax(0, 1fr) 64px; align-items: center; justify-items: center;
  padding: 64px 16px; background: rgba(8,9,11,.93); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  opacity: 0; visibility: hidden; transition: opacity .35s, visibility 0s .35s;
}
.lightbox.on { opacity: 1; visibility: visible; transition: opacity .35s; }
.lightbox.on.closing { opacity: 0; }
.lb-fig { grid-column: 2; margin: 0; display: grid; gap: 14px; width: min(100%, calc((100vh - 190px) * 16 / 9)); }
.lb-fig img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: contain; transform-origin: 0 0; background: #0c0d10; border: 1px solid var(--line); box-shadow: 0 40px 120px -30px #000; touch-action: pan-y; }
.lb-fig figcaption { display: flex; justify-content: space-between; gap: 12px; font: 400 13px/1.3 var(--f-mono); letter-spacing: .06em; color: var(--muted); }
.lb-fig figcaption b { font-weight: 500; color: var(--text); }
.lb-nav, .lb-close { width: 46px; height: 46px; display: grid; place-items: center; cursor: pointer; background: rgba(22,24,29,.85); border: 1px solid var(--line); color: var(--text); font: 400 17px/1 var(--f-mono); transition: color .2s, border-color .2s; }
.lb-nav:hover, .lb-close:hover { color: var(--brass); border-color: var(--brass); }
.lb-prev { grid-column: 1; }
.lb-next { grid-column: 3; }
.lb-close { position: absolute; top: 16px; right: 16px; }
.lb-count { position: absolute; top: 31px; left: 24px; font: 500 12px/1 var(--f-mono); letter-spacing: .14em; color: var(--muted); }
@media (max-width: 700px) {
  .lightbox { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr auto; padding: 72px 12px 24px; gap: 16px; }
  .lb-fig { grid-column: 1 / -1; grid-row: 1; }
  .lb-prev { grid-column: 1; grid-row: 2; justify-self: end; }
  .lb-next { grid-column: 2; grid-row: 2; justify-self: start; }
}

/* ——— Toasts, back to top ——— */
.toasts { position: fixed; left: 50%; bottom: 28px; z-index: 9700; translate: -50% 0; display: grid; gap: 10px; justify-items: center; width: max-content; max-width: calc(100vw - 32px); pointer-events: none; }
.toast {
  padding: 12px 18px; background: rgba(22,24,29,.96); border: 1px solid var(--brass-dim); color: var(--text); font: 500 14px/1.4 var(--f-body);
  box-shadow: 0 20px 50px -20px rgba(0,0,0,.9), 0 0 34px -14px rgba(201,160,90,.6);
  opacity: 0; transform: translateY(14px) scale(.98); transition: opacity .35s, transform .45s var(--ease-out);
}
.toast::before { content: "✦"; margin-right: 10px; color: var(--brass); }
.toast.on { opacity: 1; transform: none; }
.toast.blood { border-color: #a5463a; box-shadow: 0 20px 50px -20px rgba(0,0,0,.9), 0 0 44px -10px rgba(224,96,79,.6); }
.toast.blood::before { color: #e0604f; }
.totop {
  position: fixed; right: 22px; bottom: 22px; z-index: 70; width: 46px; height: 46px; padding: 0; display: grid; place-items: center; cursor: pointer;
  border: 0; border-radius: 50%; background: rgba(22,24,29,.85); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: var(--brass); font: 500 16px/1 var(--f-mono);
  opacity: 0; translate: 0 16px; pointer-events: none; transition: opacity .3s, translate .4s var(--ease-out), color .2s;
}
.totop.on { opacity: 1; translate: 0 0; pointer-events: auto; }
.totop:hover { color: var(--brass-hi); }
.totop svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); fill: none; }
.totop-track { stroke: var(--line); stroke-width: 1.5; }
.totop-ring { stroke: var(--brass); stroke-width: 1.5; stroke-dasharray: 100; stroke-dashoffset: 100; }

/* ——— Secrets: the Maelstrom and the anvil ——— */
.vortex {
  position: fixed; inset: -30vmax; z-index: 9300; pointer-events: none; opacity: 0; transition: opacity 1.4s; mix-blend-mode: screen;
  background: conic-gradient(from 0deg, transparent, rgba(125,43,34,.6), transparent 22%, rgba(201,160,90,.22) 38%, transparent 52%, rgba(125,43,34,.55) 72%, transparent);
  -webkit-mask-image: radial-gradient(circle, transparent 6%, #000 28%, #000 55%, transparent 72%); mask-image: radial-gradient(circle, transparent 6%, #000 28%, #000 55%, transparent 72%);
  animation: spin 3.5s linear infinite;
}
.maelstrom .vortex { opacity: .6; }
:root:not(.maelstrom) .vortex { animation-play-state: paused; }
.maelstrom main { animation: maelstrom-sway 8s ease-in-out both; }
@keyframes maelstrom-sway {
  15% { transform: rotate(-.6deg) scale(.99); filter: hue-rotate(-28deg) saturate(1.35); }
  50% { transform: rotate(.6deg) scale(.985); filter: hue-rotate(-34deg) saturate(1.5); }
  85% { transform: rotate(-.3deg); filter: hue-rotate(-28deg) saturate(1.35); }
}
.quake :is(main, .bar, footer) { animation: quake .55s cubic-bezier(.36,.07,.19,.97) both; }
@keyframes quake {
  10%, 90% { transform: translate(-1px, 1px); } 20%, 80% { transform: translate(3px, -2px); }
  30%, 50%, 70% { transform: translate(-5px, 3px); } 40%, 60% { transform: translate(5px, -3px); }
}
