/* Shared by the rendered pages and by play.html.
 *
 * The page background is the demos' own clear colour -- Color::srgb(0.09, 0.11,
 * 0.15) -- so a canvas dropped into the middle of the site has no seam around
 * it. No syntax highlighting: `fenced_code` emits <pre><code class="language-…">
 * and a monospace block on a darker panel is enough. */

:root {
  --bg: #171c26;
  --panel: #10141c;
  --ink: #dfe3ea;
  --dim: #949bab;
  --line: #2c3444;
  --link: #7fd4ff;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.65 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

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

nav, footer {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  padding: 0.9rem 1.5rem;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

footer {
  border-bottom: 0;
  border-top: 1px solid var(--line);
  margin-top: 3rem;
  color: var(--dim);
}

nav a, footer a { text-decoration: none; }
nav a:hover, footer a:hover { text-decoration: underline; }

main {
  max-width: 60rem;
  margin: 0 auto;
  padding: 1.5rem 1.5rem 4rem;
}

h1, h2, h3, h4 { line-height: 1.25; }
h1 { font-size: 1.9rem; margin: 1.2rem 0 0.6rem; }
h2 { font-size: 1.45rem; margin-top: 2.6rem; border-bottom: 1px solid var(--line); padding-bottom: 0.3rem; }
h3 { font-size: 1.15rem; margin-top: 2rem; }

hr { border: 0; border-top: 1px solid var(--line); margin: 2.5rem 0; }

/* Images are the point of most of these pages, and there are 38 GIFs of them.
 * `loading="lazy"` is put on every one by build_site.py; this only stops them
 * overflowing a phone. */
img {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 1rem auto;
  border-radius: 3px;
}

table {
  border-collapse: collapse;
  width: 100%;
  margin: 1.2rem 0;
  font-size: 0.94rem;
  display: block;
  overflow-x: auto;
}
th, td {
  border: 1px solid var(--line);
  padding: 0.4rem 0.6rem;
  text-align: left;
  vertical-align: top;
}
th { background: var(--panel); }

code {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 0.05rem 0.3rem;
  font-size: 0.9em;
}

pre {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.85rem 1rem;
  overflow-x: auto;
}
pre > code { background: none; border: 0; padding: 0; font-size: 0.88rem; }

blockquote {
  margin: 1.2rem 0;
  padding: 0.2rem 0 0.2rem 1rem;
  border-left: 3px solid var(--line);
  color: var(--dim);
}

/* `~~FALSIFIED~~` in FINDINGS.md is prose, not decoration: a claim that was
 * retracted. It has to read as struck through rather than merely faded. */
del { text-decoration: line-through; color: var(--dim); }

/* play.html. `play.html` gives the canvas `width="1280" height="720"`, and this
 * caps the box it is drawn in. What actually happens when it does is worth
 * writing down, because it is not what the `1280x720` attributes suggest:
 * `bevy_winit` observes the element and reports its CSS box as the window size,
 * so the render resolution *follows* this rule -- measured 993x558 in a
 * 1400x900 window. That is the better half of the deal, not a cost: HUD text
 * declared at `FontSize::Px(13.0)` lands on 13 real device pixels instead of
 * being drawn at 13 and scaled down to 10, and SwiftShader rasterises 39% fewer
 * of them. The pixel-laid-out HUD still fits, which is the thing to re-check if
 * this cap ever gets tighter.
 *
 * The side padding is load-bearing rather than decorative. Bevy's
 * `Window::prevent_default_event_handling` defaults to `true` and no demo
 * overrides it, so a wheel event over the canvas is consumed by the app and the
 * page does not scroll -- correctly, because that wheel is the camera's zoom.
 * The gutter is what the reader puts the pointer in to scroll past the demo, so
 * it has to survive every viewport: `clamp` keeps it from eating a phone screen
 * and from growing past a thumb's width on a monitor.
 *
 * The height cap goes on `.stage` as a max-WIDTH derived from it, not as a
 * max-height: `aspect-ratio` plus `width: 100%` plus `max-height` would honour
 * the height and keep the width, which is a stretched picture rather than a
 * smaller one. */
.play {
  max-width: 1280px;
  margin: 0 auto;
  padding: 1rem clamp(1rem, 7vw, 7rem) 3rem;
}

/* Sized here rather than on the canvas so `#loading`'s `inset: 0` still covers
 * exactly the canvas and not the gutter beside it. */
.stage {
  position: relative;
  width: 100%;
  max-width: min(1280px, calc(74vh * 16 / 9));
  margin-inline: auto;
}

/* `!important` on the two size properties, and it is the only `!important` in
 * this file. `bevy_winit` writes the canvas's CSS size *inline* from the backing
 * store -- the served element carries
 * `style="width: 1282px; height: 722px; min-width: 182px; min-height: 122px"` --
 * and an inline declaration beats a stylesheet rule that is not important. The
 * plain `width: 100%` this file used to carry therefore never applied at all,
 * which is exactly why the canvas was 1282 px wide on every viewport and the
 * page could not be scrolled past it.
 *
 * The canvas keeps `aspect-ratio` rather than winit's inline `height`, so the
 * box stays 16:9 whatever the cap resolves to. `min-width`/`min-height` are left
 * alone -- winit's 182x122 floor is below anything this produces. */
#isomesh-canvas {
  display: block;
  width: 100% !important;
  height: auto !important;
  aspect-ratio: 16 / 9;
  background: #000;
  border: 1px solid var(--line);
  border-radius: 4px;
  /* Without this the browser claims the touch stream for scroll and pinch, and
   * `game_dig`'s virtual stick receives a single `touchstart` and nothing after
   * it. A plain declaration is enough: `bevy_winit` writes only `width` and
   * `height` inline, which is why those two above need `!important` and nothing
   * else here does. */
  touch-action: none;
}

#loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1rem;
  background: rgba(16, 20, 28, 0.92);
  color: var(--ink);
}

