/*
 * jadilah.css — the Jadilah template's design system in one sheet.
 *
 * Every tenant app links it from the Jadilah host in app.html
 * (/template/v1/jadilah.css) before its own CSS, so a change here reaches
 * every tenant with the next Jadilah release and no tenant deploy.
 * `npm run build:app` inlines these imports (scripts/build-template-css.mjs).
 *
 * Order matters: tokens MUST load before base + components so var()
 * lookups resolve.
 */

/*
 * tokens.css — the Jadilah template's design tokens. Served to every tenant
 * inside /template/v1/jadilah.css on the Jadilah host (template/styles/
 * jadilah.css); no tenant repo holds a copy.
 *
 * Contract enforced by convention:
 *   - Every visual property in components/*.css and in route/component
 *     <style> blocks MUST read from a token defined here. No hardcoded
 *     colors, radii, spacing, fonts, shadows, or durations outside this
 *     file. A `var(--token, #fallback)` is a hardcoded value wearing a
 *     costume — it pins the old palette and silently survives a reskin.
 *     Write `var(--token)` and add the token here if it is missing.
 *   - Token names describe ROLE (--color-accent), not appearance
 *     (--color-gold). Visual descriptions rot the moment the palette
 *     swaps.
 *   - Browser floor: Safari 13+, Chrome 49+, Firefox 31+, Edge 79+.
 *     IE11 not supported. Custom properties (`var(--foo)`) and standard
 *     selectors only — no :has, :where, @container.
 *
 * A tenant's look is three layers, each loaded after the one before:
 *   1. this sheet — the template, the same for every tenant;
 *   2. the design page's colour, background and font, which Jadilah serves
 *      at /api/design/get-looks?slug=<slug> (api/design/theme.ts);
 *   3. the tenant's own app/src/lib/styles/tokens.css: only what differs.
 * Version 1 only adds. Never rename or remove a token here or a [data-*]
 * selector in components/: a tenant reads them without a deploy of its own.
 * Night mode's screen layer lives in night-mode.css; its control-edge
 * compensation (html[data-night-mode]) follows the first :root block.
 *
 * The design language lives in the account-level design brief;
 * values here implement it. Don't change one without the other.
 *
 * ───────────────────────────────────────────────────────────────────────
 * Jadilah — a chat app people already know how to use.
 *
 * Operator directive, 2026-09-26: the signed-in app mirrors WhatsApp 1:1 —
 * WhatsApp Web at desktop widths (>= 840px) and the WhatsApp iOS app
 * (Liquid Glass) on phone and tablet. Four things stay ours:
 *
 *   1. THE 1100px SHELL. WhatsApp Web runs full-bleed; ours caps at 1100px.
 *   2. THE 382/618 SPLIT. List and detail panes keep the golden ratio.
 *   3. THE NAVIGATION. The iOS floating tab bar at every width; on desktop
 *      it floats at the bottom of the list pane.
 *   4. THE PALETTE. Gold carries every signal WhatsApp's green carries: the
 *      unread badge, send button, outgoing bubble, selected chip, switch-on.
 *      The read tick stays blue. Never paint WhatsApp's greens.
 *
 * Everything else — geometry, type, corners, states, motion — follows the
 * measured specs (WhatsApp Web's own CSS; Apple HIG and WhatsApp iOS
 * references). The "WhatsApp geometry" section below holds those values;
 * iOS overrides for < 840px live in chat-surface.css.
 *
 * LIGHT ONLY (operator directive, 2026-07-25). Only two breakpoints exist,
 * max-width 839.98px and 639.98px (see "The scale"); desktop is the base.
 */

:root {
  /* Refuse UA forced darkening (Android Chromium Auto Dark, etc.).
     `only light` is the opt-out; plain `light` is not. */
  color-scheme: only light;

  /* ───── Color ─────
     A white page with a warm ramp beneath it (r > g > b by a hair) so the gold
     sits in the same temperature family as the surfaces instead of floating on
     them. The page is pure #fff by directive; the INK is not pure #000 —
     maxed black-on-white glares, warm ink reads soft on paper.

     The ramp has three levels, not two. --color-bg is the MARKETING
     page and the parent of every panel. --color-surface is the panel: the chat
     list, a card, the app bar. --color-canvas is the ground those panels sit
     ON — the conversation, the detail canvas — and it is the one value that
     makes the product read as a chat app rather than a form on a white sheet.
     --color-surface-alt is the neutral light-grey hover/selection step inside
     a white panel.

     Contrast ratios are measured against --color-bg unless stated. */
  --color-bg: #ffffff;            /* page ground — white */
  --color-surface: #ffffff;       /* PANELS — the chat list, cards, the app bar,
                                     a message bubble from the other side. White,
                                     and it earns its edge from the canvas behind
                                     it plus --shadow-xs, not from a hairline. */
  --color-canvas: #e9e3d8;        /* THE GROUND BEHIND THE PANELS — conversation
                                     wallpaper, detail canvas. Warm paper in the
                                     same family as the gold, so a white bubble
                                     reads as laid on it (1.28:1 tonal step, plus
                                     a one-pixel contact shadow — the same
                                     two-part trick WhatsApp uses).
                                     Ink measured ON this: --color-fg 14.6:1,
                                     --color-muted 5.2:1 (AA), --color-subtle
                                     3.9:1 — icons and non-essential metadata
                                     only, exactly as on --color-surface-alt.
                                     Anything that must be READ here takes
                                     --color-muted. */
  --color-surface-alt: #f5f5f5;   /* neutral hover, selection and subtle fills in a
                                     white panel */
  --color-fg: #14120e;            /* primary text, primary buttons — 18.7:1 AAA */
  --color-fg-on-accent: #14120e;  /* ink on the GOLD fill — 9.5:1 AAA.
                                     Dark, not white: white on the brand gold is
                                     1.97:1 and fails. Scoped to the accent on
                                     purpose — see --color-fg-on-dark. */
  --color-fg-on-dark: #ffffff;    /* ink on a DARK-filled control: success,
                                     danger, info, or any other saturated fill.
                                     These need the opposite ink from the gold,
                                     and reusing --color-fg-on-accent on them
                                     put near-black on #2c7830 at 3.42:1. One
                                     token per ground, not one token for "on a
                                     fill". */
  --color-muted: #625b50;         /* secondary text, captions — 6.7:1 AA */
  --color-muted-aaa: #46413a;     /* secondary text where AAA is required — 10.1:1 */
  --color-subtle: #756e63;        /* tertiary text, icons — 5.0:1 on both
                                     --color-bg and --color-surface (they are
                                     the same white), 4.3:1 on
                                     --color-surface-alt, 3.9:1 on
                                     --color-canvas.

                                     That last number is the one honest caveat in
                                     this palette. On a light theme the hover row
                                     is DARKER than the page, so it eats contrast
                                     instead of adding it, and a three-step ink
                                     ramp cannot have its tertiary step clear
                                     4.5:1 on a tinted row while still reading as
                                     tertiary — any value that does is visually
                                     indistinguishable from --color-muted.
                                     So: on --color-surface-alt this token is for
                                     ICONS and non-essential metadata, which WCAG
                                     floors at 3:1. Anything that must be READ on
                                     a hover row takes --color-muted. */
  --color-border: rgba(20, 18, 14, 0.12);           /* hairline — a row divider,
                                                       a pane edge. Softer than
                                                       the 0.16 the white-on-white
                                                       build needed: a panel now
                                                       gets its separation from
                                                       --color-canvas behind it,
                                                       so the line only has to
                                                       divide siblings. A chat
                                                       list with a heavy rule
                                                       under every row reads as a
                                                       table, not a list.
                                                       Decorative by WCAG 1.4.11
                                                       — a CONTROL edge takes
                                                       --color-border-control. */
  --color-border-strong: rgba(20, 18, 14, 0.26);    /* emphasized hairline, divider */
  --color-border-control: rgba(20, 18, 14, 0.46);   /* THE EDGE OF AN INTERACTIVE
                                     CONTROL — input, select, checkbox, radio,
                                     switch, secondary button. WCAG 1.4.11 holds
                                     these to 3:1 against their surroundings and
                                     --color-border (1.4:1) was tuned for a
                                     different job: separating two white planes,
                                     where a decorative edge is genuinely exempt.
                                     Reusing it made the OFF state of every
                                     boolean control in the product a 1.8:1
                                     rectangle. This resolves to #939290, 3.1:1
                                     on white and 3.0:1 on --color-surface-alt.
                                     On --color-canvas it is 2.96:1 — a control
                                     edge laid straight on the conversation
                                     ground misses 1.4.11 by a hair, so put the
                                     control on a panel there. Cards keep
                                     --color-border. */
  --color-grid: rgba(20, 18, 14, 0.055);            /* engineering-paper grid on
                                                       the PAGE ground. A flat
                                                       white card interrupts it,
                                                       which is what makes the
                                                       card read as a plate laid
                                                       on the sheet — no tint and
                                                       no shadow needed.
                                                       Chart gridlines keep this
                                                       too; a ruled axis is
                                                       genuinely a line. */
  --color-dot: rgba(20, 18, 14, 0.13);              /* PAGE-GROUND dot matrix —
                                                       the same texture role as
                                                       --color-grid, in the
                                                       hero mural's own idiom so
                                                       the artwork and the page
                                                       below it read as one
                                                       surface instead of dots
                                                       meeting a ruler.
                                                       Deliberately ~2.4x the
                                                       grid's alpha: at 16px
                                                       pitch a 2px dot covers
                                                       ~1.2% of its cell where a
                                                       1px cross-hatch covers
                                                       ~6%, so matching alphas
                                                       would make the dots
                                                       vanish. Equal INK, not
                                                       equal alpha. */
  /* THE dot field: the conversation wallpaper and the landing page share
     this one texture, so tuning it here changes both. */
  --dot-field: radial-gradient(circle at center, var(--color-dot) 1px, transparent 1.25px);
  --dot-pitch: 16px;
  /* The detail pane's and conversation's ground: ivory under the dot field,
     a breath off white, so the white cards and bubbles on it read as laid on
     paper. As close to white as it goes while still warm: #fcfaf6 read as
     too far from white, #fffefa as too yellow. */
  --color-ground: #fffefc;
  --dot-ground: var(--dot-field) 0 0 / var(--dot-pitch) var(--dot-pitch), var(--color-ground);
  --color-accent: #d8b46e;        /* THE brand gold: the bright metallic gold
                                     of the owner's reference (was #b8892a).
                                     Fills, borders, marks, the
                                     mural's warm channel — anything where the
                                     gold is a SIGNAL rather than a letterform. */
  --color-accent-ink: #846013;    /* The same gold darkened for TEXT on a light
                                     ground, and the reason the brand gold is not
                                     used for both. #d8b46e set as type on white
                                     is 1.97:1 and fails AA outright; this is
                                     5.7:1 on --color-bg and 4.9:1 on the hover
                                     row. Rule: `color:` takes --color-accent-ink,
                                     `background`/`border` take --color-accent. */
  --color-accent-hover: #b5975c;  /* the fill 16% darker, for FILLS;
                                     --color-fg-on-accent is 6.7:1 on it */
  --color-accent-ink-hover: #6b4d0f;
  --color-accent-soft: rgba(216, 180, 110, 0.24);   /* tinted wash on a PANEL —
                                                       brand chip and tag. Sized
                                                       for a white ground: the
                                                       lighter gold needs 24% to land
                                                       the tint 16% of #b8892a gave. */
  --color-accent-wash: rgba(216, 180, 110, 0.7);    /* the same wash for the CANVAS
                                                       ground, and the reason there are
                                                       two. --color-accent-soft is mixed
                                                       against a panel; over
                                                       --color-canvas the identical
                                                       alpha lands on #e1d5bc, which is
                                                       1.14:1 against that ground —
                                                       QUIETER than the plain white
                                                       incoming bubble at 1.28:1. The
                                                       outgoing message, the loudest
                                                       object in any chat app, was the
                                                       faintest thing on the canvas.
                                                       The brighter gold needs 70% to
                                                       land #ddc28e: 1.35:1, so it
                                                       out-reads incoming, and
                                                       --color-fg measures 10.9:1
                                                       on it. Gold carries what green
                                                       carries; a signal nobody can see
                                                       is not a signal. */
  --color-danger: #b83629;        /* 5.8:1 bg / 5.0:1 on the hover row */
  --color-danger-aaa: #8f1d14;    /* 8.9:1 */
  --color-danger-bg: rgba(184, 54, 41, 0.1);
  --color-success: #2c7830;       /* 5.5:1 bg / 4.7:1 on the hover row */
  --color-success-aaa: #14532d;   /* 9.1:1 */
  --color-success-bg: rgba(44, 120, 48, 0.12);
  /* Burnt amber, not the brand gold. Semantic warning keeps its own hue;
     this was #b8892a — byte-identical to --color-accent, with
     --color-warning-bg byte-identical to --color-accent-soft. A warning chip
     and an unread badge painted exactly the same colour, so the one hue that
     means "look here" also meant "nothing is wrong".
     The separation is LUMINANCE, not hue, and that is forced: warning has to
     live between gold (40°) and --color-danger (5.5°), and every candidate in
     that band lands 28-33°, a delta too small to read on its own. #a85c08 is
     31.5° but 5.00:1 on --color-bg against the accent's 1.97:1 — a 2.5:1
     step between the two, which is what the eye actually catches. It also
     clears 4.5:1 unaided, so a warning word needs no separate ink. */
  --color-warning: #a85c08;
  --color-warning-fg: #6b4d00;
  --color-warning-bg: rgba(168, 92, 8, 0.13);
  --color-info: #245fe2;          /* neutral-informational: env/version tags, "resumed" — 5.5:1 */
  --color-info-bg: rgba(36, 95, 226, 0.1);
  --color-overlay: rgba(20, 18, 14, 0.42);          /* dialog backdrop, scrim */
  --color-media-overlay: var(--color-overlay);    /* timestamp over a photo */
  --color-media-ticks-read: var(--color-info);
  /* Benchmark chart series, one per runtime, told apart by hue as the
     Artificial Analysis charts tell makers apart. Never a signal: the pick
     is marked by the gold ring, not by a series colour. */
  --color-series-1: #b85a36;      /* terracotta — claude-code */
  --color-series-2: #14120e;      /* ink — codex */
  --color-series-3: #6a55c9;      /* violet — grok-build */
  /* Focus gets the INK gold, not the fill gold: #d8b46e is 1.97:1 on white
     and less on the grey wash; #846013 measures 5.73:1 on white and 5.26:1 on
     --color-surface-alt, so the ring clears 3:1 on every ground we paint. */
  --color-focus-ring: #846013;
  --color-glass-bg: rgba(255, 255, 255, 0.82);      /* frosted panels, sticky headers */
  --color-glass-border: rgba(20, 18, 14, 0.1);      /* hairline on frosted panels */

  /* ───── Radius ─────
     The box scale is a real scale again — it collapsed to a single
     3px value under the old sharp language, which meant a dialog and a tick
     mark had the same corner. Reach for a literal 50% only when the shape
     carries meaning (avatar, status dot, spinner, send button, unread count). */
  --radius-xs: 4px;      /* dense inline marks — a tag inside a line of text,
                            a code chip, a tick */
  --radius-sm: 8px;      /* THE default box — inputs, cards, menus,
                            message bubbles. WhatsApp's bubble is 7.5px; 8 is
                            the same shape on a 4px grid. */
  --radius-md: 12px;     /* panels that hold a group of boxes — popovers,
                            sheets, the plates a detail canvas carries */
  --radius-lg: 16px;     /* dialogs and full sheets */
  --radius-pill: 999px;  /* the capsule — every button (--btn-radius), search
                            field, composer, chips, tags, bar tracks. A
                            hand-rolled <button> or button-styled <a> takes
                            --btn-radius too; an icon-only one is a circle. */

  /* ───── Spacing scale ───── */
  --space-0: 0;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --detail-section-gap: 1.875rem;

  /* ───── Typography ─────
     Roboto Variable is the content and UI-control voice — the same
     family WhatsApp renders in on Android, which is most of the reason the
     product feels familiar before a single colour is read. Self-hosted
     variable woff2 (SIL OFL 1.1), declared by @font-face next to the app
     shell and the catalogue. No CDN: the Capacitor shell must render
     offline on cold start.

     Face name is exactly `Roboto Variable` so Android's installed static
     Roboto does not win the family match. Stack after that is static
     Roboto, then Helvetica Neue / Helvetica.

     Geist is the display face: marketing headings, the hero and
     --font-title (list titles). chat-surface.css maps --font-display to
     Roboto inside the signed-in shell, so in-app headings and conversation
     text share one family.

     --font-mono is Geist Mono and it is for CODE AND DATA ONLY: a command
     line, a log, a prompt, an id in a diagnostic — things a user copies. It
     is NOT the system's voice any more. Timestamps, ticks, counts, badges
     and button labels are Roboto in sentence case; the old uppercase-mono
     treatment is what made a chat look like a control room. */
  --font-body: "Roboto Variable", Roboto, "Helvetica Neue", Helvetica,
    sans-serif;
  --font-display: 'Geist', system-ui, sans-serif;
  --font-hero: var(--font-display);
  --font-title: var(--font-display);
  --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo,
    Consolas, monospace;
  /* UI optical size. The shipped Roboto Variable is a Latin subset of Roboto
     Flex with three axes live — opsz 8–144, wght 100–1000, GRAD -200–150 —
     so an optical instance is a real design, not a synthesised one.
     `opsz 18` is the interface cut list rows want: even stroke, open
     counters, slightly tighter than the 14 default. Row titles use THIS,
     at --weight-regular. A list title is never bold. */
  --font-variation-ui: 'opsz' 18;
  /* The floor is "do not go below a readable phone size". --text-2xs is the
     one step under it and it is deliberately narrow in scope: the GLANCED
     metadata a chat app hangs off a name or tucks into a bubble — a
     timestamp, the tick row, an unread count, a channel tag. Never a label
     you have to read to act. WhatsApp sets that line at 11px; 12 is the
     smallest that stays comfortable on a 390px phone in Roboto. */
  --text-2xs: 0.75rem;    /* 12px — timestamps, ticks, counts */
  --text-xs: 0.875rem;    /* 14px — the secondary line: row preview, caption */
  --text-sm: 1rem;        /* 16px */
  --text-base: 1rem;      /* 16px — body floor, unchanged: this is a reskin */
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.5rem;
  --text-4xl: 3.5rem;     /* section display ceiling */
  --text-5xl: 5rem;       /* hero display. The brand word capped at --text-4xl
                             while section titles climbed to --text-3xl — a
                             1.4x step at 1440px where the phone had 1.95x.
                             The hero has to out-rank at every width. */
  --weight-light: 350;    /* DISPLAY ONLY — the landing's headline voice, and
                             the one place a weight under 400 is legitimate.
                             350, not 300: light-on-dark blooms and dark-on-light
                             thins, so the same numeral is optically lighter on
                             paper. Roboto Variable carries wght 100–1000, so
                             350 is a real instance, not a synthesised one.
                             Nothing in the app chrome reaches for it — a chat
                             row title is --weight-regular, a name in a header
                             is --weight-medium. */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --line-display: 1.05;
  --line-tight: 1.15;
  --line-snug: 1.4;
  --line-base: 1.6;
  /* Large type tightens. Small type does NOT open up any more — the
     uppercase-tracked micro-label is retired, so --tracking-normal is what
     app chrome uses, everywhere. The two open values below are the landing's
     alone: they belong to the brand marks, not to the interface. */
  --tracking-display: -0.03em;  /* --text-3xl and up, paired with --weight-light */
  --tracking-tight: -0.015em;   /* --text-xl / --text-2xl headings */
  --tracking-normal: 0;         /* everything the app chrome sets */
  --tracking-label: 0.06em;     /* marketing section markers; UI uses normal */
  --tracking-wide: 0.14em;      /* the wordmark */

  /* ───── Motion ─────
     A chat app answers immediately. Scroll reveals and staggers run
     at --duration-fast with delays in the 20-30ms range, never the 0.6s fades
     and 2.3s staggers the landing shipped with — that reads as a slow
     network, not as polish. Operator directive, 2026-07-25. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --duration-instant: 0ms;
  --duration-fast: 100ms;
  --duration-normal: 160ms;
  --duration-slow: 280ms;
  /* 1, deliberately. This used to be 0.55 and was applied on top of
     --color-subtle, which multiplies a measured 5.0:1 down to roughly 2.9:1 and
     makes every contrast figure in this file a lie at the one place users
     actually squint. Placeholders read lighter because they use a lighter
     TOKEN (--color-muted), never because they are faded. Do not put opacity on
     text. */
  --opacity-placeholder: 1;

  /* ───── Elevation ─────
     Soft warm-black at low alpha — the heavy near-opaque blacks the dark build
     needed would read as grime on paper. --shadow-md is the card lift (a plate
     on the sheet); --shadow-lg and up leave the page entirely and belong to
     overlays. Anything below is contact shadow, not elevation.

     --shadow-xs is CONTACT, and it has one headline job: a message
     bubble on --color-canvas. A white bubble on warm paper is a 1.28:1 tonal
     step, which is real but not enough on its own — the pixel of shadow under
     it is what makes it a card lying on a surface instead of a shape cut out
     of it. That is why the alpha is 0.10 and not the 0.05 of the old
     white-on-white build, where the same shadow had nothing to separate. */
  --shadow-xs: 0 1px 1px rgba(20, 18, 14, 0.1);
  --shadow-sm: 0 1px 3px rgba(20, 18, 14, 0.07);
  --shadow-md: 0 4px 14px rgba(20, 18, 14, 0.1);
  --shadow-lg: 0 12px 32px rgba(20, 18, 14, 0.14);
  --shadow-xl: 0 24px 56px rgba(20, 18, 14, 0.18);
  --shadow-glass: 0 4px 24px rgba(20, 18, 14, 0.08);
  /* --color-focus-ring, not --color-accent: this ring is drawn around
     controls, and the primary button's fill IS --color-accent — gold on gold
     is 1.00:1, so tabbing onto it made the button 1px wider and nothing else
     (WCAG 2.4.7, Level A). The ring token is the same gold darkened, 5.7:1 on
     white, and is what every other focus rule in the app already uses. Two
     pixels, matching --focus-ring-width, so the indicator survives being
     drawn against a fill of its own hue. */
  --shadow-focus: 0 0 0 var(--focus-ring-width) var(--color-focus-ring),
    var(--shadow-md);

  /* ───── The scale ─────
     THREE VIEWPORTS. Two boundaries. Nothing in this app invents a third.

       mobile    < 640px
       tablet    640px – 839px
       desktop   >= 840px

     The app is max-width-first, so desktop is the base rule and the two
     queries nest downward. Copy these verbatim:

       @media (max-width: 839.98px) { }   tablet and below
       @media (max-width: 639.98px) { }   mobile only

     The .98 is not decoration. `max-width: 839px` + `min-width: 840px` leaves
     everything between them unstyled, and fractional-DPI viewports do land
     there.

     These CANNOT be custom properties — CSS does not resolve var() inside a
     media query, so `@media (max-width: var(--bp-tablet))` is invalid and
     fails silently. The two literals are the contract; the literals are
     enforced by scripts/check-design-tokens.mjs, because a comment does not
     stop a 35th breakpoint from appearing and a check does. This is what the
     app had before: 35 distinct values across 75 queries in 41 files, several
     of them the same number written two ways (640px/40rem, 480px/30rem,
     63.9375rem/64rem — 1023 and 1024, one pixel apart). */

  /* ───── Page geometry ─────
     THE page container. 1040 outer, 20 either side, 1000 of real content.
     Every centred page shell reads these three; a route that writes its own
     max-width forks the page's left edge from every other route's.
     Changing these is a layout decision, not a reskin. */
  --page-max-width: 1040px;
  --page-gutter: var(--space-5); /* 20px */
  --page-content-width: 1000px;  /* --page-max-width - 2 * --page-gutter */

  /* The bubble column's widest. MessagesArea centres the thread in it and
     the Composer lines its capsule up with it. */
  --thread-column-max: 55rem;

  /* The composer's side margin in the conversation pane (WhatsApp Web's
     12px); on a wide pane it lines up with the bubble column instead. */
  --thread-gutter: 0.75rem;

  /* THE reading measure — how wide a paragraph is allowed to get, which is a
     typographic limit and not the same fact as the page container. 58ch lands
     inside the 50–75 characters-per-line band. api/design/preferences.ts has
     been emitting a "lock --content-measure" line into every tenant brief
     while no stylesheet declared it; it does now. */
  --content-measure: 58ch;

  /* THE hero mural's widest. A 3:1 panorama drawn to 100vw made its HEIGHT a
     function of the window: 480px tall at 1440, 640px at 1920, 853px on a 2560
     monitor — it ate the fold before a word of copy appeared. Past this it
     holds 1440x480, centres, and dissolves its outer columns into the paper.
     Canvases read this at runtime; the hero's top offset is this / 3. */
  --art-max-width: 1600px;

  /* ───── Sizing primitives ─────
     Icon sizes are roles, not literals. Four different glyph sizes (16/18/20/
     24px) were spelled inline across the app with no token to appeal to, so
     the same lucide icon rendered a different size depending on which file
     drew it. --icon-md is the list-row glyph; --icon-sm sits inside a control
     next to text; --icon-lg is the standalone row icon BasicListItem uses. */
  --icon-sm: 1rem;
  --icon-md: 1.25rem;
  --icon-lg: 1.5rem;
  --control-height-sm: 1.75rem;
  --control-height: 2.25rem;       /* default button, input height */
  --control-height-lg: 2.75rem;
  /* Agent faces: -sm on the Layanan canvas cards (AgentCard). */
  --avatar-face-sm: 3.25rem;
  --avatar-face-md: 4.5rem;
  --avatar-face-lg: 6rem;
  --content-width-xs: 12rem;
  --content-width-sm: 22rem;
  --content-width-md: 28rem;
  --content-width-lg: 48rem;
  --state-height-md: 9rem;
  --state-height-lg: 16rem;
  --border-width: 1px;
  --focus-ring-width: 2px;
  --visually-hidden-offset: -1px;
  --visually-hidden-size: 1px;
  --layer-base: 1;
  --layer-raised: 2;
  --layer-popover-scrim: 45;
  --layer-dialog-overflow: 60;
}

