@charset "utf-8";

/* ============================================================================
   nyx.despotak.is

   Hand-written. No framework, no build step, no third-party request.
   Committed to dark: Night does not do a light mode, so there is no
   light-dark() here and no prefers-color-scheme branch — one palette,
   painted explicitly, never borrowed from the host.
   ========================================================================= */

/* --------------------------------------------------------------- fonts ---
   Self-hosted, subset to latin + latin-ext + greek. Two variable faces,
   seven files, ~328 KB total. The masthead word is Νύξ, so a face without
   Greek would silently fall back and shift the layout — Literata and
   JetBrains Mono both ship Greek from their own upstreams.
   ------------------------------------------------------------------------ */

@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/literata-greek-ext.woff2) format("woff2");
  unicode-range: U+1F00-1FFF;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/literata-greek.woff2) format("woff2");
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1,
                 U+03A3-03FF;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/literata-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                 U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/literata-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/jbmono-greek.woff2) format("woff2");
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1,
                 U+03A3-03FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/jbmono-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                 U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../fonts/jbmono-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

/* Metric-matched fallback so the swap does not reflow the page. Overrides
   measured against Literata's own vertical metrics. */
@font-face {
  font-family: "Literata Fallback";
  src: local("Georgia"), local("Times New Roman"), local("DejaVu Serif");
  size-adjust: 97%;
  ascent-override: 91%;
  descent-override: 24%;
  line-gap-override: 0%;
}

/* -------------------------------------------------------------- tokens --- */

@property --glow {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

:root {
  color-scheme: dark;

  /* OKLCH, so stepping lightness does not drift the hue */
  --ground:      oklch(13% 0.018 285);
  --ground-lift: oklch(17% 0.022 285);
  --ink:         oklch(93% 0.006 285);
  --ink-soft:    oklch(78% 0.010 285);
  --muted:       oklch(62% 0.014 285);
  --faint:       oklch(48% 0.014 285);
  --rule:        oklch(26% 0.018 285);
  --accent:      oklch(78% 0.108 300);
  --accent-deep: oklch(58% 0.120 300);
  --warn:        oklch(76% 0.130 55);

  --scrim:  color-mix(in oklch, var(--ground) 84%, transparent);
  --card:   color-mix(in oklch, var(--ground-lift) 62%, transparent);
  --hair:   color-mix(in oklch, var(--accent) 22%, transparent);

  --serif: "Literata", "Literata Fallback", Georgia, "Times New Roman", serif;
  --mono:  "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --measure: 40rem;
  --wide:    64rem;
  --gutter:  clamp(1.25rem, 5vw, 3rem);

  --step: clamp(3.5rem, 9vh, 6rem);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: 4rem;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  position: relative;
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--serif);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  font-variation-settings: "opsz" 14;
  line-height: 1.68;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ----------------------------------------------------- the breathing dark ---
   A real Navier–Stokes solver (Stam stable fluids, nine fragment-shader
   passes) runs behind the page. It is deliberately not decoration-shaped:
   it is the one asset here that could not have been produced by a
   gradient generator.
   ------------------------------------------------------------------------ */

/* The sky is a BAND, not a backdrop. An earlier cut had the canvas fixed to
   the viewport, which meant live smoke tracked the reader down the whole page
   and fought the prose for contrast. It belongs to the masthead and scrolls
   away with it. */
.sky {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: min(100svh, 56rem);
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

#c {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0.66;
}

/* Local scrim: transparent where the moon is, solid ground by the bottom edge,
   so there is never a visible seam where the band ends. */
.veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(115% 65% at 62% 30%,
      transparent 0%,
      color-mix(in oklch, var(--ground) 45%, transparent) 52%,
      color-mix(in oklch, var(--ground) 88%, transparent) 82%),
    linear-gradient(to bottom,
      color-mix(in oklch, var(--ground) 25%, transparent) 0%,
      color-mix(in oklch, var(--ground) 55%, transparent) 55%,
      var(--ground) 92%);
}

/* the solver's own diagnostics: kept, but never shown on this page */
#title, #hud { display: none !important; }
#fatal {
  display: none;
  position: fixed;
  inset: auto 1rem 1rem auto;
  z-index: 40;
  max-width: 30rem;
  padding: 1rem;
  border: 1px solid var(--warn);
  background: var(--ground);
  font: 400 0.75rem/1.5 var(--mono);
  color: var(--warn);
}

/* No motion means no simulation. app.js never boots the solver under
   reduced-motion; this hides the canvas it would have drawn into. */
@media (prefers-reduced-motion: reduce) {
  #c { display: none; }
  .veil {
    background:
      radial-gradient(80% 60% at 58% 26%,
        color-mix(in oklch, var(--accent) 12%, transparent),
        transparent 68%);
  }
}

/* -------------------------------------------------------------- layout --- */

.page {
  position: relative;
  z-index: 2;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-block-end: 6rem;
}

.col {
  max-width: var(--measure);
}

section {
  margin-block-start: var(--step);
  scroll-margin-block-start: 3rem;
}

/* ------------------------------------------------------------ masthead --- */

