/* Generated by bin/build-api from src/styles/tokens.css and
   src/styles/site-header.css — do not edit the copy in public/api. */
/* Palette and type. Dracula, used dark-only: one theme across the landing page,
   the manual, and the API reference. Values are the official ones from
   draculatheme.com (MIT) except `--muted`, which is lightened — the spec's
   comment colour (#6272A4) is only 3.0:1 on the background, fine for a code
   comment but too weak for body-adjacent text.

   The `--syntax-*` roles are the same Dracula values, named by token rather
   than by hue: the manual's highlighter emits them and `bin/build-api` maps
   YARD's tokenizer classes onto them, so a keyword is one name across the
   site. Reference a role when colouring code; a literal hex is how the two
   sections drift apart.

   The body face is JetBrains Mono. Every page mixes prose with commands and
   signatures, and one monospace face keeps code and text on the same grid.

   Why the body is 15px, not the browser default 16px: a monospace face puts
   about 30% more advance width behind each character than the proportional
   faces UI type was drawn for, so 16px monospace reads as roughly 18px sans.
   The scale below is nine fixed steps modelled on omarchy.org (15px prose,
   13-14px navigation, 30px page title, 40px landing hero). It is a set of
   steps, not a ratio: a page picks a step, and a size that is not one of these
   is a bug in the page, not a new step.

   Sizes are rem so the reader's own font-size setting still scales the page.
   The px values in the comments are what each step lands on at the default
   16px root — the names describe position in the scale, not a fixed px. */

:root {
  color-scheme: dark;
  --font-body: 'JetBrains Mono Variable', ui-monospace, 'SF Mono', Menlo, monospace;
  --font-mono: 'JetBrains Mono Variable', ui-monospace, 'SF Mono', Menlo, monospace;

  --text-2xs: 0.6875rem;  /* 11px — labels, meta lines, dense list rows */
  --text-xs: 0.75rem;     /* 12px — code blocks, search fields */
  --text-sm: 0.8125rem;   /* 13px — navigation, sidebar, inline code, tables */
  --text-md: 0.875rem;    /* 14px — header nav, secondary prose, API docstrings */
  --text-base: 0.9375rem; /* 15px — body prose */
  --text-lg: 1.0625rem;   /* 17px — h3 */
  --text-xl: 1.25rem;     /* 20px — h2 */
  --text-2xl: 1.875rem;   /* 30px — manual h1 */
  --text-3xl: 2.5rem;     /* 40px — landing hero */

  /* Prose is looser than headings; code keeps prose's leading. */
  --leading-tight: 1.2;
  --leading-heading: 1.35;
  --leading-prose: 1.65;

  --weight-body: 400;
  --weight-heading: 600;
  --weight-brand: 700;

  --bg: #282a36;
  --bg-deep: #21222c;
  --surface: #343746;
  --fg: #f8f8f2;
  --muted: #9ba6c8; /* 5.9:1 — the spec's #6272a4 is 3.0:1 */
  --line: #44475a;
  --accent: #bd93f9; /* purple, 5.9:1 */
  --accent-soft: #3b3357;
  --accent-strong: #ff79c6; /* pink, hover */

  /* Dracula's token colours, named by role rather than by hue so the manual's
     highlighter and the API reference name the same token. `--syntax-comment`
     keeps the spec value: 3.0:1 is too weak for prose but fine for a comment,
     which the surrounding line already distinguishes. */
  --syntax-comment: #6272a4;
  --syntax-cyan: #8be9fd;
  --syntax-green: #50fa7b;
  --syntax-orange: #ffb86c;
  --syntax-pink: #ff79c6;
  --syntax-purple: #bd93f9;
  /* Dracula's error/diff red. The manual's grammars reach it only through a
     regexp-negation or an invalid token, so it is rare — but a block that
     hits it must still name a role rather than leak a hex. */
  --syntax-red: #ff5555;
  --syntax-yellow: #f1fa8c;

  --radius: 8px;

  /* Spacing, 4px steps: --space-4 is 16px. A page picks a step; values
     between these steps are legacy one-offs and should move onto the scale as
     they change. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-7: 1.75rem;
  --space-8: 2rem;
  --space-9: 2.25rem;
  --space-10: 2.5rem;
  --space-11: 2.75rem;
  --space-12: 3rem;
  --space-14: 3.5rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;

  /* Line length in rem (rem is the browser root, 16px, not the 15px body).
     48rem at 15px monospace is about 85 characters — the measure omarchy.org
     reads at, and the point where a monospace line stops being easy to track. */
  --measure: 48rem;
}
/* The site header. One source for both halves of the site: Astro imports this
   file, and build-api copies it into the YARD output, so the manual and the
   API reference cannot drift apart at the top of the page. */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg-deep);
  border-bottom: 1px solid var(--line);
}

