/*
 * Design tokens for the 2026 settings redesign (Figma: "Tweek 2026", components node 410-1505).
 * Scoped under .ds-v2 on purpose: the tokens must not leak into legacy screens or be affected
 * by the color-theme CSS variables. Apply .ds-v2 to the root element of every new-design surface.
 *
 * The palette is two-mode (Figma variable modes): --ds-black is "foreground" and flips to white
 * in dark mode, --ds-white flips to black, and the low black opacities step up for contrast.
 * The -static tokens never flip. Dark mode is opt-in: add .ds-dark to a DS root or any subtree.
 *
 * --ds-surface is not set here: a block with a fill of its own (the menu panel, the header over the
 * page's theme color) sets it to that fill, so what sits on it can cut itself out of it — the
 * marker's ring on a button. Readers fall back to --ds-white where no block has set it.
 */

/* The app has no global border-box reset (only body/textarea) — scope one to the DS */
.ds-v2,
.ds-v2 *,
.ds-v2 *::before,
.ds-v2 *::after {
  box-sizing: border-box;
}

/* Motion — on :root, not .ds-v2: the menu panel's level transitions style ::view-transition-*
 * pseudo-elements, which live on the document root where .ds-v2-scoped tokens can't reach;
 * plain durations can't clash with legacy styles, so the wider scope is safe.
 * --ds-transition-fast is the DS-wide default for hover/state changes and overlay enters;
 * the primitives exist for `animation`, which can't take the shorthand. --ds-duration-medium
 * is the next rung up, for enters that also travel a distance and would read as a jump at
 * the fast duration (the settings panel dropping into place, its level transitions).
 * Hover lights up at once and fades out: a hover rule sets `transition-duration: 0s`, so only leaving
 * it runs the base rule's transition (a transition takes the rules of the state it goes to). Not where
 * something moves — a switch's knob, a nudged arrow, a turning chevron keep their motion both ways. */
:root {
  --ds-duration-fast: 0.1s;
  --ds-duration-medium: 0.2s;
  --ds-ease: ease;
  --ds-transition-fast: var(--ds-duration-fast) var(--ds-ease);
  --ds-transition-medium: var(--ds-duration-medium) var(--ds-ease);
  /* One beat of the mascot's squat loop (TweekLogo) — anything keeping time with it reads this */
  --ds-duration-squat: 1s;
  /* How far a stepped value travels as it slides in (.ds-slide-forward / .ds-slide-backward) */
  --ds-slide-distance: 16px;
  /* How long a browser's autofill tint waits to fade in: longer than any session, so it never shows
   * (TextField, CodeField) */
  --ds-autofill-tint-delay: 600000s;
}