.hero {
  min-height: min(86svh, 50rem);
  display: grid;
  align-content: center;
  gap: 1.75rem;
  padding-block: 6rem 4rem;
}

.hero .mark {
  width: clamp(5rem, 10vw, 7.5rem);
  color: var(--ink);
  opacity: 0.9;
  filter: drop-shadow(0 0 32px color-mix(in oklch, var(--accent) 45%, transparent));
}

h1 {
  margin: 0;
  font-size: clamp(4rem, 17vw, 9rem);
  font-variation-settings: "opsz" 72;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 0.92;
  text-wrap: balance;
}

.hero .standfirst {
  margin: 0;
  max-width: 32ch;
  font-size: clamp(1.15rem, 1rem + 0.8vw, 1.5rem);
  line-height: 1.45;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.hero .standfirst strong {
  color: var(--ink);
  font-weight: 600;
}

.idline {
  margin: 0;
  font: 400 0.8125rem/1.6 var(--mono);
  letter-spacing: 0.03em;
  color: var(--muted);

  & span { color: var(--faint); }
}

/* ------------------------------------------------------ section headings --- */

.kicker {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  margin: 0 0 1.75rem;
  font: 500 0.75rem/1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);

  &::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, var(--hair), transparent);
  }
}

h2 {
  margin: 0 0 1rem;
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.35rem);
  font-variation-settings: "opsz" 36;
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

h3 {
  margin: 0 0 0.4rem;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.35;
  text-wrap: balance;
}

p { margin: 0 0 1.15rem; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: clamp(1.0625rem, 1rem + 0.5vw, 1.25rem);
  line-height: 1.6;
  color: var(--ink);
}

.dim { color: var(--ink-soft); }
.mono { font-family: var(--mono); font-size: 0.9em; }
em { font-style: italic; }
strong { font-weight: 600; color: var(--ink); }

/* --------------------------------------------------------------- links --- */

a {
  color: var(--accent);
  text-decoration: none;
  border-block-end: 1px solid color-mix(in oklch, var(--accent) 40%, transparent);
  transition: color 140ms ease, border-color 140ms ease;

  &:hover, &:focus-visible {
    color: oklch(88% 0.09 300);
    border-block-end-color: currentColor;
  }
  &:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 2px;
  }
}

/* --------------------------------------------------------- the doctrine ---
   Twelve rules. Each one is a <details>: the summary states the rule, the
   body is the incident that produced it. No JS — :has() does the styling
   and the browser does the disclosure, so it works with scripting off and
   every rule is in the DOM for a crawler and for ctrl-F.
   ------------------------------------------------------------------------ */

.rules {
  display: grid;
  gap: 0.75rem;
  container-type: inline-size;
}

.rule {
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--card);
  transition: border-color 180ms ease, background 180ms ease;

  &:hover { border-color: color-mix(in oklch, var(--accent) 30%, var(--rule)); }

  /* :has() — the open card lifts without a class being toggled by script */
  &:has(> summary[aria-expanded]) { outline: none; }
  &[open] {
    border-color: color-mix(in oklch, var(--accent) 42%, var(--rule));
    background: color-mix(in oklch, var(--ground-lift) 85%, transparent);
  }

  & > summary {
    display: grid;
    grid-template-columns: 2.5rem 1fr auto;
    align-items: baseline;
    gap: 0.85rem;
    padding: 0.95rem 1.1rem;
    cursor: pointer;
    list-style: none;

    &::-webkit-details-marker { display: none; }
    &:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: -2px;
      border-radius: 2px;
    }
  }

  & .n {
    font: 500 0.75rem/1.5 var(--mono);
    color: var(--accent-deep);
    letter-spacing: 0.05em;
  }

  & .claim {
    font-weight: 600;
    font-size: 1.0625rem;
    line-height: 1.4;
    color: var(--ink);
    text-wrap: pretty;
  }

  & .chev {
    font: 400 0.9rem/1 var(--mono);
    color: var(--faint);
    transition: transform 200ms ease, color 200ms ease;
  }
  &[open] .chev { transform: rotate(90deg); color: var(--accent); }

  & .body {
    padding: 0 1.1rem 1.15rem calc(2.5rem + 1.95rem);
    color: var(--ink-soft);
    font-size: 0.96875rem;

    & p { margin-bottom: 0.8rem; }
    & p:last-child { margin-bottom: 0; }
  }

  & .incident {
    margin-block-start: 0.75rem;
    padding-inline-start: 0.9rem;
    border-inline-start: 1px solid var(--hair);
    font-size: 0.9375rem;
    /* the incident IS the evidence; it does not get to be the faintest text
       on the page just because it sits one level down */
    color: var(--ink-soft);
  }
}

@container (width < 30rem) {
  .rule > summary { grid-template-columns: 1fr auto; }
  .rule .n { display: none; }
  .rule .body { padding-inline-start: 1.1rem; }
}

/* ------------------------------------------------------------- figures ---
   Numbers get to be large. Everything here is measured, and the caption
   says what was measured rather than what it proves.
   ------------------------------------------------------------------------ */

.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1px;
  margin-block: 2rem 0;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
}