/* Compensate dimmed highlights: retain readable secondary/semantic ink,
   control edges and photo metadata without changing the daytime palette. */
:root { --night-sender-ink-weight: 100%; }

html[data-night-mode] {
  --color-subtle: #625b50;
  --color-success: #246326;
  --color-warning: #8c4b06;
  --color-danger: #a22e23;
  --color-info: #2053c4;
  --color-accent-ink: #6c4e0f;
  --night-sender-ink-weight: 82%;
  --color-border-control: rgba(20, 18, 14, 0.58);
  --color-media-overlay: rgba(20, 18, 14, 0.72);
  --color-media-ticks-read: #93c5fd;
}

/* ───── WhatsApp geometry ─────
   Desktop (>= 840px) mirrors WhatsApp Web; phone and tablet mirror WhatsApp
   iOS (Liquid Glass, iOS 26/27). Sizes and materials here; colour roles for
   these parts live in chat-surface.css. */
:root {
  /* WhatsApp iOS type: SF Pro on Apple devices, Roboto elsewhere. */
  --font-ios: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Roboto Variable",
    Roboto, "Helvetica Neue", Helvetica, sans-serif;

  /* WhatsApp Web: 64px panel headers, 20px side padding, 22/28 regular
     titles; 60px settings rows inset 10px with 12px corners. */
  --list-header-pad-x: 1.25rem;
  --list-title-size: 1.375rem;
  --list-title-line: 1.75rem;
  --list-title-weight: 400;
  --list-title-tracking: 0;
  --menu-row-min: 3.75rem;
  --menu-row-inset: 0.625rem;
  --menu-row-gap: 0.875rem;
  /* Rows sit 4px apart, so a hovered row never merges with the selected one. */
  --menu-row-spacing: 0.25rem;
  /* WhatsApp's "emphasized" weight: 545 on the web, SF semibold on iOS. */
  --weight-emphasized: 545;

  /* WhatsApp iOS: 16pt margins, 54pt navigation bar (44pt button row),
     52pt large-title band, 44pt glass buttons */
  --ios-margin: 1.25rem; /* 16pt on phones, below */
  --navbar-height: 2.75rem;
  --navbar-pad-bottom: 0.625rem;
  --large-title-size: 2.125rem;
  --large-title-tracking: var(--tracking-tight);
  --large-title-pad-bottom: 0.5rem;
  --glass-btn-size: 2.75rem;
  /* Floating tab bar: a 62pt capsule inset 21pt, 4pt inner padding */
  --tabbar-inset: 1.3125rem;
  --tabbar-height: 3.875rem;
  --tabbar-pad: 0.25rem;
  --tabbar-max-width: 25rem;
  --tab-icon-size: 1.625rem;
  --tab-label-size: 0.625rem;
  --tab-label-gap: 0.0625rem;
  /* Inset-grouped lists: 26pt cards, 52pt rows, 20pt between groups */
  --group-radius: 1.625rem;
  --group-row-min: 3.25rem;
  --group-gap: 1.25rem;
  --ios-row-gap: 0.875rem;
  --ios-row-icon-box: 1.75rem;
  --disclosure-width: 0.5rem;
  --disclosure-height: 0.8125rem;
  /* Liquid Glass material */
  --glass-blur: blur(20px) saturate(180%);
  --glass-shadow: 0 6px 20px rgba(20, 18, 14, 0.1),
    inset 0 0 0 0.5px rgba(20, 18, 14, 0.06),
    inset 0 0.5px 0 rgba(255, 255, 255, 0.9);
  --color-glass-fill: rgba(255, 255, 255, 0.62);
  --color-tab-selected: rgba(20, 18, 14, 0.07);
  /* WhatsApp Web's surface-highlight: hovered and selected rows, search
     fills, icon-button hover. */
  --color-highlight: rgba(20, 18, 14, 0.06);
  /* Shared controls. WhatsApp Web: pill buttons 32/40/56 with 14px
     emphasized labels, 40px text fields with 12px corners. iOS values are
     set for phone and tablet in chat-surface.css. */
  --btn-height-sm: 2rem;
  --btn-height: 2.5rem;
  --btn-height-lg: 3.5rem;
  --btn-pad-x: 1.5rem;
  --btn-radius: var(--radius-pill);
  --btn-font-size: var(--text-xs);
  --field-height: 2.5rem;
  --field-radius: var(--radius-md);
  /* iOS standard push: 540ms, outgoing parallax -33% */
  --ease-ios: cubic-bezier(0.32, 0.72, 0, 1);
  --duration-push: 540ms;
}

/* iOS side margin: 16pt on phones. On :root so every token built from it
   (the detail and card padding) resolves to 16 as well. */
@media (max-width: 639.98px) {
  :root {
    --ios-margin: 1rem;
  }
}

/* ───── Chat surface geometry ─────
   Conversation, chat list and composer sizes. */
:root {
  /* WhatsApp Web: 7.5px bubbles, 6px thumbnails and date chips, a 26px
     composer, a 24px intro card. */
  --radius-bubble: 0.46875rem;
  --radius-thumb: 0.375rem;
  --radius-date-chip: var(--radius-thumb);
  --radius-composer: 1.625rem;
  --radius-intro-card: 1.5rem;
  /* The bubble column: 63px sides in a 1:1 chat, easing to 25/19px on the
     narrowest pane; 9% in a group. Bubbles cap at 75% of the 640px pane and
     95% of the narrowest one, WhatsApp's 1025-1300px and 900px bands. */
  --thread-pad-start: clamp(1.5625rem, 20.65% - 4.3125rem, 3.9375rem);
  --thread-pad-end: clamp(1.1875rem, 23.9% - 5.625rem, 3.9375rem);
  --thread-pad-group: 9%;
  --bubble-max-width: max(65%, min(95%, 24rem));
  /* The chat-row chevron slides in over 75ms. */
  --duration-row-chevron: 75ms;
  --ease-row-chevron: cubic-bezier(0.14, 0.62, 0.33, 0.9);
  --shadow-conv-header: 0 1px 4px rgba(20, 18, 14, 0.12);
  --shadow-composer: 0 1px 6px rgba(20, 18, 14, 0.12);
  --shadow-date-chip: 0 0 1px 1px rgba(20, 18, 14, 0.06),
    0 1px 0 rgba(20, 18, 14, 0.05);
  --shadow-jump-btn: 0 1px 1px rgba(20, 18, 14, 0.06),
    0 2px 5px rgba(20, 18, 14, 0.2);
  /* System chips (the day divider): white at 90% over the wallpaper. */
  --color-chip-system: rgba(255, 255, 255, 0.9);
}

/* WhatsApp iOS: 18pt bubbles and capsule date chips; bubbles 14pt from the
   screen edge, at most 75% of it. */
@media (max-width: 839.98px) {
  :root {
    --radius-bubble: 1.125rem;
    --radius-thumb: calc(var(--radius-bubble) - 0.1875rem);
    --radius-date-chip: var(--radius-pill);
    --thread-pad-start: 0.875rem;
    --thread-pad-end: 0.875rem;
    --thread-pad-group: 0.875rem;
    --bubble-max-width: min(80%, 30rem);
  }
}

/* ───── Controls geometry ─────
   Buttons, dialogs, menus, switches, checkboxes, toasts, tooltips.
   Desktop mirrors WhatsApp Web (WDS); the block after it swaps in WhatsApp
   iOS values. Declared on :root, not .chat-surface, because bits-ui portals
   dialogs and menus to <body>. */
:root {
  /* Dialog: 28px corners, widths 300/400/560/680 capped at 92vw, 24px
     padding, 1px inset outline instead of a shadow. */
  --dialog-radius: 1.75rem;
  --dialog-width-sm: min(18.75rem, 92vw);
  --dialog-width-md: min(25rem, 92vw);
  --dialog-width-lg: min(35rem, 92vw);
  --dialog-width-xl: min(42.5rem, 92vw);
  --dialog-pad: 1.5rem;
  --dialog-title-size: var(--text-sm);
  --dialog-title-line: 1.5rem;
  --dialog-title-weight: var(--weight-regular);
  --dialog-text-size: var(--text-xs);
  --dialog-text-line: 1.25rem;
  --dialog-btn-height: var(--btn-height);
  /* iOS alert and sheet (phone and tablet only; see below) */
  --alert-width: min(18.75rem, 90vw);
  --sheet-inset: 0.5rem;
  --sheet-radius: 2.375rem;
  --sheet-max-width: 35rem;
  --grabber-width: 2.25rem;
  --grabber-height: 0.3125rem;

  /* Menus, popovers and select lists: 16px corners, 4px padding and gap,
     36px items with 12px corners and 14/20 labels. */
  --menu-radius: 1rem;
  --menu-pad-y: 0.25rem;
  --menu-pad-x: 0.25rem;
  --menu-gap: 0.25rem;
  --menu-min-width: 9.375rem;
  --menu-item-min: 2.25rem;
  --menu-item-radius: 0.75rem;
  --menu-item-pad-x: 0.75rem;
  --menu-item-size: var(--text-xs);
  --menu-item-line: 1.25rem;
  --menu-icon-size: 1.25rem;
  /* iOS menu section heading, 13pt */
  --menu-heading-size: 0.8125rem;

  /* Switch: 40x24 track; off = 12px thumb 6px in, on = 16px thumb 4px in.
     Hover stretches the thumb 2px off, 4px on. */
  --switch-width: 2.5rem;
  --switch-height: 1.5rem;
  --switch-thumb-w: 0.75rem;
  --switch-thumb-h: 0.75rem;
  --switch-thumb-inset: 0.375rem;
  --switch-thumb-on-w: 1rem;
  --switch-thumb-on-h: 1rem;
  --switch-thumb-on-inset: 0.25rem;
  --switch-travel: 0.875rem;
  --switch-stretch-off: 0.125rem;
  --switch-stretch-on: 0.25rem;

  /* Checkbox 18 with 4px corners, radio ring 20 with a 10px dot; both 2px
     strokes in a 24px hit box. */
  --checkbox-size: 1.125rem;
  --radio-size: 1.25rem;
  --radio-dot: 0.625rem;
  --control-stroke: 2px;
  /* The tick, as a mask so it takes any ink token */
  --checkmark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4.5 12.5l5 5L19.5 7' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* The chevron a native <select> draws: lucide chevron-down, 2px stroke,
     in --color-muted (a background image cannot read var()). */
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23625b50' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");

  /* Tooltip: 4px corners, 4/8 padding, 24 min, 200 max, 12/16 text */
  --tooltip-radius: var(--radius-xs);
  --tooltip-max-width: 12.5rem;

  /* Toast: pill with 24px corners, 48 tall, 360 wide at most */
  --toast-radius: 1.5rem;
  --toast-min-height: 3rem;
  --toast-max-width: 22.5rem;

  /* Motion. Press: scale .96 in 120ms. Menus: 300ms fade + 8px + scale .95.
     Dialogs: backdrop 300ms, box 200ms. (The toast's 650ms lives in
     SnackbarHost's transitions.) */
  --ease-press: cubic-bezier(0.2, 0, 0, 1);
  --duration-press: 120ms;
  --press-scale: 0.96;
  --ease-menu: cubic-bezier(0.17, 0.17, 0, 1);
  --duration-menu: 300ms;
  --duration-menu-exit: 150ms;
  --ease-modal: cubic-bezier(0.19, 0.73, 0.28, 1);
  --duration-modal: 300ms;
  --duration-dialog-box: 200ms;
  /* WhatsApp's state layer: hover paints the role colour at 10%. Disabled
     is 38% opacity plus grayscale. */
  --state-layer-opacity: 0.1;
  --disabled-opacity: 0.38;

  /* Elevation (palette warm black) */
  --shadow-popover: 0 12px 16px -4px rgba(20, 18, 14, 0.1);
  --shadow-toast: 0 10px 26px rgba(20, 18, 14, 0.2);
  --shadow-tooltip: 0 0 20px rgba(20, 18, 14, 0.2), 0 1px 0 rgba(20, 18, 14, 0.04);
  --shadow-knob: 0 2px 6px rgba(20, 18, 14, 0.18);
  --shadow-segment: 0 1px 3px rgba(20, 18, 14, 0.08), 0 2px 20px rgba(20, 18, 14, 0.06);

  /* Colours the controls need that the palette spells differently.
     Inverse = tooltip and toast. The iOS fills are systemFill (switch off
     track) and tertiarySystemFill (segmented track) in the palette's ink. */
  --color-surface-inverse: var(--color-fg);
  --color-fg-inverse: var(--color-bg);
  --color-inverse-glass: rgba(20, 18, 14, 0.85);
  --color-highlight-inverse: rgba(255, 255, 255, 0.1);
  --color-ios-fill: rgba(20, 18, 14, 0.12);
  --color-ios-fill-3: rgba(20, 18, 14, 0.07);
  --color-scrim-light: rgba(20, 18, 14, 0.2);
  --color-glass-strong: rgba(255, 255, 255, 0.8);
  --glass-blur-strong: blur(32px) saturate(180%);
}