.ds-v2 {
  /* Colors — names mirror the Figma variable names */
  --ds-black: #000000;
  --ds-black-5: rgba(0, 0, 0, 0.05);
  --ds-black-10: rgba(0, 0, 0, 0.1);
  --ds-black-15: rgba(0, 0, 0, 0.15);
  --ds-black-20: rgba(0, 0, 0, 0.2);
  --ds-black-25: rgba(0, 0, 0, 0.25);
  --ds-black-40: rgba(0, 0, 0, 0.4);
  --ds-black-50: rgba(0, 0, 0, 0.5);
  --ds-black-60: rgba(0, 0, 0, 0.6);
  --ds-black-75: rgba(0, 0, 0, 0.75);
  /* Hover shade of solid-black chips (Upgrade pill, a hovered badge) */
  --ds-black-90: rgba(0, 0, 0, 0.9);
  --ds-white: #ffffff;
  --ds-white-15: rgba(255, 255, 255, 0.15);
  --ds-white-20: rgba(255, 255, 255, 0.2);
  --ds-white-25: rgba(255, 255, 255, 0.25);
  --ds-white-60: rgba(255, 255, 255, 0.6);
  --ds-white-75: rgba(255, 255, 255, 0.75);
  --ds-white-90: rgba(255, 255, 255, 0.9);
  /* Mode-independent black/white — for places that must not flip in dark mode */
  --ds-black-static: #000000;
  --ds-white-static: #ffffff;
  /* White-static at the editor toolbar's opacities: control hover and divider, active control hover */
  --ds-white-static-15: rgba(255, 255, 255, 0.15);
  /* The shortcut chip of a tooltip, on its dark surface in both modes */
  --ds-white-static-20: rgba(255, 255, 255, 0.2);
  /* The editor toolbar field's placeholder */
  --ds-white-static-50: rgba(255, 255, 255, 0.5);
  --ds-white-static-90: rgba(255, 255, 255, 0.9);
  /* Popover sheet of the task card's palette (Figma lightgrey-90) */
  --ds-lightgrey-90: rgba(239, 239, 239, 0.9);
  /* Tooltip surface (Figma: black-tooltip) — dark in both modes (#1a1a1a in dark), its text is white-static */
  --ds-black-tooltip: #000000;
  --ds-purple: #be9cf3;
  --ds-purple-25: rgba(190, 156, 243, 0.25);
  --ds-purple-50: rgba(190, 156, 243, 0.5);
  --ds-purple-60: rgba(190, 156, 243, 0.6);
  --ds-purple-75: rgba(190, 156, 243, 0.75);
  --ds-lightpurple: #e5d8fa;
  --ds-blue: #5167f4;
  --ds-lightblue: #dce1fd;
  --ds-cyan: #98f4f9;
  --ds-green: #23ffa1;
  --ds-yellow: #feee5d;
  --ds-lightorange: #f8e9e2;
  --ds-dangerred: #df525f;
  --ds-red: #cd2c54;
  /* The tint under an error line in red (the menu's sync error) */
  --ds-red-10: rgba(205, 44, 84, 0.1);

  /* Corner radii */
  --ds-radius-s: 6px; /* icon hit-areas, tiny controls */
  --ds-radius-m: 12px; /* text fields */
  --ds-radius-l: 16px; /* cards, tiles, cell groups */
  --ds-radius-xl: 24px; /* panels, popups */
  --ds-radius-pill: 256px; /* buttons, badges */

  /* Control sizes */
  --ds-control-h-small: 32px;
  --ds-control-h-medium: 40px;
  --ds-control-h-large: 44px;
  /* Figma button-inline: the buttons inside other elements */
  --ds-control-h-inline: 36px;
  --ds-control-h-compact: 22px;
  --ds-cell-h: 52px;
  --ds-icon-s: 16px;
  --ds-icon-m: 20px;
  --ds-icon-l: 24px;

  /* Type scale — sizes/line-heights behind the Figma text styles (ds-text-* below) */
  --ds-text-captions-size: 14px;
  --ds-text-captions-lh: 20px;
  --ds-text-14-size: 14px;
  --ds-text-14-lh: 18px;
  --ds-text-12-size: 12px;
  --ds-text-12-lh: 18px;
  --ds-text-15-size: 15px;
  --ds-text-15-lh: 20px;
  --ds-text-body-size: 17px;
  --ds-text-body-lh: 22px;
  /* Initials in avatar circles (Figma "16 initials") — the only off-scale size */
  --ds-text-16-initials-size: 16px;
  --ds-text-21-size: 21px;
  --ds-text-21-lh: 24px;
  --ds-text-24-size: 24px;
  --ds-text-24-lh: 28px;
  /* Task card title (Figma "28 bold") */
  --ds-text-28-size: 28px;
  --ds-text-28-lh: 34px;
  --ds-text-31-size: 31px;
  --ds-text-31-lh: 40px;
  --ds-text-36-size: 36px;
  --ds-text-36-lh: 48px;

  /* Overlay stacking — the menu panel itself sits at 999/1000 (MenuPanel.module.css),
   * DS overlays stack above it; the legacy modals and the colour palette take the rungs above
   * these, on :root in 1_app/globalStyles.css (this file loads lazily with the DS chunk) */
  --ds-z-menu: 1001;
  --ds-z-popup: 1003;

  /* Dropdown menus use their own radius, per the Figma overlays ("task options") */
  --ds-radius-menu: 16px;
  /* A menu item's hover and a small text field inside a menu (Figma dropdown-item, textfield size=small) */
  --ds-radius-menu-item: 8px;
  /* The floating editor toolbar, between -s and -m */
  --ds-radius-toolbar: 10px;

  /* Shadows keep the static black in both modes — a mode-flipped shadow would glow in dark */
  --ds-shadow-menu: 0 8px 16px rgba(0, 0, 0, 0.1);

  /* Menu edge fades match the menu surface (white-75 over blur), not the text color */
  --ds-overlay-fade: rgba(255, 255, 255, 0.9);
  --ds-overlay-fade-transparent: rgba(255, 255, 255, 0);

  font-family: SuisseIntl, sans-serif;
  color: var(--ds-black);
}

