Files
hyperframes/docs/custom.css
T
Ular Kimsanov a06fdfe26e docs(catalog): put each item page's title, description and Docs text in the server HTML (#6711)
* docs(catalog): put each item page's title, description and Docs text in the server HTML

Mintlify renders snippet components in the browser only, so everything inside
CatalogDetail (title, standfirst, the Docs tab) was missing from the HTML search
engines read: 448 catalog pages served Googlebot no body text. The generator now
writes the H1 and standfirst as page markup above the component and the Docs tab
as page markup after it, shown with that tab (docs/custom.css). The component no
longer draws its own title. Pages patched structurally only; registry drift on 14
pages is left for a regeneration of its own.

* docs(catalog): keep the title's top spacing the component gave it

* fix(docs): catalog titles and descriptions keep markdown markers literal

MDX reads text inside the static <h1> and <p> as inline markdown, so @_blue_sweater_
rendered as italic blue_sweater. mdxText now writes backslash, backtick, * _ [ ] ~ as
character references too, with a unit test; the four affected pages are re-escaped.
2026-10-30 15:48:25 +00:00

1847 lines
50 KiB
CSS

/* HyperFrames Design System — Mintlify Theme Overrides */
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap");
@font-face {
font-family: "TT Norms Pro";
src: url("https://www-static-assets.heygen.com/fonts/tt-norms/TT_Norms_Pro_Light.woff2")
format("woff2");
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "TT Norms Pro";
src: url("https://www-static-assets.heygen.com/fonts/tt-norms/TT_Norms_Pro_Normal.woff2")
format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "TT Norms Pro";
src: url("https://www-static-assets.heygen.com/fonts/tt-norms/TT_Norms_Pro_Medium.woff2")
format("woff2");
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "TT Norms Pro";
src: url("https://www-static-assets.heygen.com/fonts/tt-norms/TT_Norms_Pro_DemiBold.woff2")
format("woff2");
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "TT Norms Pro";
src: url("https://www-static-assets.heygen.com/fonts/tt-norms/TT_Norms_Pro_Bold.woff2")
format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
/* ── Light mode (default) ── */
/*
* NOTE: All custom variables are namespaced with `--hf-` to avoid
* colliding with Mintlify's Tailwind color system, which owns names
* like `--background-light` / `--background-dark` and uses them via
* `rgb(var(--background-light)/<alpha>)`. Overriding those with hex
* values breaks the rgb() call and makes surfaces transparent (e.g.
* the "Copy page" dropdown panel in light mode).
*/
/* Light mode is the Studio app's light palette (packages/desktop/src/index.css :root,
* "Graphite"): warm paper, near-white cards and ink on hue 70. */
:root {
--hf-background: #f2f0ed;
--hf-background-light: oklch(0.987 0.005 70);
--hf-surface2: oklch(1 0 70);
--hf-border-color: oklch(0.205 0.003 70 / 0.08);
--hf-border-color-light: oklch(0.205 0.003 70 / 0.15);
--hf-text: oklch(0.205 0.003 70);
--hf-text-secondary: oklch(0.403 0.003 70);
--hf-text-tertiary: oklch(0.503 0.003 70);
--hf-heading: oklch(0.205 0.003 70);
--hf-code-bg: oklch(0.987 0.005 70);
--hf-ui-border: oklch(0.205 0.003 70 / 0.08);
--hf-sidebar-rail: oklch(0.205 0.003 70 / 0.15);
--hf-sidebar-text: oklch(0.403 0.003 70);
--hf-floating-input-shadow: 0 1px 2px oklch(0.2 0.01 70 / 0.06), 0 10px 30px oklch(0.2 0.01 70 / 0.06);
--mintlify-slot-header-height: 3rem;
/* The mint accent is for dark grounds; on paper links take the app's light accent ink. */
--hf-brand: oklch(0.45 0.096 164);
--hf-brand-soft: color-mix(in oklch, oklch(0.536 0.114 164) 13%, transparent);
--hf-video-accent: #3ce6ac;
--hf-glass: rgb(242 240 237 / 0.82);
--hf-chip: oklch(1 0 70);
--hf-accent-green: #1a7a0a;
--hf-accent-green-light: rgba(26, 122, 10, 0.07);
--hf-accent-green-border: rgba(26, 122, 10, 0.25);
--hf-accent-blue: #2563eb;
--hf-accent-blue-light: rgba(37, 99, 235, 0.06);
--hf-accent-blue-border: rgba(37, 99, 235, 0.2);
--hf-accent-purple: #7c3aed;
--hf-accent-purple-light: rgba(124, 58, 237, 0.06);
--hf-accent-purple-border: rgba(124, 58, 237, 0.2);
--hf-selection-bg: rgba(128, 128, 128, 0.2);
}
/* ── Dark mode ── */
/* Dark mode is the Studio app's Night palette (packages/desktop/src/index.css,
* :root[data-chrome="night"]): warm paper, cards and ink on hue 70. */
.dark,
[data-theme="dark"] {
--hf-background: #201e1c;
--hf-background-light: #272522;
--hf-surface2: #2f2c29;
--hf-border-color: rgb(245 243 241 / 0.1);
--hf-border-color-light: rgb(245 243 241 / 0.16);
--hf-text: #e2e0de;
--hf-text-secondary: #b8b6b4;
--hf-text-tertiary: #979593;
--hf-heading: #f5f3f1;
--hf-code-bg: #24211e;
--hf-ui-border: rgb(245 243 241 / 0.075);
--hf-sidebar-rail: rgb(245 243 241 / 0.1);
--hf-sidebar-text: #b8b6b4;
--hf-floating-input-shadow: 0 8px 28px rgba(0, 0, 0, 0.4), 0 1px 4px rgba(0, 0, 0, 0.4);
--hf-brand: #3ce6ac;
--hf-brand-soft: rgba(60, 230, 172, 0.12);
--hf-glass: rgb(32 30 28 / 0.72);
--hf-chip: rgb(255 255 255 / 0.08);
--hf-accent-green: #22c55e;
--hf-accent-green-light: rgba(34, 197, 94, 0.1);
--hf-accent-green-border: rgba(34, 197, 94, 0.3);
--hf-accent-blue: #3b82f6;
--hf-accent-blue-light: rgba(59, 130, 246, 0.1);
--hf-accent-blue-border: rgba(59, 130, 246, 0.3);
--hf-accent-purple: #a78bfa;
--hf-accent-purple-light: rgba(167, 139, 250, 0.1);
--hf-accent-purple-border: rgba(167, 139, 250, 0.3);
--hf-selection-bg: rgba(255, 255, 255, 0.15);
}
/* ── Typography ── */
body {
font-family:
"TT Norms Pro",
"Inter",
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family:
"TT Norms Pro",
"Inter",
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
}
h1,
h2 {
letter-spacing: -0.02em;
}
h3 {
letter-spacing: -0.01em;
}
/* ── Workflow routing ── */
.hf-workflow-routes {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.75rem 1.25rem;
margin: 1.5rem 0;
}
.hf-workflow-route {
display: flex;
flex-direction: column;
gap: 0.6rem;
color: inherit;
text-decoration: none;
border-bottom: 0 !important;
box-shadow: none !important;
}
.hf-workflow-route:hover .hf-workflow-route-title {
color: var(--hf-accent-green);
}
.hf-workflow-route video {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
margin: 0;
border-radius: 0.5rem;
background: #000;
object-fit: cover;
pointer-events: none;
}
/* A route with no preview clip: same box, no black rectangle. */
.hf-workflow-route-noclip {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
margin: 0;
border-radius: 0.5rem;
background: color-mix(in srgb, currentColor 8%, transparent);
}
.hf-workflow-route-title {
display: block;
color: var(--hf-heading);
font-weight: 650;
line-height: 1.35;
transition: color 120ms ease;
}
.hf-workflow-route-copy {
display: block;
margin-top: 0.3rem;
color: var(--hf-text-secondary);
font-size: 0.9rem;
line-height: 1.5;
}
@media (max-width: 639px) {
.hf-workflow-routes {
grid-template-columns: 1fr;
}
}
/* Code font — IBM Plex Mono (loaded via Google Fonts above).
*
* Deliberately scoped to real code elements. The previous rule also matched
* [class*="code"] / [class*="Code"], which caught any element whose class
* merely contained that substring — including every Accordion, whose wrapper
* carries the Tailwind utility `dark:bg-codeblock`. That set the whole
* accordion (and, by inheritance, its title and prose) in monospace, so plain
* sentences rendered like terminal output. Syntax tokens inside `pre` inherit
* from `pre`, so they do not need a selector of their own. */
code,
pre,
pre code,
kbd,
samp {
font-family: "IBM Plex Mono", "SF Mono", "Fira Code", monospace;
}
/* ── Code block copy button ── */
/*
* One button, every code block on the site, and all of it is Tailwind
* utilities on the element itself. The shipped bundle has no `--copy-*`
* custom property, no documented class and no docs.json key for it (its only
* button tokens, `--button-*`, belong to the <Button> component, which this
* is not), so there is no supported hook to prefer. `custom.css` is the
* documented extension point; `[data-testid]` is the handle, because a
* testid outlives the utility soup wrapped around it.
*
* What was wrong: the resting icon is `text-gray-400 / dark:text-white/40`,
* which measures 2.37:1 on a catalog page and 2.57:1 on a plain one against
* the surface behind it. Both are under the 3:1 that 1.4.11 asks of a
* control. Dark mode was the better half of the pair at 3.8:1, over the line
* but not by enough to see. It sat in a 26px box and did not change on
* hover, so a reader could not read it, could not comfortably hit it, and
* was never told it was a control.
*
* What is deliberately left alone: the copied state. Mintlify already swaps
* the clipboard for a check in the brand colour and fills a sibling
* `role="status"` with "Copied" — the announcement pattern — so the rules
* below exclude `.text-primary` instead of restyling it.
*
* Nothing here moves. The plate and the icon change colour over 100ms; there
* is no transform and no keyframe, the same rule the explorer above follows.
*/
.code-block [data-testid="copy-code-button"] {
position: relative;
/* 44x44 of pointer and touch target, given back to the layout by the same
9px it took, so every header keeps its height and the floating variant
keeps its top-3 right-4 anchor. */
width: 44px;
height: 44px;
margin: -9px;
/* The plate is ::before, so the 44px box itself is never painted — the
conditional `bg-gray-100` Mintlify puts on the floating variant would
otherwise render as a 44px slab. */
background-color: transparent;
}
/* The plate: 26px, the size the button used to be. ::before precedes the
<svg> in the box tree, so it paints under the icon without a z-index. */
.code-block [data-testid="copy-code-button"]::before {
content: "";
position: absolute;
inset: 9px;
border-radius: 6px;
background-color: transparent;
transition: background-color 100ms ease;
}
.code-block [data-testid="copy-code-button"]:hover::before {
background-color: color-mix(in srgb, var(--hf-text) 10%, transparent);
}
/* `:not(.text-primary)` is the resting icon only; the check keeps Mintlify's
own colour. Two classes and an attribute because `dark:text-white/40` is
`.dark .text-white\/40`, and a shorter selector silently loses to it. */
.code-block [data-testid="copy-code-button"] svg:not(.text-primary) {
color: var(--hf-text-secondary);
transition: color 100ms ease;
}
.code-block [data-testid="copy-code-button"]:hover svg:not(.text-primary) {
color: var(--hf-text);
}
/* The ring sits on the element that has focus, not on the plate, and is
pulled inside the 44px target so it reads as a ring around the icon
rather than a box floating clear of it. */
.code-block [data-testid="copy-code-button"]:focus-visible {
border-radius: 14px;
outline: 2px solid var(--hf-brand);
outline-offset: -6px;
}
/* ── Install command copy button ── */
/*
* The command itself is a bare <code>, so it inherits the chrome Mintlify puts
* on every inline code span: a translucent plate and a 6px radius. Inside this
* control that plate is a second rounded rectangle in a slightly different
* tone, and its two right-hand corners let the row's own background through —
* which reads as a gap between the field and the button. The layout was never
* gapped; the elements are flush (no flex gap, no margin). Drop the inherited
* plate and the field and the button become one surface, divided by the
* field's 1px border-right and nothing else. That divider lives on the field
* rather than on the button because the focus ring rounds the button to 14px,
* which would bend a border on that edge out of sight while it is focused.
*/
.hf-install-command code {
background: none;
border-radius: 0;
border-color: var(--hf-ui-border) !important;
color: var(--hf-heading) !important;
}
/*
* The catalog page's own copy control, `snippets/install-command.jsx`. It
* draws Mintlify's clipboard and check icons, so it is styled from the same
* tokens as the sitewide button above and kept next to it: one visual
* language for the two copy affordances a reader meets on the same page.
*
* The button is the whole 44px cell rather than a plate inside a larger box,
* because here the row it sits in has a border and a background of its own —
* the cell is already a shape, so lighting it is the hover.
*/
.hf-install-copy {
display: grid;
place-items: center;
flex-shrink: 0;
width: 44px;
background-color: transparent;
transition: background-color 100ms ease;
}
.hf-install-copy:hover {
background-color: color-mix(in srgb, var(--hf-text) 10%, transparent);
}
/* Both icons occupy the same cell, so the swap is a crossfade in place and
nothing in the row moves or resizes. */
.hf-install-copy > svg {
grid-area: 1 / 1;
color: var(--hf-text-secondary);
transition:
opacity 180ms ease,
color 100ms ease;
}
.hf-install-copy:hover > svg {
color: var(--hf-text);
}
.hf-install-copy > .hf-install-copy-check {
opacity: 0;
}
.hf-install-copy[data-copied="true"] > .hf-install-copy-clipboard {
opacity: 0;
}
/* Brand green, the colour Mintlify's own check is drawn in. The selector
carries one more class than the `:hover` rule above so the check keeps its
colour while the pointer is still on the button it was just clicked with. */
.hf-install-copy[data-copied="true"] > .hf-install-copy-check {
opacity: 1;
color: var(--hf-brand);
}
@media (prefers-reduced-motion: reduce) {
.hf-install-copy > svg {
transition-duration: 0s;
}
}
.hf-install-copy:focus-visible {
outline: 2px solid var(--hf-brand);
outline-offset: -6px;
border-radius: 14px;
}
/* The live region that says "Copied". Visually hidden rather than
`display: none`, which would take it out of the accessibility tree. */
.hf-install-copy-status {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
/* ── Selection ── */
::selection {
background: var(--hf-selection-bg);
}
/* ── Links ── */
#content-area :where(p, li, td, blockquote) a:not([class]) {
border-bottom: 1px solid color-mix(in srgb, var(--hf-brand) 72%, transparent);
color: inherit;
text-decoration: none;
}
#content-area :where(p, li, td, blockquote) a:not([class]):hover {
border-bottom-color: var(--hf-brand);
color: var(--hf-brand);
}
/* ── Documentation navigation ── */
/*
* Keep Aspen's full-width header, but place its desktop controls on one row:
* logo → section tabs → search → actions. Mobile keeps Mintlify's layout.
*/
@media (min-width: 1024px) {
#navbar {
height: 3rem;
}
#navbar > div:has(.nav-tabs) {
display: grid;
grid-template-columns: max-content max-content minmax(10.25rem, 1fr) max-content;
column-gap: 1rem;
align-items: center;
height: 3rem;
}
#navbar > div:has(.nav-tabs) > .relative,
#navbar > div:has(.nav-tabs) > .relative > div:first-child,
#navbar > div:has(.nav-tabs) > .relative > div:first-child > div:first-child {
display: contents;
}
#navbar > div:has(.nav-tabs) > .relative > div:first-child > div:first-child > div:first-child {
grid-column: 1;
grid-row: 1;
}
#navbar div:has(> .nav-tabs) {
grid-column: 2;
grid-row: 1;
height: 3rem;
padding: 0;
}
#navbar .nav-tabs {
align-items: center;
gap: 0.25rem;
height: 3rem;
}
/* Use the same quiet pill treatment as Mintlify's own documentation. */
#navbar .nav-tabs-item {
height: 2.25rem !important;
padding: 0 0.8rem;
border-radius: 999px;
color: var(--hf-text);
transition:
background-color 140ms ease,
color 140ms ease;
}
#navbar .nav-tabs-item:hover {
background: color-mix(in srgb, var(--hf-heading) 6%, transparent);
color: var(--hf-heading);
}
#navbar .nav-tabs-item[aria-current] {
background: var(--hf-brand-soft);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hf-brand) 55%, transparent);
color: var(--hf-heading) !important;
font-weight: 600;
}
#navbar .nav-tabs-item:focus:not(:focus-visible) {
outline: none;
}
#navbar .nav-tabs-item > .absolute.bottom-0 {
display: none;
}
#navbar div:has(> #search-bar-entry) {
grid-column: 3;
grid-row: 1;
min-width: 0;
}
#navbar .topbar-right-container {
grid-column: 4;
grid-row: 1;
}
#sidebar-content {
top: 3rem !important;
height: calc(100vh - 3rem) !important;
}
/* Keep the repository compact, but retain its useful live star count. */
#navbar a[title="heygen-com/hyperframes"] {
width: 7.5rem;
min-width: 7.5rem;
height: 2.25rem;
padding: 0 0.75rem;
justify-content: center;
}
#navbar a[title="heygen-com/hyperframes"] > span.truncate {
display: none;
}
#navbar a[title="heygen-com/hyperframes"] > span:not(.truncate) {
display: flex !important;
color: var(--hf-heading);
font-variant-numeric: tabular-nums;
}
/*
* Mintlify removes the live count for roughly one animation frame during
* client-side navigation. Keep a truthful placeholder in its place so the
* control does not collapse while the live count reloads.
*/
#navbar a[title="heygen-com/hyperframes"]:not(:has(> span:not(.truncate)))::after {
color: var(--hf-heading);
content: "★";
font-variant-numeric: tabular-nums;
}
}
/* The native gutter was almost 15px wide. Keep the rail quiet and compact. */
#navigation-items {
scrollbar-color: color-mix(in srgb, var(--hf-text) 30%, transparent) transparent;
scrollbar-gutter: auto !important;
scrollbar-width: thin;
}
#navigation-items::-webkit-scrollbar {
width: 5px;
}
#navigation-items::-webkit-scrollbar-track {
background: transparent;
}
#navigation-items::-webkit-scrollbar-thumb {
border-radius: 999px;
background: color-mix(in srgb, var(--hf-text) 30%, transparent);
}
#navigation-items::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--hf-text) 46%, transparent);
}
/* Preserve a useful search field on smaller desktop widths. */
@media (min-width: 1024px) and (max-width: 1199px) {
#navbar #assistant-entry {
display: none;
}
}
/* Every structural hairline (header bottom, content rules, footer) is the palette's line,
* never a light gray that would draw a pale stripe on the paper. */
[class*="border-gray-200"],
[class*="border-gray-100"] {
border-color: var(--hf-ui-border) !important;
}
div.h-px.bg-gray-100 {
background-color: var(--hf-ui-border) !important;
}
/* Keep the floating agent input noticeable against the page background. */
#body-content .chat-assistant-floating-input > div > div {
border-color: var(--hf-border-color-light) !important;
background-color: var(--hf-background-light) !important;
box-shadow: var(--hf-floating-input-shadow);
}
/*
* Match the navigation rhythm and active-page rail used on the main docs.
* Each link owns one rail segment, so the current page can highlight only
* its segment. These rules are visual only; groups remain non-collapsible.
*/
#navigation-items .sidebar-group-header {
color: var(--hf-text);
font-size: 0.875rem;
font-weight: 500;
line-height: 1.25rem;
}
#navigation-items .sidebar-group {
padding-left: 0;
}
#navigation-items .sidebar-group::before {
content: none;
}
#navigation-items .sidebar-group > li {
margin-bottom: 0;
}
#navigation-items .sidebar-group > li + li {
margin-top: 0 !important;
}
#navigation-items .sidebar-group > li > a {
width: calc(100% - 1rem);
margin-left: 1rem;
padding: 0.375rem 0.75rem 0.375rem 1rem;
border-left: 1px solid var(--hf-sidebar-rail);
border-radius: 0;
background: transparent !important;
color: var(--hf-sidebar-text);
}
#navigation-items .sidebar-group > li > a:hover {
background: transparent !important;
color: var(--hf-heading);
}
#navigation-items .sidebar-group > li[data-active="true"] > a,
#navigation-items .sidebar-group > li[data-active-nav-item="true"] > a,
#navigation-items .sidebar-group > li > a[aria-current="page"] {
border-left-color: currentColor;
background: var(--hf-chip) !important;
border-radius: 0 999px 999px 0;
color: var(--hf-heading);
font-weight: 500;
}
/* Aspen inserts horizontal separators; main uses the same space without a rule. */
#navigation-items div:has(> .sidebar-group) + div {
height: 2rem;
padding: 0;
}
#navigation-items div:has(> .sidebar-group) + div > * {
display: none;
}
/*
* Aspen assumes a 96px header and fades scrolled navigation before it reaches
* that boundary. Our header is 48px; align the sticky sidebar to it and let
* links clip exactly at the header instead of disappearing early.
*/
#navigation-items,
#navigation-items [data-id] {
-webkit-mask-image: none !important;
mask-image: none !important;
}
/* Catalog texture examples */
.hf-texture-preview-panel {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
margin: 24px 0 40px;
}
.hf-texture-preview-card {
min-width: 0;
border: 1px solid rgba(127, 127, 127, 0.22);
border-radius: 8px;
padding: 16px;
background: #101010;
}
.hf-texture-preview-label {
margin-bottom: 12px;
color: rgba(255, 255, 255, 0.6);
font-size: 12px;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.hf-texture-preview-shadow {
filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.48));
}
.hf-texture-preview-word {
color: #fff;
font-family: Impact, "Arial Black", sans-serif;
font-size: 42px;
line-height: 0.9;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
-webkit-mask-image: var(--mask-url);
mask-image: var(--mask-url);
-webkit-mask-size: cover;
mask-size: cover;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-mode: luminance;
mask-mode: luminance;
}
.hf-texture-animate-demo {
border: 1px solid rgba(127, 127, 127, 0.22);
border-radius: 8px;
padding: 22px;
margin: 20px 0 24px;
background: linear-gradient(90deg, rgba(255, 255, 255, 0.54) 1px, transparent 1px), #f1f1f1;
background-size: 44px 100%;
}
.hf-texture-animate-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 18px;
}
.hf-texture-animate-label {
min-width: 0;
color: rgba(24, 24, 24, 0.62);
font-size: 13px;
line-height: 1.2;
}
.hf-texture-animate-class {
max-width: 62%;
padding: 2px 6px;
border: 1px solid rgba(24, 24, 24, 0.12);
border-radius: 6px;
background: rgba(255, 255, 255, 0.5);
color: rgba(24, 24, 24, 0.78);
font-size: 11px;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.hf-texture-animate-shadow {
filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.48));
}
.hf-texture-animate-word {
color: #181818;
font-family: Impact, "Arial Black", sans-serif;
font-size: 92px;
line-height: 0.9;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
-webkit-mask-image: var(--mask-url);
mask-image: var(--mask-url);
-webkit-mask-size: 180% 180%;
mask-size: 180% 180%;
-webkit-mask-position: 0% 50%;
mask-position: 0% 50%;
-webkit-mask-mode: luminance;
mask-mode: luminance;
animation: hf-texture-mask-pan 2.1s ease-in-out infinite alternate;
}
@keyframes hf-texture-mask-pan {
from {
-webkit-mask-position: 0% 50%;
mask-position: 0% 50%;
}
to {
-webkit-mask-position: 100% 50%;
mask-position: 100% 50%;
}
}
.hf-texture-example-groups {
display: grid;
gap: 32px;
margin: 20px 0 40px;
}
.hf-texture-example-groups > div,
.hf-texture-example-card {
min-width: 0;
}
.hf-texture-example-title {
margin: 0 0 10px;
font-size: 14px;
font-weight: 600;
}
.hf-texture-example-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
gap: 16px;
}
.hf-texture-example-card {
border: 1px solid rgba(127, 127, 127, 0.22);
border-radius: 8px;
padding: 20px;
background: #f1f1f1;
}
.hf-texture-example-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 14px;
}
.hf-texture-example-label {
min-width: 0;
color: rgba(24, 24, 24, 0.62);
font-size: 13px;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.hf-texture-example-class {
max-width: 62%;
padding: 2px 6px;
border: 1px solid rgba(24, 24, 24, 0.12);
border-radius: 6px;
background: rgba(255, 255, 255, 0.5);
color: rgba(24, 24, 24, 0.78);
font-size: 11px;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.hf-texture-example-shadow {
filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.48));
}
.hf-texture-example-word {
color: #181818;
font-family: Impact, "Arial Black", sans-serif;
font-size: 54px;
line-height: 0.9;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
-webkit-mask-image: var(--mask-url);
mask-image: var(--mask-url);
-webkit-mask-size: cover;
mask-size: cover;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-mode: luminance;
mask-mode: luminance;
}
.hf-texture-example-usage {
display: flex;
align-items: flex-start;
gap: 6px;
min-width: 0;
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid rgba(24, 24, 24, 0.1);
color: rgba(24, 24, 24, 0.56);
font-size: 12px;
line-height: 1.3;
}
.hf-texture-example-usage code {
min-width: 0;
color: rgba(24, 24, 24, 0.82);
font-size: 11px;
line-height: 1.3;
white-space: normal;
overflow-wrap: anywhere;
}
/* Portrait proof clips should read as examples inside the page, not become the
* page. Landscape films keep the full content width; only explicitly marked
* portrait media gets this compact, centered treatment. */
.hf-portrait-video {
display: block;
width: auto;
max-width: min(100%, 18rem);
max-height: min(32rem, 68vh);
margin: 0.75rem auto 0;
border-radius: 0.5rem;
background: #111;
}
/* Full narrated films use a quiet custom control layer over the native video
* engine. Preview loops remain plain muted videos. */
.hf-docs-video-block {
width: 100%;
}
.hf-docs-video-block[data-portrait="true"] {
width: min(100%, 18rem);
margin: 0.75rem auto 0;
}
.hf-docs-video-block[data-portrait="true"] .hf-docs-video {
aspect-ratio: 9 / 16;
max-height: min(32rem, 68vh);
}
/*
* Mintlify loads custom React snippets after the page shell. Reserve the
* film's real shape so the unloaded component never flashes as a thin Frame
* rail, then let the hydrated player and chapter guide size themselves.
*/
.hf-docs-video-frame {
width: 100%;
aspect-ratio: 16 / 9;
overflow: hidden;
border-radius: 0.75rem;
background: #070707;
}
.hf-docs-video-frame:has(.hf-docs-video-block) {
aspect-ratio: auto;
overflow: visible;
border-radius: 0;
background: transparent;
}
.hf-docs-video {
position: relative;
aspect-ratio: 16 / 9;
overflow: hidden;
border-radius: 0.75rem;
background: #070707;
color: #fff;
isolation: isolate;
outline: none;
}@media (max-width: 720px) {}
@media (max-width: 520px) {}
.hf-docs-video:focus-visible {
box-shadow: 0 0 0 3px color-mix(in srgb, var(--hf-video-accent) 78%, transparent);
}
.hf-docs-video video {
display: block;
width: 100%;
height: 100%;
margin: 0 !important;
background: #070707;
object-fit: contain;
cursor: pointer;
}
.hf-docs-video-hero-play {
position: absolute;
top: 50%;
left: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 3.35rem;
height: 3.35rem;
padding: 0;
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: 50%;
background: rgba(8, 8, 8, 0.56);
color: #fff;
font: inherit;
cursor: pointer;
transform: translate(-50%, -50%);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
z-index: 3;
}
.hf-docs-video-hero-play:hover {
border-color: var(--hf-video-accent);
background: rgba(8, 8, 8, 0.78);
}
.hf-docs-video-hero-play:focus-visible,
.hf-docs-video-control:focus-visible,
.hf-docs-video-rate:focus-visible,
.hf-docs-video-progress:focus-visible {
outline: 2px solid var(--hf-video-accent);
outline-offset: 2px;
}
.hf-docs-video-hero-icon {
display: grid;
width: 2rem;
height: 2rem;
flex: 0 0 auto;
place-items: center;
border-radius: 0;
background: transparent;
color: #fff;
}
.hf-docs-video-hero-icon svg {
width: 1.25rem;
height: 1.25rem;
margin-left: 0.1rem;
fill: currentColor;
}
.hf-docs-video-controls {
position: absolute;
right: 0;
bottom: 0;
left: 0;
display: grid;
gap: 0.45rem;
padding: 3.75rem 1rem 0.78rem;
background: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.84));
opacity: 1;
transform: translateY(0);
visibility: visible;
transition:
opacity 160ms ease,
transform 160ms ease,
visibility 0s linear;
z-index: 2;
}
.hf-docs-video-controls[data-visible="false"] {
pointer-events: none;
opacity: 0;
transform: translateY(0.4rem);
visibility: hidden;
transition:
opacity 160ms ease,
transform 160ms ease,
visibility 0s linear 160ms;
}
.hf-docs-video-progress {
width: 100%;
height: 1rem;
margin: 0;
border: 0;
background: transparent;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
}
/* Timecode bubble that tracks the pointer along the progress bar. It is a label,
not a thumbnail: rendering a second <video> here made every page with a film
download the whole file twice. */
.hf-docs-video-scrub-preview {
position: absolute;
bottom: 3.6rem;
left: clamp(2rem, var(--hf-video-preview-x), calc(100% - 2rem));
border-radius: 0.35rem;
background: rgba(0, 0, 0, 0.82);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.38);
pointer-events: none;
opacity: 1;
transform: translate(-50%, 0);
transition:
opacity 120ms ease,
transform 120ms ease;
z-index: 4;
}
.hf-docs-video-scrub-preview[data-visible="false"] {
visibility: hidden;
opacity: 0;
transform: translate(-50%, 0.3rem);
}
.hf-docs-video-scrub-preview span {
display: block;
padding: 0.16rem 0.4rem;
color: #fff;
font-variant-numeric: tabular-nums;
font-size: 0.7rem;
line-height: 1.2;
}
.hf-docs-video-progress::-webkit-slider-runnable-track {
height: 0.22rem;
border-radius: 999px;
background: linear-gradient(
to right,
var(--hf-video-accent) 0,
var(--hf-video-accent) var(--hf-video-progress),
rgba(255, 255, 255, 0.34) var(--hf-video-progress),
rgba(255, 255, 255, 0.34) 100%
);
}
.hf-docs-video-progress::-moz-range-track {
height: 0.22rem;
border-radius: 999px;
background: rgba(255, 255, 255, 0.34);
}
.hf-docs-video-progress::-moz-range-progress {
height: 0.22rem;
border-radius: 999px;
background: var(--hf-video-accent);
}
.hf-docs-video-progress::-webkit-slider-thumb {
width: 0.85rem;
height: 0.85rem;
margin-top: -0.315rem;
border: 2px solid #121212;
border-radius: 50%;
background: var(--hf-video-accent);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
appearance: none;
-webkit-appearance: none;
}
.hf-docs-video-progress::-moz-range-thumb {
width: 0.85rem;
height: 0.85rem;
border: 2px solid #121212;
border-radius: 50%;
background: var(--hf-video-accent);
}
.hf-docs-video-control-row {
display: flex;
align-items: center;
gap: 0.3rem;
min-width: 0;
}
.hf-docs-video-control,
.hf-docs-video-rate {
display: grid;
height: 2rem;
min-width: 2rem;
padding: 0;
place-items: center;
border: 0;
border-radius: 0.45rem;
background: transparent;
color: rgba(255, 255, 255, 0.92);
font: inherit;
cursor: pointer;
}
.hf-docs-video-control:hover,
.hf-docs-video-rate:hover {
background: rgba(255, 255, 255, 0.13);
color: #fff;
}
.hf-docs-video-control svg {
width: 1.2rem;
height: 1.2rem;
fill: currentColor;
}
.hf-docs-video-rate {
min-width: 2.75rem;
padding: 0 0.45rem;
font-size: 0.75rem;
font-weight: 650;
}
.hf-docs-video-time {
margin-left: 0.2rem;
color: rgba(255, 255, 255, 0.82);
font-variant-numeric: tabular-nums;
font-size: 0.74rem;
line-height: 1;
white-space: nowrap;
}
.hf-docs-video-time span {
color: rgba(255, 255, 255, 0.46);
}
.hf-docs-video-spacer {
flex: 1 1 auto;
}
.hf-docs-video-spinner {
position: absolute;
top: 50%;
left: 50%;
width: 2rem;
height: 2rem;
margin: -1rem 0 0 -1rem;
border: 2px solid rgba(255, 255, 255, 0.28);
border-top-color: var(--hf-video-accent);
border-radius: 50%;
animation: hf-docs-video-spin 700ms linear infinite;
z-index: 3;
}
@keyframes hf-docs-video-spin {
to {
transform: rotate(360deg);
}
}
@media (max-width: 520px) {
.hf-docs-video-hero-play {
width: 3rem;
height: 3rem;
}
.hf-docs-video-hero-icon {
width: 2rem;
height: 2rem;
}
.hf-docs-video-controls {
gap: 0.25rem;
padding: 2.75rem 0.6rem 0.42rem;
}
.hf-docs-video-scrub-preview {
bottom: 3.2rem;
}
.hf-docs-video-time {
margin-left: 0;
font-size: 0.67rem;
}
.hf-docs-video-rate {
min-width: 2.45rem;
padding: 0 0.25rem;
}
}
@media (prefers-reduced-motion: reduce) {
.hf-docs-video-controls {
transition: none;
}
.hf-docs-video-spinner {
animation: none;
}
.hf-docs-video-scrub-preview {
transition: none;
}
}
@media (max-width: 860px) {
.hf-texture-preview-panel {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 520px) {
.hf-texture-preview-panel {
grid-template-columns: 1fr;
}
.hf-texture-preview-word {
font-size: 40px;
}
.hf-texture-animate-meta {
align-items: flex-start;
flex-direction: column;
}
.hf-texture-animate-class {
max-width: 100%;
}
.hf-texture-animate-word {
font-size: 56px;
}
}
@media (prefers-reduced-motion: reduce) {
.hf-texture-animate-word {
animation: none;
}
}
/* Hide the section/group label ("Start here", etc.) that the theme renders
* above every page title. It repeats the sidebar grouping and adds noise on
* every page; each page leads with its own H1 instead. */
.eyebrow {
display: none;
}
/* ── UX-pass tweaks (Ular): brand the Playground CTA, align the logo ── */
@media (min-width: 1024px) {
/* Line the logo up with the sidebar text (was flush at the navbar padding, 16px further left). */
#navbar a[href*="/introduction"] {
margin-left: 16px;
}
/* The Download pill is ink with paper text, like hyperframes.dev's `.sr-pill`. */
#navbar a.group > span.bg-primary-dark {
background: var(--hf-heading) !important;
border-radius: 999px;
}
#navbar a.group:has(> span.bg-primary-dark),
#navbar a.group:has(> span.bg-primary-dark) span:not(.bg-primary-dark),
#navbar a.group:has(> span.bg-primary-dark) svg {
color: var(--hf-background) !important;
font-weight: 700;
}
}
/* Frame mode (every catalog page) renders no `main#content-container`, so it loses
* that element's `px-5 lg:pr-10 lg:pl-[5.5rem]` and sits flush against the sidebar.
* These are those same values, nothing new. */
header.is-frame ~ #body-content #content-area {
padding-left: 1.25rem;
padding-right: 1.25rem;
}
@media (min-width: 1024px) {
header.is-frame ~ #body-content #content-area {
padding-left: 5.5rem;
padding-right: 2.5rem;
}
}
/* An image set beside the text it explains (magazine style); full width on narrow screens. */
.hf-aside {
float: right;
width: 46%;
margin: 0.25rem 0 1rem 1.5rem;
border-radius: 0.5rem;
border: 1px solid rgb(0 0 0 / 0.08);
}
.dark .hf-aside {
border-color: rgb(255 255 255 / 0.1);
}
@media (max-width: 640px) {
.hf-aside {
float: none;
width: 100%;
margin: 0.5rem 0 1rem;
}
}
/* A row of portrait films with a caption under each (explainer styles and similar) */
.hf-shelf { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; margin: 1.25rem 0 2rem; }
.hf-shelf p { margin: 0.5rem 0 0; font-size: 0.875rem; line-height: 1.45; }
@media (max-width: 640px) { .hf-shelf { grid-template-columns: minmax(0, 1fr); } }
/* Two results side by side (comparisons) */
.hf-versus { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; margin: 1.25rem 0; }
.hf-versus p { margin: 0 0 0.4rem; font-size: 0.9375rem; }
@media (max-width: 640px) { .hf-versus { grid-template-columns: minmax(0, 1fr); } }
/* Short looping clips that show where a control is, floated beside the text that names it */
.hf-spot { aspect-ratio: 16 / 10; object-fit: cover; border-radius: 0.6rem; background: rgb(0 0 0 / 0.06);
box-shadow: 0 0 0 1px rgb(0 0 0 / 0.08); margin: 0.25rem 0 1rem 1.25rem; }
.dark .hf-spot { box-shadow: 0 0 0 1px rgb(255 255 255 / 0.1); }
h2 { clear: both; }
.hf-spot.hf-spot-inline { width: 100%; margin: 0; }
/* The header is frosted glass over the paper. */
#navbar > div.bg-background-light {
background: var(--hf-glass) !important;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
@media (min-width: 1024px) {
#navbar .nav-tabs-item.text-primary {
background: var(--hf-chip);
}
}
/* Headlines: hyperframes.dev's heavy, tight TT Norms. */
#page-title {
font-size: clamp(2.25rem, 4vw, 3.5rem);
font-weight: 700;
line-height: 1.02;
letter-spacing: -0.045em;
color: var(--hf-heading);
}
#content-area :is(h2, h3) {
color: var(--hf-heading);
}
#content-area h2 {
font-weight: 700;
letter-spacing: -0.035em;
}
/* The page's one-line description reads like hyperframes.dev's subtitle: light and larger. */
div:has(> div > #page-title) + .prose > p {
font-size: 1.375rem;
font-weight: 300;
line-height: 1.35;
letter-spacing: -0.02em;
color: var(--hf-heading);
}
/* Cards are the app's cards on the paper: near-white, hairline, its card shadow. */
html:not(.dark) #content-area .card {
background: var(--hf-background-light) !important;
border-color: var(--hf-ui-border) !important;
box-shadow: var(--hf-floating-input-shadow);
}
/* Calm callouts are a card on the paper (a Night card in dark mode); their icon keeps its colour.
* Warnings and danger keep Mintlify's tint so they still stand out. */
.callout:is([data-callout-type="note"], [data-callout-type="info"], [data-callout-type="tip"], [data-callout-type="check"]) {
background: var(--hf-background-light) !important;
border-color: var(--hf-ui-border) !important;
color: var(--hf-text) !important;
}
.callout:is([data-callout-type="note"], [data-callout-type="info"], [data-callout-type="tip"], [data-callout-type="check"]) :where(p, div, code) {
color: inherit !important;
}
/* Catalog pages draw with their own --ve-* greys; on the paper they take the app's values. */
html:not(.dark) .hf-ve {
--ve-fg: var(--hf-text);
--ve-muted: var(--hf-text-secondary);
--ve-line: var(--hf-border-color-light);
--ve-surface: var(--hf-background-light);
--ve-sunken: var(--hf-background);
--ve-hover: var(--hf-chip);
--ve-on-bg: var(--hf-heading);
--ve-on-fg: var(--hf-background);
--ve-ring: var(--hf-border-color-light);
}
/* ── One palette for every colour on the page ──
* Mintlify draws text, borders, fills and step markers from its gray scale; these are the
* same lightness steps on the Studio app's warm hue (oklch chroma 0.006, hue 70), so
* gray-900 is the app's --ink. Shared by light and dark mode. */
:root {
--gray-50: 246 242 239;
--gray-100: 241 237 234;
--gray-200: 226 222 219;
--gray-300: 209 205 202;
--gray-400: 162 159 155;
--gray-500: 114 112 108;
--gray-600: 82 80 77;
--gray-700: 65 63 60;
--gray-800: 39 37 34;
--gray-900: 25 23 20;
--gray-950: 12 10 8;
/* Read by snippets that fall back to neutral greys. */
--border-color: var(--hf-border-color);
--code-block-background: var(--hf-code-bg);
}
/* In light mode the mid grays go darker so small text passes 4.5:1 (icons 3:1) on the paper:
* the app's gray-500 step would read 4.3:1 there. */
html:not(.dark) {
--gray-400: 108 105 102;
--gray-500: 80 77 74;
--gray-600: 67 65 62;
}
/* Article text: the typography plugin's cool grays become the same tokens. */
.prose {
--tw-prose-body: var(--hf-text);
--tw-prose-headings: var(--hf-heading);
--tw-prose-lead: var(--hf-text-secondary);
--tw-prose-links: var(--hf-heading);
--tw-prose-bold: var(--hf-heading);
--tw-prose-counters: var(--hf-text-secondary);
--tw-prose-bullets: var(--hf-text-tertiary);
--tw-prose-hr: var(--hf-border-color);
--tw-prose-quotes: var(--hf-heading);
--tw-prose-quote-borders: var(--hf-border-color);
--tw-prose-captions: var(--hf-text-secondary);
--tw-prose-code: var(--hf-heading);
--tw-prose-th-borders: var(--hf-border-color-light);
--tw-prose-td-borders: var(--hf-border-color);
--tw-prose-invert-body: var(--hf-text);
--tw-prose-invert-headings: var(--hf-heading);
--tw-prose-invert-lead: var(--hf-text-secondary);
--tw-prose-invert-links: var(--hf-heading);
--tw-prose-invert-bold: var(--hf-heading);
--tw-prose-invert-counters: var(--hf-text-secondary);
--tw-prose-invert-bullets: var(--hf-text-tertiary);
--tw-prose-invert-hr: var(--hf-border-color);
--tw-prose-invert-quotes: var(--hf-heading);
--tw-prose-invert-quote-borders: var(--hf-border-color);
--tw-prose-invert-captions: var(--hf-text-secondary);
--tw-prose-invert-code: var(--hf-heading);
--tw-prose-invert-th-borders: var(--hf-border-color-light);
--tw-prose-invert-td-borders: var(--hf-border-color);
}
html.dark .hf-ve {
--ve-fg: #f5f3f1;
--ve-muted: #b8b6b4;
--ve-line: rgb(245 243 241 / 0.1);
--ve-surface: #272522;
--ve-sunken: #24211e;
--ve-hover: #2f2c29;
--ve-on-bg: #f5f3f1;
--ve-on-fg: #201e1c;
--ve-ring: rgb(245 243 241 / 0.16);
}
/* Scrollbars, the install box and other small chrome take the same tokens. */
[data-component-part="scroll-area-scrollbar"] {
background: var(--hf-chip) !important;
}
[data-component-part="scroll-area-scrollbar"] > div {
background: color-mix(in srgb, var(--hf-heading) 28%, transparent) !important;
}
.hf-install-command {
border-color: var(--hf-ui-border) !important;
background: var(--hf-code-bg) !important;
}
/* Body copy in dark mode is the app's second ink, not Mintlify's dim gray-400. */
.dark .mdx-content {
color: var(--hf-text);
}
/* Footer links and "Powered by" read at the secondary ink (Mintlify's 50% ink fails on the paper). */
#footer a,
#footer :where(p, span, div) {
color: var(--hf-text-secondary);
}
#footer a:hover {
color: var(--hf-heading);
}
/* Table rules use the same lines: the header rule a touch stronger than the rows. */
#content-area thead {
border-bottom-color: var(--hf-border-color-light) !important;
}
#content-area tbody tr {
border-bottom-color: var(--hf-ui-border) !important;
}
/* ── Code colours: the browser editor's (packages/studio theme.css --color-code-*) ──
* Mintlify highlights code with fixed themes (GitHub light, VS Code dark) and its hosted build ignores a custom
* code theme, so each of those themes' colours is mapped by role to the editor's colour for the same role. */
/* Plain code text (GitHub light's default ink) is the page ink. */
html:not(.dark) pre [style*="color: rgb(31, 35, 40)"],
html:not(.dark) pre[style*="color: rgb(31, 35, 40)"] {
color: var(--hf-text) !important;
}
html:not(.dark) pre span[style*="color: rgb(10, 48, 105)"] {
color: oklch(0.468 0.142 143) !important;
}
html:not(.dark) pre span[style*="color: rgb(207, 34, 46)"] {
color: oklch(0.509 0.211 329) !important;
}
html:not(.dark) pre span[style*="color: rgb(110, 119, 129)"] {
color: oklch(0.48 0.009 279) !important;
}
html:not(.dark) pre span[style*="color: rgb(130, 80, 223)"],
html:not(.dark) pre span[style*="color: rgb(149, 56, 0)"] {
color: oklch(0.492 0.193 263) !important;
}
html:not(.dark) pre span[style*="color: rgb(5, 80, 174)"] {
color: oklch(0.495 0.13 50) !important;
}
html:not(.dark) pre span[style*="color: rgb(17, 99, 41)"] {
color: oklch(0.48 0.12 92) !important;
}
.dark pre span[style*="--shiki-dark: #CE9178"] {
color: oklch(0.793 0.11 133) !important;
}
.dark pre span[style*="--shiki-dark: #569CD6"],
.dark pre span[style*="--shiki-dark: #C586C0"] {
color: oklch(0.829 0.164 318) !important;
}
.dark pre span[style*="--shiki-dark: #DCDCAA"] {
color: oklch(0.805 0.121 245) !important;
}
.dark pre span[style*="--shiki-dark: #9CDCFE"] {
color: oklch(0.856 0.145 17) !important;
}
.dark pre span[style*="--shiki-dark: #6A9955"] {
color: oklch(0.806 0.03 262) !important;
}
.dark pre span[style*="--shiki-dark: #B5CEA8"],
.dark pre span[style*="--shiki-dark: #4FC1FF"] {
color: oklch(0.815 0.11 50) !important;
}
.dark pre span[style*="--shiki-dark: #D7BA7D"] {
color: oklch(0.805 0.1 92) !important;
}
.dark pre span[style*="--shiki-dark: #808080"] {
color: var(--hf-text-tertiary) !important;
}
/* Code blocks sit on the code token (frosted cream in light mode, the Night field in dark), not the theme's own. */
[class*="dark:bg-codeblock"],
html.dark body .code-block-background,
.code-block {
background-color: var(--hf-code-bg) !important;
}
pre.shiki {
background-color: transparent !important;
}
/* The fade that hides long lines under the copy button fades into the same code token. */
.code-block-fade-overlay {
background-image: linear-gradient(to right, transparent, var(--hf-code-bg) 24px) !important;
}
/* 30 Days: a numbered syllabus, one row per lesson, the film previews on hover */
.hf-days { list-style: none; margin: 1rem 0 2rem; padding: 0; border-top: 1px solid var(--hf-ui-border); }
.hf-day { display: grid; grid-template-columns: 3.25rem minmax(0, 1fr) 10.5rem; gap: 1.25rem; align-items: center;
padding: 0.9rem 0; border-bottom: 1px solid var(--hf-ui-border); margin: 0; }
.hf-day-n { font-size: 1.75rem; font-weight: 600; line-height: 1; letter-spacing: -0.02em; color: var(--hf-text-tertiary);
font-variant-numeric: tabular-nums; }
.hf-day-title { font-weight: 600; font-size: 1rem; color: inherit; text-decoration: none; }
.hf-day-title:hover { text-decoration: underline; text-underline-offset: 3px; }
.hf-day-text p { margin: 0.2rem 0 0; font-size: 0.875rem; line-height: 1.45; color: var(--hf-text-secondary); }
.hf-day-film { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 0.5rem; background: var(--hf-surface2); }
@media (max-width: 640px) {
.hf-day { grid-template-columns: 2.25rem minmax(0, 1fr) 6.5rem; gap: 0.75rem; }
.hf-day-n { font-size: 1.25rem; }
}
.hf-day-play { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; border-radius: 0.5rem; }
.hf-day-play:focus-visible { outline: 2px solid var(--hf-brand); outline-offset: 2px; }
/* Showcase rows: two tracks of films drifting in opposite directions, each track twice its films for a seamless loop. */
.hf-film-rows {
display: grid;
gap: 0.6rem;
margin: 1.25rem 0 1.5rem;
overflow: hidden;
border-radius: 0.6rem;
mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.hf-film-row {
overflow: hidden;
}
.hf-film-track {
display: flex;
width: max-content;
cursor: grab;
/* Vertical swipes still scroll the page; sideways ones drag the row (film-rows.jsx). */
touch-action: pan-y;
}
.hf-film-track.is-dragging {
cursor: grabbing;
user-select: none;
}
.hf-film-card {
position: relative;
height: 11.5rem;
margin: 0 0.6rem 0 0;
padding: 0;
border: 0;
border-radius: 0.5rem;
overflow: hidden;
background: #1a1a1a;
cursor: pointer;
flex: none;
}
.hf-film-card video {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.hf-film-card:focus-visible {
outline: 2px solid var(--hf-brand);
outline-offset: 2px;
}
.hf-film-label {
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 1.2rem 0.6rem 0.45rem;
font-size: 0.72rem;
line-height: 1.25;
text-align: left;
color: #fff;
background: linear-gradient(transparent, rgb(0 0 0 / 0.7));
}
.hf-film-label b {
display: block;
font-weight: 600;
opacity: 0.75;
text-transform: uppercase;
letter-spacing: 0.06em;
font-size: 0.62rem;
}
.hf-film-dialog {
position: fixed;
inset: 0;
margin: auto;
height: fit-content;
width: min(92vw, 1100px);
padding: 0;
border: 0;
border-radius: 0.75rem;
background: #111;
color: #fff;
}
.hf-film-dialog::backdrop {
background: rgb(0 0 0 / 0.7);
}
.hf-film-dialog video {
display: block;
width: 100%;
max-height: 80vh;
background: #000;
}
.hf-film-dialog-bar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
padding: 0.6rem 0.9rem;
font-size: 0.85rem;
}
.hf-film-dialog-bar button {
font: inherit;
color: inherit;
background: transparent;
border: 1px solid rgb(255 255 255 / 0.4);
border-radius: 999px;
padding: 0.25rem 0.8rem;
cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
.hf-film-track {
cursor: auto;
touch-action: auto;
}
.hf-film-row {
overflow-x: auto;
}
}
@media (max-width: 640px) {
.hf-film-card {
height: 9rem;
}
}
.hf-film-pause { display: block; margin: 0.5rem 0 0 auto; padding: 0.25rem 0.75rem; border: 1px solid var(--hf-border-color-light);
border-radius: 999px; font-size: 0.8125rem; font-weight: 600; background: transparent; color: inherit; }
/* Remix shelves are columns that each stack their cards, so cards of different shapes leave no holes. */
.hf-remix-shelf {
columns: 2 16rem;
column-gap: 1rem;
}
.hf-remix-shelf.is-tall {
columns: 3 9.5rem;
}
.hf-remix-shelf > * {
break-inside: avoid;
margin-bottom: 1rem;
}
/* Remix cards in the docs palette: an app card on the paper (a Night card in dark mode), ink text, ink pill. */
.hf-remix-card { background: var(--hf-background-light); border-color: var(--hf-ui-border); backdrop-filter: blur(12px); }
.hf-remix-media { background: var(--hf-surface2); }
.hf-remix-name { color: var(--hf-heading); }
.hf-remix-credit, .hf-remix-help { color: var(--hf-text-secondary); }
.hf-remix-credit a { color: inherit; }
.hf-remix-btn { background: var(--hf-heading); color: var(--hf-background); }
/* Catalog item pages: the title, the standfirst and the Docs tab are written into the page itself
(scripts/generate-catalog-pages.ts), because Mintlify renders snippet components in the browser only and
search engines read the server HTML. CatalogDetail adds the player, tabs and tools around them. */
.hf-ve-static-head { margin: 24px 0 28px; } /* the component's own my-4 (16px) + its header's 8px */
.hf-ve-static-head h1 { margin: 0; font-size: 44px; line-height: 1.1; font-weight: 700; letter-spacing: -0.02em; color: var(--hf-text); }
.hf-ve-static-head p { margin: 12px 0 0; font-size: 18px; line-height: 1.5; color: var(--hf-text-secondary); max-width: 70ch; }
html.dark .hf-ve-static-head h1 { color: #f5f3f1; }
html.dark .hf-ve-static-head p { color: #b8b6b4; }
@media (max-width: 640px) { .hf-ve-static-head h1 { font-size: 32px; } }
/* The Docs tab's text sits after the component and shows only while that tab is open, as the tab's own slot did. */
[data-static-slot] { display: none; }
body:has(.hf-ve-slots[data-tab="docs"]) [data-static-slot="docs"] { display: block; }