/* What Yeti does not do. Unlayered, so every rule here wins over Yeti's
   layers without having to raise its own specificity. Yeti's stylesheet and
   theme.css carry the whole of the site's type, colour, spacing and layout;
   what is left is the handful of document settings Yeti has no opinion
   about, the view transitions, the dot background, the syntax colours, the
   hairline under a docs heading, and the parts of the docs shell — the
   sticky header and regions, the page list, the table of contents — that
   Yeti positions but does not draw. */

/* ── Links ── */
/* No underline at rest, one on hover, which is what this site has always done.
   Yeti's base underlines a link in prose, which is the right default for a
   framework and the wrong one here. Chrome that already says text-decoration:
   none on its own links outranks the hover rule, so the nav and the table of
   contents keep their tinted hover instead of gaining a line. */
a {
  text-decoration: none;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration: underline;
}

/* ── The Document ── */
/* The height of the sticky header, which Yeti builds out of the control size,
   the nav's block padding and its bottom edge. Named once here because three
   rules below need to agree on it. */
:root {
  --site-header-size: calc(var(--yeti-control-size) + 2 * var(--yeti-space-sm) + var(--yeti-border-width));

  /* Checkboxes, radios and the like take the site's teal, as they always have. */
  accent-color: var(--yeti-color-primary);
}

/* A link into the table of contents scrolls smoothly and stops clear of the
   sticky bar instead of landing underneath it. */
html {
  scroll-behavior: smooth;
  scroll-padding-block-start: calc(var(--site-header-size) + var(--yeti-space-md));
}

/* Light text on a dark page has always been drawn with macOS's thinner
   antialiasing here; without it the whole site reads a weight heavier. */
body {
  -webkit-font-smoothing: antialiased;
}

/* ── View Transitions ── */
/* The one rule Yeti cannot write for us: @view-transition is an at-rule with
   no element to select, so a framework can neither hang it off a class nor
   guard a feature still below Baseline. The crossfade itself and its timing
   come from Yeti's base/transitions.css, tuned by --yeti-page-duration in
   theme.css. Firefox ignores this and navigates normally. */
@view-transition {
  navigation: auto;
}

/* ── Reduced Motion ── */
/* Yeti's own reset already collapses every animation and transition for a
   reader who has asked for less motion, and its components collapse through
   their duration tokens, the page crossfade included now that it is Yeti's.
   The homepage's staggered card entrance is the site's own and is not reached
   by either. The navigation is also turned off outright by a second
   @view-transition rule, which wins because it comes later in the same sheet.
   The stagger is turned off beside its own rules further down, because a
   universal selector cannot reach an animation set at (0,2,0) without
   !important. Smooth scrolling is turned off here for the same reason: the
   `html` rule above that asks for it outranks a universal one. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms;
    animation-iteration-count: 1;
    transition-duration: 0.01ms;
  }

  html {
    scroll-behavior: auto;
  }

  @view-transition {
    navigation: none;
  }
}

/* ── Dot Grid Background ── */
/* The dots used to sit on the homepage's outermost div, which the Yeti rewrite
   does not have; the body carries them instead, so they reach the whole page
   rather than stopping where the content does. */
.bg-option-dots.page-home {
  /* The dots reach the bottom of the window even when the page is shorter
     than it. A background on body normally propagates to the canvas and fills
     the viewport by itself, but only while html has none of its own, and
     Yeti's reset gives html the surface colour. So the body is told to be at
     least a screen tall, which is what the old .home did with min-height. */
  min-block-size: 100dvh;
  background-image: radial-gradient(circle, var(--yeti-color-border) 1px, transparent 1px);
  background-size: 32px 32px;
}

/* ── Card Hover ── */
/* The movement and the shadow come from Yeti's `lift`, which a card opts into
   by carrying the class; what is left here is the colour, which lift has no
   business owning. `lift` also reaches keyboard focus, which this rule never
   did. The theme sets the lift's distance to zero, because any rise at all
   reads as jerky on a tile this size. */
.card.lift {
  /* lift transitions the colours as well as the shadow, so the site only has
     to say how long and on what curve: the 0.2s ease the old .home-card used,
     rather than Yeti's shorter, sharper default, which suits a control better
     than a tile this size. */
  --yeti-lift-duration: 0.2s;
  --yeti-lift-ease: ease;
}

