/* Vendored verbatim from the flytedesk Design System (Claude Design project "flytedesk Design System"), foundations/components.css. */
/* flytedesk components — class-based so hover/focus/press states are real CSS.
   Every value below traces to tokens/. Control heights are deliberately larger
   than the marketing-site spec (44px default, not 40px): the product is used for
   whole shifts and the brief asks for generous, calm hit areas. */

/* ============ Button ============ */
.fd-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  height: var(--control-h-md);
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-size: var(--body-size);
  font-weight: var(--w-semibold);
  letter-spacing: -0.005em;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  background: none;
  position: relative;
  isolation: isolate;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease),
    transform var(--dur-instant) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-btn:hover {
  text-decoration: none;
}
/* While a real mouse holds a button down, the pointer is over it, so :hover's own rule is
   also matching — but :hover and :active are equal specificity, and each variant's own
   :active rule below is declared after that variant's :hover rule, so the cascade resolves
   to :active's background/box-shadow, not :hover's. That is what gives an enabled button a
   pressed colour genuinely distinct from its hovered one, on top of the translateY here
   shared by every variant. */
.fd-btn:active {
  transform: translateY(1px);
}
/* The disabled look lives on the content and fill alone, both via tokens — never `opacity`
   on the whole element, which would also fade the :focus-visible ring drawn as this same
   element's box-shadow (see the ring rule just below). One flat, variant-independent fill
   (--surface-3/--border) and text/icon color (--text-disabled, inherited by the icon font
   and by .fd-spinner's `currentColor` border) replace every variant's own resting look while
   disabled — a disabled button never needs to keep reading as "primary" or "danger". */
.fd-btn[disabled],
.fd-btn[aria-disabled="true"] {
  cursor: not-allowed;
  background: var(--surface-3);
  border-color: var(--border);
  color: var(--text-disabled);
  box-shadow: none;
  transform: none;
}
.fd-btn-link[disabled],
.fd-btn-link[aria-disabled="true"] {
  background: none;
  border-color: transparent;
}
/* A focusableWhenDisabled button (aria-disabled, never native disabled) keeps the same
   :focus-visible ring an enabled button gets, drawn at full strength — that is the whole
   point of keeping it in the tab order. Restated here because the box-shadow:none above is a
   compound selector (0,2,0: one class + one attribute) that beats plain button:focus-visible
   from foundations.css (0,1,1: one element + one pseudo-class), so without this the ring
   never shows on a control Tab can still land on. Native [disabled] is included for symmetry
   — a real browser never actually gives a natively disabled control focus at all, so it
   never matches there, but nothing here should depend on that platform behaviour to stay
   correct. */
.fd-btn[disabled]:focus-visible,
.fd-btn[aria-disabled="true"]:focus-visible {
  box-shadow: var(--focus-ring);
}
/* A disabled or aria-disabled button never shows a hover or pressed look, in any variant —
   this compound selector (class + attribute + pseudo-class = 0,3,0) beats every variant's
   own :hover/:active (class + pseudo-class = 0,2,0) regardless of source order, so a real
   mouse hovering or pressing a disabled button sees only its resting disabled look. One rule
   suffices for every variant now that the disabled fill/text no longer vary by variant.
   box-shadow and transform are deliberately NOT restated here: the base [disabled]/
   [aria-disabled] rule above already sets both, and restating box-shadow here would tie this
   rule's specificity with the :focus-visible rule above it, letting a still-:hover'd (mouse
   left in place) focused button lose its ring to source order. */
.fd-btn[disabled]:hover,
.fd-btn[aria-disabled="true"]:hover,
.fd-btn[disabled]:active,
.fd-btn[aria-disabled="true"]:active {
  background: var(--surface-3);
  border-color: var(--border);
  color: var(--text-disabled);
}
.fd-btn-link[disabled]:hover,
.fd-btn-link[aria-disabled="true"]:hover,
.fd-btn-link[disabled]:active,
.fd-btn-link[aria-disabled="true"]:active {
  background: none;
  border-color: transparent;
  text-decoration: none;
}
.fd-btn-sm {
  height: var(--control-h-sm);
  padding: 0 14px;
  font-size: var(--body-sm-size);
  gap: 7px;
}
.fd-btn-lg {
  height: var(--control-h-lg);
  padding: 0 26px;
  font-size: var(--body-lg-size);
  gap: 10px;
}
.fd-btn-block {
  width: 100%;
}
.fd-btn-primary {
  background: var(--grad-primary);
  color: #fff;
  box-shadow: var(--e-brand);
}
.fd-btn-primary:hover {
  background: var(--grad-primary-hover);
}
.fd-btn-primary:active {
  background: var(--blue-800);
  box-shadow: none;
}
.fd-btn-brandsoft {
  background: var(--grad-brand-soft);
  color: #fff;
  box-shadow: var(--e-brand);
  font-size: var(--body-lg-size);
  font-weight: var(--w-bold);
}
.fd-btn-brandsoft:hover {
  background: var(--grad-brand-soft-hover);
}
.fd-btn-secondary {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
  box-shadow: var(--e-1);
}
.fd-btn-secondary:hover {
  background: var(--surface-2);
  border-color: var(--border-strong);
}
.fd-btn-secondary:active {
  background: var(--surface-3);
  box-shadow: none;
}
.fd-btn-ghost {
  background: transparent;
  color: var(--text-2);
}
.fd-btn-ghost:hover {
  background: var(--surface-3);
  color: var(--text);
}
.fd-btn-ghost:active {
  background: var(--border);
}
.fd-btn-danger {
  background: var(--danger-solid);
  color: #fff;
  box-shadow: 0 2px 6px rgba(208, 71, 61, 0.26);
}
.fd-btn-danger:hover {
  background: #b93a31;
}
.fd-btn-danger:active {
  background: var(--btn-solid-danger-bg-active);
  box-shadow: none;
}
.fd-btn-link {
  background: none;
  color: var(--link);
  height: auto;
  padding: 0;
  font-weight: var(--w-medium);
}
.fd-btn-link:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.fd-btn-arrow {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.22);
  font-size: 12px;
  transition: transform var(--dur-base) var(--ease-out);
}
/* Excludes [disabled]/[aria-disabled="true"] so a disabled arrow button never nudges on
   hover — the disabled selector's own :hover rule above sets no transform, but this rule
   targets a *descendant* (.fd-btn-arrow), which that selector's specificity can't reach, so
   it needs its own explicit exclusion. */
.fd-btn:hover:not([disabled]):not([aria-disabled="true"]) .fd-btn-arrow {
  transform: translateX(2px);
}
.fd-btn-loading {
  cursor: progress;
}
.fd-btn-icon {
  display: grid;
  place-items: center;
  width: var(--control-h-md);
  height: var(--control-h-md);
  padding: 0;
  border-radius: var(--r-md);
  color: var(--text-2);
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  font-size: 18px;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    transform var(--dur-instant) var(--ease);
}
.fd-btn-icon:hover {
  background: var(--surface-3);
  color: var(--text);
}
.fd-btn-icon:active {
  transform: translateY(1px);
  background: var(--border);
}
.fd-btn-icon-outline {
  border-color: var(--border);
  background: var(--surface);
  box-shadow: var(--e-1);
}
/* Tone on a quiet (ghost/outline) icon button: the glyph carries it, on hover too.
   MP-114 follow-up: also excludes .fd-btn-icon-soft, which was never meant to match
   here (it isn't ghost or outline — it has its own real fill, see .fd-btn-icon-soft
   below) but did, at (0,3,0) beating the soft rule's own un-toned (0,1,0)/toned
   (0,2,0) color rules at rest. That stomped --btn-soft-ok-ink/--btn-soft-danger-ink
   (chosen to clear 4.5:1 against the soft fill) with --ok-text/--danger-text (chosen
   to clear 4.5:1 against a plain card instead) — a real fill behind the wrong ink,
   e2e-measured at 2.04:1. The soft rule's own `:hover`/`:active` restatements already
   won their own specificity fight against this same rule's `:hover` (both (0,3,0),
   soft declared later so it wins the tie) — only the REST state, where soft never
   restated color at all, actually lost. */
.fd-btn-icon.is-ok:not(.fd-btn-icon-solid):not(.fd-btn-icon-soft),
.fd-btn-icon.is-ok:not(.fd-btn-icon-solid):not(.fd-btn-icon-soft):hover {
  color: var(--ok-text);
}
.fd-btn-icon.is-danger:not(.fd-btn-icon-solid):not(.fd-btn-icon-soft),
.fd-btn-icon.is-danger:not(.fd-btn-icon-solid):not(.fd-btn-icon-soft):hover {
  color: var(--danger-text);
}
/* Solid: a real fill in the tone's colour. The fills and inks are the --btn-solid-*
   tokens (tokens.css), struck per theme so the glyph clears 4.5:1 on the fill and the
   fill clears 3:1 against both a default and a danger-toned EntityRow card, at rest,
   hovered and pressed. The tone classes only swap which token set is in play. */
.fd-btn-icon-solid {
  --btn-solid-bg: var(--btn-solid-neutral-bg);
  --btn-solid-bg-hover: var(--btn-solid-neutral-bg-hover);
  --btn-solid-bg-active: var(--btn-solid-neutral-bg-active);
  --btn-solid-ink: var(--btn-solid-neutral-ink);
  background: var(--btn-solid-bg);
  color: var(--btn-solid-ink);
  border-color: transparent;
  box-shadow: var(--e-1);
}
.fd-btn-icon-solid.is-ok {
  --btn-solid-bg: var(--btn-solid-ok-bg);
  --btn-solid-bg-hover: var(--btn-solid-ok-bg-hover);
  --btn-solid-bg-active: var(--btn-solid-ok-bg-active);
  --btn-solid-ink: var(--btn-solid-ok-ink);
}
.fd-btn-icon-solid.is-danger {
  --btn-solid-bg: var(--btn-solid-danger-bg);
  --btn-solid-bg-hover: var(--btn-solid-danger-bg-hover);
  --btn-solid-bg-active: var(--btn-solid-danger-bg-active);
  --btn-solid-ink: var(--btn-solid-danger-ink);
}
.fd-btn-icon-solid:hover,
.fd-btn-icon-solid.is-ok:hover,
.fd-btn-icon-solid.is-danger:hover {
  background: var(--btn-solid-bg-hover);
  color: var(--btn-solid-ink);
}
/* Pressed restates every selector hover uses: a toned `:hover` is three classes deep, so a
   bare `.fd-btn-icon-solid:active` loses to it and a pressed add/remove button would keep
   its hover fill. */
.fd-btn-icon-solid:active,
.fd-btn-icon-solid.is-ok:active,
.fd-btn-icon-solid.is-danger:active {
  background: var(--btn-solid-bg-active);
  box-shadow: none;
}
/* foundations.css gives every button:focus-visible the focus ring; restated after
   :active so pressing a focused solid button cannot reset the ring away. */
.fd-btn-icon-solid:focus-visible {
  box-shadow: var(--focus-ring);
}
/* Soft: a lighter fill than solid, with a visibly darker border drawn around it (MP-52's
   "lighter fill, darker border" row action). Same --btn-soft-* tokens (tokens.css), same
   per-theme measurement discipline as solid, and the same pressed-selector-specificity
   fix baked in from the start (see the comment on .fd-btn-icon-solid:active above).

   MP-114 hover/active: the base `.fd-btn-icon:hover`/`:active` rules above (plain
   `.fd-btn-icon`, no variant) set `background` too, at the same (0,2,0) specificity as
   `.fd-btn-icon-soft:hover`/`:active` — a tie the cascade breaks by source order, so
   whichever rule sets `background` LAST wins. The old hover/active rules here only set
   `filter` and `color`, never `background`, so they never entered that tie for the
   `background` property at all: the base rule's `background: var(--surface-3)` /
   `var(--border)` was the only declaration left standing, and the soft fill vanished
   under a plain neutral surface colour while the ink stayed tuned for the soft fill —
   e2e-measured at 1.11:1. `filter: brightness()` made it worse in a way no contrast
   check (this file's or a screen reader user's own eye) could catch: a filter changes
   the pixels without ever touching `background-color`, so it cannot be reasoned about
   from the declared colours at all. Fixed on both counts: every state below restates a
   real `background` from a real token, so it wins its own tie the same way solid's
   already does, and there is no filter left to hide behind. */
.fd-btn-icon-soft {
  background: var(--btn-soft-bg);
  color: var(--btn-soft-ink);
  border-color: var(--btn-soft-border);
  box-shadow: var(--e-1);
}
.fd-btn-icon-soft.is-ok {
  --btn-soft-bg: var(--btn-soft-ok-bg);
  --btn-soft-bg-hover: var(--btn-soft-ok-bg-hover);
  --btn-soft-bg-active: var(--btn-soft-ok-bg-active);
  --btn-soft-border: var(--btn-soft-ok-border);
  --btn-soft-ink: var(--btn-soft-ok-ink);
}
.fd-btn-icon-soft.is-danger {
  --btn-soft-bg: var(--btn-soft-danger-bg);
  --btn-soft-bg-hover: var(--btn-soft-danger-bg-hover);
  --btn-soft-bg-active: var(--btn-soft-danger-bg-active);
  --btn-soft-border: var(--btn-soft-danger-border);
  --btn-soft-ink: var(--btn-soft-danger-ink);
}
.fd-btn-icon-soft:hover,
.fd-btn-icon-soft.is-ok:hover,
.fd-btn-icon-soft.is-danger:hover {
  background: var(--btn-soft-bg-hover);
  color: var(--btn-soft-ink);
}
/* Pressed restates every selector hover uses, same reasoning as
   .fd-btn-icon-solid:active above. */
.fd-btn-icon-soft:active,
.fd-btn-icon-soft.is-ok:active,
.fd-btn-icon-soft.is-danger:active {
  background: var(--btn-soft-bg-active);
  color: var(--btn-soft-ink);
  box-shadow: none;
}
/* Restated after :active, same reasoning as .fd-btn-icon-solid:focus-visible above: a
   pressed-while-focused button must keep the ring, not the pressed rule's `box-shadow:
   none`. */
.fd-btn-icon-soft:focus-visible {
  box-shadow: var(--focus-ring);
}
.fd-btn-icon-sm {
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  font-size: 15px;
}
.fd-btn-icon-lg {
  width: var(--control-h-lg);
  height: var(--control-h-lg);
  font-size: 21px;
}
.fd-btn-icon-round {
  border-radius: var(--r-full);
}
.fd-btn-icon[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ============ Segmented control ============ */
.fd-seg {
  display: inline-flex;
  /* .fd-seg is already inline-flex to hug its own content, but any flex-column
     parent with the default align-items:stretch (e.g. .fd-pop) overrides that by
     stretching this as a flex ITEM — align-self pins it back to content width
     regardless of the ambient container, so it never silently goes full-width
     just because it's dropped inside a popover/panel. */
  align-self: flex-start;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 3px;
  gap: 3px;
  /* Options can't shrink below their longest word; wrap onto a second row rather
     than letting a clipping ancestor (Card, Collapsible) cut the last one off. */
  flex-wrap: wrap;
}
.fd-seg button {
  border: 0;
  background: transparent;
  color: var(--text-2);
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  padding: 0 14px;
  height: 36px;
  border-radius: 6px;
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}
.fd-seg button:hover {
  color: var(--text);
}
.fd-seg button[aria-pressed="true"],
.fd-seg button.is-on {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--e-1);
}

/* ============ Fields ============ */
.fd-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: none;
}
.fd-field-label {
  font-size: var(--label-lg-size);
  line-height: var(--label-lg-lh);
  letter-spacing: var(--label-lg-track);
  font-weight: var(--w-semibold);
  color: var(--text);
}
.fd-field-req {
  color: var(--danger-solid);
  margin-left: 3px;
}
.fd-field-help {
  font-size: var(--body-sm-size);
  color: var(--text-muted);
}
.fd-field-error {
  font-size: var(--body-sm-size);
  color: var(--danger-text);
  display: flex;
  align-items: center;
  gap: 6px;
}
.fd-input {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--control-h-md);
  padding: 0 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition:
    border-color var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}
.fd-input:hover {
  border-color: var(--border-strong);
}
.fd-input:focus-within {
  border-color: var(--blue-500);
  box-shadow: 0 0 0 3px var(--blue-100);
}
.fd-input input,
.fd-input textarea,
.fd-input select {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  outline: none;
  font-size: var(--body-size);
  color: var(--text);
  box-shadow: none;
}
.fd-input input:focus,
.fd-input input:focus-visible,
.fd-input textarea:focus,
.fd-input select:focus {
  outline: none;
  box-shadow: none;
  border: 0;
}
.fd-input input::placeholder,
.fd-input textarea::placeholder {
  color: var(--text-disabled);
}
.fd-input-affix {
  color: var(--text-muted);
  font-size: var(--body-size);
  flex: none;
}
.fd-input-icon {
  color: var(--text-muted);
  font-size: 17px;
  flex: none;
  display: grid;
  place-items: center;
}
.fd-input-num input {
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
}
.fd-input-textarea {
  height: auto;
  padding: 12px 14px;
  align-items: stretch;
}
.fd-input-textarea textarea {
  resize: vertical;
  min-height: 96px;
  line-height: var(--body-lh);
}
.fd-input-error {
  border-color: var(--danger-solid);
}
.fd-input-error:focus-within {
  border-color: var(--danger-solid);
  box-shadow: 0 0 0 3px var(--danger-fill);
}
.fd-input-disabled {
  background: var(--surface-2);
  border-color: var(--border);
  cursor: not-allowed;
  opacity: 0.7;
}
.fd-input-lg {
  height: var(--control-h-lg);
  font-size: var(--body-lg-size);
  padding: 0 16px;
}
.fd-select {
  position: relative;
}
.fd-select select {
  appearance: none;
  cursor: pointer;
  padding-right: 22px;
}
.fd-select-caret {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  font-size: 14px;
  pointer-events: none;
}

/* ============ Choice controls ============ */
.fd-choice {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  cursor: pointer;
  padding: 10px 12px;
  margin: -10px -12px;
  border-radius: var(--r-md);
  transition: background var(--dur-fast) var(--ease);
}
.fd-choice:hover {
  background: var(--surface-2);
}
.fd-choice-input {
  position: relative;
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 1px;
}
.fd-choice-input input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.fd-choice-box {
  position: absolute;
  inset: 0;
  border: 1.5px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  display: grid;
  place-items: center;
  color: transparent;
  font-size: 13px;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    transform var(--dur-instant) var(--ease);
}
.fd-choice-box-round {
  border-radius: var(--r-full);
}
.fd-choice input:hover + .fd-choice-box {
  border-color: var(--blue-500);
}
.fd-choice input:checked + .fd-choice-box {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.fd-choice input:active + .fd-choice-box {
  transform: scale(0.92);
}
.fd-choice input:focus-visible + .fd-choice-box {
  box-shadow: var(--focus-ring);
}
.fd-choice input:disabled + .fd-choice-box {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--text-disabled);
}
.fd-choice-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--r-full);
  background: #fff;
  transform: scale(0);
  transition: transform var(--dur-fast) var(--ease-spring);
}
.fd-choice input:checked + .fd-choice-box .fd-choice-dot {
  transform: scale(1);
}
.fd-choice-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.fd-choice-title {
  font-size: var(--body-size);
  font-weight: var(--w-medium);
}
.fd-choice-desc {
  font-size: var(--body-sm-size);
  color: var(--text-muted);
}
.fd-choice-card {
  border: 1px solid var(--border);
  background: var(--surface);
  margin: 0;
  padding: 14px 16px;
  box-shadow: var(--e-1);
}
.fd-choice-card:hover {
  border-color: var(--border-strong);
  background: var(--surface);
}
.fd-choice-card:has(input:checked) {
  border-color: var(--blue-500);
  background: var(--surface-brand);
  box-shadow: 0 0 0 1px var(--blue-500);
}

.fd-choice-badge { margin-left: 8px; }
.fd-radiogroup { display: flex; flex-direction: column; gap: 8px; }
.fd-radiogroup-label { font-weight: var(--w-medium); }
.fd-fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.fd-fieldset[aria-busy="true"] { opacity: 0.6; }

/* ============ Switch ============ */
.fd-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
}
.fd-switch-track {
  position: relative;
  flex: none;
  width: 48px;
  height: 28px;
  border-radius: var(--r-full);
  background: var(--n-300);
  transition: background var(--dur-slow) var(--ease);
}
.fd-switch input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.fd-switch-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: var(--r-full);
  background: #fff;
  box-shadow: var(--e-1);
  transition: transform 240ms var(--ease-spring);
}
.fd-switch input:checked ~ .fd-switch-track {
  background: var(--brand);
}
.fd-switch input:checked ~ .fd-switch-track .fd-switch-thumb {
  transform: translateX(20px);
}
.fd-switch input:focus-visible ~ .fd-switch-track {
  box-shadow: var(--focus-ring);
}
.fd-switch input:disabled ~ .fd-switch-track {
  opacity: 0.45;
  cursor: not-allowed;
}
.fd-switch-label {
  font-size: var(--body-size);
  font-weight: var(--w-medium);
}

/* ============ Slider ============ */
.fd-slider {
  position: relative;
  padding: 14px 0;
}
.fd-slider input[type="range"] {
  appearance: none;
  width: 100%;
  height: 6px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  outline: none;
  margin: 0;
}
.fd-slider input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 24px;
  height: 24px;
  border-radius: var(--r-full);
  background: #fff;
  border: 1px solid var(--border-strong);
  box-shadow: var(--e-2);
  cursor: grab;
  transition: transform var(--dur-fast) var(--ease);
}
.fd-slider input[type="range"]:active::-webkit-slider-thumb {
  cursor: grabbing;
  transform: scale(1.1);
}
.fd-slider input[type="range"]::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: var(--r-full);
  background: #fff;
  border: 1px solid var(--border-strong);
  box-shadow: var(--e-2);
  cursor: grab;
}
.fd-slider-fill {
  position: absolute;
  left: 0;
  top: 50%;
  height: 6px;
  transform: translateY(-50%);
  border-radius: var(--r-full);
  background: var(--brand);
  pointer-events: none;
}
.fd-slider-chip {
  position: absolute;
  top: -16px;
  transform: translateX(-50%);
  background: var(--n-900);
  color: #fff;
  font-size: var(--label-size);
  font-weight: var(--w-semibold);
  padding: 4px 9px;
  border-radius: var(--r-sm);
  white-space: nowrap;
  animation: fd-pop var(--dur-fast) var(--ease-out) both;
  font-variant-numeric: tabular-nums;
}

/* ============ Card ============ */
.fd-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--e-1);
  overflow: hidden;
  /* MP-271: column flex so a card stretched taller than its own content (CardGrid's
     equal-height rows — a row's shorter cards stretch to match the tallest) still keeps its
     footer pinned to the bottom rather than leaving a gap above it. flex-direction: column on
     a `<div>`/`<a>`/`<button>` all behave identically, so this holds regardless of which
     element Card renders as (see `interactive` in Card.tsx). */
  display: flex;
  flex-direction: column;
}
.fd-card-flat {
  box-shadow: none;
}
.fd-card-raised {
  box-shadow: var(--e-2);
}
.fd-card-hoverable {
  transition:
    box-shadow var(--dur-base) var(--ease),
    border-color var(--dur-base) var(--ease),
    transform var(--dur-base) var(--ease);
}
.fd-card-hoverable:hover {
  box-shadow: var(--e-2);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}
/* MP-271: a real interactive card (Card rendered as <a> or <button> — `href`/`onClick`).
   Reset the native element's own look (button chrome, link underline/colour) so it reads as
   the same card either way, then add hover/press states that only ever touch box-shadow and
   border-color — never `transform` or a size-affecting property — so nothing jumps or
   reflows on press (MP-271 AC). A `:focus-visible` rule of its own IS needed, restated after
   `:hover`/`:active` below: without it, the global `button:focus-visible`/`a:focus-visible`
   rule (styles/foundations.css, specificity 0,1,1) loses to `.fd-card-interactive:hover`
   (0,2,0) whenever a card is both keyboard-focused and still under the pointer — a real,
   reachable state (tab to a card, and the mouse that was already resting on it never moved)
   — which would hide the focus ring entirely. Same fix Button.tsx's own `:focus-visible`
   rule already uses for the identical reason (see components.css's own comment on
   `.fd-btn-icon-solid:focus-visible`). */
.fd-card-interactive {
  display: block;
  width: 100%;
  text-align: left;
  color: inherit;
  text-decoration: none;
  font: inherit;
  cursor: pointer;
  transition: box-shadow var(--dur-base) var(--ease), border-color var(--dur-base) var(--ease);
}
.fd-card-interactive:hover {
  box-shadow: var(--e-2);
  border-color: var(--border-strong);
}
.fd-card-interactive:active {
  box-shadow: var(--e-1);
  border-color: var(--border-strong);
}
.fd-card-interactive:focus-visible {
  box-shadow: var(--focus-ring);
}
/* MP-271: the draft/placeholder variant — dashed instead of solid, using the same
   `--border-strong` token an emphatic-but-still-neutral border already uses elsewhere
   (Card's own `:hover` above), so light, dark and `[data-contrast="high"]` (tokens/
   appearance.css: high contrast promotes `--border` to `--border-strong` itself) all
   resolve a correct, themed dash with no new colour token. */
