/* Shared shell for every page on 10ktrials.com.
 *
 * Split out of index.html when the closed-lines page arrived. Design tokens
 * duplicated across two files are the same drift problem the rest of this repo
 * exists to stop, and a hex copied by hand is what goes stale first. Rules that
 * belong to one page stay inline in the page that owns them.
 */
/* ------------------------------------------------------------------
   The parent brand cannot borrow either product's look. Blackjack
   Ledger is felt green and Didot; The Algomist is gold on near-black
   with Cinzel. Wearing one would imply the company IS that product and
   make the other a guest on its own page.

   So the company gets the thing both products are actually for:
   measurement. Ink ground, graph paper, instrument type, and a signal
   blue that belongs to neither. Each product card then carries its own
   real palette, which is what makes them read as two companies-worth of
   work rather than two links.
   ------------------------------------------------------------------ */
:root {
  color-scheme: dark;
  --ink: #0b0f14;
  --ink-2: #10161e;
  --rule: rgba(198, 218, 236, .13);
  --paper: #eef4f8;
  --muted: #8ba0b4;
  --signal: #63b3d8;      /* the company's own accent */
  --felt: #0f4d3f;        /* Blackjack Ledger */
  --felt-ink: #f4e9cf;
  --card-red: #e2553e;
  --gold: #c9a84c;        /* The Algomist */
  --gold-soft: #e8c97a;
  --up: #22c55e;
  --down: #ef4444;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; min-height: 100svh;
  background: var(--ink);
  color: var(--paper);
  font: 400 16px/1.65 "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
/* Graph paper. Two grids — a fine one and a heavier decade line every
   fifth — because that is what measurement paper actually looks like,
   and a single uniform grid reads as decoration instead. */
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    linear-gradient(rgba(198,218,236,.045) 1px, transparent 1px) 0 0 / 100% 22px,
    linear-gradient(90deg, rgba(198,218,236,.045) 1px, transparent 1px) 0 0 / 22px 100%,
    linear-gradient(rgba(198,218,236,.05) 1px, transparent 1px) 0 0 / 100% 110px,
    linear-gradient(90deg, rgba(198,218,236,.05) 1px, transparent 1px) 0 0 / 110px 100%;
  mask-image: radial-gradient(120% 80% at 50% 0%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 80% at 50% 0%, #000 20%, transparent 78%);
}
/* Film grain. An SVG turbulence tile rather than an image: no request,
   no data URI in a CSP-sensitive place, and it scales at any DPI. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.055'/%3E%3C/svg%3E");
}
.glow {
  position: fixed; z-index: 0; pointer-events: none;
  top: -32vh; left: 50%; width: min(1100px, 130vw); aspect-ratio: 1; transform: translateX(-50%);
  background: radial-gradient(circle, rgba(99,179,216,.13), rgba(99,179,216,.04) 42%, transparent 66%);
}
.shell { position: relative; z-index: 1; width: min(980px, 100%); margin: 0 auto; padding: 34px 22px 60px; }

/* ---- masthead ---- */
header.top { display: flex; align-items: center; gap: 12px; padding-bottom: 30px; }
.mark { width: 40px; height: 40px; flex: 0 0 auto; }
.wordmark { display: grid; gap: 1px; }
.wordmark b {
  font: 600 1.12rem/1 "Fraunces", Georgia, serif;
  font-variation-settings: "opsz" 40; letter-spacing: -.005em;
}
.wordmark span {
  color: var(--muted); font-family: "IBM Plex Mono", monospace;
  font-size: .58rem; letter-spacing: .19em; text-transform: uppercase;
}

/* Site nav. Lives in the shell so a page cannot quietly disappear from it —
   the tab set is one list, in one file, on every page. */
.nav { display: flex; gap: 18px; margin-left: auto; align-items: center; }
.nav a {
  color: var(--muted); text-decoration: none; white-space: nowrap;
  font-family: "IBM Plex Mono", monospace; font-size: .62rem;
  letter-spacing: .15em; text-transform: uppercase;
  padding-bottom: 3px; border-bottom: 1px solid transparent;
}
.nav a:hover { color: var(--paper); }
.nav a[aria-current="page"] { color: var(--paper); border-bottom-color: var(--signal); }
/* A tab for the section you are browsing, but not the page you are on. Brighter
   than the rest so you can see where you are, no underline so it does not claim
   to be the current page — the underline is what makes a tab look unclickable. */
.nav a.section { color: var(--paper); }
@media (max-width: 420px) { .nav { gap: 13px; } .nav a { font-size: .56rem; letter-spacing: .1em; } }

/* One orchestrated entrance. Everything rises a little and settles, in
   reading order, so the page assembles itself rather than appearing. */
.rise { opacity: 0; transform: translateY(14px); animation: rise .8s cubic-bezier(.22,.7,.3,1) forwards; }
/* The default for a .rise that was given no explicit slot. Same specificity as
   the numbered classes below and written before them, so an explicit slot always
   wins. As a bare :nth-of-type(1) it OUTRANKED .d1..d5 — a class plus a
   pseudo-class beats a class — so the first element of every tag type snapped to
   .05s whatever slot it was given, which raised the graveyard's index before the
   glossary sitting above it. */
.rise:nth-of-type(1) { animation-delay: .05s; }
.rise.d1 { animation-delay: .10s; } .rise.d2 { animation-delay: .20s; } .rise.d3 { animation-delay: .32s; }
.rise.d4 { animation-delay: .46s; } .rise.d5 { animation-delay: .60s; }
.rise.d6 { animation-delay: .74s; }
@keyframes rise { to { opacity: 1; transform: none; } }
html.js .reveal > * { opacity: 0; transform: translateY(16px); transition: opacity .7s ease, transform .7s cubic-bezier(.22,.7,.3,1); }
html.js .reveal.seen > * { opacity: 1; transform: none; }
html.js .reveal.seen > :nth-child(2) { transition-delay: .11s; }
html.js .reveal.seen > :nth-child(3) { transition-delay: .22s; }

footer { margin-top: 44px; padding-top: 22px; border-top: 1px solid var(--rule); color: var(--muted); font-size: .78rem; display: grid; gap: 5px; }
footer a { color: var(--paper); text-underline-offset: 3px; }

/* A route from a credibility page to the thing it supports. One contextual line,
   never a banner: these pages earn attention by not selling, and the link is
   only honest if it follows from what the page just argued. */
.related { margin: 40px 0 0; padding-top: 22px; border-top: 1px solid var(--rule); }
.related p { margin: 0 0 14px; max-width: 66ch; color: var(--muted); font-size: .88rem; line-height: 1.6; }
.related p b { color: var(--paper); font-weight: 500; }
.related-links { display: flex; flex-wrap: wrap; gap: 10px; }
.related-links a {
  display: inline-flex; align-items: baseline; gap: 9px;
  padding: 9px 15px; border: 1px solid var(--rule); border-radius: 999px;
  background: var(--ink-2); color: var(--paper); text-decoration: none;
  font-size: .86rem; transition: border-color .18s ease, transform .18s ease;
}
.related-links a:hover, .related-links a:focus-visible {
  border-color: var(--signal); transform: translateY(-1px);
}
.related-links span {
  color: var(--muted); font-family: "IBM Plex Mono", monospace;
  font-size: .62rem; letter-spacing: .1em; text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) { .related-links a { transition: none; } }

/* The shell's own reduced-motion rules travel with the shell; each page
   keeps a block for the animations it alone owns. */
@media (prefers-reduced-motion: reduce) {
  .rise { animation: none; opacity: 1; transform: none; }
  html.js .reveal > * { opacity: 1; transform: none; transition: none; }
}