.site-header-inner {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  /* The API output concatenates this file without site.css's global
     `box-sizing: border-box`, so the max-width has to include the padding
     explicitly or the brand starts 1.5rem left of the API navigation. */
  box-sizing: border-box;
  /* Same shell as the centered pages below: the brand starts where the content
     starts, not 3rem outside it. */
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.9rem var(--space-6);
}

.site-header .brand {
  font-size: var(--text-base);
  font-weight: var(--weight-brand);
  color: var(--syntax-pink);
  text-decoration: none;
}

.site-header .brand:hover {
  color: var(--accent-strong);
}

/* Navigation sits one step below the body so it reads as chrome, not content.
   14px is omarchy.org's top-nav step; 13px stays for the sidebar and code. */
.site-header .site-nav {
  display: flex;
  gap: var(--space-6);
  font-size: var(--text-md);
}

.site-header .site-nav a {
  color: var(--muted);
  text-decoration: none;
}

.site-header .site-nav a:hover {
  color: var(--fg);
}

.site-header .site-nav a.active {
  color: var(--syntax-green);
}

@media (max-width: 60rem) {
  /* The page shell drops to 1.25rem side padding here; the header has to
     follow it or the brand sits 4px inside the content below. */
  .site-header-inner {
    padding-left: var(--space-5);
    padding-right: var(--space-5);
  }
}

@media (max-width: 40rem) {
  .site-header-inner {
    gap: var(--space-6);
    padding: var(--space-3) var(--space-5);
  }
}

/* --- API surface --------------------------------------------------------
   The API pages carry the same Dracula palette as the rest of the site. YARD's
   own stylesheet hardcodes light greys, so the colours below are the one place
   they are re-pointed.

   Type sizes come from the site scale in tokens.css, one step down from the
   manual where YARD packs more onto the page. YARD's own scale (13px body,
   15px docstring) was tuned for a proportional face; JetBrains Mono is a
   monospace and each character is ~30% wider, so the same px sizes overflow —
   nav labels clip and code blocks force horizontal scroll. The steps below
   restore the *measured line width* YARD was designed for, not the nominal px
   value.

   Contrast follows the same rule as the site: the spec's comment colour
   (var(--syntax-comment)) is used for syntax only, never for text that must be read. */

/* YARD's own stylesheet sizes most of its content in `em` against this body
   size (menus, inheritance trees, the on-page table of contents). Those em
   chains were tuned for a 13px proportional body; 12px is the step that
   occupies the same measured width in a monospace face, and leaving it here
   keeps every YARD-internal ratio intact. Text the site actually writes
   (docstrings, summaries, code) is set explicitly below. */
body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  line-height: var(--leading-prose);
}

.yard-body {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* The shared header is 72rem. Center YARD's body on the same shell so the
   navigation starts where the brand does, instead of at the viewport edge.
   The side padding follows the header's own breakpoint: 1.25rem under 60rem,
   1.5rem above it. */
@media (min-width: 921px) {
  .yard-body {
    box-sizing: border-box;
    width: 100%;
    max-width: 72rem;
    margin: 0 auto;
    padding: 0 var(--space-5);
  }
}

@media (min-width: 961px) {
  .yard-body {
    padding: 0 var(--space-6);
  }
}

/* The nav is a fixed column, not a percentage: monospace class names are wider
   than the proportional face YARD sized the 20% split for. */
.nav_wrap {
  width: 20rem;
  flex-shrink: 0;
}

@media (max-width: 920px) {
  .nav_wrap {
    width: auto;
  }
}

/* YARD sets 15px for prose; the site's 14px step is what a monospace face
   carries at the same measured width. */
.docstring,
.tags,
#filecontents {
  font-size: var(--text-md);
  line-height: var(--leading-prose);
}

.docstring h1 { font-size: var(--text-xl); }
.docstring h2 { font-size: var(--text-lg); }
.docstring h3,
.docstring h4 { font-size: var(--text-base); }