/* WhatsApp iOS controls, phone and tablet */
@media (max-width: 839.98px) {
  :root {
    /* Alert: glass card, 34pt corners, 22pt padding, 17/22 semibold title,
       15/20 message, 48pt capsule buttons. */
    --dialog-radius: 2.125rem;
    --dialog-pad: 1.375rem;
    --dialog-title-size: 1.0625rem;
    --dialog-title-line: 1.375rem;
    --dialog-title-weight: var(--weight-semibold);
    --dialog-text-size: 0.9375rem;
    --dialog-text-line: 1.25rem;
    --dialog-btn-height: 3rem;
    /* Context menu: glass, 250 wide, 26pt corners, 44pt rows of 17/22 with
       the highlight inset 8pt and 20pt corners. */
    --menu-radius: 1.625rem;
    --menu-pad-y: 0.5rem;
    --menu-pad-x: 0.5rem;
    --menu-gap: 0;
    --menu-min-width: 15.625rem;
    --menu-item-min: 2.75rem;
    --menu-item-radius: 1.25rem;
    --menu-item-pad-x: 0.625rem;
    --menu-item-size: 1.0625rem;
    --menu-item-line: 1.375rem;
    /* Switch: 64x28 track, 38x24 capsule knob 2pt in; pressing stretches
       it to 46. */
    --switch-width: 4rem;
    --switch-height: 1.75rem;
    --switch-thumb-w: 2.375rem;
    --switch-thumb-h: 1.5rem;
    --switch-thumb-inset: 0.125rem;
    --switch-thumb-on-w: 2.375rem;
    --switch-thumb-on-h: 1.5rem;
    --switch-thumb-on-inset: 0.125rem;
    --switch-travel: 1.375rem;
    --switch-stretch-off: 0.5rem;
    --switch-stretch-on: 0.5rem;
  }
}

/* ───── Detail pages geometry ─────
   Detail headers, canvases and sections. */
:root {
  /* WhatsApp Web drawer header: 64px, 40px icon buttons, Body1 title, 13/20
     subtitle, a soft shadow instead of a hairline. 20px sides, so the title
     sits on the cards' edge as the list title sits on its rows. */
  --detail-header-pad-y: 0.625rem;
  --detail-header-pad-x: 1.25rem;
  --detail-icon-btn: 2.5rem;
  --detail-title-line: 1.5rem;
  --detail-subtitle-size: 0.8125rem;
  --detail-subtitle-line: 1.25rem;
  --shadow-detail-header: 0 1px 4px rgba(20, 18, 14, 0.12);
  /* WhatsApp Web drawer sections as white cards on the wash: 12px corners,
     20px padding, 62px rows with a 40px icon slot, 120px profile photo. */
  --detail-pad: 1.25rem;
  --detail-pad-bottom: 2rem;
  --detail-card-pad: 1.25rem;
  --detail-card-gap: 0.75rem;
  --detail-card-radius: var(--radius-md);
  --detail-row-min: 3.875rem;
  --detail-row-icon: 2.5rem;
  --detail-avatar: 7.5rem;
  /* Headline1 24/32: the profile name, a domain. */
  --detail-headline-size: 1.5rem;
  --detail-headline-line: 2rem;
  /* WhatsApp Web intro panel card: 352px wide, 24px corners and padding. */
  --detail-intro-width: 22rem;
  --detail-intro-radius: 1.5rem;
  --detail-intro-pad: 1.5rem;
  /* WhatsApp iOS: 96pt profile photo, 22/28 bold name, the scroll-edge fade
     under the navigation bar, and the push's left-edge shadow. */
  --detail-avatar-ios: 6rem;
  --shadow-push-edge: -2px 0 12px rgba(20, 18, 14, 0.1);
}

/* WhatsApp iOS below 840px: inset-grouped cards — 26pt corners, 16pt
   margins and padding (20pt on tablets), 20pt between groups. */
@media (max-width: 839.98px) {
  :root {
    --detail-pad: var(--ios-margin);
    --detail-card-pad: var(--ios-margin);
    --detail-card-gap: var(--group-gap);
    --detail-card-radius: var(--group-radius);
    /* iOS Title 2, 22/28. */
    --detail-headline-size: 1.375rem;
    --detail-headline-line: 1.75rem;
  }
}

/* ───── Feature components geometry ─────
   Cards and controls inside feature components. */
:root {
  /* Feature cards share the detail cards' corners and padding, so a list
     card and a section card line up. Drawer rows: 62px, 40px icon slot. */
  --card-radius: var(--detail-card-radius);
  --card-pad: var(--detail-card-pad);
  --drawer-row-min: 3.875rem;
  --drawer-icon-slot: 2.5rem;
  /* Chat-list rows: 72px, a 49px avatar; 40px avatars in headers. */
  --chat-row-min: 4.5rem;
  --row-avatar-size: 3.0625rem;
  --head-avatar-size: 2.5rem;
  /* WhatsApp search field: 40px pill (iOS 36pt capsule). */
  --search-height: 2.5rem;
  /* WDS chip: 32px pill, 12px sides. */
  --chip-height: 2rem;
  --chip-pad-x: 0.75rem;
  /* iOS segmented control: 32pt track, 28pt segments inset 2pt, 13pt label. */
  --seg-track-height: 2rem;
  --seg-height: 1.75rem;
  --seg-inset: 0.125rem;
  --seg-font-size: 0.8125rem;
  /* Status pills and counts: 12px emphasized on a 20px pill. */
  --pill-height: 1.25rem;
  --pill-pad-x: 0.5rem;
}

/* WhatsApp iOS: 52pt rows, 76pt chat rows with 52pt avatars, 36pt header
   avatars, 36pt search capsule, 14pt chip sides. */
@media (max-width: 839.98px) {
  :root {
    --drawer-row-min: var(--group-row-min);
    --chat-row-min: 4.75rem;
    --drawer-icon-slot: var(--ios-row-icon-box);
    --row-avatar-size: 3.25rem;
    --head-avatar-size: 2.25rem;
    --search-height: 2.25rem;
    --chip-pad-x: 0.875rem;
  }
}

/* The shell: 1100px wide, 64px panel headers. The platform app and the
   tenant starter share these. */
:root { --app-shell-max-width: 1100px; --header-min-height: 4rem; }

/*
 * The template's faces, served with this sheet from the Jadilah host: a
 * `/fonts/` URL here resolves against that host, not the tenant's.
 */
@font-face {
  font-family: 'Roboto Variable';
  src: url('/fonts/Roboto-Variable.woff2') format('woff2');
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
}

/* Headings, titles and hero copy use a separate display face. */
@font-face {
  font-family: 'Geist';
  src: url('/fonts/Geist-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Code snippets are the one place the design language keeps a mono voice. */
@font-face {
  font-family: 'Geist Mono';
  src: url('/fonts/GeistMono-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/*
 * PAGE-GROUND — the conversation wallpaper: the shared dot ground
 * (--dot-ground, the landing page's texture) standing in for WhatsApp's
 * doodle. Paint it on the ground a conversation sits on, never on chrome.
 */

.page-ground {
  background: var(--dot-ground);
}

/*
 * Element baseline shared by the tenant app and Storybook through index.css.
 * Roboto Variable is the UI voice; mono is reserved for copyable code/data.
 */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-fg);
  background-color: var(--color-bg);
  color-scheme: only light;
  min-height: 100%;
  -webkit-text-size-adjust: 100%;
}

body,
#app {
  background-color: var(--color-bg);
  color: var(--color-fg);
  color-scheme: only light;
  min-height: 100%;
}

#app {
  min-height: 100dvh;
}

button,
input,
select,
textarea {
  font-family: inherit;
  font-size: inherit;
}

a {
  color: inherit;
  text-decoration: none;
}

code,
kbd,
samp,
pre {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

::selection {
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
}

/*
 * headings.css — the TYPE baseline: body leading, then headings bound to the
 * type scale.
 *
 * Its own file for one reason: it has TWO consumers and they load differently.
 * The live app imports it from routes/+layout.svelte; the Storybook catalogue
 * gets it through base.css → index.css. It first shipped inside base.css alone,
 * which the app has never imported — so the fix read as landed and was inert in
 * the product, and headings kept falling back to the UA's 2em bold, the exact
 * inverse of the 350-weight display voice.
 *
 * That "two consumers, one file" property is the whole reason this file exists,
 * and it is why the global line-height below lives here rather than in
 * base.css: a type value that both surfaces need has to sit somewhere both
 * surfaces load. Anything you are tempted to add to base.css and that the app
 * also needs belongs here instead — check which file the APP loads before
 * believing a global shipped.
 *
 * Still NOT merged into base.css wholesale: that file is a Storybook-only
 * mirror of routes/+layout.svelte's element globals, and importing a mirror
 * into the thing it mirrors is how the two drift in the first place.
 */

/*
 * Body leading, 1.6, and the ONE place it is declared.
 *
 * Before this it was set only in base.css — Storybook-only — so the catalogue
 * led every element that carries no line-height of its own at 1.6 while the
 * app fell through to the UA's `normal` (~1.15–1.2 for Roboto): ~33% more
 * leading in the catalogue than in the product, on row height, bubble height
 * and list density, which is precisely what a WhatsApp-grammar reskin is
 * judged on. The app's only global leading came from an unscoped `body {}`
 * block leaked by the landing route's stylesheet — present after a visit to
 * the landing, absent on a deep link. Declared once, here, it is simply
 * always true.
 *
 * On `html` rather than `body`: it inherits either way, and `html` is where
 * routes/+layout.svelte declares the rest of the document-level type.
 */
html {
  line-height: var(--line-base);
}

h1, h2, h3, h4, h5, h6 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-light);
  line-height: var(--line-tight);
  letter-spacing: var(--tracking-display);
  color: var(--color-fg);
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }

/* Below --text-2xl the display tracking is too loose and 350 too frail, so the
   smaller levels tighten and gain weight. */
h3 {
  font-size: var(--text-xl);
  letter-spacing: var(--tracking-tight);
}
h4 {
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight);
}
h5, h6 {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-normal);
}

p { margin: 0; }

/*
 * focus.css — the keyboard focus indicator.
 *
 * Its own file for the same reason headings.css is: it has two consumers that
 * load differently. The live app imports it from routes/+layout.svelte; the
 * Storybook catalogue gets it through base.css → index.css.
 *
 * It first shipped inside base.css alone — a file the app has never imported —
 * so the design system's focus ring existed only in the catalogue and every
 * keyboard user in the product got the UA default or, on the several controls
 * that set `outline: none`, nothing at all. That is WCAG 2.4.7 Focus Visible,
 * Level A. The heading baseline had the identical bug; if you add another
 * global rule, check which file the APP loads before believing it shipped.
 *
 * `outline` rather than `box-shadow`: it follows border-radius, it is not
 * clipped by `overflow: hidden` ancestors, and it survives forced-colors mode.
 */
:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

/*
 * Wrapper pattern. A control that hides its own outline because the visible
 * affordance belongs to a parent (a search field inside a styled shell, a chip
 * inside a rail) must hand the ring to that parent — never simply remove it.
 * Add `data-focus-shell` to the wrapper and `outline: none` on the inner
 * control is then legitimate.
 */
