/* Share An App design tokens. Single source of truth.
   Style: neutral white Apple/Google minimalism. Big content, quiet labels,
   white cards on flat neutral gray, olive-dollar green accent used sparingly.

   Two layers:
   1. PRIMITIVES: raw ramps and scales (--gray-*, --green-*, --space-*, ...).
      Never referenced by component CSS.
   2. SEMANTIC: role-named aliases components consume (--color-bg-page,
      --input-border, --btn-primary-bg, ...). Component stylesheets use ONLY
      this layer; every visual value in a component resolves to a semantic
      var(--*). No raw hex, no primitive tokens outside this file. */

/* ------------------------------------------------------------------ */
/* LAYER 1: PRIMITIVES                                                  */
/* ------------------------------------------------------------------ */

:root {
  /* Neutral gray ramp (pure neutral, no warm or cool cast) */
  --gray-0: #ffffff;
  --gray-50: #f6f6f7;
  --gray-100: #f0f0f1;
  --gray-150: #ebebeb;
  --gray-200: #e3e3e4;
  --gray-250: #dddddd;
  --gray-300: #d1d1d3;
  --gray-400: #aeaeb2;
  --gray-500: #8e8e93;
  --gray-600: #6e6e73;
  --gray-700: #48484a;
  --gray-800: #3a3a3c;
  --gray-900: #1c1c1e;

  /* Olive/dollar green ramp */
  --green-50: #f4f8ec;
  --green-100: #e8f0d8;
  --green-200: #d4e3b6;
  --green-300: #b7cf8e;
  --green-400: #9cbb68;
  --green-500: #85a952;
  --green-600: #7a9e3f;
  --green-700: #5f7d30;
  --green-800: #4a6226;
  --green-900: #37491d;

  /* Status hues */
  --red-500: #d64545;
  --red-600: #ba3a3a;
  --red-100: #fbe9e9;
  --amber-500: #c98a1b;
  --amber-100: #faf1de;

  /* Neutral overlays */
  --alpha-hover: rgba(28, 28, 30, 0.05);
  --alpha-pressed: rgba(28, 28, 30, 0.09);
  --alpha-scrim: rgba(28, 28, 30, 0.5);

  /* Size scale (type) */
  --size-11: 11px;
  --size-12: 12px;
  --size-13: 13px;
  --size-14: 14px;
  --size-15: 15px;
  --size-16: 16px;
  --size-18: 18px;
  --size-22: 22px;
  --size-32: 32px;
  --size-48: 48px;
  --size-56: 56px;

  /* Elevation scale (neutral, soft) */
  --shadow-0: none;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-2: 0 1px 3px rgba(0, 0, 0, 0.05), 0 4px 12px rgba(0, 0, 0, 0.04);
  --shadow-3: 0 2px 8px rgba(0, 0, 0, 0.07), 0 8px 24px rgba(0, 0, 0, 0.06);
  --shadow-4: 0 4px 12px rgba(0, 0, 0, 0.09), 0 16px 40px rgba(0, 0, 0, 0.1);
  /* For an edge content slides under rather than a surface floating above
     it. Deliberately not --shadow-1, which is too close to invisible
     behind a 1px hairline.

     RAISED ON THE USER'S ASK, "add a shadow below the divider line",
     which is a request for a shadow that already existed and could not
     be seen. Measured against the page ground between two cards, at 3x,
     the old value darkened the pixels below the line by 1.5 of 255. That
     is a tenth of a percent from nothing.

     THE GEOMETRY WAS ALREADY RIGHT AND ONLY THE ALPHA WAS WRONG, which
     is worth recording because the obvious fix is the wrong one. A
     shadow cast by a 1px line has almost nothing to cast with, so
     REACHING FURTHER makes it fainter, not stronger: 4px/10px measured
     0.8%, 6px/12px 1.6%, 8px/16px 1.2%. Holding the original 2px throw
     and 4px blur and raising the alpha alone reaches 3.9%, the darkest
     of everything tried. Short and dark beats long and thin when the
     caster is a hairline. */
  --shadow-sticky: 0 2px 4px rgba(0, 0, 0, 0.2);

  /* Motion */
  --duration-fast: 150ms;
  --duration-base: 200ms;
  --duration-slow: 300ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
}

