/* andrewsilvestri.com
 *
 * Dark ground, luminous data, quiet type. The rule throughout: the page is
 * the frame and the work is the picture, so nothing here competes with a
 * figure or a map. One accent colour, hairline rules, and a lot of air.
 *
 * Light mode is a deliberate second-class citizen — it exists so the site is
 * readable for anyone who insists on it, and it is warm paper rather than a
 * white box.
 */

:root {
  --bg:      #070a12;
  --bg-lift: #0c1020;
  --card:    #10152a;
  --ink:     #e3e6f2;
  --dim:     #8b93b0;
  --faint:   #1a2038;
  --rule:    #232a45;
  --acc:     #8b7ff2;   /* violet — links, emphasis */
  --acc-dim: #5a4fb0;
  --acc-ink: #f2f0ff;   /* text on a violet ground */
  --moss:    #4f9d84;   /* dark green, second data accent */
  --cool:    #5aa8d8;   /* blue, for data */
  --shadow:  0 18px 50px rgba(2, 4, 12, .62);
  /* Three widths, not one. Prose stays at a readable measure because line
     length is a legibility constraint, not a stylistic one — past about 80
     characters the eye loses the return sweep. Everything that is not prose
     has no such limit, so figures, tables and the hero break out of the text
     column and use the screen. */
  --text:    min(72ch, 100%);
  --wide:    min(1140px, 100%);
  --shell:   1440px;
  --serif:   "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
             "Times New Roman", serif;
  --sans:    ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono:    ui-monospace, "SF Mono", "Cascadia Mono", Consolas,
             "Liberation Mono", monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg:      #f4f5fa;
    --bg-lift: #ecedf6;
    --card:    #ffffff;
    --ink:     #161a26;
    --dim:     #5c6480;
    --faint:   #e0e3ef;
    --rule:    #d2d7e6;
    --acc:     #4c3fb5;
    --acc-dim: #7a6fd8;
    --acc-ink: #ffffff;
    --cool:    #2a6a96;
    --moss:    #2f6f5c;
    --shadow:  0 14px 34px rgba(30, 34, 60, .12);
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 17.5px/1.72 var(--serif);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* a barely-there wash so the black is not a void */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(1100px 640px at 50% -8%,
                    rgba(110, 128, 240, .075), transparent 70%),
    radial-gradient(900px 520px at 86% 6%,
                    rgba(79, 157, 132, .05), transparent 68%);
}
@media (prefers-color-scheme: light) { body::before { opacity: .5; } }

main, nav.top { position: relative; z-index: 1; }

/* ---------------------------------------------------------------- nav --- */
nav.top {
  max-width: var(--shell);
  margin: 0 auto;
  /* 34px less the 8px each item carries as padding, so the first item's text
     lines up with the page text. Never set margin-left here: it overrides the
     auto margins that centre the shell and drags the whole page to the left. */
  padding: 26px 34px 0 26px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font: 13px/1 var(--sans);
  letter-spacing: .02em;
  position: relative;
  z-index: 50;
}
/* Every item carries the same padding, so the highlight sits square on its own
   text and nothing shifts when an item becomes current. */
nav.top a {
  color: var(--dim);
  text-decoration: none;
  padding: 5px 10px;
  margin: 0;
  border-bottom: 0;
  white-space: nowrap;
  transition: color .18s, background .18s;
}
nav.top a:hover { color: var(--ink); }
nav.top a.on,
nav.top a[aria-current="page"] {
  color: var(--acc-ink);
  background: var(--acc);
  font-weight: 600;
  border-radius: 3px;
  text-decoration: none;
}
/* the dropdowns are their own inline-block, so they need the same rhythm */
nav.top .dd { margin: 0; }
.ddmenu a.on { color: var(--acc-ink); background: var(--acc); }


/* dropdown */
.dd { position: relative; display: inline-block; margin-right: 22px; }
.dd > .ddbtn { margin-right: 0; cursor: pointer; }
.caret { font-size: 9px; opacity: .65; }
.ddmenu {
  display: none;
  position: absolute;
  left: -16px;
  top: 100%;
  padding: 9px 0;
  min-width: 268px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 2px;
  box-shadow: var(--shadow);
}
.dd:hover > .ddmenu, .dd:focus-within > .ddmenu { display: block; }
.ddmenu a {
  display: block;
  margin: 0;
  padding: 8px 18px;
  color: var(--dim);
  font-size: 13.5px;
  white-space: nowrap;
  border: 0;
}
.ddmenu a:hover { color: var(--acc); background: var(--bg-lift); }

/* --------------------------------------------------------------- text --- */
/* A content grid with three named tracks. Children default to the text
   column; anything tagged .wide or .full breaks out sideways without needing
   to escape the flow. */
