/* ============================================================================
 * base — reset, document defaults, ambient glow, typography primitives
 * ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  background: var(--bg); /* code-bg: inherit — page background inherits root overrides. */
  color: var(--text);
  font-family: var(--font-sans);
  font-weight: var(--weight-normal);
  /* rank: body */
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection {
  background: color-mix(in srgb, var(--accent) 30%, transparent); /* code-bg: inherit — selection paint is not a focus container. */
  color: var(--strong);
}

a {
  color: var(--accent);
  text-decoration: none;
}

/* -- The two typeface roles -----------------------------------------------
 * A heading is the display face, running text is the text face, and the
 * ELEMENT decides which — never the size. A size threshold would change a
 * heading's typeface halfway through a resize, which is the one thing a
 * reader notices. A component that wants a heading tag set in the text face
 * says so on its own rule, which outranks this one at (0,1,0); .ui-card__title,
 * .ui-drawer__title and .ui-confirm__title are the three that do.
 * why: docs/foundations.md#typefaces */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
}

/* The browser default for b/strong is 700, and at the 13px the kit's tables and
 * chat feeds run at, 700 stops reading as emphasis and starts reading as a
 * filled-in shape. The semibold step is the emphasis; the bold step stays
 * available to anything that asks for it by name.
 * why: docs/foundations.md#typefaces */
b,
strong {
  font-weight: var(--weight-semibold);
}

/* Ambient blurred glow — the deck's signature background depth.
   Place <span class="ui-glow ui-glow--purple"> absolutely inside a positioned
   parent. Two colour variants ship; scale/position with inline styles. */
.ui-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(100px);
  opacity: 0.5;
  pointer-events: none;
  z-index: 0;
  width: 420px;
  height: 420px;
}
.ui-glow--purple { background: radial-gradient(circle, var(--purple-light), transparent 70%); }
.ui-glow--green  { background: radial-gradient(circle, var(--green), transparent 70%); opacity: 0.28; }
.ui-glow--cyan   { background: radial-gradient(circle, var(--cyan), transparent 70%); opacity: 0.3; }

/* ----------------------------------------------------------------------------
 * Background treatments — drop-in page/section backdrops. Each is a ::before
 * layer, so add the class to a positioned wrapper and give the real content a
 * higher stacking context (position:relative;z-index:1). All read the accent /
 * glow tokens, so they re-theme with the sub-theme and work in dark + light.
 * -------------------------------------------------------------------------- */
[class*="ui-bg-"] { position: relative; }
[class*="ui-bg-"] > * { position: relative; z-index: 1; }
[class*="ui-bg-"]::before { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; }

/* Spotlight — a soft radial from the top-centre (auth cards, focused heroes). */
.ui-bg-spotlight::before {
  background: radial-gradient(620px 340px at 50% -12%, var(--glow-purple), transparent 70%); /* code-bg: inherit — a wash paints over a ground and behind a chip, so the opaque ground below it is the step. */
}
/* Grid — a faint token-coloured grid, masked to fade at the edges. */
.ui-bg-grid::before {
  background-image:
    linear-gradient(to right, var(--border) 1px, transparent 1px),
    linear-gradient(to bottom, var(--border) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: radial-gradient(circle at 50% 35%, #000, transparent 78%);
  mask-image: radial-gradient(circle at 50% 35%, #000, transparent 78%);
}
/* Dots — a subtle dot field for dashboards / technical surfaces. */
.ui-bg-dots::before {
  background-image: radial-gradient(var(--border) 1.4px, transparent 1.4px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(circle at 50% 35%, #000, transparent 80%);
  mask-image: radial-gradient(circle at 50% 35%, #000, transparent 80%);
}
/* Accent wash — a gentle top-down tint in the current accent. */
.ui-bg-wash::before {
  background: linear-gradient(180deg, var(--glow-purple), transparent 45%); /* code-bg: inherit — a wash paints over a ground and behind a chip, so the opaque ground below it is the step. */
}

/* Layout helpers used by the example apps */
.ui-container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 clamp(14px, 2.4vw, 26px); }
.ui-stack > * + * { margin-top: var(--space-4); }

/* Eyebrow — the label above a title or a figure, in sentence case like every
   label in the kit. why: docs/foundations.md#labels-and-titles */
.ui-eyebrow {
  /* rank: label */
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text);
}

/* Sensible default size for inline icons that a parent rule doesn't size.
   A floor, not a ceiling: :where() holds the whole filter at zero specificity,
   so this weighs (0,0,1) and any component rule that sizes an icon outranks it.
   The count of those rules is deliberately not written here — it moved once
   already, and two gates hold it over the ground each actually sweeps.
   */
svg:where(:not([width]):not([height])) {
  width: 1.1em;
  height: 1.1em;
  flex: none;
  vertical-align: -0.15em;
}

/* Focus-visible ring, shared by all interactive controls */
/* `.toggle` is the theme switch — a real button that wears neither .ui-btn nor
   .ui-focusable, in the vanilla topbar, React ThemeToggle and the React shell's bar
   alike, so keyboard focus on it fell back to the browser's own outline in all three.
   It has no class of its own to opt in with; it joins the list instead. Found on #385. */
/* `a` is here as an ELEMENT, not a class, because a link in running text is the one
   control a consumer writes with no class on it at all — so it took the browser's
   outline, which #457 refused. The net is over every anchor; a component that rings
   its own anchor outranks this at two classes and keeps the shape it chose. The band
   sits at whatever corner the link carries, which is the rule .ui-table's links
   already take. Found on #586, decided on #587. */
a:focus-visible,
.ui-focusable:focus-visible,
.ui-snippet :focus-visible,
.ui-btn:focus-visible,
.ui-input:focus-visible,
.ui-seg button:focus-visible,
.toggle:focus-visible,
.ui-switch:focus-visible {
  outline: var(--ring);
  outline-offset: var(--ring-offset);
}
