/* The site around the catalog on the /ui pages.

   The site's baseline (app/shared/styles/page.css) styles the chrome: the
   topbar, the search palette and the footer are the site's. The package's
   token contract and themes are confined to .ui-root (../styles, written by
   tools/sync-ui-catalog.mjs), so the look picker restyles the catalog and
   nothing around it. What is here: the type rules that keep the page's
   prose in the site's type while the demos take the theme's, the site rules
   that step back inside the catalog, and the page's own pieces. */

/* The site's type, captured above the catalog, where the tokens are still
   the site's, so the prose below can read it after a theme has redefined
   them. The theme's own fonts are captured on .ui-root for the stages. */
body:has(.catalog) {
  --site-sans:    var(--font-sans);
  --site-text-sm: var(--text-sm);
  --site-text-xs: var(--text-xs);
  --site-mono:    var(--font-mono);
  --site-text:    var(--text-base);
  --site-leading: var(--leading-body);
}

.ui-root {
  --theme-body:    var(--font-body);
  --theme-heading: var(--font-heading);
  --theme-ui:      var(--font-ui);
  --theme-mono:    var(--font-mono);
}

/* The page around the demos reads in the site's type at the site's body
   size, as the manual does: the title, the intro, the tree, the toolbar,
   the usage and the reference. The package's scoped body and heading rules
   are layered, so these win inside the catalog. */
.catalog-content,
.ui-root .sidebar,
.ui-root .sidebar-sheet {
  --font-body:    var(--site-sans);
  --font-heading: var(--site-sans);
  --font-ui:      var(--site-sans);
  --font-mono:    var(--site-mono);
  font-family: var(--site-sans);
  font-size:   var(--site-text);
  line-height: var(--site-leading);
}

/* Only what is inside a demo stage takes the theme's fonts, which is the
   point of the toolbar. */
.demo-stage {
  --font-body:    var(--theme-body);
  --font-heading: var(--theme-heading);
  --font-ui:      var(--theme-ui);
  --font-mono:    var(--theme-mono);
  font-family: var(--font-body);
  font-size:   var(--text-base);
  line-height: var(--leading-body);
}

/* Headings as the manual sets them. */
.catalog-content :is(h1, h2, h3, h4) {
  font-family:    var(--site-sans);
  letter-spacing: var(--tracking-tight);
}

.doc-header h1 {
  font-size:      var(--page-title);
  font-weight:    var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  line-height:    var(--leading-none);
}

/* There is no lede: the first paragraph under a title is body text like the
   paragraphs after it, at one width on every /ui page, the site's intro
   width. */
.catalog-content .lede,
.doc-description,
.index-intro p {
  margin:      0;
  max-width:   40rem;
  font-size:   inherit;
  line-height: inherit;
  color:       inherit;
}

.index-intro p + p { margin-top: var(--space-3); }

/* Inline code in the prose is the manual's: monospace, no box. A code
   element a page classes itself (a swatch's token name) keeps its own rules. */
.catalog-content :not(pre):not(.demo-stage *) > code:not([class]) {
  font-family:   var(--site-mono);
  font-size:     0.875em;
  color:         var(--ink);
  background:    none;
  border:        0;
  padding:       0;
  border-radius: 0;
  overflow-wrap: anywhere;
}

/* The site's own rules for toggles, kbd, inline code and the button text
   baseline step back inside the catalog, where those classes and elements
   are the package's. revert-layer hands each property back to the layered
   package styles; the chained class outranks every site toggle selector. */
.ui-root .toggle.toggle.toggle.toggle,
.ui-root .toggle.toggle.toggle.toggle::after {
  all: revert-layer;
}

.ui-root kbd {
  all: revert-layer;
}

.ui-root .demo-stage :not(pre) > code {
  all: revert-layer;
}

.ui-root :where(button, .button) {
  padding-top:    revert-layer;
  padding-bottom: revert-layer;
}

/* The frame runs the width of the window under the full-width topbar: the
   sidebar is a rail anchored to the window's left edge, stuck to the top
   while the page scrolls, and the content centers in the width left. */
.catalog-frame {
  --sidebar-width:  16rem;
  --sidebar-height: 100svh;
}
.catalog-frame > .sidebar { top: 0; }
.catalog-frame > .sidebar[data-variant="sidebar"][data-side="left"] > .sidebar-container {
  border:       0;
  border-right: 1px solid var(--rule);
}
.catalog-nav-head {
  gap:     var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-4);
  /* A rule under the toolbar, so the tree visibly scrolls under it rather
     than folding into it. */
  border-bottom: 1px solid var(--rule);
}
/* The tree fades out at both ends of its scroll, so a half-clipped row
   reads as scrolled away, not cut off, and room under the last row so it
   can scroll clear of the bottom edge. */