main {
  display: grid;
  margin: 0 auto;
  padding: 40px 0 120px;
  max-width: var(--shell);
  grid-template-columns:
    [full-start] minmax(34px, 1fr)
    [wide-start] minmax(0, calc((var(--wide) - var(--text)) / 2))
    [text-start] minmax(0, var(--text)) [text-end]
    minmax(0, calc((var(--wide) - var(--text)) / 2)) [wide-end]
    minmax(34px, 1fr) [full-end];
}
main > * { grid-column: text; min-width: 0; }
main > .wide, main > table, main > img.fig, main > #hero,
main > .cardgrid { grid-column: wide; }
main > .full { grid-column: full; }

h1 {
  font-size: 34px;
  font-weight: 500;
  letter-spacing: -.015em;
  line-height: 1.16;
  margin: 0 0 10px;
}
h2 {
  font-size: 13px;
  font-family: var(--sans);
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--dim);
  margin: 58px 0 16px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--rule);
}
h3 {
  font-size: 19px;
  font-weight: 500;
  margin: 26px 0 5px;
  letter-spacing: -.005em;
}

p { margin: 15px 0; }
.dim { color: var(--dim); }
.small { font-size: 15px; color: var(--dim); }

a {
  color: var(--acc);
  text-decoration: none;
  border-bottom: 1px solid var(--faint);
}
a:hover { border-bottom-color: var(--acc); }

hr { border: 0; border-top: 1px solid var(--rule); margin: 52px 0; }

ul { padding-left: 22px; }
li { margin: 8px 0; }

code {
  font: 14px var(--mono);
  background: var(--bg-lift);
  border: 1px solid var(--faint);
  padding: 2px 7px;
  border-radius: 2px;
  color: var(--cool);
}

/* -------------------------------------------------------------- table --- */
table {
  width: 100%;
  border-collapse: collapse;
  font: 14.5px/1.5 var(--sans);
  margin: 20px 0;
  font-variant-numeric: tabular-nums;
}
th, td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--faint);
  vertical-align: top;
}
th {
  color: var(--dim);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .1em;
  border-bottom-color: var(--rule);
}
tr:hover td { background: var(--bg-lift); }
/* Numeric cells, right-aligned so digits line up against each other. The
   class was in use on several pages and in the house conventions before it
   had a rule here, which is why those columns were left-aligned in a
   stylesheet that already asks for tabular figures. */
th.n, td.n { text-align: right; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------- figs --- */
img.fig {
  width: 100%;
  max-width: 100%;
  border: 1px solid var(--rule);
  border-radius: 2px;
  margin: 18px 0 8px;
  background: var(--card);
  display: block;
}

/* --------------------------------------------------------------- grid --- */
/* Cards sit two-up on a wide screen. Each one's prose therefore stays short
   even though the block is wider than the text column — which is the whole
   point of widening: more room without longer lines. */
.cardgrid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  margin: 22px 0;
}
.cardgrid .card { margin: 0; height: 100%; }

/* -------------------------------------------------------------- cards --- */
.card {
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 26px 28px;
  margin: 22px 0;
  background: linear-gradient(180deg, var(--card), var(--bg-lift));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .03);
  transition: border-color .2s;
}
.card:hover { border-color: var(--acc-dim); }
.card .tag {
  font: 10.5px var(--sans);
  color: var(--acc);
  text-transform: uppercase;
  letter-spacing: .16em;
  margin-bottom: 4px;
}
.card h3 { margin-top: 4px; }
.card h3 a { border: 0; color: var(--ink); }
.card h3 a:hover { color: var(--acc); }

/* --------------------------------------------------------------- btns --- */
.btn {
  display: inline-block;
  background: var(--acc);
  color: var(--acc-ink);
  padding: 10px 20px;
  border-radius: 2px;
  font: 600 14px var(--sans);
  letter-spacing: .01em;
  margin: 12px 10px 0 0;
  border: 1px solid var(--acc);
  transition: filter .18s;
}
.btn:hover { background: var(--acc-dim); border-color: var(--acc-dim);
             color: var(--acc-ink); }
.btn.ghost {
  background: transparent;
  color: var(--dim);
  border-color: var(--rule);
}
.btn.ghost:hover { color: var(--ink); border-color: var(--dim); }