[data-focus-shell]:focus-within {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

/*
 * chat-surface.css — the chat surface's ROLE MAPPING, in one place.
 *
 * Components read short role names (--incoming-bubble, --bg-deeper,
 * --bubble-shadow …); this file maps them to tokens.css. The app shell and
 * the Storybook frames both apply it through the .chat-surface class, so the
 * catalogue cannot fork from the product. Declare a role here and nowhere
 * else (design-language.test.ts enforces it). Structural sizes stay in the
 * app shell.
 */

.chat-surface {
  /* In-app headings use the conversation face. Screen titles (the list
     header) keep --font-title, the Geist title face, on desktop; below
     840px they take the phone's system face with the rest of the app. */
  --font-display: var(--font-body);

  /* ── Surfaces ── */
  --surface: var(--color-surface);
  --surface-2: var(--color-surface-alt);
  --surface-3: var(--color-surface-alt);
  --surface-raised: var(--color-surface-alt);

  /* The conversation ground: ivory under the shared dot field
     (page-ground.css). */
  --bg-deeper: var(--color-ground);
  --bg-conv-header: var(--color-surface);
  /* WhatsApp Web's surface-highlight: search fill, hovered or open chat row,
     quoted-reply block. */
  --search-bg: var(--color-highlight);
  --input-bg: var(--color-surface-alt);

  /* ── Bubbles ──
     White coming in, the accent wash going out: the wash, not the lighter
     --color-accent-soft, so the message you sent out-reads the one you got. */
  --incoming-bubble: var(--color-surface);
  --outgoing-bubble: var(--color-accent-wash);

  /* Contact, not elevation. --shadow-xs is one pixel under a white
     shape lying on warm paper — the same two-part trick (tonal step + contact)
     WhatsApp uses. A bubble is still not an overlay. */
  --bubble-shadow: var(--shadow-xs);
  --composer-pill-shadow: var(--shadow-composer);
  --composer-btn-text: var(--color-muted);

  /* ── Text + icons ── */
  --text-primary: var(--color-fg);
  --text-secondary: var(--color-muted);
  --header-icon: var(--color-muted);

  /* The clock and ticks inside the outgoing bubble: --color-muted is too
     light on the accent wash; --color-muted-aaa keeps AA there. */
  --bubble-meta-on-outgoing: var(--color-muted-aaa);

  /* ── Date separator + quoted message ──
     The day divider is WhatsApp's white-at-90% system chip. */
  --date-sep-bg: var(--color-chip-system);
  --date-sep-text: var(--color-muted);
  --quote-bg: var(--color-highlight);
  --quote-bar: var(--color-accent);

  /* ── Ticks ──
     Only ever on the outgoing wash, so they share the clock's ink; read
     stays blue, the one colour users already read. */
  --ticks-read: var(--color-info);
  --ticks-delivered: var(--bubble-meta-on-outgoing);

  /* Queued — this device has the message, the server does not yet. It is the
     ordinary first instant of every send, so it is deliberately the SAME
     weight as a delivered tick: a clock that shouted would turn "working
     normally" into "something is wrong". Failure is the state that earns the
     alarm colour, and it is the only one that does. */
  --ticks-queued: var(--bubble-meta-on-outgoing);
  --ticks-failed: var(--color-danger-aaa);

  /* ── Unread badge — the accent, not WhatsApp green ── */
  --unread-badge-bg: var(--color-accent);

  /* ── Message bubble group ── */
  --message-bubble-group-avatar-size: 1.75rem;
  --message-bubble-group-avatar-gap: 0.625rem;

  /* ── Feedback ── */
  --success: var(--color-success);
  --warning: var(--color-warning);
  --danger: var(--color-danger);
  --scrollbar: var(--color-border);
  --scrollbar-thumb: var(--color-border-strong);

  /* ── Send button ── */
  --send-btn-bg: var(--color-accent);
  --send-btn-hover: var(--color-accent-hover);
  --send-btn-icon: var(--color-fg-on-accent);

  /* ── Navigation: WhatsApp iOS tab bar ── */
  --glass-bg: var(--color-glass-fill);
  --tab-inactive: var(--color-muted);
  --tab-active: var(--color-fg);
  --tab-selected-bg: var(--color-tab-selected);
  --disclosure-color: var(--color-border-strong);
  --tabbar-clearance: calc(var(--tabbar-height) + 2 * var(--tabbar-inset));
  --group-card-bg: var(--color-surface);
  /* The grouped ground: WhatsApp iOS's You tab. */
  --grouped-bg: var(--color-surface-alt);
  --row-pressed-bg: var(--color-surface-alt);
}

/* WhatsApp iOS below 840px: system font, Dynamic Type sizes (body 17,
   subheadline 15, caption 12) and iOS control sizes. bits-ui portals dialogs,
   menus, tooltips and link previews to <body>, outside .chat-surface, so
   their roots take the same scale here. */
@media (max-width: 839.98px) {
  .chat-surface,
  [data-dialog-content],
  [data-alert-dialog-content],
  [data-popover-content],
  [data-tooltip-content],
  [data-link-preview-content],
  [data-dropdown-menu-content],
  [data-context-menu-content],
  [data-menubar-content],
  [data-select-content],
  [data-combobox-content] {
    --font-body: var(--font-ios);
    --text-xs: 0.9375rem;
    --text-sm: 1.0625rem;
    --text-base: 1.0625rem;
    --text-lg: 1.25rem;
    --text-xl: 1.375rem;
    --weight-emphasized: var(--weight-semibold);
    --btn-height-sm: 1.75rem;
    --btn-height: 2.25rem;
    --btn-height-lg: 3.125rem;
    --btn-pad-x: 1rem;
    --btn-font-size: var(--text-xs);
    --field-height: 2.75rem;
    font-family: var(--font-body);
    font-size: var(--text-base);
  }
}

/* ── Chat surface roles ── */
.chat-surface {
  --chat-row-hover: var(--color-highlight);
  /* Filter chips: a tinted wash and the deep accent ink when selected. */
  --chip-selected-bg: var(--color-accent-soft);
  --chip-selected-ink: var(--color-accent-ink);
  --chip-idle-bg: var(--color-highlight);
  --chip-edge: var(--color-border-strong);
  --date-chip-shadow: var(--shadow-date-chip);
  --conv-header-shadow: var(--shadow-conv-header);
  --jump-btn-shadow: var(--shadow-jump-btn);
  /* No chat open: WhatsApp's intro panel, a white card on the wash. */
  --intro-bg: transparent;
  --intro-card-bg: var(--color-surface);
}

/* ── Controls roles ── */
.chat-surface {
  --toast-bg: var(--color-surface-inverse);
  --toast-fg: var(--color-fg-inverse);
}

/* ── Detail pages roles ──
   The detail pane paints the dot ground once; headers on phone, content,
   footers and empty panels stay transparent over it so the pattern never
   breaks. Sections are white cards. */
.chat-surface {
  --detail-bg: transparent;
  --detail-card-bg: var(--color-surface);
  --detail-header-bg: var(--color-surface);
  --detail-icon: var(--color-muted);
  --detail-btn-hover: var(--color-highlight);
}

/* ── Feature components roles ── */
.chat-surface {
  /* iOS segmented control: grey track, white selected segment. The track
     tint is laid over white so the dotted canvas never shows through it;
     read it with the `background` shorthand. */
  --seg-track-bg: linear-gradient(var(--color-tab-selected), var(--color-tab-selected)) var(--color-surface);
  --seg-selected-bg: var(--color-surface);
  --seg-selected-shadow: var(--shadow-sm);
}

/*
 * night-mode.css — the Night theme's screen layer. html[data-night-mode] is
 * set by the tenant's app.html (before first paint) and lib/night-mode.ts.
 * The same rules sit inline in the Jadilah app's app.html, which paints
 * before any sheet loads; app/template-parity.test.ts holds them equal.
 */

/* Static dimming covers the whole viewport, including portalled UI.
   Darken reduces every highlight, not just the scanline rows. The
   light palette and text geometry remain unchanged; no animated glow. */
html[data-night-mode]::after {
  --night-screen-rgb: 155, 155, 155;
  --night-dim-alpha: 0.16;
  --night-scanline-alpha: 0.06;
  --night-vignette-alpha: 0.04;
  content: "";
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10000;
  pointer-events: none;
  mix-blend-mode: darken;
  background-image:
    linear-gradient(rgba(var(--night-screen-rgb), var(--night-dim-alpha)), rgba(var(--night-screen-rgb), var(--night-dim-alpha))),
    repeating-linear-gradient(
      to bottom,
      rgba(var(--night-screen-rgb), var(--night-scanline-alpha)) 0,
      rgba(var(--night-screen-rgb), var(--night-scanline-alpha)) 2px,
      rgba(var(--night-screen-rgb), 0) 2px,
      rgba(var(--night-screen-rgb), 0) 4px
    ),
    radial-gradient(
      ellipse at center,
      rgba(var(--night-screen-rgb), 0) 35%,
      rgba(var(--night-screen-rgb), var(--night-vignette-alpha)) 100%
    );
}
/* Browser chrome cannot be dimmed by the layer, so it is tinted to
   match: Safari 26 samples the body background, other browsers read
   theme-color (copied from html in lib/night-mode.ts and app.html). That grey is what
   the layer makes of paper at the screen edges; re-measure it when the
   alphas above change. #app keeps the original paper under the layer. */
html[data-night-mode],
html[data-night-mode] body {
  /* design-tokens-ignore: measured from the layer, matches app.html */
  background-color: #eaeaea;
}
@media print, (forced-colors: active) {
  html[data-night-mode]::after {
    display: none;
  }
}


[data-accordion-root] {
  display: block;
  width: 100%;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

[data-accordion-item] {
  border-bottom: var(--border-width) solid var(--color-border);
}

[data-accordion-item]:last-child {
  border-bottom: none;
}

[data-accordion-header] {
  margin: 0;
}

[data-accordion-trigger] {
  /* Self-contained reset, same reason as switch.css: bits-ui
     Accordion.Trigger renders a native <button>, and the live app loads
     this file WITHOUT base.css — the app has no global stylesheet, only
     Storybook pulls base.css through index.css. Without this the UA drew a
     2px outset border around every row, and Storybook could not show it.
     The root already carries the one hairline frame; the trigger carries
     none. */
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  border: none;
  color: inherit;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  text-align: left;
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-accordion-trigger]:hover:not([data-disabled]) {
  background: var(--color-surface-alt);
}

[data-accordion-trigger][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

/* The chevron (or any icon in the row): the in-control glyph size. */
[data-accordion-trigger] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  flex-shrink: 0;
}

/* Chevron indicator — rotates on open. The trigger renders its label,
   so the agent can drop in any chevron node and tag it with this class
   to get the open-state rotation for free. */
[data-accordion-trigger] [data-accordion-chevron] {
  transition: transform var(--duration-normal) var(--ease-out);
}

[data-accordion-trigger][data-state='open'] [data-accordion-chevron] {
  transform: rotate(180deg);
}

/* Bits UI sets --bits-accordion-content-height to the measured content
   height when open; we transition between 0 and that value. The
   keyframe approach gives smoother open/close than transition: height,
   because closing from `height: <number>` to `height: 0` works
   reliably without flicker. */
[data-accordion-content] {
  overflow: hidden;
  color: var(--color-muted);
}

@keyframes bits-accordion-open {
  from { height: 0; }
  to { height: var(--bits-accordion-content-height); }
}

@keyframes bits-accordion-close {
  from { height: var(--bits-accordion-content-height); }
  to { height: 0; }
}

[data-accordion-content][data-state='open'] {
  animation: bits-accordion-open var(--duration-normal) var(--ease-out);
}

[data-accordion-content][data-state='closed'] {
  animation: bits-accordion-close var(--duration-normal) var(--ease-out);
}

[data-accordion-content] > * {
  padding: var(--space-2) var(--space-5) var(--space-4);
}

/*
 * alert-dialog.css — bits-ui AlertDialog, the confirmation.
 *
 * Desktop: the same WhatsApp Web dialog as dialog.css at the md width (400).
 * Below 840px: a WhatsApp iOS alert — a glass card 300 wide with 34pt
 * corners and 22pt padding, a 17/22 semibold title over a 15/20 message
 * (both centred), 48pt capsule buttons side by side (three or more stack),
 * a light scrim, and a scale 1.1 → 1 entrance.
 *
 * Put `data-dialog-actions` on the button row, as in dialog.css.
 */

[data-alert-dialog-overlay] {
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  z-index: 50;
  opacity: 1;
  transition: opacity var(--duration-modal) var(--ease-modal);
}

[data-alert-dialog-overlay][data-starting-style],
[data-alert-dialog-overlay][data-ending-style] {
  opacity: 0;
}

[data-alert-dialog-content] {
  font-family: var(--font-body);
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(1);
  box-sizing: border-box;
  width: 92vw;
  max-width: var(--dialog-width-md);
  max-height: calc(100dvh - var(--space-12));
  overflow-y: auto;
  background: var(--color-surface);
  color: var(--color-fg);
  border: none;
  border-radius: var(--dialog-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-strong);
  padding: var(--dialog-pad);
  z-index: 51;
  opacity: 1;
  transition:
    opacity var(--duration-dialog-box) var(--ease-modal),
    transform var(--duration-dialog-box) var(--ease-modal);
}

[data-alert-dialog-content][data-starting-style],
[data-alert-dialog-content][data-ending-style] {
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.9);
}

/* Same title and text as dialog.css: to a reader these are one object with
   two urgencies. */
[data-alert-dialog-title] {
  display: flex;
  align-items: center;
  min-height: var(--btn-height);
  margin: 0 0 var(--space-1);
  font-size: var(--dialog-title-size);
  font-weight: var(--dialog-title-weight);
  line-height: var(--dialog-title-line);
  letter-spacing: var(--tracking-normal);
  overflow-wrap: anywhere;
}

[data-alert-dialog-description] {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--dialog-text-size);
  line-height: var(--dialog-text-line);
}

[data-alert-dialog-content] [data-dialog-actions] {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--dialog-pad);
}

@media (max-width: 839.98px) {
  [data-alert-dialog-overlay] {
    background: var(--color-scrim-light);
  }

  [data-alert-dialog-content] {
    width: var(--alert-width);
    max-width: none;
    padding: var(--dialog-pad) var(--dialog-pad) calc(var(--dialog-pad) - var(--space-2));
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
    transition:
      opacity var(--duration-slow) var(--ease-out),
      transform var(--duration-slow) var(--ease-out);
  }

  [data-alert-dialog-content][data-starting-style],
  [data-alert-dialog-content][data-ending-style] {
    transform: translate(-50%, -50%) scale(1.1);
  }

  /* An iOS alert centres its title and message. */
  [data-alert-dialog-title] {
    justify-content: center;
    min-height: 0;
    margin-bottom: var(--space-1);
    text-align: center;
  }

  [data-alert-dialog-description] {
    text-align: center;
  }

  /* Buttons sit 14pt from the card edge, 8pt outside the text column. */
  [data-alert-dialog-content] [data-dialog-actions] {
    margin: var(--space-5) calc(-1 * var(--space-2)) 0;
  }

  [data-alert-dialog-content] [data-dialog-actions] > * {
    flex: 1 1 0;
    min-width: max-content;
    height: var(--dialog-btn-height);
    border-radius: var(--btn-radius);
  }

  [data-alert-dialog-content] [data-dialog-actions] > :first-child:nth-last-child(n + 3),
  [data-alert-dialog-content] [data-dialog-actions] > :first-child:nth-last-child(n + 3) ~ * {
    flex-basis: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-alert-dialog-overlay],
  [data-alert-dialog-content] {
    transition: none;
  }
}

/* Aspect Ratio — Bits UI wraps content in an outer div that uses
   padding-bottom (= 100/ratio%) to create the aspect-ratio box. The
   inner `[data-aspect-ratio-root]` div has no positioning of its own
   and must absolute-fill the outer box, otherwise children with
   percentage heights have nothing to size against. */
[data-aspect-ratio-root] {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
  border-radius: var(--radius-md);
}

[data-aspect-ratio-root] > * {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

[data-avatar-root] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  /* Rule 2 names the avatar as a meaningful circle: it stands in for a
     face. --radius-pill capsules a rectangle; on a square it is not a circle
     at any size but 50%. */
  border-radius: 50%;
  background: var(--color-surface-alt);
  color: var(--color-fg);
  font-weight: var(--weight-medium);
  font-size: var(--text-sm);
  overflow: hidden;
  vertical-align: middle;
}

[data-avatar-image] {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Initials stand in for a face, so they are set in the face the rest of the
   product speaks in — --font-body, inherited from the root above. The mono
   cut this used to carry gave every faceless contact a serial number.
   `text-transform` survives Rule 4 here because it is not emphasis: an
   initial IS a capital letter, and the caller passes a whole name that this
   has to normalise. Nothing is being shouted. */
[data-avatar-fallback] {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  text-transform: uppercase;
}

/*
 * button.css — the app's button.
 *
 * Desktop is WhatsApp Web's WDSButton: a pill 32/40/56 tall with a 14/20
 * emphasized label, a 10% state layer on hover and a .96 press. Below 840px
 * it is a WhatsApp iOS capsule at the iOS heights (the --btn-* tokens swap
 * there). The label is sentence-case --font-body, never mono or uppercase.
 *
 * The ink on the accent is --color-fg-on-accent, which each palette sets
 * for at least 4.5:1 on --color-accent; never assume white reads there.
 *
 * Variants are data attributes so a plain <button data-button-root> and a
 * bits-ui Button.Root read the same rules:
 *   data-variant  filled (default) · tonal · outline · borderless ·
 *                 destructive · destructive-tonal
 *                 (iOS: filled · tinted · gray · plain)
 *   data-size     sm (32) · lg (56); default 40
 *   data-icon     icon-only, square
 */

[data-button-root] {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--btn-height);
  padding: 0 var(--btn-pad-x);
  font-family: inherit;
  font-size: var(--btn-font-size);
  font-weight: var(--weight-emphasized);
  line-height: 1.25rem;
  letter-spacing: var(--tracking-normal);
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
  /* Transparent until the outline variant (or a caller) colours it. */
  border: var(--border-width) solid transparent;
  border-radius: var(--btn-radius);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--duration-press) var(--ease-press);
}

/* The state layer: the variant's ink at 10%, drawn over the fill. */
[data-button-root]::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--color-fg);
  opacity: 0;
  pointer-events: none;
}

@media (hover: hover) {
  [data-button-root]:hover:not(:disabled):not([data-disabled]):not([aria-disabled='true'])::after {
    opacity: var(--state-layer-opacity);
  }
}

[data-button-root]:active:not(:disabled):not([data-disabled]):not([aria-disabled='true']) {
  transform: scale(var(--press-scale));
}

[data-button-root] svg {
  width: var(--icon-md);
  height: var(--icon-md);
  flex-shrink: 0;
}

/* ── Sizes ── */
/* Press depth follows size: .94 small, .96 medium, .98 large. */
[data-button-root][data-size='sm'] {
  --press-scale: 0.94;
  height: var(--btn-height-sm);
  padding: 0 var(--space-4);
}

[data-button-root][data-size='lg'] {
  --press-scale: 0.98;
  height: var(--btn-height-lg);
  padding: 0 calc(var(--space-6) + var(--space-1));
}

[data-button-root][data-icon] {
  width: var(--btn-height);
  padding: 0;
}

[data-button-root][data-icon][data-size='sm'] {
  width: var(--btn-height-sm);
}

[data-button-root][data-icon][data-size='lg'] {
  width: var(--btn-height-lg);
}

/* ── Variants ── */
[data-button-root][data-variant='tonal'] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

[data-button-root][data-variant='outline'] {
  background: transparent;
  color: var(--color-accent-ink);
  border-color: var(--color-border-control);
}

[data-button-root][data-variant='borderless'] {
  background: transparent;
  color: var(--color-accent-ink);
  padding: 0 var(--space-4);
}

[data-button-root][data-variant='tonal']::after,
[data-button-root][data-variant='outline']::after,
[data-button-root][data-variant='borderless']::after {
  background: var(--color-accent);
}

[data-button-root][data-variant='destructive'] {
  background: var(--color-danger);
  color: var(--color-fg-on-dark);
}

[data-button-root][data-variant='destructive-tonal'] {
  background: var(--color-danger-bg);
  color: var(--color-danger);
}

[data-button-root][data-variant='destructive-tonal']::after {
  background: var(--color-danger);
}

/* Button.Root with an href renders a link, which has no :disabled; a
   disabled one carries aria-disabled="true" instead. */
[data-button-root][data-disabled],
[data-button-root][aria-disabled='true'],
[data-button-root]:disabled {
  opacity: var(--disabled-opacity);
  filter: grayscale(1);
  cursor: not-allowed;
}

/* ── WhatsApp iOS capsules ──
   filled and tinted keep their fills; outline becomes the gray (bordered)
   capsule, which reads on a white card and on the dot ground alike, and
   borderless the plain tinted label. Medium and small labels are 500, the
   large one semibold. A plain label dims while pressed. */
@media (max-width: 839.98px) {
  [data-button-root] {
    font-weight: var(--weight-medium);
  }

  [data-button-root][data-size='sm'] {
    padding: 0 var(--space-3);
  }

  [data-button-root][data-size='lg'] {
    padding: 0 var(--space-5);
    font-size: var(--text-base);
    line-height: 1.375rem;
    font-weight: var(--weight-semibold);
  }

  [data-button-root][data-variant='outline'] {
    background: var(--color-ios-fill-3);
    color: var(--color-accent-ink);
    border-color: transparent;
  }

  [data-button-root][data-variant='borderless'] {
    padding: 0 var(--space-2);
  }

  [data-button-root][data-variant='borderless']:active:not(:disabled):not([data-disabled]):not([aria-disabled='true']) {
    transform: none;
    opacity: 0.3;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-button-root] {
    transition: none;
  }
}

/* Calendar.Root has no surface of its own — it inherits the parent's
   background / border / padding. Consumers wrap it in a Popover or a
   card if they want a contained widget; otherwise it lives inline. */
[data-calendar-root] {
  font-family: var(--font-body);
  display: inline-block;
  font-size: var(--text-sm);
}

[data-calendar-header] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}

[data-calendar-heading] {
  font-weight: var(--weight-medium);
  font-size: var(--text-base);
}

[data-calendar-prev-button],
[data-calendar-next-button] {
  color: var(--color-muted);
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height-sm);
  height: var(--control-height-sm);
  border-radius: var(--btn-radius);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-calendar-prev-button] svg,
[data-calendar-next-button] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
}

[data-calendar-prev-button]:hover:not([data-disabled]):not(:disabled),
[data-calendar-next-button]:hover:not([data-disabled]):not(:disabled) {
  background: var(--color-surface-alt);
}

[data-calendar-grid] {
  width: 100%;
  border-collapse: collapse;
}

/* Rule 4: a weekday abbreviation is a WORD, shortened — Sen, Sel, Rab. It
   takes the same sentence-case --font-body as the numbers under it, one step
   down in size and in --color-muted so the grid still reads header-then-body.
   Tracked uppercase mono turned a familiar row of day names into a legend. */
[data-calendar-grid-head] {
  color: var(--color-muted);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-normal);
}

[data-calendar-head-cell] {
  padding: var(--space-1);
  font-weight: var(--weight-regular);
  text-align: center;
}

[data-calendar-cell] {
  padding: 0;
  text-align: center;
}

[data-calendar-day] {
  color: var(--color-fg);
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height-sm);
  height: var(--control-height-sm);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-calendar-day]:hover:not([data-disabled]):not(:disabled):not([data-selected]) {
  background: var(--color-surface-alt);
}