.fd-card-draft {
  border-style: dashed;
  border-color: var(--border-strong);
  box-shadow: none;
}
/* MP-271 review (comment 2920, finding 3): an interactive Card (href/onClick) can no longer
   render `action`/`footer` INSIDE the `<a>`/`<button>` — that was the only way this component
   could ever produce a real `<button>` (or a link) nested inside a real `<a>`, which is invalid
   HTML5 and double-fires clicks. `.fd-card-shell` is the plain, non-interactive wrapper Card
   renders around the `<a>`/`<button>` only when it's interactive; `action` and `footer` become
   its ordinary siblings, never its descendants, so nesting is impossible regardless of what a
   caller puts in either slot. `footer` needs nothing extra (it was already the last thing
   painted, so a sibling after the `<a>` lands in the exact same visual spot); `action` sits
   inside the header row visually, so it's positioned back into that corner over the `<a>`,
   given a higher stacking order so it stays independently clickable/focusable (the "stretched
   link" technique's own z-index rule, applied to a real sibling instead of a pseudo-element). */
.fd-card-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
}
.fd-card-shell > .fd-card-interactive {
  flex: 1 1 auto;
}
.fd-card-shell-action {
  position: absolute;
  top: 16px;
  right: 18px;
  z-index: 1;
}
/* The header degrades in two steps as the action slot needs more room than is left:
   first the title gives up ITS OWN spare width (ordinary flex-shrink) down to
   fd-card-head-title's min-width; once even that doesn't leave enough room for the
   action slot, flex-wrap moves the action onto its own row below the title rather than
   continuing to squeeze the title past a readable width. Nothing here is per-consumer —
   a wide action slot (badges, buttons, a switch) never needs an app-side workaround. */
.fd-card-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
}
.fd-card-head-title {
  font-size: var(--h3-size);
  line-height: var(--h3-lh);
  letter-spacing: var(--h3-track);
  font-weight: var(--w-semibold);
  flex: 1;
  /* The floor the title may shrink to before the action slot is made to wrap instead —
     enough for a short word plus an ellipsis, never zero. Text past this on one line
     truncates rather than overflowing the header. */
  min-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fd-card-body {
  padding: 18px;
  /* MP-271: lets the body absorb any extra height CardGrid's equal-height stretch adds,
     keeping `fd-card-foot` pinned to the bottom instead of leaving a gap above it. */
  flex: 1 1 auto;
}
.fd-card-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 18px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.fd-card-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.fd-card-row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}
.fd-card-row-label {
  font-size: var(--body-sm-size);
  color: var(--text-2);
  font-weight: var(--w-medium);
}
.fd-card-row-value {
  font-size: var(--body-size);
  color: var(--text);
  font-weight: var(--w-medium);
}

/* ============ FactList ============ */
/* The columns follow the list's own width (a container query), so a narrow card on a wide screen
   is one column too: 1 below 480px, then 2, 3 and 4 from 480, 720 and 960. */
.fd-facts {
  container-type: inline-size;
  width: 100%;
}
.fd-facts-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px 24px;
  margin: 0;
}
@container (min-width: 480px) {
  .fd-facts-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@container (min-width: 720px) {
  .fd-facts-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@container (min-width: 960px) {
  .fd-facts-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.fd-fact {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.fd-fact-label {
  font-size: var(--body-sm-size);
  color: var(--text-2);
  font-weight: var(--w-medium);
}
.fd-fact-value {
  margin: 0;
  font-size: var(--body-size);
  color: var(--text);
  font-weight: var(--w-medium);
  overflow-wrap: anywhere;
}

/* ============ Collapsible ============ */
.fd-coll {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
  transition:
    box-shadow var(--dur-base) var(--ease),
    border-color var(--dur-base) var(--ease);
}
.fd-coll[data-open="true"] {
  box-shadow: var(--e-2);
  border-color: var(--border-strong);
}
.fd-coll-trigger {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: var(--control-h-lg);
  padding: 16px 18px;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.fd-coll-head {
  display: flex;
  align-items: center;
}
.fd-coll-head > .fd-coll-trigger {
  flex: 1;
  width: auto;
  min-width: 0;
}
.fd-coll-actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 18px;
}
.fd-coll-head .fd-coll-title {
  overflow-wrap: break-word;
}
/* DS-47: on a phone the actions drop to their own line under the title and subtitle,
   aligned with the trigger's content, so the title keeps the full heading width. */
@media (max-width: 520px) {
  .fd-coll-head {
    flex-wrap: wrap;
  }
  .fd-coll-head > .fd-coll-trigger {
    flex: 1 1 100%;
  }
  .fd-coll-actions {
    padding: 0 18px 14px;
  }
}
.fd-coll-badge {
  flex: none;
  display: inline-flex;
}
/* DS-59: on a phone the meta badge drops to its own line under the title and subtitle, so they
   keep the heading's width less the toggle; an identifier title breaks only at punctuation. */
@media (max-width: 520px) {
  .fd-coll-trigger {
    flex-wrap: wrap;
    row-gap: 8px;
  }
  .fd-coll-badge {
    order: 3;
    flex: 1 1 100%;
  }
}
.fd-coll-trigger:hover {
  background: var(--surface-2);
}
.fd-coll-trigger:active {
  background: var(--surface-3);
}
.fd-coll-title {
  flex: 1;
  min-width: 0;
  font-size: var(--h4-size);
  font-weight: var(--w-semibold);
  letter-spacing: var(--h4-track);
}
.fd-coll-sub {
  font-size: var(--body-sm-size);
  color: var(--text-muted);
  font-weight: var(--w-regular);
  margin-top: 2px;
}
.fd-coll-caret {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 13px;
  transition:
    transform var(--dur-base) var(--ease),
    background var(--dur-fast) var(--ease);
}
.fd-coll-trigger[aria-expanded="true"] > .fd-coll-caret {
  transform: rotate(180deg);
  background: var(--brand-soft);
  color: var(--brand);
}
/* A closed panel is collapsed to zero height, and must also leave the tab order and the accessibility
   tree: visibility flips only after the close animation, and at once on open. */
.fd-coll-panel {
  overflow: hidden;
  transition:
    grid-template-rows var(--dur-panel) var(--ease),
    visibility 0s linear var(--dur-panel);
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
}
.fd-coll[data-open="true"] > .fd-coll-panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition:
    grid-template-rows var(--dur-panel) var(--ease),
    visibility 0s;
}
.fd-coll-panel > div {
  overflow: hidden;
  min-height: 0;
}
.fd-coll-content {
  padding: 0 18px 18px;
  border-top: 1px solid var(--border);
  padding-top: 16px;
  margin-top: 0;
}

/* ============ Badge / pill / tag ============ */
.fd-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--r-full);
  font-size: var(--label-size);
  line-height: 1;
  letter-spacing: var(--label-track);
  font-weight: var(--w-semibold);
  white-space: nowrap;
  border: 1px solid transparent;
  /* One line, capped at the container: a long label ellipsizes instead of being
     clipped out of sight. Callers with unbounded content pass a `title`. */
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-badge-neutral {
  background: var(--surface-3);
  color: var(--text-2);
}
.fd-badge-info {
  background: var(--info-fill);
  border-color: var(--info-border);
  color: var(--info-text);
}
.fd-badge-success {
  background: var(--ok-fill);
  border-color: var(--ok-border);
  color: var(--ok-text);
}
.fd-badge-warning {
  background: var(--warn-fill);
  border-color: var(--warn-border);
  color: var(--warn-text);
}
.fd-badge-danger {
  background: var(--danger-fill);
  border-color: var(--danger-border);
  color: var(--danger-text);
}
.fd-badge-live {
  background: var(--grad-brand-soft);
  color: #fff;
  padding: 0 12px;
  height: 26px;
}
.fd-badge-approved {
  background: var(--grad-ok);
  color: #fff;
  padding: 0 14px;
  height: 28px;
  font-size: var(--label-lg-size);
}
.fd-badge-count {
  background: var(--blue-500);
  color: #fff;
  min-width: 26px;
  height: 26px;
  justify-content: center;
  padding: 0 8px;
  font-size: var(--label-lg-size);
  font-weight: var(--w-bold);
}
.fd-badge-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  background: currentColor;
  flex: none;
}
.fd-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  white-space: nowrap;
  flex: none;
  padding: 0 12px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-2);
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-tag:hover {
  background: var(--surface-3);
  color: var(--text);
}
.fd-tag[aria-pressed="true"] {
  background: var(--surface-brand);
  border-color: var(--border-brand);
  color: var(--text-on-surface-brand);
}
.fd-tag[aria-pressed="true"].fd-tag-info {
  background: var(--info-fill);
  border-color: var(--info-border);
  color: var(--info-text);
}
.fd-tag[aria-pressed="true"].fd-tag-success {
  background: var(--ok-fill);
  border-color: var(--ok-border);
  color: var(--ok-text);
}
.fd-tag[aria-pressed="true"].fd-tag-warning {
  background: var(--warn-fill);
  border-color: var(--warn-border);
  color: var(--warn-text);
}
.fd-tag[aria-pressed="true"].fd-tag-danger {
  background: var(--danger-fill);
  border-color: var(--danger-border);
  color: var(--danger-text);
}
/* DS-51: StatusIndicator — a non-toggle chip. Same box in every tone, icon and loading
   state: fixed height and a fixed-size icon slot, so a header does not jump when the
   status changes. Colour comes from the tone class alone. */
.fd-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  max-width: 100%;
  box-sizing: border-box;
  white-space: nowrap;
  flex: none;
  padding: 0 10px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-2);
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  cursor: pointer;
}
.fd-status:hover {
  background: var(--surface-3);
  color: var(--text);
}
.fd-status-icon {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  flex: none;
  font-size: 14px;
}
.fd-status-icon .fd-spinner {
  width: 12px;
  height: 12px;
  border-width: 2px;
}
.fd-status-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-status-success,
.fd-status-success:hover {
  background: var(--ok-fill);
  border-color: var(--ok-border);
  color: var(--ok-text);
}
.fd-status-warning,
.fd-status-warning:hover {
  background: var(--warn-fill);
  border-color: var(--warn-border);
  color: var(--warn-text);
}
.fd-status-danger,
.fd-status-danger:hover {
  background: var(--danger-fill);
  border-color: var(--danger-border);
  color: var(--danger-text);
}
.fd-tag-remove {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  /* MP-282: fixed at 18×18 on purpose (a real hit target) — never one of the flex items a
     squeezed .fd-tag shrinks to make room for a long label (see .fd-filterbar .fd-tag-label
     below), so it stays visible and clickable at any chip width. */
  flex: none;
  border-radius: var(--r-full);
  background: var(--border);
  color: var(--text-2);
  font-size: 10px;
  border: 0;
  cursor: pointer;
}
.fd-tag-remove:hover {
  background: var(--n-400);
  color: #fff;
}

/* ============ Avatar ============ */
.fd-avatar {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--r-full);
  background: var(--surface-brand-strong);
  color: var(--text-on-surface-brand);
  font-size: var(--body-sm-size);
  font-weight: var(--w-bold);
  overflow: hidden;
  flex: none;
  letter-spacing: 0.01em;
}
.fd-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fd-avatar-sm {
  width: 26px;
  height: 26px;
  font-size: 10.5px;
}
.fd-avatar-lg {
  width: 48px;
  height: 48px;
  font-size: var(--h4-size);
}
.fd-avatar-stack {
  display: flex;
}
.fd-avatar-stack .fd-avatar {
  border: 2px solid var(--surface);
  margin-right: -9px;
}

/* ============ CSI ============ */
.fd-csi {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border-radius: var(--r-full);
  border: 1px solid;
  font-weight: var(--w-semibold);
  white-space: nowrap;
  transition:
    background var(--dur-base) var(--ease),
    color var(--dur-base) var(--ease),
    border-color var(--dur-base) var(--ease);
}
.fd-csi-compact {
  height: 22px;
  padding: 0 9px;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.fd-csi-medium {
  height: 30px;
  padding: 0 12px;
  font-size: var(--label-lg-size);
}
.fd-csi-1 {
  background: var(--csi-1-fill);
  border-color: var(--csi-1-edge);
  color: var(--csi-1-text);
}
.fd-csi-2 {
  background: var(--csi-2-fill);
  border-color: var(--csi-2-edge);
  color: var(--csi-2-text);
}
.fd-csi-3 {
  background: var(--csi-3-fill);
  border-color: var(--csi-3-edge);
  color: var(--csi-3-text);
}
.fd-csi-4 {
  background: var(--csi-4-fill);
  border-color: var(--csi-4-edge);
  color: var(--csi-4-text);
}
.fd-csi-preview {
  opacity: 0.7;
  border-style: dashed;
}
.fd-csi-crp {
  font-variant-numeric: tabular-nums lining-nums;
  opacity: 0.85;
  font-weight: var(--w-medium);
}
.fd-meter {
  display: inline-flex;
  gap: 2px;
  align-items: center;
}
.fd-meter-seg {
  border-radius: 1.5px;
  background: currentColor;
  opacity: 0.22;
  transition: opacity var(--dur-base) var(--ease);
}
.fd-meter-seg.is-on {
  opacity: 1;
}
.fd-csi-hero-num {
  font-size: var(--num-hero-size);
  line-height: 1;
  letter-spacing: var(--num-hero-track);
  font-weight: var(--w-bold);
  font-variant-numeric: tabular-nums lining-nums;
}

@keyframes fd-badge-pop {
  0% {
    transform: scale(0.55);
  }
  55% {
    transform: scale(1.22);
  }
  100% {
    transform: scale(1);
  }
}

/* ============ Channel identity ============ */
.fd-chan {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px 3px 7px;
  border-radius: 99px;
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  line-height: 1.35;
  white-space: nowrap;
  color: color-mix(in srgb, var(--chan) 78%, var(--n-900));
  background: color-mix(in srgb, var(--chan) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--chan) 26%, transparent);
}
.fd-chan i {
  font-size: 13px;
  color: var(--chan);
  flex: none;
}
.fd-chan-sm {
  padding: 1px 7px 1px 5px;
  font-size: 11.5px;
  gap: 4px;
}
.fd-chan-sm i {
  font-size: 11.5px;
}
.fd-chan-label {
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-chan-weight {
  font-family: var(--font-mono);
  font-size: 10px;
  opacity: 0.7;
  padding-left: 1px;
}
.fd-chan-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex: none;
}
[data-theme="dark"] .fd-chan {
  color: color-mix(in srgb, var(--chan) 62%, var(--n-0));
  background: color-mix(in srgb, var(--chan) 18%, var(--surface));
  border-color: color-mix(in srgb, var(--chan) 34%, transparent);
}

/* ============ Pagination ============ */
.fd-pag {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 10px 4px 2px;
}
.fd-pag-count {
  font-size: var(--body-sm-size);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.fd-pag-count strong {
  color: var(--text);
  font-weight: var(--w-semibold);
}
.fd-pag-size {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--body-sm-size);
  color: var(--text-2);
  margin-left: auto;
}
.fd-pag-size select {
  appearance: none;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 4px 22px 4px 8px;
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-2) 50%),
    linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position:
    calc(100% - 12px) 52%,
    calc(100% - 8px) 52%;
  background-size:
    4px 4px,
    4px 4px;
  background-repeat: no-repeat;
}
.fd-pag-size select:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-pag-nav {
  display: flex;
  align-items: center;
  gap: 3px;
}
.fd-pag-nav button {
  min-width: 28px;
  height: 28px;
  padding: 0 7px;
  display: grid;
  place-items: center;
  font: inherit;
  font-size: var(--body-sm-size);
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-pag-nav button:hover:not(:disabled) {
  background: var(--surface-2);
  color: var(--text);
}
.fd-pag-nav button:disabled {
  opacity: 0.35;
  cursor: default;
}
.fd-pag-nav button.is-current {
  background: var(--surface-brand);
  border-color: var(--info-border);
  color: var(--text-on-surface-brand);
  font-weight: var(--w-semibold);
}
.fd-pag-nav button:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-pag-gap {
  color: var(--text-muted);
  padding: 0 2px;
  font-size: var(--body-sm-size);
}

/* ============ Coming soon (unwired feature) ============ */
.fd-soon {
  position: relative;
  isolation: isolate;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.fd-soon-under {
  pointer-events: none;
  user-select: none;
}
.fd-soon-veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: color-mix(in srgb, var(--page) 46%, transparent);
  background-image: repeating-linear-gradient(
    135deg,
    color-mix(in srgb, var(--warn-solid) 7%, transparent) 0 10px,
    transparent 10px 20px
  );
}
/* Anchored near the top, not centred: a full screen is far taller than the viewport, so
   dead-centre put the only explanation hundreds of pixels below the fold — a blurred page with
   no reason given. Top-anchored is visible the moment the screen opens, at any content height. */
.fd-soon-note {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 20px;
  transform: translateX(-50%);
  max-width: min(420px, calc(100% - 32px));
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  text-align: center;
  padding: 16px 20px;
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--warn-border);
  box-shadow: var(--e-3);
}
.fd-soon-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--warn-fill);
  color: var(--warn-text);
  border: 1px solid var(--warn-border);
  font-size: var(--body-sm-size);
  font-weight: var(--w-bold);
  /* Wraps at word boundaries and never exceeds its container: the bypassed veil's
     bar has no clipping ancestor, so a one-line long label would widen the shell. */
  max-width: 100%;
}
.fd-soon-badge .ph {
  font-size: 14px;
}
.fd-soon-detail {
  font-size: var(--body-sm-size);
  color: var(--text-2);
  text-wrap: pretty;
}
.fd-soon-backend {
  font-size: var(--body-sm-size);
  color: var(--text-muted);
  text-wrap: pretty;
}
.fd-soon-backend .fd-overline {
  color: var(--text-muted);
  margin-right: 5px;
}
.fd-soon-view {
  all: unset;
  cursor: pointer;
  margin-top: 2px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
}
.fd-soon-view:hover {
  background: var(--surface-3);
  border-color: var(--text-muted);
}
.fd-soon-view:focus-visible {
  box-shadow: var(--focus-ring);
}
/* inline variant — a control-scale marker, not a panel-scale card */
/* The inline variant has nothing to clip — its blur lives on the inner .fd-soon-under, while the
   cone badge (inset -6px) and the dashed frame (::after, inset -2px) are deliberately OUTSIDE the
   wrapper box. The base .fd-soon overflow:hidden exists for the block variant's blurred panel and
   was silently slicing both off; hence overflow:visible here. No margins: the parents are
   flex/align-items:center, so any top margin shifts the gated control off its siblings' centre
   line — the cone is allowed to overhang instead. */
.fd-soon-inline {
  display: inline-flex;
  position: relative;
  vertical-align: middle;
  isolation: isolate;
  overflow: visible;
  border-radius: 0;
}
.fd-soon-inline > .fd-soon-under {
  display: inline-flex;
}
.fd-soon-inline::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 8px;
  border: 1px dashed var(--warn-border);
  background: color-mix(in srgb, var(--warn-fill) 22%, transparent);
  pointer-events: none;
  z-index: 1;
}
.fd-soon-cone-mark {
  position: absolute;
  top: -6px;
  right: -6px;
  left: auto;
  bottom: auto;
  transform: none;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 50%;
  font: inherit;
  appearance: none;
  background: var(--warn-fill);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
  cursor: help;
  box-shadow: 0 1px 4px rgba(11, 13, 17, 0.18);
  transition: transform var(--dur-fast) var(--ease);
}
.fd-soon-cone-mark:focus-visible {
  transform: scale(1.12);
}
.fd-soon-inline:hover .fd-soon-cone-mark {
  transform: scale(1.12);
}
.fd-soon-cone-mark:focus-visible {
  box-shadow: var(--focus-ring);
}
.fd-soon-cone-mark i {
  font-size: 11px;
}
/* z-index is set inline by ComingSoon.tsx via useLayerZIndex (kits/layerStack.tsx). */
.fd-soon-hovercard {
  transform: none;
  box-shadow: 0 18px 48px rgba(11, 13, 17, 0.26);
  animation: fd-fade var(--dur-fast) var(--ease) both;
}
.fd-soon-inline-on {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.fd-soon-cone {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 6px;
  cursor: pointer;
  background: var(--warn-fill);
  border: 1px dashed var(--warn-border);
  color: var(--warn-text);
}
.fd-soon-cone:hover {
  border-style: solid;
}
.fd-soon-cone:focus-visible {
  box-shadow: var(--focus-ring);
}
.fd-soon-cone i {
  font-size: 12px;
}
/* Persistent while bypassed: striped so it reads as the same hazard language as the veil, and
   never dismissible — only re-blurrable. A warning you can close is a warning you will forget. */
.fd-soon-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  padding: 9px 14px;
  border-radius: var(--r-lg);
  border: 1px solid var(--warn-border);
  background: var(--warn-fill);
  background-image: repeating-linear-gradient(
    135deg,
    color-mix(in srgb, var(--warn-solid) 9%, transparent) 0 10px,
    transparent 10px 20px
  );
}
.fd-soon-bar-detail {
  flex: 1;
  min-width: 200px;
  font-size: var(--body-sm-size);
  color: var(--warn-text);
  text-wrap: pretty;
}
.fd-soon-bar-actions {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  flex: none;
}
.fd-soon-bar .fd-soon-link {
  color: var(--warn-text);
}
.fd-soon-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  justify-content: center;
  align-items: center;
  font-size: var(--body-sm-size);
  color: var(--text-muted);
}
.fd-soon-meta > span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
.fd-soon-link {
  all: unset;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--brand);
  font-weight: var(--w-semibold);
  font-size: var(--body-sm-size);
}
.fd-soon-link:hover {
  text-decoration: underline;
}
@media (max-width: 520px) {
  .fd-soon-note {
    padding: 12px 14px;
    gap: 6px;
  }
  .fd-soon-backend {
    display: none;
  }
}

/* ============ Roadmap timeline ============ */
.fd-rm {
  position: relative;
  padding-left: 0;
}
.fd-rm-scroll {
  max-height: min(74vh, 860px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 4px 4px 60px;
  scroll-behavior: smooth;
}
.fd-rm-track {
  position: relative;
  padding-left: 132px;
}
@media (max-width: 760px) {
  .fd-rm-track {
    padding-left: 66px;
  }
}
.fd-rm-spine {
  position: absolute;
  left: 112px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--border);
  border-radius: 1px;
}
@media (max-width: 760px) {
  .fd-rm-spine {
    left: 46px;
  }
}
.fd-rm-spine-done {
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  background: var(--csi-3-mark);
  border-radius: 1px;
}
.fd-rm-row {
  position: relative;
  padding-bottom: 14px;
}
.fd-rm-date {
  position: absolute;
  left: -132px;
  top: 14px;
  width: 100px;
  text-align: right;
  font-size: 11.5px;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
@media (max-width: 760px) {
  .fd-rm-date {
    position: static;
    width: auto;
    text-align: left;
    margin-bottom: 5px;
  }
}
.fd-rm-dot {
  position: absolute;
  left: -25px;
  top: 16px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--surface);
  border: 2.5px solid var(--border-strong);
  z-index: 1;
}
@media (max-width: 760px) {
  .fd-rm-dot {
    left: -25px;
    top: 2px;
  }
}
.fd-rm-dot.is-shipped {
  background: var(--csi-3-mark);
  border-color: var(--csi-3-mark);
}
.fd-rm-dot.is-next {
  background: var(--surface);
  border-color: var(--warn-solid);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--warn-solid) 18%, transparent);
}
.fd-rm-now {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 10px 0 18px;
}
.fd-rm-now::before,
.fd-rm-now::after {
  content: "";
  height: 1px;
  background: var(--warn-border);
  flex: 1;
}
.fd-rm-now-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 12px;
  border-radius: 999px;
  background: var(--warn-fill);
  color: var(--warn-text);
  border: 1px solid var(--warn-border);
  font-size: 12px;
  font-weight: var(--w-bold);
  white-space: nowrap;
}
.fd-rm-era {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: 22px 0 12px;
  padding: 8px 0 10px;
  background: var(--page);
  border-bottom: 1px solid var(--border);
  font-size: var(--body-size);
  letter-spacing: 0;
  text-transform: none;
  font-weight: var(--w-bold);
  color: var(--text);
}
.fd-rm-era:first-child {
  margin-top: 0;
}
.fd-rm-era-why {
  margin: 6px 0 0;
  max-width: 62ch;
  font-size: var(--body-sm-size);
  line-height: 1.5;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-2);
  text-wrap: pretty;
}

/* ============ Stat tile ============ */
/* MP-141: kit-wide truncation rule for Stat (and every future text class here) —
 * explanatory/label copy (.fd-stat-sub, .fd-stat-label) always WRAPS, never
 * ellipsizes: a client reading a narrow tile must never lose part of a sentence
 * behind a "…" with no way to read the rest, and a tooltip is not a substitute
 * for readable client-facing copy. Only a user-data identifier displayed in a
 * dense row (a table cell, a chip) may ellipsize — and only when it also exposes
 * its full text via `title`/tooltip. Decide this once, here, for every Stat
 * consumer, not per screen. */
.fd-stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 14px 16px;
  min-width: 0;
  overflow: hidden;
}
/* The figure and its delta share a line while both fit; when the tile is too narrow for
 * both, the delta wraps onto its own line under the figure. Each is one unbreakable unit
 * (`nowrap` on `.fd-stat-figure` and `.fd-stat-delta`), so neither is shrunk or split:
 * only the gap between them yields. */