/* --------------------------------------------------------------- hero --- */
#hero {
  position: relative;
  width: 100%;
  height: clamp(320px, 46vh, 560px);
  /* The h1 sits directly under the globe and needs air, or the name reads
     as a caption on the image rather than the top of the page. */
  margin: 18px 0 30px;
  border-radius: 2px;
  overflow: hidden;
  background: radial-gradient(circle at 50% 46%, #0a1024 0%, #05070f 72%);
  border: 1px solid var(--rule);
}
.hero-layer { position: absolute; inset: 0; display: block; }
/* the WebGL canvas fades in over the 2D pair, then they are stopped */
.hero-gl { z-index: 2; }
.hero-cap {
  font: 11.5px var(--sans);
  color: var(--dim);
  letter-spacing: .05em;
  margin: 10px 0 0;
}
@media (max-width: 620px) { #hero { height: 300px; } }

/* ------------------------------------------------------------- footer --- */
/* ----------------------------------------------------------- citations --- */
/* Superscript markers in the prose, and the list they point at. Clicking a
   marker jumps to the entry and highlights it; clicking back returns. */
sup.cite { font-size: 10.5px; line-height: 0; vertical-align: super; }
sup.cite a {
  color: var(--acc);
  border: 0;
  padding: 0 1px;
  font-family: var(--sans);
  font-variant-numeric: tabular-nums;
}
sup.cite a:hover { text-decoration: underline; }
ol.refs {
  counter-reset: ref;
  list-style: none;
  padding: 0;
  margin: 14px 0 0;
  font: 14px/1.6 var(--sans);
  color: var(--dim);
}
ol.refs li {
  counter-increment: ref;
  position: relative;
  padding: 9px 0 9px 34px;
  border-bottom: 1px solid var(--faint);
  scroll-margin-top: 24px;
}
ol.refs li::before {
  content: counter(ref);
  position: absolute;
  left: 0;
  top: 9px;
  width: 24px;
  text-align: right;
  color: var(--acc);
  font-variant-numeric: tabular-nums;
}
ol.refs li:target { background: var(--bg-lift); }
ol.refs .src { color: var(--ink); }
ol.refs .what { display: block; margin-top: 2px; font-size: 13px; }

footer {
  margin-top: 74px;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
  font: 13.5px var(--sans);
  color: var(--dim);
}

.grid { display: grid; grid-template-columns: 1fr; gap: 26px; }

/* ------------------------------------------------------------- mobile --- */
@media (max-width: 760px) {
  main { grid-template-columns: [full-start wide-start text-start] 1fr
                                [text-end wide-end full-end];
         padding-left: 20px; padding-right: 20px;
         max-width: 100%; }
  .cardgrid { grid-template-columns: 1fr; }
  /* Nothing may be wider than the screen. One over-wide child gives the
     whole document a horizontal scroll, and every block then reads as
     though it has been cut off down the right edge. */
  main > * { max-width: 100%; min-width: 0; }
  #hero { max-width: 100%; }
  /* A table of numbers cannot be made narrow without lying about it, so it
     scrolls inside its own box rather than stretching the page. */
  table { display: block; width: 100%; overflow-x: auto; }
  pre, code { overflow-x: auto; word-break: break-word; }
}
@media (max-width: 620px) {
  body { font-size: 16.5px; }
  main { padding-top: 30px; padding-bottom: 90px; }
  nav.top { padding: 20px 20px 0; }
  h1 { font-size: 27px; }
  /* On a phone the dropdowns used to be forced open — position:static plus
     display:block — so every page began with the whole site map spilled down
     the screen and the content pushed below the fold. They stay closed here
     and open on tap: an anchor takes focus when touched, which is the same
     mechanism the desktop hover uses, so no script is needed. */
  .ddmenu {
    position: static;
    display: none;
    border: 0;
    box-shadow: none;
    padding: 2px 0 6px;
    min-width: 0;
    background: transparent;
  }
  .dd:focus-within > .ddmenu { display: block; }
  .ddmenu a { padding: 9px 0 9px 18px; font-size: 15px; }
  .dd { display: block; margin: 2px 0; width: 100%; }
  /* One item per row. The bar is a wrapping flex row, so the groups — which
     are block-level — took a line each while the plain links flowed
     together and shared one: "Pipeline liquid holdup  Climate cost
     calculator" sat side by side looking like a single stuck item. A column
     gives every item the same shape. */
  nav.top { gap: 0; padding: 16px 20px 6px;
            flex-direction: column; align-items: stretch; }
  nav.top > a, nav.top > .dd { width: 100%; }
  nav.top a { padding: 9px 4px; font-size: 15px; display: block; }
  /* The current-page highlight hugs its own text rather than running the
     width of the bar, which in a column layout stretch would otherwise do. */
  nav.top a.on { align-self: flex-start; width: auto; }
  .dd > .ddbtn { display: block; }
  .caret { float: right; font-size: 11px; opacity: .8; }
  .card { padding: 20px; }
}
