@font-face {
  font-family: "Virgil";
  src: url("/static/fonts/Virgil-Regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

:root {
  --world-margin: 2000px;
  --dot-pitch: 20px;
  --dot-color: rgb(106 98 89 / 24%);
}

.ink,
.text-plane,
#scroll-proxy,
#reset-view,
#mode-toggle {
  display: none;
}

/* Everything below this line is *canvas* geometry, and almost all of it is gated on the
   canvas actually being open.
 *
 * Article mode is plain responsive HTML scrolled by the browser: no fixed viewport, no
 * world coordinates, no camera and no transform. It used to be none of those things only
 * until `mode.js` ran, at which point the article became a 720-unit paper fitted into the
 * window — which on a phone is a scale of 0.54, and an 18px article rendered at 10px. The
 * fixed paper is what a reader gets when they ask for the canvas, and not before.
 */

/* The one canvas rule article mode keeps: a horizontal swipe is never a pan, in either
   mode, so the promise does not change under the reader when they open the canvas. */
html[data-canvas-ready] #viewport {
  touch-action: pan-y pinch-zoom;
}

html[data-canvas-ready] body[data-mode="canvas"] {
  overflow-x: hidden;
}

html[data-canvas-ready] body[data-mode="canvas"] #viewport {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--paper);
  cursor: grab;
  touch-action: none;
}

@supports (overflow: clip) {
  html[data-canvas-ready] body[data-mode="canvas"] #viewport {
    overflow: clip;
  }
}

html[data-canvas-ready] body[data-mode="canvas"] #paper {
  cursor: auto;
  user-select: text;
}

html[data-canvas-ready] body[data-mode="canvas"][data-tool="draw"] #viewport,
html[data-canvas-ready] body[data-mode="canvas"][data-tool="draw"] #paper {
  cursor: crosshair;
  user-select: none;
}

html[data-canvas-ready] body[data-mode="canvas"][data-tool="erase"] #viewport,
html[data-canvas-ready] body[data-mode="canvas"][data-tool="erase"] #paper {
  cursor: cell;
  user-select: none;
}

html[data-canvas-ready] body[data-mode="canvas"] #world {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--paper-w);
  transform-origin: 0 0;
  will-change: transform;
}

/* The surface the paper sits on: bullet-journal dots over paper, reaching a world margin
   past the paper on every side so a panned camera never runs off the edge of it. It only
   exists in canvas mode — article mode's background is the body's own paper. */
html[data-canvas-ready] body[data-mode="canvas"] #world::before {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--world-margin)) auto auto calc(-1 * var(--world-margin));
  z-index: 0;
  width: calc(var(--paper-w) + 2 * var(--world-margin));
  height: calc(var(--paper-h, 0px) + 2 * var(--world-margin));
  background:
    radial-gradient(circle at center, var(--dot-color) 0 1px, transparent 1.25px),
    var(--paper);
  background-size: var(--dot-pitch) var(--dot-pitch);
}

html[data-canvas-ready] body[data-mode="canvas"] #paper {
  position: relative;
  z-index: 2;
  width: var(--paper-w);
  max-width: none;
  margin: 0;
  background: transparent;
}

html[data-canvas-ready] body[data-mode="canvas"] .ink {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: var(--paper-w);
  height: var(--paper-h, 0px);
  overflow: visible;
  pointer-events: none;
}

html[data-canvas-ready] body[data-mode="canvas"] #ink-under { z-index: 1; }
html[data-canvas-ready] body[data-mode="canvas"] #ink-over { z-index: 3; }

/* Scene text is real HTML, so it needs a plane of its own rather than an SVG <text>.
   Each plane shares its sibling ink plane's z-index and follows it in document order, so
   text paints just above its own layer's ink and the article still sits between the two.
   The plane itself is inert; only the private text editor ever takes a pointer here. */
html[data-canvas-ready] body[data-mode="canvas"] .text-plane {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: var(--paper-w);
  height: var(--paper-h, 0px);
  overflow: visible;
  pointer-events: none;
}

html[data-canvas-ready] body[data-mode="canvas"] #text-under { z-index: 1; }
html[data-canvas-ready] body[data-mode="canvas"] #text-over { z-index: 3; }

/* Every text element carries its own paint and position from the scene; the stylesheet
   only says how a run of text behaves once it is placed. */
/* A note is text written onto the paper, not a card sitting on it: no fill, no border, no
   shadow. Stated explicitly rather than left to the default, because the whole point is
   that a committed note looks identical to what the author was typing a moment earlier. */
html[data-canvas-ready] .sx-text {
  position: absolute;
  margin: 0;
  border: 0;
  padding: 0;
  background: transparent;
  box-shadow: none;
  font-family: var(--body);
  line-height: 1.35;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

html[data-canvas-ready] body[data-mode="normal"] .text-plane {
  visibility: hidden;
}

/* Ink is never repainted by the stylesheet: every stroke carries its own colour, width
   and opacity, so what the author drew is what the reader sees. */

html[data-canvas-ready] body[data-mode="normal"] .ink {
  visibility: hidden;
}

html[data-canvas-ready] body[data-mode="normal"] #reset-view {
  display: none;
}

/* In article mode the canvas is hidden, so this section is where the annotations are
   read. In canvas mode the notes are on the page itself, so showing both would be a
   duplicate — and `visibility` is the only way to hide it that leaves the article's
   geometry byte-identical across the mode handoff the probe checks. */
html[data-canvas-ready] body[data-mode="canvas"] #spatial-annotations {
  visibility: hidden;
}

html[data-canvas-ready] body[data-mode="canvas"] #scroll-proxy {
  display: block;
  width: 1px;
  pointer-events: none;
}

html[data-canvas-ready] #mode-toggle {
  display: block;
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 1002;
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--paper);
  box-shadow: 0 2px 12px rgb(42 38 34 / 18%);
  font: 700 12px/1 var(--mono);
  cursor: pointer;
}

html[data-canvas-ready] #mode-toggle:hover {
  filter: brightness(0.92);
}

html[data-canvas-ready] #mode-toggle:focus-visible,
html[data-canvas-ready] #paper :focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

html[data-canvas-ready] .skip-link:focus {
  z-index: 1001;
}

@media (prefers-reduced-motion: reduce) {
  html[data-canvas-ready] .ink path {
    animation: none !important;
    transition: none !important;
  }
}