.fd-stat-top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 8px;
  row-gap: 2px;
  min-width: 0;
}
.fd-stat-delta {
  flex: none;
  font-weight: 600;
  font-size: var(--body-sm-size);
  white-space: nowrap;
}
.fd-stat-sub {
  /* MP-141: this is explanatory copy ("on every funded campus, at minimum"),
   * never a user-data identifier — per the kit's truncation rule (see this
   * file's own header note above .fd-stat), explanatory/label copy always
   * wraps instead of ellipsizing, so a client reading a narrow tile never
   * loses part of the sentence behind a "…" with no way to read the rest. */
  display: block;
  margin-top: 4px;
  font-size: var(--body-sm-size);
  color: var(--text-2);
  min-width: 0;
  overflow-wrap: break-word;
  white-space: normal;
}
.fd-stat-label {
  /* MP-141: same rule as .fd-stat-sub above — this is the tile's fixed
   * caption, not a user-entered identifier, so it wraps rather than losing
   * words to an ellipsis. */
  display: block;
  margin-top: 6px;
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--text-muted);
  overflow-wrap: break-word;
  white-space: normal;
}
.fd-stat-figure {
  flex: none;
  font-size: clamp(22px, 1vw + 15px, 30px);
  line-height: 1.1;
  letter-spacing: var(--num-hero-track);
  font-weight: var(--w-bold);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--text);
  white-space: nowrap;
}
.fd-stat-delta-up {
  color: var(--ok-text);
}
.fd-stat-delta-down {
  color: var(--danger-text);
}
.fd-stat-delta-neutral {
  color: var(--text-muted);
}
/* MP-311: a pressable tile (StatTile with `onPress`) is a real <button> that filters a list.
 * Reset the button chrome so it reads as the same tile, then give it hover, press, focus,
 * pressed and disabled states that only touch border, fill and shadow, never size, so nothing
 * reflows. `:focus-visible` is restated after `:hover`/`:active` for the reason .fd-card-interactive
 * gives above (a hovered, focused tile must still show its ring). A pressed tile uses the brand
 * tokens .fd-tag[aria-pressed] uses, so light, dark and high contrast all resolve. */
.fd-stat-pressable {
  display: block;
  width: 100%;
  text-align: left;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition:
    background var(--dur-base) var(--ease),
    border-color var(--dur-base) var(--ease),
    box-shadow var(--dur-base) var(--ease);
}
.fd-stat-pressable:hover {
  box-shadow: var(--e-2);
  border-color: var(--border-strong);
}
.fd-stat-pressable:active {
  box-shadow: var(--e-1);
  border-color: var(--border-strong);
}
.fd-stat-pressable[aria-pressed="true"] {
  background: var(--surface-brand);
  border-color: var(--border-brand);
}
.fd-stat-pressable:focus-visible {
  box-shadow: var(--focus-ring);
}
.fd-stat-pressable:disabled {
  cursor: not-allowed;
  opacity: 0.6;
  box-shadow: none;
}

/* ============ Meter / progress ============ */
.fd-meterbar {
  height: 8px;
  border-radius: var(--r-xs);
  background: var(--surface-3);
  overflow: hidden;
  display: flex;
  gap: 2px;
}
.fd-meterbar-seg {
  height: 100%;
}
.fd-meterbar-unallocated {
  background: repeating-linear-gradient(135deg, var(--n-200) 0 5px, var(--n-100) 5px 10px);
}

/* ============ Table ============ */
.fd-table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: auto;
  box-shadow: var(--e-1);
}
/* Stale rows during a re-query (sort, filter, page).
   The dimming is painted by a real scrim element rather than opacity on <tbody>: an in-tree
   table section does not reliably take opacity/filter even when the rule matches and wins
   (a detached tbody with the same class does), so relying on it left the state invisible.
   A scrim is an element this file controls, composited above the rows, and cannot be defeated
   by a cascade elsewhere. .fd-stale is still applied to the tbody for pointer-events:none —
   that half works, and it is what actually stops input on superseded data.
   The pill uses sticky with an ABSOLUTE offset: a percentage top resolves against the overlay's
   own height (900px+ here), which parked it far below the fold. */
.fd-table-host {
  position: relative;
}
.fd-table-stale {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  border-radius: inherit;
  background: color-mix(in srgb, var(--page) 52%, transparent);
  pointer-events: none;
  animation: fd-fade var(--dur-fast) var(--ease) both;
}
.fd-table-stale-pill {
  position: sticky;
  top: 12px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 15px;
  border-radius: 99px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--e-2);
  font-size: var(--body-sm-size);
  font-weight: 600;
  color: var(--text-2);
  white-space: nowrap;
}

.fd-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--body-sm-size);
}
.fd-table th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 38px;
  padding: 0 14px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  text-align: left;
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--text-muted);
  white-space: nowrap;
}
.fd-table th.is-num {
  text-align: right;
}
.fd-table th.is-sorted {
  color: var(--text);
}
.fd-table th button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  text-transform: inherit;
  letter-spacing: inherit;
}
.fd-table th .fd-caret {
  color: var(--brand);
  font-size: 9px;
}
.fd-table td {
  padding: 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
}
/* SMS-50: a link-variant Button in a cell (a name that acts on its row) is text, not a control:
   it wraps like the text around it and reads left-aligned. A Button on its own never wraps
   (`white-space: nowrap`), so a long name kept its row on one line and stretched the table
   past its card. */
.fd-table td .fd-btn-link {
  white-space: normal;
  text-align: left;
}
.fd-table td.is-num {
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: var(--w-medium);
}
.fd-table-nowrap {
  white-space: nowrap;
}
.fd-table tbody tr {
  transition:
    background var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}
.fd-table tbody tr:hover {
  background: var(--surface-brand);
}
.fd-table tbody tr[data-clickable] {
  cursor: pointer;
}
.fd-table tbody tr[aria-selected="true"] {
  background: var(--surface-brand);
  box-shadow: inset 2px 0 0 var(--brand);
}
.fd-table-compact td {
  padding: 9px 14px;
}
.fd-table tbody tr:last-child td {
  border-bottom: 0;
}
/* Stacked mode (DataTable at 640px wide or less): the rows are compact cards in the same surface as the table.
   A card is a title line (primary columns; the first one ellipsizes, the rest keep their size, so a
   status stays beside a long name) and a muted meta line of labelled secondary values, two lines at most. */
.fd-table-wrap-stacked {
  overflow: visible;
}
.fd-dt-sort {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.fd-dt-sort::before {
  content: "Sort";
  margin-right: 4px;
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--text-muted);
}
.fd-dt-sort button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--text-2);
  font: inherit;
  font-size: var(--label-size);
  font-weight: var(--w-semibold);
  cursor: pointer;
}
.fd-dt-sort button[aria-pressed="true"] {
  border-color: var(--brand);
  color: var(--text);
}
.fd-dt-sort .fd-caret {
  color: var(--brand);
  font-size: 9px;
}
/* A card and, when the row has an action of its own, that action beside it: siblings, so the action is
   never inside the card's button. The item carries the hairline between rows. */
.fd-dt-item {
  display: flex;
  align-items: center;
  min-width: 0;
  border-bottom: 1px solid var(--border);
  transition:
    background var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}
.fd-dt-item:last-child {
  border-bottom: 0;
}
.fd-dt-item > .fd-dt-card {
  flex: 1 1 auto;
  align-self: stretch;
}
.fd-dt-action {
  flex: none;
  padding-right: 8px;
}
/* The table's form of a row action: the row's last cell, as narrow as its button. */
.fd-table td.fd-table-action,
.fd-table th.fd-table-action-head {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}
.fd-dt-card {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding: 12px 14px;
}
.fd-dt-card[data-clickable] {
  cursor: pointer;
}
/* The item is tinted, not the card, so the strip under a row's action is tinted with it. */
.fd-dt-item:has(> .fd-dt-card[data-clickable]):hover,
.fd-dt-item:has(> .fd-dt-card[data-selected="true"]) {
  background: var(--surface-brand);
}
.fd-dt-item:has(> .fd-dt-card[data-selected="true"]) {
  box-shadow: inset 2px 0 0 var(--brand);
}
.fd-dt-card-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
  font-size: var(--body-size);
  font-weight: var(--w-semibold);
  color: var(--text);
}
.fd-dt-card-title > span {
  flex: none;
}
.fd-dt-card-title > span:first-child {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fd-dt-card-meta {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: var(--body-sm-size);
  color: var(--text-2);
}
/* The separator lives in the item it follows, in padding the item reserves at its end, so no line break
   can fall between an item and its dot: an item that wraps to a new line starts with its own text, never
   with a stray dot. (Text between the two would not do: a line may break after a badge, which is an atomic
   box, and the dot would lead the next line.) */
.fd-dt-card-meta > span:not(:last-child) {
  position: relative;
  padding-right: 15px;
}
.fd-dt-card-meta > span:not(:last-child)::after {
  content: "·";
  position: absolute;
  right: 6px;
}
.fd-dt-card-label {
  color: var(--text-muted);
}
.fd-dt-card .is-num {
  font-variant-numeric: tabular-nums lining-nums;
}
.fd-table-trunc {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============ Tabs ============ */
.fd-tabs {
  --fd-tabs-fade-start: 0px;
  --fd-tabs-fade-end: 0px;
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}
/* Tabs that do not fit scroll sideways; the edge that has more fades out (Tabs sets the data
   attributes from the scroll position). The fade is a mask, so it is the same in either theme. */
.fd-tabs[data-more-start="true"] {
  --fd-tabs-fade-start: 32px;
}
.fd-tabs[data-more-end="true"] {
  --fd-tabs-fade-end: 32px;
}
.fd-tabs[data-more-start="true"],
.fd-tabs[data-more-end="true"] {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--fd-tabs-fade-start), #000 calc(100% - var(--fd-tabs-fade-end)), transparent);
  mask-image: linear-gradient(to right, transparent, #000 var(--fd-tabs-fade-start), #000 calc(100% - var(--fd-tabs-fade-end)), transparent);
}
.fd-tabs::-webkit-scrollbar {
  display: none;
}
.fd-tab {
  position: relative;
  height: 46px;
  padding: 0 16px;
  background: none;
  border: 0;
  font-size: var(--label-lg-size);
  font-weight: var(--w-semibold);
  color: var(--text-2);
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition:
    color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
  border-radius: var(--r-md) var(--r-md) 0 0;
}
.fd-tab:hover {
  color: var(--text);
  background: var(--surface-2);
}
.fd-tab::after {
  content: "";
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--brand);
  transform: scaleX(0);
  transition: transform var(--dur-base) var(--ease-out);
}
.fd-tab[aria-selected="true"] {
  color: var(--text);
}
.fd-tab[aria-selected="true"]::after {
  transform: scaleX(1);
}

/* ============ Account menu ============ */
.fd-acct-trigger {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 6px 3px 3px;
  border-radius: 99px;
  border: 1px solid transparent;
  background: none;
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.fd-acct-trigger:hover {
  background: var(--surface-2);
  border-color: var(--border);
}
.fd-acct-trigger[aria-expanded="true"] {
  background: var(--surface-2);
  border-color: var(--border-strong);
}
.fd-acct-trigger:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-acct-group {
  display: flex;
  flex-direction: column;
  padding: 5px 0;
}
.fd-acct-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 14px;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  color: var(--text);
  transition: background var(--dur-fast) var(--ease);
}
.fd-acct-item > i {
  font-size: 16px;
  color: var(--text-muted);
  flex: none;
}
.fd-acct-item:hover {
  background: var(--surface-brand);
}
.fd-acct-item:hover > i {
  color: var(--text-on-surface-brand);
}
.fd-acct-item:focus-visible {
  outline: none;
  box-shadow: inset var(--focus-ring);
}
.fd-acct-item[data-danger="true"]:hover {
  background: var(--danger-fill);
  color: var(--danger-text);
}
.fd-acct-item[data-danger="true"]:hover > i {
  color: var(--danger-text);
}
.fd-acct-item[data-current="true"] {
  background: var(--surface-2);
}

/* ============ Permission matrix ============ */
.fd-matrix-wrap {
  overflow: auto;
  max-height: min(70vh, 660px);
  border-radius: var(--r-md);
}
.fd-matrix {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--body-sm-size);
}
.fd-matrix th,
.fd-matrix td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}
.fd-matrix thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--surface-2);
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: var(--w-bold);
  white-space: nowrap;
}
.fd-matrix thead th:first-child {
  left: 0;
  z-index: 4;
}
.fd-matrix tbody th {
  font-weight: var(--w-semibold);
  color: var(--text);
  position: sticky;
  left: 0;
  background: var(--surface);
  z-index: 2;
  min-width: 220px;
}
.fd-matrix td {
  text-align: center;
}
.fd-matrix tbody tr:hover th,
.fd-matrix tbody tr:hover td {
  background: var(--surface-2);
}
.fd-matrix-group th {
  background: var(--surface-3);
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  color: var(--text-2);
  font-weight: var(--w-bold);
  z-index: 2;
}

/* ============ JSON block (API spec) ============ */
.fd-json {
  margin: 0;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.55;
  overflow-x: auto;
  white-space: pre;
  color: var(--text);
}

/* ============ Nav ============ */
.fd-side {
  width: var(--sidebar-w);
  flex: none;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  transition:
    margin-left var(--dur-panel) var(--ease),
    opacity var(--dur-base) var(--ease);
}
.fd-side[data-open="false"] {
  margin-left: calc(-1 * var(--sidebar-w));
  opacity: 0;
  pointer-events: none;
}
/* DS-26: AppShell's docked side panel. The outer box animates width in and out (the content beside it reflows
   with it); the inner box keeps the full width so what is inside slides rather than rewraps. Both keyframes
   leave one end implicit, so it is the panel's live width: a resized panel opens to the width it was left at.
   The exit runs for PANEL_EXIT_MS (kits/useClosingAnimation.ts), like .fd-drawer.is-closing. Only an open that follows
   a close slides in (.is-entering): a panel that is open when it mounts is simply there. */
.fd-sidepanel {
  flex: none;
  min-width: 0;
  overflow: hidden;
  background: var(--surface);
  border-left: 1px solid var(--border);
}
.fd-sidepanel.is-entering {
  animation: fd-sidepanel-in 220ms var(--ease-out) backwards;
}
.fd-sidepanel.is-closing {
  animation: fd-sidepanel-out 220ms var(--ease) both;
}
@keyframes fd-sidepanel-in {
  from {
    width: 0;
  }
}
@keyframes fd-sidepanel-out {
  to {
    width: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .fd-sidepanel.is-entering,
  .fd-sidepanel.is-closing {
    animation-duration: 1ms;
  }
}
.fd-sidepanel-inner {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.fd-sidepanel-grip {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  touch-action: none;
  z-index: 4;
  transition: background var(--dur-fast) var(--ease);
}
.fd-sidepanel-grip:hover,
.fd-sidepanel-grip:focus-visible,
.fd-sidepanel.is-resizing .fd-sidepanel-grip {
  background: color-mix(in oklab, var(--brand) 26%, transparent);
}
.fd-side-group {
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--text-muted);
  padding: 0 14px;
  margin: 20px 0 8px;
}
.fd-side-item {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 44px;
  padding: 0 14px;
  border-radius: var(--r-md);
  color: var(--text-2);
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  cursor: pointer;
  border: 0;
  background: none;
  width: 100%;
  text-align: left;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-side-item:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fd-side-item[aria-current="page"] {
  background: var(--surface-brand);
  color: var(--text-on-surface-brand);
  font-weight: var(--w-semibold);
}
.fd-side-item-icon {
  font-size: 19px;
  flex: none;
  width: 20px;
  display: grid;
  place-items: center;
}
.fd-side-item-count {
  margin-left: auto;
  font-size: var(--label-size);
  font-weight: var(--w-bold);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.fd-brand {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
}
.fd-brand-mark {
  display: inline-flex;
  align-items: center;
  line-height: 0;
  flex: none;
}
.fd-brand-mark img {
  display: block;
  height: 26px;
  width: auto;
}
/* The mark's own artwork is a fixed dark navy with no light colorway (see
   FlytedeskBrand.tsx's comment) — on a dark surface it would otherwise vanish.
   brightness(0) turns every opaque ink pixel pure black while leaving transparent
   pixels transparent; invert(1) flips that black to white — same trick as
   forcing a single-color mark to work on both themes without a second asset to
   keep in sync. Light theme (the default, no selector needed) gets no filter and
   shows the real navy ink, which is what the mark was actually drawn in. */
[data-theme="dark"] .fd-brand-mark img {
  filter: brightness(0) invert(1);
}
.fd-brand-sm .fd-brand-mark img,
.fd-brand-mark-sm img {
  height: 19px;
}
.fd-brand-lg .fd-brand-mark img,
.fd-brand-mark-lg img {
  height: 32px;
}
.fd-topbar {
  height: var(--topbar-h);
  flex: none;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 var(--gutter-lg);
  position: relative;
}
/* MP-141: the breadcrumb is the Topbar's only elastic item. Every other direct child
   (overflowActions, actions — the version badge, the account trigger, any icon button)
   keeps its content width at any viewport: it never shrinks below what its own content
   needs. The crumb absorbs whatever space that leaves, growing to fill the row (so no
   separate spacer element is needed) and shrinking first when the row is tight. */
.fd-topbar > *:not(.fd-crumb) {
  flex-shrink: 0;
}
.fd-crumb {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--body-sm-size);
  color: var(--text-muted);
  min-width: 0;
}
.fd-crumb a {
  color: var(--text-muted);
}
.fd-crumb a:hover {
  color: var(--text);
}
/* The current crumb already exposes its full text via `truncationTitle` (Topbar.tsx),
   so it may ellipsize at any width, not only `.is-narrow` — the same rule that used to
   apply only in the collapsed layout now applies everywhere the row runs out of room. */
.fd-crumb-current {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-weight: var(--w-semibold);
}
.fd-topbar-overflow-list {
  gap: 2px;
  min-width: 160px;
}
/* MP-117 — every direct child of the overflow list (Ask, a version badge, Appearance,
   Dev tools, Undo — whatever a screen collapses) is one full-width row, so a compact
   control that packed tightly against its neighbours in the dense bar (a pill badge, a
   fixed-size icon square) can't sit at a different width/height than the rest and read
   as overlapping or uneven once stacked. */
.fd-topbar-overflow-list > * {
  width: 100%;
  flex: none;
}
.fd-topbar-overflow-list > .fd-badge {
  height: var(--control-h-md);
  border-radius: var(--r-md);
  justify-content: flex-start;
}
/* An IconButton rendered here (see OverflowRowContext/IconButton.tsx) trades its
   dense-bar square for a full labelled row: same icon, same accessible name, now with
   that name shown as text instead of only living in `aria-label`/`title`. */
.fd-btn-icon-row {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  width: 100%;
  height: var(--control-h-md);
  padding: 0 10px;
}
.fd-btn-icon-row .ph {
  font-size: 18px;
  flex: none;
}
.fd-btn-icon-row-label {
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Narrow Topbar (`is-narrow`, set by Topbar from its own `overflowBreakpoint`, so the
   crumb rules and the overflow menu always switch together): earlier crumbs hide (the
   nav drawer `onMenu` opens still reaches them). The crumb's grow/shrink and the current
   crumb's ellipsis are the base `.fd-crumb`/`.fd-crumb-current` rules above — they apply
   at every width, not only here. */
.fd-topbar.is-narrow .fd-crumb > *:not(:last-child) {
  display: none;
}

/* ============ Overlays ============ */
/* z-index is set inline by Modal.tsx/Drawer.tsx via useLayerZIndex (kits/layerStack.tsx). */
.fd-scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  backdrop-filter: blur(3px);
  animation: fd-fade var(--dur-base) var(--ease) both;
  display: grid;
  place-items: center;
  padding: 24px;
}
@keyframes fd-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes fd-fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
@keyframes fd-modal-in {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes fd-modal-out {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(8px) scale(0.99);
  }
}
@keyframes fd-drawer-in {
  from {
    transform: translateX(100%);
  }
  to {
    transform: none;
  }
}
@keyframes fd-drawer-out {
  from {
    transform: none;
  }
  to {
    transform: translateX(100%);
  }
}
.fd-scrim.is-closing {
  animation: fd-fade-out 200ms var(--ease) both;
}
.fd-drawer.is-closing {
  animation: fd-drawer-out 220ms var(--ease) both;
}
.fd-modal.is-closing {
  animation: fd-modal-out 190ms var(--ease) both;
}
@keyframes fd-view-in {
  from {
    opacity: 0;
    transform: translateY(7px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.fd-view-enter {
  animation: fd-view-in 340ms var(--ease-out) both;
}
@media (prefers-reduced-motion: reduce) {
  .fd-view-enter,
  .fd-drawer,
  .fd-modal,
  .fd-drawer.is-closing,
  .fd-modal.is-closing {
    animation-duration: 1ms;
  }
}
.fd-modal {
  width: 100%;
  max-width: 560px;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--e-3);
  animation: fd-modal-in var(--dur-slow) var(--ease-out) both;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.fd-modal-wide {
  max-width: 760px;
}
.fd-modal-head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 22px 24px 16px;
}
.fd-modal-title {
  flex: 1;
  font-size: var(--h2-size);
  line-height: var(--h2-lh);
  letter-spacing: var(--h2-track);
  font-weight: var(--w-semibold);
}
.fd-modal-body {
  padding: 0 24px 22px;
  position: relative; /* MP-298: contains absolutely positioned sr content, see .fd-scroll */
  overflow: auto;
}
.fd-modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 24px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
/* z-index is set inline by Drawer.tsx (and its scrim's) via useLayerZIndex (kits/layerStack.tsx). */
.fd-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: auto;
  height: auto;
  max-height: 100vh;
  min-height: min(340px, 100vh);
  width: min(520px, 100%);
  background: var(--surface);
  box-shadow: var(--e-4);
  display: flex;
  flex-direction: column;
  animation: fd-drawer-in var(--dur-panel) var(--ease-out) both;
}
/* `bare`: the content owns the whole panel (its own header, no padding), so the panel takes the
   viewport's full height instead of sizing to its content. */
.fd-drawer.is-bare {
  height: 100vh;
  height: 100dvh;
  max-height: none;
}
/* Tooltip's trigger wrapper. It takes no room of its own: it hugs its one child. */
.fd-tooltip-anchor {
  display: inline-flex;
  flex: none;
  min-width: 0;
}
/* Portaled to document.body and placed by Tooltip.tsx (fixed, anchored geometry), so no
   overflow: hidden ancestor of the trigger can clip it. Short labels stay on one line
   (max-content); a sentence wraps at a readable measure instead of running off-screen.
   z-index is set inline by Tooltip.tsx via useLayerZIndex (kits/layerStack.tsx). */
.fd-tooltip {
  position: fixed;
  width: max-content;
  max-width: min(280px, calc(100vw - 16px));
  background: var(--n-900);
  color: #fff;
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  line-height: 1.4;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  box-shadow: var(--e-2);
  white-space: normal;
  text-wrap: pretty;
  animation: fd-pop var(--dur-fast) var(--ease-out) both;
}
.fd-toast {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 340px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--e-3);
  padding: 14px 16px;
  animation: fd-rise var(--dur-slow) var(--ease-out) both;
}
.fd-toast-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: var(--r-full);
  font-size: 12px;
  color: #fff;
}
.fd-toast-body {
  flex: 1;
  min-width: 0;
  font-size: var(--body-sm-size);
}
.fd-toast-title {
  font-weight: var(--w-semibold);
  color: var(--text);
  font-size: var(--body-size);
}
/* The corner stack: the one bottom-right corner every floating surface (the toasts, the job
   tray) renders into a slot of, so they lay out one above the next instead of each pinning
   itself to the same corner. The stack itself has no box; each slot is fixed to the corner and its
   layer is set inline (the toasts above every overlay layer, the jobs just under the first one, so a
   menu opens over the tray). A slot is 340px wide, and on a phone the width between two gutters.
   A slot takes no clicks: it has a real box wherever a surface is, including the gaps between
   surfaces and the shadow around each, and without this a click aimed at the control underneath
   would land on it. Each surface takes its clicks back. The toasts sit one gap above the jobs
   (--fd-corner-stack-inset is the jobs' reach up from the bottom, 0 when there are none), and an
   empty slot takes no room (the toast region is always mounted for its live region). */
.fd-corner-stack {
  display: contents;
}
.fd-corner-stack-slot {
  position: fixed;
  bottom: var(--s-lg);
  right: calc(var(--s-lg) + var(--fd-corner-stack-offset, 0px));
  width: 340px;
  pointer-events: none;
}
.fd-corner-stack-slot[data-corner-stack-slot="toasts"] {
  bottom: max(var(--s-lg), calc(var(--fd-corner-stack-inset, 0px) + var(--s-sm)));
}
@media (max-width: 640px) {
  .fd-corner-stack-slot {
    width: calc(100vw - 2 * var(--s-lg));
  }
}
/* DS-29: a side-panel sheet covers the screen with its composer at the bottom; the jobs wait behind it. */
:root[data-fd-sheet-open] .fd-corner-stack-slot[data-corner-stack-slot="jobs"] {
  display: none;
}
/* ToastProvider's stack, in the corner stack's toasts slot. */
.fd-toast-region {
  display: flex;
  flex-direction: column;
  gap: var(--s-sm);
}
.fd-toast-region > * {
  pointer-events: auto;
}
.fd-toast-region > .fd-toast {
  width: auto;
}

/* ============ Flag / empty ============ */
.fd-flag {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 0 var(--r-md) var(--r-md) 0;
  border-left: 3px solid;
  font-size: var(--body-sm-size);
  flex-wrap: wrap;
}
.fd-flag-info {
  background: var(--info-fill);
  border-color: var(--info-solid);
  color: var(--info-text);
}
.fd-flag-success {
  background: var(--ok-fill);
  border-color: var(--ok-solid);
  color: var(--ok-text);
}
.fd-flag-warning {
  background: var(--warn-fill);
  border-color: var(--warn-solid);
  color: var(--warn-text);
}
.fd-flag-danger {
  background: var(--danger-fill);
  border-color: var(--danger-solid);
  color: var(--danger-text);
}
.fd-flag-text {
  flex: 1;
  min-width: 220px;
}
.fd-flag-cost {
  font-weight: var(--w-bold);
}
.fd-flag-actions {
  display: flex;
  gap: 8px;
}
.fd-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  padding: 56px 32px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--wash-panel);
}
.fd-empty-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: var(--r-full);
  background: var(--brand-soft);
  color: var(--brand);
  font-size: 24px;
}
.fd-empty-title {
  font-size: var(--h3-size);
  font-weight: var(--w-semibold);
  letter-spacing: var(--h3-track);
}
.fd-empty-body {
  font-size: var(--body-size);
  color: var(--text-2);
  max-width: 44ch;
  text-wrap: pretty;
}

