/* ── luna.golia.jp — research-paper design system ──────────────────────
   A Golia Lab project page, set like a journal article: warm paper ground,
   ink black text, hairline rules, generous measure. The system is the one
   tiktoken.golia.jp and kevy.golia.jp use, taken verbatim so the three lab
   pages read as one publication; what differs is what luna has to show — a
   dialect matrix and a JIT pipeline rather than a token strip or a live
   terminal.

   GOLIA blue is structural, not decorative: section numbers, key figures,
   and the single link state.

   The masthead, frontmatter, tables, code, cards, footer and docs layers
   below are copied from kevy.golia.jp without modification. If you change
   one here, change it there and in tiktoken too — the family resemblance
   is the thing that breaks first. */


:root {
  /* paper & ink */
  --paper: #fcfbf8;
  --paper-raised: #ffffff;
  --paper-sunk: #f5f3ee;
  --ink: #17161a;
  --ink-soft: #4a4852;
  --ink-faint: #7d7a85;
  --rule: #e4e0d8;
  --rule-strong: #cdc8bd;

  /* GOLIA blue, structural accent — the same scale golia.jp and
     tiktoken.golia.jp use, resolved to sRGB so the page needs no
     colour-space plumbing. blue-600 measures 5.07:1 on this paper, clear
     of WCAG AA, so the brand value is used directly rather than darkened. */
  --golia: #1576ff;
  --accent: #155dfc;
  --accent-deep: #1447e6;
  --accent-wash: #eef3ff;

  /* Archivo is a tight grotesque — engineered rather than literary; it does
     the display work a serif used to. Plex Sans carries prose, Plex Mono
     every number, identifier and command. CJK falls back to the system UI
     faces, not Mincho: the page reads as modern in all three languages. */
  --display: 'Archivo', 'PingFang SC', 'Hiragino Sans', 'Noto Sans CJK SC', sans-serif;
  --sans: 'IBM Plex Sans', 'PingFang SC', 'Hiragino Sans', 'Noto Sans CJK SC', sans-serif;
  --mono: 'IBM Plex Mono', 'SFMono-Regular', Menlo, Consolas, monospace;

  --maxw: 74rem;
  --measure: 42rem;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* the sticky header must not cover an anchored section heading */
  scroll-padding-top: 5rem;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16.5px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Kinsoku: CJK must not start a line with closing punctuation (。、」）)
     or end one with an opener. The browser enforces this natively and
     correctly — nothing in JS needs to help it. */
  line-break: strict;
  overflow-wrap: break-word;
  /* Japanese only: a browser-native refinement that prefers phrase
     boundaries over the default per-character fold. Engines without it
     fall back to `normal`, which is also correct CJK typesetting. */
  word-break: auto-phrase;
}

a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(21, 93, 252, 0.3);
  transition: border-color 130ms ease, color 130ms ease;
}
a:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Headings balance across their lines; running text avoids a one-word last
   line. Both degrade to normal wrapping where unsupported. */
h1,
h2,
h3 {
  text-wrap: balance;
}
p,
.lede,
.caption,
.abstract,
.figure .k {
  text-wrap: pretty;
}

.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.shell {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 2rem;
}
@media (max-width: 640px) {
  .shell {
    padding: 0 1.15rem;
  }
}

section {
  border-top: 1px solid var(--rule);
  padding: 4rem 0;
}

/* Heading, lede and the content the section introduces share one left edge. */
.sechead {
  margin-bottom: 1.5rem;
}
.sechead h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.4rem, 3vw, 1.95rem);
  line-height: 1.2;
  letter-spacing: -0.022em;
}
.sechead .lede {
  color: var(--ink-soft);
  max-width: var(--measure);
  margin-top: 0.7rem;
  font-size: 1rem;
}

.prose {
  color: var(--ink-soft);
  max-width: var(--measure);
}

.caption {
  margin-top: 1rem;
  font-size: 0.85rem;
  color: var(--ink-faint);
  max-width: var(--measure);
}
.caption b {
  color: var(--ink-soft);
  font-weight: 600;
}