/*
 * Dark mode (Figma "Variable collection", mode dark). Every colour token that has a dark value in the
 * Figma modes flips here: black/white swap roles and keep their opacity, except the low black
 * opacities, which become white one grade up for perceived contrast (5% → 12%, 10% → 15%,
 * 15% → 20%, 20% → 25%, 25% → 30%). The tooltip surface lightens to #1a1a1a. The accents and the
 * -static tokens are mode-independent: whatever must stay dark or light in both modes (a scrim, an
 * edge on a dark canvas, the editor toolbar) takes a -static token.
 */
.ds-v2.ds-dark,
.ds-v2 .ds-dark {
  --ds-black: #ffffff;
  --ds-black-5: rgba(255, 255, 255, 0.12);
  --ds-black-10: rgba(255, 255, 255, 0.15);
  --ds-black-15: rgba(255, 255, 255, 0.2);
  --ds-black-20: rgba(255, 255, 255, 0.25);
  --ds-black-25: rgba(255, 255, 255, 0.3);
  --ds-black-40: rgba(255, 255, 255, 0.4);
  --ds-black-50: rgba(255, 255, 255, 0.5);
  --ds-black-60: rgba(255, 255, 255, 0.6);
  --ds-black-75: rgba(255, 255, 255, 0.75);
  --ds-black-90: rgba(255, 255, 255, 0.9);
  --ds-white: #000000;
  --ds-white-15: rgba(0, 0, 0, 0.15);
  --ds-white-20: rgba(0, 0, 0, 0.2);
  --ds-white-25: rgba(0, 0, 0, 0.25);
  --ds-white-60: rgba(0, 0, 0, 0.6);
  --ds-white-75: rgba(0, 0, 0, 0.75);
  --ds-white-90: rgba(0, 0, 0, 0.9);
  --ds-black-tooltip: #1a1a1a;
  --ds-lightgrey-90: rgba(32, 32, 35, 0.9);
  --ds-overlay-fade: rgba(0, 0, 0, 0.9);
  --ds-overlay-fade-transparent: rgba(0, 0, 0, 0);

  color: var(--ds-black);
}

/* Native scrollbars are hidden on every DS surface; scrollable blocks that
 * need a visual indicator opt in with .ds-scroll below.
 * NOTE: setting the standard scrollbar-width property makes Chrome ignore
 * ::-webkit-scrollbar styling entirely, so .ds-scroll elements must be
 * excluded here and get scrollbar-width only in the Firefox-only fallback. */
.ds-v2:not(.ds-scroll),
.ds-v2 *:not(.ds-scroll) {
  scrollbar-width: none;
}

.ds-v2:not(.ds-scroll)::-webkit-scrollbar,
.ds-v2 *:not(.ds-scroll)::-webkit-scrollbar {
  display: none;
}