.card.lift:hover,
.card.lift:has(:focus-visible) {
  border-color: var(--yeti-color-primary);
  background-color: var(--yeti-color-surface-sunken);
}

/* A card's heading link names the whole card and is stretched over it, so it
   is the card's title rather than a link in a sentence and drops the
   underline. It keeps the accent colour on the landing pages, where the old
   .feature-card headings were accented too. */
.card [data-stretch] {
  text-decoration: none;
}

/* A card's h4 names one link in a grid of them, not a section of the page, so
   it takes the sizes the old .feature-card did: 0.9rem for the title and
   0.8rem for the line under it. Left on Yeti's heading scale the title
   reaches the size of the page's own h2 and the landing pages read as though
   the guide tiles outranked Quick Start. The padding is the old 1.25rem too,
   which sat tighter than a card's default. */
.docs-content .card {
  --yeti-card-padding: 1.25rem;
}

.docs-content .card h4 {
  font-size: 0.9rem;
}

.docs-content .card p {
  font-size: 0.8rem;
}

/* ── The Homepage ── */
/* Yeti lays the front page out — a center holding stacks, a grid of cards and
   a grid of boxes. These are the handful of things it has no opinion about:
   the page's own block padding (the old .home held its title 15vh down a
   full-height page), text centred over the column, the muted supporting lines
   under each heading, and the accent on a feature's heading. The feature boxes
   read as prose and stay ranged left, as .home-features did. */
.page-home main {
  padding-block: 15vh var(--yeti-space-3xl);
  text-align: center;
}

.page-home p {
  color: var(--yeti-color-text-muted);
}

.page-home .box {
  text-align: start;
}

.page-home .box h3 {
  color: var(--yeti-color-primary);
}

/* A product's name is the card's title, not a link in prose, so it takes the
   card's own colour; the underline is already gone with every stretched link. */
.product-cards [data-stretch] {
  color: inherit;
}

/* The three mascots are portraits of different widths, so each is drawn at one
   height and lets its own width follow, which is what the old 160px contain
   box did. */
.product-cards img {
  block-size: 10rem;
  inline-size: auto;
}

/* A center nested directly in a stack shrinks to its content rather than
   filling to its own data-max: the stack is a flex column, and the auto inline
   margins center gives itself override the stack's stretch, which in flexbox
   sizes the item to fit-content. Asking for the full width restores the cap as
   the only thing deciding the column's width. Recorded for Yeti as a gap. */
.home-about {
  inline-size: 100%;
}

/* ── The Front Page, from the stylesheet it used to have ──
   Every number below is the value the old main.css declared, kept because the
   page is meant to look exactly as it did. Where Yeti has a token for the
   thing, the token carries it; where the value is this page's alone, it is
   said here. Yeti's own defaults are close but not equal, and on a page this
   sparse the eye reads the difference. */

/* .home: 15vh down a full-height page. */
.page-home main {
  padding-block: 15vh var(--yeti-space-3xl);
  text-align: center;
}

/* .home-title */
.page-home h1 {
  font-size: 3.5rem;
  letter-spacing: -0.02em;
}

/* 3rem under the tagline, and half a rem between the title and the tagline:
   two different gaps, and a stack has one, so the inner pair sets its own. */
.page-home > main > .stack {
  gap: 3rem;
}

.page-home > main > .stack > .stack {
  gap: 0.5rem;
}

/* .home-tagline, and 3rem of air under it before the products. */
.page-home > main > .stack > .stack p {
  font-size: 1.1rem;
}

/* .home-card: 280x320 with 2rem of padding and the larger corner. */
/* The entrance runs on ease-out, the curve the old card-enter used. Scoped
   here rather than in the theme so it changes this one gesture, not every
   transition on the site. */
.product-cards.enter > * {
  --yeti-enter-ease: ease-out;
}

.product-cards > .card {
  position: relative;
  inline-size: 17.5rem;
  min-block-size: 20rem;
  --yeti-card-padding: 2rem;
  --yeti-card-radius: 0.75rem;
}

/* .home-card-name and .home-card-desc */
.product-cards h2 {
  font-size: 1.5rem;
  font-weight: 600;
  margin-block-start: auto;
}

.product-cards li p {
  font-size: 0.875rem;
}

/* .home-card-badge: the corner pill, lettered out. */
.product-cards .badge {
  position: absolute;
  inset-block-start: 1rem;
  inset-inline-end: 1rem;
  padding: 0.25rem 0.5rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  --yeti-badge-radius: 4px;
}

