@layer starlight, user; @layer user.overrides { :root { --font-fallback: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; --sl-font: "Inter Variable", var(--font-fallback); --sl-font-heading: "polymath-display", sans-serif; --sl-font-mono: "dm-mono", ui-monospace, monospace; --sl-color-text-heading: var(--heading-fill); /* Heading baseline: one notch smaller than Starlight's wide-viewport scale; the full-size scale only applies at desktop widths (below) */ --sl-text-h1: var(--sl-text-5xl); --sl-text-h2: var(--sl-text-2xl); --sl-text-h3: var(--sl-text-xl); --sl-text-h4: var(--sl-text-lg); --sl-color-accent-hsl: 311 100% 50%; --sl-color-accent-low: hsl(var(--sl-color-accent-hsl) / 0.1); --sl-color-accent: hsl(var(--sl-color-accent-hsl) / 0.9); --sl-color-accent-high: hsl(var(--sl-color-accent-hsl) / 1); --sl-color-bg: var(--background); --sl-color-bg-nav: var(--background); --sl-color-bg-sidebar: var(--background); --sl-color-bg-inline-code: var(--surface-inner-fill); --sl-color-bg-accent: var(--sl-color-accent-high); --sl-color-hairline-light: var(--surface-border-fill); --sl-color-hairline: var(--surface-border-fill); --sl-color-hairline-shade: var(--surface-border-fill); --sl-icon-color: var(--heading-fill); /* extra room for the hatched separator strip under the navbar */ --hatch-height: 0.75rem; --sl-nav-height: 4.25rem; scrollbar-width: thin; scrollbar-gutter: stable; scrollbar-color: hsl(var(--sl-color-accent-hsl)) var(--surface-fill); } ::selection { background-color: var(--color-pink-100); color: var(--color-gray-100); } /* bomb.sh viewport frame: 8px background strips + 1px grid border, drawn over everything (pointer-events: none) so scrolled content passes "behind" the frame exactly like on the marketing site */ body::before { content: ""; position: fixed; inset: 0; z-index: 101; pointer-events: none; background-image: /* fill strips */ linear-gradient(var(--background), var(--background)), linear-gradient(var(--background), var(--background)), linear-gradient(var(--background), var(--background)), linear-gradient(var(--background), var(--background)), /* border lines */ linear-gradient(var(--c-grid), var(--c-grid)), linear-gradient(var(--c-grid), var(--c-grid)), linear-gradient(var(--c-grid), var(--c-grid)), linear-gradient(var(--c-grid), var(--c-grid)); background-size: /* fill: top, bottom, left, right */ 100% var(--s-grid-padding), 100% var(--s-grid-padding), var(--s-grid-padding) 100%, var(--s-grid-padding) 100%, /* border: top, bottom, left, right */ 100% var(--s-grid-width), 100% var(--s-grid-width), var(--s-grid-width) 100%, var(--s-grid-width) 100%; background-position: top left, bottom left, top left, top right, 0 var(--s-grid-padding), 0 calc(100% - var(--s-grid-padding)), var(--s-grid-padding) 0, calc(100% - var(--s-grid-padding)) 0; background-repeat: no-repeat; } /* bomb.sh hatched separator strip along the bottom of the navbar. Nav content stays centered across the full nav height; the strip overlays the bottom edge like the homepage separator. */ header.header::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: var(--hatch-height); border-top: var(--s-grid-width) solid var(--c-grid); --_size: var(--s-grid-width); --_space: 6px; background-image: repeating-linear-gradient( 45deg, transparent, transparent var(--_space), var(--c-grid-muted) var(--_space), var(--c-grid-muted) calc(var(--_space) + var(--_size)) ); pointer-events: none; } /* Full-size heading scale on desktop viewports only */ @media (min-width: 72rem) { :root { --sl-text-h1: var(--sl-text-6xl); --sl-text-h2: var(--sl-text-4xl); --sl-text-h3: var(--sl-text-3xl); --sl-text-h4: var(--sl-text-2xl); } } :is(h1, h2, h3, h4, h5, h6) { font-feature-settings: "ss03" on, "ss12" on; } :is(h1, .starlight-sidebar-topics) { font-feature-settings: "ss01" on, "ss03" on, "ss09" on, "ss10" on, "ss12" on; font-family: var(--sl-font-heading); } :is(.starlight-sidebar-topics li) { font: inherit; font-feature-settings: inherit; text-transform: lowercase; } :is(h1) { --c-border: var(--heading-fill); --c-start: var(--heading-fill); --c-end: var(--heading-muted); --s-border: 1px; -webkit-text-stroke-color: var(--c-border); -webkit-text-stroke-width: var(--s-border); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(to right, var(--c-start), var(--c-end)); letter-spacing: 0.1ch; } :is(h2, h3, h4, h5, h6) { --c-start: var(--heading-fill); --c-end: color-mix(in srgb, var(--heading-fill) 35%, transparent); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(to right, var(--c-start), var(--c-end)); letter-spacing: 0.1ch; } :is(h1, h2, h3, h4, h5, h6) code { background-clip: border-box; -webkit-background-clip: border-box; -webkit-text-fill-color: var(--heading-fill); color: var(--heading-fill); } /* Target specific elements */ .sl-nav-link, .site-title, .sl-doc-title, header h1 { font-family: var(--sl-font-heading); } a.site-title { color: var(--heading-fill); } /* Right sidebar (TOC) background gradient */ .right-sidebar { background: linear-gradient( to bottom, var(--panel-grad-start) 0%, var(--background) 100% ); } starlight-toc nav > ul { border-left: 1px solid transparent; position: relative; &::before { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: var(--border-050); background: linear-gradient( to bottom, var(--surface-border-highlight), var(--surface-border-fill) ); } a { border-left: 2px solid transparent; border-radius: 0; } [aria-current] { border-left-color: hsl(var(--sl-color-accent-hsl) / 0.9); font-weight: 600; color: var(--separator-fill); } /* When the animated marker is active, the static per-link border is replaced by a single sliding indicator (injected by Head.astro). */ &.has-marker [aria-current] { border-left-color: transparent; } .toc-marker { position: absolute; left: 0; width: 2px; background: hsl(var(--sl-color-accent-hsl) / 0.9); transition: top 250ms cubic-bezier(0.23, 1, 0.32, 1), height 250ms cubic-bezier(0.23, 1, 0.32, 1); pointer-events: none; } @media (prefers-reduced-motion: reduce) { .toc-marker { transition: none; } } } p, li, td, blockquote { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } /* Buttons — match the bomb.sh homepage hero CTAs */ .sl-link-button { border-radius: 0.33em; corner-shape: bevel; font-family: var(--sl-font); font-weight: 500; transition: color 120ms cubic-bezier(0.23, 1, 0.32, 1), background-color 120ms cubic-bezier(0.23, 1, 0.32, 1), border-color 120ms cubic-bezier(0.23, 1, 0.32, 1); } .sl-link-button.primary { background: var(--color-white-100); color: var(--color-gray-100); border: var(--s-grid-width) solid var(--c-grid); &:is(:hover, :focus-visible) { background: color-mix(in srgb, var(--color-pink-100) 30%, transparent); color: var(--color-pink-100); border-color: var(--color-pink-100); } } .sl-link-button:not(.primary) { background: transparent; color: var(--color-gray-40); border: var(--s-grid-width) solid var(--color-gray-40); &:is(:hover, :focus-visible) { background: var(--color-gray-80); color: var(--color-white-100); border-color: var(--color-white-100); } } .sl-link-button > svg { fill: currentColor; } /* Content links — white at rest, topic accent on hover */ .sl-markdown-content a:not(:where(.not-content *)) { color: var(--color-white-100); transition: color 120ms cubic-bezier(0.23, 1, 0.32, 1); &:is(:hover, :focus-visible) { color: hsl(var(--sl-color-accent-hsl)); } /* Links wrapping code chips: accent at rest (so the underline matches the chip), flipping to white on hover — the inverse of plain links */ &:has(> code) { color: hsl(var(--sl-color-accent-hsl)); &:is(:hover, :focus-visible) { color: var(--color-white-100); & > code { --color: var(--color-white-100); } } } } /* Inline code — bomb.sh gradient chip, tinted by the topic accent */ .sl-markdown-content code:not(:where(.not-content *)):not(pre *) { --color: hsl(var(--sl-color-accent-hsl)); font-family: var(--sl-font-mono); color: var(--color); transition: color 120ms cubic-bezier(0.23, 1, 0.32, 1), background 120ms cubic-bezier(0.23, 1, 0.32, 1); font-size-adjust: 0.5; background: linear-gradient( -45deg, color-mix(in srgb, var(--color) 25%, transparent) 0%, color-mix(in srgb, var(--color) 12%, transparent) 100% ); padding-inline: 0.25em; padding-block: 0.1em; border-radius: 4px; } /* Search — a full-height section of the nav, delimited by vertical hairline bars, aligned with the main content column */ site-search { width: 100%; height: 100%; display: flex; align-items: center; } /* Desktop with a TOC column: cap the search at the main content area so its right bar aligns with the content/TOC boundary (measured value from Head.astro; the calc is a close fallback that ignores scrollbar width) */ @media (min-width: 72rem) { :root[data-has-toc] site-search { max-width: var( --search-clamp, calc((100vw - 2 * var(--sl-sidebar-width) + var(--sl-content-width)) / 2) ); } } @media (min-width: 50rem) { site-search button[data-open-modal] { border-radius: 0; max-width: 100%; height: 100%; border-block: none; border-inline: 1px solid var(--surface-border-fill); /* No fill — the nav's hatch strip stays visible through the section */ background-color: transparent; /* Stack above the nav's hatch strip so the bars stay unbroken, and nudge 1px left so the left bar overlaps the sidebar border exactly */ position: relative; z-index: 1; translate: -1px 0; } } .cli-preview { padding: 1em; border: 1px solid var(--surface-border-fill); border-radius: 0.5em; white-space: pre; line-height: 1.2em; font-family: var(--sl-font-mono); background-color: var(--container-fill); color: var(--color-white-100); overflow-x: auto; max-width: 100%; } /* Code frames — subtle gradient fade on terminal/editor title bars, matching the hatch-and-hairline chrome of the rest of the site */ .expressive-code .frame.is-terminal .header, .expressive-code .frame.has-title:not(.is-terminal) .header { background: linear-gradient( to bottom, transparent, color-mix(in srgb, var(--heading-fill) 7%, transparent) ); border-bottom: 1px solid var(--surface-border-fill); } /* Twoslash hovercards — same panel language as the rest of the chrome */ .expressive-code .twoslash-popup-container { border-radius: var(--radius-100); box-shadow: 0 8px 24px color-mix(in srgb, #000 35%, transparent); } .expressive-code .twoslash-popup-docs, .expressive-code .twoslash-popup-docs-tags { font-family: var(--sl-font); font-size: var(--sl-text-xs); } .expressive-code .twoslash-popup-code { font-family: var(--sl-font-mono); } .sidebar-pane { background: linear-gradient( to bottom, var(--panel-grad-start) 0%, var(--background) 100% ); a { border: 1px solid transparent; } ul.top-level a:not([aria-current="page"]):is(:hover, :focus-visible) { --c-start: hsl(var(--sl-color-accent-hsl) / 100%); --c-end: hsl(var(--sl-color-accent-hsl) / 50%); border-color: var(--sl-color-accent); color: var(--color-gray-100); background: linear-gradient(to right, var(--c-start), var(--c-end)); } [aria-current="page"] { --c-start: hsl(var(--sl-color-accent-hsl) / 5%); --c-end: hsl(var(--sl-color-accent-hsl) / 30%); color: var(--sl-color-accent); background: linear-gradient(to right, var(--c-start), var(--c-end)); border-color: var(--sl-color-accent); } } [data-has-sidebar] header.header { padding-inline-end: 1rem; } starlight-menu-button button { top: unset; bottom: calc( (var(--sl-mobile-toc-height) - var(--sl-menu-button-size)) / 2 ); background-color: var(--color-gray-80); } mobile-starlight-toc nav { top: unset; bottom: 0; } /* Light theme specific overrides for better readability */ :root[data-theme="light"] { --sl-color-text: var(--color-gray-100); --sl-color-text-muted: var(--color-gray-70); --sl-color-text-accent: var(--color-gray-90); .sl-nav-link, .site-title, .sl-doc-title { color: var(--color-gray-100); } input::placeholder { color: var(--color-gray-50); } ul.top-level a:not([aria-current="page"]):is(:hover, :focus-visible) { color: var(--color-white-100); } --sl-icon-color: var(--color-gray-100); .sl-link-button.primary { background: var(--color-gray-100); color: var(--color-white-100); border-color: var(--color-gray-100); &:is(:hover, :focus-visible) { background: color-mix(in srgb, var(--color-pink-100) 12%, transparent); color: var(--color-gray-100); border-color: var(--color-pink-100); } } .sl-link-button:not(.primary) { background: transparent; color: var(--color-gray-70); border-color: var(--color-gray-40); &:is(:hover, :focus-visible) { background: var(--color-gray-20); color: var(--color-gray-100); border-color: var(--color-gray-100); } } } /* The plugin's own component style is unlayered, so directly overriding `color`/`background-color`/`border-color` here would always lose regardless of specificity. Instead, override the custom properties it reads (--sl-color-white, --sl-color-text-accent) scoped to this element — no competing declaration targets this element directly, so no layer/specificity fight happens. Hover/focus/current text color keeps the plugin's own accent-color behavior (now per-topic, see below); only the icon's background/border fill is disabled. */ .starlight-sidebar-topics { --sl-text-base: 1.25em; --sl-color-white: var(--heading-highlight); --sl-color-text-accent: transparent; } .starlight-sidebar-topics a > div:not(.starlight-sidebar-topics-icon) { transition: transform 0.15s ease-out, opacity 0.15s ease-out; } .starlight-sidebar-topics a:is(.starlight-sidebar-topics-current, :hover, :focus-visible) > div:not(.starlight-sidebar-topics-icon) { transform: translateX(3px); opacity: 1; } /* Custom per-topic sidebar icons, replacing starlight-sidebar-topics' built-in Iconify icons. The plugin has no native custom-icon API (see https://github.com/HiDeoo/starlight-sidebar-topics/issues/5), so we hide its rendered and swap in our own via background-image, matched by the topic's link path (the only per-topic hook the plugin exposes). */ .starlight-sidebar-topics-icon svg { display: none; } /* Each topic's icon is stored once in --icon and consumed two ways: as a `mask-image` filled with solid white at rest (a flat silhouette), and as a full-color `background-image` on hover/focus/current. */ a[href*="/clack/"] .starlight-sidebar-topics-icon { --icon: url("../assets/topics/clack.svg"); } a[href*="/args/"] .starlight-sidebar-topics-icon { --icon: url("../assets/topics/args.svg"); } a[href*="/tab/"] .starlight-sidebar-topics-icon { --icon: url("../assets/topics/tab.svg"); } a[href*="/tty/"] .starlight-sidebar-topics-icon { --icon: url("../assets/topics/tty.svg"); } .starlight-sidebar-topics-icon { --size: 1.25em; width: var(--size); height: var(--size); background-size: contain; background-repeat: no-repeat; background-position: center; mask-image: var(--icon); mask-size: contain; mask-repeat: no-repeat; mask-position: center; background-color: var(--heading-highlight); opacity: 0.7; } a:is(.starlight-sidebar-topics-current, :hover, :focus-visible) .starlight-sidebar-topics-icon { mask-image: none; background-color: transparent; background-image: var(--icon); opacity: 1; } } /* these rules must not be layered because the Starlight Sidebar Topics plugin doesn't use Cascade Layers */ /* each topic link carries its own accent so hover/current always shows the topic's color, not the current page's accent */ .starlight-sidebar-topics a[href*="/clack/"] { --sl-color-accent-hsl: 184 100% 48%; } .starlight-sidebar-topics a[href*="/args/"] { --sl-color-accent-hsl: 52 100% 56%; } .starlight-sidebar-topics a[href*="/tab/"] { --sl-color-accent-hsl: 142 100% 47%; } .starlight-sidebar-topics a[href*="/tty/"] { --sl-color-accent-hsl: 300 100% 55%; } :root[data-theme="light"] { .starlight-sidebar-topics a[href*="/clack/"] { --sl-color-accent-hsl: 184 100% 30%; } .starlight-sidebar-topics a[href*="/args/"] { --sl-color-accent-hsl: 45 100% 33%; } .starlight-sidebar-topics a[href*="/tab/"] { --sl-color-accent-hsl: 142 100% 28%; } .starlight-sidebar-topics a[href*="/tty/"] { --sl-color-accent-hsl: 300 100% 38%; } } ul.starlight-sidebar-topics a:is(.starlight-sidebar-topics-current, :hover, :focus-visible) { color: hsl(var(--sl-color-accent-hsl) / 1); } .starlight-sidebar-topics .starlight-sidebar-topics-icon { border: none; } .starlight-sidebar-topics a { padding-block: 0.125em; } .starlight-sidebar-topics li + li { margin-top: 0; } /* Run the topics separator on the same horizontal line as the divider under the page title, so it reads as one continuous rule across sidebar and content. The min-height mirrors the first content panel's box: mobile-toc bar + panel padding (2 × 1.5rem) + h1 margin (1rem) + one h1 line (--sl-text-6xl × 1.2 line-height), minus the sidebar's own 1rem top padding. Applies wherever the sidebar is visible. */ @media (min-width: 50rem) { .starlight-sidebar-topics { display: flex; flex-direction: column; /* Measured offset set by Head.astro (no static fallback — it would act as a floor and defeat the natural-height measurement; without JS the two rules are simply compact and unaligned). */ min-height: var(--topics-rule-offset, auto); } .starlight-sidebar-topics::after { margin-top: auto; } /* When the title panel grows to meet a taller topics column, anchor the title to the bottom of the available space, just above the shared rule */ main .content-panel:first-of-type { display: flex; flex-direction: column; justify-content: flex-end; /* As a flex item the inner container would otherwise shrink to fit and its auto margins would center it */ & > .sl-container { width: 100%; } } } /* Tablet only: drop the title panel's top padding and the h1's default top margin — they only add dead space above the title and force the topics list to stretch further to keep the shared rule aligned. Desktop keeps its larger title spacing. */ @media (min-width: 50rem) and (max-width: 71.9375rem) { main .content-panel:first-of-type { padding-block-start: 0; } main h1#_top { margin-top: 0; } }