/* Clash Display's variable cut (wght 200 to 700), only for the Typography
   drawing's weight sweep. Latin subset, from the font Zach licenses for the
   site (assets/fonts/ClashDisplay-FFL.txt). */
@font-face {
  font-family: "Clash Display Variable";
  font-style: normal;
  font-weight: 200 700;
  font-display: swap;
  src: url("../assets/fonts/ClashDisplay-Variable.woff") format("woff");
}

/* =============================================================================
   Chrome for design-system.html only.
   Nothing here styles the site. The specimens on that page load the real
   css/styles.css, so they cannot drift from what ships.
   ========================================================================== */

.ds {
  /* The site's own side padding (18, 32, 64), so the top bar, the intro and
     every section sit exactly where zachblevins.com puts them. */
  --ds-gutter: var(--pad);
  /* Content never runs wider than 1440: past that, the edge grows instead,
     and the top bar, side panel, page and pager all start from it, so the
     logo always sits over the content's left edge. */
  --ds-max: 1440px;
  --ds-edge: max(var(--ds-gutter), calc((100vw - var(--ds-max)) / 2));
  /* Figma: panels are Background/Default/Primary, rules Border/Default/
     Primary, dim text Typography/Default/Tertiary, the code well
     Background/Default/Secondary with Typography/Default/Secondary on it.
     All semantic, so Dark follows on its own. */
  --ds-panel: var(--c-bg);
  --ds-rule: var(--c-line);
  --ds-dim: var(--c-text-3);
  --ds-code: var(--op-050);
  --ds-code-ink: var(--c-text-2);
  /* An icon tool's glyph when the tool is solid: lime on ink in Light, ink
     on chalk in Dark, where lime on chalk would all but vanish. */
  --ds-tool-glyph-on: var(--c-accent);
  background: var(--ds-bg);
  color: var(--c-text);
  min-height: 100dvh;
}

/* The page colour goes on <html> too, the element browsers paint past the
   page's edges (the bounce at the top and bottom, Safari's toolbar band),
   so overscrolling shows the system's ground rather than the site's white. */
html:has(> body.ds) {
  --ds-bg: #f6f6f5;
  background-color: var(--ds-bg);
}

/* Dark: the page chrome takes the site's own dark ground, and the specimens
   flip by themselves because they only read semantic tokens. */
:root[data-theme="dark"]:has(> body.ds) {
  --ds-bg: var(--c-bg);
}

:root[data-theme="dark"] .ds {
  --ds-tool-glyph-on: var(--c-bg);
}

/* ---------- Shell: the site's top nav, with the side nav under it -------- */

.ds-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  min-height: 100dvh;
}

/* The site's nav at every width: a frosted pill with the logo and the menu
   button, and the theme toggle on the right. The menu button opens and
   closes the side nav. */
.ds-topbar {
  grid-column: 1 / -1;
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: var(--nav-pad-y) var(--ds-edge);
  padding-top: calc(var(--nav-pad-y) + var(--safe-t));
}

/* The site's nav layout and glass, with the design system's own contents:
   the pill (frosted ground, no gap) holds the logo and the button that opens
   the sections panel, and the right holds the way back and the toggle. */

/* The panel is the site's mobile menu: logo and X at the top, large links
   with the selector bar, socials and the legal line at the foot. It drops
   over the top of the page as tall as its links, and the page below dims.
   Figma ds-nav (2324:329): Blanket and Background/Default/Nav under a
   background blur of 100, over the menu scrim (Ink/800). */
.ds-nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
  max-height: 100dvh;
  padding-top: calc(var(--nav-pad-y) + var(--safe-t));
  overflow: hidden;
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: 0 0 0 100vmax transparent;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease), visibility 0s linear var(--dur);
}

.ds-nav-open .ds-nav {
  visibility: visible;
  opacity: 1;
  transform: none;
  box-shadow: 0 0 0 100vmax var(--c-dim);
  transition-delay: 0s;
}

/* The panel's logo sits exactly on the top bar's logo, and the X sits on
   the panel's right, as the site's menu has it. The menu glyph travels
   from the top bar to the X and back (js/site.js, travelMenuGlyph). The
   links line up under the logo. */
.ds-nav .mobile-menu__head {
  justify-content: space-between;
  padding: 0 var(--ds-gutter) 0 var(--ds-edge);
}

.ds-nav .mobile-menu__body,
.ds-nav .menu__foot {
  padding-inline: var(--ds-edge) var(--ds-gutter);
}

.ds-nav.menu {
  background: var(--c-menu-glass);
}

/* The glass would show the top bar's sitelink and toggle through it, so
   they step out while the panel is up. */
.ds-topbar > * {
  transition: opacity var(--dur) var(--ease);
}

.ds-nav-open .ds-topbar > * {
  opacity: 0;
}

/* An open group is not a reason for the selector bar on its own: only the
   group holding the section in view carries it. */
.ds-nav [data-ds-group][aria-expanded="true"]:not(.is-current)::after {
  transform: scaleX(0);
}

.ds-nav [data-ds-group].is-current::after {
  transform: scaleX(1);
}

.ds-nav__body {
  flex: none;
}

.ds-nav .menu__links {
  padding-left: 0.125rem;
}

.ds-nav .menu__links[hidden] {
  display: none;
}

/* The section in view: the menu's current-page treatment. */
.ds-nav .menu__link[aria-current],
.ds-nav .mobile-menu__link[aria-current] {
  color: var(--c-text);
}

.ds-nav .menu__link[aria-current]::after,
.ds-nav .mobile-menu__link[aria-current]::after {
  transform: scaleX(1);
}

.ds-main {
  --ds-main-top: 0.5rem;
  min-width: 0;
  padding: var(--ds-main-top) var(--ds-edge) 7.5rem;
}

@media (min-width: 1024px) {
  /* The page's side padding is the top bar's, so content lines up under
     the logo and runs to the theme toggle's right edge. */
  .ds-main {
    --ds-main-top: 1.5rem;
    padding: var(--ds-main-top) var(--ds-edge) 8rem;
  }
}

/* ---------- Page head ----------------------------------------------------- */

/* The overview opens the way the home page does: the site's own hero, at
   the site's width and rhythm. Eyebrow, then the page title on the hatch
   and the lead, with the overview running straight on beneath. */
.ds-head .ds-hero {
  padding-block: var(--band-y);
  /* Only as tall as what it holds, closing row included: the overview runs
     straight on beneath it rather than waiting a screen below. */
  min-height: 0;
  /* .ds-main already sits under the bar with its own top padding. */
  margin-top: calc(-1 * var(--ds-main-top));
}

.ds-head .ds-hero > :last-child {
  margin-top: 0;
}

.ds-intro {
  display: flex;
  flex-direction: column;
  gap: 2rem;
}

.ds-head__sub {
  font-family: var(--f-sans);
  font-size: 1rem;
  line-height: 1.75rem;
  color: var(--ds-dim);
  max-width: 64ch;
  margin: 0;
}

.ds-intro .ds-head__facts {
  margin: 0;
}

.ds-head__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1px;
  margin: 2rem 0 0;
  background: var(--ds-panel);
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  overflow: hidden;
}

/* Each fact draws its own rules, so a short last row leaves panel, not a
   grey hole, however many columns the width allows. */
.ds-head__facts div {
  background: var(--ds-panel);
  box-shadow: 0 0 0 1px var(--ds-rule);
  padding: 1rem 1.25rem;
}

.ds-head__facts dt {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--ds-dim);
}

.ds-head__facts dd {
  margin: 0;
  font-family: var(--f-sans);
  font-size: 0.875rem;
  line-height: 1.5rem;
  color: var(--c-text);
}

/* ---------- Sections: a 12-column grid of documented items ---------------- */

.ds-section {
  margin-top: 4.5rem;
  /* A link straight to a section lands it where the page opens it, so its
     drawing clears the nav: 124 on a phone, 136 from 768, 152 from 1024. */
  scroll-margin-top: 124px;
}

@media (min-width: 768px) {
  .ds-section {
    scroll-margin-top: 136px;
  }
}

@media (min-width: 1024px) {
  .ds-section {
    scroll-margin-top: 152px;
  }
}

.ds-section__title {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 2rem;
  line-height: 2.5rem;
  color: var(--c-text);
  margin: 0 0 0.375rem;
}

/* Figma ds-section-head at 1440: Title Header/MD, 40/48. */
@media (min-width: 1200px) {
  .ds-section__title {
    font-size: 2.5rem;
    line-height: 3rem;
  }
}

/* Figma ds-section-head: each section's overview drawing sits right on top
   of its title, at 135 x 76 for the 40px title (8.4375rem). Below 1200 the
   title is 32px, so the drawing keeps the same proportion to it at 0.8 of
   that. js/ds-playground.js clones it from the section's overview card.
   The drawing's 661-unit artboard has a margin round its ink, so it shifts
   left to put the ink on the title's edge: Figma's offset over the 135px
   box, per drawing. translate reads the box's own width, so the shift
   scales with it. */
.ds-section__art {
  display: block;
  width: 6.75rem;
  aspect-ratio: 661 / 372;
  translate: var(--art-x, -18.5%) 0;
  pointer-events: none;
}

.ds-section__art svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.25;
}

#elevation > .ds-section__art { --art-x: -30.4%; }
#navigation > .ds-section__art { --art-x: -24.4%; }
#headers > .ds-section__art { --art-x: -20.7%; }
#cards > .ds-section__art { --art-x: -29.6%; }
#lists > .ds-section__art { --art-x: -17.8%; }
#media > .ds-section__art,
#forms > .ds-section__art,
#motion > .ds-section__art { --art-x: -14.1%; }
#figma > .ds-section__art,
#agents > .ds-section__art { --art-x: -8.5%; }

@media (min-width: 1200px) {
  .ds-section__art {
    width: 8.4375rem;
  }
}

.ds-section__note {
  font-family: var(--f-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ds-dim);
  /* Figma ds-section-head: the note runs the full width, 24 above the body. */
  margin: 0 0 1.5rem;
}

/* Cards in a row line up part for part: heads with heads, canvases with
   canvases, controls with controls, so two halves always end level. A half
   card fills the first gap that fits it, so halves pair up. */
.ds-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-flow: row dense;
  gap: 1.25rem;
  align-items: stretch;
}

.ds-grid > .ds-item {
  grid-column: span 12;
  margin-bottom: 0;
}

@media (min-width: 1200px) {
  .ds-grid > .ds-item--half {
    grid-column: span 6;
  }
}

/* ---------- One documented item ------------------------------------------- */

.ds-item {
  background: var(--ds-panel);
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 1.25rem;
}

.ds-item__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  /* Figma ds-item__head: 8 between parts, 13 between wrapped rows. */
  gap: 0.8125rem 0.5rem;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--ds-rule);
}

.ds-item__name {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;  /* Code/2XS, 12/22 */
  color: var(--c-text);
  margin: 0;
}

.ds-item__note {
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
  margin: 0;
  flex: 1 1 320px;
}

.ds-demo {
  padding: 2rem 1.25rem;
}

.ds-demo--flush {
  padding: 0;
}

.ds-code {
  margin: 0;
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--ds-rule);
  background: var(--ds-code);
  overflow-x: auto;
}