/* ------------------------------------------------------------------ */
/* LAYER 2: SEMANTIC (the only layer components may reference)          */
/* ------------------------------------------------------------------ */

:root {
  /* Shared scales (semantic-consumable): spacing and radius are part of the
     public layer; components compose them directly. */
  --space-05: 2px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 28px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;

  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-pill: 999px;
  --radius-circle: 50%;

  /* Backgrounds: one pure-white ground everywhere; contrast comes from
     grey control and card surfaces, never from banded sections. */
  --color-bg-page: var(--gray-0);
  --color-bg-raised: var(--gray-0);
  --color-bg-sunken: var(--gray-100);
  --color-bg-band: var(--gray-0);
  --color-surface: var(--gray-0);
  --color-hover: var(--alpha-hover);
  --color-active: var(--alpha-pressed);
  --color-scrim: var(--alpha-scrim);
  --color-search-fill: var(--gray-100);

  /* Borders */
  --color-border-hairline: var(--gray-150);
  --color-border: var(--gray-150);
  --color-border-mid: var(--gray-200);
  --color-border-strong: var(--gray-300);

  /* Text */
  --color-ink: var(--gray-900);
  --color-ink-secondary: var(--gray-600);
  --color-ink-tertiary: var(--gray-500);
  --color-ink-faint: var(--gray-500);
  --color-ink-disabled: var(--gray-400);
  --color-ink-inverse: var(--gray-0);

  /* Accent (replaces every place Docs uses blue) */
  --color-accent: var(--green-500);
  --color-accent-hover: var(--green-600);
  --color-accent-pressed: var(--green-700);
  --color-accent-strong: var(--green-600);
  --color-accent-ink: var(--green-700);
  --color-accent-ink-strong: var(--green-800);
  --color-accent-tint: var(--green-100);
  --color-accent-tint-strong: var(--green-200);
  --color-accent-tint-faint: var(--green-50);
  --color-on-accent: var(--gray-0);

  /* Semantic slots */
  --color-link: var(--green-700);
  --color-link-hover: var(--green-800);
  --color-success: var(--green-700);
  --color-danger: var(--red-500);
  --color-danger-tint: var(--red-100);
  --color-warning: var(--amber-500);
  --color-warning-tint: var(--amber-100);
  --color-positive-delta: var(--green-600);

  /* Focus ring */
  --focus-ring-width: 2px;
  --focus-ring-offset: 1px;
  --focus-ring-color: var(--green-700);
  --focus-ring: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);

  /* Hairline */
  --hairline-width: 1px;

  /* Per-surface: card */
  --card-bg: var(--gray-50);
  --card-border: var(--gray-150);
  --card-border-hover: var(--green-500);
  --card-radius: var(--radius-lg);
  --card-padding: var(--space-6);
  --card-elevation-rest: var(--shadow-0);
  --card-elevation-hover: var(--shadow-2);

  /* Other elevations */
  --btn-elevation-hover: var(--shadow-1);
  --searchbar-elevation-focus: var(--shadow-2);
  --viewport-elevation: var(--shadow-1);
  /* Depth cue under pinned chrome once it sticks. Short throw on purpose:
     it should read as the content passing beneath an edge, not as a band
     or a floating card. */
  --sticky-divider-elevation: var(--shadow-sticky);

  /* Per-surface: dialog */
  --dialog-bg: var(--gray-0);
  --dialog-radius: var(--radius-xl);
  --dialog-padding: var(--space-6);
  --dialog-elevation: var(--shadow-4);

  /* Per-surface: menu / popover */
  --menu-bg: var(--gray-0);
  --menu-border: var(--gray-150);
  --menu-radius: var(--radius-md);
  --menu-elevation: var(--shadow-3);

  /* Per-surface: input */
  --input-bg: var(--gray-0);
  --input-border: var(--gray-250);
  --input-border-focus: var(--green-700);
  --input-placeholder: var(--gray-500);
  --input-radius: var(--radius-md);

  /* Per-surface: chip */
  --chip-bg: var(--gray-100);
  --chip-text: var(--gray-600);
  --chip-accent-bg: var(--green-100);
  --chip-accent-text: var(--green-800);
  --chip-radius: var(--radius-pill);

  /* Per-surface: drag-and-drop deploy */
  --dropzone-bg: var(--green-50);
  --dropzone-border: var(--green-500);
  --dropzone-border-width: 2px;
  --dropzone-ink: var(--green-700);
  --upload-track: var(--green-100);
  --upload-fill: var(--green-500);
  /* --duration-upload is gone with the animation it drove. The card's
     upload bar is bytes sent now, so there is no duration to state: the
     upload takes as long as it takes, and the two waits either side of
     it cycle rather than counting. */

  /* Per-surface: tooltip */
  --tooltip-bg: var(--gray-800);
  --tooltip-text: var(--gray-0);
  --tooltip-radius: var(--radius-sm);

  /* Per-surface: toast (Docs-style snackbar) */
  --toast-bg: var(--gray-800);
  --toast-text: var(--gray-0);
  --toast-radius: var(--radius-sm);

  /* Per-surface: segmented control */
  --segmented-bg: var(--gray-100);
  --segmented-selected-bg: var(--green-100);
  --segmented-selected-text: var(--green-800);
  --segmented-text: var(--gray-600);

  /* Per-surface: chart (the site overview's account growth plot)

     WHY A CHART NEEDS SLOTS OF ITS OWN, when the page it sits on is
     built from the borders and inks above. Every other surface here
     paints ink on a ground and the question is legibility. A chart
     paints a VALUE, and the rule it answers to is a different one: a
     mark that carries a number has to clear 3:1 against the surface it
     is drawn on, or the number is decoration. Measured on the white
     surface, --green-500 (the accent) reaches 2.69:1 and --green-600
     reaches 3.09:1, so the mark is the darker step even though the
     accent is the lighter one. This is the one place in this file
     where a contrast figure, not a role, picked the value.

     The wash under the line is the ramp's own light step rather than
     the mark at low opacity: a fill and a hairline gridline overlap in
     that band, and a translucent fill composites over the gridline
     into a fourth colour nobody chose.

     ONE MARK COLOUR ACROSS BOTH PLOTS, on purpose. The chart draws two
     measures, the account total and the accounts made each day, as two
     plots with two scales rather than two series sharing one. Separate
     hues would say they are series to be told apart; they are one
     subject at two resolutions, so they take the same mark and their
     own labelled axes do the telling. */
  --chart-mark: var(--green-600);
  --chart-wash: var(--green-100);
  --chart-grid: var(--gray-150);
  --chart-baseline: var(--gray-200);
  --chart-axis-ink: var(--gray-600);
  --chart-crosshair: var(--gray-300);
  /* The ring that keeps the end dot legible where it sits on its own
     line. Surface coloured, so it reads as a gap rather than a stroke:
     a stroke around a mark is ink that is not data. */
  --chart-mark-ring: var(--gray-0);

  /* Per-surface: account status dot

     Three quiet cues rather than three badges. The chip ground under
     all three is the shared neutral one and only the dot carries the
     state, so a column of them reads as a column instead of as traffic
     lights. Never signed in is a hollow ring rather than a third fill,
     which is what makes the three separable by shape and not by tone
     alone; the word beside every dot is the other half of that, and
     neither is optional. */
  --status-active: var(--green-600);
  --status-dormant: var(--gray-400);
  --status-never: var(--gray-400);

  /* Per-surface: code browser */
  --code-bg: var(--gray-0);
  --code-text: var(--gray-800);
  --code-gutter: var(--gray-400);
  --filetree-bg: var(--gray-50);
  --filetree-selected-bg: var(--green-100);
  --filetree-selected-text: var(--green-800);

  /* Buttons */
  --btn-primary-bg: var(--green-600);
  --btn-primary-bg-hover: var(--green-700);
  --btn-primary-bg-pressed: var(--green-800);
  --btn-primary-text: var(--gray-0);
  --btn-outline-border: var(--gray-250);
  --btn-outline-border-hover: var(--green-700);
  --btn-outline-text: var(--green-700);
  --btn-outline-bg-hover: var(--green-50);
  --btn-tonal-bg: var(--green-100);
  --btn-tonal-bg-hover: var(--green-200);
  --btn-tonal-text: var(--green-800);
  --btn-danger-bg: var(--red-500);
  --btn-danger-bg-hover: var(--red-600);
  --btn-danger-text: var(--gray-0);
  --btn-radius: var(--radius-pill);

  /* Per-surface: switch (Available offline toggle) */
  --switch-track-off: var(--gray-300);
  --switch-track-on: var(--green-500);
  --switch-thumb: var(--gray-0);

  /* Avatars (decorative identity hues, muted neutrals) */
  --color-avatar-1: #a98a56;
  --color-avatar-2: #6b8f71;
  --color-avatar-3: #a3707f;
  --color-avatar-4: #6f8296;
  --avatar-ring: var(--gray-0);

  /* Thumbnail placeholder grays (one step darker than the grey card) */
  --thumb-bg: var(--gray-50);
  --thumb-block: var(--gray-150);
  --thumb-block-alt: var(--gray-200);
  --thumb-line: var(--gray-200);

  /* Real-source card previews: tiny quiet code on the grey card */
  --thumb-code-size: 5px;
  --thumb-code-leading: 1.6;
  --thumb-code-ink: var(--gray-600);

  /* Snapshot previews: the running app scaled into the thumb area */
  --thumb-snapshot-scale: 0.25;
  --thumb-accent: var(--green-100);
  --thumb-accent-faint: var(--green-50);

  /* Typography: family, sizes, weights, leading, tracking */
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono",
    "Courier New", monospace;

  --text-2xs: var(--size-11);
  --text-xs: var(--size-12);
  --text-sm: var(--size-13);
  --text-base: var(--size-14);
  --text-md: var(--size-15);
  --text-lg: var(--size-16);
  --text-xl: var(--size-18);
  --text-2xl: var(--size-22);
  --text-3xl: var(--size-32);
  --text-display: var(--size-48);
  --text-display-lg: var(--size-56);

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;

  --leading-none: 1.1;
  --leading-tight: 1.25;
  --leading-normal: 1.5;

  --tracking-tight: -0.01em;
  --tracking-normal: 0;
  --tracking-wide: 0.01em;
  --tracking-caps: 0.08em;

  /* Composed type roles (font shorthand: weight size/line-height family).
     Components pick a role, not raw values. */
  --text-role-micro-label: var(--weight-semibold) var(--size-11) /
    var(--leading-tight) var(--font-ui);
  --text-role-title: var(--weight-medium) var(--size-18) / var(--leading-tight)
    var(--font-ui);
  --text-role-section: var(--weight-regular) var(--size-16) /
    var(--leading-tight) var(--font-ui);
  --text-role-heading: var(--weight-regular) var(--size-22) /
    var(--leading-tight) var(--font-ui);
  --text-role-body: var(--weight-regular) var(--size-14) / var(--leading-normal)
    var(--font-ui);
  --text-role-card-name: var(--weight-medium) var(--size-14) /
    var(--leading-tight) var(--font-ui);
  --text-role-meta: var(--weight-regular) var(--size-13) / var(--leading-normal)
    var(--font-ui);
  --text-role-display: var(--weight-medium) var(--size-56) /
    var(--leading-none) var(--font-ui);
  --text-role-code: var(--weight-regular) var(--size-13) / 1.7 var(--font-mono);

  /* Semantic spacing */
  --section-gap: var(--space-6);
  --grid-gap: var(--space-4);
  --control-pad-x: var(--space-6);
  --control-pad-y: var(--space-2);

  /* Radius uses */
  --radius-input: var(--radius-md);
  --radius-card: var(--radius-lg);
  --radius-dialog: var(--radius-xl);
  --radius-chip: var(--radius-pill);
  --radius-button: var(--radius-pill);

  /* Motion uses */
  --motion-fast: var(--duration-fast);
  --motion-base: var(--duration-base);
  --motion-slow: var(--duration-slow);
  --motion-ease: var(--ease-standard);
  --transition-hover: background-color var(--duration-fast)
      var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    box-shadow var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);

  /* Control heights and icon sizes */
  --height-button: var(--space-10);
  --height-button-sm: var(--space-8);
  --height-input: var(--space-12);
  --height-searchbar: var(--space-12);
  --icon-sm: 16px;
  --icon-md: 20px;
  --icon-lg: 24px;

  /* Layout */
  --topbar-height: 64px;
  /* THE MARK, AND THE AVATAR FACING IT ACROSS THE BAR. One number for
     both ends, and it is the app page's logo box: the owner's rule is
     that the mark does not change size or move when you open an app, so
     home's bar is built to the denser page's geometry rather than the
     other way round. --control-h-logo in tokens-compact.css is the same
     --space-10, reached through the same primitive rather than through a
     cross-file reference, because that file belongs to the app page and
     this one is global. bar-geometry.mjs measures the two pages against
     each other, so if the two are ever pointed at different steps, that
     check is what says so rather than somebody's eye.

     The avatar comes with it, at 40 rather than the 32 it was on a
     laptop. A 40px filled tile facing a 32px circle leaves the bar
     visibly heavier on the left, and the app page already pairs 40 with
     40, so following the mark is both the balanced answer and the one
     that keeps the two pages telling the same story. */
  --topbar-mark-size: var(--space-10);
  /* The floor under EACH of the bar's two outer columns, and the reason
     it is one token rather than the 200 and 120 it replaces. The search
     pill is centred in the room between those two columns, and that room
     is only centred on the WINDOW when the columns match. They did not:
     200 against 120 put the pill 40px right of the centreline at every
     desktop width, measured. One value for both is what makes the
     centring true rather than approximately true.

     RE-DERIVED WITH THE MARK, rather than nudged. The floor's one job is
     to hold the brand cluster without clipping the wordmark, so it is
     built from what that cluster actually measures rather than from
     whatever the last number happened to be. Growing the mark from 36 to
     40 grew the cluster from 193 to 197: 8px of padding, the 40px mark,
     8px of gap, and 133px of "Share An App" at --text-role-heading. 197
     plus a deliberate 12px of margin is 209, and the next step up on the
     4px grid everything else here sits on is 212, so the margin lands at
     15px.

     The margin is for the FONT, not for the layout. --font-ui resolves
     to a different face on every platform, so those 133px are a macOS
     measurement and Segoe UI or Roboto will not agree with it exactly.
     15px is about 11% of the wordmark, which covers ordinary variation
     between system faces without reserving room nobody uses.

     Smaller is better here as long as it fits, which is the other reason
     not to leave it high: the floor only binds below about 1128px, and
     below that every pixel it takes is a pixel off the search pill. At
     700px wide, 212 leaves the pill 236px where 232 would have left it
     196.

     The phone breakpoint drops it to the mark plus its ground, because
     down there the wordmark is not drawn and there is nothing to
     reserve. */
  --topbar-side-min: 212px;
  /* The account avatar in the APP PAGE's header action row, which is a
     different pairing and therefore a second token rather than a reuse of
     the one above. There the circle is matched to the logo mark; here it
     is matched to the controls it sits between, and those are taller: the
     Share pill measures 40px and the Download split's shell measures 40px
     too (38px of content inside a hairline each side), while the avatar
     was drawn at the component's own 32px default and read as the one
     shrunken thing in a row of full-height controls.

     It resolves to --control-h-split rather than restating 40, so the
     circle cannot drift from the pills: whatever height that row's
     controls take, the avatar takes. That token lives in
     tokens-compact.css, which the app page loads, and the app page is the
     only surface this token is for. */
  --chrome-avatar-size: var(--control-h-split);
  --search-max-width: 720px;
  --content-max-width: 1200px;
  --card-width: 210px;
  --card-thumb-height: 200px;
  --card-thumb-aspect: 17 / 20;
  --new-card-width: 170px;
  --new-card-height: 225px;
  --rail-width: 232px;
  --dialog-width: 640px;
  --viewport-max-width: 960px;
  --viewport-min-height: 640px;
  /* The cell of the blueprint ground the frame sits on when it has been
     given a size. A size rather than a colour: the rules themselves are
     --color-border-mid on --color-bg-sunken, both of which already
     existed and neither of which needed a new value. Sits with the other
     --viewport-* tokens because it belongs to the same surface. */
  --viewport-grid-cell: var(--space-6);

  /* Z-index scale */
  --z-base: 0;
  --z-sticky-row: 9;
  --z-sticky: 10;
  --z-menu: 30;
  --z-dialog: 50;
  --z-overlay: 60;
  --z-toast: 70;
}