[data-calendar-day][data-selected] {
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
}

[data-calendar-day][data-outside-month] {
  color: var(--color-subtle);
}

[data-calendar-day][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-calendar-day][data-today] {
  font-weight: var(--weight-medium);
  outline: var(--border-width) solid var(--color-accent);
}

[data-calendar-prev-button][data-disabled],
[data-calendar-next-button][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

/*
 * checkbox.css — bits-ui Checkbox, and any native <input type="checkbox"
 * data-checkbox-root>. WhatsApp Web's WDSBaseCheckbox: an 18px square with
 * 4px corners and a 2px control stroke; checked fills with the accent and
 * the tick scales in over 160ms. bits-ui draws the caller's icon; a native
 * input draws --checkmark.
 */
[data-checkbox-root] {
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--checkbox-size);
  height: var(--checkbox-size);
  padding: 0;
  border: var(--control-stroke) solid var(--color-border-control);
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--color-fg-on-accent);
  cursor: pointer;
}

[data-checkbox-root][data-state='checked'],
[data-checkbox-root][data-state='indeterminate'],
input[data-checkbox-root]:checked {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

input[data-checkbox-root] {
  display: inline-grid;
  place-content: center;
  margin: 0;
}

input[data-checkbox-root]::before {
  content: '';
  width: 0.75rem;
  height: 0.75rem;
  background: var(--color-fg-on-accent);
  -webkit-mask: var(--checkmark) center / contain no-repeat;
  mask: var(--checkmark) center / contain no-repeat;
  transform: scale(0);
  transition: transform var(--duration-normal) ease-out;
}

input[data-checkbox-root]:checked::before {
  transform: scale(1);
}

/* The tick fills the box inside its stroke. */
[data-checkbox-root] svg {
  width: calc(var(--checkbox-size) - 2 * var(--control-stroke));
  height: calc(var(--checkbox-size) - 2 * var(--control-stroke));
  flex-shrink: 0;
  animation: checkbox-tick var(--duration-normal) ease-out;
}

[data-checkbox-root]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

[data-checkbox-root][data-disabled] {
  opacity: var(--disabled-opacity);
  filter: grayscale(1);
  cursor: not-allowed;
}

@keyframes checkbox-tick {
  from { transform: scale(0); }
}

@media (prefers-reduced-motion: reduce) {
  [data-checkbox-root] svg {
    animation: none;
  }

  input[data-checkbox-root]::before {
    transition: none;
  }
}

[data-collapsible-root] {
  display: block;
}

[data-collapsible-trigger] {
  color: var(--color-fg);
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  font-family: var(--font-body);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  border-radius: var(--radius-sm);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-collapsible-trigger]:hover:not([data-disabled]):not(:disabled) {
  background: var(--color-surface-alt);
}

[data-collapsible-content] {
  overflow: hidden;
}

@keyframes bits-collapsible-open {
  from { height: 0; }
  to { height: var(--bits-collapsible-content-height); }
}

@keyframes bits-collapsible-close {
  from { height: var(--bits-collapsible-content-height); }
  to { height: 0; }
}

[data-collapsible-content][data-state='open'] {
  animation: bits-collapsible-open var(--duration-normal) var(--ease-out);
}

[data-collapsible-content][data-state='closed'] {
  animation: bits-collapsible-close var(--duration-normal) var(--ease-out);
}

[data-collapsible-content][data-state='open'] > * {
  padding-top: var(--space-2);
}

[data-collapsible-trigger][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

/*
 * combobox.css — bits-ui Combobox.
 *
 * Combobox.Root emits no DOM element. Combobox.Input + Combobox.Trigger
 * render as siblings; wrap them in `.combobox-field` to fuse them into one
 * WhatsApp Web text field (40px, 12px corners, 1px outline → 2px accent
 * ring on focus). The list is the WDSMenu panel (see dropdown-menu.css).
 */

[data-combobox-input] {
  box-sizing: border-box;
  height: var(--field-height);
  padding: 0 var(--space-4);
  font-family: inherit;
  font-size: var(--text-xs);
  line-height: 1.25rem;
  border: none;
  border-radius: var(--field-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-control);
  background: var(--color-surface);
  color: var(--color-fg);
  caret-color: var(--color-accent);
  outline: none;
}

[data-combobox-input]:hover:not(:focus):not([data-disabled]) {
  background: var(--color-highlight);
}

[data-combobox-input]:focus {
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-accent);
}

[data-combobox-trigger] {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--field-height);
  height: var(--field-height);
  padding: 0;
  border: none;
  border-radius: var(--field-radius);
  background: transparent;
  color: var(--color-muted);
  cursor: pointer;
}

[data-combobox-trigger]:hover:not([data-disabled]) {
  color: var(--color-fg);
}

/* Unified field: the outline moves to the wrapper and the chevron sits
   inside it. */
.combobox-field {
  display: inline-flex;
  align-items: center;
  width: 100%;
  max-width: 20rem;
  border-radius: var(--field-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-control);
  background: var(--color-surface);
}

.combobox-field:hover:not(:focus-within) {
  background: var(--color-highlight);
}

.combobox-field:focus-within {
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-accent);
}

.combobox-field [data-combobox-input] {
  flex: 1;
  min-width: 0;
  box-shadow: none;
  background: transparent;
}

[data-combobox-input][data-disabled],
[data-combobox-trigger][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-combobox-content] {
  box-sizing: border-box;
  min-width: max(var(--menu-min-width), var(--bits-combobox-anchor-width));
  padding: var(--menu-pad-y) var(--menu-pad-x);
  color: var(--color-fg);
  font-family: var(--font-body);
  background: var(--color-surface);
  /* design-tokens-ignore: a floating panel edge; the trigger keeps the control boundary. */
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  max-height: 20rem;
  overflow-y: auto;
  transform-origin: var(--bits-floating-transform-origin, top);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-combobox-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-combobox-content][data-ending-style] {
  opacity: 0;
}

[data-combobox-item] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  border-radius: var(--menu-item-radius);
  cursor: pointer;
  user-select: none;
  outline: none;
}

[data-combobox-item] + [data-combobox-item] {
  margin-top: var(--menu-gap);
}

[data-combobox-item] svg {
  width: var(--menu-icon-size);
  height: var(--menu-icon-size);
  flex-shrink: 0;
}

[data-combobox-item][data-highlighted] {
  background: var(--color-highlight);
}

[data-combobox-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

/* The chosen value: accent ink and a tick-free wash, like a selected chip. */
[data-combobox-item][data-selected] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
  font-weight: var(--weight-emphasized);
}

/* Group heading: 12/16 emphasized, muted, sentence case. */
[data-combobox-group-label] {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-emphasized);
  color: var(--color-muted);
  letter-spacing: var(--tracking-normal);
}

/* WhatsApp iOS context menu: glass, 250 wide, 26pt corners, 44pt rows of
   17/22 with the highlight inset 8pt. */
@media (max-width: 839.98px) {
  [data-combobox-content] {
    border: none;
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
  }

  [data-combobox-group-label] {
    padding: var(--space-1) var(--menu-item-pad-x) var(--space-2);
    font-family: inherit;
    font-size: var(--menu-heading-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
  }

}

/* WhatsApp Web menu entrance: fade, 8px towards the anchor, .95 → 1.01 → 1. */
@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-combobox-content] {
    animation: none;
  }
}

/* bits-ui Command: the WDSMenu panel (16px corners, hairline, popover
   shadow) with a search line on top and WDSMenu items below. */
[data-command-root] {
  color: var(--color-fg);
  font-family: var(--font-body);
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 32rem;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  overflow: hidden;
  box-shadow: var(--shadow-popover);
}

[data-command-input] {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: transparent;
  border: none;
  border-bottom: var(--border-width) solid var(--color-border-control);
  outline: none;
  font-size: var(--text-sm);
  color: var(--color-fg);
  caret-color: var(--color-accent);
  font-family: inherit;
}

[data-command-input]:focus {
  border-bottom-color: var(--color-accent);
}

[data-command-input]::placeholder {
  color: var(--color-muted);
}

[data-command-list] {
  max-height: 20rem;
  overflow-y: auto;
  padding: var(--menu-pad-y) var(--menu-pad-x);
}

/* Group heading: 12/16 emphasized, muted, sentence case. */
[data-command-group-heading] {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-emphasized);
  color: var(--color-muted);
  letter-spacing: var(--tracking-normal);
}

[data-command-item] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  border-radius: var(--menu-item-radius);
  cursor: pointer;
}

[data-command-item][data-selected] {
  background: var(--color-highlight);
}

/* An empty state is prose: flush left like everything else. */
[data-command-empty] {
  padding: var(--space-6);
  color: var(--color-muted);
  font-size: var(--text-xs);
}

[data-command-separator] {
  height: var(--border-width);
  background: var(--color-border);
  margin: var(--space-1) var(--space-2);
}

/*
 * context-menu.css — WhatsApp Web's WDSMenu on desktop: a white panel with 16px
 * corners, 4px padding, a hairline and the popover shadow; 36px items with
 * 12px corners and 14/20 labels, 4px apart. Opens with a 300ms fade, 8px
 * slide and .95 → 1 scale; closes with a 150ms fade. Below 840px it is the
 * WhatsApp iOS glass context menu.
 */

[data-context-menu-content],
[data-context-menu-sub-content] {
  box-sizing: border-box;
  min-width: var(--menu-min-width);
  padding: var(--menu-pad-y) var(--menu-pad-x);
  color: var(--color-fg);
  font-family: var(--font-body);
  background: var(--color-surface);
  /* design-tokens-ignore: a floating panel edge; the trigger keeps the control boundary. */
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  transform-origin: var(--bits-floating-transform-origin, top);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-context-menu-content][data-side='top'],
[data-context-menu-sub-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-context-menu-content][data-ending-style],
[data-context-menu-sub-content][data-ending-style] {
  opacity: 0;
}

[data-context-menu-item],
[data-context-menu-sub-trigger],
[data-context-menu-checkbox-item],
[data-context-menu-radio-item] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  border-radius: var(--menu-item-radius);
  cursor: pointer;
  user-select: none;
  outline: none;
}

:is([data-context-menu-item], [data-context-menu-sub-trigger], [data-context-menu-checkbox-item], [data-context-menu-radio-item]) + :is([data-context-menu-item], [data-context-menu-sub-trigger], [data-context-menu-checkbox-item], [data-context-menu-radio-item]) {
  margin-top: var(--menu-gap);
}

[data-context-menu-item] svg,
[data-context-menu-sub-trigger] svg,
[data-context-menu-checkbox-item] svg,
[data-context-menu-radio-item] svg {
  width: var(--menu-icon-size);
  height: var(--menu-icon-size);
  flex-shrink: 0;
}

[data-context-menu-item][data-highlighted],
[data-context-menu-sub-trigger][data-highlighted],
[data-context-menu-checkbox-item][data-highlighted],
[data-context-menu-radio-item][data-highlighted] {
  background: var(--color-highlight);
}

/* Destructive items: add data-destructive. */
[data-context-menu-item][data-destructive],
[data-context-menu-sub-trigger][data-destructive],
[data-context-menu-checkbox-item][data-destructive],
[data-context-menu-radio-item][data-destructive] {
  color: var(--color-danger);
}

[data-context-menu-item][data-destructive][data-highlighted],
[data-context-menu-sub-trigger][data-destructive][data-highlighted],
[data-context-menu-checkbox-item][data-destructive][data-highlighted],
[data-context-menu-radio-item][data-destructive][data-highlighted] {
  background: var(--color-danger-bg);
}

[data-context-menu-item][data-disabled],
[data-context-menu-sub-trigger][data-disabled],
[data-context-menu-checkbox-item][data-disabled],
[data-context-menu-radio-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-context-menu-separator] {
  height: var(--border-width);
  background: var(--color-border);
  margin: var(--space-1) var(--space-2);
}

/* Group heading: 12/16 emphasized, muted, sentence case. */
[data-context-menu-group-heading] {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-emphasized);
  color: var(--color-muted);
  letter-spacing: var(--tracking-normal);
}

[data-context-menu-shortcut] {
  margin-left: auto;
  padding: 0 var(--space-1);
  border-radius: var(--radius-xs);
  background: var(--color-highlight);
  font-size: var(--text-2xs);
  line-height: 1rem;
  color: var(--color-muted);
}

/* WhatsApp iOS context menu: glass, 250 wide, 26pt corners, 44pt rows of
   17/22 with the highlight inset 8pt. */
@media (max-width: 839.98px) {
  [data-context-menu-content],
  [data-context-menu-sub-content] {
    border: none;
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
  }

  [data-context-menu-group-heading] {
    padding: var(--space-1) var(--menu-item-pad-x) var(--space-2);
    font-family: inherit;
    font-size: var(--menu-heading-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
  }

  [data-context-menu-separator] {
    margin: var(--space-2) calc(-1 * var(--menu-pad-x));
  }
}

/* WhatsApp Web menu entrance: fade, 8px towards the anchor, .95 → 1.01 → 1. */
@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-context-menu-content],
  [data-context-menu-sub-content] {
    animation: none;
  }
}

/* WhatsApp Web text field: 40px, 12px corners, 1px outline → 2px accent. */
[data-date-field-input] {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  height: var(--field-height);
  padding: 0 var(--space-4);
  border: none;
  border-radius: var(--field-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-control);
  background: var(--color-surface);
  /* No --font-mono. The mono face is for code and data the user might
     copy; a date field is chrome they type into, and it was taking the
     mono face purely to line the segments up. tabular-nums already does that,
     on the body face, which is why it stays and the family goes. */
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
}

[data-date-field-input]:focus-within {
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-accent);
}

/* The segment highlight is a dense inline mark sitting INSIDE the 12px field,
   so it takes --radius-xs — matching the field's own corner would have the
   day chip curve as hard as the box containing it. */
[data-date-field-segment] {
  padding: 0 var(--space-1);
  border-radius: var(--radius-xs);
  color: var(--color-fg);
  outline: none;
}

/* bits-ui 2.18 sets no data-focused or data-placeholder on a segment: an
   empty one reads aria-valuetext="Empty", and the one being typed into is
   the focused element. */
[data-date-field-segment][aria-valuetext='Empty'] {
  color: var(--color-muted);
}

[data-date-field-segment]:focus {
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
}

[data-date-field-segment][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-date-field-label] {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

[data-date-field-input][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-date-field-input][data-disabled] [data-segment] {
  color: var(--color-subtle);
}

/* date-picker composes date-field + popover + calendar. The trigger
   delegates to PopoverTrigger and emits `data-popover-trigger` (not
   any date-picker-specific attribute) — Bits UI defines no extra parts
   for the picker family. Use `data-segment="trigger"` (set by Bits UI
   on the picker's trigger button) to target the picker's calendar
   button specifically, distinguishing it from other PopoverTriggers. */

[data-popover-trigger][data-segment='trigger'] {
  margin-left: var(--space-1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height-sm);
  height: var(--control-height-sm);
  border-radius: var(--radius-sm);
  color: var(--color-muted);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

[data-popover-trigger][data-segment='trigger'] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
}

[data-popover-trigger][data-segment='trigger']:hover {
  background: var(--color-surface-alt);
  color: var(--color-fg);
}

/* DateRangeField composes two DateField.Input children inside its Root.
   The Inputs emit `data-date-field-input` (shared component) and
   segments emit `data-date-field-segment` — both styled in
   date-field.css. Here we only style the outer Root as a layout
   wrapper. */

[data-date-range-field-root] {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
  font-size: var(--text-sm);
}

/* A phone cannot hold the label and both halves on one line: the label
   takes a line of its own and the halves wrap under it. */
@media (max-width: 639.98px) {
  [data-date-range-field-root] {
    flex-wrap: wrap;
  }

  [data-date-range-field-label] {
    flex-basis: 100%;
  }
}

/* date-range-picker composes date-range-field + popover + range-calendar.
   Like DatePicker, the trigger delegates to PopoverTrigger and emits
   `data-popover-trigger` + `data-segment="trigger"` — the picker family
   doesn't define its own data-attribute. The shared
   [data-popover-trigger][data-segment='trigger'] rule in
   date-picker.css already styles it; nothing more to add here. */

/*
 * dialog.css — bits-ui Dialog.
 *
 * Desktop is WhatsApp Web's WDSDialog: a white box with 28px corners and a
 * 1px inset outline (no drop shadow), 560 wide by default (data-size sm 300,
 * md 400, xl 680; all capped at 92vw), 24px padding, a Body1 title, a 14/20
 * muted description, and a right-aligned footer of pill buttons 8px apart.
 * The backdrop fades in over 300ms and the box scales in over 200ms.
 *
 * Below 840px it is a WhatsApp iOS sheet: a glass card floating 8pt from the
 * sides and bottom with concentric corners, a 36x5 grabber, and content that
 * scrolls inside it.
 *
 * Put `data-dialog-actions` on the row of buttons at the end of a dialog.
 */

[data-dialog-overlay] {
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  z-index: 50;
  opacity: 1;
  transition: opacity var(--duration-modal) var(--ease-modal);
}

[data-dialog-overlay][data-starting-style],
[data-dialog-overlay][data-ending-style] {
  opacity: 0;
}

[data-dialog-content] {
  font-family: var(--font-body);
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(1);
  box-sizing: border-box;
  width: 92vw;
  max-width: var(--dialog-width-lg);
  max-height: calc(100dvh - var(--space-12));
  overflow-y: auto;
  background: var(--color-surface);
  color: var(--color-fg);
  border: none;
  border-radius: var(--dialog-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-strong);
  padding: var(--dialog-pad);
  z-index: 51;
  opacity: 1;
  transition:
    opacity var(--duration-dialog-box) var(--ease-modal),
    transform var(--duration-dialog-box) var(--ease-modal);
}

[data-dialog-content][data-starting-style],
[data-dialog-content][data-ending-style] {
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.9);
}

[data-dialog-content][data-size='sm'] { max-width: var(--dialog-width-sm); }
[data-dialog-content][data-size='md'] { max-width: var(--dialog-width-md); }
[data-dialog-content][data-size='xl'] { max-width: var(--dialog-width-xl); }

/* The title row is 40px tall so it lines up with a 40px close button in the
   corner; the end padding keeps a long title clear of it. */
[data-dialog-title] {
  display: flex;
  align-items: center;
  min-height: var(--btn-height);
  margin: 0 0 var(--space-1);
  padding-inline-end: calc(var(--btn-height) + var(--space-2));
  font-size: var(--dialog-title-size);
  font-weight: var(--dialog-title-weight);
  line-height: var(--dialog-title-line);
  letter-spacing: var(--tracking-normal);
  overflow-wrap: anywhere;
}