.ds-code code {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;  /* Code/2XS */
  color: var(--ds-code-ink);
  white-space: pre;
}

/* ---------- Spec tables --------------------------------------------------- */

.ds-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--f-mono);
  font-size: 0.75rem;
}

.ds-table th,
.ds-table td {
  text-align: left;
  padding: 0.5625rem 0.75rem;
  border-bottom: 1px solid var(--ds-rule);
  white-space: nowrap;
}

.ds-table th {
  font-weight: 500;
  color: var(--ds-dim);
  letter-spacing: 0.04em;
  font-size: 0.6875rem;
}

.ds-table td:first-child {
  color: var(--c-text);
}

.ds-table td {
  color: var(--ds-dim);
}

.ds-table tr:last-child td {
  border-bottom: 0;
}

.ds-scroll {
  overflow-x: auto;
}

/* Keep long-form specimens from running the full page width. */
.ds-measure {
  max-width: 720px;
  /* The .t-display specimen sizes itself against this column. See .t-fit
     in css/styles.css. Without it the specimen reads 1cqi as 1vw and runs
     to four lines on a narrow phone, which is not what it is showing. */
  container-type: inline-size;
}

/* ---------- Token tables -------------------------------------------------- */

.ds-demo--table {
  padding: 0;
}

.ds-table--tokens th,
.ds-table--tokens td {
  padding: 0.625rem 1.25rem;
  vertical-align: middle;
}

.ds-table--tokens td:first-child {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

/* ---------- One section at a time ---------------------------------------- */

.ds-paged .ds-head:not(.is-active),
.ds-paged .ds-section:not(.is-active) {
  display: none;
}

.ds-paged .ds-section.is-active {
  margin-top: 2.5rem;
}

.ds-paged .ds-head.is-active {
  border-bottom: 0;
}

/* Previous / next stay pinned to the bottom of the window, on a frosted
   strip with the page's side padding, so moving on never needs a scroll. */
.ds-pager {
  position: fixed;
  /* Above the site's bottom edge blur, which would soften the labels. */
  z-index: 21;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem var(--ds-edge) calc(0.75rem + var(--safe-b));
  /* No ground of its own: the buttons float on the site's bottom edge blur
     (.edge-blur), the same softening every page has under its last line. */
}

/* Figma ds-pager: 12 above and below at 390, 16 from 768. */
@media (min-width: 768px) {
  .ds-pager {
    padding-block: 1rem calc(1rem + var(--safe-b));
  }
}

/* Room under the last item so the strip never covers it. */
.ds-paged .ds-main {
  padding-bottom: 8rem;
}

/* ---------- Specimens cut from the live pages ---------------------------- */

.ds-fig {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--c-link);  /* Button/Typography/Tertiary: Opacity/900 */
  padding: 0.125rem 0.5rem;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  max-width: 100%;
  overflow-wrap: anywhere;
}

.ds-fig b {
  font-weight: 400;
  color: var(--c-text);
}

.ds-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}

/* Fixed and sticky pieces (the nav) are drawn inside the demo, not the
   window: a transform makes the demo their containing block. */
.ds-demo--frame {
  position: relative;
  min-height: 120px;
  transform: translateZ(0);
  overflow: hidden;
}

.ds-demo--frame .nav {
  position: absolute;
}

/* The player specimen is a picture: no footage behind it, so nothing in it
   takes a tap. */
.ds-static .player {
  pointer-events: none;
}

/* Menus that open over the page on the site are shown open, in place. */
.ds-static .dropdown,
.ds-static .mobile-menu {
  position: static !important;
  display: flex !important;
  width: auto;
  max-width: none;
  max-height: none;
  box-shadow: none;
  border-radius: var(--radius);
  transform: none;
  opacity: 1;
  visibility: visible;
}

.ds-glyphs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 1.5rem 1rem;
}

.ds-glyph {
  /* The site tints some icons with the accent; the catalogue shows them in
     the text color so every glyph reads on both grounds. */
  --c-accent: var(--c-text);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.625rem;
  color: var(--c-text);
}

.ds-glyph .icon {
  color: var(--c-text);
}

.ds-glyph__name {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  color: var(--ds-dim);
}

.ds-glyph-notes {
  margin: 1.75rem 0 0;
  padding: 1rem 0 0;
  border-top: 1px solid var(--ds-rule);
  list-style: none;
  display: grid;
  gap: 0.25rem;
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.25rem;
  color: var(--ds-dim);
}

.ds-elev {
  height: 120px;
  border-radius: var(--radius);
  background: var(--c-bg);
  border: 1px solid var(--c-line);
}

/* =============================================================================
   Playground. js/ds-playground.js builds a toolbar, a sandboxed canvas and a
   controls panel into every component card. Without script the card shows
   the production specimen and its code, as before.
   ========================================================================== */

/* No controls: the canvas (or a card's code, like the agent prompt) takes
   the controls' row too, so it reaches the bottom of the card instead of
   leaving that row as an empty strip. */
.ds-story > .ds-canvas:last-child,
.ds-grid > .ds-item > .ds-demo:last-child,
.ds-grid > .ds-item > .ds-codeview:last-child {
  grid-row: span 2;
}

.ds-story,
.ds-grid > .ds-item {
  grid-column: span 12;
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: 0;
  min-width: 0;
  margin: 0;
  background: var(--ds-panel);
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  overflow: clip;
}

@media (min-width: 1200px) {
  .ds-grid > .ds-story--half,
  .ds-grid > .ds-item--half {
    grid-column: span 6;
  }
}

@supports not (grid-template-rows: subgrid) {
  .ds-story,
  .ds-grid > .ds-item {
    display: flex;
    flex-direction: column;
  }

  .ds-story .ds-canvas,
  .ds-grid > .ds-item > .ds-demo {
    flex: 1 1 auto;
  }
}

/* A foundation card's demo fills its row, so a short table sits level with
   a tall one beside it. */
.ds-grid > .ds-item > .ds-demo {
  min-width: 0;
}

/* ---------- Card head ------------------------------------------------------ */

.ds-story__head {
  display: grid;
  align-content: start;
  gap: 0.375rem;
  padding: 1.125rem 1.25rem 1rem;
  border-bottom: 1px solid var(--ds-rule);
}

.ds-story__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}

.ds-story__name {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.5rem;
  color: var(--c-text);
}

.ds-story__css {
  margin: 0;
}

.ds-story__css code {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--c-text);
  overflow-wrap: anywhere;
}

.ds-story__note {
  margin: 0;
  max-width: 72ch;
  font-family: var(--f-sans);
  font-size: 0.8125rem;
  line-height: 1.25rem;
  color: var(--ds-dim);
}

/* ---------- Canvas: toolbar, stage, code ---------------------------------- */

.ds-canvas {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.ds-canvas > .ds-stage:not(.ds-stage--live) {
  flex: 1 1 auto;
  padding: 2rem;
}

.ds-canvas > .ds-stage.ds-demo--flush {
  padding: 0;
}

.ds-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--ds-bar-h);
  /* Phones and tablets: the selected tab's label starts on the card's 20
     text edge, and the last tool's glyph ends 20 in on the right, so the
     bar lines up with the head and the stage under it. */
  padding: 0 0.875rem 0 0.375rem;
  /* The rule is drawn inside the bar rather than as a border, so the
     selected tab's underline can sit on it without poking past the bar's
     edge. A border would leave that pixel outside, and the bar, which
     scrolls sideways when it has to, would scroll up and down by one. */
  box-shadow: inset 0 -1px 0 var(--ds-rule);
  overflow-x: auto;
  scrollbar-width: none;
}

@media (min-width: 1200px) {
  .ds-toolbar {
    padding: 0 0.5rem 0 0.25rem;
  }
}

.ds-toolbar::-webkit-scrollbar {
  display: none;
}

.ds-tabs {
  display: flex;
  align-self: stretch;
  flex: none;
}

.ds-tab {
  position: relative;
  padding: 0 0.875rem;
  border: 0;
  background: none;
  font-family: var(--f-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.25rem;
  color: var(--ds-dim);
  cursor: pointer;
  transition: color var(--dur) var(--ease);
}

.ds-tab::after {
  content: "";
  position: absolute;
  left: 0.875rem;
  right: 0.875rem;
  bottom: 0;
  height: 2px;
  background: var(--c-text);
  transform: scaleX(0);
  transition: transform var(--dur) var(--ease);
}

.ds-tab[aria-selected="true"] {
  color: var(--c-text);
}

@media (hover: hover) and (pointer: fine) {
  .ds-tab:hover {
    color: var(--c-text);
  }
}

.ds-tab[aria-selected="true"]::after {
  transform: scaleX(1);
}

.ds-tab:focus-visible,
.ds-tool:focus-visible,
.ds-copy:focus-visible,
.ds-reset:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: -2px;
  border-radius: var(--radius);
}

/* Figma ds-tools: 4 between tools, 6 either side of the rule. */
.ds-tools {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex: none;
}

.ds-tools__rule {
  width: 1px;
  height: 20px;
  margin: 0 0.125rem;
  background: var(--ds-rule);
}

.ds-tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--c-text-3);  /* Figma ds-tools: resting tools are Tertiary */
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.ds-tool--text {
  padding: 0 0.5rem;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
}

.ds-tool .ds-ui {
  width: 14px;
  height: 14px;
}

/* Figma ds-tool: hover and selected go solid ink with the page colour on
   top (an icon tool's glyph turns lime instead, ink again in Dark); hover lifts with
   Elevation / Hover, selected settles to Elevation / Pressed. */
@media (hover: hover) and (pointer: fine) {
  .ds-tool:hover {
    background: var(--c-text);
    color: var(--c-bg);
    box-shadow: 0 2px 3px rgb(0 0 0 / 0.06), 0 8px 12px rgb(0 0 0 / 0.12);
  }

  .ds-tool:not(.ds-tool--text):hover {
    color: var(--ds-tool-glyph-on);
  }
}

.ds-tool[aria-pressed="true"],
.ds-tool[aria-checked="true"],
.ds-tool.is-override {
  background: var(--c-text);
  color: var(--c-bg);
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.04);
}

.ds-tool:not(.ds-tool--text)[aria-pressed="true"],
.ds-tool:not(.ds-tool--text).is-override {
  color: var(--ds-tool-glyph-on);
}

.ds-ui {
  display: block;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ds-seg--bar {
  display: flex;
  gap: 0.25rem;
}

.ds-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

/* The stage: the frame sits in the middle of whatever height the row gives
   it. At a fixed viewport the frame is drawn as a device on a dotted ground,
   and anything wider than the card scrolls sideways. */
.ds-stage--live {
  --canvas-bg: var(--c-bg);
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-height: 140px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  background: var(--canvas-bg);
  transition: background-color var(--dur) var(--ease);
}

.ds-stage--live[hidden] {
  display: none;
}

.ds-stage--live:not([data-vp="fill"]) {
  padding: 1.5rem;
  background-color: var(--ds-bg);
  background-image: radial-gradient(var(--ds-rule) 1px, transparent 1.2px);
  background-size: 16px 16px;
}

.ds-port {
  flex: 1 0 auto;
  margin: auto;
  min-width: 0;
}

.ds-stage--live:not([data-vp="fill"]) .ds-port {
  flex: none;
  border-radius: var(--radius);
  box-shadow: 0 0 0 1px var(--ds-rule), 0 8px 24px #0000000f;
  overflow: hidden;
}

.ds-frame-el {
  display: block;
  width: 100%;
  height: 120px;
  border: 0;
  background: transparent;
  color-scheme: normal;
}

/* Scroll hints: soft edges when there is more to either side. */
.ds-panel::before,
.ds-panel::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 1;
  width: 32px;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}