/* ── masthead ─────────────────────────────────────────────────────── */
/* The Golia Lab masthead, matching tiktoken.golia.jp exactly: the two lab
   pages are one publication and should not differ in their chrome. */

.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(252, 251, 248, 0.88);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--rule);
}
.masthead-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0.7rem 2rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
@media (max-width: 640px) {
  .masthead-inner {
    padding: 0.6rem 1.15rem;
  }
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border-bottom: none;
  color: var(--ink);
}
.brand:hover {
  border-bottom: none;
  color: var(--ink);
  text-decoration: none;
}
.brand img {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  display: block;
}
.brand .wordmark {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -0.01em;
}

.topnav {
  display: flex;
  align-items: center;
  gap: 1.35rem;
  font-size: 0.86rem;
  /* A flex item will not shrink below its content, so without this the
     nav pushes the document wider than the viewport — 7px at 390 with the
     Japanese labels, which verify.mjs measures. */
  min-width: 0;
}
.topnav a {
  color: var(--ink-soft);
  border-bottom: none;
}
.topnav a:hover {
  color: var(--accent);
  text-decoration: none;
}
@media (max-width: 860px) {
  .topnav a.hide-sm {
    display: none;
  }
}
@media (max-width: 460px) {
  .topnav {
    gap: 0.8rem;
  }
  .topnav a {
    display: none;
  }
}

.langswitch {
  display: inline-flex;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  overflow: hidden;
  background: var(--paper-raised);
}
/* Buttons on the landing page, links everywhere else — one control, two
   elements, and for a while only one of them had any of this. */
.langswitch button,
.langswitch a {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-faint);
  font-family: var(--sans);
  font-size: 0.75rem;
  line-height: 1.4;
  padding: 0.28rem 0.55rem;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 120ms ease, color 120ms ease;
}
.langswitch button + button,
.langswitch a + a {
  border-left: 1px solid var(--rule);
}
.langswitch button:hover,
.langswitch a:hover {
  color: var(--ink);
  text-decoration: none;
}
.langswitch button.on,
.langswitch a.on {
  background: var(--accent);
  color: #fff;
}

/* ── frontmatter ──────────────────────────────────────────────────── */

.frontmatter {
  border-top: none;
  padding: 4.5rem 0 3.4rem;
}
.eyebrow {
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 1.3rem;
}
.frontmatter h1 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(2rem, 5vw, 3.3rem);
  line-height: 1.08;
  letter-spacing: -0.035em;
  max-width: 22ch;
}
.frontmatter h1 em {
  font-style: normal;
  color: var(--accent);
}
.frontmatter .abstract {
  margin-top: 1.5rem;
  max-width: var(--measure);
  color: var(--ink-soft);
  font-size: 1.05rem;
}

/* figures row — the headline numbers, set as a data strip */
.figures {
  margin-top: 2.6rem;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--rule-strong);
}
@media (max-width: 720px) {
  .figures {
    grid-template-columns: repeat(2, 1fr);
  }
}
.figure {
  padding: 0.95rem 1.1rem 0.9rem 0;
}
.figure + .figure {
  border-left: 1px solid var(--rule);
  padding-left: 1.1rem;
}
@media (max-width: 720px) {
  .figure:nth-child(3) {
    border-left: none;
    padding-left: 0;
    border-top: 1px solid var(--rule);
  }
  .figure:nth-child(4) {
    border-top: 1px solid var(--rule);
  }
}
.figure .v {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.figure .k {
  font-size: 0.78rem;
  color: var(--ink-faint);
  margin-top: 0.1rem;
}

.actions {
  margin-top: 2.1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  font-size: 0.88rem;
}
.btn > svg:first-child,
footer .links a > svg:first-child {
  flex: none;
  opacity: 0.75;
}
.btn:hover > svg:first-child,
footer .links a:hover > svg:first-child {
  opacity: 1;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 1rem;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  color: var(--ink);
  background: var(--paper-raised);
  transition: border-color 130ms ease, background 130ms ease, color 130ms ease;
}
.btn:hover {
  border-color: var(--ink);
  text-decoration: none;
}
.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 500;
}
.btn.primary:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
  color: #fff;
}
.btn .ext {
  opacity: 0.45;
}

