/* ---------------------------------------------------------------
   caimanm.com — "worldlines"
   One stylesheet for every page. Edit the tokens in :root to restyle.

   The design is dark-only on purpose: the diagrams are drawn as light
   strokes on an unlit ground, which is what makes the crossings and
   propagators read. A light palette would need different artwork.
   --------------------------------------------------------------- */

:root {
  /* Type */
  --font-body: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont,
    "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas,
    monospace;
  --leading: 1.7;

  /* Layout */
  --measure: 46rem;
  --gap: 3.25rem;

  /* Ground. Neutral greys on purpose — a blue-cast near-black reads as lit
     rather than as ink, and pairing it with blue-cast text makes the glyphs
     halate at these contrast ratios. */
  --bg: #050505;
  --fg: #dcdde0;
  --dim: #83868e;
  --line: #1a1a1c; /* hairlines, gate borders, unlit diagram strokes */
  --line-lit: #3c3d42; /* diagram strokes that need to be seen */
  --surface: #0d0d0e; /* code blocks, hover tint */

  /* UI accents: nav, links, tags, timeline vertices.
     c) near-mono — these sit close to --fg and register as tints.
     See the candidate palettes below to compare against the others. */
  --cyan: #a8c0bd;
  --mag: #c3aab6;
  --amber: #c5b795;

  /* The three anyon species, as drawn in the diagrams. Held apart from the UI
     accents on purpose: the strands are the one place where hue is carrying
     information, so they keep real chroma while the chrome stays quiet. */
  --strand-a: #58b6ae;
  --strand-b: #d0819f;
  --strand-c: #cba766;

  --ease: cubic-bezier(0.35, 0, 0.2, 1);
}

/* --- Candidate palettes (temporary) ---------------------------
   These swap the UI accents only; the strand colours are separate and stay
   put. While choosing an accent set, set the attribute on <html> to see one
   without editing this file:

     document.documentElement.dataset.palette = 'a'   // or 'b', 'neon'
     delete document.documentElement.dataset.palette  // back to c, the default

   Once a set is chosen, fold it into :root above and delete this block. */

html[data-palette="b"] {
  /* heather — cooler, more architectural; pink becomes lilac */
  --cyan: #8ab0bd;
  --mag: #b295b8;
  --amber: #b8a583;
}

html[data-palette="a"] {
  /* dusted — the original three hues, chroma pulled down about a third */
  --cyan: #7ab5b0;
  --mag: #c890ac;
  --amber: #c0a878;
}

html[data-palette="neon"] {
  /* the original, for side-by-side comparison */
  --cyan: #56d8d8;
  --mag: #e07ab0;
  --amber: #d9b26a;
}

/* --- Candidate grounds (temporary) ----------------------------
   Steps from true black to a soft charcoal. Each preset moves --line,
   --line-lit and --surface with --bg, because they sit only one or two steps
   above it — raising the ground alone would swallow every hairline, gate
   border and diagram stroke on the page.

     document.documentElement.dataset.ground = '4'     // 0-5, see below
     delete document.documentElement.dataset.ground    // back to 1, the default

   For an arbitrary shade, set the tokens directly and eyeball the rest:

     document.documentElement.style.setProperty('--bg', '#131316')

   Once a step is chosen, fold its four values into :root and delete this. */

html[data-ground="0"] { /* true black */
  --bg: #000000;
  --surface: #0a0a0a;
  --line: #171719;
  --line-lit: #3a3b40;
}
/* 1 is the current default, defined in :root above. */
html[data-ground="2"] {
  --bg: #0a0a0a;
  --surface: #111112;
  --line: #1e1e20;
  --line-lit: #3f4045;
}
html[data-ground="3"] {
  --bg: #101010;
  --surface: #171718;
  --line: #242426;
  --line-lit: #45464b;
}
html[data-ground="4"] {
  --bg: #161616;
  --surface: #1e1e1f;
  --line: #2b2b2d;
  --line-lit: #4b4c51;
}
html[data-ground="5"] { /* soft charcoal */
  --bg: #1c1c1c;
  --surface: #242425;
  --line: #313133;
  --line-lit: #515257;
}

/* --- Base ----------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  background: var(--bg);
}

body {
  margin: 0;
  padding: 3rem 1.75rem 6rem;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: var(--leading);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* A faint square lattice over the top of the page — a spin model seen from
   above. Masked so it dissolves before it reaches the text.
   Temporarily off — delete this block, or drop the `display: none`, to restore. */
body::before {
  display: none;
  content: "";
  position: fixed;
  inset: 0 0 auto 0;
  height: 60vh;
  pointer-events: none;
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 44px 44px;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(120% 80% at 50% 0%, #000 0%, transparent 70%);
  mask-image: radial-gradient(120% 80% at 50% 0%, #000 0%, transparent 70%);
}

.page {
  position: relative;
  max-width: var(--measure);
  margin: 0 auto;
}

::selection {
  background: var(--fg);
  color: var(--bg);
}

:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 3px;
}

/* --- Nav: a quantum circuit ----------------------------------- */

.circuit {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 4rem;
}

/* The wire runs the full width; gates sit on it with an opaque background,
   so the line appears to pass between them. */
.wire {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--line);
}