/* ============ Rich popover fields (Select v2, pickers) ============ */
@keyframes fd-pop-in {
  from {
    opacity: 0;
    transform: translateY(-5px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.fd-popfield {
  position: relative;
}
.fd-pop {
  /* z-index is set inline by Popover.tsx via useLayerZIndex (kits/layerStack.tsx). */
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--e-3);
  animation: fd-pop-in 160ms var(--ease-out) both;
  transform-origin: top center;
  /* THE SURFACE NEVER SCROLLS. max-height (set inline by Popover.tsx) caps it at the
     real room between the anchor and the viewport edge; what does not fit is scrolled
     inside .fd-pop-body, never by the surface itself — a surface that scrolls as a whole
     carries its footer action below the fold and stacks a second scrollbar on any list
     inside it. overflow: hidden also keeps children inside the rounded corners. */
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Pinned regions. flex: none so the body is the only thing that gives up height. */
.fd-pop-header,
.fd-pop-footer {
  flex: none;
  padding: var(--s-12) var(--s-16);
}
.fd-pop-header {
  border-bottom: 1px solid var(--border);
}
/* DS-51: the standard title-and-Close header (Popover `title`). */
.fd-pop-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-8);
}
.fd-pop-title-row:not(:last-child) {
  margin-bottom: var(--s-8);
}
.fd-pop-title {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: var(--body-size);
  font-weight: var(--w-semibold);
  color: var(--text);
}
.fd-pop-title-row .fd-btn-icon {
  flex: none;
}
.fd-pop-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--s-8);
  border-top: 1px solid var(--border);
}
/* The one scroll region. min-height: 0 is what lets it shrink below its content inside
   the capped surface instead of pushing the footer out. It is itself a flex column so
   that a child owning a scroll region of its own (a Menu frame, a Select listbox) can
   take min-height: 0 too and shrink into the body — the child scrolls, the body does
   not, and there is still exactly one scrollbar. */
.fd-pop-body {
  flex: 1 1 auto;
  min-height: 0;
  position: relative; /* MP-298: contains absolutely positioned sr content, see .fd-scroll */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
}
/* Ordinary content never shrinks inside the body — it overflows it, and the body scrolls.
   (Without this, any child with overflow set would be squeezed and clipped instead.)
   Only a region that scrolls itself opts back in: .fd-pop-list and .fd-menu-frame, both
   declared later in this file. */
.fd-pop-body > * {
  flex-shrink: 0;
}
.fd-pop.is-up {
  top: auto;
  bottom: calc(100% + 6px);
  transform-origin: bottom center;
}
/* A list that scrolls inside a popover body. No max-height of its own: the surface is
   already capped by the viewport (and by Popover's maxHeight when a caller wants it
   shorter), and a second fixed cap here is exactly what used to put a scrollbar inside
   a scrollbar. */
.fd-pop-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 5px;
}
/* A popover's search row. It sits in the popover header, which owns the padding and the
   hairline below it. */
.fd-pop-search {
  display: flex;
  align-items: center;
  gap: 8px;
}
.fd-pop-search input {
  border: none;
  outline: none;
  background: none;
  font: inherit;
  font-size: var(--body-sm-size);
  color: var(--text);
  flex: 1;
  min-width: 0;
}
.fd-pop-group {
  padding: 9px 11px 3px;
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--text-muted);
}
.fd-opt {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: var(--r-sm);
  background: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--text);
}
.fd-opt.is-active {
  background: var(--surface-brand);
}
.fd-opt.is-selected .fd-opt-label {
  color: var(--brand);
  font-weight: var(--w-semibold);
}
.fd-opt[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}
.fd-opt-icon {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  display: grid;
  place-items: center;
  color: var(--text-2);
  font-size: 15px;
}
.fd-opt-label {
  display: block;
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  line-height: 1.35;
}
.fd-opt-desc {
  display: block;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.4;
  margin-top: 1px;
}
.fd-opt-meta {
  flex: none;
  margin-left: auto;
  font-size: 12px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  padding-top: 2px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.fd-opt-check {
  flex: none;
  width: 16px;
  color: var(--brand);
  font-size: 14px;
  padding-top: 2px;
}
.fd-pop-empty {
  padding: 16px 12px;
  font-size: var(--body-sm-size);
  color: var(--text-muted);
  text-align: center;
}
.fd-select-caret i {
  transition: transform var(--dur-base) var(--ease);
}
.fd-popfield.is-open .fd-select-caret i {
  transform: rotate(180deg);
}

/* ============ FilterBar (MP-243, SMS-50) ============ */
/* At 30rem and wider the bar is two columns on one wrapping row: the MAIN column, which is the
   "Filter" trigger (its own column, always first) beside the chips (a wrapping area of their own,
   taking the room left over), and an optional `actions` slot pinned to the right edge
   (`margin-left: auto`). The columns top-align, so however many lines the chips wrap onto, the
   trigger and the actions never move. The main column never wraps its two children under each
   other; when the row is too narrow for main and actions together (main keeps a floor of
   --filterbar-main-min), the actions wrap onto a row of their own and stay right-aligned.

   Below 30rem (a phone) there is no room for a column beside the button: the main column takes
   the whole row, the Filter button and Clear all share its first line, the chips wrap underneath
   on rows of their own, and the actions take the row below that. The switch is a container query
   on the bar itself, so it follows the room the bar is given, not the viewport.

   It is a block-level flex box that fills the row it is put in, and `min-width: 0` lets it
   shrink inside a flex parent instead of forcing that parent wider. A block-level flex box takes
   its width from its container, which is what makes wrapping, and the chips column's own width,
   well defined. */
.fd-filterbar {
  --filterbar-main-min: 20rem;
  /* The most a chip may take. A longer value is shortened in the middle (MiddleEllipsis). */
  --filterbar-chip-max: 15rem;
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--s-sm) var(--s-md);
  min-width: 0;
  container: fd-filterbar / inline-size;
}
.fd-filterbar-main {
  flex: 1 1 var(--filterbar-main-min);
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: var(--s-sm) var(--s-md);
}
/* A bar with nothing to show in it (no Filter button, no chips: the options have not loaded yet)
   gives up its main column entirely, so the actions are not pushed onto a row of their own by a
   column that holds nothing. */
.fd-filterbar-main:not(:has(.fd-filterbar-trigger, .fd-tag)) {
  display: none;
}
/* The Filter button, and Clear all right after it. Beside each other while the main column has
   room for both and a chip; when the actions beside the main column leave it under 30rem (the two,
   a gap and one chip at its max) Clear all stacks under the button, still in this column and
   never on a row of the chips' own. The column is exactly as wide as what is in it either way, so
   the chips always start one gap from it. The switch is a container query on the main column, not
   a wrapping flex row: a wrapped row takes its cap as its width and leaves a hole beside the
   button. A bar under 30rem wide is the phone layout below, which puts Clear all beside the
   button again. */
.fd-filterbar-main {
  container-type: inline-size;
}
.fd-filterbar-trigger {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--s-sm) var(--s-md);
}
@container (width < 30rem) {
  .fd-filterbar-trigger {
    flex-direction: column;
    align-items: flex-start;
  }
}
/* The count of applied filters, inside the Filter button: the kit's blue count pill, shrunk to
   sit beside the button's text without making the button taller. */
.fd-filterbar-count {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  margin-inline-start: var(--s-sm);
}
.fd-filterbar-chips {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  gap: var(--s-sm);
  /* One chip row centres on the Filter button (a control-h-md button) beside it. */
  min-height: var(--control-h-md);
}
.fd-filterbar-actions {
  flex: none;
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: flex-end;
  gap: var(--s-sm) var(--s-md);
  max-width: 100%;
}
/* A phone-width bar: the main column is the whole row, stacked, with Filter and Clear all side
   by side on its first line and the chips wrapping underneath at up to their max width each.
   It follows the rules it overrides so the two never tie on source order. */
@container fd-filterbar (width < 30rem) {
  .fd-filterbar-main {
    flex: 1 1 100%;
    flex-direction: column;
    align-items: stretch;
  }
  .fd-filterbar-trigger {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
  }
  .fd-filterbar-chips {
    flex: none;
    min-height: 0;
  }
  /* No chips, no row: an empty chips area would still add a row gap under the button. */
  .fd-filterbar-chips:empty {
    display: none;
  }
}
/* MP-282: seen live at 375px — a chip whose value is long (a full campaign name) painted
   637px wide inside a 297px-wide bar instead of respecting it, because .fd-tag is `flex:
   none; white-space: nowrap; max-width: none` with nothing to clamp it, and the ONLY thing
   that then hid the overflow was the page's own ancestor .fd-card `overflow: hidden` —
   which silently clipped the chip's × remove control right along with the label.
   Scoped to FilterBar's own chips, not `.fd-tag`/`.fd-tag-label` themselves: "never wider
   than this row" is FilterBar's rule, not Tag's. Tag is also used by RoadmapTimeline (a
   milestone label) and ApiSpecBrowser (an HTTP method, a module name, a screen path) —
   short, already-bounded-by-their-own-layout content where this bug was never observed and
   a forced max-width + ellipsis would only truncate text that fits today for no reason.

   The bound goes on .fd-filterbar-chip, the actual flex item of the chips column (the extra
   <span> FilterBar.tsx wraps `.fd-tag` in for select/multiSelect/range/date's chip, so React
   keeps one stable DOM node across the editing/non-editing transition). A percentage
   `max-width` on the button ALONE does nothing: this item's own width is shrink-to-fit
   (`auto`) with a default `min-width: auto`, which for non-wrapping text equals the label's
   full intrinsic width, so the percentage would resolve against a size derived from the very
   content it is meant to clamp (CSS2.1 §10.2: undefined; real browsers ignore it).
   `min-width: 0` on the flex item breaks that cycle, and `max-width` here is a plain length
   bounded by the row, so the chip is never wider than --filterbar-chip-max nor than the row
   it wraps in (SMS-50: was "the row" only, so a long value ran the whole row wide). */
.fd-filterbar-chip {
  min-width: 0;
  max-width: min(100%, var(--filterbar-chip-max));
}
/* DS-55: a chip with help keeps the chip and its help button on one line; the chip shrinks (its text
   ellipsizes), the button never does, so a wrapped chip carries its help with it. */
.fd-filterbar-chip.has-help {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1, 4px);
}
.fd-filterbar-chip.has-help > :first-child {
  min-width: 0;
  display: inline-flex;
}
.fd-filterbar-chip.has-help > .fd-tooltip-anchor,
.fd-filterbar-fixed .fd-tooltip-anchor {
  flex: none;
}
.fd-filterbar .fd-tag {
  max-width: 100%;
  min-width: 0;
}
/* Tag.tsx always wraps its children in this span (see Tag.tsx's own MP-282 comment) so
   there is something block-level (flex items are blockified, .fd-tag is inline-flex) to
   hang the ellipsis off. `min-width: 0` is needed because this label is itself a flex item
   of .fd-tag. The full text stays as the label's actual text content regardless of what is
   painted — that's what keeps the button's accessible name (computed from content, not from
   what's painted) the whole value; Tag's `title` prop (FilterBar passes the same full value)
   covers the hover-tooltip half of that same requirement. */
.fd-filterbar .fd-tag-label {
  overflow: hidden;
  white-space: nowrap;
  min-width: 0;
}
/* MiddleEllipsis (SMS-50): the head shrinks and ends in "…"; the tail never shrinks, so the end
   of a long value stays visible ("Flytedesk Spr…ement (na)"). `white-space: pre` keeps a space
   at the seam between the two spans, which a flex item would otherwise strip. */
.fd-mid-ellipsis {
  display: flex;
  min-width: 0;
  white-space: pre;
}
.fd-mid-ellipsis-head {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-mid-ellipsis-tail {
  flex: none;
}
/* The text field's own inline "chip that is also an input" — its editing state reuses
   .fd-tag's box but swaps in the selected/brand treatment .fd-tag[aria-pressed] already
   defines elsewhere, and the raw <input> inside is stripped of its own chrome so it reads
   as chip text you can type into, not a field dropped inside a chip. */
.fd-filterbar-text {
  background: var(--surface-brand);
  border-color: var(--border-brand);
  cursor: text;
}
/* MP-312: a chip whose filter the host set (a "fixed" field): the selected chip's look, but not a
   control. Only its x is one, so no hover change and no pointer on the label. */
.fd-filterbar-fixed {
  background: var(--surface-brand);
  border-color: var(--border-brand);
  color: var(--text-on-surface-brand);
  cursor: default;
}
.fd-filterbar-fixed:hover {
  background: var(--surface-brand);
  color: var(--text-on-surface-brand);
}
.fd-filterbar-fixed .fd-tag-remove:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-filterbar-text-input {
  all: unset;
  min-width: 90px;
  color: var(--text-on-surface-brand);
}
/* DS-44: the value panel's two toggles (Is any of / Is none of, Search / Paste a list) share one
   row. Each keeps its natural width and its options on one line, so a row too narrow for both wraps
   the second toggle whole onto its own line. The compact option padding is what lets the pair fit
   a 375-390px phone. */
.fd-filterbar-toggles .fd-seg {
  flex: none;
  flex-wrap: nowrap;
}
.fd-filterbar-toggles .fd-seg button {
  padding: 0 var(--s-8);
  white-space: nowrap;
}
/* The multi-select panel's own option rows are DIVs, not buttons (MP-243: options are
   reached by arrow keys via aria-activedescendant, not by Tab), so the checked/unchecked
   indicator is a plain decorative icon rather than .fd-opt-check's "only present once
   selected" checkmark. */
.fd-filterbar-opt-check {
  flex: none;
  color: var(--text-muted);
  font-size: 15px;
}
.fd-filterbar-opt-check.is-checked {
  color: var(--brand);
}

/* ============ Range slider ============ */
.fd-range {
  position: relative;
  height: 28px;
  display: flex;
  align-items: center;
  touch-action: none;
}
.fd-range-rail {
  position: absolute;
  left: 0;
  right: 0;
  height: 6px;
  border-radius: 3px;
  background: var(--surface-3);
}
.fd-range-fill {
  position: absolute;
  height: 6px;
  border-radius: 3px;
  background: var(--brand);
}
.fd-range-mark {
  position: absolute;
  top: 50%;
  width: 2px;
  height: 10px;
  transform: translate(-50%, -50%);
  border-radius: 1px;
  background: var(--border-strong);
}
.fd-range-mark.is-in {
  background: color-mix(in srgb, #fff 55%, var(--brand));
}
.fd-range-mark-label {
  position: absolute;
  top: calc(50% + 12px);
  transform: translateX(-50%);
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
}
.fd-range-thumb {
  position: absolute;
  top: 50%;
  width: 20px;
  height: 20px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--brand);
  box-shadow: var(--e-1);
  cursor: grab;
  transition:
    transform 120ms var(--ease-spring),
    box-shadow 120ms var(--ease);
}
.fd-range-thumb:hover {
  transform: translate(-50%, -50%) scale(1.12);
}
.fd-range-thumb:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-range-thumb.is-drag {
  cursor: grabbing;
  transform: translate(-50%, -50%) scale(1.22);
  box-shadow: var(--e-2);
}
.fd-range-chip {
  position: absolute;
  bottom: calc(50% + 14px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--n-900);
  color: #fff;
  font-size: 11.5px;
  font-weight: var(--w-semibold);
  font-variant-numeric: tabular-nums;
  padding: 3px 8px;
  border-radius: var(--r-sm);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms var(--ease);
}
.fd-range-thumb:hover .fd-range-chip,
.fd-range-thumb:focus .fd-range-chip,
.fd-range-thumb.is-drag .fd-range-chip {
  opacity: 1;
}
.fd-range.has-labels {
  margin-bottom: 16px;
}

/* ============ Calendar ============ */
.fd-cal {
  width: 292px;
  padding: 12px;
  user-select: none;
}
.fd-cal-head {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;
}
.fd-cal-title {
  flex: 1;
  text-align: center;
  border: none;
  background: none;
  cursor: pointer;
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  color: var(--text);
  padding: 6px 8px;
  border-radius: var(--r-sm);
}
.fd-cal-title:hover {
  background: var(--surface-2);
}
/* MP-272: visually hidden but still read by assistive tech — used for the calendar's live
 * month/year announcement, which has no visible element of its own (the mode-switch button
 * already shows the same text, but re-reads "button" on every change if it owns the label). */
.fd-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.fd-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
/* MP-272: each week (and the header) is a role="row" for grid semantics, but must not
 * introduce its own layout box — its 7 cells are still tracks of the parent's 7-column grid. */
.fd-cal-row {
  display: contents;
}
.fd-cal-dow {
  text-align: center;
  font-size: 10.5px;
  font-weight: var(--w-bold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 4px 0;
}
.fd-cal-day {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 34px;
  border: none;
  background: none;
  border-radius: var(--r-sm);
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: background var(--dur-fast) var(--ease);
}
.fd-cal-day:hover {
  background: var(--surface-2);
}
.fd-cal-day.is-empty {
  cursor: default;
}
.fd-cal-day.is-today::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 4px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--brand);
  transform: translateX(-50%);
}
.fd-cal-day.in-range {
  background: var(--surface-brand);
  border-radius: 0;
}
.fd-cal-day.is-edge {
  background: var(--brand);
  color: #fff;
  font-weight: var(--w-semibold);
  border-radius: var(--r-sm);
}
.fd-cal-day.is-edge.is-today::after {
  background: #fff;
}
.fd-cal-grid-months {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}
.fd-cal-cell {
  height: 44px;
  border: none;
  background: none;
  border-radius: var(--r-sm);
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  color: var(--text);
}
.fd-cal-cell:hover {
  background: var(--surface-2);
}
.fd-cal-cell.is-sel {
  background: var(--brand);
  color: #fff;
  font-weight: var(--w-semibold);
}
.fd-cal-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

/* ============ Clock (time picker) ============ */
.fd-clock {
  width: 216px;
  height: 216px;
  border-radius: 50%;
  background: var(--surface-2);
  position: relative;
  margin: 10px auto;
  touch-action: none;
}
.fd-clock-num {
  position: absolute;
  width: 32px;
  height: 32px;
  margin: -16px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  z-index: 2;
  pointer-events: none;
}
.fd-clock-num.is-sel {
  background: var(--brand);
  color: #fff;
  font-weight: var(--w-semibold);
}
.fd-clock-hand {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2px;
  background: var(--brand);
  transform-origin: bottom center;
  pointer-events: none;
}
.fd-clock-pivot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px;
  border-radius: 50%;
  background: var(--brand);
  pointer-events: none;
}
.fd-clock-digits {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.fd-clock-digit {
  border: none;
  font: inherit;
  font-size: 26px;
  font-weight: var(--w-bold);
  font-variant-numeric: tabular-nums;
  width: 64px;
  text-align: center;
  background: var(--surface-2);
  color: var(--text);
  border-radius: var(--r-sm);
  padding: 6px 0;
  cursor: pointer;
}
.fd-clock-digit.is-active {
  background: var(--surface-brand);
  color: var(--brand);
}

/* ============ Number stepper ============ */
.fd-stepbtn {
  flex: none;
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-2);
  display: grid;
  place-items: center;
  cursor: pointer;
  font-size: 14px;
  transition:
    background var(--dur-fast) var(--ease),
    transform 80ms var(--ease);
}
.fd-stepbtn:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fd-stepbtn:active {
  transform: scale(0.9);
}
.fd-stepbtn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
/* NumberInput's +/- pair, sitting after the input inside .fd-input (whose own gap
 * separates the pair from the text). */
.fd-input-steppers {
  display: flex;
  align-items: center;
  gap: var(--s-xs);
  flex: none;
}

/* ============ Misc layout helpers ============ */
.fd-shell {
  display: flex;
  height: 100%;
  min-height: 0;
  background: var(--page);
}
.fd-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.fd-scroll {
  flex: 1;
  /* MP-298: positioned so an absolutely positioned child (a chart's `.fd-sr` data table) is
     contained and clipped by this scroller instead of stretching the page behind it. */
  position: relative;
  overflow: auto;
  padding: var(--gutter-lg);
}
/* The app shell's content scroller. Its bottom padding also clears the corner stack (the job
   tray, the toasts), which is fixed over the viewport's bottom corner: the stack publishes how
   far it reaches up as --fd-corner-stack-inset while a surface shows, so the last of the
   content scrolls clear of it at every width instead of ending underneath it. */
.fd-app-shell-content {
  padding: 24px 24px calc(24px + var(--fd-corner-stack-inset, 0px));
}
.fd-stack {
  display: flex;
  flex-direction: column;
}
.fd-row {
  display: flex;
  align-items: center;
}
/* SMS-7: layout utility modifiers for .fd-stack/.fd-row — the gap/wrap/
 * align/min-width/flex values every consumer app was reaching for inline —
 * pulled out here once so no app hand-rolls `style={{ gap, flexWrap,
 * alignItems, ... }}` again. Gap sizes are the spacing scale's own sm/md/lg/xl
 * steps (styles/tokens.css) — each class name is that token's tier, so
 * `fd-gap-md` is always `var(--s-md)`, never a value only that class knows
 * about. There is no bare `fd-gap-xs`: the scale's xs step (4px) hasn't had a
 * consumer yet, so it isn't exposed as an unused utility (add it, at
 * `var(--s-xs)`, the day something needs it). min-width sizes are named, not
 * arbitrary, so a consumer picks "sm"/"md" rather than inventing a pixel
 * value. */
/* MP-243: FilterBar's own stacks (a panel's selected-count line, a tag row) needed the
 * scale's xs step — the day this comment predicted. */
.fd-gap-xs {
  gap: var(--s-xs);
}
.fd-gap-sm {
  gap: var(--s-sm);
}
.fd-gap-md {
  gap: var(--s-md);
}
.fd-gap-lg {
  gap: var(--s-lg);
}
.fd-gap-xl {
  gap: var(--s-xl);
}
.fd-wrap {
  flex-wrap: wrap;
}
.fd-align-start {
  align-items: flex-start;
}
.fd-align-center {
  align-items: center;
}
.fd-align-end {
  align-items: flex-end;
}
.fd-justify-between {
  justify-content: space-between;
}
.fd-flex-1 {
  flex: 1 1 0%;
}
.fd-min-w-sm {
  min-width: 200px;
}
.fd-min-w-md {
  min-width: 280px;
}
/* A full-viewport centered region — the loading/error shell around a
 * signed-in app's auth gate, before the real chrome (Shell/Topbar) mounts. */
.fd-center-viewport {
  display: grid;
  place-items: center;
  height: 100vh;
}
.fd-grid-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 175px), 1fr));
  gap: 16px;
}
/* MP-310 — StatGrid (src/components/data/StatGrid.tsx): a stat tile set that wraps only into even
   rows. `fd-grid-stats` above is `auto-fit` and stays as it is; this is the opt-in for a set that
   must never strand one tile on a line (four tiles at a width that fits three). The root is the
   size container and the tiles sit in a grid inside it (a grid cannot query its own width), so the
   count follows the box the set is placed in, not the viewport. Each step is the narrowest
   container that holds that many tiles at the same 175px floor `fd-grid-stats` uses and one 16px
   gap between: two tiles need 366px, four need 748px. A set of four stops at 2 between those two
   widths rather than going to 3. */