.ds-panel::before {
  left: 0;
  background: linear-gradient(90deg, var(--ds-panel), transparent);
}

.ds-panel::after {
  right: 0;
  background: linear-gradient(270deg, var(--ds-panel), transparent);
}

.ds-panel:has(> .ds-stage.has-left:not([hidden]))::before,
.ds-panel:has(> .ds-stage.has-right:not([hidden]))::after {
  opacity: 1;
}

/* Code view */
.ds-codeview {
  position: relative;
  flex: 1 1 auto;
  min-height: 140px;
  background: var(--ds-code);
}

.ds-codeview[hidden] {
  display: none;
}

.ds-code--live {
  flex: 1 1 auto;
  max-height: 520px;
  margin: 0;
  padding: 1rem 1.25rem;
  border: 0;
  overflow: auto;
  tab-size: 2;
}

.ds-code--live:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: -2px;
}

.ds-copy,
.ds-reset {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: 28px;
  padding: 0 0.75rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);  /* Figma ds-mini-button: Nav over Blanket */
  -webkit-backdrop-filter: blur(24px);  /* Figma background blur 48 */
  backdrop-filter: blur(24px);
  font-family: var(--f-sans);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.375rem;
  color: var(--c-text);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
    color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.ds-codeview {
  display: flex;
  flex-direction: column;
}

.ds-codeview__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0.75rem 0.5rem 1.25rem;
  border-bottom: 1px solid var(--ds-rule);
}

.ds-codeview__label {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ds-dim);
}

/* Figma ds-mini-button: the tertiary button at a small size. The nav's
   glass at rest with a Tertiary label and an icon in Icon/Button/Tertiary
   (ink in Light, lime in Dark); hover keeps the glass, lifts and brings the
   label up to full strength; pressed and copied lay the tint on twice. */
.ds-copy,
.ds-reset {
  color: var(--c-link);  /* Button/Typography/Tertiary */
}

.ds-copy .ds-ui,
.ds-reset .ds-ui {
  color: var(--c-btn-icon);  /* Icon/Button/Tertiary */
}

@media (hover: hover) and (pointer: fine) {
  .ds-copy:hover,
  .ds-reset:hover {
    color: var(--c-text);  /* Button/Typography/Tertiary Hover */
    box-shadow: 0 2px 3px rgb(0 0 0 / 0.06), 0 8px 12px rgb(0 0 0 / 0.12);
  }
}

.ds-copy:active,
.ds-reset:active,
.ds-copy.is-done {
  border-color: transparent;
  background: linear-gradient(var(--c-nav), var(--c-nav)), linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);
  color: var(--c-btn-icon);  /* Button/Typography/Tertiary Pressed */
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.04);
}

/* Syntax colors, each at least 4.5:1 on the code ground in its theme. */
.hl-tag { color: #0a6e66; }
.hl-attr { color: #6d28d9; }
.hl-str { color: #9a4a00; }
.hl-punc { color: var(--ds-dim); }

:root[data-theme="dark"] .hl-tag { color: #5eead4; }
:root[data-theme="dark"] .hl-attr { color: #c4b5fd; }
:root[data-theme="dark"] .hl-str { color: #fcd34d; }

/* ---------- Controls -------------------------------------------------------- */

.ds-controls {
  min-width: 0;
  border-top: 1px solid var(--ds-rule);
  transition: opacity var(--dur) var(--ease);
}

.ds-controls.is-dim {
  opacity: 0.45;
  pointer-events: none;
}

.ds-controls__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--ds-bar-h);
  padding: 0 0.75rem 0 1.25rem;
  background: var(--c-overlay);  /* 5% ink */
  border-bottom: 1px solid var(--ds-rule);
}

.ds-controls__title {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  text-transform: uppercase;
  color: var(--ds-dim);
}

/* 14 over the name, 20 under the control: the name's line carries about 7
   of air above its letters, while a control's edge is hard, so the extra
   6 below makes the two read as the same space, and as the card's 20
   sides. */
.ds-ctl {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
  padding: 0.875rem 1.25rem 1.25rem;
}

.ds-ctl + .ds-ctl {
  border-top: 1px solid var(--ds-rule);
}

.ds-ctl[hidden] {
  display: none;
}

/* Figma ds-ctl layout=inline: a 232 name column, 24 to the control, and the
   control sits on the row's bottom edge. Text fields and selects hold at
   348 rather than filling the column. */
@media (min-width: 768px) {
  .ds-ctl {
    grid-template-columns: 14.5rem minmax(0, 1fr);
    gap: 1.5rem;
    align-items: end;
  }

  .ds-ctl__input > .ds-input,
  .ds-ctl__input > .ds-select {
    max-width: 21.75rem;
  }
}

.ds-ctl__key {
  display: block;
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--c-text);
}

.ds-ctl__desc {
  margin: 0.125rem 0 0;
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
}

.ds-ctl__input {
  display: flex;
  justify-content: flex-end;
  min-width: 0;
}

/* Segments, switches and sliders sit at the row's right edge at every width;
   text fields and selects fill what they are given (the whole row on a
   phone, up to 348 from 768). */
.ds-ctl__input > .ds-seg {
  justify-content: flex-end;
}

/* Upload: the mini button, at the row's right edge like the segments. Its
   file input is visually hidden; focus shows on the button. */
.ds-upload {
  display: flex;
  justify-content: flex-end;
}

.ds-upload .ds-reset {
  cursor: pointer;
}

.ds-upload input:focus-visible + .ds-reset {
  outline: 2px solid var(--c-text);
  outline-offset: -2px;
}

.ds-ctl__input > :is(.ds-input, .ds-select) {
  flex: 1 1 auto;
}

/* Figma ds-input, ds-input-paragraph and ds-select, size=touch on phones
   and tablets: 44 tall, text 10 down and 12 in from the outer edge at
   16/24, which also keeps iOS from zooming in. size=desktop from 1200 is
   32 tall at 13/20. */
.ds-input,
.ds-select__field {
  box-sizing: border-box;
  width: 100%;
  min-height: 44px;
  padding: 0.5625rem 0.6875rem;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--c-bg);  /* Background/Default/Primary */
  font-family: var(--f-sans);
  font-size: 1rem;
  line-height: 1.5rem;
  color: var(--c-text);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.ds-input--area {
  resize: none;
  overflow: hidden;
}

@media (min-width: 1200px) {
  .ds-input,
  .ds-select__field {
    min-height: 32px;
    padding: 0.3125rem 0.625rem;
    font-size: 0.8125rem;
    line-height: 1.25rem;
  }

  /* The stroke sits inside, so the text starts 4 down and 10 in from the
     outer edge. */
  .ds-input--area {
    padding: 0.1875rem 0.5625rem;
  }
}

/* iOS zooms the page into any field set under 16px, and stays zoomed, so a
   touch screen wide enough for the desktop size keeps 16px type. */
@media (pointer: coarse) {
  .ds-input,
  .ds-select__field {
    font-size: 1rem;
  }
}

/* Figma ds-input, ds-input-paragraph and ds-select: hover darkens the edge
   to Opacity/900 at 90% and lifts with Elevation / Hover inside a 2px
   Lime/300 ring; focus holds the edge, settles to Elevation / Pressed and
   widens the ring to 3px of Lime/600. */
@media (hover: hover) and (pointer: fine) {
  .ds-input:hover,
  .ds-select__field:hover {
    border-color: color-mix(in srgb, var(--op-900) 90%, transparent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--c-accent) 30%, transparent),
      0 2px 3px rgb(0 0 0 / 0.06), 0 8px 12px rgb(0 0 0 / 0.12);
  }
}

.ds-input:focus,
.ds-select__field:focus-visible,
.ds-select.is-open .ds-select__field {
  outline: none;
  border-color: color-mix(in srgb, var(--op-900) 90%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 60%, transparent),
    0 1px 1px rgb(0 0 0 / 0.04);
}

.ds-select {
  position: relative;
  display: block;
}

.ds-select__field {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.ds-select__value {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.ds-select .ds-ui {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--c-text-3);
}

@media (min-width: 1200px) {
  .ds-select .ds-ui {
    width: 14px;
    height: 14px;
  }
}

/* Figma ds-ui-icon chevron and chevron-up: down while closed, up while
   the list is open. */
.ds-select .ds-ui--chevron-up,
.ds-select.is-open .ds-ui--chevron {
  display: none;
}

.ds-select.is-open .ds-ui--chevron-up {
  display: block;
}

/* Figma ds-list: 4 off the field, 4 in, 2 between rows, the field's
   edge and fill, and the Elevation / Hover lift. It is fixed to the window
   and placed by ds-playground.js, which also caps its height to the room
   it has. Long lists scroll inside it. */
.ds-list {
  position: fixed;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-sizing: border-box;
  max-height: 20rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0.25rem;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--c-bg);
  box-shadow: 0 2px 3px rgb(0 0 0 / 0.06), 0 8px 12px rgb(0 0 0 / 0.12);
  transform-origin: top center;
  animation: ds-list-in 150ms var(--ease-enter);
}

.ds-list[hidden] {
  display: none;
}

.ds-select.is-up .ds-list {
  transform-origin: bottom center;
}

@keyframes ds-list-in {
  from {
    opacity: 0;
    transform: scale(0.97);
  }
}

/* Figma .selection-link: 28 tall, 4 by 8, Opacity/050 under the pointer
   or the arrow keys, Opacity/100 for the one that is picked. Phones and
   tablets get a 44 row at 16px, a size a thumb can hit and iOS will not
   zoom into; desktop is the Figma row. */
.ds-option {
  flex: none;
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0.625rem 0.75rem;
  border-radius: var(--radius);
  font-family: var(--f-sans);
  font-size: 1rem;
  line-height: 1.5rem;
  color: var(--c-text);
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

@media (min-width: 1200px) {
  .ds-option {
    min-height: 28px;
    padding: 0.25rem 0.5rem;
    font-size: 0.8125rem;
    line-height: 1.25rem;
  }
}

.ds-option.is-active {
  background: var(--op-050);
}

.ds-option[aria-selected="true"] {
  background: var(--op-100);
}

@media (prefers-reduced-motion: reduce) {
  .ds-list {
    animation-name: ds-list-fade;
  }
}

@keyframes ds-list-fade {
  from {
    opacity: 0;
  }
}

/* Segmented radios: native inputs, so arrow keys move between options. */
.ds-seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  max-width: 100%;
}

.ds-seg__opt {
  position: relative;
  display: inline-flex;
}

.ds-seg__face {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding: 0 0.75rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  /* Figma ds-seg-option at rest: Background/Default/Nav over Background/
     Utilities/Blanket under a background blur of 48, the nav's glass. */
  background: linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
  font-family: var(--f-sans);
  font-size: 0.8125rem;
  line-height: 1.25rem;
  color: var(--c-text-2);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* Figma ds-seg-option: hover and selected take Button/Background/Primary
   Hover and Pressed (the same values); an icon option's glyph turns lime. */
@media (hover: hover) and (pointer: fine) {
  .ds-seg__opt:hover .ds-seg__face {
    background: var(--c-btn-primary-hover);
    border-color: var(--c-btn-primary-hover);
    color: var(--c-btn-primary-fg-hover);  /* the primary button's label: white on ink in Light, ink on chalk in Dark */
    box-shadow: 0 2px 3px rgb(0 0 0 / 0.06), 0 8px 12px rgb(0 0 0 / 0.12);
  }

  .ds-seg--icons .ds-seg__opt:hover .ds-seg__face {
    color: var(--c-btn-primary-icon);
  }
}

.ds-seg__opt input:checked + .ds-seg__face {
  background: var(--c-btn-primary-hover);
  border-color: var(--c-btn-primary-hover);
  color: var(--c-btn-primary-fg-hover);  /* the primary button's label: white on ink in Light, ink on chalk in Dark */
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.04);
}

.ds-seg--icons .ds-seg__opt input:checked + .ds-seg__face {
  color: var(--c-btn-primary-icon);
}

.ds-seg__opt input:focus-visible + .ds-seg__face {
  outline: 2px solid var(--c-text);
  outline-offset: 2px;
}

.ds-seg--icons .ds-seg__face {
  min-width: 32px;
  min-height: 32px;
  padding: 0;
}

/* The None option is a word, so it keeps the text option's inset. */
.ds-seg--icons .ds-seg__face:not(:has(svg)) {
  padding: 0 0.75rem;
}

.ds-seg--icons .ds-seg__face svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Switch */
.ds-switch {
  appearance: none;
  position: relative;
  width: 38px;
  height: 22px;
  margin: 0;
  border: 1px solid var(--ds-rule);
  border-radius: 11px;
  background: linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);  /* Figma ds-switch off: Nav over Blanket */
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.ds-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--ds-dim);
  transition: transform var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.ds-switch:checked {
  background: var(--c-ink);  /* ink in Light */
  border-color: var(--c-text);
}

.ds-switch:checked::after {
  background: var(--c-btn-primary-icon);  /* lime on the ink track */
  transform: translateX(16px);
}

/* Dark: on fills lime and the knob turns ink, the accent button's pair. */
:root[data-theme="dark"] .ds-switch:checked {
  background: var(--c-accent);
  border-color: var(--c-accent);
}

:root[data-theme="dark"] .ds-switch:checked::after {
  background: var(--c-ink);
}

.ds-switch:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: 2px;
}