/*
 * Slim overlay scrollbar: invisible until the block is hovered, then a bare
 * 4px thumb strip. Width stays constant so hovering never shifts the layout.
 */
.ds-v2 .ds-scroll::-webkit-scrollbar,
.ds-v2.ds-scroll::-webkit-scrollbar {
  width: 4px;
  background: transparent;
}

.ds-v2 .ds-scroll::-webkit-scrollbar-track,
.ds-v2.ds-scroll::-webkit-scrollbar-track {
  background: transparent;
}

.ds-v2 .ds-scroll::-webkit-scrollbar-thumb,
.ds-v2.ds-scroll::-webkit-scrollbar-thumb {
  border-radius: 2px;
  background: transparent;
}

.ds-v2 .ds-scroll:hover::-webkit-scrollbar-thumb,
.ds-v2.ds-scroll:hover::-webkit-scrollbar-thumb {
  background: var(--ds-black-25);
}

/* Firefox has no ::-webkit-scrollbar — use the standard properties there */
@supports not selector(::-webkit-scrollbar) {
  .ds-v2 .ds-scroll,
  .ds-v2.ds-scroll {
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
  }

  .ds-v2 .ds-scroll:hover,
  .ds-v2.ds-scroll:hover {
    scrollbar-color: var(--ds-black-25) transparent;
  }
}

/* Spinner rotation for the comet loader icon (a gradient-tailed arc): one shared
 * utility so every loading control spins identically */
.ds-v2 .ds-spin {
  animation: ds-spin 0.8s linear infinite;
}

@keyframes ds-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Skeleton pulse shared by loading placeholders (cell skeletons, label-button loading);
 * the background stays with each consumer — only the rhythm is common */
.ds-v2 .ds-pulse {
  animation: ds-pulse 1.5s ease-in-out infinite;
}

@keyframes ds-pulse {
  50% {
    opacity: 0.5;
  }
}

/* A stepped value (a calendar's month, a reminder's day) comes in from the side of the step, as if the
 * row scrolled: from the right going forward, from the left going back (see useSlideIn) */
.ds-v2 .ds-slide-forward {
  animation: ds-slide-forward var(--ds-duration-medium) var(--ds-ease);
}

.ds-v2 .ds-slide-backward {
  animation: ds-slide-backward var(--ds-duration-medium) var(--ds-ease);
}

@keyframes ds-slide-forward {
  from {
    opacity: 0;
    transform: translateX(var(--ds-slide-distance));
  }
}

@keyframes ds-slide-backward {
  from {
    opacity: 0;
    transform: translateX(calc(-1 * var(--ds-slide-distance)));
  }
}

@media (prefers-reduced-motion: reduce) {
  .ds-v2 .ds-spin,
  .ds-v2 .ds-pulse,
  .ds-v2 .ds-slide-forward,
  .ds-v2 .ds-slide-backward {
    animation: none;
  }
}

/* Text styles — names mirror the Figma text styles */

.ds-v2 .ds-text-captions {
  font-size: var(--ds-text-captions-size);
  font-weight: 400;
  line-height: var(--ds-text-captions-lh);
  letter-spacing: 0;
}

.ds-v2 .ds-text-15 {
  font-size: var(--ds-text-15-size);
  font-weight: 400;
  line-height: var(--ds-text-15-lh);
  letter-spacing: 0;
}

.ds-v2 .ds-text-body {
  font-size: var(--ds-text-body-size);
  font-weight: 400;
  line-height: var(--ds-text-body-lh);
  letter-spacing: 0;
}

.ds-v2 .ds-text-21 {
  font-size: var(--ds-text-21-size);
  font-weight: 400;
  line-height: var(--ds-text-21-lh);
  letter-spacing: 0;
}

/* Initials in an avatar circle (Figma "16 initials") — content is centered in a fixed
 * circle, so the style carries no line-height */