/* ── tables ───────────────────────────────────────────────────────── */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
thead th {
  text-align: left;
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 0 0.7rem 0.55rem 0;
  border-bottom: 1px solid var(--rule-strong);
}
tbody td {
  padding: 0.55rem 0.7rem 0.55rem 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}
tbody tr:last-child td {
  border-bottom: 0;
}
td.num,
th.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  padding-right: 0;
}
td.win {
  color: var(--accent);
  font-weight: 600;
}
.tablewrap {
  overflow-x: auto;
}

/* ── code ─────────────────────────────────────────────────────────── */

.codeblock {
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background: var(--paper-raised);
  overflow: hidden;
}
.code-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.8rem;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-sunk);
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--ink-faint);
}
.code-head button {
  margin-left: auto;
  font: inherit;
  font-size: 0.72rem;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  background: var(--paper-raised);
  color: var(--ink-soft);
  padding: 0.15rem 0.45rem;
  cursor: pointer;
}
.code-head button:hover {
  border-color: var(--ink);
  color: var(--ink);
}
pre {
  font-family: var(--mono);
  font-size: 0.83rem;
  line-height: 1.6;
  padding: 0.85rem 0.9rem;
  overflow-x: auto;
}
/* A grid or flex child defaults to min-width:auto, which is the content's
   intrinsic width — so `overflow-x: auto` on the <pre> never engages and
   the widest code line silently widens the whole document instead. Only
   visible on a phone, where it ruins every section. */
.codeblock {
  min-width: 0;
}
pre > code {
  display: block;
  min-width: 0;
}
code {
  font-family: var(--mono);
  font-size: 0.92em;
}
:not(pre) > code {
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.05em 0.3em;
}
.tok-c {
  color: var(--ink-faint);
}
.tok-k {
  color: var(--accent-deep);
}
.tok-s {
  color: #7a5c1e;
}

.install-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 1.6rem;
  align-items: start;
}
@media (max-width: 820px) {
  .install-grid {
    grid-template-columns: 1fr;
  }
}

/* ── cards ────────────────────────────────────────────────────────── */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
.card {
  background: var(--paper);
  padding: 1.1rem 1.2rem 1.2rem;
}
.card h3 {
  font-family: var(--display);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.card p {
  margin-top: 0.4rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}
.card .cmd {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-faint);
  margin-top: 0.55rem;
}

/* ── footer ───────────────────────────────────────────────────────── */

/* The Golia Lab footer, matching tiktoken.golia.jp: a 2px ink rule closes
   the page the way the figures strip opens it, and the organisation mark
   is the wordmark rather than the word. */
footer {
  border-top: 2px solid var(--ink);
  padding: 2rem 0 3.2rem;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.2rem;
  align-items: start;
  font-size: 0.82rem;
  color: var(--ink-faint);
}
@media (max-width: 640px) {
  footer {
    grid-template-columns: 1fr;
  }
}
footer .org {
  display: inline-block;
  border-bottom: none;
  margin-bottom: 0.6rem;
}

footer .org:hover {
  border-bottom: none;
  opacity: 0.75;
}

footer .org img {
  display: block;
  width: auto;
  height: 20px;
}

footer .links {
  display: flex;
  gap: 1.1rem;
  flex-wrap: wrap;
}

footer a {
  color: var(--ink-soft);
  border-bottom-color: var(--rule-strong);
}

footer a:hover {
  color: var(--accent);
}


footer .links a {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
}


/* ── docs ─────────────────────────────────────────────────────────── */

/* The reference pages share the landing page's system so the site reads as
   one publication. What they add is a two-column shell: the measure stays
   at --measure regardless of viewport, because a 74rem line of prose is
   unreadable no matter how much room there is. */