.fd-stat-grid {
  container-type: inline-size;
}
.fd-stat-grid-tiles {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}
@container (width >= 366px) {
  .fd-stat-grid-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@container (width >= 748px) {
  .fd-stat-grid-tiles[data-columns="4"] {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
/* DS-54 — StatGrid columns=3: three tiles at the 175px floor need 559px; below that, one column
   (the 2-column step above is cancelled so a set of three is never 2 + 1). */
@container (width >= 366px) {
  .fd-stat-grid-tiles[data-columns="3"] {
    grid-template-columns: minmax(0, 1fr);
  }
}
@container (width >= 559px) {
  .fd-stat-grid-tiles[data-columns="3"] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
/* DS-54 — PanelRow (src/components/layout/PanelRow.tsx): two equal panels, one column when the row's
   own container is under 560px. */
.fd-panel-row {
  container-type: inline-size;
}
.fd-panel-row-panels {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}
@container (width >= 560px) {
  .fd-panel-row-panels {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* MP-271 — CardGrid (src/components/layout/CardGrid.tsx). `auto-fill` rather than
   `fd-grid-stats`'s own `auto-fit` above on purpose: a dashboard of Cards should keep a
   consistent card width as the count changes, not stretch a lone card to fill the whole row
   the way a handful of stat tiles usefully do. `--card-grid-min` is set inline per instance
   (CardGrid's `minCardWidth` prop, default 280px); `1fr` is what lets the last, partial row's
   cards still share the leftover width evenly rather than sitting at a fixed size with a gap
   down one side. Gap is deliberately NOT set here — CardGrid applies one of the existing
   `fd-gap-*` utility classes above alongside this one, so a "medium gap" stays one token
   shared with every other flex/grid consumer of the spacing scale, not a second grid-only
   value. Equal-height rows need no explicit rule: `align-items: stretch` is Grid's own
   default, restated below only so it can't silently regress if that default is ever
   overridden elsewhere for `.fd-card-grid`'s selector specifically. MP-299: the track floor is
   `min(100%, var(--card-grid-min))` so a `minCardWidth` wider than the container (a 560px floor on
   a 375px phone) collapses to one full-width column instead of a track that overflows it. */
.fd-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--card-grid-min, 280px)), 1fr));
  align-items: stretch;
}
/* MP-271 review (comment 2920, finding 2): CardGrid wraps every item in its own
   `<div role="listitem">` rather than cloning `role` onto the child (a clone silently drops
   an added prop on a Fragment child, and can't fix that). The wrapper is now the real grid
   item that `align-items: stretch` above stretches to the row's height, so it has to pass
   that height on to its own one real child the same way `.fd-card-body`'s `flex: 1 1 auto`
   passes extra height down to `.fd-card-foot` — otherwise a stretched wrapper with an
   un-stretched child inside it would look identical to no equal-height rows at all. */
.fd-card-grid > [role="listitem"] {
  display: flex;
  min-width: 0;
}
.fd-card-grid > [role="listitem"] > * {
  flex: 1 1 auto;
  min-width: 0;
}
@media (max-width: 640px) {
  .fd-grid-stats {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
    gap: 10px;
  }
  .fd-stat {
    padding: 12px 14px;
  }
  .fd-stat-figure {
    font-size: clamp(18px, 5vw, 24px);
  }
  .fd-table {
    min-width: 560px;
  }
}
.fd-stat-span2 {
  grid-column: span 2;
}
@media (max-width: 380px) {
  .fd-stat-span2 {
    grid-column: auto;
  }
}
.fd-stat-compact {
  padding: 10px 14px;
}
.fd-stat-compact .fd-stat-figure {
  font-size: clamp(17px, 0.6vw + 12px, 22px);
}
.fd-stat-compact .fd-stat-label {
  margin-top: 3px;
}
.fd-grid-stats.is-thin {
  gap: 10px;
}
@media (max-width: 1024px) {
  .fd-side {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    z-index: 90;
    transform: translateX(-100%);
    margin-left: 0;
    opacity: 1;
    transition: transform var(--dur-panel) var(--ease);
  }
  .fd-side[data-open="false"] {
    margin-left: 0;
    opacity: 1;
    pointer-events: none;
  }
  .fd-side[data-open="true"] {
    transform: none;
    box-shadow: var(--e-4);
    pointer-events: auto;
  }
}
.fd-nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 85;
  background: color-mix(in srgb, var(--n-900) 32%, transparent);
  backdrop-filter: blur(6px) saturate(0.9);
  -webkit-backdrop-filter: blur(6px) saturate(0.9);
  animation: fd-fade var(--dur-base) var(--ease) both;
  border: 0;
}
.fd-nav-scrim.is-closing {
  animation: fd-fade-out var(--dur-base) var(--ease) both;
}
@media (max-width: 768px) {
  :root {
    --gutter-lg: 16px;
  }
  .fd-scroll {
    padding: 16px;
  }
  .fd-card-head,
  .fd-card-body {
    padding: 14px;
  }
  .fd-modal {
    max-width: 100%;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    align-self: flex-end;
  }
  .fd-scrim {
    padding: 0;
    align-items: flex-end;
  }
  .fd-toast {
    width: calc(100vw - 32px);
  }
}

/* ==========================================================================
   1 · generic additions
   ========================================================================== */

/* --- key hints ------------------------------------------------------------ */
.fd-keyhint {
  display: inline-flex;
  gap: 2px;
  align-items: center;
  vertical-align: middle;
}
.fd-keyhint kbd {
  font: inherit;
  font-size: 11px;
  line-height: 1;
  font-weight: var(--w-medium);
  font-family: var(--font-sans);
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  display: inline-grid;
  place-items: center;
  color: var(--text-muted);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-xs);
}
.fd-keyhint-solid kbd {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--text-2);
}
.fd-keyhint-sm kbd {
  font-size: 10.5px;
  height: 15px;
  min-width: 15px;
}

/* --- clamp --------------------------------------------------------------- */
.fd-clamp {
  position: relative;
  min-width: 0;
}
.fd-clamp-body {
  overflow: hidden;
}
.fd-clamp.is-clamped .fd-clamp-body {
  -webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
}
.fd-clamp-more,
.fdc-more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 8px;
  border: 0;
  background: none;
  color: var(--brand);
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.fd-clamp-more:hover,
.fdc-more:hover {
  background: var(--surface-2);
}
.fdc-more-len {
  color: var(--text-muted);
  font-weight: var(--w-regular);
  font-size: 12px;
}

/* --- segmented meter + quota rows ---------------------------------------- */
.fd-segmeter {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}
.fd-segmeter-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  justify-content: space-between;
}
.fd-segmeter-label {
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  color: var(--text-2);
}
.fd-segmeter-total {
  font-size: var(--body-sm-size);
  color: var(--text-2);
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}
.fd-segmeter-sep,
.fd-segmeter-pct {
  color: var(--text-muted);
}
.fd-segmeter-rail {
  display: flex;
  gap: 2px;
  width: 100%;
  border-radius: var(--r-full);
  background: var(--surface-3);
  overflow: hidden;
}
.fd-segmeter-seg {
  display: block;
  height: 100%;
  border-radius: 1px;
  transition: width var(--dur-base) var(--ease);
}
.fd-segmeter-legend {
  list-style: none;
  margin: 2px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.fd-segmeter-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text-2);
}
.fd-segmeter-dot {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  flex: none;
}
.fd-segmeter-dot.is-empty {
  background: var(--surface-3);
  box-shadow: inset 0 0 0 1px var(--border);
}
.fd-segmeter-key {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fd-segmeter-val {
  color: var(--text-muted);
}
.fd-segmeter-legend .is-remainder {
  color: var(--text-muted);
}

.fd-quota {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.fd-quota-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.fd-quota-label {
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  color: var(--text);
}
.fd-quota-note {
  flex: 1;
  text-align: right;
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
}
.fd-quota-pct {
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  color: var(--text-2);
  min-width: 34px;
  text-align: right;
}
.fd-quota-rail {
  height: 5px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  overflow: hidden;
}
.fd-quota-fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  transition: width var(--dur-base) var(--ease);
}

/* --- charts (MP-210): TrendChart, DonutChart, BarList, FunnelChart -------- */
/* Colour comes only from --chart-1..8 (tokens.css), which are declared once in :root
   and never redefined under [data-theme="dark"] or [data-contrast="high"] — so every
   fill/stroke below is already correct in all three without a single override rule
   here. Only the theme-aware tokens (--text, --text-2, --text-muted, --border,
   --surface-3) carry axes, gridlines and labels, which DO need to shift per theme. */
.fd-chart-legend {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
}
.fd-chart-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: none;
  background: none;
  padding: 3px 4px;
  margin: -3px -4px;
  border-radius: var(--r-sm);
  font-size: var(--body-sm-size);
  color: var(--text-2);
  cursor: pointer;
  transition: opacity var(--dur-base) var(--ease), background var(--dur-fast) var(--ease);
}
.fd-chart-legend-item:hover {
  background: var(--surface-2);
}
.fd-chart-legend-item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-chart-legend-item.is-dim {
  opacity: 0.45;
}
.fd-chart-legend-swatch {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  flex: none;
}
.fd-chart-legend-label {
  white-space: nowrap;
}

/* TrendChart */
.fd-trend {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  min-width: 0;
}
.fd-trend-plot {
  width: 100%;
}
.fd-trend-svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.fd-trend-grid {
  stroke: var(--border);
  stroke-width: 1;
}
.fd-trend-axis {
  stroke: var(--border-strong);
  stroke-width: 1;
}
/* SMS-50: 10px, and it stays 10px — TrendChart draws its SVG in real pixels at the container's
   width (viewBox === rendered size), so this is what paints, never multiplied by the card. */
.fd-trend-axis-label {
  fill: var(--text-muted);
  font-size: 10px;
  font-family: var(--font-sans);
}
.fd-trend-line {
  transition: opacity var(--dur-base) var(--ease);
  vector-effect: non-scaling-stroke;
}
.fd-trend-dot {
  cursor: pointer;
  transition: r var(--dur-fast) var(--ease);
}
.fd-trend-dot:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}
.fd-trend-tip text {
  fill: var(--text);
  font-size: 11px;
  font-weight: var(--w-medium);
  paint-order: stroke;
  stroke: var(--surface);
  stroke-width: 3px;
}
.fd-trend-skel {
  width: 100%;
}

/* DonutChart */
.fd-donut {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fd-donut-body {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}
.fd-donut-ring {
  position: relative;
  flex: none;
}
.fd-donut-ring svg {
  display: block;
  width: 100%;
  height: 100%;
}
.fd-donut-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
}
.fd-donut-center[hidden] { display: none; }
.fd-donut-center-big {
  font-size: var(--h3-size);
  font-weight: var(--w-semibold);
  color: var(--text);
  line-height: 1.1;
}
.fd-donut-center-small {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}
.fd-donut-legend {
  /* Basis is the widest row, so the legend takes the room it needs beside the ring and drops below it
     (full width) only when that room is not there. */
  flex: 1 1 max-content;
  min-width: 160px;
  margin-top: 0;
  flex-direction: column;
  align-items: flex-start;
  max-width: 100%;
}
/* DS-54: the legend row now carries the count too, so the label may wrap inside a narrow
   container instead of pushing the chart past it. */
.fd-donut-legend > li {
  max-width: 100%;
}
.fd-donut-legend .fd-chart-legend-item {
  text-align: left;
}
.fd-donut-legend .fd-chart-legend-label {
  white-space: normal;
  min-width: 0;
}
/* The `pct% · count` part of a row never splits; only a long label wraps. */
.fd-donut-legend-value {
  white-space: nowrap;
}

/* BarList */
/* One shared column set for the whole list, so every row's label, bar, value and percent
   line up. The label column is as wide as the widest label (capped at 40% of the list, past
   which a long label ellipsizes and exposes its full text via `title`), so a short label such
   as a date is always shown whole instead of being cut to a fixed share of the row. Each level
   between the list and the cells (item, Tooltip anchor, button) is a subgrid over those same
   columns. */
.fd-barlist-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: fit-content(40%) minmax(48px, 1fr) max-content max-content;
  column-gap: 10px;
  row-gap: 2px;
}
.fd-barlist-row,
.fd-barlist-row .fd-tooltip-anchor,
.fd-barlist-btn {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  min-width: 0;
}
.fd-barlist-btn {
  align-items: center;
  border: none;
  background: none;
  padding: 6px 4px;
  border-radius: var(--r-sm);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
}
.fd-barlist-btn:hover {
  background: var(--surface-2);
}
.fd-barlist-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-barlist-label {
  font-size: var(--body-sm-size);
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.fd-barlist-track {
  min-width: 0;
  display: flex;
  align-items: center;
}
.fd-barlist-track svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.fd-barlist-rail {
  fill: var(--surface-3);
}
.fd-barlist-value {
  font-size: var(--body-sm-size);
  color: var(--text);
  white-space: nowrap;
}
.fd-barlist-pct {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  min-width: 34px;
  text-align: right;
}
@media (max-width: 480px) {
  .fd-barlist-list {
    grid-template-columns: fit-content(40%) minmax(40px, 1fr) max-content;
    column-gap: 6px;
  }
  .fd-barlist-pct {
    display: none;
  }
}

/* FunnelChart */
.fd-funnel-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  /* Wider than the label-to-bar gap in .fd-funnel-btn, so each label groups with the bar beneath it. */
  gap: 14px;
}
/* See the identical rule on .fd-barlist-row: Tooltip's trigger wrapper shrink-wraps its
   content by default, but here the trigger is the whole step row. */
.fd-funnel-row .fd-tooltip-anchor {
  display: block;
  width: 100%;
}
.fd-funnel-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 100%;
  border: none;
  background: none;
  padding: 4px;
  border-radius: var(--r-sm);
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.fd-funnel-btn:hover {
  background: var(--surface-2);
}
.fd-funnel-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-funnel-shape-wrap {
  width: 100%;
  display: flex;
  justify-content: center;
}
.fd-funnel-shape {
  display: block;
  height: 100%;
  transition: width var(--dur-base) var(--ease);
}
.fd-funnel-meta {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: var(--body-sm-size);
}
.fd-funnel-label {
  font-weight: var(--w-medium);
  color: var(--text);
}
.fd-funnel-value {
  color: var(--text-2);
}
.fd-funnel-rates {
  display: flex;
  gap: 10px;
  color: var(--text-muted);
  font-size: 12px;
}