.gate {
  position: relative;
  z-index: 1;
  padding: 0.28rem 0.7rem;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-decoration: none;
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}

.gate:hover {
  color: var(--fg);
  border-color: var(--dim);
}

/* Mark the current page's gate with class="here". Distinguished from :hover by
   the filled ground rather than by colour, so it stays legible in mono. The
   fill must be opaque — the wire passes behind it. */
.gate.here {
  color: var(--fg);
  border-color: var(--dim);
  background: var(--surface);
}

/* Measurement symbol terminating the wire. */
.meter {
  position: relative;
  z-index: 1;
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 32px;
  height: 27px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--dim);
}

/* --- Masthead ------------------------------------------------- */

.masthead {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2.5rem;
  margin-bottom: 3.5rem;
}

h1 {
  margin: 0 0 0.5rem;
  font-size: 2.1rem;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.1;
}

.tagline {
  margin: 0;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
}

.epigraph {
  margin: 2.25rem 0 0;
  padding-left: 1.15rem;
  border-left: 1px solid var(--cyan);
  color: var(--dim);
  max-width: 62ch;
}

.epigraph cite {
  display: block;
  margin-top: 0.6rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-style: normal;
  letter-spacing: 0.02em;
}

/* Inner pages: title on the left, page motif on the right. */
.pagehead {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2.5rem;
  margin-bottom: 3rem;
}

.pagehead h1 {
  font-size: 1.6rem;
}

/* --- Section labels: gates on a wire -------------------------- */

h2 {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: var(--gap) 0 1.25rem;
  font-weight: 400;
}

h2::before {
  content: "";
  width: 1.25rem;
  height: 1px;
  background: var(--line);
}

h2::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

h2 span {
  padding: 0.22rem 0.6rem;
  border: 1px solid var(--line);
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  white-space: nowrap;
}

/* A plain subhead, for project titles and sections inside a post. */
h3 {
  margin: 2.25rem 0 0.6rem;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* --- Text ----------------------------------------------------- */

p {
  margin: 0 0 1.15rem;
  max-width: 62ch;
}

.muted {
  color: var(--dim);
}

a {
  color: var(--fg);
  text-decoration: none;
}

/* Inline links in prose. The underline is the whole affordance now that the
   accents are quiet, so it rests one step below the text rather than at
   --line, which is invisible against the ground. */
p a,
.prose a,
li a.link {
  border-bottom: 1px solid var(--dim);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}

p a:hover,
.prose a:hover,
li a.link:hover {
  color: var(--cyan);
  border-bottom-color: var(--cyan);
}

/* --- Lists with tensor nodes ---------------------------------- */

ul.items {
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.items > li > a,
ul.items > li > div {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  padding: 0.4rem 0;
  color: var(--fg);
}

.node {
  flex: none;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.85rem;
  transition: color 0.18s var(--ease);
}

ul.items > li > a:hover {
  color: var(--cyan);
}

ul.items > li > a:hover .node {
  color: var(--mag);
}

.desc {
  color: var(--dim);
  font-size: 0.88rem;
}

.desc::before {
  content: "— ";
}

/* --- Writing index: posts as insertions on a worldline -------- */

/* A single vertical wire runs down the list; each post is a vertex on it. */
ul.timeline {
  position: relative;
  margin: 0;
  padding: 0 0 0 1.9rem;
  list-style: none;
}

ul.timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 0.55rem;
  bottom: 0.55rem;
  width: 1px;
  background: var(--line);
}

ul.timeline > li {
  position: relative;
  --vertex: var(--cyan);
}

/* Problem rows carry a status class; writing rows don't and stay cyan. */
ul.timeline > li.open { --vertex: var(--amber); }
ul.timeline > li.stuck { --vertex: var(--mag); }
ul.timeline > li.solved { --vertex: var(--cyan); }

/* The vertex itself. */
ul.timeline > li::before {
  content: "";
  position: absolute;
  left: -1.9rem;
  top: 1.05rem;
  width: 11px;
  height: 11px;
  margin-left: 0;
  border: 1px solid var(--dim);
  border-radius: 50%;
  background: var(--bg);
  transition: border-color 0.18s var(--ease), background-color 0.18s var(--ease);
}

/* A status'd row shows its color at rest, too. */
ul.timeline > li.open::before,
ul.timeline > li.stuck::before,
ul.timeline > li.solved::before {
  border-color: var(--vertex);
}

ul.timeline > li:hover::before {
  border-color: var(--vertex);
  background: var(--vertex);
}

ul.timeline > li > a {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.55rem 0;
}

ul.timeline > li > a:hover {
  color: var(--vertex);
}

.date {
  flex: none;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
}

/* --- Problems -------------------------------------------------- */

/* Status tag: the nav gate's box, one size down. A status is a label on the
   problem the way a gate is a label on the wire. */
.tag {
  padding: 0.16rem 0.5rem;
  border: 1px solid var(--line);
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  white-space: nowrap;
}

/* The three anyon colors, reused: still thinking / blocked / done. */
.tag.open { color: var(--amber); }
.tag.stuck { color: var(--mag); }
.tag.solved { color: var(--cyan); }

/* Tag + date, pushed to the right of a timeline row. */
.pmeta {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.65rem;
}

/* The status header on a problem's own page. */
.problem-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  margin: -0.1rem 0 2.5rem;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.68rem;
}