/* .home-about: its own narrower column, 6rem below the products. */
.home-about {
  inline-size: 100%;
  max-inline-size: 800px;
  margin-block-start: 3rem;
}

/* .home-about-heading and .home-about-text */
.home-about h2 {
  font-size: 1.5rem;
  font-weight: 600;
}

.home-about > div > div > p {
  font-size: 1.05rem;
  line-height: 1.8;
}

/* .home-feature; the grid's own gap comes from data-gap, because the column
   arithmetic reads that token and a bare gap here would leave the two out of
   step, which is what silently cost the third column. */
.home-about li {
  padding: 1.5rem;
  border-radius: 0.5rem;
  background-color: var(--yeti-color-surface-raised);
}

/* .home-feature-title and .home-feature-desc */
.home-about li h3 {
  font-size: 0.95rem;
  font-weight: 600;
}

.home-about li p {
  font-size: 0.875rem;
  line-height: 1.6;
}

/* ── The Article ── */
/* Yeti's base layer now carries the whole of the docs' prose: the type scale,
   the flow rhythm, the reading measure, inline code, code blocks, quotes,
   rules and tables. Two things are the site's own design rather than Yeti's
   defaults, and only those two are said here. */

/* ── Docs Typography, from the stylesheet the site used to have ──
   Yeti's scale is geometric: every step is the last one times the ratio. The
   docs' headings never were, so they cannot be reached by moving the ratio,
   and the sizes below are the ones the old docs.css declared. Yeti's own
   scale is still what the rest of the site uses; this is the reading surface
   asking for something quieter than the framework's default. */