[data-dialog-description] {
  margin: 0 0 var(--space-6);
  color: var(--color-muted);
  font-size: var(--dialog-text-size);
  line-height: var(--dialog-text-line);
}

[data-dialog-actions] {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--dialog-pad);
}

/* A Dialog.Close straight in the content is the corner close: a 40px round
   icon button level with the title row. One in the actions row is a footer
   button and keeps its own look.
   It is always the content's first child. Floated right with no height of
   its own, it sits in the corner without moving the title; sticky, it stays
   there while a long dialog scrolls under it, so the way out never scrolls
   away. Content laid out as flex or grid ignores the float, so the
   self-alignment keeps it right there too. */
[data-dialog-content] > [data-dialog-close] {
  position: sticky;
  top: 0;
  z-index: 1;
  float: right;
  align-self: flex-end;
  justify-self: end;
  flex-shrink: 0;
  margin-bottom: calc(var(--btn-height) * -1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--btn-height);
  height: var(--btn-height);
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-muted);
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

[data-dialog-content] > [data-dialog-close]:hover {
  background: linear-gradient(var(--color-highlight), var(--color-highlight)),
    var(--color-surface);
  color: var(--color-fg);
}

[data-dialog-content] > [data-dialog-close] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
}

@media (max-width: 839.98px) {
  [data-dialog-overlay] {
    background: var(--color-scrim-light);
  }

  [data-dialog-content] {
    top: auto;
    left: var(--sheet-inset);
    right: var(--sheet-inset);
    bottom: calc(var(--sheet-inset) + env(safe-area-inset-bottom, 0px));
    transform: none;
    width: auto;
    /* On a tablet the sheet stays a phone-width card, centred. */
    max-width: var(--sheet-max-width);
    margin: 0 auto;
    max-height: calc(100dvh - var(--space-12) - env(safe-area-inset-top, 0px));
    overscroll-behavior: contain;
    padding: calc(var(--space-4) + var(--grabber-height)) var(--dialog-pad) var(--dialog-pad);
    border-radius: var(--sheet-radius);
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
    transition: transform var(--duration-push) var(--ease-ios);
  }

  [data-dialog-content][data-size] {
    max-width: var(--sheet-max-width);
  }

  [data-dialog-content][data-starting-style],
  [data-dialog-content][data-ending-style] {
    opacity: 1;
    transform: translateY(calc(100% + var(--sheet-inset)));
  }

  /* The grabber: 36x5, 5pt from the top, in the tertiary ink. */
  [data-dialog-content]::before {
    content: '';
    position: absolute;
    top: 0.3125rem;
    left: 50%;
    width: var(--grabber-width);
    height: var(--grabber-height);
    margin-left: calc(var(--grabber-width) / -2);
    border-radius: var(--radius-xs);
    background: var(--color-border-strong);
  }

  [data-dialog-title] {
    justify-content: center;
    text-align: center;
    padding-inline-start: calc(var(--btn-height) + var(--space-2));
  }

  [data-dialog-description] {
    text-align: center;
  }

  /* iOS: a grey circle, level with the title under the grabber. */
  /* The iOS grey, laid over white so it stays opaque over scrolled text. */
  [data-dialog-content] > [data-dialog-close] {
    margin-right: calc(var(--space-4) - var(--dialog-pad));
    background: linear-gradient(var(--color-ios-fill-3), var(--color-ios-fill-3)),
      var(--color-surface);
  }

  /* iOS footer: two capsules share the row; three or more, or labels too
     long for half the row, stack. */
  [data-dialog-actions] > * {
    flex: 1 1 0;
    min-width: max-content;
    height: var(--dialog-btn-height);
    border-radius: var(--btn-radius);
  }

  [data-dialog-actions] > :first-child:nth-last-child(n + 3),
  [data-dialog-actions] > :first-child:nth-last-child(n + 3) ~ * {
    flex-basis: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-dialog-overlay],
  [data-dialog-content] {
    transition: none;
  }
}

/*
 * dropdown-menu.css — WhatsApp Web's WDSMenu on desktop: a white panel with 16px
 * corners, 4px padding, a hairline and the popover shadow; 36px items with
 * 12px corners and 14/20 labels, 4px apart. Opens with a 300ms fade, 8px
 * slide and .95 → 1 scale; closes with a 150ms fade. Below 840px it is the
 * WhatsApp iOS glass context menu.
 */

[data-dropdown-menu-content],
[data-dropdown-menu-sub-content] {
  box-sizing: border-box;
  min-width: var(--menu-min-width);
  padding: var(--menu-pad-y) var(--menu-pad-x);
  color: var(--color-fg);
  font-family: var(--font-body);
  background: var(--color-surface);
  /* design-tokens-ignore: a floating panel edge; the trigger keeps the control boundary. */
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  transform-origin: var(--bits-floating-transform-origin, top);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-dropdown-menu-content][data-side='top'],
[data-dropdown-menu-sub-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-dropdown-menu-content][data-ending-style],
[data-dropdown-menu-sub-content][data-ending-style] {
  opacity: 0;
}

[data-dropdown-menu-item],
[data-dropdown-menu-sub-trigger],
[data-dropdown-menu-checkbox-item],
[data-dropdown-menu-radio-item] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  border-radius: var(--menu-item-radius);
  cursor: pointer;
  user-select: none;
  outline: none;
}

:is([data-dropdown-menu-item], [data-dropdown-menu-sub-trigger], [data-dropdown-menu-checkbox-item], [data-dropdown-menu-radio-item]) + :is([data-dropdown-menu-item], [data-dropdown-menu-sub-trigger], [data-dropdown-menu-checkbox-item], [data-dropdown-menu-radio-item]) {
  margin-top: var(--menu-gap);
}

[data-dropdown-menu-item] svg,
[data-dropdown-menu-sub-trigger] svg,
[data-dropdown-menu-checkbox-item] svg,
[data-dropdown-menu-radio-item] svg {
  width: var(--menu-icon-size);
  height: var(--menu-icon-size);
  flex-shrink: 0;
}

[data-dropdown-menu-item][data-highlighted],
[data-dropdown-menu-sub-trigger][data-highlighted],
[data-dropdown-menu-checkbox-item][data-highlighted],
[data-dropdown-menu-radio-item][data-highlighted] {
  background: var(--color-highlight);
}

/* Destructive items: add data-destructive. */
[data-dropdown-menu-item][data-destructive],
[data-dropdown-menu-sub-trigger][data-destructive],
[data-dropdown-menu-checkbox-item][data-destructive],
[data-dropdown-menu-radio-item][data-destructive] {
  color: var(--color-danger);
}

[data-dropdown-menu-item][data-destructive][data-highlighted],
[data-dropdown-menu-sub-trigger][data-destructive][data-highlighted],
[data-dropdown-menu-checkbox-item][data-destructive][data-highlighted],
[data-dropdown-menu-radio-item][data-destructive][data-highlighted] {
  background: var(--color-danger-bg);
}

[data-dropdown-menu-item][data-disabled],
[data-dropdown-menu-sub-trigger][data-disabled],
[data-dropdown-menu-checkbox-item][data-disabled],
[data-dropdown-menu-radio-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-dropdown-menu-separator] {
  height: var(--border-width);
  background: var(--color-border);
  margin: var(--space-1) var(--space-2);
}

/* Group heading: 12/16 emphasized, muted, sentence case. */
[data-dropdown-menu-group-heading] {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-emphasized);
  color: var(--color-muted);
  letter-spacing: var(--tracking-normal);
}

[data-dropdown-menu-shortcut] {
  margin-left: auto;
  padding: 0 var(--space-1);
  border-radius: var(--radius-xs);
  background: var(--color-highlight);
  font-size: var(--text-2xs);
  line-height: 1rem;
  color: var(--color-muted);
}

/* WhatsApp iOS context menu: glass, 250 wide, 26pt corners, 44pt rows of
   17/22 with the highlight inset 8pt. */
@media (max-width: 839.98px) {
  [data-dropdown-menu-content],
  [data-dropdown-menu-sub-content] {
    border: none;
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
  }

  [data-dropdown-menu-group-heading] {
    padding: var(--space-1) var(--menu-item-pad-x) var(--space-2);
    font-family: inherit;
    font-size: var(--menu-heading-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
  }

  [data-dropdown-menu-separator] {
    margin: var(--space-2) calc(-1 * var(--menu-pad-x));
  }
}

/* WhatsApp Web menu entrance: fade, 8px towards the anchor, .95 → 1.01 → 1. */
@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-dropdown-menu-content],
  [data-dropdown-menu-sub-content] {
    animation: none;
  }
}

[data-label-root] {
  display: inline-block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-fg);
  line-height: var(--line-snug);
  user-select: none;
}

[data-label-root][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

/* bits-ui LinkPreview: the popover panel (see popover.css) at 12px padding. */
[data-link-preview-content] {
  box-sizing: border-box;
  color: var(--color-fg);
  font-family: var(--font-body);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  padding: var(--space-3);
  max-width: 20rem;
  font-size: var(--text-xs);
  line-height: 1.25rem;
  z-index: 60;
  transform-origin: var(--bits-floating-transform-origin, center);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-link-preview-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-link-preview-content][data-ending-style] {
  opacity: 0;
}

@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-link-preview-content] {
    animation: none;
  }
}

/*
 * menubar.css — WhatsApp Web's WDSMenu on desktop: a white panel with 16px
 * corners, 4px padding, a hairline and the popover shadow; 36px items with
 * 12px corners and 14/20 labels, 4px apart. Opens with a 300ms fade, 8px
 * slide and .95 → 1 scale; closes with a 150ms fade. Below 840px the menus
 * are the WhatsApp iOS glass context menu; the bar keeps 36pt capsule
 * triggers.
 */

[data-menubar-root] {
  display: inline-flex;
  align-items: center;
  gap: var(--menu-gap);
  padding: var(--menu-pad-y) var(--menu-pad-x);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
}

[data-menubar-trigger] {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  border: none;
  border-radius: var(--menu-item-radius);
  background: transparent;
  color: var(--color-fg);
  font-family: var(--font-body);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  font-weight: var(--weight-emphasized);
  cursor: pointer;
  user-select: none;
}

[data-menubar-trigger][data-state='open'],
[data-menubar-trigger][data-highlighted] {
  background: var(--color-highlight);
}

[data-menubar-trigger][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-menubar-content],
[data-menubar-sub-content] {
  box-sizing: border-box;
  min-width: var(--menu-min-width);
  padding: var(--menu-pad-y) var(--menu-pad-x);
  color: var(--color-fg);
  font-family: var(--font-body);
  background: var(--color-surface);
  /* design-tokens-ignore: a floating panel edge; the trigger keeps the control boundary. */
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  transform-origin: var(--bits-floating-transform-origin, top);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-menubar-content][data-side='top'],
[data-menubar-sub-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-menubar-content][data-ending-style],
[data-menubar-sub-content][data-ending-style] {
  opacity: 0;
}

[data-menubar-item],
[data-menubar-sub-trigger],
[data-menubar-checkbox-item],
[data-menubar-radio-item] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  border-radius: var(--menu-item-radius);
  cursor: pointer;
  user-select: none;
  outline: none;
}

:is([data-menubar-item], [data-menubar-sub-trigger], [data-menubar-checkbox-item], [data-menubar-radio-item]) + :is([data-menubar-item], [data-menubar-sub-trigger], [data-menubar-checkbox-item], [data-menubar-radio-item]) {
  margin-top: var(--menu-gap);
}

[data-menubar-item] svg,
[data-menubar-sub-trigger] svg,
[data-menubar-checkbox-item] svg,
[data-menubar-radio-item] svg {
  width: var(--menu-icon-size);
  height: var(--menu-icon-size);
  flex-shrink: 0;
}

[data-menubar-item][data-highlighted],
[data-menubar-sub-trigger][data-highlighted],
[data-menubar-checkbox-item][data-highlighted],
[data-menubar-radio-item][data-highlighted] {
  background: var(--color-highlight);
}

/* Destructive items: add data-destructive. */
[data-menubar-item][data-destructive],
[data-menubar-sub-trigger][data-destructive],
[data-menubar-checkbox-item][data-destructive],
[data-menubar-radio-item][data-destructive] {
  color: var(--color-danger);
}

[data-menubar-item][data-destructive][data-highlighted],
[data-menubar-sub-trigger][data-destructive][data-highlighted],
[data-menubar-checkbox-item][data-destructive][data-highlighted],
[data-menubar-radio-item][data-destructive][data-highlighted] {
  background: var(--color-danger-bg);
}

[data-menubar-item][data-disabled],
[data-menubar-sub-trigger][data-disabled],
[data-menubar-checkbox-item][data-disabled],
[data-menubar-radio-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-menubar-separator] {
  height: var(--border-width);
  background: var(--color-border);
  margin: var(--space-1) var(--space-2);
}

/* Group heading: 12/16 emphasized, muted, sentence case. */
[data-menubar-group-heading] {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-emphasized);
  color: var(--color-muted);
  letter-spacing: var(--tracking-normal);
}

/* WhatsApp iOS context menu: glass, 250 wide, 26pt corners, 44pt rows of
   17/22 with the highlight inset 8pt. */
@media (max-width: 839.98px) {
  /* The bar stays a capsule of 36pt triggers; the iOS rows and corners are
     for the menus. */
  [data-menubar-root] {
    gap: var(--space-1);
    padding: var(--space-1);
    border-radius: var(--radius-pill);
  }

  [data-menubar-trigger] {
    min-height: var(--control-height);
    padding: 0 var(--space-3);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    line-height: 1.25rem;
  }

  [data-menubar-content],
  [data-menubar-sub-content] {
    border: none;
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
  }

  [data-menubar-group-heading] {
    padding: var(--space-1) var(--menu-item-pad-x) var(--space-2);
    font-family: inherit;
    font-size: var(--menu-heading-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
  }

  [data-menubar-separator] {
    margin: var(--space-2) calc(-1 * var(--menu-pad-x));
  }
}

/* WhatsApp Web menu entrance: fade, 8px towards the anchor, .95 → 1.01 → 1. */
@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-menubar-content],
  [data-menubar-sub-content] {
    animation: none;
  }
}

/*
 * meter.css — a static quantity inside a known range: quota used, disk
 * filled, seats taken. (Progress, in progress.css, is the same bar for a
 * task that is moving; the two share a shape on purpose.)
 *
 * Rule 2 names a bar track as one of the four things the capsule is FOR,
 * alongside the search field, the composer and chips, so the track and its
 * fill are --radius-pill. The 4px rectangle this used to be was chosen to
 * look like an readout on a control panel; on a soft interface it reads as
 * an unfinished input. A round cap is also the honest shape: the fill has
 * two ends and neither of them is a corner of anything.
 */

[data-meter-root] {
  position: relative;
  width: 100%;
  height: var(--space-2);
  background: var(--color-surface-alt);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

/* The fill is square-cornered and clipped by the track's own radius, so its
   leading edge picks up the capsule at 100% and stays flat mid-run — a
   separately-rounded fill pinches to a lozenge at low values and reads as a
   smaller number than it is. */
[data-meter-indicator] {
  display: block;
  height: 100%;
  background: var(--color-accent);
  border-radius: 0;
  transition: width var(--duration-normal) var(--ease-out);
}

/* A meter that reports a CONDITION and not only a quantity — a disk filling
   up, memory getting tight. The semantic tint REPLACES the accent fill rather
   than sitting beside it: two signal colours on one bar is two claims about
   the same number. Rule 3 reserves these colours for state, which is exactly
   what a bar past its threshold is. */
[data-meter-root][data-tone='warning'] [data-meter-indicator] {
  background: var(--color-warning);
}

[data-meter-root][data-tone='danger'] [data-meter-indicator] {
  background: var(--color-danger);
}

[data-navigation-menu-root] {
  position: relative;
}

[data-navigation-menu-list] {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  margin: 0;
  padding: var(--space-1);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  /* Same shape as menubar's root: the menu radius outside, 4px of padding,
     the menu-item radius on the links inside. */
  border-radius: var(--menu-radius);
}

[data-navigation-menu-trigger],
[data-navigation-menu-link] {
  font-family: var(--font-body);
  display: inline-flex;
  align-items: center;
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  font-weight: var(--weight-emphasized);
  border-radius: var(--menu-item-radius);
  background: transparent;
  color: var(--color-fg);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-navigation-menu-trigger]:hover:not([data-disabled]):not(:disabled),
[data-navigation-menu-link]:hover:not([data-disabled]):not(:disabled),
[data-navigation-menu-trigger][data-state='open'] {
  background: var(--color-highlight);
}

[data-navigation-menu-content] {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: var(--space-2);
  padding: var(--space-4);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  z-index: 50;
  min-width: 16rem;
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

[data-navigation-menu-content][data-starting-style],
[data-navigation-menu-content][data-ending-style] {
  opacity: 0;
  transform: translateY(-4px);
}

[data-navigation-menu-viewport] {
  position: relative;
}

[data-navigation-menu-indicator] {
  display: none;
}

[data-navigation-menu-trigger] {
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
}

[data-navigation-menu-trigger][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-pagination-root] {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

[data-pagination-prev],
[data-pagination-next],
[data-pagination-page] {
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--btn-height-sm);
  height: var(--btn-height-sm);
  padding: 0 var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasized);
  border-radius: var(--btn-radius);
  background: transparent;
  color: var(--color-fg);
  transition: background var(--duration-fast) var(--ease-out);
}

/* A page number is chrome, not code — nobody copies "3" out of a pager —
   so it inherits --font-body from the rule above with everything else in the
   strip. What stops the strip reflowing as 9 becomes 10 is the tabular
   figures below, which is a NUMERAL setting, not a family: design-stepper
   .css puts it in one line — "tabular figures keep the line from shuffling.
   Numerals, not a monospaced face." Reading the mono cut as the thing that
   delivered the alignment is what put a second typeface on a row of buttons
   whose siblings are chevrons. */
[data-pagination-page] {
  font-variant-numeric: tabular-nums;
}

[data-pagination-prev]:hover:not([data-disabled]):not(:disabled),
[data-pagination-next]:hover:not([data-disabled]):not(:disabled),
[data-pagination-page]:hover:not([data-disabled]):not(:disabled):not([data-selected]) {
  background: var(--color-highlight);
}

[data-pagination-page][data-selected] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

[data-pagination-prev]:disabled,
[data-pagination-next]:disabled {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-pin-input-root] {
  display: inline-flex;
  gap: var(--space-2);
}

/* Keeps --font-mono, and this is the mono exemption rather than an
   oversight: a one-time code IS data the user copies — read off another
   device, typed once, and checked digit by digit. Mono is what makes 0/O and
   1/l distinguishable while they do that. Its neighbours date-field and
   time-field were only ever using mono to line segments up and have moved to
   the body face; this one is genuinely a code. */
[data-pin-input-cell] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  border: none;
  border-radius: var(--field-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-control);
  background: var(--color-surface);
  color: var(--color-fg);
}