.ds-v2 .ds-text-16-initials {
  font-size: var(--ds-text-16-initials-size);
  font-weight: 400;
  letter-spacing: 0;
}

.ds-v2 .ds-text-17-bold {
  font-size: var(--ds-text-body-size);
  font-weight: 700;
  line-height: var(--ds-text-body-lh);
  letter-spacing: 0;
}

.ds-v2 .ds-text-21-bold {
  font-size: var(--ds-text-21-size);
  font-weight: 700;
  line-height: var(--ds-text-21-lh);
  letter-spacing: -0.5px;
}

.ds-v2 .ds-text-24-bold {
  font-size: var(--ds-text-24-size);
  font-weight: 700;
  line-height: var(--ds-text-24-lh);
  letter-spacing: -0.24px;
}

.ds-v2 .ds-text-31-bold {
  font-size: var(--ds-text-31-size);
  font-weight: 700;
  line-height: var(--ds-text-31-lh);
  letter-spacing: -1px;
}

.ds-v2 .ds-text-36-bold {
  font-size: var(--ds-text-36-size);
  font-weight: 700;
  line-height: var(--ds-text-36-lh);
  letter-spacing: -1px;
}

.button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Fixed-height control: never squeezed by a height-constrained flex column */
  flex-shrink: 0;
  border: none;
  border-radius: var(--ds-radius-pill);
  font-family: inherit;
  font-size: var(--ds-text-body-size);
  font-weight: 700;
  line-height: var(--ds-text-body-lh);
  cursor: pointer;
  padding: 0;
  transition: background-color var(--ds-transition-fast);
}

.button:is(:disabled, [aria-disabled="true"]) {
  cursor: default;
}

.link {
  text-decoration: none;
}

/* Keyboard focus: the app's global button reset drops every outline, which left DS buttons with no
 * focus indication at all */
.button:focus-visible {
  outline: 2px solid var(--ds-black);
  outline-offset: 2px;
}

/* The label never wraps: text that does not fit the button is cut with an ellipsis
 * (e.g. the confirm popup's equal-width action pair in verbose locales).
 * min-width lets the flex item shrink below its content width. */
.label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Every hover below is only where a pointer really hovers: a touch screen keeps :hover on the last
 * tapped button, which then stayed shaded after its popover closed (EditorToolbar.module.css does the
 * same). Each sits where its rule stood, so the pressed and selected rules after it still win. */

/* A hovered button lights an inline badge up (e.g. "Create new · Premium") — see Badge.module.css */
@media (hover: hover) {
  .button:hover:not(:is(:disabled, [aria-disabled="true"])) {
    --ds-badge-background: var(--ds-black-90);
    --ds-badge-color: var(--ds-white);
    --ds-badge-transition-duration: 0s;
  }

  /* Hover lights up at once and fades out (see the motion note in tokens.css) */
  .button:hover {
    transition-duration: 0s;
  }
}

/* Sizes */

.large {
  height: var(--ds-control-h-large);
  padding: 0 24px;
}

.medium {
  height: var(--ds-control-h-medium);
  padding: 0 18px;
}

/* Figma: the small button's label is Book 15/20, not the bold body text of the larger sizes */
.small {
  gap: 6px;
  height: var(--ds-control-h-small);
  padding: 0 12px;
  font-size: var(--ds-text-15-size);
  font-weight: 400;
  line-height: var(--ds-text-15-lh);
}

/* Figma button-inline: a Book 15/20 label, closer padding and gap */
.inlineNormal {
  gap: 6px;
  height: var(--ds-control-h-inline);
  padding: 0 16px;
  font-size: var(--ds-text-15-size);
  font-weight: 400;
  line-height: var(--ds-text-15-lh);
}

.inlineCompact {
  gap: 4px;
  height: var(--ds-control-h-compact);
  padding: 0 8px;
  font-size: var(--ds-text-15-size);
  font-weight: 400;
  line-height: var(--ds-text-15-lh);
}