.docs-content h1 {
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.docs-content h2 {
  font-size: 1.5rem;
  font-weight: 600;
}

.docs-content h3 {
  font-size: 1.125rem;
  font-weight: 600;
}

/* The reference pages read at 1rem rather than Yeti's 1.125rem body size:
   a page of attribute tables and prose is denser than an article, and the
   larger size pushed the column past what the three regions leave it. The
   lede keeps the larger size through Yeti's own `lede` class, which the docs
   generator writes and the hand-written pages carry, rather than through a
   rule about which paragraph follows the heading. Headings and code are set
   in rem and do not follow; inline code is set in em and does. */
.docs-content {
  font-size: 1rem;
}



/* Prose is muted and the headings stay white, which is what gives a long
   reference page its hierarchy: everything set in the text colour reads as
   uniformly loud, and the headings stop standing out however large they get.
   A bold run stays with its paragraph rather than brightening. */
.docs-content :is(p, li) {
  color: var(--yeti-color-text-muted);
}

.docs-content p {
  line-height: 1.7;
}

/* Inline code sits with the text rather than above it; a code block is a
   step down again, as both were. */
.docs-content code {
  font-size: 0.875em;
}

.docs-content pre code {
  font-size: 0.85rem;
}

/* A hairline under every section heading, which is how a long reference page
   has always been broken up here. Yeti's reading measure never binds on a
   heading — 65ch of 2xl type is wider than the column at every width — so the
   rule runs the whole width of the article, as it always did. */
.docs-content h2 {
  padding-block-end: var(--yeti-space-xs);
  border-block-end: var(--yeti-border-width) solid var(--yeti-color-border);
}

/* Yeti's bare table is tidy but undesigned; this takes it to the site's docs
   table using the table component's own tokens, so a Markdown table — which
   cannot carry class="table" — reads the same as a themed one. */
.docs-content th,
.docs-content td {
  border-block-end: var(--yeti-border-width) solid var(--yeti-table-border);
}

.docs-content th {
  background-color: var(--yeti-color-surface-raised);
}

/* The first cell of a row is the name of the thing the row is about: a token,
   an attribute, a class. Those are identifiers, and an identifier broken over
   two lines stops reading as one name — --yeti-color-text-muted wrapped after
   the second hyphen is three guesses, not a token. So that column keeps its
   line and the description column, which is prose and wraps happily, gives up
   the width. At every width: the generator puts each table in a scroller, so a
   table too wide for a phone scrolls in place rather than pushing the page. */
.docs-content :is(th, td):first-child {
  white-space: nowrap;
}

/* A table that fits still fills the column; only a wider one scrolls. The
   scroller is a flex track whose children do not shrink, and Yeti already
   gives a bare table inline-size: 100%, so a narrow table takes the full width
   and a wide one takes its own and overflows the track. */
.docs-content .scroller > table {
  min-inline-size: 100%;
}
/* ── Syntax Highlighting (tempest/highlight) ── */
.docs-content pre code .hl-keyword { color: #f97583; }
.docs-content pre code .hl-property { color: #34A853; }
.docs-content pre code .hl-attribute { font-style: italic; }
.docs-content pre code .hl-type { color: #EA4334; }
.docs-content pre code .hl-generic { color: #9d3af6; }
.docs-content pre code .hl-value { color: #9ecbff; }
.docs-content pre code .hl-literal { color: #9ecbff; }
.docs-content pre code .hl-number { color: #9ecbff; }
.docs-content pre code .hl-variable { color: #ffab70; }
.docs-content pre code .hl-comment { color: #6a737d; }
.docs-content pre code .hl-blur { filter: blur(2px); }
.docs-content pre code .hl-strong { font-weight: bold; }
.docs-content pre code .hl-em { font-style: italic; }
.docs-content pre code .hl-addition { display: inline-block; min-width: 100%; background-color: #00FF0022; }
.docs-content pre code .hl-deletion { display: inline-block; min-width: 100%; background-color: #FF000011; }

/* ── The Docs Shell ── */
/* Task 3's markup: Yeti's shell recipe with the page list in the sidebar and
   again in the header nav's panel. Yeti positions all of it; these rules are
   the three things it has no opinion about — a header that stays put, regions
   that scroll on their own, and which copy of the page list is on screen. */

/* The header sticks the way the old .docs-header did. The translucent bar is
   a token override plus the one property Yeti has no token for, so the blur
   rides on whatever the theme sets the nav's surface to. */
/* The page is capped rather than run edge to edge. Yeti's shell fills its
   container, and on a wide monitor that put the page list hard against the
   left edge and the table of contents hard against the right. The old design
   capped its header at 1200px; D9 capped the whole page at 2xl, the widest
   Yeti stop, so the three regions stay together. The background still paints
   the full window, because a background on body propagates to the canvas.

   96rem rather than that stop, which is the one place this site names a width
   the vocabulary has no word for. The reference pages are mostly tables, and
   at 2xl the article came out at 695px: the sidebar and the table of contents
   take 257px each out of the cap, so the article's own data-max never even
   bound. Widening costs nothing in readability, because Yeti's 70ch measure
   holds a paragraph at 705px however wide the page gets — the extra width goes
   to tables, code blocks and demos and nowhere else. 96rem is 1536px, wider
   than a 1440px laptop, so on one the page fills the window and the cap only
   bites on a larger monitor.
*/
.shell {
  max-inline-size: 96rem;
  margin-inline: auto;
}

/* The reading column starts at the same place on every page. Centred inside
   main it drifted, because main is narrower on a page that has a table of
   contents than on one that does not, so prose began 180px further right on
   the pages without one (D9). */
.shell main > .center {
  margin-inline: 0;
}

.shell > header {
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
}

.shell > header > .nav {
  --yeti-nav-surface: color-mix(in oklab, var(--yeti-color-surface) 85%, transparent);
  backdrop-filter: blur(12px);
}

/* The brand is the site's name, not a link in a sentence, so it never takes
   the underline the global hover rule gives prose links. The GitHub link
   beside it already says the same for itself. */
.shell > header .nav > [data-brand] {
  text-decoration: none;
}

/* The brand's mark. Yeti leaves an image its natural size; the old header
   drew the logo at 24px and this keeps it there. */
.shell > header .nav > [data-brand] img {
  inline-size: 24px;
  block-size: auto;
}

/* The GitHub link in the bar sits back until it is pointed at, as it did. */
.shell > header .nav > [data-actions] a {
  color: var(--yeti-color-text-muted);
  display: flex;
  text-decoration: none;
  opacity: 0.6;
  transition: opacity var(--yeti-duration-fast) var(--yeti-ease);
}

.shell > header .nav > [data-actions] a:hover {
  opacity: 1;
  text-decoration: none;
}

/* The header and the body row are both named containers, so that the page
   list's two copies, which sit in different branches of the tree, answer one
   question with one number. The name is what makes that possible: Yeti's nav
   is itself an anonymous container, so an unnamed query asked inside the
   header would be answered by the bar's content box, which is narrower than
   the page by the bar's own padding, and the two copies would both be on
   screen for those few pixels. Both of these elements are direct children of
   the shell, so both of them measure the page. */
.shell > header,
.shell > div:has(> main) {
  container: page / inline-size;
}

/* Both side regions scroll on their own under the sticky header, the way the
   old sidebar and table of contents did, so a fifty-link list never drags the
   article along with it. The offset is the bar's own height, named once at
   the top of this file. */
.shell > div:has(> main) > :is(.page-nav, .page-toc) {
  position: sticky;
  inset-block-start: var(--site-header-size);
  max-block-size: calc(100dvh - var(--site-header-size));
  overflow-y: auto;
}

/* ── The Page List ── */
/* One macro renders this list twice, once here in the sidebar and once inside
   the header nav's popover panel (D3). Exactly one copy is ever displayed, so
   a screen reader meets the list once and no link exists twice. The switch is
   at 48rem, which is the 768px the old off-canvas drawer used, and comfortably
   above the width at which the shell first seats the sidebar beside the
   article, so the sidebar never appears in a column too narrow for it. */
@container page (inline-size < 48rem) {
  .page-nav {
    display: none;
  }
}

/* The same width, and the same container: at or above it the sidebar carries
   the list, so the toggle and its panel go; below it they are the only way to
   it. */
@container page (inline-size >= 48rem) {
  .nav > button[popovertarget],
  .nav > ul[popover] {
    display: none;
  }
}

/* The rule between the sidebar and the article, which the old .docs-sidebar
   drew. The shell separates its regions with space alone. */
.shell > div:has(> main) > .page-nav {
  border-inline-end: var(--yeti-border-width) solid var(--yeti-color-border);
}

/* In the panel the list has only the nav's own small gap between its items, so
   a group heading would land hard against the link above it; in the sidebar
   the stack's larger gap already does this. */
.nav > ul[popover] > .page-nav-group {
  margin-block-start: var(--yeti-space-md);
}

/* A group heading in either copy, and the table of contents' own: small,
   spaced capitals, exactly as .docs-nav-group h3 drew them. */
.page-nav-heading {
  font-size: var(--yeti-text-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--yeti-color-text-muted);
  font-weight: var(--yeti-weight-strong);
  line-height: var(--yeti-leading-tight);
  margin-block-end: var(--yeti-space-xs);
}

/* The way back to the front page, set apart above the groups. */
.page-nav-home {
  font-size: var(--yeti-text-sm);
  padding-block-end: var(--yeti-space-sm);
  border-block-end: var(--yeti-border-width) solid var(--yeti-color-border);
}

/* The sidebar's links. Yeti styles the panel's copy through the nav
   component, but a column of links down the side of a page is, in Yeti's own
   words, a stack that needs no component, so the site draws it: the padded,
   rounded rows the old .docs-nav-group a had, with the current page picked out
   in the accent. */
.page-nav a {
  display: block;
  text-decoration: none;
  padding: 0.35rem 0.75rem;
  font-size: var(--yeti-text-sm);
  color: var(--yeti-color-text-muted);
  border-radius: var(--yeti-radius-md);
  transition: color var(--yeti-duration-fast) var(--yeti-ease), background-color var(--yeti-duration-fast) var(--yeti-ease);
}

.page-nav a:hover {
  color: var(--yeti-color-text);
  background-color: var(--yeti-color-surface-raised);
  text-decoration: none;
}

.page-nav a[aria-current] {
  color: var(--yeti-color-primary-text);
  background-color: var(--yeti-color-primary-subtle);
}

/* ── The Table of Contents ── */
/* Hidden until the shell has room for three regions, which with data-width="xs"
   is about 1100px — the width the old media query used (D4). Below it the
   article takes the row back rather than the headings dropping under the text,
   where they would read as noise. */
@container page (inline-size < 69rem) {
  .page-toc {
    display: none;
  }
}

/* A step up from where these started: against 18px body copy an xs menu is
   10px, which is unreadable rather than quiet. Both menus now sit at sm, one
   step under the prose, which is the relationship the old design had. */
.page-toc a {
  display: block;
  text-decoration: none;
  font-size: var(--yeti-text-sm);
  color: var(--yeti-color-text-muted);
  line-height: var(--yeti-leading-tight);
  padding-inline-start: 0.75rem;
  border-inline-start: 2px solid transparent;
}

.page-toc a:hover {
  color: var(--yeti-color-text);
  border-inline-start-color: var(--yeti-color-primary);
  text-decoration: none;
}