.ui-root .sidebar-content {
  padding-top:    var(--space-3);
  padding-bottom: var(--space-12);
  mask-image:     linear-gradient(to bottom, transparent 0, #000 var(--space-5), #000 calc(100% - var(--space-5)), transparent 100%);
}
/* The mode buttons sit over the look select. Their type, size and corners
   are the site's rather than the theme's, so the controls that pick a look
   keep the same shape whatever look they pick. */
.catalog-switcher {
  flex-direction: column;
  align-items:    stretch;
  gap:            var(--space-2);
}
.catalog-switcher .mode-switch {
  display:       flex;
  border-radius: 6px;
}
.catalog-switcher .mode-switch-button { flex: 1; }
.catalog-switcher .mode-switch-button { border-radius: 4px; }
.catalog-switcher .catalog-look select {
  width:          100%;
  height:         2rem;
  border-radius:  6px;
  font-family:    var(--site-sans);
  font-size:      var(--site-text-sm);
  font-weight:    400;
  letter-spacing: normal;
  text-transform: none;
}

/* The tree reads in the site's type at the site's small size in every look. */
.ui-root .sidebar .sidebar-menu-button,
.ui-root .sidebar-sheet .sidebar-menu-button {
  font-family:    var(--site-sans);
  font-size:      var(--site-text-sm);
  font-weight:    400;
  letter-spacing: normal;
  text-transform: none;
}
.ui-root .sidebar .sidebar-group-label,
.ui-root .sidebar-sheet .sidebar-group-label {
  font-family:    var(--site-sans);
  font-size:      var(--site-text-xs);
  letter-spacing: normal;
  text-transform: none;
}
.catalog-search { width: 100%; }
.catalog-nav-tree {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-2);
}
.catalog-nav-empty {
  margin:  0;
  padding: var(--space-2) var(--space-4);
  color:   var(--ink-faint);
}
.catalog-nav-row {
  display:         flex;
  justify-content: flex-end;
}

/* The tree reads as a table of contents: tighter rows than a menu. */
.catalog-nav-tree .sidebar-menu-button {
  height:  1.625rem;
  padding: 0 var(--space-2);
}
.catalog-nav-tree .sidebar-group {
  padding-block: var(--space-2);
}

/* Collapsed to the icon rail, only the trigger stays in the header, and
   the toolbar's rule goes with the toolbar: there is nothing under it. */
.sidebar-wrapper[data-state="collapsed"] .catalog-nav-head {
  border-bottom: 0;
  padding: var(--space-1);
}
.sidebar-wrapper[data-state="collapsed"] .catalog-nav-row { justify-content: center; }
.sidebar-wrapper[data-state="collapsed"] .catalog-nav-head > :not(.catalog-nav-row),
.sidebar-wrapper[data-state="collapsed"] .ui-root .sidebar-content,
.sidebar-wrapper[data-state="collapsed"] .sidebar-content {
  display: none;
}

/* The title sits where every site page's title sits, the page chrome's 4rem
   plus the hero's 2rem below the topbar, with the breadcrumb row above it
   in that space: the row's line, its margin and the header's gap come off
   the top. Every /ui page carries the row, so the title never moves. */
.catalog-page {
  padding: calc(var(--space-16) + var(--space-8) - var(--text-xs) * 1.5 - var(--space-4) - var(--space-3)) var(--space-10) var(--space-24);
}
/* On a phone the sidebar is a sheet, so its trigger sits outside it, in
   the same left rail the collapsed desktop panel is: a bordered column
   with the trigger at the top, beside the page. */
.catalog-phone-bar { display: none; }
@media (max-width: 48rem) {
  /* A small box at the top left holding the trigger; the page runs the
     full width under it. The sheet opens from the box's own corner. */
  .catalog-phone-bar {
    display:         inline-flex;
    align-self:      flex-start;
    border:          1px solid var(--rule);
    border-radius:   6px;
    padding:         var(--space-1);
    margin:          var(--space-4) 1rem;
  }
  .catalog-page {
    min-width: 0;
    padding:   0 1rem var(--space-16);
  }
  /* The title fits the phone instead of running off it. */
  .doc-header h1 { font-size: 2.25rem; overflow-wrap: anywhere; }
}
html:has(.ui-root) { scroll-padding-top: 0; }

/* A template's main example, under the title and before the usage code. */
.doc-main-demo { margin-bottom: var(--space-14); }

/* The reference is the manual page: the whole box is the link. */
.doc-reference {
  display:         flex;
  flex-direction:  column;
  gap:             var(--space-1);
  margin-top:      var(--space-14);
  padding:         var(--space-5) var(--space-6);
  border:          1px solid var(--rule);
  border-radius:   var(--radius-md);
  background:      var(--bg);
  color:           inherit;
  text-decoration: none;
  transition:      border-color 120ms ease, background-color 120ms ease;
}
.doc-reference:hover {
  border-color: var(--accent-edge);
  background:   var(--bg-soft);
}
.doc-reference-label {
  font-size:      var(--text-xs);
  font-weight:    var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color:          var(--ink-dim);
}
.doc-reference-title {
  font-weight: var(--weight-semibold);
  color:       var(--ink);
}
.doc-reference:hover .doc-reference-title { color: var(--accent-deep); }
.doc-reference-text {
  font-size: var(--text-sm);
  color:     var(--ink-soft);
}

/* The manual's footer navigation (nav-icons/style.css) sits under the box. */
.catalog-content .nav-footer-row { margin-top: var(--space-8); }