.docshell {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 2rem;
  display: grid;
  grid-template-columns: 16rem minmax(0, 1fr);
  gap: 0 3rem;
  align-items: start;
}
@media (max-width: 960px) {
  .docshell {
    grid-template-columns: 1fr;
    padding: 0 1.15rem;
  }
}
.docnav {
  position: sticky;
  top: 4.2rem;
  max-height: calc(100vh - 5.5rem);
  overflow-y: auto;
  padding: 2rem 0;
  font-size: 0.86rem;
  border-right: 1px solid var(--rule);
}
@media (max-width: 960px) {
  .docnav {
    position: static;
    max-height: none;
    border-right: 0;
    border-bottom: 1px solid var(--rule);
    padding-bottom: 1.2rem;
  }
}
.docnav .group {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 1.4rem 0 0.45rem;
}
.docnav .group:first-child {
  margin-top: 0;
}
.docnav a {
  display: block;
  padding: 0.2rem 0;
  color: var(--ink-soft);
}
.docnav a:hover {
  color: var(--ink);
  text-decoration: none;
}
.docnav a.on {
  color: var(--accent);
  font-weight: 500;
}
.docmain {
  padding: 2.6rem 0 4rem;
  min-width: 0;
}
.docmain h1 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.03em;
}
.docmain h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.3rem;
  letter-spacing: -0.018em;
  margin: 2.4rem 0 0.8rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
}
.docmain h3 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.05rem;
  margin: 1.8rem 0 0.6rem;
}
.docmain p,
.docmain ul,
.docmain ol {
  max-width: var(--measure);
  margin-bottom: 0.9rem;
}
.docmain ul,
.docmain ol {
  padding-left: 1.3rem;
}
.docmain li {
  margin-bottom: 0.25rem;
}
.docmain pre {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 4px;
  margin-bottom: 1rem;
}
.docmain table {
  margin-bottom: 1.2rem;
}
.docmain blockquote {
  border-left: 2px solid var(--rule-strong);
  padding-left: 1rem;
  color: var(--ink-soft);
  margin-bottom: 1rem;
  max-width: var(--measure);
}
.docmain hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 2rem 0;
}
.breadcrumb {
  font-family: var(--mono);
  font-size: 0.74rem;
  color: var(--ink-faint);
  margin-bottom: 0.9rem;
}
.breadcrumb a {
  color: var(--ink-faint);
}

/* A section number in the margin, the way a paper numbers its parts. It is
   decorative on narrow viewports, where there is no margin to put it in. */
.docmain h2 .n {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--accent);
  margin-right: 0.5rem;
}

@media print {
  .masthead,
  .docnav,
  .term-form,
  .actions {
    display: none;
  }
}

/* ── content blocks ───────────────────────────────────────────────────
   The block types the trilingual page content uses. They inherit the
   page's type and rules; what each one adds is the shape its content
   needs — a callout has to sit apart from the prose without shouting,
   a numbered step has to carry its number in the margin. */

.callout {
  border: 1px solid var(--rule-strong);
  border-left: 2px solid var(--accent);
  border-radius: 3px;
  background: var(--paper-raised);
  padding: 1.1rem 1.25rem;
  max-width: var(--measure);
}
/* A section about what the engine will NOT do is not a warning and not an
   error — it is a boundary, and it reads better in ink than in red. */
.callout.loss {
  border-left-color: var(--ink);
}
.callout h3 {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
}
.callout p + p {
  margin-top: 0.6rem;
}

.steps {
  counter-reset: step;
  list-style: none;
  padding: 0;
  display: grid;
  gap: 1.4rem;
  max-width: var(--measure);
}
.steps li {
  counter-increment: step;
  padding-left: 2.4rem;
  position: relative;
}
.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0.05rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--accent);
  border: 1px solid var(--rule-strong);
  border-radius: 50%;
  width: 1.6rem;
  height: 1.6rem;
  display: grid;
  place-items: center;
}
.steps h3 {
  font-family: var(--display);
  font-size: 0.98rem;
  font-weight: 600;
}
.steps p {
  color: var(--ink-soft);
  margin-top: 0.25rem;
}
.steps pre {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
  margin-top: 0.5rem;
}