/* --- code + diff --------------------------------------------------------- */
.fd-code {
  border: 1px solid var(--chat-code-border);
  border-radius: var(--r-md);
  background: var(--chat-code-bg);
  overflow: hidden;
  margin: 10px 0;
}
.fd-code-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px 5px 12px;
  border-bottom: 1px solid var(--chat-code-border);
  background: var(--surface-2);
  min-height: 32px;
}
.fd-code-icon {
  color: var(--text-muted);
  font-size: 14px;
}
.fd-code-file {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: var(--w-medium);
  color: var(--text-2);
}
.fd-code-lang {
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--text-muted);
}
.fd-code-spacer {
  flex: 1;
}
.fd-code-act {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 0;
  background: none;
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  font-weight: var(--w-medium);
  padding: 4px 7px;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-code-act:hover {
  background: var(--surface-3);
  color: var(--text);
}
.fd-code-act.is-done {
  color: var(--ok-solid);
}
.fd-code-act i {
  font-size: 13px;
}
.fd-code-body {
  display: flex;
  overflow: auto;
}
.fd-code-gutter {
  margin: 0;
  padding: 10px 0 10px 12px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.62;
  color: var(--text-disabled);
  text-align: right;
  user-select: none;
  flex: none;
  background: none;
  border: 0;
}
.fd-code-pre {
  margin: 0;
  padding: 10px 12px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.62;
  color: var(--text);
  overflow: auto;
  flex: 1;
  min-width: 0;
  tab-size: 2;
}
.fd-code.is-wrap .fd-code-pre {
  white-space: pre-wrap;
  word-break: break-word;
}
.fd-code-pre:focus-visible {
  outline: none;
  box-shadow: inset var(--focus-ring);
}
.fd-code-fold {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 0;
  border-top: 1px solid var(--chat-code-border);
  background: var(--surface-2);
  color: var(--text-2);
  font: inherit;
  font-size: 12px;
  font-weight: var(--w-semibold);
  padding: 6px;
  cursor: pointer;
}
.fd-code-fold:hover {
  background: var(--surface-3);
  color: var(--text);
}
.tok-kw {
  color: var(--code-kw);
}
.tok-str {
  color: var(--code-str);
}
.tok-num {
  color: var(--code-num);
}
.tok-com {
  color: var(--code-com);
  font-style: italic;
}
.tok-fn {
  color: var(--code-fn);
}
.tok-type {
  color: var(--code-type);
}
.tok-prop {
  color: var(--code-prop);
}
.tok-lit {
  color: var(--code-lit);
}
.tok-pun {
  color: var(--code-pun);
}
.tok-op {
  color: var(--code-pun);
}

/* ── MP-274: CodeEditor ──────────────────────────────────────────────────
   Shares .fd-input's chrome (border, radius, focus ring, disabled tint) with
   Input/Textarea, and .fd-code's border/background tokens, so it reads as a
   form field AND a code surface rather than inventing a third look. CodeMirror
   renders its own DOM into .fd-code-editor-host; every color it uses is a CSS
   variable set on that DOM by CodeEditor.tsx's EditorView.theme, and the
   .tok-* rules above (shared with CodeBlock) are the ones that actually paint
   its syntax highlighting, so both components' SQL always looks identical in
   light, dark and high-contrast. */
.fd-code-editor {
  padding: 0;
  font-family: var(--font-mono);
  background: var(--chat-code-bg);
  overflow: hidden;
}
.fd-code-editor-host {
  height: 100%;
}
.fd-code-editor-host .cm-editor {
  height: 100%;
}
.fd-code-editor.fd-input-disabled .fd-code-editor-host {
  opacity: 0.6;
}
.fd-code-editor-diagnostics {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fd-code-editor-diag {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: var(--text-sm-size, 12.5px);
  color: var(--text-2);
}
.fd-code-editor-diag i {
  flex: none;
}
.fd-code-editor-diag.is-error {
  color: var(--danger-text);
}
.fd-code-editor-diag.is-error i {
  color: var(--danger-solid);
}
.fd-code-editor-diag.is-warning {
  color: var(--warn-text);
}
.fd-code-editor-diag.is-warning i {
  color: var(--warn-solid);
}
.fd-code-editor-diag.is-info {
  color: var(--info-text);
}
.fd-code-editor-diag.is-info i {
  color: var(--info-solid);
}
.fd-code-editor-diag-loc {
  font-family: var(--font-mono);
  font-weight: var(--w-semibold);
  flex: none;
}
.fd-code-editor-hint {
  color: var(--text-disabled);
}

.fd-diff-body {
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.6;
  overflow-x: auto;
  padding: 4px 0;
}
.fd-diff-line {
  display: flex;
  gap: 8px;
  padding: 0 12px 0 0;
  white-space: pre;
}
.fd-diff-mark {
  width: 16px;
  flex: none;
  text-align: center;
  color: var(--text-disabled);
  user-select: none;
}
.fd-diff-line.is-add {
  background: var(--diff-add-bg);
  color: var(--diff-add-text);
}
.fd-diff-line.is-del {
  background: var(--diff-del-bg);
  color: var(--diff-del-text);
}
.fd-diff-line.is-hunk {
  color: var(--code-kw);
  background: var(--surface-2);
}
.fd-diff-line.is-meta {
  color: var(--text-muted);
}
.fd-diff-stat {
  display: flex;
  gap: 7px;
  font-size: 11.5px;
  font-weight: var(--w-semibold);
}
.fd-diff-stat .is-add {
  color: var(--ok-solid);
}
.fd-diff-stat .is-del {
  color: var(--danger-solid);
}

/* --- markdown ------------------------------------------------------------ */
.fd-md {
  font-size: var(--body-size);
  line-height: 1.62;
  color: var(--chat-text);
  text-wrap: pretty;
  min-width: 0;
}
.fd-md--small {
  font-size: var(--body-sm-size);
}
.fd-md--muted {
  color: var(--chat-text-2);
}
.fd-md-inline--body {
  font-size: var(--body-size);
}
.fd-md-inline--small {
  font-size: var(--body-sm-size);
}
.fd-md-inline--muted {
  color: var(--text-2);
}
.fd-md-p {
  margin: 0;
}
/* DS-6: after .fd-md-p so sibling spacing wins at equal specificity */
.fd-md > * + * {
  margin-top: 10px;
}
.fd-md-h {
  margin: 16px 0 0;
  font-weight: var(--w-semibold);
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.fd-md > .fd-md-h:first-child {
  margin-top: 0;
}
.fd-md-h1,
.fd-md-h2 {
  font-size: 17px;
}
.fd-md-h3 {
  font-size: 15.5px;
}
.fd-md-h4,
.fd-md-h5,
.fd-md-h6 {
  font-size: 14px;
  color: var(--text-2);
}
.fd-md-code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  padding: 1.5px 5px;
  border-radius: var(--r-xs);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
}
.fd-md-hr {
  margin: 16px 0;
  border-top: 1px solid var(--border);
}
.fd-md-quote {
  margin: 0;
  padding: 2px 0 2px 14px;
  border-left: 2px solid var(--border-strong);
  color: var(--text-2);
}
.fd-md-list {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fd-md-list.is-task {
  list-style: none;
  padding-left: 2px;
}
.fd-md-list li {
  min-width: 0;
}
.fd-md-list.is-task li {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}
.fd-md-task {
  color: var(--brand);
  font-size: 15px;
  line-height: 1.5;
  flex: none;
}
.fd-md-list.is-task li.is-done .fd-md-li {
  color: var(--text-muted);
  text-decoration: line-through;
}
.fd-md-li {
  display: block;
  min-width: 0;
}
.fd-md-li > * + * {
  margin-top: 6px;
}
.fd-md-img {
  max-width: 100%;
  max-height: 320px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  margin: 4px 0;
}
.fd-md-imgalt {
  font-size: var(--body-sm-size);
  color: var(--text-muted);
}
.fd-md-cite {
  font-size: 10px;
  font-weight: var(--w-bold);
  color: var(--brand);
  background: var(--surface-brand);
  padding: 1px 4px;
  border-radius: var(--r-full);
  margin-left: 2px;
  vertical-align: super;
}
.fd-md-tablewrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.fd-md-table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--body-sm-size);
}
.fd-md-table th {
  background: var(--surface-2);
  font-weight: var(--w-semibold);
  color: var(--text-2);
  font-size: var(--label-size);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  padding: 8px 11px;
  white-space: nowrap;
}
.fd-md-table td {
  padding: 8px 11px;
  border-top: 1px solid var(--border);
  font-variant-numeric: tabular-nums lining-nums;
}
.fd-md-inline {
  min-width: 0;
}

/* --- files --------------------------------------------------------------- */
.fd-filegrid {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.fd-filegrid-tiles {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.fd-filegrid-chips {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.fd-file {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  max-width: 100%;
  transition:
    border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}
.fd-file:hover {
  border-color: var(--border-strong);
}
.fd-file.is-error {
  border-color: var(--danger-border);
  background: var(--danger-fill);
}
.fd-file-main {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--text);
}
.fd-file-main:disabled {
  cursor: default;
}
.fd-file-icon {
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  display: grid;
  place-items: center;
  color: var(--text-2);
  font-size: 15px;
  overflow: hidden;
}
.fd-file-icon img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fd-file-play {
  position: absolute;
  color: #fff;
  font-size: 12px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.fd-file-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.fd-file-name {
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-file-meta {
  font-size: 11.5px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 5px;
}
.fd-file-err {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--danger-text);
}
.fd-file-act {
  flex: none;
  width: 28px;
  height: 28px;
  margin-right: 4px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: var(--text-muted);
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: 14px;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-file-act:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fd-file-prog,
.fd-tile .fd-file-prog {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--surface-3);
}
.fd-file-prog-fill {
  display: block;
  height: 100%;
  background: var(--brand);
  transition: width 160ms linear;
}
.fd-file.is-compact .fd-file-icon {
  width: 24px;
  height: 24px;
  font-size: 13px;
}
.fd-file.is-compact .fd-file-main {
  padding: 5px 7px;
  gap: 8px;
}

.fd-tile {
  position: relative;
  margin: 0;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-2);
  max-width: 100%;
}
.fd-tile-btn {
  display: block;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  max-width: 100%;
}
.fd-tile-btn:disabled {
  cursor: default;
}
.fd-tile img {
  display: block;
  max-width: 100%;
  width: auto;
  object-fit: cover;
}
.fd-tile-fallback {
  display: grid;
  place-items: center;
  width: 120px;
  height: 90px;
  color: var(--text-muted);
  font-size: 22px;
}
.fd-tile-x {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-full);
  background: rgba(11, 13, 17, 0.62);
  color: #fff;
  font-size: 11px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.fd-tile:hover .fd-tile-x,
.fd-tile-x:focus-visible {
  opacity: 1;
}
.fd-tile-err {
  padding: 5px 8px;
  font-size: 11.5px;
  color: var(--danger-text);
  display: flex;
  align-items: center;
  gap: 5px;
}
.fd-tile.is-error {
  border-color: var(--danger-border);
}

/* ============ ReferenceList ============ */
/* Reads the same at every width: the term and its tag on one line, the description wrapped below.
   Long terms break anywhere rather than push the page sideways. */
.fd-ref {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.fd-ref-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
/* The match-count live region stays rendered (and so in the accessibility tree) while empty: a region that
   only appears with its first text is not reliably announced. Empty, it takes no room. */
.fd-ref-status {
  margin: 0;
  font-size: var(--body-sm-size);
  color: var(--text-2);
}
.fd-ref-status:not(:empty) {
  margin-top: var(--s-6);
}
.fd-ref-empty {
  margin: 0;
  color: var(--text-2);
}
.fd-ref-entries {
  margin: 0;
  display: flex;
  flex-direction: column;
}
.fd-ref-entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "head actions" "desc desc";
  align-items: center;
  column-gap: 8px;
  row-gap: 2px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
  min-width: 0;
}
.fd-ref-entry:first-child {
  border-top: 0;
  padding-top: 0;
}
.fd-ref-head {
  grid-area: head;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  min-width: 0;
}
.fd-ref-term {
  font-weight: var(--w-medium);
  color: var(--text);
  overflow-wrap: anywhere;
  min-width: 0;
}
.fd-ref-term.is-mono {
  font-family: var(--font-mono);
  font-size: var(--mono-size);
}
.fd-ref-tag {
  height: 20px;
  font-family: var(--font-mono);
}
.fd-ref-desc {
  grid-area: desc;
  margin: 0;
  color: var(--text-2);
  font-size: var(--body-sm-size);
  overflow-wrap: anywhere;
  white-space: normal;
}
.fd-ref-actions {
  grid-area: actions;
  margin: 0;
  display: flex;
  align-items: center;
}

/* ============ Scroll region and plain list (utilities) ============ */
/* .fd-scroll-region — a bounded-height, vertically scrolling container. The height cap is
   --fd-scroll-region-max (override it on the element or an ancestor); the scrollbar is
   .fd-scrollbar's treatment (shared rules below). A scrollable region must be reachable by keyboard: give it tabIndex={0}
   and an aria-label. */
.fd-scroll-region {
  max-height: var(--fd-scroll-region-max, min(60vh, 480px));
  overflow-y: auto;
  overflow-x: hidden;
}
/* .fd-list-plain — a ul/ol with no bullets, margin or padding. */
.fd-list-plain {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* ============ Custom scrollbar (utility) ============ */
/* .fd-scrollbar — the one on-brand thin scrollbar treatment, applicable to any
   scrollable container (vertical or horizontal). Named distinctly from the
   unrelated, pre-existing .fd-scroll (the app SHELL's own main scrollable
   region, styles/components.css's "Misc layout helpers" section — flex:1 +
   padding, nothing to do with scrollbar appearance) to avoid colliding with
   it. Originally a one-off on .fd-filestrip; generalized so every scrollable
   list/panel in the kit (e.g. VirtualList) renders the same custom thumb
   instead of the browser default. Firefox via scrollbar-width/scrollbar-color,
   everything else via the ::-webkit-scrollbar pseudo-elements; both read the
   same border tokens so light/dark theming (see tokens.css's
   [data-theme="dark"] overrides of --border-strong) is automatic. */
.fd-scrollbar,
.fd-scroll-region {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
.fd-scrollbar::-webkit-scrollbar,
.fd-scroll-region::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.fd-scrollbar::-webkit-scrollbar-thumb,
.fd-scroll-region::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 99px;
}
.fd-scrollbar::-webkit-scrollbar-thumb:hover,
.fd-scroll-region::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
}
.fd-scrollbar::-webkit-scrollbar-track,
.fd-scroll-region::-webkit-scrollbar-track {
  background: transparent;
}

/* ============ Data list (VirtualList / TransferList / EntityRow) ============ */
/* Each mounted row is absolutely positioned (top:0 + transform:translateY(index *
   itemHeight)) inside VirtualList's totalHeight track, so when an item's index
   changes — a resort, or rows closing a gap after one above them is removed —
   React reuses the same DOM node (keyed by the caller's keyOf) and it slides to
   its new slot instead of snapping. transform, not top, for the animated property:
   compositor-only, no layout thrash even with ~50 rows mounted at once. */
.fd-vlist-row {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  transition: transform var(--dur-base) var(--ease);
}
.fd-vlist-row-content {
  /* Shorter than the row's own fixed slot, not 100% of it — the leftover space
     at the bottom of each slot is what reads as a gap between cards, without
     touching itemHeight itself (that number is load-bearing for the
     scroll/virtualization math in VirtualList.tsx, not just visual spacing).
     The size comes from VirtualList's `rowGap` prop via this custom property,
     since the right gap depends on how tall and heavy the row is; the literal
     fallback only applies to markup that sets neither. */
  height: calc(100% - var(--fd-vlist-gap, 6px));
}
/* A freshly-added row (e.g. the destination side right after a move) gets a brief
   fade/scale-in instead of popping in instantly. Scale/opacity only — never
   `transform: translateY(...)` here, which would fight the row's own positioning
   transform above; this lives on the row's CONTENT wrapper, one level in. */
.fd-vlist-row-enter {
  animation: fd-vlist-row-in var(--dur-base) var(--ease) both;
}
@keyframes fd-vlist-row-in {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .fd-vlist-row {
    transition: none;
  }
  .fd-vlist-row-enter {
    animation: none;
  }
}
/* The "whole result set is being replaced" overlay (VirtualList's `refreshing`
   prop) — a scrim over the full panel with a small centered spinner+label card,
   while the PREVIOUS rows stay mounted and visible underneath. .fd-vlist-wrap is
   the non-scrolling positioning root (a sibling of the scrolling .fd-vlist itself)
   so the scrim always covers the full visible panel regardless of scroll offset. */
.fd-vlist-wrap {
  position: relative;
}
.fd-vlist-refresh-scrim {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--scrim);
  border-radius: var(--r-md);
  z-index: 5;
}
.fd-vlist-refresh-card {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--e-2);
  color: var(--text);
}

/* EntityRow — a real card per row (not flat text): distinct surface from the
   list's own background, hairline border, soft rest elevation, a stronger hover
   elevation as the drag affordance. Same border/radius/shadow vocabulary Card
   itself uses (--r-md here rather than Card's --r-lg — a compact list row reads
   better with the tighter radius; --e-1/--e-2 are the same elevation tokens). */
.fd-erow {
  /* display/align-items/gap/padding live here, not on the component's inline style
     (where they used to be, MP-114 follow-ups) — an inline style always wins over a
     stylesheet rule, which would make it impossible for the narrow-container rule
     below to ever switch this row from a flex row to a grid. gap/padding/border-width
     read the shared --erow-* custom properties (declared once on .fd-tlist above)
     rather than carrying their own literals, which is also what lets
     .fd-tlist-footer's indent stay correct by construction instead of by two
     numbers happening to agree. */
  display: flex;
  align-items: center;
  gap: var(--erow-gap);
  padding: 0 var(--erow-pad-x);
  background: var(--surface-2);
  border: var(--erow-border-w) solid var(--erow-border);
  border-radius: var(--r-md);
  box-shadow: var(--e-1);
  transition:
    box-shadow var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}
.fd-erow:hover {
  border-color: var(--erow-border-hover);
  box-shadow: var(--e-2);
}
/* The row's one non-default state colour: this row exists but can't be used
   (a school with no sellable inventory). Fill, border and title all move, so
   it survives being scanned at a glance down a long list — a border-only
   treatment disappears at 60px row pitch. Tokens are --erow-danger-*, defined
   for both grounds; on dark the fill can't separate from a near-black panel by
   luminance, so the border and the title colour carry it there. */
.fd-erow-danger {
  background: var(--erow-danger-fill);
  border-color: var(--erow-danger-border);
}
.fd-erow-danger:hover {
  border-color: var(--erow-danger-border);
}
.fd-erow-danger .fd-erow-title {
  color: var(--erow-danger-text);
}

/* The row's own two-line body: title line, then the aligned metric strip. The
   strip line only exists when there are metrics or an accessory, so a plain
   name-only row is still exactly one line tall. */
.fd-erow-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
}
.fd-erow-titleline {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
/* The title keeps a floor and the meta is what gives way. Previously the title was
   "flex: 1; min-width: 0" against a "flex: none" meta, which means the title is the
   ONLY thing that can shrink — so in a narrow panel (a two-pane transfer list at ~245px
   per side) a row carrying three figures squeezed the school name to zero width and the
   row lost its identity entirely. A row you cannot name is a row you cannot act on,
   which makes the name the last thing that should go, not the first. */
.fd-erow-title {
  flex: 1 1 auto;
  min-width: 45%;
  font-weight: var(--w-semibold);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-erow-meta {
  flex: 0 1 auto;
  min-width: 0;
  font-size: var(--overline-size);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The title-icon Tooltip trigger (MP-52): icon and title share one hoverable/focusable
   region rather than two, so hovering either opens the same explanation. Carries the same
   flex floor .fd-erow-title has on its own (see the comment above it) so wrapping the
   title in a button never changes how the titleline shares space with `meta`. Reset to a
   plain inline button — no border/background/font change — because visually this must
   read exactly like a title with an icon in front of it, not a control. */
.fd-erow-title-icon {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: 1 1 auto;
  min-width: 45%;
  border: 0;
  background: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.fd-erow-title-icon .fd-erow-title {
  min-width: 0;
}
.fd-erow-title-icon > .ph {
  flex: none;
  font-size: 14px;
  color: var(--text-muted);
}
.fd-erow-title-icon.is-danger > .ph {
  color: var(--danger-solid);
}
.fd-erow-title-icon:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--r-sm);
}
.fd-erow-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
/* Fixed-width cells, not auto-sized ones: the whole point of the strip is that
   the same column lands at the same x on every row (and on the totals line in
   TransferList's footer, which renders this very component with the same
   widths), which auto width cannot give you when the numbers differ in digits. */
.fd-erow-metrics {
  display: flex;
  align-items: center;
  min-width: 0;
  /* When even the figures themselves don't fit (see .fd-erow-cell), the strip loses
     the tail rather than pushing it: without this the overflowing cells paint straight
     through whatever is pinned to the end of the strip. */
  overflow: hidden;
}
/* One column slot. It takes its column's width (--erow-metric-w, set per cell by
   EntityRowMetrics) whenever the strip has room for every column at its width, which keeps
   rows and totals aligned. In a strip too narrow for that — a phone, or a list pane squeezed
   beside another — the slots shrink toward their own figure instead of clipping whole
   columns off the end: a narrow row gives up alignment before it gives up a figure. The
   right padding (inside the width) keeps shrunk figures from running into each other. */
.fd-erow-cell {
  display: flex;
  flex: 0 1 auto;
  width: var(--erow-metric-w);
  min-width: min-content;
  padding-right: 6px;
}
.fd-erow-cell > .fd-tooltip-anchor,
.fd-erow-cell .fd-erow-metric {
  flex: 1 1 auto;
  min-width: 0;
}
.fd-erow-metric {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--overline-size);
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
}
.fd-erow-metric > .ph {
  font-size: 12px;
  color: var(--text-muted);
  flex: none;
}
.fd-erow-metric-value {
  font-weight: var(--w-medium);
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-erow-metric.is-danger > .ph {
  color: var(--danger-text);
}
/* A metric that carries a tooltip is a real button (focusable, tappable, and skipped by
   TransferList's drag arming) that must still look exactly like its plain neighbours —
   so the UA button chrome goes, and a dotted underline on the figure is the one hint
   that there is more to read. */
button.fd-erow-metric {
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--overline-size);
  line-height: inherit;
  text-align: left;
  border-radius: var(--r-xs);
  cursor: help;
}
/* The strip clips its overflow (see .fd-erow-metrics), which would shear off the
   standard outset focus ring — so this one ring is drawn inside the cell. */
button.fd-erow-metric:focus-visible {
  box-shadow: inset 0 0 0 2px var(--blue-500);
}
.fd-erow-metric.is-described .fd-erow-metric-value {
  text-decoration: underline dotted;
  text-decoration-color: var(--text-muted);
  text-underline-offset: 2px;
}
/* The row's action is a real 44px target wherever a finger is the pointer or the screen
   is narrow. The default card is 64px tall, so it fits without growing the row. */
@media (pointer: coarse), (max-width: 768px) {
  .fd-erow-action.fd-btn-icon-sm {
    width: var(--control-h-md);
    height: var(--control-h-md);
    font-size: 18px;
  }
}
.fd-erow-accessory {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
}
/* Size lives here, not on the component's inline style (MP-114 third follow-up,
   same reasoning as .fd-erow's own padding above): .fd-tlist-footer's indent reads
   it back as --erow-grip-size. */
.fd-erow-grip {
  font-size: var(--erow-grip-size);
}
.fd-erow[draggable="true"]:active {
  cursor: grabbing;
}
/* The dragged card itself, mid-drag (see TransferList's pointer-based custom drag
   — native HTML5 drag images are a static snapshot, not a live element, so a
   persistent tilt-and-follow needs real pointer tracking instead). */
.fd-erow-dragging {
  box-shadow: var(--e-2);
  border-color: var(--border-strong);
}
/* The gray placeholder left in a dragged row's original slot — reads as an
   obviously-empty slot, not a still-there-but-faded real row. */
.fd-erow-placeholder {
  height: 100%;
  border-radius: var(--r-md);
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  opacity: 0.6;
}

/* TransferList: two panels side by side, each its own bordered surface — while the
   component itself is wide enough for that. Below 600px of its OWN width (a phone, or a
   half-width card on a desktop page) the panels stack: two panes under ~290px each are too
   narrow for a search field beside its sort button, or for a row's name beside its figures
   and action, so a list you cannot read is traded for one you scroll past. A container
   query, not a media query, because the width that matters is the list's, not the
   screen's. */
.fd-tlist {
  container-type: inline-size;
  /* A row's own geometry, declared ONCE here rather than as literals wherever
     something needs to line up with it (MP-114, third follow-up: the totals
     footer's indent restated these as bare numbers in two places while the real
     values lived as inline styles on EntityRow.tsx's row and its drag grip — a
     change to either drifted the footer's indent silently, which is exactly what
     the second follow-up's 24px misalignment was). `.fd-erow` and `.fd-erow-grip`
     read these instead of carrying their own inline padding/font-size, and
     `.fd-tlist-footer`'s two indents (below) are `calc()` of the same four
     properties — a row and the totals line can only drift apart now if one of
     THESE four values changes, and both readers change with it. Declared on
     `.fd-tlist` (the one ancestor common to both a row and the footer, which are
     otherwise unrelated siblings under `.fd-tlist-side`) rather than on `.fd-erow`
     itself, so the footer — which is never a descendant of any `.fd-erow` — can
     still read them by ordinary custom-property inheritance. */
  --erow-border-w: 1px;
  --erow-pad-x: 12px;
  --erow-grip-size: 14px;
  --erow-gap: 10px;
}
.fd-tlist-panes {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
/* TransferList's per-side slots. The footer is where a running totals line goes;
   it sits on the panel, not on a card, and is separated by a rule rather than a
   gap so it reads as a summary OF the list rather than another row IN it.
   Declared here, BEFORE the narrow @container block below, deliberately: CSS
   cascade order for two rules of equal specificity is source order regardless of
   which one sits inside an at-rule, so a base rule declared AFTER a narrow
   override for the same property would silently win at every width, override
   included — this is what actually happened to this rule's own `padding-left`
   for two follow-ups running (the override was textually correct and had a
   passing stylesheet-contract test, but the base rule used to be declared further
   down the file, after the @container block, and always won the tie). */
.fd-tlist-header {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.fd-tlist-footer {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding-top: 8px;
  /* Indented to the x a row's own body starts at, so a totals strip in here lands
     under the columns it totals rather than a card's width to the left of them: the
     card's border, the row's own padding, the drag grip and its gap — every row in
     a TransferList is a drag source, so it is the same on all of them. Written as
     calc() of the shared --erow-* custom properties (.fd-tlist's own comment)
     rather than as separate literals that merely happened to equal the same
     numbers EntityRow.tsx's row/grip carried inline — a change to any one of those
     four properties now moves this indent with it instead of silently drifting out
     of alignment, which is exactly how this went wrong at the narrow breakpoint
     (see that rule's own comment). */
  padding-left: calc(var(--erow-border-w) + var(--erow-pad-x) + var(--erow-grip-size) + var(--erow-gap));
  border-top: 1px solid var(--border);
  font-size: var(--overline-size);
  color: var(--text-2);
}
@container (max-width: 600px) {
  .fd-tlist-panes {
    flex-direction: column;
    align-items: stretch;
  }
  /* MP-114 (second follow-up). The first follow-up kept every `.fd-erow-cell` at its
     exact fixed `--erow-metric-w` down here (never `width: auto` — see the alignment
     argument in EntityRowMetrics/.fd-erow-metrics's own comments above, which this
     still honours) and let `.fd-erow-metrics` scroll instead of clip when the strip ran
     out of room. That satisfied the alignment contract, but media-planner's
     audience-list-affordances.spec.ts (375px, touch) caught what it traded away: a
     scrollable strip still HIDES figures behind a scroll a touch user has no reason to
     discover, which the spec's `stripClipsNothing` check treats as no better than
     clipping — at phone width every figure has to be actually, fully visible.

     The real room was never in the strip itself — it was in the REST of the row.
     EntityRow is `title (+ titleIcon/meta)` above `metrics (+ accessory)` beside
     `action`, with a drag grip down the side: at desktop width that two-line-plus-rail
     shape is what lets metrics and a school's name and its preference-meter accessory
     and its +/- action all fit on a compact row. At a stacked phone pane that shape is
     the problem — cramming metrics onto the SAME line as an accessory (media-planner's
     TransferList rows carry a ScoreMeter accessory) leaves the strip a fraction of the
     row's own width even though the row has plenty of width overall.

     So below this width the row becomes a two-row GRID instead: name (+ its icon/meta)
     with the accessory and the +/- action all on row one, and the metric strip ALONE
     spanning the full row width on row two — the same width `.fd-tlist-footer`'s totals
     line gets (see below), which is what keeps the two aligned. `.fd-erow-body` and
     `.fd-erow-strip` contribute no box of their own any more here (`display: contents`
     unwraps them, MDN's own documented way to let a grid reach through a wrapper
     without changing the component's DOM/JSX) — every element that actually needs a
     grid position (title line, grip, accessory, metrics, action) becomes a direct
     grid child by that unwrapping alone. `grid-template-areas` uses one row with no
     "strip" cell in it for a plain row that has neither metrics nor an accessory (an
     unfilled `auto` grid row is 0-height), so a name-only row still stays one line
     tall exactly as `.fd-erow-body`'s own base-rule comment describes.

     Even spanning the full row, three columns this wide (media-planner: 96/82/92px)
     can still be tight once the row also loses width to its drag grip and a 44px
     touch-target action button — so `--erow-metric-w` itself also shrinks by a flat,
     modest 15% here, identically for a row's own cells and the totals footer's (both
     read the SAME custom property, so both shrink the same and stay aligned). 15% is a
     deliberate buffer, not a measured minimum: it keeps real figures (media-planner's
     own test data reaches "958,000") comfortably clear of `.fd-erow-metric-value`'s
     own `text-overflow: ellipsis` floor rather than sizing to the exact edge of it. */
  .fd-erow {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      "grip title accessory action"
      "strip strip strip strip";
    /* Row-gap is a new number (there was no vertical gap to preserve — the old
       layout never had two grid rows), but the column-gap is the same --erow-gap
       the wide flex row uses, not a second literal 10px that could drift from it. */
    gap: 4px var(--erow-gap);
  }
  .fd-erow-body,
  .fd-erow-strip {
    display: contents;
  }
  .fd-erow-grip {
    grid-area: grip;
  }
  .fd-erow-titleline {
    grid-area: title;
  }
  .fd-erow-accessory {
    grid-area: accessory;
  }
  .fd-erow-action {
    grid-area: action;
  }
  .fd-erow-cell {
    flex-shrink: 0;
    width: calc(var(--erow-metric-w) * 0.85);
  }
  .fd-erow-metrics {
    /* Row context (.fd-erow is the grid above): claims the whole second grid row.
       Footer context (.fd-tlist-footer is a plain flex row, see below): `grid-area`
       is a no-op there since its parent isn't a grid, and `flex: 1 1 100%` is what
       does the equivalent job — combined with that flex row's own `flex-wrap: wrap`,
       claiming the full line pushes the "Totals · N schools" caption after it onto
       a second line, the same shape the row now has. Only one of the two rules ever
       actually applies in a given parent, so both can live on this one selector. */
    grid-area: strip;
    flex: 1 1 100%;
    /* Belt-and-suspenders, not the primary mechanism any more: if some OTHER
       consumer's columns still don't fit even the whole row's width after the 15%
       reduction above, this scrolls that overflow rather than clipping it (the same
       "wide content gets its own scroll container" rule DataTable's `.fd-table-wrap`
       follows, and the layout auditor already treats an `overflow: auto` ancestor as
       fine by design) — never reached by media-planner's own audience columns, which
       the full-width row and the 15% reduction together already fit. */
    overflow-x: auto;
    overflow-y: hidden;
  }
  .fd-tlist-footer {
    flex-wrap: wrap;
    /* The wide-width padding-left (see the base rule's own comment) indents the
       totals strip to where a row's metric strip used to start: AFTER the card border,
       the row's own padding, the drag grip and its gap. Down here the row's strip no
       longer starts there — it's `.fd-erow`'s own full-width second grid row (see
       `.fd-erow`'s own comment above), which starts at the row's own left padding
       edge, before the grip rather than after it. audience-builder.spec.ts caught the
       mismatch this left behind: a row's strip and the totals strip 24px apart at the
       SAME breakpoint that made the grid switch active in the first place (any
       TransferList pane under 600px, which an ordinary 1280px desktop window reaches
       easily — see that rule's own comment). The totals strip needs the SAME new
       origin: just the card's border and the row's own padding, with the grip/gap
       terms dropped since they no longer apply to either strip — both terms of the
       SAME --erow-* properties (.fd-tlist's own comment) the base rule below uses,
       not separately-guessed numbers, so the two can't drift apart again. */
    padding-left: calc(var(--erow-border-w) + var(--erow-pad-x));
  }
}
.fd-tlist-side {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  position: relative;
}
.fd-tlist-side.is-drop-target {
  border-color: var(--brand);
}
/* TransferList's full-panel drop overlay — extends the existing subtle
   dragOverSide border-color change into real visual weight: a dashed blue
   border and a translucent brand scrim across the WHOLE target side, with
   a centered card (not bare text) telling the user what dropping here does —
   the same "small card floating over the list" language the refresh overlay
   already uses, so the two read as one consistent pattern. */
.fd-tlist-drop-overlay {
  position: absolute;
  inset: 6px;
  display: grid;
  place-items: center;
  border: 2px dashed var(--brand);
  border-radius: var(--r-md);
  background: var(--surface-brand);
  opacity: 0.92;
  z-index: 6;
  pointer-events: none;
  text-align: center;
  padding: 16px;
}
.fd-tlist-drop-card {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: var(--surface);
  border: 1px solid var(--border-brand);
  border-radius: var(--r-md);
  box-shadow: var(--e-2);
  color: var(--brand);
}

/* --- ScoreMeter — a small categorical 0-100 bar, optionally a trigger ------ */
.fd-scoremeter {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.fd-scoremeter-rail {
  display: block;
  flex: none;
}
.fd-scoremeter-value {
  font-size: var(--overline-size);
  font-weight: var(--w-semibold);
  color: var(--text-2);
  min-width: 2ch;
  text-align: right;
}
/* The trigger is a real button (keyboard-operable, and skipped by TransferList's
   drag arming, which ignores any pointerdown inside a button) — so it has to be
   stripped of the browser's own button chrome and given this kit's own. */
.fd-scoremeter-button {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  padding: 2px 5px;
  margin: -2px -5px;
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.fd-scoremeter-button:hover {
  background: var(--surface-3);
  border-color: var(--border);
}
.fd-scoremeter-button.is-open {
  background: var(--surface-brand);
  border-color: var(--border-brand);
}

/* --- importance scale: the tag, and the score breakdown it appears in ------ */
.fd-imp-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
  padding: 2px 7px;
  border: 1px solid transparent;
  border-radius: var(--r-full);
  font-size: var(--overline-size);
  line-height: var(--overline-lh);
  font-weight: var(--w-semibold);
  white-space: nowrap;
}
.fd-imp-tag > .ph {
  font-size: 12px;
}
.fd-imp-tag.is-md {
  padding: 4px 10px;
  font-size: var(--label-size);
}
.fd-imp-tag.is-md > .ph {
  font-size: 14px;
}
/* Disabled paints from the same trio `.fd-btn[disabled]` uses (--surface-3/--border/
   --text-disabled) instead of this level's own fill/edge/text — never `opacity`, per the
   kit's 0.41 rule. React sets the colours inline (they're computed from the level), this
   rule only owns the cursor. */
.fd-imp-tag.is-disabled {
  cursor: not-allowed;
}
.fd-prefbreak {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.fd-prefbreak-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.fd-prefbreak-score {
  font-size: var(--h4-size);
  font-weight: var(--w-bold);
  color: var(--text);
}
.fd-prefbreak-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.fd-prefbreak-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
}
/* A criterion that earned nothing is dimmed rather than hidden — the reason a
   score is low is exactly the rows that contributed zero. */
.fd-prefbreak-item.is-unmet {
  opacity: 0.55;
}
.fd-prefbreak-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.fd-prefbreak-label {
  font-size: var(--body-sm-size);
  line-height: var(--body-sm-lh);
  color: var(--text);
}
.fd-prefbreak-note {
  font-size: var(--overline-size);
  color: var(--text-muted);
}
.fd-prefbreak-val {
  flex: none;
  font-size: var(--body-sm-size);
  color: var(--text-2);
}
.fd-prefbreak-sep {
  color: var(--text-muted);
  padding: 0 2px;
}

/* uniform staging strip — one row, scrolls sideways */
.fd-filestrip {
  display: flex;
  gap: 8px;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 1px 1px 3px;
}
.fd-cell {
  position: relative;
  flex: none;
  width: var(--fd-cell, 68px);
  height: var(--fd-cell, 68px);
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface-2);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease);
}
.fd-cell:hover {
  border-color: var(--border-strong);
}
.fd-cell.is-error {
  border-color: var(--danger-border);
  background: var(--danger-fill);
}
.fd-cell.is-uploading .fd-cell-main {
  opacity: 0.75;
}
.fd-cell-main {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
}
.fd-cell-main:disabled {
  cursor: default;
}
.fd-cell-main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.fd-cell-doc {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  width: 100%;
  height: 100%;
  padding: 4px;
}
.fd-cell-doc > i {
  font-size: 17px;
  color: var(--text-2);
}
.fd-cell-name {
  font-size: 10.5px;
  font-weight: var(--w-semibold);
  color: var(--text);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.2;
}
.fd-cell-size {
  font-size: 9.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.fd-cell-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  font-size: 15px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
.fd-cell-err {
  position: absolute;
  left: 4px;
  bottom: 4px;
  color: var(--danger-solid);
  font-size: 12px;
  line-height: 1;
  background: var(--surface);
  border-radius: 99px;
  padding: 1px;
}
.fd-cell-x {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 17px;
  height: 17px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-full);
  background: rgba(11, 13, 17, 0.66);
  color: #fff;
  font-size: 9px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.fd-cell-x.is-retry {
  right: 23px;
  background: rgba(11, 13, 17, 0.5);
}
.fd-cell:hover .fd-cell-x,
.fd-cell-x:focus-visible {
  opacity: 1;
}
.fd-cell.is-error .fd-cell-x {
  opacity: 1;
}

/* --- dropzone + attach --------------------------------------------------- */
.fd-dropzone {
  position: relative;
}
.fd-dropzone-veil {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-items: center;
  border-radius: var(--chat-radius);
  background: color-mix(in oklab, var(--surface-brand) 82%, transparent);
  border: 2px dashed var(--brand);
  animation: fd-pop var(--dur-fast) var(--ease-out) both;
}
.fd-dropzone-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: var(--text-on-surface-brand);
}
.fd-dropzone-card i {
  font-size: 22px;
}
.fd-dropzone-label {
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
}
.fd-dropzone-hint {
  font-size: 11.5px;
  opacity: 0.8;
}
.fd-attachbtn {
  width: 32px;
  height: 32px;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  background: none;
  color: var(--text-2);
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: 17px;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.fd-attachbtn:hover {
  background: var(--surface-2);
  color: var(--text);
  border-color: var(--border);
}
.fd-attachbtn:disabled {
  color: var(--text-disabled);
  cursor: not-allowed;
}
.fd-attachbtn.is-live {
  color: var(--danger-solid);
  border-color: var(--danger-border);
  background: var(--danger-fill);
}

/* --- steps -------------------------------------------------------------- */
.fd-steps {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
  margin: 2px 0 8px;
}
.fd-steps-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--body-sm-size);
  color: var(--text-2);
  cursor: pointer;
  text-align: left;
  transition: background var(--dur-fast) var(--ease);
}
.fd-steps-head:hover {
  background: var(--surface-2);
}
.fd-steps-head > i:first-child {
  color: var(--ok-solid);
  font-size: 15px;
  flex: none;
}
.fd-steps.is-active .fd-steps-head > i:first-child {
  color: var(--text-muted);
}
.fd-steps-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--w-medium);
  color: var(--text);
}
.fd-steps-count {
  font-size: 11.5px;
  color: var(--text-muted);
  flex: none;
}
.fd-steps-failed {
  color: var(--danger-text);
}
.fd-steps-caret {
  font-size: 11px;
  color: var(--text-muted);
  flex: none;
}
.fd-steps-spin {
  display: inline-block;
  width: 12px;
  height: 12px;
  flex: none;
  border-radius: var(--r-full);
  border: 1.6px solid var(--brand);
  border-right-color: transparent;
  animation: fd-spin 620ms linear infinite;
}
.fd-steps-list {
  list-style: none;
  margin: 0;
  padding: 2px 0 5px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.fd-step {
  padding: 0 10px;
}
.fd-step-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 26px;
}
.fd-step-icon {
  flex: none;
  width: 16px;
  display: grid;
  place-items: center;
  color: var(--text-muted);
  font-size: 13px;
}
.fd-step.is-error .fd-step-icon {
  color: var(--danger-solid);
}
.fd-step-label {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: none;
  padding: 3px 0;
  font: inherit;
  font-size: 12.5px;
  color: var(--text-2);
  cursor: pointer;
  text-align: left;
}
.fd-step-label span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fd-step-label i {
  font-size: 10px;
  color: var(--text-disabled);
}
.fd-step-label:hover {
  color: var(--text);
}
.fd-step-label.is-static {
  cursor: default;
}
.fd-step-badge.is-error {
  font-size: 10.5px;
  font-weight: var(--w-bold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--danger-text);
  background: var(--danger-fill);
  border-radius: var(--r-full);
  padding: 1px 6px;
}
.fd-step-dur {
  font-size: 11px;
  color: var(--text-disabled);
  flex: none;
}
.fd-step-detail {
  margin: 2px 0 8px 24px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 220px;
  overflow: auto;
}
.fd-steps.is-dense .fd-step-row {
  min-height: 24px;
}