/* Range */
.ds-range {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 36px;
}

/* Figma ds-range: a 4px rail, ink up to the value, a 16px lime thumb in a
   3px Button/Background/Primary ring. --p is set by js/ds-playground.js. */
.ds-range input {
  flex: 1 1 auto;
  height: 16px;
  margin: 0;
  appearance: none;
  background: none;
  cursor: pointer;
}

.ds-range input::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(to right, var(--c-text) var(--p, 0%), var(--c-line) var(--p, 0%));
}

.ds-range input::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--c-line);
}

.ds-range input::-moz-range-progress {
  height: 4px;
  border-radius: 2px;
  background: var(--c-text);
}

.ds-range input::-webkit-slider-thumb {
  -webkit-appearance: none;
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  margin-top: -6px;
  border: 3px solid var(--c-btn-primary);
  border-radius: 50%;
  background: var(--c-btn-primary-icon);
}

.ds-range input::-moz-range-thumb {
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  border: 3px solid var(--c-btn-primary);
  border-radius: 50%;
  background: var(--c-btn-primary-icon);
}

.ds-range input:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: 4px;
}

.ds-range output {
  min-width: 2ch;
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--c-text);
  text-align: right;
}

/* ---------- Inside a canvas frame ----------------------------------------- */
/* design-system.css also loads in every canvas, for these. */

.ds-frame,
.ds-frame body {
  margin: 0;
  background: var(--c-bg);
}

.ds-frame body {
  overflow: hidden;
}

.ds-frame body::before {
  display: none;
}

.ds-root {
  box-sizing: border-box;
}

.ds-root--centered {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 3rem 2rem;
}

.ds-root--centered > .field {
  flex: 0 1 440px;
}

.ds-root--centered > .ds-row {
  justify-content: center;
}

.ds-root--padded {
  padding: 2rem;
}

.ds-root--fullscreen {
  padding: 0;
}

@media (max-width: 767px) {
  .ds-root--centered {
    padding: 2rem 1.25rem;
  }

  .ds-root--padded {
    padding: 1.5rem 1.25rem;
  }
}

/* The nav is fixed to the frame's own top, so the frame holds its height. */
.ds-root.ds-demo--frame {
  min-height: 120px;
}

.ds-frame .ds-demo--frame .nav {
  position: absolute;
}

.ds-frame .ds-root.ds-demo--frame {
  position: relative;
}

.ds-outlined #ds-root * {
  outline: 1px dashed #e0368c99;
  outline-offset: -1px;
}

.ds-ruler {
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  pointer-events: none;
  visibility: hidden;
}

.ds-ruler.is-on {
  visibility: visible;
}

.ds-ruler i,
.ds-ruler b {
  position: fixed;
  display: block;
}