.keys { color: var(--dim); font-size: 0.94rem; }
.keys kbd {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 0.05rem 0.35rem;
  font-family: inherit;
  color: var(--ink);
}

/* `play.html`'s landing state: reached by opening the page with no `?demo=`, or
 * with one that is not on the allow-list. It replaces the canvas rather than
 * sitting under it -- a black 16:9 box above a list reads as a demo that broke.
 * `.keys`'s dim colour is deliberately not reused: this is the page's content
 * when it is showing, not a footnote to something else. */
.play-index { margin: 0.5rem 0 0; }
.play-index ul {
  list-style: none;
  padding: 0;
  margin: 0.9rem 0 0;
  display: grid;
  gap: 0.55rem;
}
.play-index a {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--ink);
}
.play-index li { color: var(--dim); }

/* index.md's front-page demo, which is not a Bevy build and so has none of the
 * fixed-canvas constraint above: `lite.js` sizes its backing store from
 * `clientWidth` on every draw, so this one really does fit its parent. */
#isomesh-lite {
  display: block;
  width: 100%;
  /* Same height cap as the play page, same reason: on a short window the demo
   * must not fill the viewport, or there is nowhere to scroll from. `lite.js`
   * re-reads `clientWidth` every draw, so the backing store follows. */
  max-width: min(100%, calc(68vh * 16 / 9));
  margin-inline: auto;
  aspect-ratio: 16 / 9;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 4px;
  /* The canvas is the drag surface for the orbit camera. Without this, a drag
   * that leaves the element selects the prose behind it. */
  touch-action: none;
  user-select: none;
}

.lite-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 1.1rem;
  margin: 0.8rem 0 0.4rem;
  font-size: 0.94rem;
  color: var(--dim);
}

.lite-controls select,
.lite-controls input[type="range"] {
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 0.15rem 0.3rem;
  font: inherit;
}

.lite-controls label { display: flex; align-items: center; gap: 0.4rem; }

/* The report, and it is the point of the demo rather than decoration: these are
 * the same counters `isomesh::validate` puts in front of every test in the
 * repository, recomputed in the reader's browser. */
.lite-hud {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.4rem;
  margin: 0.2rem 0 0;
  padding: 0.55rem 0.75rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 4px;
  font-size: 0.9rem;
  color: var(--dim);
}

.lite-hud b { color: var(--ink); font-weight: 600; }

/* Hidden until something actually fails, and then it is the only thing on the
 * page that matters -- there is no degraded renderer behind it to fall back to. */
#lite-error {
  margin: 0.8rem 0 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid #7a3b3b;
  border-radius: 4px;
  background: #2a1a1c;
  color: #ffd9d9;
}