.iconOnly.large {
  width: var(--ds-control-h-large);
  padding: 0;
}

.iconOnly.medium {
  width: var(--ds-control-h-medium);
  padding: 0;
}

.iconOnly.small {
  width: var(--ds-control-h-small);
  padding: 0;
}

.iconOnly.inlineNormal {
  width: var(--ds-control-h-inline);
  padding: 0;
}

.iconOnly.inlineCompact {
  width: var(--ds-control-h-compact);
  padding: 0;
}

/* Priorities. Hover and pressed are separate shades (Figma state=hover / state=pressed); pressed comes
 * after hover and is as specific, so a press under the pointer shows the pressed shade */

/* The label is cut from the surface the button sits on: windows and settings panels set
 * --ds-button-primary-label to their own colour, elsewhere it is plain white */
.primary {
  background: var(--ds-black);
  color: var(--ds-button-primary-label, var(--ds-white));
}

@media (hover: hover) {
  .primary:hover:not(:is(:disabled, [aria-disabled="true"])) {
    background: var(--ds-black-75);
  }
}

.primary:active:not(:is(:disabled, [aria-disabled="true"])),
.primary.pressed:not(:is(:disabled, [aria-disabled="true"])) {
  background: var(--ds-black-75);
}

.primary:is(:disabled, [aria-disabled="true"]) {
  background: var(--ds-black-15);
  color: var(--ds-white-75);
}

.secondary {
  background: var(--ds-black-5);
  color: var(--ds-black);
}

@media (hover: hover) {
  .secondary:hover:not(:is(:disabled, [aria-disabled="true"])) {
    background: var(--ds-black-10);
  }
}

.secondary:active:not(:is(:disabled, [aria-disabled="true"])),
.secondary.pressed:not(:is(:disabled, [aria-disabled="true"])) {
  background: var(--ds-black-15);
}

.secondary:is(:disabled, [aria-disabled="true"]) {
  background: var(--ds-black-5);
  color: var(--ds-black-20);
}

.ghost {
  background: transparent;
  color: var(--ds-black);
}

@media (hover: hover) {
  .ghost:hover:not(:is(:disabled, [aria-disabled="true"])) {
    background: var(--ds-black-5);
  }
}

.ghost:active:not(:is(:disabled, [aria-disabled="true"])),
.ghost.pressed:not(:is(:disabled, [aria-disabled="true"])) {
  background: var(--ds-black-10);
}

.ghost:is(:disabled, [aria-disabled="true"]) {
  background: transparent;
  color: var(--ds-black-20);
}

/* Selected (Figma selected=yes): black in every kind, a shade lighter under the pointer. As specific as
 * the hover and pressed rules above and listed after them, so it wins over both. The icon is cut from
 * the surface where it sets --ds-button-selected-label (the task card's toolbar), elsewhere it is white */
.primary.selected:not(:is(:disabled, [aria-disabled="true"])),
.secondary.selected:not(:is(:disabled, [aria-disabled="true"])),
.ghost.selected:not(:is(:disabled, [aria-disabled="true"])) {
  background: var(--ds-black);
  color: var(--ds-button-selected-label, var(--ds-white));
}

@media (hover: hover) {
  .primary.selected:hover:not(:is(:disabled, [aria-disabled="true"])),
  .secondary.selected:hover:not(:is(:disabled, [aria-disabled="true"])),
  .ghost.selected:hover:not(:is(:disabled, [aria-disabled="true"])) {
    background: var(--ds-black-75);
  }
}

.primary.selected:active:not(:is(:disabled, [aria-disabled="true"])),
.secondary.selected:active:not(:is(:disabled, [aria-disabled="true"])),
.ghost.selected:active:not(:is(:disabled, [aria-disabled="true"])) {
  background: var(--ds-black-75);
}

.danger {
  background: var(--ds-dangerred);
  color: var(--ds-white);
}