.ds-ruler__m { background: #f6b26b55; }
.ds-ruler__p { background: #93c47d66; }
.ds-ruler__c { background: #6fa8dc66; }

.ds-ruler__tag {
  height: 20px;
  padding: 0 6px;
  border-radius: 3px;
  background: #1c1d1f;
  color: #ffffff;
  font: 500 11px/20px var(--f-mono);
  white-space: pre;
}

.ds-measuring #ds-root,
.ds-measuring #ds-root * {
  cursor: crosshair !important;
}

/* A full-width card at desktop: canvas on the left, controls in a panel on
   the right, the way a workbench is laid out. Halves keep them underneath. */
@media (min-width: 1200px) {
  .ds-story:not(.ds-story--half):has(> .ds-controls) {
    grid-template-columns: minmax(0, 1fr) minmax(320px, 30%);
  }

  .ds-story:not(.ds-story--half):has(> .ds-controls) > .ds-story__head {
    grid-column: 1 / -1;
  }

  .ds-story:not(.ds-story--half):has(> .ds-controls) > .ds-canvas {
    grid-row: 2 / 4;
  }

  /* The panel never sets the card's height: the canvas does, and a long
     panel scrolls inside it. */
  .ds-story:not(.ds-story--half) > .ds-controls {
    grid-column: 2;
    grid-row: 2 / 4;
    contain: size;
    display: flex;
    flex-direction: column;
    border-top: 0;
    border-left: 1px solid var(--ds-rule);
    overflow: hidden;
  }

  /* The heading stays put and only the rows under it scroll, so the
     scrollbar starts below the heading instead of running beside it. */
  .ds-story:not(.ds-story--half) > .ds-controls .ds-controls__head {
    flex: none;
  }

  .ds-story:not(.ds-story--half) > .ds-controls .ds-controls__grid {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .ds-story:not(.ds-story--half) > .ds-controls .ds-ctl {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
  }

  /* Figma ds-ctl layout=stacked in the side panel: fields and sliders fill
     the panel; segments and switches keep to its right edge (above). */
  .ds-story:not(.ds-story--half) > .ds-controls .ds-ctl__input > .ds-input,
  .ds-story:not(.ds-story--half) > .ds-controls .ds-ctl__input > .ds-select {
    max-width: none;
  }

  .ds-story:not(.ds-story--half) > .ds-controls .ds-ctl__input > :is(.ds-input, .ds-select, .ds-range) {
    flex: 1 1 auto;
  }

  .ds-story:not(.ds-story--half):has(> .ds-controls) .ds-canvas .ds-stage--live {
    min-height: 380px;
  }
}

/* The icon playground: the glyph at size, and at 8x on its 24px grid so the
   2px stroke and round joins can be read. */
.ds-iconview {
  display: flex;
  align-items: center;
  gap: 3rem;
}

.ds-iconview__zoom {
  display: grid;
  place-items: center;
  width: 192px;
  height: 192px;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  background-color: var(--c-bg);
  background-image: linear-gradient(var(--c-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--c-line) 1px, transparent 1px);
  background-size: 8px 8px;
  background-position: -1px -1px;
}

.ds-iconview__zoom .icon {
  transform: scale(8);
}

.ds-iconview__zoom .icon--20 { transform: scale(9.6); }
.ds-iconview__zoom .icon--16 { transform: scale(12); }

/* Phones: the tabs and the tools take a row each, so nothing hides off the
   edge of the toolbar. */
@media (max-width: 767px) {
  .ds-toolbar {
    flex-wrap: wrap;
    gap: 0;
    min-height: 0;
    padding: 0;
    border-bottom: 1px solid var(--ds-rule);
    box-shadow: none;
    overflow: visible;
  }

  /* Nothing scrolls here, so the underline sits on the tools' top rule. */
  .ds-tab::after {
    bottom: -1px;
  }

  .ds-tabs {
    min-height: var(--ds-bar-h);
    padding-left: 0.375rem;
  }

  /* The Fill pill starts where the selected tab's underline starts, on
     the card's 20 edge, and the code glyph ends 20 in, matching the left. */
  .ds-tools {
    flex: 1 1 100%;
    justify-content: space-between;
    padding: 0.75rem 0.875rem 0.75rem 1.25rem;  /* Figma ds-tools: Space/300 above and below */
    border-top: 1px solid var(--ds-rule);
  }
}

.ds-iconview__real {
  display: inline-flex;
}

/* =============================================================================
   Motion. Every value comes from the site's tokens: --press-dur and
   --press-ease for presses, --dur with --ease or --arrow-ease for the rest.
   ========================================================================== */

/* Press: the page's own controls give under a press the way .btn does. */
.ds-tool,
.ds-tab,
.ds-seg__face,
.ds-copy,
.ds-reset {
  transition-property: background-color, color, border-color, box-shadow, transform;
  transition-duration: var(--dur), var(--dur), var(--dur), var(--dur), var(--press-dur);
  transition-timing-function: var(--ease), var(--ease), var(--ease), var(--ease), var(--press-ease);
}

.ds-tool:active,
.ds-tab:active,
.ds-seg__opt:active .ds-seg__face,
.ds-copy:active,
.ds-reset:active {
  transform: scale(0.97);
}

/* A canvas fades in once its first render has a height. */
.ds-frame-el {
  opacity: 0;
  transition: opacity var(--dur-fast) var(--arrow-ease);
}

.ds-frame-el.is-ready {
  opacity: 1;
}

.ds-port {
  transition: background-color var(--dur) var(--ease);
}

/* A new section rises in a little, so Previous and Next read as moving
   somewhere. Entering only: leaving never holds the next page up. The
   content moves, not the section, since a transform on the section would
   carry the fixed pager inside it along for the ride. */
.motion .ds-paged .ds-section.is-active > :not(.ds-pager),
.motion .ds-paged .ds-head.is-active > :not(.ds-pager),
.motion.ds-paged .ds-section.is-active > :not(.ds-pager),
.motion.ds-paged .ds-head.is-active > :not(.ds-pager) {
  transition: opacity var(--dur) var(--arrow-ease), transform var(--dur) var(--arrow-ease);
}

@starting-style {
  .motion.ds-paged .ds-section.is-active > :not(.ds-pager),
  .motion.ds-paged .ds-head.is-active > :not(.ds-pager) {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* Copy: the copy glyph gives way to a check, scaling and sharpening in. */
.ds-copy__glyphs {
  display: grid;
  width: 16px;
  height: 16px;
}

.ds-copy__glyphs .ds-ui {
  grid-area: 1 / 1;
  transition: opacity var(--dur-fast) var(--arrow-ease), transform var(--dur-fast) var(--arrow-ease), filter var(--dur-fast) var(--arrow-ease);
}

.ds-copy__glyphs .ds-ui:last-child,
.ds-copy.is-done .ds-copy__glyphs .ds-ui:first-child {
  opacity: 0;
  transform: scale(0.6);
  filter: blur(2px);
}

.ds-copy.is-done .ds-copy__glyphs .ds-ui:last-child {
  opacity: 1;
  transform: none;
  filter: none;
}

/* A control that folds away: the rows under it slide up instead of jumping. */
.ds-fold {
  display: grid;
  grid-template-rows: 1fr;
  overflow: hidden;
  transition: grid-template-rows var(--dur) var(--ease), opacity var(--dur-fast) var(--arrow-ease);
}

.ds-fold > .ds-ctl {
  min-height: 0;
  overflow: hidden;
  border-top: 1px solid var(--ds-rule);
}

.ds-fold.is-folded {
  grid-template-rows: 0fr;
  opacity: 0;
}

/* Padding and the rule do not shrink with the track, so they fold too. */
.ds-fold > .ds-ctl {
  transition: padding var(--dur) var(--ease), border-top-width var(--dur) var(--ease);
}

.ds-fold.is-folded > .ds-ctl {
  padding-block: 0;
  border-top-width: 0;
}

.ds-fold + .ds-ctl {
  border-top: 1px solid var(--ds-rule);
}

.ds-fold:first-child > .ds-ctl {
  border-top: 0;
}

/* Reduced motion: fades stay, travel goes. */
@media (prefers-reduced-motion: reduce) {
  .ds-tool:active,
  .ds-tab:active,
  .ds-seg__opt:active .ds-seg__face,
  .ds-copy:active,
  .ds-reset:active {
    transform: none;
  }

  .ds-copy__glyphs .ds-ui:last-child,
  .ds-copy.is-done .ds-copy__glyphs .ds-ui:first-child {
    transform: none;
    filter: none;
  }

  .ds-fold {
    transition: none;
  }
}

/* The label sizes to its word, so Copy sits with even padding on both sides. */
.ds-copy__label {
  text-align: left;
}

/* The menu and close glyph's morph lives in css/styles.css, shared with the
   site. A mobile menu shown open as a specimen has no .is-menu-open around
   it, so its close button is drawn as the X here. */
.ds-static .mobile-menu__head .menu-icon__bar--a {
  translate: 0 3px;
  rotate: 45deg;
}

.ds-static .mobile-menu__head .menu-icon__bar--b {
  translate: 0 -3px;
  rotate: -45deg;
}

/* ---------- Back to the site ------------------------------------------------
   The logo opens the design system's own overview, so the way back to the
   portfolio is a labelled link: in the top bar beside the theme toggle, in
   the same frosted ground, and at the foot of the side panel. */
.ds-topbar__end {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* .ds-sitelink is the site's nav button (css/styles.css .nav-btn) with
   the arrow leading. Only where it differs is set here. */

/* In the panel it leads the foot, as a plain line above the socials. */
.ds-sitelink--panel {
  align-self: flex-start;
  height: auto;
  margin: 0 0 2.5rem -0.125rem;  /* Figma: 8 + 40 to the socials */
  padding: 0;
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

@media (hover: hover) and (pointer: fine) {
  .ds-sitelink--panel:hover {
    background: none;
    box-shadow: none;
    text-decoration: underline;
    text-underline-offset: 4px;
  }
}

.ds-sitelink--panel:active {
  box-shadow: none;
}

/* =============================================================================
   Foundations, drawn rather than tabled. tools/ds_tokens.py writes these from
   data/figma-library.json (the library) and css/styles.css (what ships).
   ========================================================================== */

/* ---------- Previous / next: the site's own buttons --------------------- */

.ds-pager__btn {
  min-width: 0;
  max-width: calc(50% - 0.375rem);
  /* Figma button size=large: 20 in from each side. */
  padding-inline: 1.25rem;
}

/* Figma ds-pager: Previous is the tertiary button on the nav's glass,
   Background/Default/Nav over Background/Utilities/Blanket under the 128
   background blur every button carries. */
.ds-pager__btn.btn--tertiary {
  background: linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);
}

.ds-pager__btn.btn--tertiary:focus-visible {
  background: linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);
}

/* Hover keeps the glass and lifts; press lays a second tint over it. */
@media (hover: hover) and (pointer: fine) {
  .ds-pager__btn.btn--tertiary:hover {
    background: linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);
  }
}

.ds-pager__btn.btn--tertiary:active {
  background: linear-gradient(var(--c-nav), var(--c-nav)), linear-gradient(var(--c-nav), var(--c-nav)), var(--c-blanket);
}

.ds-pager__btn span:not(.icon) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Back and forward arrows step along their own axis rather than turning the
   way the site's diagonal arrows do. */
.ds-pager__btn .icon,
.ds-pager__btn:focus-visible .icon,
.ds-pager__btn:active .icon {
  transform: none;
  transition: translate var(--arrow-dur) var(--arrow-ease);
}

@media (hover: hover) and (pointer: fine) {
  .ds-pager__btn:hover .icon {
    transform: none;
    transition: translate var(--arrow-dur) var(--arrow-ease);
  }
}

@media (hover: hover) and (pointer: fine) {
  .ds-pager__btn:hover .icon {
    translate: -3px 0;
  }

  .ds-pager__btn--next:hover .icon {
    translate: 3px 0;
  }
}

.ds-pager__btn--next {
  margin-left: auto;
}

/* The strip is part of the window, not the page. motion.js would reveal it
   with each section's content, so it would rise on every page change.
   Instead it rises once, with the first page, and then stays put. */
.motion .ds-pager[data-reveal] {
  opacity: 1;
  transform: none;
  transition: none;
}

.motion.ds-paged:not(.ds-pager-settled) .ds-pager {
  animation: ds-pager-in 600ms var(--ease-out-expo) 200ms both;
}

@keyframes ds-pager-in {
  from {
    opacity: 0;
    transform: translate3d(0, 100%, 0);
  }
}

@media (max-width: 767px) {
  .ds-pager {
    gap: 1.125rem;
  }

  /* Two equal halves on a phone, whatever the labels say, so the buttons
     never change width from one section to the next. A long label ends in
     an ellipsis rather than pushing its neighbour. */
  .ds-pager__btn {
    width: auto;
    flex: 1 1 0;
    min-width: 0;
    max-width: none;
    height: 48px;
    padding-inline: 1.375rem;
  }
}

/* ---------- Shared group heads ------------------------------------------- */

.ds-ramp-group,
.ds-prim-group {
  margin-top: 3rem;
  scroll-margin-top: 96px;
}

.ds-ramp-group:first-of-type,
.ds-prim-group:first-of-type {
  margin-top: 1.5rem;  /* Figma ds-section: 24 under the head */
}

.ds-ramp-group__head {
  display: grid;
  gap: 0.25rem;
  margin-bottom: 1rem;
}

.ds-ramp-group__name {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 1.25rem;
  line-height: 1.875rem;
  color: var(--c-text);
}

.ds-ramp-group__meta {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
}

.ds-ramp-group__meta b {
  font-weight: 500;
  color: var(--c-text);
}

.ds-ramp-group__note {
  margin: 0.125rem 0 1rem;
  font-family: var(--f-sans);
  font-size: 0.875rem;
  line-height: 1.5rem;
  color: var(--c-text-2);  /* Typography/Default/Secondary */
}

.ds-ramp-group__head .ds-ramp-group__note {
  margin: 0;  /* Figma ds-group-head: the head's 4px gap only */
}

/* Jump list for the ten ramps. */
.ds-ramp-index {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.ds-ramp-filter {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: 32px;
  padding: 0 0.75rem 0 0.5rem;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--ds-panel);
  font-family: var(--f-sans);
  font-size: 0.8125rem;
  color: var(--c-text);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
    color var(--dur) var(--ease), transform var(--press-dur) var(--press-ease);
}

.ds-ramp-filter[data-ramp="all"] {
  padding-left: 0.75rem;
}

@media (hover: hover) and (pointer: fine) {
  .ds-ramp-filter:hover {
    border-color: var(--c-text);
    box-shadow: 0 2px 3px rgb(0 0 0 / 0.06), 0 8px 12px rgb(0 0 0 / 0.12);
  }
}

.ds-ramp-filter:active {
  transform: scale(0.97);
}

/* The chosen filter: the site's ink button, so it reads as selected. */
.ds-ramp-filter[aria-pressed="true"] {
  border-color: var(--c-text);
  background: var(--c-text);
  color: var(--c-bg);
}

/* Dark swatches (the brand ink, black) need an edge on the dark page. */
:root[data-theme="dark"] .ds-ramp-index span {
  box-shadow: inset 0 0 0 1px #ffffff33;
}

/* Selected, Black, White and Lime show their full 1000 step rather than the
   half-strength 500 they wear at rest. */
.ds-ramp-filter[aria-pressed="true"] span,
:root[data-theme="dark"] .ds-ramp-filter[aria-pressed="true"] span {
  background: var(--ds-chip-on, var(--ds-chip));
  /* The inner edge keeps a square that matches its chip in view: Ink on the
     ink chip in Light, Chalk on the white chip in Dark. */
  box-shadow: 0 0 0 1px var(--c-bg), inset 0 0 0 1px color-mix(in srgb, var(--c-bg) 40%, transparent);
}

.ds-ramp-group[hidden] {
  display: none;
}

.ds-ramp-index span {
  background: var(--ds-chip);
  width: 14px;
  height: 14px;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px #0000001f;
}

/* White would vanish into the white chip, so its square carries a clear
   1px border of its own, in every state. */
.ds-ramp-filter[data-ramp="ramp-white"] span,
:root[data-theme="dark"] .ds-ramp-filter[data-ramp="ramp-white"] span {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ds-black-1000) 40%, transparent);
}

.ds-ramp-filter[data-ramp="ramp-white"][aria-pressed="true"] span {
  box-shadow: 0 0 0 1px var(--c-bg), inset 0 0 0 1px color-mix(in srgb, var(--ds-black-1000) 40%, transparent);
}

/* ---------- Color cards --------------------------------------------------- */

/* Figma ds-colors: cards at least 200 wide, 16 apart, wrapping to as many
   as the width holds (six at 1440, three at 768, one at 390). */
.ds-colors {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
}

.ds-color {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 0;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--ds-panel);
  color: var(--c-text);
  text-align: left;
  font: inherit;
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
    transform var(--press-dur) var(--press-ease);
}

@media (hover: hover) and (pointer: fine) {
  .ds-color:hover {
    border-color: var(--c-text-3);
    box-shadow: 0 2px 3px rgba(0, 0, 0, 0.06), 0 8px 12px rgba(0, 0, 0, 0.12);
  }
}

.ds-color:active {
  transform: scale(0.97);
}

.ds-color:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: 2px;
}