/* A long first line in a code block runs under the copy button otherwise. */
.code pre { padding-right: var(--space-12); }

/* The tree sits on the page, not on a panel of its own. */
.ui-root .sidebar-inner,
.ui-root .sidebar-wrapper {
  background: transparent;
}

/* The content column centers in whatever width the sidebar leaves it. */
.ui-root .catalog-content {
  margin-inline: auto;
}

/* Text runs the same width as the cards and the demos under it. */
.ui-root .doc-header .lede,
.ui-root .doc-section > ul {
  max-width: none;
}

/* On a phone the tree opens as a full-height panel from the window's left
   edge, the desktop rail drawn over the page, over a dark overlay with no
   blur. */
.ui-root .dialog.sheet.sidebar-sheet {
  top:           0;
  bottom:        0;
  left:          0;
  height:        100dvh;
  width:         min(18rem, 85vw);
  max-width:     none;
  background:    var(--bg);
  border:        0;
  border-right:  1px solid var(--catalog-line, var(--rule));
  border-radius: 0;
  box-shadow:    0 0 2rem color-mix(in oklab, var(--ink) 12%, transparent);
}
.ui-root .dialog-overlay:has(> .sidebar-sheet),
.ui-root .dialog-overlay:has(> .sidebar-sheet) .sheet-backdrop {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.ui-root .dialog-overlay:has(> .sidebar-sheet) {
  background: rgb(0 0 0 / 0.45);
}
.ui-root .dialog-overlay:has(> .sidebar-sheet) .sheet-backdrop { background: transparent; }
.ui-root .sidebar-sheet .catalog-nav-head { padding-top: var(--space-3); }

/* The panel focuses its first button when it opens, so the arrow keys work
   at once. On a touch screen that focus would draw the keyboard ring around
   the close button, so the ring is left to devices with a pointer. */
@media (hover: none) {
  .ui-root .sidebar-sheet .sidebar-trigger:focus-visible {
    outline:    none;
    box-shadow: none;
  }
}

/* The breadcrumb row, the manual's (app/pages/man/style.css). */
.catalog-crumbs {
  font-family:   var(--site-mono);
  font-size:     var(--text-xs);
  line-height:   var(--leading-body);
  color:         var(--ink-dim);
  margin-bottom: var(--space-4);
}
.catalog-crumbs a {
  color:                 var(--ink-soft);
  text-decoration:       underline;
  text-decoration-color: color-mix(in oklab, currentColor 30%, transparent);
  text-underline-offset: 0.25em;
}
.catalog-crumb-sep { padding: 0 0.4em; }
.catalog-crumb-current { color: var(--ink); }

/* A token or theme name in a table cell is one word: the cell sizes to it
   instead of breaking it across lines. */
.catalog-content :is(td, th) > code {
  overflow-wrap: normal;
  white-space:   nowrap;
}

/* The index header spaces its rows as every other page's header does. */
.index-hero { gap: var(--space-3); }

/* Code reads as typed: no ligatures, so <!-- and -> keep their characters. */
.catalog .code pre { font-variant-ligatures: none; }

/* Code wraps inside its box and keeps clear of the copy button, so a long
   import line never runs under the button or off the card. */
.catalog .code pre {
  padding-right: var(--space-12);
  white-space:   pre-wrap;
  overflow-wrap: anywhere;
}

/* The catalog's own frames (the rail, the controls that pick a look, the
   demo cards and the code blocks) draw a lighter line than the theme's
   rule, so the chrome recedes and the examples inside carry the look. The
   line is mixed from each theme's own rule, so it stays in that look's hue. */
.catalog {
  --catalog-line: color-mix(in oklab, var(--rule), var(--bg) 40%);
}
.catalog-frame > .sidebar[data-variant="sidebar"][data-side="left"] > .sidebar-container,
.catalog-nav-head {
  border-color: var(--catalog-line);
}
.catalog-switcher .mode-switch,
.catalog-switcher select {
  border-color: var(--rule);
}
.catalog .demo,
.catalog .code,
.catalog .demo-head,
.catalog .demo-code {
  border-color: var(--catalog-line);
}

/* On a wide window the content centers on the window, under the topbar's
   centered column, rather than in the width the sidebar leaves; where the
   window is too narrow for that it sits as close as the sidebar allows. The
   topbar keeps its width on every page, so moving to /ui never shifts it. */
@media (min-width: 48rem) {
  .ui-root .catalog-content {
    margin-left:  clamp(0px, calc((100% - 56rem) / 2 - var(--sidebar-width) / 2), 100%);
    margin-right: auto;
  }
}

/* The current page in the tree: a tint of the accent and the item's ink at
   a medium weight, so it reads as where you are without a box or a bar
   drawn on it. */
.ui-root .catalog-nav-tree .sidebar-menu-button[aria-current="page"] {
  background:  color-mix(in oklab, var(--accent) 9%, transparent);
  color:       var(--ink);
  font-weight: 500;
}
.ui-root .catalog-nav-tree .sidebar-menu-button:not([aria-current="page"]):hover {
  background: color-mix(in oklab, var(--ink) 5%, transparent);
}