@media (hover: hover) {
  .danger:hover:not(:is(:disabled, [aria-disabled="true"])) {
    background: var(--ds-red);
  }
}

.danger:active:not(:is(:disabled, [aria-disabled="true"])),
.danger.pressed {
  background: var(--ds-red);
}

.danger:is(:disabled, [aria-disabled="true"]) {
  background: var(--ds-black-15);
  color: var(--ds-white);
}

/* user: the avatar circle — initials as content, so the width is pinned to the height
 * and the label is Book, not bold. Colors come from the theme's header block (GlobalStyles
 * vars): the accent with a readable foreground, or DS purple + black on the default theme. */
.user {
  background: var(--header--avatar-background);
  color: var(--header--avatar-foreground);
  font-size: var(--ds-text-16-initials-size);
  font-weight: 400;
}

/* A selected avatar keeps its fill (Figma selected=yes) and shades only under the pointer */
@media (hover: hover) {
  .user:hover:not(:is(:disabled, [aria-disabled="true"])) {
    background: color-mix(in srgb, var(--header--avatar-background) 75%, transparent);
  }
}

.user:active:not(:is(:disabled, [aria-disabled="true"])),
.user.pressed:not(:is(:disabled, [aria-disabled="true"])) {
  background: color-mix(in srgb, var(--header--avatar-background) 75%, transparent);
}

.user:is(:disabled, [aria-disabled="true"]) {
  background: color-mix(in srgb, var(--header--avatar-background) 25%, transparent);
  color: color-mix(in srgb, var(--header--avatar-foreground) 25%, transparent);
}

/* The user button exists in the Figma library at the medium size only */
.user.medium {
  width: var(--ds-control-h-medium);
  padding: 0;
}

/* Loading state of a label button: a skeleton text bar in place of the label, like
 * the text-line bars of CellSkeleton. The content turns transparent but stays laid
 * out, so the button keeps its exact width (doubled class + last position — must
 * outrank every priority/disabled color above, e.g. the white danger:is(:disabled, [aria-disabled="true"])). */
.button.skeleton,
.button.skeleton:is(:disabled, [aria-disabled="true"]) {
  position: relative;
  color: transparent;
}

/* Bar box mirrors .skeletonTitle in Cell (14px, radius-s); a real element (not a
 * pseudo) because the pulse comes from the global ds-pulse utility class — CSS
 * modules rename animation-name references, so the shared keyframes can't be used
 * from inside this file */
/* Waiting state after a click (see the loader prop): content hides but stays laid out
 * so the width holds; the comet inherits the priority's disabled text color */
.button.loader {
  position: relative;
}

/* The label and the icons are the button's direct children; the LoaderOverlay comet sits
 * inside its own wrapper, so it is not caught here */
.button.loader > .label,
.button.loader > svg {
  visibility: hidden;
}

.skeletonBar {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 40%;
  height: 14px;
  border-radius: var(--ds-radius-s);
  background: var(--ds-black-15);
}

/* Figma marker (4840-133319): an 8px dot on an 11px disc of the surface the button sits on (--ds-surface,
 * white where no block sets it — see tokens.css), so a 1.5px ring, centred in the 12px top-right corner box;
 * the box sits 1px outside the smaller buttons */
.marker {
  position: relative;
}

.marker::after {
  content: '';
  position: absolute;
  top: 2px;
  right: 2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ds-black);
  box-shadow: 0 0 0 1.5px var(--ds-surface, var(--ds-white));
}

.marker.small::after,
.marker.inlineCompact::after {
  top: 1px;
  right: 1px;
}

/* Figma marker in red (#df525f): something is wrong behind the button */
.markerDanger::after {
  background: var(--ds-dangerred);
}

/* Figma marker in grey (black-40): something waits behind the button, nothing is wrong. The grey lies on the
 * surface's colour, not on the button under the dot: the dot reads the same on any fill */