/* --- Diagrams -------------------------------------------------- */

.motif {
  width: 100%;
  max-width: 260px;
  height: auto;
  overflow: visible;
}

.strand {
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
}

.s-a { stroke: var(--strand-a); }
.s-b { stroke: var(--strand-b); }
.s-c { stroke: var(--strand-c); }

/* An over-strand is redrawn on a background-colored halo, which is what
   punches the gap that makes a crossing read as "over". */
.halo {
  fill: none;
  stroke: var(--bg);
  stroke-width: 6;
}

/* Unlit structural strokes: bonds, legs, brane edges. */
.wireline {
  fill: none;
  stroke: var(--line-lit);
  stroke-width: 1.3;
  stroke-linecap: round;
}

@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fade { to { opacity: 1; } }

.strand.full {
  stroke-dasharray: 700;
  stroke-dashoffset: 700;
  animation: draw 1.9s var(--ease) forwards;
}

.strand.full.d2 { animation-delay: 0.12s; }
.strand.full.d3 { animation-delay: 0.24s; }

.cross {
  opacity: 0;
  animation: fade 0.45s ease 1.45s forwards;
}

.anyon {
  opacity: 0;
  animation: fade 0.6s ease 1.7s forwards;
}

/* Motifs on the inner pages draw in more quickly and all at once. */
.motif .quick {
  opacity: 0;
  animation: fade 0.7s ease 0.15s forwards;
}

/* --- Post body ------------------------------------------------- */

.post .byline {
  display: block;
  margin: -0.15rem 0 2.5rem;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.72rem;
}

.post blockquote {
  margin: 1.75rem 0;
  padding-left: 1.15rem;
  border-left: 1px solid var(--cyan);
  color: var(--dim);
  max-width: 62ch;
}

.post code {
  font-family: var(--mono);
  font-size: 0.85em;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 0.08em 0.35em;
}

.post pre {
  overflow-x: auto;
  max-width: 62ch;
  padding: 1rem 1.15rem;
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 0.85rem;
  line-height: 1.6;
}

.post pre code {
  background: none;
  border: 0;
  padding: 0;
}

.post img {
  max-width: 100%;
  height: auto;
}

/* --- Math ------------------------------------------------------ */

/* KaTeX brings its own fonts and metrics; these rules only fit it to the
   column. It inherits color from the page, so it needs no palette of its
   own. Loaded from a CDN — see /assets/math.js. */

.katex {
  /* KaTeX's serif runs small next to Inter at the same nominal size. */
  font-size: 1.06em;
}

/* A long equation scrolls inside itself rather than widening the page. */
.katex-display {
  margin: 1.75rem 0;
  padding: 0.3rem 0;
  overflow-x: auto;
  overflow-y: hidden;
}

/* --- Footer ---------------------------------------------------- */

/* On the home page the footer follows an "elsewhere" section label, which
   already draws the dividing line. */
footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 2rem;
  margin-top: 0.5rem;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.72rem;
}

/* Inner pages have nothing to label, so they carry their own rule instead. */
footer.ruled {
  margin-top: var(--gap);
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}

/* Covers the elsewhere links and the "← problems" back-links, which both sit
   in a --dim block and would otherwise be indistinguishable from plain text. */
footer a {
  color: var(--dim);
  border-bottom: 1px solid var(--line-lit);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}

footer a:hover {
  color: var(--cyan);
  border-bottom-color: var(--cyan);
}

.worldsheet {
  width: 100%;
  max-width: 244px;
  height: auto;
}

.sheet-line {
  fill: none;
  stroke: var(--line-lit);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Diagram plus its caption. */
.motif-fig {
  margin: 0;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
}

.caption {
  max-width: 25ch;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.6rem;
  line-height: 1.5;
  letter-spacing: 0.03em;
  text-align: center;
}

/* --- Small screens --------------------------------------------- */

@media (max-width: 40rem) {
  body {
    padding: 2.25rem 1.25rem 4rem;
  }

  .masthead,
  .pagehead {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .motif {
    max-width: 300px;
  }

  .circuit {
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 3rem;
  }

  /* The wire only makes sense as one straight line; hide it when the gates
     wrap onto two rows. */
  .circuit .wire {
    display: none;
  }

  .meter {
    margin-left: 0;
  }

  footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 1.25rem;
  }
}

/* --- Accessibility ---------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .strand.full {
    stroke-dashoffset: 0;
    animation: none;
  }

  .cross,
  .anyon,
  .motif .quick {
    opacity: 1;
    animation: none;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
  }
}