h1 {
  font-size: var(--text-2xl);
  line-height: var(--leading-tight);
  /* `Class: ActionController::API` is one unbreakable token wider than a phone.
     YARD's own headings never wrapped, so this only shows up at the narrow end. */
  overflow-wrap: anywhere;
}
h1.alphaindex { font-size: var(--text-xl); }
h2 { font-size: var(--text-xl); line-height: var(--leading-heading); }
h3.inherited { font-size: var(--text-md); }

/* Everything YARD renders in a monospace face — signatures, summaries, code —
   uses the site face so the page reads as one system. */
h3.signature,
p.signature,
h3.signature tt,
p.signature tt,
ul.summary,
ul.summary a,
#content code,
#content tt,
pre.code,
.tags pre.example,
.docstring pre.code,
#filecontents pre.code,
.source_code pre,
.docstring pre.code code,
.summary_desc .object_link a,
.docstring .object_link a {
  font-family: var(--font-mono);
}

ul.summary,
ul.summary a {
  font-size: var(--text-sm);
}

h3.signature,
p.signature {
  font-size: var(--text-sm);
}

pre.code,
.tags pre.example,
.docstring pre.code,
#filecontents pre.code {
  font-size: var(--text-xs);
  line-height: var(--leading-prose);
}

/* Links and headings */
a, #content a, #content a:visited, #menu a, #menu a:visited {
  color: var(--accent);
}

#content a:hover {
  color: var(--accent-strong);
  background: transparent;
}

#main {
  background: var(--bg);
  /* YARD insets #main by 1.2em. The nav ends at a border; 1rem is the content
     gap the rest of the site uses most often, and the resize handle is hidden
     so nothing overlays this gutter. */
  padding-left: var(--space-4);
}

h1, h2, h3, h4, h5, h6 {
  color: var(--fg);
}

h1 {
  border-top-color: var(--line);
}

h2 {
  border-bottom-color: var(--line);
}

/* Signatures and summaries */
h3.signature, p.signature {
  background: var(--bg-deep);
  border-color: var(--line);
  border-radius: var(--radius);
  color: var(--fg);
}

h3.signature a, p.signature a {
  color: var(--syntax-cyan);
}

.summary_signature {
  background: var(--surface);
  border-color: var(--line);
  border-radius: var(--radius);
}

.summary_signature:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}

.summary_signature a,
ul.summary a {
  color: var(--syntax-cyan);
}

/* Inline code and code blocks */
*:not(pre) > code,
.docstring p > code,
.docstring p > tt,
.tags p > code,
.tags p > tt {
  color: var(--syntax-orange);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: 4px;
}

pre.code,
.docstring pre.code,
#filecontents pre.code,
.tags pre.example {
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  color: var(--fg);
}

/* A constant's value is a bare <pre> inside its <dd>, outside `.docstring`, so
   YARD's padding rule (which only matches docstring and file examples) never
   reaches it: the value sat flush against the accent border, and as a block it
   drew an empty box the full 75% column width. Inline-block keeps the box the
   size of the value.

   `white-space: pre` on the `dd` means a long literal (the timezone table, the
   status-code map) cannot wrap, so it scrolls inside its own box instead of
   widening the whole page on a phone. */
dl.constants dd pre.code {
  display: inline-block;
  margin: 0;
  padding: var(--space-1) 0.625rem;
  max-width: 100%;
  overflow-x: auto;
}

/* YARD's tag lists (Yields:, Returns:, Parameters:) hold types in a `span.type`
   with `white-space: pre` on the enclosing `dd`-free list, so a long signature
   such as `(token, token_options(...))` stays on one line and runs off a phone.
   The tags are prose-like data, not code: they wrap. */