/* ------------------------------------------------------------------ */
/* DARK THEME                                                           */
/* ------------------------------------------------------------------ */

/* Applied when <html data-theme="dark">, which the no-flash line in each
   page's <head> sets from localStorage studio:theme or, while the choice
   is System, from prefers-color-scheme. Light is the :root default above,
   so data-theme="light" needs no block of its own.

   Same names, new values: no token is added here, only the semantic layer
   and the shadow scale are redefined. The primitive ramps stay as they
   are, which is what keeps map marks drawn from them identical in both
   themes. The relationships carry over: one flat ground, surfaces a step
   lighter than it rather than darker, hairlines a quiet step above the
   surface, ink near white with the same three falling steps, and the
   olive accent kept for fills while its ink moves up the ramp so text in
   it still reads on a dark ground. */
:root {
  color-scheme: light;
}

[data-theme="dark"] {
  color-scheme: dark;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-2: 0 1px 3px rgba(0, 0, 0, 0.35), 0 4px 12px rgba(0, 0, 0, 0.3);
  --shadow-3: 0 2px 8px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
  --shadow-4: 0 4px 12px rgba(0, 0, 0, 0.45), 0 16px 40px rgba(0, 0, 0, 0.45);
  --shadow-sticky: 0 2px 4px rgba(0, 0, 0, 0.5);

  /* Backgrounds */
  --color-bg-page: #161618;
  --color-bg-raised: #1e1e21;
  --color-bg-sunken: #232326;
  --color-bg-band: #161618;
  --color-surface: #1e1e21;
  --color-hover: rgba(255, 255, 255, 0.06);
  --color-active: rgba(255, 255, 255, 0.1);
  --color-scrim: rgba(0, 0, 0, 0.6);
  --color-search-fill: #232326;

  /* Borders */
  --color-border-hairline: #2c2c30;
  --color-border: #2c2c30;
  --color-border-mid: #38383c;
  --color-border-strong: #4a4a4e;

  /* Text */
  --color-ink: #f2f2f3;
  --color-ink-secondary: #aeaeb2;
  --color-ink-tertiary: #8e8e93;
  --color-ink-faint: #8e8e93;
  --color-ink-disabled: #5c5c60;
  --color-ink-inverse: #1c1c1e;

  /* Accent */
  --color-accent: var(--green-500);
  --color-accent-hover: var(--green-400);
  --color-accent-pressed: var(--green-600);
  --color-accent-strong: var(--green-400);
  --color-accent-ink: var(--green-300);
  --color-accent-ink-strong: var(--green-200);
  --color-accent-tint: rgba(133, 169, 82, 0.2);
  --color-accent-tint-strong: rgba(133, 169, 82, 0.34);
  --color-accent-tint-faint: rgba(133, 169, 82, 0.1);
  --color-on-accent: var(--gray-0);

  /* Semantic slots */
  --color-link: var(--green-300);
  --color-link-hover: var(--green-200);
  --color-success: var(--green-300);
  --color-danger: #ef6f6f;
  --color-danger-tint: rgba(214, 69, 69, 0.2);
  --color-warning: #dba23c;
  --color-warning-tint: rgba(201, 138, 27, 0.2);
  --color-positive-delta: var(--green-400);

  /* Focus ring */
  --focus-ring-color: var(--green-400);

  /* Card */
  --card-bg: #1e1e21;
  --card-border: #2c2c30;
  --card-border-hover: var(--green-500);

  /* Dialog, menu, input */
  --dialog-bg: #1e1e21;
  --menu-bg: #232326;
  --menu-border: #38383c;
  --input-bg: #161618;
  --input-border: #3e3e42;
  --input-border-focus: var(--green-400);
  --input-placeholder: #8e8e93;

  /* Chip */
  --chip-bg: #2a2a2e;
  --chip-text: #aeaeb2;
  --chip-accent-bg: rgba(133, 169, 82, 0.2);
  --chip-accent-text: var(--green-200);

  /* Drag-and-drop deploy */
  --dropzone-bg: rgba(133, 169, 82, 0.1);
  --dropzone-ink: var(--green-300);
  --upload-track: rgba(133, 169, 82, 0.2);

  /* Tooltip and toast: a raised neutral, lighter than every surface. */
  --tooltip-bg: #3a3a3e;
  --tooltip-text: #f2f2f3;
  --toast-bg: #3a3a3e;
  --toast-text: #f2f2f3;

  /* Segmented control */
  --segmented-bg: #2a2a2e;
  --segmented-selected-bg: rgba(133, 169, 82, 0.26);
  --segmented-selected-text: var(--green-200);
  --segmented-text: #aeaeb2;

  /* Chart */
  --chart-mark: var(--green-400);
  --chart-wash: rgba(133, 169, 82, 0.2);
  --chart-grid: #2c2c30;
  --chart-baseline: #38383c;
  --chart-axis-ink: #aeaeb2;
  --chart-crosshair: #4a4a4e;
  --chart-mark-ring: #1e1e21;

  /* Account status dot */
  --status-active: var(--green-400);
  --status-dormant: #5c5c60;
  --status-never: #5c5c60;

  /* Code browser */
  --code-bg: #161618;
  --code-text: #e3e3e4;
  --code-gutter: #5c5c60;
  --filetree-bg: #1e1e21;
  --filetree-selected-bg: rgba(133, 169, 82, 0.2);
  --filetree-selected-text: var(--green-200);

  /* Buttons. The solid fill stays the same green, so its white label
     keeps the contrast it has in light. */
  --btn-primary-bg: var(--green-600);
  --btn-primary-bg-hover: var(--green-500);
  --btn-primary-bg-pressed: var(--green-700);
  --btn-primary-text: var(--gray-0);
  --btn-outline-border: #3e3e42;
  --btn-outline-border-hover: var(--green-400);
  --btn-outline-text: var(--green-300);
  --btn-outline-bg-hover: rgba(133, 169, 82, 0.1);
  --btn-tonal-bg: rgba(133, 169, 82, 0.2);
  --btn-tonal-bg-hover: rgba(133, 169, 82, 0.3);
  --btn-tonal-text: var(--green-200);

  /* Switch */
  --switch-track-off: #4a4a4e;
  --switch-track-on: var(--green-500);
  --switch-thumb: var(--gray-0);

  --avatar-ring: #1e1e21;

  /* Thumbnails */
  --thumb-bg: #232326;
  --thumb-block: #2c2c30;
  --thumb-block-alt: #38383c;
  --thumb-line: #38383c;
  --thumb-code-ink: #aeaeb2;
  --thumb-accent: rgba(133, 169, 82, 0.2);
  --thumb-accent-faint: rgba(133, 169, 82, 0.1);
}