.markerMuted::after {
  background: linear-gradient(var(--ds-black-40), var(--ds-black-40)) var(--ds-surface, var(--ds-white));
}

/* The dot fades to half over its ring */
.marker:is(:disabled, [aria-disabled="true"])::after {
  background: color-mix(in srgb, var(--ds-black) 50%, var(--ds-surface, var(--ds-white)));
}

/* Takes the free room of its row (see the `stretched` prop) */
.stretched {
  flex: 1;
  min-width: 0;
}

/* Transform lengths below are in the vector's 128-unit space: 4.5 units ≈ 2px at the rendered 56px */

/* The white fallback keeps the eye visible where the logo renders outside the DS scope */
.eye {
  fill: var(--ds-white, #ffffff);
  transform-box: fill-box;
  transform-origin: center;
}

/* One wink: the eye squints to a sliver and opens again — longer than the DS state
 * transitions on purpose, a 0.2s blink reads as a flicker. The hover variant plays once
 * per pointer entry and re-arms when the pointer leaves */
.blink,
.hover:hover .eye {
  animation: blink 0.36s var(--ds-ease);
}

@keyframes blink {
  40%,
  60% {
    transform: scaleY(0.12);
  }
}

/* The squat: the body (with the eye) drops while the legs bend at the hip; the boots stay */
.body,
.leg {
  transition: transform var(--ds-transition-medium);
}

.leg {
  transform-box: fill-box;
  transform-origin: 50% 0;
}

.hover:hover .body {
  transform: translateY(4.5px);
}

.hover:hover .leg {
  transform: rotate(-3deg);
}

/* The dance: the hover squat on a loop, with the body swaying a couple of degrees around the
 * hip line — the pivot sits at the bottom of the body so the beak swings the most. The legs
 * bend half as much as on hover, first to one side then the other. A clockwise leg swings its
 * foot to the left and bares the right end of the boot, so on that beat each boot pulls its
 * right end in; the left end stays */
.body {
  transform-box: fill-box;
  transform-origin: 50% 100%;
}

.boot {
  transform-box: fill-box;
  transform-origin: 0 50%;
}

.dance .body {
  animation: dance-body 0.9s ease-in-out infinite;
}

.dance .leg {
  animation: dance-leg 0.9s ease-in-out infinite;
}

.dance .boot {
  animation: dance-boot 0.9s ease-in-out infinite;
}

@keyframes dance-body {
  25% {
    transform: translateY(4.5px) rotate(-2.5deg);
  }

  50% {
    transform: translateY(0) rotate(0);
  }

  75% {
    transform: translateY(4.5px) rotate(2.5deg);
  }
}

@keyframes dance-leg {
  25% {
    transform: rotate(-1.5deg);
  }

  50% {
    transform: rotate(0);
  }

  75% {
    transform: rotate(1.5deg);
  }
}

@keyframes dance-boot {
  50% {
    transform: scaleX(1);
  }

  75% {
    transform: scaleX(0.95);
  }
}

/* The squat loop: the hover squat played over and over — down and up, nothing else moves. The
 * beat is a :root token so a companion animation (e.g. loading dots) can keep time with it */
.squat .body {
  animation: squat-body var(--ds-duration-squat) ease-in-out infinite;
}

.squat .leg {
  animation: squat-leg var(--ds-duration-squat) ease-in-out infinite;
}

@keyframes squat-body {
  50% {
    transform: translateY(4.5px);
  }
}

@keyframes squat-leg {
  50% {
    transform: rotate(-3deg);
  }
}

/* Without the animation onAnimationEnd never fires and the blink flag simply stays set — harmless */
@media (prefers-reduced-motion: reduce) {
  .blink,
  .hover:hover .eye,
  .dance .body,
  .dance .leg,
  .dance .boot,
  .squat .body,
  .squat .leg {
    animation: none;
  }

  .hover:hover .body,
  .hover:hover .leg {
    transform: none;
  }
}
