/* ==========================================================================
   ASTER — Design Tokens
   A two-layer system: spacious "page layer" + dense "app layer".
   See DESIGN-SYSTEM.md for the rules that govern these values.

   Load order:
     1. aster-tokens.css      (this file — declares the fonts below)
     2. aster-components.css

   All fonts are SELF-HOSTED, from /fonts on this origin. They used to come
   from api.fontshare.com and rsms.me, which meant two third-party origins on
   every page load, no integrity guarantee, and a Content-Security-Policy that
   had to name someone else's CDN. Serving them ourselves closes all three.

   §2 says never substitute a system stack for Clash Display: if it fails, fall
   back to Inter 600. That is what --font-display encodes, and self-hosting
   makes the failure it was written for — a blocked or slow CDN — no longer
   reachable without the whole origin being down.
   ========================================================================== */

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-var-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Clash Display";
  src: url("/fonts/clash-display-600-latin.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Satoshi";
  src: url("/fonts/satoshi-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("/fonts/satoshi-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("/fonts/satoshi-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("/fonts/satoshi-900.woff2") format("woff2");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
:root {
  /* ======================================================================
     TYPOGRAPHY
     ====================================================================== */
  --font-display: "Clash Display", "Inter", sans-serif;   /* ≥32px headings ONLY */
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
  --font-marketing: "Satoshi", var(--font-sans);
  --fw-regular: 400;   /* prose only */
  --fw-medium: 500;    /* UI default */
  --fw-semibold: 600;  /* all headings (except marketing display) */
  --fw-bold: 700;      /* marketing display titles */
  --fw-black: 900;     /* marketing display hero */

  /* ---- Page layer: ratio line-heights ---- */
  --t-display-xl: 64px;  --t-display-xl-lh: 70px; --t-display-xl-ls: 0.026em;
  --t-display-lg: 48px;  --t-display-lg-lh: 53px; --t-display-lg-ls: 0.033em;
  --t-display-md: 32px;  --t-display-md-lh: 38px; --t-display-md-ls: 0.02em;
  --t-hero-ls: -0.035em; /* marketing display tracking */
  --t-lead: 20px;        --t-lead-lh: 28px;       --t-lead-ls: -0.012em;
  --t-prose-lg: 18px;    --t-prose-lg-lh: 26px;   --t-prose-lg-ls: -0.02em;
  --t-prose: 16px;       --t-prose-lh: 22px;      --t-prose-ls: -0.02em;
  --t-overline: 11px;    --t-overline-lh: 12px;   --t-overline-ls: 0.02em;

  /* ---- App layer: integer grid line-heights ---- */
  --t-title-lg: 24px;    --t-title-lg-lh: 28px;   --t-title-lg-ls: -0.02em;
  --t-title: 20px;       --t-title-lh: 24px;      --t-title-ls: -0.02em;
  --t-heading: 16px;     --t-heading-lh: 20px;    --t-heading-ls: -0.02em;
  --t-body: 14px;        --t-body-lh: 20px;       --t-body-ls: -0.01em;  /* THE default */
  --t-label: 12px;       --t-label-lh: 16px;      --t-label-ls: -0.01em;
  --t-micro: 11px;       --t-micro-lh: 11px;      --t-micro-ls: 0.02em;

  /* ======================================================================
     NEUTRALS
     ====================================================================== */
  --n-0:   #ffffff;
  --n-25:  #fbfbfb;   /* sidebar, subtle band, selected tab */
  --n-50:  #f6f7f7;   /* hover fill, mockup tray */
  --n-75:  #f1f2f3;   /* sunken */
  --n-100: #eeeff1;   /* THE divider / grid-line */
  --n-150: #e6e7ea;
  --n-200: #d9dade;
  --n-300: #a2a4a7;
  --n-400: #898a8d;
  --n-600: #505155;
  --n-800: #2a2b2f;
  --n-900: #14151a;   /* PRIMARY BUTTON FILL */
  --n-950: #0b0c0d;
  --transparent: transparent;

  /* ---- Ink ramp: black at N% opacity ---- */
  --ink:   #101112;
  --ink-2: rgba(0, 0, 0, 0.63);
  --ink-3: rgba(0, 0, 0, 0.55);
  --ink-4: rgba(0, 0, 0, 0.50);
  --ink-5: rgba(0, 0, 0, 0.35);
  --ink-on-dark: #f1f2f3;

  /* ---- Interaction alphas ---- */
  --a-1: rgba(0, 0, 0, 0.02);   /* hover */
  --a-2: rgba(0, 0, 0, 0.04);   /* active / selected */
  --a-3: rgba(0, 0, 0, 0.06);   /* inset ring */
  --a-4: rgba(0, 0, 0, 0.09);   /* pressed */
  --a-5: rgba(0, 0, 0, 0.14);  /* the line inside a modal's band (§16.53) */

  /* ---- Semantic surfaces ---- */
  --bg-canvas: var(--n-0);
  /* Canvas field texture. Far fainter than the ink ramp: --ink-5 is a
     perceptible 1px edge, and a grid of 1px dots at that weight reads as
     content. Light dots on a dark pane, not a darker mark. Below 0.06 a
     1px dot does not render on most displays. */
  --canvas-dot: rgba(0, 0, 0, 0.08);
  --bg-subtle: var(--n-25);
  --bg-hover:  var(--n-50);
  --bg-sunken: var(--n-75);
  --border:    var(--n-100);
  --border-strong: var(--n-150);

  /* ======================================================================
     ACCENT  — swap this block to re-theme the entire system
     ====================================================================== */
  --accent-50:   color-mix(in srgb, var(--accent) 7%, #fff);
  --accent-100:  color-mix(in srgb, var(--accent) 14%, #fff);
  --accent-200:  color-mix(in srgb, var(--accent) 28%, #fff);
  --accent-400:  color-mix(in srgb, var(--accent) 60%, #fff);
  --accent-500:  color-mix(in srgb, var(--accent) 88%, #fff);   /* emphasis text: eyebrows, metric values */
  --accent:      #9333ea;   /* fills, focus ring, active state */
  --accent-hover: color-mix(in srgb, var(--accent) 82%, #000);
  --accent-fg:   #ffffff;   /* legible on --accent; recomputed per preset */

  /* Accent-FILLED buttons. The fill is the accent *by reference*, so the
     button on a page and the swatch in Settings → Appearance are the same
     value and cannot drift apart — an earlier version deepened this per preset
     for label contrast and the two visibly stopped matching. The label is
     always white; see §16.19 for what that costs on the lighter presets. */
  --accent-btn:       var(--accent);
  --accent-btn-hover: var(--accent-hover);
  --accent-btn-fg:    #ffffff;

  /* Alternate presets — swap --accent / --accent-hover / --accent-500 to use */
  --preset-purple: #9333ea;
  --preset-blue:   #266df0;
  --preset-cyan:   #00b9eb;
  --preset-green:  #00d17e;
  --preset-amber:  #f5a300;
  --preset-orange: #f97514;
  --preset-pink:   #fa4b94;

  /* ======================================================================
     SEMANTIC
     ====================================================================== */
  --success: #00d17e; --success-strong: #02ad6e; --success-deep: #007d53;
  --success-bg: #e0fced; --success-ring: #cbf7e1;
  --warning: #f5a300; --warning-strong: #cf8300; --warning-deep: #874d00;
  --warning-bg: #fff3cc; --warning-ring: #ffe59e;
  --danger: #ff5454;  --danger-strong: #eb3b3b;  --danger-deep: #ba2525;
  --danger-bg: #ffebeb;  --danger-ring: #ffdcdb;
  --info: #266df0;    --info-strong: #215bc4;    --info-deep: #215bc4;
  --info-bg: #e5eeff;    --info-ring: #d6e5ff;

  /* Delta pills */
  --delta-up-bg: rgba(0, 188, 125, 0.15); --delta-up-fg: #009966;
  --delta-down-bg: var(--danger-bg);      --delta-down-fg: var(--danger-deep);

  /* ======================================================================
     TAG PALETTE — 12 hues. fill + ring (one step darker) + deep text.
     ====================================================================== */
  --tag-grey-bg:    #f6f7f7; --tag-grey-ring:    #eeeff1; --tag-grey-fg:    #505155;
  --tag-blue-bg:    #e5eeff; --tag-blue-ring:    #d6e5ff; --tag-blue-fg:    #215bc4;
  --tag-cyan-bg:    #ddf7ff; --tag-cyan-ring:    #d0eff7; --tag-cyan-fg:    #056c87;
  --tag-green-bg:   #e0fced; --tag-green-ring:   #cbf7e1; --tag-green-fg:   #007d53;
  --tag-lime-bg:    #f4fbcb; --tag-lime-ring:    #e9f797; --tag-lime-fg:    #536300;
  --tag-yellow-bg:  #fdf7c4; --tag-yellow-ring:  #fcef7e; --tag-yellow-fg:  #665a00;
  --tag-amber-bg:   #fff3cc; --tag-amber-ring:   #ffe59e; --tag-amber-fg:   #874d00;
  --tag-orange-bg:  #feeee1; --tag-orange-ring:  #fee0c8; --tag-orange-fg:  #9e3f00;
  --tag-red-bg:     #ffebeb; --tag-red-ring:     #ffdcdb; --tag-red-fg:     #ba2525;
  --tag-pink-bg:    #feecf3; --tag-pink-ring:    #fdddea; --tag-pink-fg:    #b81c5d;
  --tag-magenta-bg: #fdedff; --tag-magenta-ring: #fad6ff; --tag-magenta-fg: #9c1bab;
  --tag-purple-bg:  #f5f0ff; --tag-purple-ring:  #e8ddfe; --tag-purple-fg:  #6238b5;

  /* ======================================================================
     RADIUS
     ====================================================================== */
  --r-xs: 2px;
  --r-sm: 6px;      /* checkbox, keycap */
  --r-chip: 7px;    /* tags */
  --r-md: 8px;      /* buttons, inputs, tabs, tooltips */
  --r-lg: 9px;      /* nav rows, 32px fields */
  --r-xl: 12px;     /* popovers, small cards, page CTA */
  --r-2xl: 16px;    /* cards, modals */
  --r-3xl: 20px;    /* pricing, media panels */
  --r-4xl: 24px;    /* feature panels */
  --r-5xl: 32px;    /* hero panels */
  --r-squircle: 30%;
  --r-pill: 999px;

  /* ======================================================================
     SPACING — one scale, three regions
     ====================================================================== */
  --s-1: 2px;   --s-2: 4px;   --s-3: 6px;   --s-4: 8px;   --s-5: 10px;
  --s-6: 12px;  --s-7: 16px;  --s-8: 20px;  --s-9: 24px;  --s-10: 28px;
  --s-11: 32px; --s-12: 40px; --s-13: 48px; --s-14: 56px; --s-15: 64px;
  --s-16: 80px; --s-17: 96px; --s-18: 112px; --s-19: 128px;

  /* ---- Control heights ---- */
  --h-chip: 22px;
  --h-control-sm: 24px;   /* popover footer */
  --h-control: 28px;      /* app default */
  --h-control-lg: 32px;
  --h-row: 36px;
  --h-row-head: 40px;
  --h-cta: 48px;          /* page default */
  --h-topbar: 49px;
  --h-navbar: 52px;
  --icon: 16px;
  --icon-lg: 18px;

  /* ---- Layout ---- */
  --container: 1000px;
  --container-text: 896px;
  --container-wide: 1200px;
  --w-dialog-sm:   440px;                        /* .ar-modal default, Fulfillment */
  --w-dialog-form: 560px;                        /* shell-framed forms: contact, deal */
  --w-dialog-task: 660px;
  --w-dialog-note: min(840px, calc(100vw - 64px));
  --col-half: 528px;
  --gutter: clamp(20px, 6vw, 100px);
  --section-y: 80px;
  --section-y-hero: 112px;
  --stack-gap: 64px;
  --copy-gap: 20px;
  --sidebar: 260px;

  /* ======================================================================
     ELEVATION — never write a raw box-shadow outside this list
     ====================================================================== */
  --shadow-ring: inset 0 0 0 1px var(--a-3);
  --shadow-hairline: 0 0 0 0.5px rgba(0, 0, 0, 0.12);

  /* BAND AND LINE — how a floating surface draws its edge (§16.53).

     An overlay does not put a rim on its own edge. It draws a BAND inset from
     that edge with a 1px LINE at the band's inner boundary. The line is the
     drawn edge; the band is what gives it clean space to sit in, clear of the
     blurred outer shadow. Measured off Attio's command palette, which is where
     this shape comes from.

     THE BAND WIDTH IS GEOMETRY, NOT TASTE. An inset shadow's inner corner
     radius is the outer radius minus its spread, so --r-2xl - --edge-band =
     --r-xl keeps the two curves concentric and parallel through the corner.
     The palette spends the same 4px as padding on its shell and gives its inner
     pane --r-xl, for exactly the same arithmetic. Change one of the three
     numbers and the curves cross.

     WHAT THE BAND IS MADE OF depends on whether the surface is see-through.
     The palette's shell is translucent over a scrim, so 4px of shell IS the
     band and the pane draws the line outward into it (--shadow-line). A modal
     is opaque, so a band of its own fill would be invisible: the band is
     --bg-sunken, the surface one step beneath the pane, and the line is --a-5 —
     the same alpha that used to sit on the modal's rim, moved inward to where
     it finally has a band to contrast with rather than the fill. Measured on
     white: pane 255, band 241, line 219.

     THE BAND MUST BE OPAQUE. Both layers are inset, so the deeper one paints
     under the whole band, not just under its own 1px: with an alpha band the
     line shows through and comes out lighter than the band it is meant to
     divide. That is why this is a surface token and not an --a-N. */
  --edge-band: 4px;
  --shadow-band:
    inset 0 0 0 var(--edge-band) var(--bg-sunken),
    inset 0 0 0 calc(var(--edge-band) + 1px) var(--a-5);
  --shadow-line: 0 0 0 1px var(--a-3);

  --shadow-raised:
    0 0 0 1px rgba(28, 40, 64, 0.08),
    0 1px 2px 0 rgba(28, 40, 64, 0.08),
    0 2px 6px 0 rgba(28, 40, 64, 0.04);

  --shadow-popover:
    0 0 0 1px rgba(28, 40, 64, 0.04),
    0 4px 8px -4px rgba(28, 40, 64, 0.12),
    0 4px 12px -2px rgba(24, 41, 75, 0.16);

  --shadow-overlay:
    0 8px 28px -6px rgba(28, 40, 64, 0.12),
    0 18px 88px -4px rgba(28, 40, 64, 0.16),
    0 0 1px 0 rgba(28, 40, 64, 0.16);

  --shadow-float:
    0 14px 30px 0 rgba(0, 0, 0, 0.05),
    0 55px 55px 0 rgba(0, 0, 0, 0.04),
    0 125px 75px 0 rgba(0, 0, 0, 0.03),
    0 222px 89px 0 rgba(0, 0, 0, 0.01);

  --shadow-accent:
    0 3px 7px 0   color-mix(in srgb, var(--accent) 8%, transparent),
    0 13px 13px 0 color-mix(in srgb, var(--accent) 6%, transparent),
    0 29px 18px 0 color-mix(in srgb, var(--accent) 4%, transparent),
    0 52px 21px 0 color-mix(in srgb, var(--accent) 2%, transparent);

  /* Button-specific glows */
  --glow-accent:
    inset 0 0 0 1px var(--a-3),
    0 2px 4px -2px color-mix(in srgb, var(--accent) 12%, transparent),
    0 3px 6px -2px color-mix(in srgb, var(--accent) 8%, transparent);
  --glow-danger:
    inset 0 0 0 1px var(--a-3),
    0 2px 4px -2px color-mix(in srgb, var(--danger) 12%, transparent),
    0 3px 6px -2px color-mix(in srgb, var(--danger) 8%, transparent);

  /* The edge on a keycap sitting inside a filled button.

     Named for the surface it sits on — a filled button — and not for a theme,
     because the two fills it lands on disagree about what the theme means.
     .as-btn--accent is the accent in both themes with white text throughout;
     .as-btn--primary is --n-900, which is #14151a in light and #f1f2f3 in dark.
     A ring named "on dark" was white 24% for both, and on the primary button in
     dark that is white on near-white: 1.03:1, invisible.

     currentColor is what makes one value serve both. A filled button already
     declares a text colour legible on its own fill — that is what makes it a
     button — and a keycap inheriting that colour gets a ring guaranteed to
     contrast with whatever is behind it, with no theme named anywhere.
     Resolved at the point of use, the same way --shadow-ring resolves --a-3
     per theme. The keycap must therefore inherit its colour; app.css does that
     in the same rule that applies this. */
  --kbd-ring: inset 0 0 0 1px color-mix(in srgb, currentColor 24%, transparent);

  /* Halo that fuses a screenshot into the page */
  --halo: 0 0 4px 4px var(--n-50);

  /* ======================================================================
     MOTION
     ====================================================================== */
  --dur-fast: 140ms;
  --dur-base: 160ms;
  --dur-slow: 200ms;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --transition-ghost: background-color var(--dur-fast) var(--ease),
                      box-shadow var(--dur-fast) var(--ease),
                      color var(--dur-fast) var(--ease);
  --transition-button: background-color var(--dur-slow) var(--ease),
                       color var(--dur-slow) var(--ease),
                       box-shadow var(--dur-slow) var(--ease),
                       transform var(--dur-slow) var(--ease);

  /* ======================================================================
     EFFECTS
     ====================================================================== */
  --glass-bg: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.75));
  --glass-blur: blur(8px);
  --palette-bg: rgba(255, 255, 255, 0.6);
  --palette-blur: blur(15px);
  --fade-to-canvas: linear-gradient(rgba(255, 255, 255, 0) 0%, var(--n-0) 83%);
  --panel-gradient: linear-gradient(var(--n-0) 0%, var(--n-50) 100%);

  /* Unauthenticated login island only (§16.73). Clearer than --glass-bg so the
     clouds read through; the edge is a white hairline, not --shadow-line, because
     a 4px band of glass is invisible against a photograph. Not an elevation. */
  --auth-ink: #101112;
  --auth-ink-2: rgba(0, 0, 0, 0.63);
  --auth-ink-3: rgba(0, 0, 0, 0.55);
  --auth-ink-4: rgba(0, 0, 0, 0.50);
  --auth-n-0: #ffffff;
  --auth-n-900: #14151a;
  --auth-a-1: rgba(0, 0, 0, 0.02);
  --auth-a-3: rgba(0, 0, 0, 0.06);
  --auth-glass-bg: linear-gradient(rgba(255, 255, 255, 0.38), rgba(255, 255, 255, 0.55));
  --auth-glass-blur: blur(16px);
  --shadow-auth-edge: 0 0 0 1px rgba(255, 255, 255, 0.78);
  --auth-shadow-ring: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  --auth-shadow-raised:
    0 0 0 1px rgba(28, 40, 64, 0.08),
    0 1px 2px 0 rgba(28, 40, 64, 0.08),
    0 2px 6px 0 rgba(28, 40, 64, 0.04);
  --auth-shadow-float:
    0 14px 30px 0 rgba(0, 0, 0, 0.05),
    0 55px 55px 0 rgba(0, 0, 0, 0.04),
    0 125px 75px 0 rgba(0, 0, 0, 0.03),
    0 222px 89px 0 rgba(0, 0, 0, 0.01);
}

/* ==========================================================================
   DARK THEME
   The sidebar goes DARKER than the canvas. That inversion is the signature.
   ========================================================================== */
[data-theme="dark"] {
  --bg-canvas: #101112;
  --canvas-dot: rgba(255, 255, 255, 0.10);
  --bg-subtle: #0b0c0d;
  --bg-hover:  #17181a;
  --bg-sunken: #1b1c1f;
  --border:    #1b1c1f;
  --border-strong: rgba(255, 255, 255, 0.09);

  --n-0:   #101112;
  --n-25:  #0b0c0d;
  --n-50:  #17181a;
  --n-75:  #1b1c1f;
  --n-100: #1b1c1f;
  --n-150: rgba(255, 255, 255, 0.09);
  --n-200: #2a2b2f;
  --n-300: #6d6e72;
  --n-400: #898a8d;
  --n-600: #a2a4a7;
  --n-800: #d9dade;
  --n-900: #f1f2f3;
  --n-950: #ffffff;

  --ink:   #f1f2f3;
  --ink-2: rgba(255, 255, 255, 0.60);
  --ink-3: rgba(255, 255, 255, 0.55);
  --ink-4: rgba(255, 255, 255, 0.45);
  --ink-5: rgba(255, 255, 255, 0.30);
  --ink-on-dark: #101112;

  --a-1: rgba(255, 255, 255, 0.04);
  --a-2: rgba(255, 255, 255, 0.05);
  --a-3: rgba(255, 255, 255, 0.07);
  --a-4: rgba(255, 255, 255, 0.09);
  --a-5: rgba(255, 255, 255, 0.14);

  --accent-50:  color-mix(in srgb, var(--accent) 10%, var(--n-0));
  --accent-100: color-mix(in srgb, var(--accent) 17%, var(--n-0));
  --accent-200: color-mix(in srgb, var(--accent) 28%, var(--n-0));
  --accent-400: color-mix(in srgb, var(--accent) 60%, #fff);
  --accent-500: color-mix(in srgb, var(--accent) 72%, #fff);
  --accent:     #a855f7;
  --accent-hover: color-mix(in srgb, var(--accent) 72%, #fff);

  --shadow-ring: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
  --shadow-hairline: 0 0 0 0.5px rgba(255, 255, 255, 0.09);
  --shadow-raised:
    inset 0 0 0 1px #212224,
    0 1px 3px 0 rgba(0, 0, 0, 0.12),
    0 2px 6px 0 rgba(0, 0, 0, 0.08);
  --shadow-popover:
    0 0 0 1px rgba(255, 255, 255, 0.07),
    0 4px 8px -4px rgba(0, 0, 0, 0.4),
    0 4px 12px -2px rgba(0, 0, 0, 0.5);
  --shadow-overlay:
    0 8px 28px -6px rgba(0, 0, 0, 0.5),
    0 18px 88px -4px rgba(0, 0, 0, 0.6),
    0 0 1px 0 rgba(255, 255, 255, 0.1);
  --shadow-float:
    0 14px 30px 0 rgba(0, 0, 0, 0.3),
    0 55px 55px 0 rgba(0, 0, 0, 0.2),
    0 125px 75px 0 rgba(0, 0, 0, 0.15);

  --glass-bg: linear-gradient(rgba(23, 24, 26, 0.5), rgba(23, 24, 26, 0.75));
  --palette-bg: rgba(23, 24, 26, 0.6);
  --fade-to-canvas: linear-gradient(rgba(16, 17, 18, 0) 0%, #101112 83%);
  --panel-gradient: linear-gradient(#17181a 0%, #101112 100%);
  --halo: 0 0 4px 4px #17181a;

  /* Dark tag palette: deep fill, mid ring, bright text */
  --tag-grey-bg:    #17181a; --tag-grey-ring:    #212224; --tag-grey-fg:    #d9dade;
  --tag-blue-bg:    #12233f; --tag-blue-ring:    #1b3560; --tag-blue-fg:    #80acff;
  --tag-cyan-bg:    #12333a; --tag-cyan-ring:    #1a4650; --tag-cyan-fg:    #a9ebfc;
  --tag-green-bg:   #1d4034; --tag-green-ring:   #244a3a; --tag-green-fg:   #a7f2cf;
  --tag-lime-bg:    #2f3802; --tag-lime-ring:    #3b4217; --tag-lime-fg:    #d7eb67;
  --tag-yellow-bg:  #373313; --tag-yellow-ring:  #423e17; --tag-yellow-fg:  #f5e242;
  --tag-amber-bg:   #3a2d12; --tag-amber-ring:   #523817; --tag-amber-fg:   #ffd269;
  --tag-orange-bg:  #432410; --tag-orange-ring:  #593217; --tag-orange-fg:  #ffbf9e;
  --tag-red-bg:     #4e1b28; --tag-red-ring:     #692623; --tag-red-fg:     #ffd1d1;
  --tag-pink-bg:    #4e1b30; --tag-pink-ring:    #642640; --tag-pink-fg:    #ffbfda;
  --tag-magenta-bg: #3a1440; --tag-magenta-ring: #4e1c56; --tag-magenta-fg: #f6bdfc;
  --tag-purple-bg:  #251a43; --tag-purple-ring:  #33245c; --tag-purple-fg:  #d8c4ff;
}

/* ==========================================================================
   BASE RESET
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: var(--t-body-lh);
  letter-spacing: var(--t-body-ls);
  font-weight: var(--fw-medium);
  font-feature-settings: "cv05" 1;
  color: var(--ink);
  background: var(--bg-canvas);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; }
svg { stroke-width: 1.5; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

/* Focus: 1px accent ring, offset 1px. Never remove without a replacement. */
:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 1px;
}

/* Hidden native scrollbars inside custom scroll areas */
[data-scroll-area] { scrollbar-width: none; }
[data-scroll-area]::-webkit-scrollbar { display: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