/* --- menus (extends .fd-pop / .fd-opt) ----------------------------------- */
.fd-pop-padded {
  padding: var(--s-16);
}
.fd-menu {
  outline: none;
}
/* A Menu is one shrinkable frame: header and footer pinned, items scrolling between. */
.fd-menu-frame {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.fd-menu-header,
.fd-menu-footer {
  flex: none;
}
.fd-menu-item {
  align-items: center;
}
.fd-menu-icon {
  flex: none;
  width: 18px;
  display: grid;
  place-items: center;
  color: var(--text-2);
  font-size: 15px;
}
.fd-menu-text {
  flex: 1;
  min-width: 0;
}
.fd-menu-shortcut {
  flex: none;
  color: var(--text-disabled);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}
.fd-menu-more {
  flex: none;
  color: var(--text-muted);
  font-size: 11px;
}
.fd-menu-row {
  position: relative;
  display: flex;
  align-items: stretch;
}
.fd-menu-row > .fd-menu-item {
  flex: 1;
  min-width: 0;
  padding-right: 36px;
}
.fd-menu-row-act {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 13px;
  opacity: 0;
  transition:
    opacity var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fd-menu-row:hover .fd-menu-row-act,
.fd-menu-row-act:focus-visible {
  opacity: 1;
}
.fd-menu-row-act:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fd-menu-row-act.is-danger:hover {
  background: var(--danger-fill);
  color: var(--danger-text);
}
.fd-menu-row-act:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fd-menu-sep {
  height: 1px;
  background: var(--border);
  margin: 5px 4px;
}
.fd-menu-custom {
  padding: 2px 4px;
}
.fd-menubtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 8px;
  border: 1px solid transparent;
  background: none;
  color: var(--text-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: var(--w-medium);
  border-radius: var(--r-md);
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.fd-menubtn:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fd-menubtn.is-open {
  background: var(--surface-2);
  color: var(--text);
  border-color: var(--border);
}
.fd-menubtn.is-md {
  height: 34px;
  font-size: var(--body-sm-size);
}
.fd-menubtn-ghost {
  width: 32px;
  justify-content: center;
  padding: 0;
  font-size: 16px;
}
.fd-menubtn-caret {
  font-size: 10px;
  opacity: 0.75;
}
.fd-menubtn:disabled {
  color: var(--text-disabled);
  cursor: not-allowed;
}

/* --- rich markdown composer --------------------------------------------- */
.fd-rme-wrap {
  position: relative;
  font-size: var(--body-size);
  line-height: 1.55;
  min-width: 0;
}
.fd-rme {
  outline: none;
  overflow-y: auto;
  overflow-x: hidden;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--chat-text);
  caret-color: var(--chat-accent);
  tab-size: 2;
}
.fd-rme-wrap.is-disabled {
  opacity: 0.6;
}
.fd-rme-line {
  min-height: 1.55em;
}
.fd-rme-line.is-h1 {
  font-size: 1.22em;
  font-weight: var(--w-bold);
  line-height: 1.35;
}
.fd-rme-line.is-h2 {
  font-size: 1.14em;
  font-weight: var(--w-bold);
  line-height: 1.38;
}
.fd-rme-line.is-h3 {
  font-size: 1.06em;
  font-weight: var(--w-semibold);
}
.fd-rme-line.is-h4,
.fd-rme-line.is-h5,
.fd-rme-line.is-h6 {
  font-weight: var(--w-semibold);
}
.fd-rme-line.is-quote {
  border-left: 2px solid var(--border-strong);
  padding-left: 8px;
  color: var(--chat-text-2);
  font-style: italic;
}
.fd-rme-line.is-code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--chat-code-bg);
  border-left: 2px solid var(--border);
  padding-left: 8px;
}
.fd-rme-line.is-table {
  font-family: var(--font-mono);
  font-size: 0.9em;
  color: var(--chat-text-2);
}
.fd-rme-line.is-rule {
  color: var(--text-disabled);
}
.fd-rme-ph {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  color: var(--text-disabled);
}
.rme-mk {
  opacity: 0.36;
}
.rme-b {
  font-weight: var(--w-bold);
}
.rme-i {
  font-style: italic;
}
.rme-s {
  text-decoration: line-through;
  opacity: 0.68;
}
.rme-c {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--surface-2);
  border-radius: var(--r-xs);
  padding: 0 2px;
}
.rme-lk {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.rme-bullet {
  color: var(--brand);
  font-weight: var(--w-bold);
}
.rme-task {
  color: var(--brand);
}
.rme-task.is-done {
  opacity: 0.6;
}
.rme-lang {
  color: var(--text-muted);
}

/* ==========================================================================
   2 · the chat panel
   ========================================================================== */

.fdc-panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  position: relative;
  background: var(--chat-surface);
  color: var(--chat-text);
  font-family: var(--font-sans);
  font-size: var(--body-size);
  line-height: var(--body-lh);
  isolation: isolate;
}
.fdc-panel * {
  box-sizing: border-box;
}

/* surfaces */
/* DS-26: fills the panel it is put in; AppShell's side panel (.fd-sidepanel) owns the width and the edge. */
.fdc-panel.is-sidebar {
  height: 100%;
  width: 100%;
}
.fdc-panel.is-inline {
  border: 1px solid var(--chat-border);
  border-radius: var(--chat-radius);
  box-shadow: var(--e-1);
  overflow: hidden;
  height: 100%;
}
.fdc-panel.is-page {
  height: 100%;
  background: var(--page);
}
.fdc-panel.is-page .fdc-log,
.fdc-panel.is-page .fdc-composer-inner {
  max-width: 768px;
  margin: 0 auto;
}
.fdc-panel.is-page .fdc-composer {
  max-width: 768px;
  margin: 0 auto;
  width: 100%;
}
.fdc-panel.is-modal {
  height: min(76vh, 720px);
  border-radius: var(--chat-radius);
  box-shadow: var(--e-3);
  border: 1px solid var(--chat-border);
  overflow: hidden;
  width: min(680px, 92vw);
}
.fdc-panel.is-sheet {
  height: 100%;
  width: 100%;
}

/* header — the same height as the app topbar (--topbar-h), the one header size across the shell */
.fdc-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px 0 var(--chat-pad-x);
  height: var(--topbar-h);
  flex: none;
  border-bottom: 1px solid var(--chat-border);
  background: var(--chat-surface);
}
.fdc-head-mark {
  width: 26px;
  height: 26px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--surface-brand);
  color: var(--brand);
  font-size: 15px;
}
.fdc-head-titles {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.fdc-head-title {
  font-size: var(--h4-size);
  font-weight: var(--w-semibold);
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fdc-head-sub {
  font-size: 11.5px;
  color: var(--chat-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fdc-head-acts {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
}
.fdc-iconbtn {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: var(--text-2);
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: 16px;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fdc-iconbtn:hover {
  background: var(--surface-2);
  color: var(--text);
}

/* transcript */
.fdc-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  overscroll-behavior: contain;
}
.fdc-log {
  display: flex;
  flex-direction: column;
  gap: var(--chat-gap-turn);
  padding: 20px var(--chat-pad-x) 14px;
  min-height: 100%;
}
.fdc-day {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--chat-muted);
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
}
.fdc-day::before,
.fdc-day::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--chat-border);
}

.fdc-turn {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
  animation: fd-rise var(--dur-slow) var(--ease-out) both;
}
.fdc-turn-head {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}
.fdc-turn.is-user .fdc-turn-head {
  justify-content: flex-end;
}
.fdc-avatar {
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  background: var(--surface-brand);
  color: var(--brand);
  font-size: 12px;
  overflow: hidden;
}
.fdc-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fdc-avatar.is-user {
  background: var(--surface-3);
  color: var(--text-2);
}
.fdc-avatar-txt {
  font-size: 10.5px;
  font-weight: var(--w-bold);
}
.fdc-who {
  font-size: 12.5px;
  font-weight: var(--w-semibold);
  color: var(--chat-text);
}
.fdc-when {
  font-size: 11.5px;
  color: var(--chat-muted);
}
.fdc-turn-model {
  font-size: 11px;
  color: var(--chat-muted);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.fdc-turn.is-user .fdc-turn-model {
  margin-left: 0;
}
.fdc-turn-body {
  display: flex;
  flex-direction: column;
  gap: var(--chat-gap-run);
  min-width: 0;
}
.fdc-turn.is-user .fdc-turn-body {
  align-items: flex-end;
}
.fdc-msg {
  min-width: 0;
  max-width: 100%;
}
.fdc-msg.is-pending {
  opacity: 0.62;
}
.fdc-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

/* asymmetric roles: the user gets a bubble, the assistant runs full-bleed —
   symmetric bubbles read as a peer messenger, and boxing markdown, tables and
   code fights the content at sidebar widths. */
.fdc-turn.is-user .fdc-text {
  background: var(--chat-user-fill);
  border: 1px solid var(--chat-user-border);
  color: var(--chat-user-text);
  border-radius: var(--r-lg);
  padding: 9px 13px;
  max-width: min(88%, 52ch);
  margin-left: auto;
}
.fdc-turn.is-user .fdc-body {
  align-items: flex-end;
}
.fdc-text {
  min-width: 0;
  max-width: var(--chat-max-read);
}
.fdc-plain {
  white-space: pre-wrap;
  word-break: break-word;
}
.fdc-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--brand);
  animation: fdc-blink 1s steps(2, start) infinite;
}
@keyframes fdc-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

.fdc-dots {
  display: inline-flex;
  gap: 3px;
  align-items: center;
}
.fdc-dots span {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--brand);
  animation: fdc-bounce 1.1s var(--ease) infinite;
}
.fdc-dots span:nth-child(2) {
  animation-delay: 140ms;
}
.fdc-dots span:nth-child(3) {
  animation-delay: 280ms;
}
@keyframes fdc-bounce {
  0%,
  80%,
  100% {
    opacity: 0.3;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-2px);
  }
}

.fdc-working {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--body-sm-size);
  color: var(--chat-text-2);
}
.fdc-working-job {
  color: var(--chat-muted);
}
.fdc-stopped {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--body-sm-size);
  color: var(--chat-muted);
}
.fdc-error {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-radius: var(--r-md);
  background: var(--danger-fill);
  border: 1px solid var(--danger-border);
  border-left: 3px solid var(--danger-solid);
  color: var(--danger-text);
  font-size: var(--body-sm-size);
}
.fdc-error i {
  font-size: 15px;
  flex: none;
}
.fdc-error-text {
  flex: 1;
  min-width: 0;
  word-break: break-word;
  font-family: var(--font-mono);
  font-size: 12px;
}
.fdc-error-retry {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  border: 1px solid var(--danger-border);
  background: var(--surface);
  color: var(--danger-text);
  font: inherit;
  font-size: 12px;
  font-weight: var(--w-semibold);
  padding: 4px 9px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.fdc-error-retry:hover {
  background: var(--danger-fill);
}

/* thinking */
.fdc-think {
  border-left: 2px solid var(--border-strong);
  padding-left: 12px;
}
.fdc-think-head {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: none;
  padding: 2px 0;
  font: inherit;
  font-size: var(--body-sm-size);
  color: var(--chat-muted);
  cursor: pointer;
}
.fdc-think-head:hover {
  color: var(--chat-text-2);
}
.fdc-think-head > i:first-child {
  font-size: 14px;
}
.fdc-think-body {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--chat-text-2);
  white-space: pre-wrap;
  font-style: italic;
  max-height: 280px;
  overflow: auto;
}

/* packets */
.fdc-packet {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
  box-shadow: var(--e-1);
}
.fdc-packet.is-invalid {
  border-color: var(--danger-border);
}
.fdc-packet-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.fdc-packet-head > i:first-child {
  color: var(--brand);
  font-size: 16px;
}
.fdc-packet-title {
  flex: 1;
  min-width: 0;
  font-size: var(--h4-size);
  font-weight: var(--w-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fdc-packet-badge {
  font-size: 10.5px;
  font-weight: var(--w-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--warn-text);
  background: var(--warn-fill);
  border: 1px solid var(--warn-border);
  border-radius: var(--r-full);
  padding: 1px 7px;
}
.fdc-packet-badge.is-danger {
  color: var(--danger-text);
  background: var(--danger-fill);
  border-color: var(--danger-border);
}
.fdc-packet-body {
  padding: 12px 14px;
}
.fdc-packet-body > .fd-code:first-child {
  margin-top: 0;
}
.fdc-packet-body > .fd-code:last-child {
  margin-bottom: 0;
}
.fdc-packet-alert {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  padding: 12px 14px;
  background: var(--danger-fill);
  color: var(--danger-text);
  font-size: var(--body-sm-size);
}
.fdc-packet-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.fdc-packet-decision {
  flex-wrap: wrap;
  justify-content: flex-end;
}
.fdc-packet-decision-msg {
  padding: 10px 14px;
  border-top: 1px solid var(--border);
}
.fdc-packet-note {
  font-size: 11.5px;
  color: var(--chat-muted);
}

/* citations */
.fdc-cites {
  border-top: 1px solid var(--border);
  padding-top: 6px;
}
.fdc-cites-head {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: none;
  padding: 2px 0;
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  color: var(--chat-text-2);
  cursor: pointer;
}
.fdc-cites-head:hover {
  color: var(--chat-text);
}
.fdc-cites-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.fdc-cites-list li {
  display: flex;
  gap: 8px;
  align-items: baseline;
  font-size: var(--body-sm-size);
}
.fdc-cite-n {
  flex: none;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  border-radius: var(--r-full);
  background: var(--surface-brand);
  color: var(--brand);
  font-size: 10.5px;
  font-weight: var(--w-bold);
}
.fdc-cite-detail {
  color: var(--chat-muted);
  font-size: 12px;
}

/* run actions */
.fdc-actions {
  display: flex;
  align-items: center;
  gap: 1px;
  margin-top: 1px;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.fdc-turn:hover .fdc-actions,
.fdc-turn:focus-within .fdc-actions {
  opacity: 1;
}
.fdc-turn.is-user .fdc-actions {
  justify-content: flex-end;
}
.fdc-act {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 7px;
  border: 0;
  background: none;
  color: var(--chat-muted);
  font: inherit;
  font-size: 12px;
  font-weight: var(--w-medium);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fdc-act:hover {
  background: var(--surface-2);
  color: var(--chat-text);
}
.fdc-act.is-on {
  color: var(--brand);
  background: var(--surface-brand);
}
.fdc-act.is-done {
  color: var(--ok-solid);
}
.fdc-act i {
  font-size: 14px;
}
.fdc-act-label {
  display: none;
}
.fdc-act:hover .fdc-act-label,
.fdc-act.is-done .fdc-act-label {
  display: inline;
}

/* empty + dead + skeleton + pill */
.fdc-empty,
.fdc-dead {
  margin: auto 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 0 20px;
}
.fdc-empty-icon,
.fdc-dead-icon {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  background: var(--surface-brand);
  color: var(--brand);
  font-size: 20px;
  margin-bottom: 2px;
}
.fdc-dead-icon {
  background: var(--warn-fill);
  color: var(--warn-solid);
}
.fdc-empty-title,
.fdc-dead-title {
  font-size: var(--h3-size);
  font-weight: var(--w-semibold);
  letter-spacing: -0.01em;
}
.fdc-empty-body,
.fdc-dead-body {
  font-size: var(--body-sm-size);
  color: var(--chat-text-2);
  max-width: 46ch;
  text-wrap: pretty;
}
.fdc-suggest {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  margin-top: 10px;
}
.fdc-suggest-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  font: inherit;
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.fdc-suggest-item:hover {
  background: var(--surface-2);
  border-color: var(--border-strong);
}
.fdc-suggest-item > i:first-child {
  color: var(--brand);
  font-size: 16px;
  flex: none;
}
.fdc-suggest-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.fdc-suggest-label {
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  color: var(--chat-text);
}
.fdc-suggest-desc {
  font-size: 11.5px;
  color: var(--chat-muted);
}
.fdc-suggest-go {
  color: var(--text-disabled);
  font-size: 12px;
  flex: none;
}
.fdc-suggest-item:hover .fdc-suggest-go {
  color: var(--brand);
}
.fdc-skel {
  display: flex;
  flex-direction: column;
  gap: var(--chat-gap-turn);
}
.fdc-skel-turn {
  display: flex;
  gap: 9px;
}
.fdc-skel-lines {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-top: 3px;
}
.fdc-pill {
  position: sticky;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-full);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--e-2);
  color: var(--chat-text);
  font: inherit;
  font-size: 12.5px;
  font-weight: var(--w-semibold);
  cursor: pointer;
  animation: fd-rise var(--dur-base) var(--ease-out) both;
}
.fdc-pill:hover {
  background: var(--surface-2);
}

/* composer */
.fdc-composer {
  flex: none;
  padding: 8px var(--chat-pad-x) var(--chat-pad-y);
  display: flex;
  flex-direction: column;
  gap: 7px;
  background: var(--chat-surface);
  border-top: 1px solid var(--chat-border);
}
.fdc-composer.is-disabled {
  opacity: 0.72;
}
.fdc-queue {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fdc-queue-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 9px;
  border-radius: var(--r-sm);
  background: var(--warn-fill);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
  font-size: 12.5px;
}
.fdc-queue-row > i:first-child {
  font-size: 14px;
  flex: none;
}
.fdc-queue-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fdc-queue-x {
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: inherit;
  border-radius: var(--r-xs);
  cursor: pointer;
  font-size: 11px;
  opacity: 0.7;
}
.fdc-queue-x:hover {
  opacity: 1;
  background: rgba(0, 0, 0, 0.06);
}

.fdc-field {
  border: 1px solid var(--border);
  border-radius: var(--chat-radius);
  background: var(--chat-surface);
  transition:
    border-color var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}
.fdc-field:hover {
  border-color: var(--border-strong);
}
.fdc-field:focus-within {
  border-color: var(--border-strong);
}
.fdc-field-inner {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 10px 8px 12px;
}
.fdc-staged {
  margin-bottom: 2px;
}
.fdc-staged .fd-filegrid {
  margin-top: 0;
}
.fdc-tools {
  display: flex;
  align-items: center;
  gap: 4px;
}
.fdc-tools-gap {
  flex: 1;
}
.fdc-count {
  font-size: 11.5px;
  color: var(--chat-muted);
  padding-right: 4px;
}
.fdc-count.is-hot {
  color: var(--danger-text);
  font-weight: var(--w-semibold);
}
.fdc-send {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--grad-primary);
  color: #fff;
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  cursor: pointer;
  box-shadow: var(--e-brand);
  transition:
    background var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}
.fdc-send:hover:not(:disabled) {
  background: var(--grad-primary-hover);
}
.fdc-send:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: none;
}
.fdc-send:disabled {
  background: var(--surface-3);
  color: var(--text-disabled);
  box-shadow: none;
  cursor: not-allowed;
}
.fdc-send i {
  font-size: 14px;
}
.fdc-stop {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-semibold);
  cursor: pointer;
}
.fdc-stop:hover {
  background: var(--surface-2);
  border-color: var(--danger-border);
  color: var(--danger-text);
}
.fdc-stop i {
  font-size: 15px;
}
.fdc-notice {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--danger-text);
}
.fdc-hint {
  font-size: 11.5px;
  color: var(--chat-muted);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* session bar */
.fdc-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.fdc-bar-btn {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  border: 0;
  background: none;
  padding: 3px 6px;
  border-radius: var(--r-sm);
  color: var(--chat-muted);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
  text-align: left;
  font-variant-numeric: tabular-nums lining-nums;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}
.fdc-bar-btn:hover:not(:disabled) {
  background: var(--surface-2);
  color: var(--chat-text-2);
}
.fdc-bar-btn:disabled {
  cursor: default;
}
.fdc-bar-mini {
  width: 46px;
  flex: none;
}
.fdc-bar-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fdc-bar-caret {
  font-size: 10px;
  flex: none;
  opacity: 0.7;
}
.fdc-usage {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}
.fdc-usage-sec {
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.fdc-usage-h {
  margin: 0;
  font-size: var(--overline-size);
  letter-spacing: var(--overline-track);
  text-transform: uppercase;
  font-weight: var(--w-bold);
  color: var(--chat-muted);
}
.fdc-usage-rows {
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.fdc-usage-stats {
  border-top: 1px solid var(--border);
  padding-top: 11px;
  gap: 6px;
}
.fdc-usage-stats > div {
  display: flex;
  justify-content: space-between;
  font-size: 12.5px;
  color: var(--chat-text-2);
}
.fdc-usage-stats b {
  color: var(--chat-text);
  font-weight: var(--w-semibold);
}
.fdc-usage-clear {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: none;
  color: var(--danger-text);
  font: inherit;
  font-size: var(--body-sm-size);
  font-weight: var(--w-medium);
  padding: 4px 6px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.fdc-usage-clear:hover {
  background: var(--danger-fill);
}
.fdc-switchrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 10px;
  font-size: var(--body-sm-size);
  color: var(--chat-text);
  cursor: pointer;
  border-radius: var(--r-sm);
}
.fdc-switchrow:hover {
  background: var(--surface-2);
}

/* narrow panel */
.fdc-panel.is-narrow {
  --chat-pad-x: 14px;
  --chat-gap-turn: 22px;
}
.fdc-panel.is-narrow .fdc-send-label {
  display: none;
}
.fdc-panel.is-narrow .fdc-send {
  padding: 0 10px;
}
.fdc-panel.is-narrow .fdc-text {
  font-size: 14.5px;
}

@media (max-width: 768px) {
  .fdc-log {
    padding-left: 14px;
    padding-right: 14px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .fdc-turn,
  .fdc-pill,
  .fd-dropzone-veil {
    animation: none;
  }
  .fdc-caret {
    animation: none;
  }
  .fdc-dots span {
    animation: none;
    opacity: 0.6;
  }
}

/* ============ Build mode (live / test) ============ */
.fd-mode-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 8px;
  cursor: pointer;
  background: none;
  border: 1px solid transparent;
  color: var(--text-muted);
  transition:
    color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}
.fd-mode-btn:hover {
  color: var(--text);
  background: var(--surface-2);
}
.fd-mode-btn.is-open {
  background: var(--surface-brand);
  border-color: var(--info-border);
  color: var(--text-on-surface-brand);
}
.fd-mode-btn.is-test {
  color: var(--warn-solid);
}
.fd-mode-btn.is-test.is-open {
  background: var(--warn-fill);
  border-color: var(--warn-border);
  color: var(--warn-text);
}
.fd-mode-btn:focus-visible {
  box-shadow: var(--focus-ring);
}
.fd-mode-count {
  position: absolute;
  top: -3px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 99px;
  background: var(--chart-7);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--surface);
  animation: fd-badge-pop 260ms var(--ease) both;
}
/* The mode panel is a Popover surface (.fd-pop) opened through InlinePanelSurface, which owns its
   position, width and z-index. This is only its own look. */
.fd-mode-pop {
  border-radius: 12px;
  box-shadow: 0 20px 52px rgba(11, 13, 17, 0.2);
}
.fd-mode-choice {
  display: grid;
  gap: 6px;
  padding: 10px;
}
.fd-mode-opt {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 10px 11px;
  border-radius: 9px;
  cursor: pointer;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font: inherit;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.fd-mode-opt:hover {
  background: var(--surface-2);
}
.fd-mode-opt.is-on {
  background: var(--surface-brand);
  border-color: var(--info-border);
}
.fd-mode-opt:focus-visible {
  box-shadow: var(--focus-ring);
}
.fd-mode-opt > i {
  font-size: 17px;
  flex: none;
  color: var(--text-muted);
}
.fd-mode-opt.is-on > i {
  color: var(--text-on-surface-brand);
}
.fd-mode-opt-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
  min-width: 0;
}
.fd-mode-opt-title {
  font-size: var(--body-sm-size);
  font-weight: 700;
}
.fd-mode-opt-desc {
  font-size: 12px;
  color: var(--text-2);
}
.fd-testbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 7px 16px;
  background: repeating-linear-gradient(
    135deg,
    var(--warn-fill),
    var(--warn-fill) 10px,
    color-mix(in srgb, var(--warn-fill) 78%, var(--surface)) 10px,
    color-mix(in srgb, var(--warn-fill) 78%, var(--surface)) 20px
  );
  border-bottom: 1px solid var(--warn-border);
  flex: none;
}
.fd-testbar-detail {
  font-size: var(--body-sm-size);
  color: var(--warn-text);
  flex: 1;
  min-width: 180px;
}

/* ============ foundations/skeleton.css (vendored verbatim) ============
   Loading is a first-class state in this system.
   Three tiers, and only three:
   1. fd-skel-*   — the shell before first data (structure is already correct)
   2. fd-stale    — data on screen while a refresh is in flight (visible, dimmed, inert)
   3. fd-progress — a determinate or indeterminate bar for a known long job
   Never blank a region that already has data. Never spin over a whole page. */
@keyframes fd-sheen{0%{background-position:-160% 0}100%{background-position:260% 0}}
@keyframes fd-pulse{0%,100%{opacity:1}50%{opacity:.55}}
@keyframes fd-spin{to{transform:rotate(360deg)}}
@keyframes fd-bar{0%{transform:translateX(-100%) scaleX(.4)}50%{transform:translateX(20%) scaleX(.7)}100%{transform:translateX(140%) scaleX(.4)}}
@keyframes fd-rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes fd-pop{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}

.fd-skel{position:relative;overflow:hidden;background:var(--skeleton-base);border-radius:var(--r-sm);background-image:linear-gradient(100deg,transparent 20%,var(--skeleton-sheen) 50%,transparent 80%);background-size:220% 100%;background-repeat:no-repeat;animation:fd-sheen var(--skeleton-dur) linear infinite;color:transparent!important;user-select:none;pointer-events:none}
.fd-skel-text{height:1em;border-radius:var(--r-xs);margin:.27em 0}
.fd-skel-circle{border-radius:var(--r-full)}
.fd-skel-block{border-radius:var(--r-md)}
.fd-skel-card{border-radius:var(--r-lg)}

/* A skeleton sized by the content it stands in for (ReservedSkeleton): the content is laid out for its
   size but is invisible and unreachable (visibility:hidden also removes it from focus order and the
   accessibility tree), and the skeleton block fills the box edge to edge over it. */
.fd-skel-reserve{position:relative}
.fd-skel-reserve-content{visibility:hidden;pointer-events:none;user-select:none}
.fd-skel-reserve-cover{position:absolute;inset:0}

/* data present, refresh in flight — stays readable, refuses input */
.fd-stale{opacity:.52;filter:saturate(.7);pointer-events:none;transition:opacity var(--dur-base) var(--ease),filter var(--dur-base) var(--ease)}
.fd-stale-region{position:relative}
.fd-stale-region::after{content:"";position:absolute;inset:0;border-radius:inherit;background:linear-gradient(100deg,transparent 30%,var(--skeleton-sheen) 50%,transparent 70%);background-size:220% 100%;background-repeat:no-repeat;animation:fd-sheen var(--skeleton-dur) linear infinite;pointer-events:none}
.fd-arrived{animation:fd-rise var(--dur-slow) var(--ease-out) both}

.fd-spinner{display:inline-block;width:16px;height:16px;border-radius:var(--r-full);border:2px solid currentColor;border-right-color:transparent;opacity:.85;animation:fd-spin 620ms linear infinite}
.fd-spinner-lg{width:26px;height:26px;border-width:2.5px}

.fd-progress{position:relative;height:6px;border-radius:var(--r-full);background:var(--surface-3);overflow:hidden}
.fd-progress-fill{height:100%;border-radius:inherit;background:var(--grad-primary);transition:width var(--dur-slow) var(--ease)}
.fd-progress-indeterminate .fd-progress-fill{width:40%;animation:fd-bar 1200ms var(--ease) infinite}

/* top-of-app route loader */
.fd-topload{position:absolute;inset:0 0 auto;height:2px;background:transparent;overflow:hidden}
.fd-topload::after{content:"";position:absolute;inset:0;background:var(--grad-brand-soft);animation:fd-bar 1100ms var(--ease) infinite}
@media (prefers-reduced-motion:reduce){
  .fd-skel,.fd-stale-region::after,.fd-topload::after,.fd-progress-indeterminate .fd-progress-fill{animation:fd-pulse 1.6s ease-in-out infinite}
  .fd-spinner{animation-duration:1.6s}
  .fd-arrived{animation:none}
}

/* ============ JobTray / PhasedProgress (MP-211) ============
   A stack of background-job cards (exports, syncs) and an ordered-phase display for the
   same kind of job. Both are entirely props-driven — no timers here, only layout. */
.fd-job-tray{
  display:flex;
  flex-direction:column-reverse;
  gap:10px;
}
.fd-job-tray>.fd-job-card{pointer-events:auto}
.fd-job-card{
  display:flex;
  flex-direction:column;
  gap:8px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-md);
  box-shadow:var(--e-3);
  padding:14px 16px;
  animation:fd-rise var(--dur-slow) var(--ease-out) both;
}
.fd-job-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.fd-job-card-title{font-weight:var(--w-semibold);color:var(--text);font-size:var(--body-size)}
.fd-job-card-note{display:block}
.fd-job-card-progress{display:flex;flex-direction:column;gap:4px}
.fd-job-card-done{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.fd-job-card-done-note{display:block}
.fd-job-card-failed{display:flex;align-items:flex-start;gap:8px;color:var(--danger-text);font-size:var(--body-sm-size)}
.fd-job-card-failed .ph{flex:none;font-size:16px;margin-top:1px}
/* On a phone the tray is the width of the screen, so each card takes only what its words need. */
@media (max-width:640px){
  .fd-job-tray{gap:6px}
  .fd-job-card{padding:8px 10px 8px 12px;gap:2px}
  .fd-job-card-head{align-items:center}
}

.fd-phased-progress{display:flex;flex-direction:column;gap:12px}
.fd-phase-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.fd-phase{display:flex;align-items:center;gap:10px;color:var(--text-muted);font-size:var(--body-size)}
.fd-phase .ph{flex:none;font-size:18px}
.fd-phase-label{flex:1;min-width:0}
.fd-phase-count{white-space:nowrap}
.fd-phase-pending{color:var(--text-muted)}
.fd-phase-active{color:var(--text)}
.fd-phase-active .ph{color:var(--brand)}
.fd-phase-done{color:var(--text)}
.fd-phase-done .ph{color:var(--ok-solid)}
.fd-phase-failed{color:var(--danger-text)}
.fd-phase-failed .ph{color:var(--danger-solid)}
.fd-phase-spin{animation:fd-spin 900ms linear infinite}
.fd-phase-summary{font-size:var(--body-sm-size);color:var(--text-2)}
@media (prefers-reduced-motion:reduce){
  .fd-phase-spin{animation:fd-pulse 1.6s ease-in-out infinite}
  .fd-job-card{animation:none}
}

/* FileViewer (MP-130): a preview pane plus an optional host-supplied side panel — the
   companion notes/metadata surface the app composes in, generic here as `sidePanel`.
   Two regions, one scroll region each (R-8): `.fd-fv-body` never scrolls, each pane owns
   its own overflow. Side by side while there's room; below a narrow width of the
   component's OWN box (a container query, not a media query — the same reasoning as
   `.fd-tlist`'s above, since a FileViewer opened full-page and one opened in a Drawer see
   completely different widths at the same viewport) the side panel becomes a tab next to
   Preview and exactly one pane is visible at a time. */
.fd-fv {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  background: var(--surface);
  color: var(--text);
}
.fd-fv-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.fd-fv-head-icon {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 17px;
  flex: none;
}
.fd-fv-head-titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}
.fd-fv-head-title {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fd-fv-head-meta {
  font-size: var(--body-sm-size);
  color: var(--text-2);
}
.fd-fv-head-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}
.fd-fv-download-error {
  margin: 10px 16px 0;
  padding: 8px 12px;
  border-radius: var(--r-md);
  background: var(--danger-fill);
  border: 1px solid var(--danger-border);
  color: var(--danger-text);
  font-size: var(--body-sm-size);
}
/* Only ever shown below the narrow container-query breakpoint (see the block at the
   bottom of this section) — at full width both panes are already visible, so a tab
   bar choosing between them would be a control with nothing to do. */