/* Figma ds-color: a 104px chip over an Opacity/050 rule. */
.ds-color__chip {
  position: relative;
  display: block;
  height: 104px;
  border-bottom: 1px solid var(--op-050);
}

.ds-color__paint {
  position: absolute;
  inset: 0;
}

/* Alpha steps sit on a checker so transparency reads as transparency. */
.ds-color__chip--on-light,
.ds-color__chip--on-mid {
  /* The checker stops at the rule, or its white shows through the rule's 5%
     and draws a bright line in Dark. */
  background-clip: padding-box;
  background-size: 12px 12px;
  background-position: 0 0, 6px 6px;
}

.ds-color__chip--on-light {
  background-color: #ffffff;
  background-image: linear-gradient(45deg, #e4e4e4 25%, transparent 25%, transparent 75%, #e4e4e4 75%),
    linear-gradient(45deg, #e4e4e4 25%, transparent 25%, transparent 75%, #e4e4e4 75%);
}

.ds-color__chip--on-mid {
  background-color: #8a8a8a;
  background-image: linear-gradient(45deg, #9c9c9c 25%, transparent 25%, transparent 75%, #9c9c9c 75%),
    linear-gradient(45deg, #9c9c9c 25%, transparent 25%, transparent 75%, #9c9c9c 75%);
}

.ds-color__aa {
  position: absolute;
  left: 0.75rem;
  bottom: 0.5rem;
  font-family: var(--f-sans);
  font-weight: 500;
  font-size: 0.9375rem;
  line-height: 1;
}

.ds-color__aa small {
  font-family: var(--f-mono);
  font-weight: 400;
  font-size: 0.625rem;
}

.ds-color__meta {
  display: grid;
  gap: 0.125rem;
  padding: 0.5rem 0.75rem 0.75rem;
}

.ds-color__step {
  font-family: var(--f-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.125rem;
}

.ds-color__hex {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--ds-dim);
}

.ds-color.is-copied .ds-color__hex {
  color: var(--c-text);
}

.ds-color__token {
  margin-top: 0.25rem;
  font-family: var(--f-mono);
  font-size: 0.625rem;
  line-height: 1rem;
  color: var(--c-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-color__token--lib {
  color: var(--ds-dim);
}

/* ---------- Primitive chips ---------------------------------------------- */

.ds-prims {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ds-prim {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  padding: 0.5rem 0.75rem 0.5rem 0.5rem;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--ds-panel);
}

.ds-prim__chip {
  position: relative;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--op-100);  /* Opacity/100 */
}

.ds-prim__chip > span {
  position: absolute;
  inset: 0;
}

.ds-prim__name {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  color: var(--c-text);
}

.ds-prim__hex {
  margin-left: auto;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  color: var(--ds-dim);
}

/* ---------- Semantic split cards ---------------------------------------- */

.ds-sems {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ds-sems--op {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

@media (min-width: 1200px) {
  .ds-sems--op {
    grid-template-columns: repeat(7, minmax(0, 1fr));
  }
}

.ds-sem {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--ds-panel);
  overflow: hidden;
}

.ds-sem__chip {
  display: flex;
  height: 84px;
  border-bottom: 1px solid var(--ds-rule);
}

.ds-sem__half {
  position: relative;
  flex: 1 1 50%;
}

.ds-sem__half > span {
  position: absolute;
  inset: 14px;
  border-radius: 3px;
}

.ds-sem__half--light > span {
  box-shadow: inset 0 0 0 1px #0000001a;
}

.ds-sem__half--dark > span {
  box-shadow: inset 0 0 0 1px var(--ds-white-150);  /* Chalk/150, on the dark half in both themes */
}

.ds-sem__body {
  display: grid;
  gap: 0.25rem;
  padding: 0.75rem 0.875rem 0.875rem;
}

.ds-sem__name {
  font-family: var(--f-mono);
  font-size: 0.8125rem;
  line-height: 1.125rem;
  font-weight: 500;
  color: var(--c-text);
}

.ds-sem__fig {
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
}

.ds-sem__vals {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--c-text);
}

.ds-sem__vals b {
  font-weight: 400;
  color: var(--ds-dim);
}

.ds-sem__via {
  font-family: var(--f-sans);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--ds-dim);
}

.ds-sem__via code {
  font-family: var(--f-mono);
  color: var(--c-text);
}

/* ---------- Text styles --------------------------------------------------- */

.ds-type-group {
  margin-top: 1.25rem;
  padding: 1.25rem 1.25rem 0.5rem;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--ds-panel);
}

.ds-section > .ds-type-group:first-of-type {
  margin-top: 0;
}

.ds-ts-list {
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
}

.ds-ts {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
  padding: 1.25rem 0;
  border-top: 1px solid var(--ds-rule);
}

@media (min-width: 768px) {
  .ds-ts {
    grid-template-columns: 180px minmax(0, 1fr);
    gap: 2rem;
    align-items: center;
  }
}

.ds-ts__meta {
  display: grid;
  gap: 0.25rem;
}

.ds-ts__name {
  font-family: var(--f-sans);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--c-text);
}

.ds-ts__spec {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--ds-dim);
}

/* A specimen never wraps: it scrolls sideways, so the style is always seen
   at its true size and line height. */
.ds-ts__sample {
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.ds-ts__sample:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: 2px;
}

.ds-ts__sample p {
  margin: 0;
  white-space: nowrap;
  color: var(--c-text);
}

/* ---------- Spacing ------------------------------------------------------- */

.ds-space {
  display: flex;
  align-items: flex-end;
  gap: 0.375rem;
  margin: 0.5rem 0 0;
  padding: 0 0 1rem;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.ds-space:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: 2px;
}

.ds-space__step {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  gap: 0.375rem;
  width: 34px;
}

.ds-space__bar {
  display: block;
  width: 16px;
  height: max(var(--v), 1px);
  border-radius: 2px;
  background: var(--c-text);
}

.ds-space__px {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  color: var(--c-text);
}

.ds-space__name {
  font-family: var(--f-mono);
  font-size: 0.625rem;
  color: var(--ds-dim);
}

.ds-shapes {
  display: grid;
  gap: 1.5rem;
  padding-bottom: 1.25rem;
}

@media (min-width: 1024px) {
  .ds-shapes {
    grid-template-columns: 2fr 1fr 1.2fr;
  }
}

.ds-radii {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1.25rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}

.ds-radius {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.375rem;
}

.ds-radius__box,
.ds-stroke {
  display: block;
  width: 56px;
  height: 56px;
  background: var(--c-overlay);
}

.ds-radius__box {
  border: 1px solid var(--c-text);
}

.ds-stroke {
  border: 0 solid var(--c-text);
  border-radius: 0;
}

.ds-iconbox {
  display: grid;
  place-items: center;
  color: var(--c-text);
}

.ds-iconbox svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Rhythm: each token three times, one bar per breakpoint. */
.ds-rhythms {
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
}

.ds-rhythm {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
  padding: 0.875rem 0;
  border-top: 1px solid var(--ds-rule);
}

.ds-rhythm--head {
  display: none;
}

@media (min-width: 768px) {
  .ds-rhythm,
  .ds-rhythm--head {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    gap: 1.5rem;
    align-items: center;
  }

  .ds-rhythm--head {
    border-top: 0;
    padding-bottom: 0.25rem;
    font-family: var(--f-mono);
    font-size: 0.6875rem;
    color: var(--ds-dim);
  }
}

.ds-rhythm__name {
  display: grid;
  gap: 0.125rem;
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.375rem;  /* Figma ds-rhythm note: 12/22 */
  color: var(--ds-dim);
}

.ds-rhythm__name code {
  font-family: var(--f-mono);
  font-size: 0.8125rem;
  line-height: 1.125rem;  /* Figma ds-rhythm token: 13/18 */
  color: var(--c-text);
}

.ds-rhythm__bars {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}

.ds-rhythm__bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.ds-rhythm__bar::before {
  content: "";
  flex: none;
  width: min(var(--v), calc(100% - 2.5rem));
  height: 12px;
  border-radius: 2px;
  background: var(--c-text);
}

.ds-rhythm__bar span {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  color: var(--c-text);
}

/* ---------- Breakpoints + motion ---------------------------------------- */

.ds-frames,
.ds-durs,
.ds-eases {
  margin: 1rem 0 1.25rem;
  padding: 0;
  list-style: none;
}

.ds-frame-row {
  display: grid;
  gap: 0.5rem;
  padding: 0.75rem 0;
  border-top: 1px solid var(--ds-rule);
}

.ds-frame-row__bar {
  display: flex;
  align-items: center;
  min-width: 56px;
  height: 40px;
  padding: 0 0.75rem;
  border: 1px solid var(--c-text);
  border-radius: var(--radius);
  background: var(--c-overlay);
  font-family: var(--f-mono);
  font-size: 0.8125rem;
  color: var(--c-text);
}

.ds-frame-row__bar b {
  font-weight: 500;
}

.ds-frame-row__meta {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  color: var(--ds-dim);
}

.ds-frame-row__meta span {
  margin-right: 0.5rem;
  font-family: var(--f-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--c-text);
}

.ds-dur {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem 1rem;
  align-items: center;
  padding: 0.75rem 0;
  border-top: 1px solid var(--ds-rule);
}

/* Figma ds-durs from 768: 8 between rows. */
@media (min-width: 768px) {
  .ds-durs {
    display: grid;
    gap: 0.5rem;
  }

  .ds-dur {
    grid-template-columns: 220px minmax(0, 1fr) 64px;
  }
}

.ds-dur__name {
  display: grid;
  gap: 0.125rem;  /* Figma .ds-dur__name: 2 between token and note */
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
}

.ds-dur__name code {
  font-family: var(--f-mono);
  font-size: 0.8125rem;
  line-height: 1.125rem;
  color: var(--c-text);
}

.ds-dur__bar {
  display: block;
  height: 12px;
  border-radius: 2px;
  background: var(--c-text);
}

.ds-dur__ms {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  color: var(--c-text);
}

@media (max-width: 767px) {
  .ds-dur__bar {
    grid-column: 1 / -1;
    grid-row: 2;
  }
}

.ds-eases {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.75rem;
}

@media (min-width: 1024px) {
  .ds-eases {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.ds-ease {
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  align-content: start;
  gap: 0.75rem;
  padding: 1rem;
  border: 1px solid var(--ds-rule);
  border-radius: var(--radius);
  background: var(--op-050);  /* Background/Default/Secondary */
  outline: none;
}

.ds-ease:focus-visible {
  outline: 2px solid var(--c-text);
  outline-offset: 2px;
}

.ds-ease__plot {
  width: 100%;
  height: 140px;
  overflow: visible;
}

.ds-ease__axis {
  fill: none;
  stroke: var(--op-150);  /* Opacity/150 */
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.ds-ease__curve {
  fill: none;
  stroke: var(--c-text);
  stroke-width: 2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.ds-ease__track {
  position: relative;
  display: block;
  height: 12px;
  border-radius: 6px;
  background: var(--c-overlay);
}

.ds-ease__ball {
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--c-text);
  transition: left 900ms var(--curve);
}

.ds-ease:focus-visible .ds-ease__ball {
  left: calc(100% - 12px);
}

@media (hover: hover) and (pointer: fine) {
  .ds-ease:hover .ds-ease__ball {
    left: calc(100% - 12px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ds-ease__ball {
    transition: none;
  }
}

.ds-ease__name {
  display: grid;
  gap: 0.125rem;
  font-family: var(--f-sans);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
}

.ds-ease__name code {
  font-family: var(--f-mono);
  font-size: 0.8125rem;
  color: var(--c-text);
}

.ds-ease__val {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  line-height: 1rem;
  color: var(--ds-dim);
}

/* The canvas toolbar and the controls head sit side by side on a wide card,
   so they share one height: the controls head's, set by its Reset button. */
.ds {
  --ds-bar-h: 49px;
}

/* Phones: two color cards to a row. The gap stays Space/400, as at every
   width. */
@media (max-width: 767px) {
  .ds-colors {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .ds-color__meta {
    padding: 0.5rem 0.5rem 0.625rem;
  }

  .ds-color__aa {
    left: 0.5rem;
    font-size: 0.8125rem;
  }
}

/* The panel's head (logo and X) stays put; on a short screen the links and
   foot scroll under it, so the scrollbar starts below the head. */
.ds-nav__scroll {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 2.5rem;
  min-height: 0;
  padding-bottom: 2rem;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* While the glyph travels, the two real ones stay hidden; it lands on one. */
.is-menu-travelling [data-ds-menu] .menu-icon,
.is-menu-travelling [data-ds-close] .menu-icon {
  opacity: 0;
}

/* The overview fits the window and the sections after it scroll, so with a
   classic scrollbar (Windows, or macOS with a mouse) the bar would appear
   between them and push the whole page sideways. The page keeps the
   scrollbar's room reserved instead, so moving between sections never
   shifts anything. Canvases are excluded: their frames never scroll. */
html:not(.ds-frame) {
  scrollbar-gutter: stable;
}

/* =============================================================================
   Overview map: a bento of live line drawings, one per section, each a link.
   tools/ds_overview.py writes the markup; the drawings animate with SMIL, so
   they run with no script. Reduced motion holds each one on a drawn frame.

   One tinted panel per grid slides to whichever card is hovered or focused,
   positioned with CSS anchor positioning: the active card names itself the
   anchor and the panel's insets follow it.
   ========================================================================== */

.ds-map {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.ds-map__group {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.ds-map__head span {
  color: var(--ds-dim);
  margin-left: 0.5rem;  /* Figma ds-map-head: 8 */
}

.ds-bento {
  --bento-r: 14px;
  --bento-dur: 280ms;
  --bento-ease: var(--arrow-ease);
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-flow: row dense;
  grid-auto-rows: 1fr;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
  /* Each grid's panel only answers to its own cards. */
  anchor-scope: --ds-ill;
}

.ds-bento__cell {
  position: relative;
  z-index: 1;
  display: flex;
  min-width: 0;
}

/* Phones: the two leads and the breakpoints card run across. */
.ds-bento__cell--xl,
.ds-bento__cell--half,
.ds-bento__cell:has([href="#breakpoints"]) {
  grid-column: span 2;
}

@media (min-width: 768px) {
  .ds-bento {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
  }

  .ds-bento__cell--xl {
    grid-column: span 2;
    grid-row: span 2;
  }

  .ds-bento__cell--wide:not(:has([href="#player"])) {
    grid-column: span 2;
  }

  .ds-bento__cell:has([href="#breakpoints"]):not(.ds-bento__cell--wide) {
    grid-column: auto;
  }

  .ds-bento__cell--half {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1200px) {
  .ds-bento {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .ds-bento__cell--wide:has([href="#player"]),
  .ds-bento__cell--half {
    grid-column: span 2;
  }
}

/* ---------- The card ------------------------------------------------------ */

.ds-ill,
.ds-section__art {
  /* The Figma illustrations' palette: the library's illustrations/*
     variables, light here and dark below (see tools/ds_overview.py). */
  --ix-surface: #ffffff;
  --ix-ink: #0e0f10;
  --ix-on-lime: #0e0f10;
  --ix-n100: #e7e7e7;
  --ix-n200: #cfcfcf;
  --ix-n400: #b7b7b7;
  --ix-n500: #9f9f9f;
  --ix-n600: #868787;
  --ix-n700: #6e6f70;
  --ix-n800: #565758;
  --ix-n1000: #3e3f40;
  --ix-n1200: #262728;
  --ix-accent: #d7ff38;
  --ix-accent-1: #bbde24;
  --ix-accent-2: #88a217;
  --ix-accent-3: #748b12;
  --ix-accent-4: #445207;
}

.ds-ill {
  --accent: var(--ds-accent-50);
  --hue-ink: var(--h-700);
  --hue-tint: color-mix(in srgb, var(--h-wash, var(--h-100)) var(--h-wash-amt, 45%), var(--ds-bg));
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100%;
  border: 1px solid var(--ds-rule);
  border-radius: var(--bento-r);
  color: var(--c-text);
  transition: border-color var(--bento-dur) var(--bento-ease), transform var(--press-dur) var(--press-ease);
}

:root[data-theme="dark"] .ds-ill,
:root[data-theme="dark"] .ds-section__art {
  --ix-surface: #0e0f10;
  --ix-ink: #ffffff;
  --ix-n100: #262728;
  --ix-n200: #3e3f40;
  --ix-n400: #565758;
  --ix-n500: #6e6f70;
  --ix-n700: #9f9f9f;
  --ix-n800: #b7b7b7;
  --ix-n1000: #cfcfcf;
  --ix-n1200: #e7e7e7;
}

:root[data-theme="dark"] .ds-ill {
  --hue-ink: var(--h-300);
  --hue-tint: color-mix(in srgb, var(--h-wash, var(--h-900)) var(--h-wash-amt, 45%), var(--ds-bg));
}

.ds-ill__num {
  position: absolute;
  top: 0.875rem;
  right: 1rem;
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.375rem;
  color: var(--ds-dim);
}

.ds-ill__art {
  display: block;
  /* Rows share one height (see .ds-bento), and the drawing fills what the
     text leaves, so a wide card is as tall as a square one and a big card
     is two rows tall. */
  position: relative;
  flex: 1 1 auto;
  min-height: 10rem;
  /* Room under the drawing for the lifted name to rise into. */
  padding: 1.25rem 1.25rem 1.5rem;
}

/* The drawing fills its box without sizing it: the row decides the height. */
.ds-ill__art svg {
  position: absolute;
  inset: 1.25rem 1.25rem 1.5rem;
  display: block;
  width: calc(100% - 2.5rem);
  height: calc(100% - 2.75rem);
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.25;
}

.ds-ill__text {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 1rem 1.25rem 1.25rem;
}

/* The active card lifts its name and line by the call to action's height
   and the call to action rises into the space. Transforms only, so the
   card, and the row it sits in, never change size. */
.ds-ill__lede {
  display: flex;
  flex-direction: column;
  transition: translate var(--bento-dur) var(--bento-ease);
}

.ds-ill__name {
  font-family: var(--f-sans);
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.625rem;
}

.ds-bento__cell--xl .ds-ill__name {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 1.75rem;
  line-height: 2.25rem;
}

.ds-ill__meta {
  font-family: var(--f-sans);
  font-size: 0.875rem;
  line-height: 1.5rem;
  color: var(--ds-dim);
}

.ds-ill__cta {
  position: absolute;
  left: 1.25rem;
  right: 1.25rem;
  bottom: 1.25rem;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-family: var(--f-sans);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.5rem;
  color: var(--hue-ink);
  opacity: 0;
  translate: 0 0.5rem;
  transition: opacity var(--bento-dur) var(--bento-ease), translate var(--bento-dur) var(--bento-ease);
}

.ds-ill__cta .icon {
  color: currentColor;
  transition: translate var(--arrow-dur) var(--arrow-ease);
}

/* 112 units of track for 800 units of weight. */
/* Typography's drawing (661 x 372 units): the header face sweeps its
   variable cut while the dial runs its 260 units of track. */
.ds-ill .i-wght-x,
.ds-section__art .i-wght-x {
  font-family: "Clash Display Variable", var(--f-display);
  /* Sized so the cap height (0.67 em) spans the two guides exactly:
     79.3 units from the cap line at 89.2 to the baseline at 168.4. */
  font-size: 118.4px;
  font-weight: 200;
  fill: var(--ix-ink);
  stroke: none;
  animation: ds-wght-x 6s infinite;
}

/* The variable cut sweeps its whole weight axis, 200 to 700 and back,
   while the dial tracks it. */
@keyframes ds-wght-x {
  0%, 10% { font-weight: 200; animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
  45%, 55% { font-weight: 700; animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
  90%, 100% { font-weight: 200; }
}

.ds-ill .i-dial-x,
.ds-section__art .i-dial-x {
  animation: ds-dial-x 6s infinite;
}

@keyframes ds-dial-x {
  0%, 10% { transform: translateX(0); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
  45%, 55% { transform: translateX(260px); animation-timing-function: cubic-bezier(0.77, 0, 0.175, 1); }
  90%, 100% { transform: translateX(0); }
}

/* Off screen, or under reduced motion, the sweep stops. Reduced motion
   holds a semibold 600, the dial three fifths along. */
.ds-ill.is-off .i-wght-x,
.ds-ill.is-off .i-dial-x,
.ds-section__art.is-off .i-wght-x,
.ds-section__art.is-off .i-dial-x {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  .ds-ill .i-wght-x,
  .ds-section__art .i-wght-x {
    animation: none;
    font-weight: 600;
  }

  .ds-ill .i-dial-x,
  .ds-section__art .i-dial-x {
    animation: none;
    transform: translateX(208px);
  }
}

/* ---------- The active card ---------------------------------------------- */

@media (hover: hover) and (pointer: fine) {
  .ds-bento__cell:hover > .ds-ill {
    border-color: transparent;
  }

  .ds-bento__cell:hover .ds-ill__lede {
    translate: 0 -2.125rem;
  }

  .ds-bento__cell:hover .ds-ill__cta {
    opacity: 1;
    translate: 0 0;
  }

  .ds-bento__cell:hover .ds-ill__cta .icon {
    translate: 3px 0;
  }

  .ds-bento__cell:hover .ds-ill__num {
    color: var(--hue-ink);
  }
}

.ds-ill:focus-visible {
  border-color: transparent;
  outline: 2px solid var(--hue-ink);
  outline-offset: 2px;
}

.ds-ill:focus-visible .ds-ill__lede {
  translate: 0 -2.125rem;
}

.ds-ill:focus-visible .ds-ill__cta {
  opacity: 1;
  translate: 0 0;
}

.ds-ill:active {
  transform: scale(0.99);
}

/* ---------- The sliding panel -------------------------------------------- */

/* The six hues, from the Figma library ramps. A card carries its own; the
   panel takes the hue of whichever card is active. */
.ds-hue-0,
.ds-bento:has(> .ds-hue-0 > :focus-visible) .ds-bento__indicator {
  /* Figma Brand/Secondary 100, 300, 700, 900. The lime card washes with
     Lime/200 (the lime at 20%) in both themes rather than a ramp step. */
  --h-100: #caf028;
  --h-300: #aaca20;
  --h-700: #5d710d;
  --h-900: #293302;
  --h-wash: var(--ds-accent-50);
  --h-wash-amt: 20%;
}

@media (hover: hover) and (pointer: fine) {
  .ds-bento:has(> .ds-hue-0:hover) .ds-bento__indicator {
    /* Figma Brand/Secondary 100, 300, 700, 900, washed with Lime/200 */
    --h-100: #caf028;
    --h-300: #aaca20;
    --h-700: #5d710d;
    --h-900: #293302;
    --h-wash: var(--ds-accent-50);
    --h-wash-amt: 20%;
  }
}

.ds-hue-1,
.ds-bento:has(> .ds-hue-1 > :focus-visible) .ds-bento__indicator {
  /* Figma Blue 100, 300, 700, 900 */
  --h-100: #d0e2fe;
  --h-300: #98c0fc;
  --h-700: #0c64d1;
  --h-900: #062c5f;
}

@media (hover: hover) and (pointer: fine) {
  .ds-bento:has(> .ds-hue-1:hover) .ds-bento__indicator {
    /* Figma Blue 100, 300, 700, 900 */
    --h-100: #d0e2fe;
    --h-300: #98c0fc;
    --h-700: #0c64d1;
    --h-900: #062c5f;
  }
}

.ds-hue-2,
.ds-bento:has(> .ds-hue-2 > :focus-visible) .ds-bento__indicator {
  /* Figma Green 100, 300, 700, 900 */
  --h-100: #c5eace;
  --h-300: #70d18d;
  --h-700: #0f783d;
  --h-900: #033618;
}

@media (hover: hover) and (pointer: fine) {
  .ds-bento:has(> .ds-hue-2:hover) .ds-bento__indicator {
    /* Figma Green 100, 300, 700, 900 */
    --h-100: #c5eace;
    --h-300: #70d18d;
    --h-700: #0f783d;
    --h-900: #033618;
  }
}

.ds-hue-3,
.ds-bento:has(> .ds-hue-3 > :focus-visible) .ds-bento__indicator {
  /* Figma Yellow 100, 300, 700, 900 */
  --h-100: #fff0a1;
  --h-300: #fbd73d;
  --h-700: #a56a06;
  --h-900: #56340e;
}

@media (hover: hover) and (pointer: fine) {
  .ds-bento:has(> .ds-hue-3:hover) .ds-bento__indicator {
    /* Figma Yellow 100, 300, 700, 900 */
    --h-100: #fff0a1;
    --h-300: #fbd73d;
    --h-700: #a56a06;
    --h-900: #56340e;
  }
}

.ds-hue-4,
.ds-bento:has(> .ds-hue-4 > :focus-visible) .ds-bento__indicator {
  /* Figma Red 100, 300, 700, 900 */
  --h-100: #fed8d3;
  --h-300: #fda89d;
  --h-700: #c22826;
  --h-900: #561210;
}

@media (hover: hover) and (pointer: fine) {
  .ds-bento:has(> .ds-hue-4:hover) .ds-bento__indicator {
    /* Figma Red 100, 300, 700, 900 */
    --h-100: #fed8d3;
    --h-300: #fda89d;
    --h-700: #c22826;
    --h-900: #561210;
  }
}

.ds-hue-5,
.ds-bento:has(> .ds-hue-5 > :focus-visible) .ds-bento__indicator {
  /* Figma Slate 100, 300, 700, 900 */
  --h-100: #dbe2eb;
  --h-300: #b5bfcd;
  --h-700: #5f6979;
  --h-900: #29303a;
}

@media (hover: hover) and (pointer: fine) {
  .ds-bento:has(> .ds-hue-5:hover) .ds-bento__indicator {
    /* Figma Slate 100, 300, 700, 900 */
    --h-100: #dbe2eb;
    --h-300: #b5bfcd;
    --h-700: #5f6979;
    --h-900: #29303a;
  }
}

.ds-bento__indicator {
  --hue-tint: color-mix(in srgb, var(--h-wash, var(--h-100)) var(--h-wash-amt, 45%), var(--ds-bg));
}

:root[data-theme="dark"] .ds-bento__indicator {
  --hue-tint: color-mix(in srgb, var(--h-wash, var(--h-900)) var(--h-wash-amt, 45%), var(--ds-bg));
}

.ds-bento__indicator {
  display: none;
}

@supports (anchor-name: --a) {
  @media (hover: hover) and (pointer: fine) {
    .ds-bento__cell:hover > .ds-ill {
      anchor-name: --ds-ill;
    }
  }

  .ds-ill:focus-visible {
    anchor-name: --ds-ill;
  }

  .ds-bento__indicator {
    display: block;
    position: absolute;
    z-index: 0;
    position-anchor: --ds-ill;
    inset: anchor(inside);
    border-radius: var(--bento-r);
    background: var(--hue-tint, transparent);
    opacity: 0;
    pointer-events: none;
    transition:
      inset var(--bento-dur) var(--bento-ease),
      background-color var(--bento-dur) var(--bento-ease),
      opacity var(--dur-fast) var(--ease);
  }

  /* The panel takes the active card's hue. */
  .ds-bento:has(.ds-ill:focus-visible) .ds-bento__indicator {
    opacity: 1;
  }

  @media (hover: hover) and (pointer: fine) {
    .ds-bento:has(.ds-bento__cell:hover) .ds-bento__indicator {
      opacity: 1;
    }
  }

}

/* Without anchor positioning the active card fills with its own tint. */
@supports not (anchor-name: --a) {
  @media (hover: hover) and (pointer: fine) {
    .ds-bento__cell:hover > .ds-ill {
      background: var(--hue-tint);
    }
  }

  .ds-ill:focus-visible {
    background: var(--hue-tint);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ds-bento {
    --bento-dur: 0ms;
  }
}

@media (max-width: 767px) {
  .ds-ill__meta {
    display: none;
  }

  .ds-ill__art {
    min-height: 6.5rem;
  }

  .ds-ill__art svg {
    inset: 1rem 0.75rem 0.25rem;
    width: calc(100% - 1.5rem);
    height: calc(100% - 1.25rem);
  }

  .ds-ill__text {
    padding: 0.75rem 0.875rem 0.875rem;
  }

  .ds-ill__name {
    font-size: 0.9375rem;
    line-height: 1.375rem;
  }

  .ds-ill__num {
    top: 0.625rem;
    right: 0.75rem;
  }
}

/* Specimens are copied into their preview frames after js/motion.js has
   tagged the page's reveal targets, and no motion.js runs in a frame to
   reveal them, so anything tagged would sit at opacity 0 (the footer's two
   rows did, when you paged into the section). Frames show everything. */
html.ds-frame [data-reveal] {
  opacity: 1;
  transform: none;
  transition: none;
}

/* A breakpoint scaled down to fit (Story.zoomToFit) has nothing to scroll
   to, so it sits centred with no side fades. */
.ds-stage.is-zoomed {
  overflow-x: hidden;
}

.ds-stage.is-zoomed::before,
.ds-stage.is-zoomed::after {
  opacity: 0;
}

/* ---------- Top bar: the site nav's format, the design system's links ----
   Foundations and Components are label links with carets that open their
   sections, as Work does on the site, References included. Below
   768 the links fold into the menu button, which opens the side panel. */
.ds-topbar .nav__links {
  padding-inline: 1rem 1.25rem;
}

/* The section on screen, and the group it belongs to. */
.ds-topbar .nav__link[aria-current] {
  color: var(--c-text);
}

.ds-topbar .nav__link[aria-current]::after {
  transform: scaleX(1);
}

.ds-topbar .menu__link[aria-current] {
  color: var(--c-text);
}

.ds-topbar .menu__link[aria-current]::after {
  transform: scaleX(1);
}

/* With Overview in the pill, tablet widths have no room for the labelled
   way back, so from 768 to 1023 it rests as the arrow alone, the size of
   the theme toggle beside it (its name stays in aria-label). Hovering or
   focusing it opens the label out, and the pill eases down to 86% from its
   left edge to make the room, so the arrow says where it goes. */
@media (min-width: 768px) and (max-width: 1023px) {
  /* Pinned to the right edge so the label opens leftward, into the room
     the pill gives up, instead of pushing the toggle off the bar. */
  .ds-topbar__end {
    position: absolute;
    top: calc(var(--nav-pad-y) + var(--safe-t));
    right: var(--ds-edge);
    bottom: var(--nav-pad-y);
  }

  /* Slower than the 220ms colour fades and on the gentler site ease, so
     the open reads as a move the eye can follow, close to the dropdowns'
     staggered reveal. The label fades in behind the width so it never
     shows clipped. */
  .ds-topbar {
    --link-open: 480ms;
  }

  .ds-topbar .ds-sitelink {
    gap: 0;
    padding: 0 10px;
    transition: box-shadow var(--dur) var(--ease), transform var(--press-dur) var(--press-ease),
      padding var(--link-open) var(--ease), gap var(--link-open) var(--ease);
  }

  .ds-topbar .ds-sitelink span:not(.icon) {
    display: inline-block;
    max-width: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-width var(--link-open) var(--ease), opacity var(--dur-short) var(--ease);
  }

  .ds-topbar .nav__pill {
    transform-origin: left center;
    transition: scale var(--link-open) var(--ease);
  }

  .ds-topbar .ds-sitelink:focus-visible {
    gap: 0.375rem;
    padding: 0 0.875rem 0 0.625rem;
  }

  .ds-topbar .ds-sitelink:focus-visible span:not(.icon) {
    max-width: 8rem;
    opacity: 1;
    transition: max-width var(--link-open) var(--ease), opacity 320ms var(--ease) 140ms;
  }

  .ds-topbar:has(.ds-sitelink:focus-visible) .nav__pill {
    scale: 0.86;
  }
}

@media (min-width: 768px) and (max-width: 1023px) and (hover: hover) and (pointer: fine) {
  .ds-topbar .ds-sitelink:hover {
    gap: 0.375rem;
    padding: 0 0.875rem 0 0.625rem;
  }

  .ds-topbar .ds-sitelink:hover span:not(.icon) {
    max-width: 8rem;
    opacity: 1;
    transition: max-width var(--link-open) var(--ease), opacity 320ms var(--ease) 140ms;
  }

  .ds-topbar:has(.ds-sitelink:hover) .nav__pill {
    scale: 0.86;
  }
}

/* ---------- Agent Guide --------------------------------------------------- */

.ds-rules {
  display: grid;
  gap: 1rem 3rem;
  margin: 0;
  padding-left: 1.5rem;
  list-style: decimal;
  font-family: var(--f-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--c-text-2);
}

.ds-rules li::marker {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  color: var(--c-text-3);
}

.ds-rules b {
  font-weight: 600;
  color: var(--c-text);
}

.ds-rules code {
  font-family: var(--f-mono);
  font-size: 0.8125em;
  color: var(--c-text);
  overflow-wrap: anywhere;
}

/* Wide enough for two columns: read down the first, then the second. */
@media (min-width: 1200px) {
  .ds-rules {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(5, auto);
    grid-auto-flow: column;
    padding-left: 1.75rem;
  }
}

/* The prompt is prose, so it wraps instead of scrolling sideways. */
.ds-code--wrap code {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.ds-agent-prompt .ds-code--live {
  max-height: none;
}