/* The WhatsApp field focus: a 2px accent ring. */
[data-pin-input-cell][data-active] {
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-accent);
}

/* bits-ui marks no cell disabled: pass data-disabled on each Cell along
   with disabled on the Root. Grey fill and subtle digits; the edge stays. */
[data-pin-input-cell][data-disabled] {
  background: var(--color-surface-alt);
  color: var(--color-subtle);
}

[data-pin-input-input]:disabled {
  cursor: not-allowed;
}

/*
 * popover.css — bits-ui Popover. The WDSMenu panel (16px corners, hairline,
 * popover shadow, 300ms entrance) with 16px of room for prose. Below 840px
 * it is iOS glass with 26pt corners.
 */

[data-popover-content] {
  box-sizing: border-box;
  font-family: var(--font-body);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  padding: var(--space-4);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  max-width: 24rem;
  font-size: var(--text-xs);
  line-height: 1.25rem;
  color: var(--color-fg);
  transform-origin: var(--bits-floating-transform-origin, center);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-popover-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-popover-content][data-ending-style] {
  opacity: 0;
}

/* The arrow's polygon fills with currentColor: `color` paints it the
   panel's surface. */
[data-popover-arrow] {
  color: var(--color-surface);
}

[data-popover-close] {
  appearance: none;
  -webkit-appearance: none;
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--btn-height-sm);
  height: var(--btn-height-sm);
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--color-muted);
  cursor: pointer;
}

[data-popover-close]:hover {
  background: var(--color-highlight);
  color: var(--color-fg);
}

@media (max-width: 839.98px) {
  [data-popover-content] {
    border: none;
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
  }

  [data-popover-arrow] {
    color: var(--color-glass-strong);
  }
}

@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-popover-content] {
    animation: none;
  }
}

/*
 * progress.css — a task in flight: an upload, a provision, a deploy.
 * (Meter, in meter.css, is the same bar for a static quantity; the two share
 * a shape on purpose, because to a reader they are the same object.)
 *
 * Rule 2 names a bar track as one of the four things the capsule is FOR,
 * alongside the search field, the composer and chips, so the track and its
 * fill are --radius-pill. The 4px rectangle this used to be was chosen to
 * look like a readout on a control panel; on a soft interface it reads as an
 * unfinished input. A round cap is also the honest shape: the fill has two
 * ends and neither of them is a corner of anything.
 *
 * Rule 8: the width transition runs at --duration-normal, so a step forward
 * is visible as movement rather than as a jump, and still resolves before a
 * reader could call it slow.
 */

[data-progress-root] {
  position: relative;
  width: 100%;
  height: var(--space-2);
  background: var(--color-surface-alt);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

/* The fill is square-cornered and clipped by the track's own radius, so its
   leading edge picks up the capsule at 100% and stays flat mid-run — a
   separately-rounded fill pinches to a lozenge at low values and reads as a
   smaller number than it is. */
[data-progress-indicator] {
  display: block;
  height: 100%;
  background: var(--color-accent);
  border-radius: 0;
  transition: width var(--duration-normal) var(--ease-out);
}

/*
 * radio-group.css — bits-ui RadioGroup. WhatsApp Web's WDSBaseRadio: a 20px
 * ring with a 2px stroke that turns accent when checked, around a 10px accent
 * dot (the caller's [data-radio-group-item-indicator]). The dot is what tells
 * checked from unchecked without relying on hue.
 */
[data-radio-group-root] {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* A literal 50%: the round is what says "pick one". */
[data-radio-group-item] {
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--radio-size);
  height: var(--radio-size);
  padding: 0;
  border: var(--control-stroke) solid var(--color-border-control);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

[data-radio-group-item][data-state='checked'] {
  border-color: var(--color-accent);
}

[data-radio-group-item]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* Opacity only: a disabled colour-swatch radio must keep its hue. */
[data-radio-group-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-radio-group-item-indicator] {
  display: none;
  width: var(--radio-dot);
  height: var(--radio-dot);
  border-radius: 50%;
  background: var(--color-accent);
}

[data-radio-group-item][data-state='checked'] [data-radio-group-item-indicator] {
  display: inline-block;
}

/* RangeCalendar.Root — same contract as Calendar.Root: no own surface,
   inherits from parent. Keep in lockstep with calendar.css. */
[data-range-calendar-root] {
  font-family: var(--font-body);
  display: inline-block;
  font-size: var(--text-sm);
}

[data-range-calendar-header] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}

[data-range-calendar-heading] {
  font-weight: var(--weight-medium);
  font-size: var(--text-base);
}

[data-range-calendar-prev-button],
[data-range-calendar-next-button] {
  color: var(--color-muted);
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  width: var(--control-height-sm);
  height: var(--control-height-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--btn-radius);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-range-calendar-prev-button] svg,
[data-range-calendar-next-button] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
}

[data-range-calendar-prev-button]:hover:not([data-disabled]):not(:disabled),
[data-range-calendar-next-button]:hover:not([data-disabled]):not(:disabled) {
  background: var(--color-surface-alt);
}

[data-range-calendar-grid] {
  width: 100%;
  border-collapse: collapse;
}

/* Rule 4: a weekday abbreviation is a WORD, shortened — Sen, Sel, Rab. It
   takes the same sentence-case --font-body as the numbers under it, one step
   down in size and in --color-muted so the grid still reads header-then-body.
   Tracked uppercase mono turned a familiar row of day names into a legend. */
[data-range-calendar-grid-head] {
  color: var(--color-muted);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-normal);
}

[data-range-calendar-head-cell] {
  padding: var(--space-1);
  font-weight: var(--weight-regular);
  text-align: center;
}

[data-range-calendar-cell] {
  padding: 0;
  text-align: center;
}

[data-range-calendar-day] {
  color: var(--color-fg);
  border-color: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height-sm);
  height: var(--control-height-sm);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-range-calendar-day]:hover:not([data-disabled]):not(:disabled):not([data-selected]):not([data-selection-start]):not([data-selection-end]) {
  background: var(--color-surface-alt);
}

/* The range being chosen: bits-ui marks every day from the start to the one
   under the pointer, the start included, so this comes before the selected
   fills and the start keeps its accent fill under the preview. */
[data-range-calendar-day][data-highlighted] {
  background: var(--color-surface-alt);
}

[data-range-calendar-day][data-selected] {
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
}

[data-range-calendar-day][data-selection-start],
[data-range-calendar-day][data-selection-end] {
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
}

[data-range-calendar-day][data-outside-month] {
  color: var(--color-subtle);
}

[data-range-calendar-day][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-range-calendar-day][data-today] {
  font-weight: var(--weight-medium);
  outline: var(--border-width) solid var(--color-accent);
}

[data-range-calendar-prev-button][data-disabled],
[data-range-calendar-next-button][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-rating-group-root] {
  display: inline-flex;
  gap: var(--space-1);
}

[data-rating-group-item] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height-sm);
  height: var(--control-height-sm);
  color: var(--color-border-strong);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out);
}

/* The star: the list-row glyph size, centred in the 28px item. */
[data-rating-group-item] svg {
  width: var(--icon-md);
  height: var(--icon-md);
}

[data-rating-group-item][data-state='active'] {
  color: var(--color-accent-ink);
}

[data-rating-group-item][data-state='partial'] {
  color: var(--color-accent-ink);
  opacity: 0.5;
}

[data-rating-group-item][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-scroll-area-root] {
  position: relative;
  overflow: hidden;
}

[data-scroll-area-viewport] {
  width: 100%;
  height: 100%;
}

/* WhatsApp Web scrollbars: 6px, a translucent ink thumb, no track. */
[data-scroll-area-scrollbar] {
  display: flex;
  touch-action: none;
  user-select: none;
  padding: 0;
  background: transparent;
}

[data-scroll-area-scrollbar][data-orientation='vertical'] {
  width: 6px;
}

[data-scroll-area-scrollbar][data-orientation='horizontal'] {
  height: 6px;
  flex-direction: column;
}

[data-scroll-area-thumb] {
  flex: 1;
  background: var(--color-border-strong);
  border-radius: var(--radius-xs);
  position: relative;
}

[data-scroll-area-corner] {
  background: transparent;
}

/*
 * select.css — bits-ui Select.
 *
 * The trigger is a WhatsApp Web text field: 40px, 12px corners, a 1px
 * outline that turns into a 2px accent ring while open or focused, and the
 * surface-highlight fill on hover. The list is the WDSMenu panel (see
 * dropdown-menu.css); below 840px the field follows the iOS field height and
 * the list turns into the iOS glass menu.
 */

[data-select-trigger] {
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  font-family: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  max-width: 20rem;
  height: var(--field-height);
  padding: 0 var(--space-3) 0 var(--space-4);
  font-size: var(--text-xs);
  line-height: 1.25rem;
  background: var(--color-surface);
  color: var(--color-fg);
  border: none;
  border-radius: var(--field-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-control);
  text-align: left;
  outline: none;
}

[data-select-trigger]:hover:not([data-disabled]):not([data-state='open']) {
  background: var(--color-highlight);
}

[data-select-trigger][data-state='open'],
[data-select-trigger]:focus-visible {
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-accent);
}

[data-select-trigger] svg {
  width: var(--icon-md);
  height: var(--icon-md);
  flex-shrink: 0;
  color: var(--color-muted);
}

[data-select-trigger][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-select-trigger][data-placeholder]:not([data-disabled]) {
  color: var(--color-muted);
}

[data-select-content] {
  box-sizing: border-box;
  min-width: max(var(--menu-min-width), var(--bits-select-anchor-width));
  padding: var(--menu-pad-y) var(--menu-pad-x);
  color: var(--color-fg);
  font-family: var(--font-body);
  background: var(--color-surface);
  /* design-tokens-ignore: a floating panel edge; the trigger keeps the control boundary. */
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-popover);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  max-height: 20rem;
  overflow-y: auto;
  transform-origin: var(--bits-floating-transform-origin, top);
  animation: menu-in var(--duration-menu) var(--ease-menu);
  transition: opacity var(--duration-menu-exit) ease-out;
}

[data-select-content][data-side='top'] {
  animation-name: menu-in-up;
}

[data-select-content][data-ending-style] {
  opacity: 0;
}

[data-select-item] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--menu-item-min);
  padding: 0 var(--menu-item-pad-x);
  font-size: var(--menu-item-size);
  line-height: var(--menu-item-line);
  border-radius: var(--menu-item-radius);
  cursor: pointer;
  user-select: none;
  outline: none;
}

[data-select-item] + [data-select-item] {
  margin-top: var(--menu-gap);
}

[data-select-item] svg {
  width: var(--menu-icon-size);
  height: var(--menu-icon-size);
  flex-shrink: 0;
}

[data-select-item][data-highlighted] {
  background: var(--color-highlight);
}

[data-select-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

/* The chosen value: accent ink and a tick-free wash, like a selected chip. */
[data-select-item][data-selected] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
  font-weight: var(--weight-emphasized);
}

/* Group heading: 12/16 emphasized, muted, sentence case. */
[data-select-group-label] {
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-emphasized);
  color: var(--color-muted);
  letter-spacing: var(--tracking-normal);
}

/* WhatsApp iOS context menu: glass, 250 wide, 26pt corners, 44pt rows of
   17/22 with the highlight inset 8pt. */
@media (max-width: 839.98px) {
  [data-select-content] {
    border: none;
    background: var(--color-glass-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    box-shadow: var(--glass-shadow);
  }

  [data-select-group-label] {
    padding: var(--space-1) var(--menu-item-pad-x) var(--space-2);
    font-family: inherit;
    font-size: var(--menu-heading-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
  }
}

/* WhatsApp Web menu entrance: fade, 8px towards the anchor, .95 → 1.01 → 1. */
@keyframes menu-in {
  0% { opacity: 0; transform: translateY(-8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes menu-in-up {
  0% { opacity: 0; transform: translateY(8px) scale(0.95); }
  50% { transform: translateY(0) scale(1.01); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  [data-select-content] {
    animation: none;
  }
}

[data-separator-root] {
  background: var(--color-border);
  border: none;
  margin: 0;
}

[data-separator-root][data-orientation='horizontal'] {
  height: var(--border-width);
  width: 100%;
}

[data-separator-root][data-orientation='vertical'] {
  width: var(--border-width);
  height: 100%;
}

/* Slider — Bits UI v2 ships Root, Range, Thumb (no Track). Root is the
   visible track itself; Range + Thumb are direct children, both
   absolutely positioned by Bits UI's internal styles. Proportions per
   Bits UI's reference example (8px track, 20px thumb). */

[data-slider-root] {
  position: relative;
  display: block;
  user-select: none;
  touch-action: none;
  background: var(--color-surface-alt);
  /* Rule 2 names a bar track as one of the things the capsule is FOR, and
     this is the same object meter.css and progress.css draw. Round caps are
     also the honest shape for it: the rail has two ends and neither of them
     is the corner of anything. */
  border-radius: var(--radius-pill);
  cursor: pointer;
}

[data-slider-root][data-orientation='horizontal'] {
  width: 100%;
  height: 0.5rem;
}

[data-slider-root][data-orientation='vertical'] {
  width: 0.5rem;
  height: 8rem;
}

[data-slider-root][data-disabled] {
  cursor: not-allowed;
}

/* The fill takes the track's own capsule rather than being clipped to it the
   way meter.css and progress.css do theirs: the thumb is 20px on an 8px rail,
   so the root cannot carry `overflow: hidden` without cutting it off. The
   fill's leading end is under the thumb at every value anyway. */
[data-slider-range] {
  position: absolute;
  display: block;
  background: var(--color-accent);
  border-radius: var(--radius-pill);
}

[data-slider-root][data-orientation='horizontal'] [data-slider-range] {
  top: 0;
  bottom: 0;
}

[data-slider-root][data-orientation='vertical'] [data-slider-range] {
  left: 0;
  right: 0;
}

[data-slider-root][data-disabled] [data-slider-range] {
  background: var(--color-border-strong);
}

/* Thumb cross-axis centering. Bits UI's inline `translate` property
   centers the thumb on its VALUE position only (horizontal axis on
   horizontal sliders, vertical axis on vertical sliders). We use the
   separate CSS `transform` property to handle the OTHER axis — the
   track-thickness axis — so the thumb sits visually centered on the
   thin track line. `translate` and `transform` are independent
   properties in modern CSS, so they stack without conflict. */

[data-slider-thumb] {
  display: block;
  position: absolute;
  width: 1.25rem;
  height: 1.25rem;
  /* White grip, control-weight edge: the part the user drags needs a 3:1
     boundary against the rail (WCAG 1.4.11). */
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-control);
  /* A literal 50% that earns it, which is the only kind Rule 2 allows: this
     is a KNOB on a rail, and the round grip is the affordance, the same way a
     status dot's round is data. No shadow — Rule 3 spends those on a message
     bubble and on an overlay, and a knob is neither; the white grip against
     the tinted rail and the accent fill behind it are what lift it. */
  border-radius: 50%;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

[data-slider-root][data-orientation='horizontal'] [data-slider-thumb] {
  top: 50%;
  transform: translateY(-50%);
}

[data-slider-root][data-orientation='vertical'] [data-slider-thumb] {
  left: 50%;
  transform: translateX(-50%);
}

[data-slider-thumb]:hover {
  background: var(--color-surface);
  border-color: var(--color-fg);
}

[data-slider-thumb]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

[data-slider-root][data-orientation='horizontal'] [data-slider-thumb][data-active] {
  transform: translateY(-50%) scale(0.96);
  border-color: var(--color-fg);
}

[data-slider-root][data-orientation='vertical'] [data-slider-thumb][data-active] {
  transform: translateX(-50%) scale(0.96);
  border-color: var(--color-fg);
}

[data-slider-thumb][data-disabled] {
  background: var(--color-surface-alt);
  border-color: var(--color-border-control);
  color: var(--color-subtle);
  cursor: not-allowed;
}

/*
 * switch.css — bits-ui Switch.
 *
 * Desktop is WhatsApp Web's WDSSwitch: a 40x24 track. Off, it is the pale
 * surface with a 2px control ring and a 12px thumb 6px in; on, the accent
 * with a 16px white thumb 4px from the end. Hover stretches the thumb.
 * Below 840px it is the iOS 26 switch: a 64x28 capsule, fill when off and
 * accent when on, carrying a 38x24 white capsule knob that stretches while
 * pressed. Geometry comes from the --switch-* tokens.
 *
 * The white thumb sits on the accent track, so a palette's --color-accent
 * keeps at least 3:1 against --color-surface, the non-text floor.
 */

[data-switch-root] {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  /* bits-ui renders a native <button> and the app loads this file without
     base.css, so the UA chrome is reset here. */
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  width: var(--switch-width);
  height: var(--switch-height);
  border: none;
  background: var(--color-surface-alt);
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-border-control);
  /* design-tokens-ignore: the switch track is a bar track, and tracks are capsules; the pill check only sees the control name */
  border-radius: var(--radius-pill);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--duration-normal) ease-out;
}

[data-switch-root][data-state='checked'] {
  background: var(--color-accent);
  box-shadow: none;
}

/* Keep the enabled control's outer boundary above 3:1 under CRT scanlines. */
html[data-night-mode] [data-switch-root][data-state='checked'] {
  box-shadow: inset 0 0 0 var(--border-width) var(--color-accent-ink);
}

[data-switch-root]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

[data-switch-root][data-disabled] {
  opacity: var(--disabled-opacity);
  filter: grayscale(1);
  cursor: not-allowed;
}

[data-switch-thumb] {
  display: block;
  position: absolute;
  top: var(--switch-thumb-inset);
  left: var(--switch-thumb-inset);
  width: var(--switch-thumb-w);
  height: var(--switch-thumb-h);
  background: var(--color-subtle);
  /* design-tokens-ignore: the knob is a capsule on iOS and a circle on the web; the pill radius covers both */
  border-radius: var(--radius-pill);
  transition:
    width 0.1s ease-out,
    height 0.1s ease-out,
    top 0.1s ease-out,
    transform 0.2s ease-out;
}

[data-switch-root][data-state='checked'] [data-switch-thumb] {
  top: var(--switch-thumb-on-inset);
  width: var(--switch-thumb-on-w);
  height: var(--switch-thumb-on-h);
  background: var(--color-surface);
  transform: translateX(var(--switch-travel));
}

@media (hover: hover) {
  [data-switch-root]:hover:not([data-disabled]) [data-switch-thumb] {
    width: calc(var(--switch-thumb-w) + var(--switch-stretch-off));
  }

  [data-switch-root][data-state='checked']:hover:not([data-disabled]) [data-switch-thumb] {
    width: calc(var(--switch-thumb-on-w) + var(--switch-stretch-on));
    transform: translateX(calc(var(--switch-travel) - var(--switch-stretch-on)));
  }
}

/* WhatsApp iOS: no ring, a filled track, a white knob with a soft shadow in
   both states; the knob stretches while pressed instead of on hover. */
@media (max-width: 839.98px) {
  [data-switch-root] {
    background: var(--color-ios-fill);
    box-shadow: none;
  }

  [data-switch-thumb] {
    background: var(--color-surface);
    box-shadow: var(--shadow-knob);
  }

  [data-switch-root]:hover:not([data-disabled]) [data-switch-thumb] {
    width: var(--switch-thumb-w);
  }

  [data-switch-root][data-state='checked']:hover:not([data-disabled]) [data-switch-thumb] {
    width: var(--switch-thumb-on-w);
    transform: translateX(var(--switch-travel));
  }

  [data-switch-root]:active:not([data-disabled]) [data-switch-thumb] {
    width: calc(var(--switch-thumb-w) + var(--switch-stretch-off));
  }

  [data-switch-root][data-state='checked']:active:not([data-disabled]) [data-switch-thumb] {
    width: calc(var(--switch-thumb-on-w) + var(--switch-stretch-on));
    transform: translateX(calc(var(--switch-travel) - var(--switch-stretch-on)));
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-switch-root],
  [data-switch-thumb] {
    transition: none;
  }
}

/*
 * tabs.css — bits-ui Tabs (and any [data-tabs-list] of [data-tabs-trigger]
 * links).
 *
 * One rule for tabs and toggle groups: desktop draws WhatsApp Web's filter
 * chips — 32px pills, 12px padding, a 1px control outline, 14/20 emphasized
 * muted labels, 8px apart; the selected chip takes the accent wash and ink.
 * Below 840px they are the iOS segmented control: a 32pt track in the
 * tertiary fill carrying 28pt segments 2pt inside it, the selected one white
 * with a soft shadow, 13/18 medium labels, no dividers. A vertical list has
 * no segmented form: it stays a column of iOS chips.
 */
[data-tabs-root] {
  display: flex;
  flex-direction: column;
}

/* A vertical list sits beside its panels, 16px from them. */
[data-tabs-root][data-orientation='vertical'] {
  flex-direction: row;
  gap: var(--space-4);
}

/* Wrap, never clip: a tab cut off by an ancestor cannot be tapped. */
[data-tabs-list] {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-self: flex-start;
  max-width: 100%;
}

[data-tabs-root][data-orientation='vertical'] [data-tabs-list] {
  flex-direction: column;
}

[data-tabs-trigger] {
  /* bits-ui renders a native <button> and the app loads this file without
     base.css, so the UA chrome is reset here. */
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--btn-height-sm);
  padding: 0 var(--space-3);
  border: var(--border-width) solid var(--color-border-control);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-muted);
  font-family: inherit;
  font-size: var(--text-xs);
  line-height: 1.25rem;
  font-weight: var(--weight-emphasized);
  letter-spacing: var(--tracking-normal);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--duration-press) var(--ease-press);
}

/* State layer: the highlight on an idle chip, the accent at 10% on the
   selected one. */
[data-tabs-trigger]::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--color-highlight);
  opacity: 0;
  pointer-events: none;
}