.fd-fv-tabs {
  display: none;
  flex: none;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
}
.fd-fv-body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}
.fd-fv-preview {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  padding: 16px;
}
.fd-fv-side {
  flex: 0 0 320px;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  padding: 16px;
  border-left: 1px solid var(--border);
  background: var(--surface-2);
}
.fd-fv-image {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 auto;
  border-radius: var(--r-md);
}
.fd-fv-pdf {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 480px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.fd-fv-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 100%;
  min-height: 220px;
  text-align: center;
  color: var(--text-2);
}
.fd-fv-fallback-icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  font-size: 26px;
}
.fd-fv-fallback-title {
  font-weight: 600;
  color: var(--text);
}
.fd-fv-fallback-meta {
  font-size: var(--body-sm-size);
}
.fd-fv-csv-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--body-sm-size);
}
.fd-fv-csv-table th,
.fd-fv-csv-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  white-space: nowrap;
}
.fd-fv-csv-table th {
  color: var(--text-2);
  font-weight: 600;
  background: var(--surface-2);
  position: sticky;
  top: 0;
}
.fd-fv-csv-note {
  margin-top: 10px;
}
/* Below 640px of `.fd-fv`'s OWN width (not the viewport's — see the block comment
   above) there is no room for a preview beside a side panel: the tab bar takes over
   choosing which one is visible, and the two panes stack full-width instead of sitting
   side by side. Each pane keeps its own `overflow: auto` from the base rules above, so
   R-8 (one scroll region per pane) holds at this width too — there is just one pane on
   screen at a time instead of two. */
@container (max-width: 640px) {
  .fd-fv-tabs {
    display: flex;
  }
  .fd-fv-body {
    flex-direction: column;
  }
  .fd-fv-side {
    border-left: 0;
    border-top: 1px solid var(--border);
  }
  .fd-fv.is-tab-preview .fd-fv-side {
    display: none;
  }
  .fd-fv.is-tab-side .fd-fv-preview {
    display: none;
  }
}

/* FileBrowser (MP-135): a folder tree pane plus the current folder's contents — folders
   and files together, create/rename/move by drag or by an equally real keyboard menu.
   Two regions, one scroll region each (R-8): the head/breadcrumb bar never scrolls, the
   tree and the main pane each own their own overflow. Side by side while there's room —
   below a narrow width of the component's OWN box (a container query, same reasoning as
   `.fd-fv` above) the tree pane disappears entirely: there is nothing to switch to, since
   the current folder's own subfolders already show up as rows in the main pane. */
.fd-fb {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  background: var(--surface);
  color: var(--text);
}
.fd-fb-dropzone {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}
.fd-fb-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.fd-fb-crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  min-width: 0;
}
.fd-fb-crumb {
  display: flex;
  align-items: center;
  border-radius: var(--r-sm);
}
.fd-fb-crumb.is-drop-target {
  background: var(--surface-brand);
}
.fd-fb-crumb:not(:last-child)::after {
  content: "/";
  margin: 0 4px;
  color: var(--text-muted);
}
.fd-fb-crumb-link {
  padding: 2px 4px;
  border-radius: var(--r-sm);
  background: none;
  border: 0;
  color: var(--text-2);
  cursor: pointer;
  font: inherit;
}
.fd-fb-crumb-link:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fd-fb-crumb-current {
  padding: 2px 4px;
  font-weight: 600;
  color: var(--text);
}
.fd-fb-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}
.fd-fb-body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}
.fd-fb-tree {
  flex: 0 0 220px;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  padding: 10px;
  border-right: 1px solid var(--border);
  background: var(--surface-2);
}
.fd-fb-main {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  padding: 10px;
  position: relative;
}
.fd-fb-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.fd-fb-row {
  display: flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--r-md);
}
.fd-fb-row.is-drop-target {
  background: var(--surface-brand);
  outline: 2px dashed var(--brand);
  outline-offset: -2px;
}
.fd-fb-row-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  border-radius: var(--r-md);
  color: var(--text);
  font: inherit;
}
.fd-fb-row-main:hover {
  background: var(--surface-2);
}
.fd-fb-tree-row.is-current .fd-fb-row-main,
.fd-fb-row.is-current .fd-fb-row-main {
  background: var(--surface-brand);
  color: var(--text-on-surface-brand);
  font-weight: 600;
}
.fd-fb-row-icon {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--text-2);
  font-size: 16px;
}
.fd-fb-row-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.fd-fb-row-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--body-sm-size);
}
.fd-fb-row-meta {
  font-size: 11.5px;
  color: var(--text-muted);
}
.fd-fb-row-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
  padding-right: 4px;
}
.fd-fb-tree-children {
  padding-left: 14px;
}
.fd-fb-menu-anchor {
  display: inline-flex;
}
/* The Move menu's items, inside its Popover surface (InlinePanelSurface). */
.fd-fb-menu {
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.fd-fb-menu-title {
  padding: 4px 8px 6px;
  display: block;
}
.fd-fb-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-size: var(--body-sm-size);
  color: var(--text);
}
.fd-fb-menu-item:hover {
  background: var(--surface-2);
}
.fd-fb-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font: inherit;
  background: var(--surface);
  color: var(--text);
}
/* Below 560px of `.fd-fb`'s OWN width, the tree pane has no room to justify itself: the
   current folder's subfolders already appear as rows in `.fd-fb-main` (see the component
   doc comment), so hiding the tree loses zero navigation, only the redundant second copy
   of the hierarchy. Breadcrumbs plus that folder list is the whole nav surface below this
   width, exactly as the card spec calls for. */
@container (max-width: 560px) {
  .fd-fb-tree {
    display: none;
  }
}

/* ============ SessionScreen (MP-288) ============
   The one full-viewport screen every flytedesk ID app shows while its session is not
   usable (signing in, recovering an expired session, signing out, reconnecting, or a
   failure with a Try again). Permanently dark backdrop, like the sign-in page it replaces; the
   card follows the active theme, and the wordmark is forced to its white variant (see
   SessionScreen.tsx) so it reads against the backdrop in either.

   `--fd-session-screen-min-height` is the one sizing hook: unset, the screen fills the
   viewport; a docs preview (or any framed embed) sets it on an ancestor to a fixed height.
   dvh is applied only where supported — a var() holding an unsupported unit is invalid at
   computed-value time and would drop the declaration instead of falling back. */
.fd-session-screen {
  position: relative;
  display: grid;
  place-items: center;
  min-height: var(--fd-session-screen-min-height, 100vh);
  padding: var(--s-24) var(--s-16);
  box-sizing: border-box;
  overflow: hidden;
  background:
    radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%),
    radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%),
    linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%);
}
@supports (min-height: 100dvh) {
  .fd-session-screen {
    min-height: var(--fd-session-screen-min-height, 100dvh);
  }
}
.fd-session-screen::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(circle at 50% 40%, black, transparent 70%);
  pointer-events: none;
}
.fd-session-screen-inner {
  position: relative;
  width: 100%;
  max-width: 408px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.fd-session-screen-mark {
  margin-bottom: var(--s-32);
}
.fd-session-screen-frame {
  width: 100%;
  min-width: 0;
  border-radius: var(--r-2xl);
  overflow: hidden;
  box-shadow: 0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3);
}
.fd-session-screen-stripe {
  height: 4px;
  background: linear-gradient(90deg, var(--blue-400), var(--blue-600), var(--navy));
}
.fd-session-screen-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--s-8) 0;
  text-align: center;
  min-width: 0;
}
.fd-session-screen-body > * {
  min-width: 0;
  max-width: 100%;
}
.fd-session-screen-title {
  margin: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}
/* Focus lands here programmatically (see SessionScreen.tsx); it is not a control, so it
   draws no ring of its own. */
.fd-session-screen .fd-session-screen-title:focus-visible {
  box-shadow: none;
}
/* The status region stays mounted (empty) on a failure so a retry is announced into an
   existing live region; only a region with content takes space, so the body needs no
   flex gap that an empty region would double. */
.fd-session-screen-status {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-12);
}
.fd-session-screen-status:not(:empty) {
  margin-top: var(--s-20);
}
.fd-session-screen-spinner {
  color: var(--brand);
}
.fd-session-screen-message {
  margin: 0;
  min-height: 1.5em;
  color: var(--text-2);
}
.fd-session-screen-failure {
  display: flex;
  flex-direction: column;
  gap: var(--s-16);
  margin-top: var(--s-20);
  width: 100%;
  text-align: left;
  overflow-wrap: anywhere;
}
/* Phone: a smaller wordmark and a tighter gutter so the card never crowds the edge. */
@media (max-width: 479px) {
  .fd-session-screen {
    padding: var(--s-16) var(--s-12);
  }
  .fd-session-screen-mark {
    margin-bottom: var(--s-24);
  }
  .fd-session-screen .fd-brand-mark img {
    height: 26px;
  }
}
/* Tablet and up: more air around the card. */
@media (min-width: 768px) {
  .fd-session-screen {
    padding: var(--s-48) var(--s-24);
  }
  .fd-session-screen-inner {
    max-width: 440px;
  }
}
/* Reduced motion: the rotating ring becomes a slow pulse (same as the other indeterminate
   indicators above); [data-motion="reduce"] already stops every animation outright. */
@media (prefers-reduced-motion: reduce) {
  .fd-spinner.fd-session-screen-spinner {
    animation: fd-pulse 1.6s ease-in-out infinite;
  }
}

/* USChoropleth: a US map shaded on the sequential ramp (--seq-1..5), its legend, an optional ranking
   and a table view. The component's own width decides the layout (a container query), not the
   window's: the same card sits in different page widths. */
.fd-uschoro {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.fd-uschoro-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}
@container (min-width: 640px) {
  .fd-uschoro-layout:has(.fd-uschoro-top) {
    grid-template-columns: minmax(0, 1fr) 280px;
    align-items: start;
  }
}
.fd-uschoro-main {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}
.fd-uschoro-stage {
  position: relative;
}
.fd-uschoro-svg {
  display: block;
  width: 100%;
  height: auto;
}
/* The skeleton holds the map's own proportions, so the page does not jump when the outlines arrive. */
.fd-uschoro-skeleton {
  aspect-ratio: 975 / 610;
}
.fd-uschoro-state {
  stroke: var(--surface);
  stroke-width: 1;
  outline: none;
}
.fd-uschoro-state[data-step="none"] { fill: var(--surface-3); stroke: var(--border-strong); }
.fd-uschoro-state[data-step="1"] { fill: var(--seq-1); }
.fd-uschoro-state[data-step="2"] { fill: var(--seq-2); }
.fd-uschoro-state[data-step="3"] { fill: var(--seq-3); }
.fd-uschoro-state[data-step="4"] { fill: var(--seq-4); }
.fd-uschoro-state[data-step="5"] { fill: var(--seq-5); }
/* The state being read (hovered, focused or tapped): an outline drawn over its neighbours, whatever its shade. */
.fd-uschoro-active {
  fill: none;
  stroke: var(--text);
  stroke-width: 2.5;
  stroke-linejoin: round;
  pointer-events: none;
}
.fd-uschoro-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--body-sm-size);
  color: var(--text-2);
}
.fd-uschoro-legend li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.fd-uschoro-swatch {
  width: 16px;
  height: 12px;
  border-radius: 3px;
  border: 1px solid var(--border-strong);
}
.fd-uschoro-swatch[data-step="none"] { background: var(--surface-3); }
.fd-uschoro-swatch[data-step="1"] { background: var(--seq-1); }
.fd-uschoro-swatch[data-step="2"] { background: var(--seq-2); }
.fd-uschoro-swatch[data-step="3"] { background: var(--seq-3); }
.fd-uschoro-swatch[data-step="4"] { background: var(--seq-4); }
.fd-uschoro-swatch[data-step="5"] { background: var(--seq-5); }

/* ============ DS-39: EditableTitle + ScreenHead toolbar ============ */
.fd-edtitle {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  line-height: inherit;
  margin: 0;
  padding: 0 var(--s-8);
  /* The padding and the border sit outside the text, so the text lines up with the kicker. */
  margin-left: calc(-1 * (var(--s-8) + 1px));
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  box-sizing: border-box;
  max-width: 100%;
}
/* A read-only title with a reason is a flex item of Tooltip's anchor, which sizes to it. The
   negative margin there would shrink the title below its own text and wrap the last word,
   so the anchor carries the pull instead. */
.fd-tooltip-anchor:has(> .fd-edtitle-readonly) {
  margin-left: calc(-1 * (var(--s-8) + 1px));
}
.fd-tooltip-anchor > .fd-edtitle-readonly {
  margin-left: 0;
}
.fd-edtitle-btn {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s-8);
  cursor: text;
  text-align: left;
}
.fd-edtitle-pencil {
  font-size: 0.6em;
  opacity: 0;
  color: var(--text-muted);
}
/* No hover on a touchscreen: the pencil is always shown there so the title reads as editable. */
@media (hover: none) {
  .fd-edtitle-pencil {
    opacity: 0.7;
  }
}
.fd-edtitle-btn:hover .fd-edtitle-pencil,
.fd-edtitle-btn:focus-visible .fd-edtitle-pencil {
  opacity: 1;
}
.fd-edtitle-btn:hover {
  border-color: var(--border);
}
.fd-edtitle-input {
  width: 100%;
  border-color: var(--brand);
  outline: none;
}
[data-contrast="high"] .fd-edtitle-btn {
  border-color: currentColor;
}
.fd-screenhead-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-12);
  margin-bottom: var(--s-4);
}
.fd-screenhead-toolbar-start,
.fd-screenhead-toolbar-end {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-12);
}
.fd-screenhead-toolbar-end {
  margin-left: auto;
}
@media (max-width: 600px) {
  .fd-screenhead-toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  .fd-screenhead-toolbar-end {
    margin-left: 0;
  }
}

/* DS-40: the DonutChart segment popover's content. Colours are tokens, so light and dark
   follow the theme; high contrast lifts the value line from muted to the full text colour. */
.fd-donut-pop {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
  color: var(--text);
}
/* DS-53: the detail sits in the ring's hole, centred, never wider than the ring's box. The
   ring is inside the chart, so the detail can cover neither the legend (beside or under the
   ring) nor anything above the chart, and it is inside the viewport whenever the ring is. */
.fd-donut-pop-surface {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* left: 50% leaves a shrink-to-fit box only half the ring to grow into; max-content then the cap
     lets it use the whole ring and wrap there. */
  width: max-content;
  max-width: 100%;
  box-sizing: border-box;
  padding: 6px 8px;
  text-align: center;
  overflow-wrap: anywhere;
  pointer-events: none;
  background: var(--surface-1, var(--surface));
  border-radius: var(--radius-sm, 6px);
  z-index: 1;
}
.fd-donut-pop { align-items: center; }
.fd-donut-pop strong { font-weight: 600; }
.fd-donut-pop .fd-tabular { color: var(--text-muted); }
[data-contrast="high"] .fd-donut-pop .fd-tabular { color: var(--text); }

/* DS-49: StatTile `info`. Inline after the label in display mode; in press mode the button is
 * an overlay sibling of the tile's <button> (no nested buttons) that repeats the label
 * invisibly so the info button follows its last word. Padding mirrors .fd-stat + its border. */
.fd-stat-label .fd-tooltip-anchor {
  margin-left: 2px;
  vertical-align: middle;
  text-transform: none;
}
.fd-stat-info-wrap {
  position: relative;
  min-width: 0;
}
.fd-stat-info-wrap > .fd-stat-pressable {
  height: 100%;
}
.fd-stat-info-overlay {
  position: absolute;
  inset: 0;
  padding: 15px 17px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  pointer-events: none;
  min-width: 0;
}
.fd-stat-info-overlay .fd-stat-label {
  pointer-events: none;
}
.fd-stat-info-overlay .fd-tooltip-anchor {
  pointer-events: auto;
}
.fd-stat-label-ghost {
  visibility: hidden;
}
@media (max-width: 640px) {
  .fd-stat-info-overlay { padding: 13px 15px; }
}
.fd-stat-info-wrap.is-compact .fd-stat-info-overlay { padding: 11px 15px; }