.tags ul,
.tags .type {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* YARD's syntax classes, mapped to the role names in tokens.css — the same
   names the manual's highlighter emits, so a token has one colour across both
   sections and tokens.css stays the only place a colour is written. */
pre.code .comment { color: var(--syntax-comment); }
pre.code .const,
pre.code .constant {
  color: var(--syntax-purple);
}
pre.code .kw,
pre.code .rubyid_require,
pre.code .rubyid_extend,
pre.code .rubyid_include {
  color: var(--syntax-pink);
}
pre.code .tstring_content,
pre.code .heredoc_beg,
pre.code .heredoc_end,
pre.code .qwords_beg,
pre.code .qwords_end,
pre.code .qwords_sep,
pre.code .words_beg,
pre.code .words_end,
pre.code .words_sep,
pre.code .qsymbols_beg,
pre.code .qsymbols_end,
pre.code .qsymbols_sep,
pre.code .symbols_beg,
pre.code .symbols_end,
pre.code .symbols_sep,
pre.code .tstring,
pre.code .dstring,
pre.code .regexp,
pre.code .dregexp {
  color: var(--syntax-yellow);
}
pre.code .label,
pre.code .symbol {
  color: var(--syntax-pink);
}
pre.code .ivar,
pre.code .gvar,
pre.code .rubyid_backref,
pre.code .rubyid_nth_ref {
  color: var(--syntax-cyan);
}
pre.code .fid,
pre.code .rubyid_new,
pre.code .rubyid_to_s,
pre.code .rubyid_to_f,
pre.code .rubyid_to_i,
pre.code .rubyid_each,
pre.code .dot + pre.code .id {
  color: var(--syntax-green);
}
pre.code .val {
  color: var(--syntax-orange);
}
pre.code .info.file {
  color: var(--muted);
}
pre.code .lines {
  color: var(--muted);
}

/* Definition boxes, tags, tables */
.box_info dl dt,
.box_info dl dd {
  border-color: var(--line);
  background: var(--surface);
  color: var(--fg);
}

.box_info dl:nth-child(odd) > * {
  background: var(--surface);
}

.box_info dl:nth-child(even) > * {
  background: var(--bg);
}

.docstring table,
.docstring table th,
.docstring table td,
#filecontents table,
#filecontents table th,
#filecontents table td {
  border-color: var(--line);
}

.docstring table th,
#filecontents table th {
  background: var(--surface);
  color: var(--fg);
}

.docstring table tr:nth-child(odd),
#filecontents table tr:nth-child(odd) {
  background: var(--surface);
}

.docstring table tr:nth-child(even),
#filecontents table tr:nth-child(even) {
  background: var(--bg);
}

.tags .tag_title,
.docstring .note.title {
  color: var(--fg);
}

.note {
  background: var(--bg-deep);
  border-color: var(--line);
  color: var(--fg);
}

.note.title {
  background: var(--surface);
}

/* YARD paints several note variants with its own light fills — grey for a void
   return, yellow for a todo, pink for deprecated. The theme's text colour stays
   near-white, so those fills make the text vanish. Each variant gets a dark
   surface instead, and the chip variants get the accent tint. */
.note.returns_void,
.note.todo,
.note.private,
.note.deprecated {
  background: var(--bg-deep);
  border-color: var(--line);
  color: var(--muted);
}

.note.title.readonly,
.note.title.writeonly,
.note.title.constructor {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-strong);
}

.note.title.private {
  background: var(--surface);
  border-color: var(--line);
  color: var(--muted);
}

#toc {
  background: var(--surface);
  border-color: var(--line);
  box-shadow: none;
}

/* Navigation frame */
.nav_wrap {
  background: var(--bg);
}

/* The nav is a fixed 20rem column, so YARD's resize handle has nothing to
   resize; it also sits 5px into the main column and covers the first
   character now that #main starts at the divider. */
#resizer {
  display: none;
}

#menu {
  color: var(--muted);
}

#menu .title, #menu a {
  color: var(--muted);
}

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

#search a {
  background: var(--surface);
  border-color: var(--line);
  color: var(--accent);
  box-shadow: none;
}

#search a:hover {
  background: var(--accent-soft);
  color: var(--accent-strong);
}

/* The collapse/expand tabs and the "more…" toggle sit on their own filled
   chips. YARD paints them with a light grey that stays white in this theme. */
h2 small a,
.toggleDefines,
.inheritanceTree,
a[href^="#more_"],
a[href^="#toggle_"] {
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--accent);
  border-radius: 4px;
  padding: 0.1rem 0.4rem;
}

h2 small a:hover,
.toggleDefines:hover,
a[href^="#more_"]:hover {
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.showSource a,
.showSource a:visited {
  color: var(--muted);
}

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

#method_missing_details .notice.this {
  color: var(--muted);
}

#footer {
  border-top-color: var(--line);
  color: var(--muted);
}

#footer a, #footer a:visited {
  color: var(--muted);
}

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