[data-tabs-trigger][data-state='active'] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

[data-tabs-trigger][data-state='active']::after {
  background: var(--color-accent);
}

@media (hover: hover) {
  [data-tabs-trigger]:hover:not([data-disabled])::after {
    opacity: 1;
  }

  [data-tabs-trigger][data-state='active']:hover:not([data-disabled])::after {
    opacity: var(--state-layer-opacity);
  }
}

[data-tabs-trigger]:active:not([data-disabled]) {
  transform: scale(var(--press-scale));
}

[data-tabs-trigger][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-tabs-content] {
  padding-top: var(--space-4);
}

[data-tabs-content][data-orientation='vertical'] {
  padding-top: 0;
}

@media (max-width: 839.98px) {
  [data-tabs-list] {
    flex-wrap: nowrap;
    gap: 0;
    height: var(--seg-track-height);
    padding: var(--seg-inset);
    box-sizing: border-box;
    overflow-x: auto;
    scrollbar-width: none;
    background: var(--color-ios-fill-3);
    border-radius: calc(var(--seg-track-height) / 2);
  }

  [data-tabs-trigger] {
    flex: 1 0 auto;
    height: var(--seg-height);
    padding: 0 var(--space-3);
    border: none;
    border-radius: calc(var(--seg-height) / 2);
    color: var(--color-fg);
    font-size: var(--seg-font-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
    transition: background var(--duration-normal) ease-out;
  }

  [data-tabs-trigger]::after {
    display: none;
  }

  [data-tabs-trigger][data-state='active'] {
    background: var(--color-surface);
    color: var(--color-fg);
    font-weight: var(--weight-semibold);
    box-shadow: var(--shadow-segment);
  }

  [data-tabs-trigger]:active:not([data-disabled]) {
    transform: none;
  }

  /* A vertical list stays a column of iOS chips, as in toggle-group.css. */
  [data-tabs-list][data-orientation='vertical'] {
    height: auto;
    gap: var(--space-2);
    padding: 0;
    overflow: visible;
    background: none;
    border-radius: 0;
  }

  [data-tabs-trigger][data-orientation='vertical'] {
    flex: 0 0 auto;
    height: var(--chip-height);
    padding: 0 var(--chip-pad-x);
    border-radius: var(--radius-pill);
    background: var(--color-highlight);
    color: var(--color-muted);
    font-size: var(--text-xs);
    line-height: 1.25rem;
  }

  [data-tabs-trigger][data-orientation='vertical'][data-state='active'] {
    background: var(--color-accent-soft);
    color: var(--color-accent-ink);
    box-shadow: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-tabs-trigger] {
    transition: none;
  }
}

/* Time-field segment selector quirk: unlike DateField, Bits UI's
   `timeFieldAttrs.parts` does NOT include "segment", so segments emit
   only `data-segment="<part>"` and NOT `data-time-field-segment`.
   Scope segment styling under [data-time-field-input] to avoid
   conflicting with DateField segments (which DO emit the
   `data-date-field-segment` attribute and are styled in date-field.css). */

/* WhatsApp Web text field: 40px, 12px corners, 1px outline → 2px accent. */
[data-time-field-input] {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  height: var(--field-height);
  padding: 0 var(--space-4);
  border: none;
  border-radius: var(--field-radius);
  box-shadow: inset 0 0 0 var(--border-width) var(--color-border-control);
  background: var(--color-surface);
  /* No --font-mono — same reasoning as date-field.css: a time you type is not
     code, and tabular-nums is what actually holds the segments in column. */
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
}

[data-time-field-input]:focus-within {
  box-shadow: inset 0 0 0 var(--control-stroke) var(--color-accent);
}

/* Keep in lockstep with date-field.css: the segment highlight is a dense
   inline mark inside the 12px field, so --radius-xs, not the field's own
   corner. */
[data-time-field-input] [data-segment] {
  padding: 0 var(--space-1);
  border-radius: var(--radius-xs);
  outline: none;
}

/* As in date-field.css: an empty segment reads aria-valuetext="Empty", and
   the one being typed into is the focused element. */
[data-time-field-input] [data-segment][aria-valuetext='Empty'] {
  color: var(--color-muted);
}

[data-time-field-input] [data-segment]:focus {
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
}

[data-time-field-input] [data-segment][data-disabled] {
  color: var(--color-subtle);
  cursor: not-allowed;
}

[data-time-field-input][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

[data-time-field-input][data-disabled] [data-segment] {
  color: var(--color-subtle);
}

/* TimeRangeField composes two TimeField.Input children inside its Root.
   The Inputs emit `data-time-field-input` (shared component) and
   segments emit only `data-segment` (NOT `data-time-field-segment` —
   see the quirk note in time-field.css) — both styled in
   time-field.css. Here we only style the outer Root as a layout
   wrapper. */

[data-time-range-field-root] {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
  font-size: var(--text-sm);
}

/* A phone cannot hold the label and both halves on one line: the label
   takes a line of its own and the halves wrap under it. */
@media (max-width: 639.98px) {
  [data-time-range-field-root] {
    flex-wrap: wrap;
  }

  [data-time-range-field-label] {
    flex-basis: 100%;
  }
}

/*
 * toggle.css — bits-ui Toggle: one WhatsApp filter chip (32px pill, 1px
 * control outline, muted 14/20 emphasized label; on = accent wash and ink).
 * Below 840px it is the iOS chip: grey fill, no outline, 15/20 medium.
 */
[data-toggle-root] {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--btn-height-sm);
  padding: 0 var(--space-3);
  border: var(--border-width) solid var(--color-border-control);
  /* design-tokens-ignore: a toggle is a WhatsApp chip, and chips are capsules */
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-muted);
  font-family: inherit;
  font-size: var(--text-xs);
  line-height: 1.25rem;
  font-weight: var(--weight-emphasized);
  cursor: pointer;
  transition: transform var(--duration-press) var(--ease-press);
}

/* An icon beside the label: the in-control glyph size. */
[data-toggle-root] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  flex-shrink: 0;
}

[data-toggle-root]::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--color-highlight);
  opacity: 0;
  pointer-events: none;
}

[data-toggle-root][data-state='on'] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

[data-toggle-root][data-state='on']::after {
  background: var(--color-accent);
}

@media (hover: hover) {
  [data-toggle-root]:hover:not([data-disabled])::after {
    opacity: 1;
  }

  [data-toggle-root][data-state='on']:hover:not([data-disabled])::after {
    opacity: var(--state-layer-opacity);
  }
}

[data-toggle-root]:active:not([data-disabled]) {
  transform: scale(var(--press-scale));
}

[data-toggle-root]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

[data-toggle-root][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

@media (max-width: 839.98px) {
  [data-toggle-root] {
    height: var(--chip-height);
    padding: 0 var(--chip-pad-x);
    border-color: transparent;
    background: var(--color-ios-fill-3);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
  }

  [data-toggle-root][data-state='on'] {
    background: var(--color-accent-soft);
    font-weight: var(--weight-semibold);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-toggle-root] {
    transition: none;
  }
}

/*
 * toggle-group.css — bits-ui ToggleGroup, and any plain group of buttons
 * that carries the same attributes (items set data-state="on" | "off").
 * Same rule as tabs.css: WhatsApp Web filter chips on desktop, the iOS
 * segmented control below 840px. A group with data-chip-row is a filter row
 * and stays chips on iOS, like WhatsApp's chat filters; so does a vertical
 * group, which a one-row segmented track cannot hold.
 */
[data-toggle-group-root] {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  max-width: 100%;
}

[data-toggle-group-root][data-orientation='vertical'] {
  flex-direction: column;
}

[data-toggle-group-item] {
  /* Live pages import this file without base.css, so the UA button chrome
     is stripped here. */
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--btn-height-sm);
  padding: 0 var(--space-3);
  border: var(--border-width) solid var(--color-border-control);
  /* design-tokens-ignore: a toggle-group item is a WhatsApp filter chip, and chips are capsules */
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-muted);
  font-family: inherit;
  font-size: var(--text-xs);
  line-height: 1.25rem;
  font-weight: var(--weight-emphasized);
  letter-spacing: var(--tracking-normal);
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--duration-press) var(--ease-press);
}

/* An icon item or an icon beside the label: the in-control glyph size. */
[data-toggle-group-item] svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  flex-shrink: 0;
}

[data-toggle-group-item]::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--color-highlight);
  opacity: 0;
  pointer-events: none;
}

[data-toggle-group-item][data-state='on'] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

[data-toggle-group-item][data-state='on']::after {
  background: var(--color-accent);
}

@media (hover: hover) {
  [data-toggle-group-item]:hover:not([data-disabled])::after {
    opacity: 1;
  }

  [data-toggle-group-item][data-state='on']:hover:not([data-disabled])::after {
    opacity: var(--state-layer-opacity);
  }
}

[data-toggle-group-item]:active:not([data-disabled]) {
  transform: scale(var(--press-scale));
}

[data-toggle-group-item]:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: 2px;
}

[data-toggle-group-item][data-disabled] {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}

/* iOS segmented control: 32pt track, 28pt segments, white selection. */
@media (max-width: 839.98px) {
  [data-toggle-group-root] {
    flex-wrap: nowrap;
    gap: 0;
    height: var(--seg-track-height);
    padding: var(--seg-inset);
    box-sizing: border-box;
    overflow-x: auto;
    scrollbar-width: none;
    background: var(--color-ios-fill-3);
    border-radius: calc(var(--seg-track-height) / 2);
  }

  [data-toggle-group-item] {
    flex: 1 0 auto;
    height: var(--seg-height);
    border: none;
    border-radius: calc(var(--seg-height) / 2);
    color: var(--color-fg);
    font-size: var(--seg-font-size);
    line-height: 1.125rem;
    font-weight: var(--weight-medium);
    transition: background var(--duration-normal) ease-out;
  }

  [data-toggle-group-item]::after {
    display: none;
  }

  [data-toggle-group-item][data-state='on'] {
    background: var(--color-surface);
    color: var(--color-fg);
    font-weight: var(--weight-semibold);
    box-shadow: var(--shadow-segment);
  }

  [data-toggle-group-item]:active:not([data-disabled]) {
    transform: none;
  }

  /* Filter chips on iOS: 32pt capsules, 15/20 medium on a grey fill with no
     edge; the selected chip is the accent tint with the deep accent ink,
     semibold. A vertical group stacks the same chips. */
  [data-toggle-group-root][data-orientation='vertical'],
  [data-toggle-group-root][data-chip-row] {
    flex-wrap: wrap;
    gap: var(--space-2);
    height: auto;
    padding: 0;
    overflow: visible;
    background: none;
    border-radius: 0;
  }

  [data-toggle-group-root][data-orientation='vertical'] [data-toggle-group-item],
  [data-toggle-group-root][data-chip-row] [data-toggle-group-item] {
    flex: 0 0 auto;
    height: var(--chip-height);
    padding: 0 var(--chip-pad-x);
    border-radius: var(--radius-pill);
    background: var(--color-highlight);
    color: var(--color-muted);
    font-size: var(--text-xs);
    line-height: 1.25rem;
  }

  [data-toggle-group-root][data-orientation='vertical'] [data-toggle-group-item][data-state='on'],
  [data-toggle-group-root][data-chip-row] [data-toggle-group-item][data-state='on'] {
    background: var(--color-accent-soft);
    color: var(--color-accent-ink);
    box-shadow: none;
  }

  [data-toggle-group-root][data-orientation='vertical'] [data-toggle-group-item]:active:not([data-disabled]),
  [data-toggle-group-root][data-chip-row] [data-toggle-group-item]:active:not([data-disabled]) {
    transform: scale(var(--press-scale));
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-toggle-group-item] {
    transition: none;
  }
}

/* A strip wider than a phone wraps between items; an item's label never
   breaks inside its 28px button. */
[data-toolbar-root] {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--menu-radius);
}

[data-toolbar-root][data-orientation='vertical'] {
  flex-direction: column;
}

/* Buttons and grouped formatting controls: 28px, transparent until hovered.
   An icon item is a 28px square, so a formatting group fits a phone's strip. */
[data-toolbar-button],
[data-toolbar-group-item] {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--control-height-sm);
  padding: 0 var(--space-3);
  border-radius: var(--menu-item-radius);
  background: transparent;
  color: var(--color-fg);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasized);
  white-space: nowrap;
  cursor: pointer;
}

[data-toolbar-button] {
  border-color: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

[data-toolbar-group-item] {
  min-width: var(--control-height-sm);
  padding: 0 var(--space-1);
  border: none;
}

[data-toolbar-group-item] svg {
  width: var(--icon-md);
  height: var(--icon-md);
  flex-shrink: 0;
}

[data-toolbar-link] {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-3);
  height: var(--control-height-sm);
  font-size: var(--text-sm);
  white-space: nowrap;
  color: var(--color-accent-ink);
  text-decoration: none;
  border-radius: var(--menu-item-radius);
}

[data-toolbar-button]:hover:not([data-disabled]):not(:disabled),
[data-toolbar-link]:hover:not([data-disabled]):not(:disabled),
[data-toolbar-group-item]:hover:not([data-disabled]):not(:disabled):not([data-state='on']) {
  background: var(--color-highlight);
}

[data-toolbar-group-item][data-state='on'] {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

[data-toolbar-button][data-disabled],
[data-toolbar-group-item][data-disabled],
[data-toolbar-group-item]:disabled {
  color: var(--color-subtle);
  cursor: not-allowed;
}

/* A group lines its items up like the strip's own buttons. */
[data-toolbar-group] {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

[data-toolbar-separator] {
  width: var(--border-width);
  height: 1rem;
  background: var(--color-border);
}

[data-toolbar-root][data-orientation='vertical'] [data-toolbar-separator] {
  width: 1rem;
  height: var(--border-width);
}

/*
 * tooltip.css — bits-ui Tooltip. WhatsApp Web's WDSTooltip: an inverse chip
 * with 4px corners, 4/8 padding, 24px min height, 200px max width and 12/16
 * text, lifted by the tooltip shadow.
 */
[data-tooltip-content] {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  min-height: 1.5rem;
  max-width: var(--tooltip-max-width);
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-2xs);
  line-height: 1rem;
  font-weight: var(--weight-regular);
  background: var(--color-surface-inverse);
  color: var(--color-fg-inverse);
  border-radius: var(--tooltip-radius);
  box-shadow: var(--shadow-tooltip);
  z-index: 60; /* above dialog content (51) so these work inside dialogs */
  opacity: 1;
  transition: opacity var(--duration-fast) var(--ease-out);
}

[data-tooltip-content][data-starting-style],
[data-tooltip-content][data-ending-style] {
  opacity: 0;
}

/* Tooltip.Arrow renders an svg[data-arrow] whose polygon fills with
   currentColor, so the arrow takes the chip's colour through `color`. */
[data-tooltip-content] [data-arrow] {
  color: var(--color-surface-inverse);
}