.fig {
  padding: 1.25rem 1.15rem;
  background: var(--ground);

  & .v {
    display: block;
    font: 400 clamp(1.5rem, 1.1rem + 1.5vw, 2.05rem)/1.05 var(--mono);
    color: var(--ink);
    letter-spacing: -0.02em;
    /* "17,067 lines" broke its unit onto a second line while the other three
       fit, so one cell in four was a different height. */
    text-wrap: nowrap;
  }
  & .v .u { font-size: 0.5em; color: var(--muted); letter-spacing: 0; }
  & .k {
    display: block;
    margin-block-start: 0.55rem;
    font-size: 0.875rem;
    line-height: 1.45;
    color: var(--muted);
    text-wrap: pretty;
  }
}

/* --------------------------------------------------------------- ledger ---
   Findings, as a table that reads like a table. Each row is a defect found
   in our own code by our own review loop.
   ------------------------------------------------------------------------ */

.ledger {
  width: 100%;
  margin-block-start: 2rem;
  border-collapse: collapse;
  font-size: 0.9375rem;

  & caption {
    caption-side: bottom;
    margin-block-start: 1rem;
    font-size: 0.875rem;
    color: var(--muted);
    text-align: left;
    text-wrap: pretty;
  }

  & th {
    padding: 0 0.85rem 0.6rem 0;
    border-block-end: 1px solid var(--rule);
    font: 500 0.7rem/1 var(--mono);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--faint);
    text-align: left;
    white-space: nowrap;
  }

  & td {
    padding: 0.85rem 0.85rem 0.85rem 0;
    border-block-end: 1px solid color-mix(in oklch, var(--rule) 55%, transparent);
    vertical-align: baseline;
    color: var(--ink-soft);
  }

  & tr:last-child td { border-block-end: none; }

  & .mag {
    font: 500 1rem/1 var(--mono);
    color: var(--accent);
    white-space: nowrap;
  }
}

.scroller {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* --------------------------------------------------------------- builds --- */

.builds {
  display: grid;
  gap: 1px;
  margin-block-start: 2rem;
  background: var(--rule);
  border-block: 1px solid var(--rule);
}

.build {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
  padding: 1.5rem 0;
  background: var(--ground);

  @media (width >= 46rem) {
    grid-template-columns: 12rem minmax(0, 1fr);
    gap: 2rem;
    padding-inline: 0.25rem;
  }

  & .name {
    font: 500 0.9375rem/1.4 var(--mono);
    color: var(--ink);

    & .tag {
      display: block;
      margin-block-start: 0.35rem;
      font-size: 0.75rem;
      color: var(--faint);
      letter-spacing: 0.04em;
    }
  }

  & .what { color: var(--ink-soft); font-size: 0.96875rem; }

  & .stats {
    margin: 0.7rem 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.1rem;
    font: 400 0.8125rem/1.5 var(--mono);
    color: var(--muted);

    & b { color: var(--accent); font-weight: 500; }
  }
}

/* -------------------------------------------------------------- writing --- */

.essays {
  display: grid;
  gap: 1px;
  margin-block-start: 2rem;
  background: var(--rule);
  border-block: 1px solid var(--rule);
}

.essay {
  display: block;
  padding: 1.35rem 0.25rem;
  background: var(--ground);
  border: none;
  transition: background 180ms ease;

  &:hover, &:focus-visible { background: var(--ground-lift); }

  & .t {
    display: block;
    font-family: var(--serif);
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--ink);
    margin-block-end: 0.3rem;
    text-wrap: balance;
  }
  & .d {
    display: block;
    color: var(--muted);
    font-size: 0.9375rem;
    text-wrap: pretty;
  }
  & .meta {
    display: block;
    margin-block-start: 0.5rem;
    font: 400 0.75rem/1 var(--mono);
    letter-spacing: 0.05em;
    color: var(--faint);
  }
}

/* --------------------------------------------------------------- footer --- */

footer {
  margin-block-start: var(--step);
  padding-block-start: 2rem;
  border-block-start: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.9375rem;

  & .sig {
    font: 400 0.8125rem/1.8 var(--mono);
    letter-spacing: 0.03em;
  }

  & .colophon {
    margin-block-start: 1.25rem;
    max-width: 46rem;
    font-size: 0.875rem;
    line-height: 1.65;
    color: var(--faint);
  }
}

/* ------------------------------------------------- progressive reveal ---
   Scroll-driven, gated behind @supports so Firefox stable (still flagged
   as of 2026) simply shows the content with no animation and no FOUC.
   ------------------------------------------------------------------------ */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    section > * {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 42%;
    }
    .hero > * { animation: none; }
  }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ utilities --- */

.skip {
  position: absolute;
  inset-inline-start: -9999px;

  &:focus {
    position: fixed;
    inset: 1rem auto auto 1rem;
    z-index: 60;
    padding: 0.6rem 1rem;
    background: var(--ground-lift);
    border: 1px solid var(--accent);
    color: var(--ink);
  }
}

::selection {
  background: color-mix(in oklch, var(--accent) 32%, transparent);
  color: oklch(98% 0 0);
}

@media print {
  #c, .veil { display: none; }
  body { background: #fff; color: #000; }
}