/* The class list is its own document inside the nav frame, with its own
   stylesheet and its own `odd`/`even` row classes. */
body#full_list_body,
#content.insearch,
#noresults {
  background: var(--bg);
  color: var(--fg);
}

.fixed_header {
  background: var(--bg-deep);
  border-bottom: 1px solid var(--line);
}

#full_list_header,
#full_list_nav a {
  color: var(--muted);
}

#full_list_nav a:hover,
#full_list_nav span.current a {
  color: var(--accent);
}

#full_list li {
  color: var(--muted);
}

.api-list #full_list li a {
  color: var(--syntax-cyan);
}

#full_list li a:hover {
  color: var(--accent-strong);
}

#full_list li.odd {
  background: var(--bg);
}

#full_list li.even {
  background: var(--surface);
}

#full_list .item:hover {
  background: var(--accent-soft);
}

#full_list li.clicked > .item {
  background: var(--accent);
  color: var(--bg-deep);
}

#full_list li.clicked > .item a,
#full_list li.clicked > .item a:visited {
  color: var(--bg-deep);
}

#search input,
input[type='text'] {
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  padding: var(--space-1) 0.4rem;
}

/* The rules below are for the class-list document that loads inside the nav
   frame. They are scoped to `.api-list` because the outer page has its own
   `#search` element (the nav toggle) that must keep YARD's positioning.

   YARD fixes that header to the top and pushes the list down by a hardcoded
   margin (70px/80px), a pair sized for Lucida at 13px. Monospace is taller, so
   the two no longer line up and the search box sits on the first rows. Sticky
   keeps the header in flow: the list starts after it at every size, with no
   height to keep in sync. */
.api-list .fixed_header {
  position: sticky;
  top: 0;
  height: auto;
  padding-bottom: 0.4rem;
}

.api-list #full_list_header {
  font-size: var(--text-base);
  padding: var(--space-3) 0.625rem var(--space-1);
}

.api-list #full_list_nav {
  font-size: var(--text-2xs);
  padding-left: 0.625rem;
}

.api-list #full_list_nav span {
  margin-right: var(--space-2);
}

.api-list #search {
  position: static;
  padding: 0.4rem 0.625rem 0;
}

.api-list #search label {
  font-size: var(--text-2xs);
}

.api-list #search input {
  width: 100%;
  max-width: 12rem;
  margin-left: var(--space-1);
}

.api-list #full_list {
  margin-top: 0;
  font-size: var(--text-sm);
}

/* YARD sets `white-space: nowrap` for its proportional faces. A monospace class
   name such as `UnpermittedParameters < StandardError` overruns the 20rem nav
   and is cut off at the panel edge, so the rows wrap instead. */
.api-list #full_list li {
  white-space: normal;
}

.api-list #full_list li .item {
  padding: 0.3rem var(--space-2);
  line-height: var(--leading-heading);
}

#full_list li a {
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  /* `Class: ActionController::API` is one unbreakable token: at 30px it is
     wider than a phone and breaks mid-identifier. The page title steps down to
     h2's size here instead, which keeps it on one line. */
  h1 {
    font-size: var(--text-xl);
  }

  /* YARD pins the section toggle to the right edge of the heading, where a
     20px monospace title runs underneath it. In flow it wraps to its own row;
     `fit-content` keeps the chip the size of its label instead of the column. */
  h2 small {
    position: static;
    display: block;
    margin-top: var(--space-1);
  }

  h2 small a {
    display: inline-block;
    width: fit-content;
  }
}

@media (max-width: 920px) {
  /* YARD turns the nav into an overlay at this width; the body must scroll the
     page instead of pinning it to the viewport, or the overlay is clipped. */
  body {
    height: auto;
    min-height: 100vh;
  }

  .yard-body {
    display: block;
    /* The header keeps its 1.25rem side padding here; the body has to start
       on the same line instead of touching the viewport edge. */
    padding: 0 var(--space-5);
  }

  /* The overlay would otherwise cover the shared header. */
  #nav {
    top: 3rem;
    background: var(--bg);
    border: 1px solid var(--line);
    box-shadow: none;
  }

  /* The nav toggle is positioned against the viewport origin in YARD's layout,
     which is now the shared header. Anchor it to the content box instead. */
  #search {
    top: 0.25rem;
  }
}

@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url(../fonts/jetbrains-mono-latin-wght-normal.woff2) format('woff2-variations');
}
