@base316/react 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +14 -0
  3. package/dist/index.cjs +4440 -2021
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +16 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +5380 -2959
  8. package/dist/index.js.map +1 -1
  9. package/dist/manifest.json +396 -14
  10. package/dist/src/AcceptInvitation.d.ts +15 -1
  11. package/dist/src/AcceptInvitation.d.ts.map +1 -1
  12. package/dist/src/BillingDetailsForm.d.ts +33 -0
  13. package/dist/src/BillingDetailsForm.d.ts.map +1 -0
  14. package/dist/src/BillingPortal.d.ts +45 -0
  15. package/dist/src/BillingPortal.d.ts.map +1 -0
  16. package/dist/src/CreditBalances.d.ts +19 -0
  17. package/dist/src/CreditBalances.d.ts.map +1 -0
  18. package/dist/src/Invoices.d.ts +10 -6
  19. package/dist/src/Invoices.d.ts.map +1 -1
  20. package/dist/src/PaymentMethod.d.ts +25 -0
  21. package/dist/src/PaymentMethod.d.ts.map +1 -0
  22. package/dist/src/PlanChangeReview.d.ts +29 -0
  23. package/dist/src/PlanChangeReview.d.ts.map +1 -0
  24. package/dist/src/PricingTable.d.ts +13 -1
  25. package/dist/src/PricingTable.d.ts.map +1 -1
  26. package/dist/src/SeatManager.d.ts +24 -0
  27. package/dist/src/SeatManager.d.ts.map +1 -0
  28. package/dist/src/SecondFactorStep.d.ts +83 -0
  29. package/dist/src/SecondFactorStep.d.ts.map +1 -0
  30. package/dist/src/SignIn.d.ts +16 -3
  31. package/dist/src/SignIn.d.ts.map +1 -1
  32. package/dist/src/SignUp.d.ts +51 -3
  33. package/dist/src/SignUp.d.ts.map +1 -1
  34. package/dist/src/SubscriptionManager.d.ts +7 -1
  35. package/dist/src/SubscriptionManager.d.ts.map +1 -1
  36. package/dist/src/TeamMembers.d.ts.map +1 -1
  37. package/dist/src/TwoFactorManager.d.ts +14 -5
  38. package/dist/src/TwoFactorManager.d.ts.map +1 -1
  39. package/dist/src/UpcomingInvoice.d.ts +21 -0
  40. package/dist/src/UpcomingInvoice.d.ts.map +1 -0
  41. package/dist/src/appearance.d.ts +2 -2
  42. package/dist/src/appearance.d.ts.map +1 -1
  43. package/dist/src/manifest.d.ts.map +1 -1
  44. package/dist/src/provider.d.ts +13 -1
  45. package/dist/src/provider.d.ts.map +1 -1
  46. package/dist/src/usePlans.d.ts +17 -0
  47. package/dist/src/usePlans.d.ts.map +1 -1
  48. package/package.json +2 -2
@@ -1,12 +1,16 @@
1
1
  import { type CSSProperties } from "react";
2
2
  /**
3
- * The signed-in user's invoices, and a way to keep one.
3
+ * The signed-in user's invoices: view one, download its PDF, and pay one that
4
+ * is still open.
4
5
  *
5
- * Downloading is done by printing a rendered invoice rather than by fetching a
6
- * PDF: there is no PDF renderer on the server, and adding one is a real
7
- * dependency decision rather than something to slip in here. Print-to-PDF is
8
- * built into every browser, produces a selectable-text document, and needs
9
- * nothing installed — so the button opens the invoice and prints it.
6
+ * The PDF is the server's own rendering (`/v1/me/invoices/:id/pdf`) — the same
7
+ * document an operator downloads — fetched with the session and handed to the
8
+ * browser as a download, so nothing about it depends on the host page's print
9
+ * stylesheet. Viewing still opens the printable layout in the page.
10
+ *
11
+ * Paying sends the browser to the hosted pay page, minted on demand for that
12
+ * invoice, where Stripe collects the card; the figure charged is read from the
13
+ * invoice there, never from this list.
10
14
  *
11
15
  * Drafts never appear. They are the rating engine's working state and can still
12
16
  * change, so showing one as a bill would be wrong.
@@ -1 +1 @@
1
- {"version":3,"file":"Invoices.d.ts","sourceRoot":"","sources":["../../src/Invoices.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAuB7E;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,+BAgI3F"}
1
+ {"version":3,"file":"Invoices.d.ts","sourceRoot":"","sources":["../../src/Invoices.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AA0B7E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,+BAkM3F"}
@@ -0,0 +1,25 @@
1
+ import { type CSSProperties } from "react";
2
+ export interface PaymentMethodProps {
3
+ /**
4
+ * Where the browser comes back to once the new card is stored. Must be one
5
+ * of the environment's redirect URIs. Defaults to the current page.
6
+ */
7
+ returnUrl?: string;
8
+ className?: string;
9
+ style?: CSSProperties;
10
+ }
11
+ /**
12
+ * The card the signed-in user's invoices are charged against, and a way to
13
+ * replace it — plus any other saved cards, each of which can be made the
14
+ * default or removed.
15
+ *
16
+ * Replacing it goes to a page hosted by Stripe, on the application's connected
17
+ * account: the card is never typed into this component, the host page or
18
+ * Base316, so adding this to an application adds nothing to its PCI scope.
19
+ * The browser returns to `returnUrl` once the card is stored.
20
+ *
21
+ * A client company whose plan a firm pays for is told so instead — the firm's
22
+ * card is the one charged.
23
+ */
24
+ export declare function PaymentMethod({ returnUrl, className, style }: PaymentMethodProps): import("react").JSX.Element;
25
+ //# sourceMappingURL=PaymentMethod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaymentMethod.d.ts","sourceRoot":"","sources":["../../src/PaymentMethod.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAWhF,MAAM,WAAW,kBAAkB;IAClC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,kBAAkB,+BAkKhF"}
@@ -0,0 +1,29 @@
1
+ import { type CSSProperties } from "react";
2
+ export interface PlanChangeReviewProps {
3
+ /** The plan version being moved to — a `PublicPlan`'s `planVersionId`. */
4
+ planVersionId: string;
5
+ /** Called once the change is made or scheduled. */
6
+ onDone?: (outcome: {
7
+ scheduled: boolean;
8
+ }) => void;
9
+ /** Called when the user backs out. Without it there is no back button. */
10
+ onCancel?: () => void;
11
+ /**
12
+ * Called when a change now needs a card the account does not have. Without
13
+ * it the review offers to start a card update itself.
14
+ */
15
+ onNeedsCard?: () => void;
16
+ className?: string;
17
+ style?: CSSProperties;
18
+ }
19
+ /**
20
+ * The review step before a plan change: what is gained and lost, what it
21
+ * costs, and when it happens — then confirm.
22
+ *
23
+ * The figures are `previewPlanChange`'s, the same function the change runs, so
24
+ * the amount shown is the amount charged. The default timing is the server's
25
+ * (an upgrade now, a downgrade at the renewal); the other is offered when it is
26
+ * open, and the reason is said when it is not.
27
+ */
28
+ export declare function PlanChangeReview({ planVersionId, onDone, onCancel, onNeedsCard, className, style, }: PlanChangeReviewProps): import("react").JSX.Element;
29
+ //# sourceMappingURL=PlanChangeReview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanChangeReview.d.ts","sourceRoot":"","sources":["../../src/PlanChangeReview.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAuC7F,MAAM,WAAW,qBAAqB;IACrC,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IACnD,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAChC,aAAa,EACb,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,KAAK,GACL,EAAE,qBAAqB,+BAoPvB"}
@@ -1,5 +1,17 @@
1
1
  import type { PublicPlan } from "@base316/sdk";
2
- import type { CSSProperties } from "react";
2
+ import { type CSSProperties } from "react";
3
+ /**
4
+ * What a plan's trial says on the card, or null when it has none.
5
+ *
6
+ * A `CONVERT` trial is the familiar "14-day free trial": it bills when it
7
+ * ends. A `DOWNGRADE` trial — the reverse trial — does not bill a subscriber
8
+ * who never added a card; it moves them to `trialDowngradePlanVersionId`. The
9
+ * card has to say so, or a visitor reads "free trial" as "then I'm charged"
10
+ * and never starts one. The target is named when it is among the published
11
+ * plans (it usually is: the Free plan); otherwise the label says what keeps
12
+ * the plan instead of guessing at a name.
13
+ */
14
+ export declare function describeTrial(plan: PublicPlan, plans: readonly PublicPlan[]): string | null;
3
15
  /**
4
16
  * The plans, as an end user picks them.
5
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"PricingTable.d.ts","sourceRoot":"","sources":["../../src/PricingTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AA4B3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,EAC5B,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,SAAS,EACT,SAAS,EACT,KAAK,GACL,EAAE;IACF;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAgJA"}
1
+ {"version":3,"file":"PricingTable.d.ts","sourceRoot":"","sources":["../../src/PricingTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,KAAK,aAAa,EAAY,MAAM,OAAO,CAAC;AA4BrD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,GAAG,IAAI,CAkB3F;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,EAC5B,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,SAAS,EACT,SAAS,EACT,KAAK,GACL,EAAE;IACF;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAqLA"}
@@ -0,0 +1,24 @@
1
+ import type { QuantityChangeOutcome } from "@base316/sdk";
2
+ import { type CSSProperties } from "react";
3
+ export interface SeatManagerProps {
4
+ /** What a unit is called, plural. "seats" by default. */
5
+ unitLabel?: string;
6
+ /** Called after a change is made, with what it did. */
7
+ onChange?: (outcome: QuantityChangeOutcome) => void;
8
+ className?: string;
9
+ style?: CSSProperties;
10
+ }
11
+ /**
12
+ * Let the signed-in user change how many seats their subscription is for —
13
+ * with the price shown before anything is charged.
14
+ *
15
+ * Preview, then confirm. The preview is the server's own calculation: adding
16
+ * seats is charged now for the part of the period that is left, removing them
17
+ * takes effect at the period end and refunds nothing. The user only chooses the
18
+ * number — how the change is paid for is the application's policy, not theirs.
19
+ *
20
+ * A client company whose plan a firm pays for is told so instead: resizing the
21
+ * firm's subscription would reach every other client it has.
22
+ */
23
+ export declare function SeatManager({ unitLabel, onChange, className, style }: SeatManagerProps): import("react").JSX.Element;
24
+ //# sourceMappingURL=SeatManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SeatManager.d.ts","sourceRoot":"","sources":["../../src/SeatManager.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAyB,MAAM,cAAc,CAAC;AACjF,OAAO,EAAoC,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AA6C7F,MAAM,WAAW,gBAAgB;IAChC,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,gBAAgB,+BAuOhG"}
@@ -0,0 +1,83 @@
1
+ import { type SignInPending } from "@base316/sdk";
2
+ import { type CSSProperties } from "react";
3
+ /**
4
+ * The second half of a sign-in that owes a second factor.
5
+ *
6
+ * Two shapes, decided by the server rather than guessed here:
7
+ *
8
+ * - **A challenge** (`enroll: false`): a code box for the factor the person
9
+ * already has — their authenticator app, or the code just sent to their inbox
10
+ * or phone — or one of their recovery codes.
11
+ * - **An enrolment** (`enroll: true`): the environment requires a second factor
12
+ * and this person has none, so there is nothing a code box could check. They
13
+ * choose one of `enrollMethods`, prove it with its first code, and are shown
14
+ * their recovery codes once before the session is handed over.
15
+ *
16
+ * The enrolment branch is what used to be missing. `SignIn` showed "from your
17
+ * authenticator app" to somebody who had never set one up, and `SignUp`
18
+ * silently stopped — so under a required policy nobody new could ever get in.
19
+ *
20
+ * Every visible string comes from `labels`, so a translated application passes
21
+ * its own and nothing here needs forking.
22
+ */
23
+ export interface SecondFactorLabels {
24
+ challengeTitle: string;
25
+ codeLabel: string;
26
+ /** Under the code box when the code went to an inbox or phone. */
27
+ codeSentTo: (destinationHint: string) => string;
28
+ /** Under the code box when it comes from an authenticator app. */
29
+ codeFromApp: string;
30
+ verify: string;
31
+ resend: string;
32
+ resent: string;
33
+ enrollTitle: string;
34
+ enrollIntro: string;
35
+ methodTotp: string;
36
+ methodTotpHint: string;
37
+ methodEmail: string;
38
+ methodEmailHint: string;
39
+ methodSms: string;
40
+ methodSmsHint: string;
41
+ totpInstructions: string;
42
+ qrAlt: string;
43
+ manualKey: string;
44
+ openInApp: string;
45
+ sixDigitCode: string;
46
+ /** Under the code box while enrolling a factor whose first code was sent. */
47
+ enrollCodeSentTo: (destinationHint: string) => string;
48
+ confirm: string;
49
+ phoneLabel: string;
50
+ phoneHint: string;
51
+ sendCode: string;
52
+ chooseAnother: string;
53
+ codesTitle: string;
54
+ codesIntro: string;
55
+ copy: string;
56
+ copied: string;
57
+ download: string;
58
+ /** The file the codes download as. */
59
+ downloadName: string;
60
+ savedConfirm: string;
61
+ continue: string;
62
+ working: string;
63
+ startOver: string;
64
+ /** A failure the server did not word. */
65
+ genericError: string;
66
+ }
67
+ export declare const DEFAULT_SECOND_FACTOR_LABELS: SecondFactorLabels;
68
+ export interface SecondFactorStepProps {
69
+ /** What `signIn`, `magicLink.verify` or `phone.verify` returned with `mfaRequired`. */
70
+ pending: SignInPending;
71
+ /** Called once the session has been handed to the provider. */
72
+ onSignedIn?: () => void;
73
+ /**
74
+ * Back to the start of the sign-in, for a challenge that has expired or been
75
+ * used up. Without it, no "Start over" button is drawn.
76
+ */
77
+ onRestart?: () => void;
78
+ labels?: Partial<SecondFactorLabels>;
79
+ className?: string;
80
+ style?: CSSProperties;
81
+ }
82
+ export declare function SecondFactorStep({ pending, onSignedIn, onRestart, labels: overrides, className, style, }: SecondFactorStepProps): import("react").JSX.Element;
83
+ //# sourceMappingURL=SecondFactorStep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecondFactorStep.d.ts","sourceRoot":"","sources":["../../src/SecondFactorStep.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAA+B,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKxF;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,kBAAkB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,gBAAgB,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,4BAA4B,EAAE,kBAyC1C,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACrC,uFAAuF;IACvF,OAAO,EAAE,aAAa,CAAC;IACvB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAuBD,wBAAgB,gBAAgB,CAAC,EAChC,OAAO,EACP,UAAU,EACV,SAAS,EACT,MAAM,EAAE,SAAS,EACjB,SAAS,EACT,KAAK,GACL,EAAE,qBAAqB,+BA8ZvB"}
@@ -1,12 +1,16 @@
1
1
  import { type CSSProperties } from "react";
2
+ import { type SecondFactorLabels } from "./SecondFactorStep";
2
3
  /**
3
- * Email and password sign-in.
4
+ * Email and password sign-in, and — where the application turns them on — a
5
+ * magic link or a code by text message.
4
6
  *
5
7
  * Handles the MFA branch, because an account with a second factor gets a
6
8
  * challenge instead of a session, and a form that ignores that case appears to
7
- * fail for exactly the users who most need it to work.
9
+ * fail for exactly the users who most need it to work. That includes the case
10
+ * where the environment requires a factor and the person has none: they enrol
11
+ * one here (`SecondFactorStep`), see their recovery codes, and are signed in.
8
12
  */
9
- export declare function SignIn({ onSignedIn, passkeys, magicLinkRedirectUrl, className, style, }: {
13
+ export declare function SignIn({ onSignedIn, passkeys, magicLinkRedirectUrl, phone, secondFactorLabels, className, style, }: {
10
14
  onSignedIn?: () => void;
11
15
  /** Offer passkeys alongside the password. On by default where supported. */
12
16
  passkeys?: boolean;
@@ -20,6 +24,15 @@ export declare function SignIn({ onSignedIn, passkeys, magicLinkRedirectUrl, cla
20
24
  * redeems it automatically.
21
25
  */
22
26
  magicLinkRedirectUrl?: string;
27
+ /**
28
+ * Offer signing in with a code sent by text message.
29
+ *
30
+ * Off by default, because it needs the environment switched on for it and,
31
+ * in production, the environment's own Twilio account.
32
+ */
33
+ phone?: boolean;
34
+ /** Override the second-factor step's wording, for translation. */
35
+ secondFactorLabels?: Partial<SecondFactorLabels>;
23
36
  className?: string;
24
37
  style?: CSSProperties;
25
38
  }): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"SignIn.d.ts","sourceRoot":"","sources":["../../src/SignIn.tsx"],"names":[],"mappings":"AAGA,OAAO,EAA+B,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKxF;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,QAAe,EACf,oBAAoB,EACpB,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BA0UA"}
1
+ {"version":3,"file":"SignIn.d.ts","sourceRoot":"","sources":["../../src/SignIn.tsx"],"names":[],"mappings":"AASA,OAAO,EAA+B,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAIxF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE/E;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,QAAe,EACf,oBAAoB,EACpB,KAAa,EACb,kBAAkB,EAClB,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAmbA"}
@@ -1,4 +1,5 @@
1
1
  import { type CSSProperties } from "react";
2
+ import { type SecondFactorLabels } from "./SecondFactorStep";
2
3
  /**
3
4
  * Create an account.
4
5
  *
@@ -8,11 +9,58 @@ import { type CSSProperties } from "react";
8
9
  *
9
10
  * Sign-up does not itself produce a session, since the account still has to
10
11
  * verify its email. The form signs in straight afterwards so the common case
11
- * does not make people type their password twice.
12
+ * does not make people type their password twice — and when that sign-in owes
13
+ * a second factor, including enrolling one under a policy that requires it,
14
+ * the form carries on into that step rather than stopping with nothing on
15
+ * screen.
16
+ *
17
+ * The password rules shown are the environment's own, read from the API, and a
18
+ * refusal is the server's sentence for the rule that was missed.
19
+ *
20
+ * On a page reached from an invitation (`?invitation=`, or `invitationToken`)
21
+ * the token rides along with the sign-up. The account is then created straight
22
+ * into the inviting team — no personal workspace — with its address counted as
23
+ * verified, because the token reached that mailbox. The form says which team
24
+ * and fills in the address the invitation went to.
12
25
  */
13
- export declare function SignUp({ onSignedUp, className, style, }: {
26
+ export interface SignUpLabels {
27
+ name: string;
28
+ email: string;
29
+ password: string;
30
+ submit: string;
31
+ working: string;
32
+ /** Rules under the password box, joined by the component. */
33
+ ruleMinLength: (count: number) => string;
34
+ ruleUppercase: string;
35
+ ruleLowercase: string;
36
+ ruleNumber: string;
37
+ ruleSymbol: string;
38
+ ruleBreached: string;
39
+ /** Account made, but the environment wants the address confirmed first. */
40
+ confirmEmailTitle: string;
41
+ confirmEmail: (email: string) => string;
42
+ /** Account made, but signing in straight after failed for another reason. */
43
+ createdSignInFailed: (reason: string) => string;
44
+ /** A failure the server did not word. */
45
+ genericError: string;
46
+ /** Above the form when the page came from an invitation. */
47
+ joining: (organizationName: string, roleName: string) => string;
48
+ }
49
+ export declare const DEFAULT_SIGN_UP_LABELS: SignUpLabels;
50
+ export interface SignUpProps {
14
51
  onSignedUp?: () => void;
52
+ /**
53
+ * The invitation this sign-up accepts. Read from `?invitation=` when
54
+ * omitted; pass `null` to ignore the URL.
55
+ */
56
+ invitationToken?: string | null;
57
+ /** Called with the team's id when the sign-up accepted an invitation. */
58
+ onJoined?: (organizationId: string) => void;
59
+ labels?: Partial<SignUpLabels>;
60
+ /** Override the second-factor step's wording, for translation. */
61
+ secondFactorLabels?: Partial<SecondFactorLabels>;
15
62
  className?: string;
16
63
  style?: CSSProperties;
17
- }): import("react").JSX.Element;
64
+ }
65
+ export declare function SignUp({ onSignedUp, invitationToken: suppliedInvitation, onJoined, labels: overrides, secondFactorLabels, className, style, }: SignUpProps): import("react").JSX.Element;
18
66
  //# sourceMappingURL=SignUp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SignUp.d.ts","sourceRoot":"","sources":["../../src/SignUp.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKrE;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAyFA"}
1
+ {"version":3,"file":"SignUp.d.ts","sourceRoot":"","sources":["../../src/SignUp.tsx"],"names":[],"mappings":"AASA,OAAO,EAAuB,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAIhF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,6EAA6E;IAC7E,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,OAAO,EAAE,CAAC,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CAChE;AAED,eAAO,MAAM,sBAAsB,EAAE,YAoBpC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC3B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAiBD,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,eAAe,EAAE,kBAAkB,EACnC,QAAQ,EACR,MAAM,EAAE,SAAS,EACjB,kBAAkB,EAClB,SAAS,EACT,KAAK,GACL,EAAE,WAAW,+BA+Nb"}
@@ -6,7 +6,13 @@ import { type CSSProperties } from "react";
6
6
  * whoever the session says it is, so one user cannot be pointed at another's
7
7
  * billing by changing a prop.
8
8
  */
9
- export declare function SubscriptionManager({ className, style, }: {
9
+ export declare function SubscriptionManager({ onChange, className, style, }: {
10
+ /**
11
+ * Called after a cancel, a resume or an undone plan change, so a sibling
12
+ * showing the same subscription — an upcoming invoice, a plan picker — can
13
+ * refresh. `BillingPortal` uses it to keep its pieces in step.
14
+ */
15
+ onChange?: () => void;
10
16
  className?: string;
11
17
  style?: CSSProperties;
12
18
  }): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/SubscriptionManager.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAU7E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,SAAS,EACT,KAAK,GACL,EAAE;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BA2HA"}
1
+ {"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/SubscriptionManager.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAW7E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,QAAQ,EACR,SAAS,EACT,KAAK,GACL,EAAE;IACF;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAkMA"}
@@ -1 +1 @@
1
- {"version":3,"file":"TeamMembers.d.ts","sourceRoot":"","sources":["../../src/TeamMembers.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAM7E;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAChC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACjF,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,EAC3B,cAAc,EACd,SAAS,EACT,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,GACL,EAAE,gBAAgB,sCA+PlB"}
1
+ {"version":3,"file":"TeamMembers.d.ts","sourceRoot":"","sources":["../../src/TeamMembers.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAM7E;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAChC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACjF,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,EAC3B,cAAc,EACd,SAAS,EACT,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,GACL,EAAE,gBAAgB,sCA0QlB"}
@@ -2,10 +2,11 @@ import { type CSSProperties } from "react";
2
2
  /**
3
3
  * Turning on two-factor authentication.
4
4
  *
5
- * Two ways in: an authenticator app, and a code to the inbox. The app is the
6
- * stronger of the two and is offered first, but the email option is the one
7
- * people who will not install anything actually use — and a factor somebody
8
- * turns on beats a stronger one they decline.
5
+ * Three ways in: an authenticator app, a code to the inbox, and — where the
6
+ * application turns it on — a code by text message. The app is the strongest
7
+ * and is offered first; the other two are the ones people who will not install
8
+ * anything actually use, and a factor somebody turns on beats a stronger one
9
+ * they decline.
9
10
  *
10
11
  * Three steps, kept separate because the middle one is what stops people
11
12
  * locking themselves out: enrolling produces a secret that is useless until a
@@ -20,10 +21,18 @@ import { type CSSProperties } from "react";
20
21
  export interface TwoFactorManagerProps {
21
22
  /** Whether this account already has a factor. Drives which side is shown. */
22
23
  enabled?: boolean;
24
+ /**
25
+ * Offer a code by text message.
26
+ *
27
+ * Off by default, because it only works once the environment can send one —
28
+ * its own Twilio account in production — and a button that can only fail is
29
+ * worse than no button.
30
+ */
31
+ allowSms?: boolean;
23
32
  onEnabled?: () => void;
24
33
  onDisabled?: () => void;
25
34
  className?: string;
26
35
  style?: CSSProperties;
27
36
  }
28
- export declare function TwoFactorManager({ enabled, onEnabled, onDisabled, className, style, }: TwoFactorManagerProps): import("react").JSX.Element | null;
37
+ export declare function TwoFactorManager({ enabled, allowSms, onEnabled, onDisabled, className, style, }: TwoFactorManagerProps): import("react").JSX.Element | null;
29
38
  //# sourceMappingURL=TwoFactorManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TwoFactorManager.d.ts","sourceRoot":"","sources":["../../src/TwoFactorManager.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAMrD;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,qBAAqB;IACrC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AASD,wBAAgB,gBAAgB,CAAC,EAChC,OAAe,EACf,SAAS,EACT,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE,qBAAqB,sCAmOvB"}
1
+ {"version":3,"file":"TwoFactorManager.d.ts","sourceRoot":"","sources":["../../src/TwoFactorManager.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAMrD;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,qBAAqB;IACrC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAWD,wBAAgB,gBAAgB,CAAC,EAChC,OAAe,EACf,QAAgB,EAChB,SAAS,EACT,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE,qBAAqB,sCA+RvB"}
@@ -0,0 +1,21 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * The signed-in user's next bill: when it arrives, what is on it, and what it
4
+ * comes to.
5
+ *
6
+ * The figures are the billing engine's own — usage so far, the plan fee,
7
+ * addons, one-off charges, discount, tax and wallet balance — computed on
8
+ * request and stored nowhere, so showing this costs the user nothing and can
9
+ * never disagree with the invoice that follows, except by usage that arrives
10
+ * in between.
11
+ *
12
+ * A client company whose plan a firm pays for sees a line saying so rather
13
+ * than the firm's invoice, which lists every other client's usage too.
14
+ */
15
+ export declare function UpcomingInvoice({ showLines, className, style, }: {
16
+ /** Show the breakdown. Off gives one line: the amount and the date. */
17
+ showLines?: boolean;
18
+ className?: string;
19
+ style?: CSSProperties;
20
+ }): import("react").JSX.Element;
21
+ //# sourceMappingURL=UpcomingInvoice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpcomingInvoice.d.ts","sourceRoot":"","sources":["../../src/UpcomingInvoice.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAsChF;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,EAC/B,SAAgB,EAChB,SAAS,EACT,KAAK,GACL,EAAE;IACF,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BA+JA"}
@@ -50,7 +50,7 @@ export declare const STYLE_ELEMENT_ID = "base316-components";
50
50
  * never sets a token still gets a coherent look, and one that sets tokens on a
51
51
  * parent still wins through normal inheritance.
52
52
  */
53
- export declare const STYLESHEET = "\n.b316-root {\n --b316-color-primary: #111827;\n --b316-color-primary-text: #ffffff;\n --b316-color-text: #111827;\n --b316-color-muted: #6b7280;\n --b316-color-background: #ffffff;\n --b316-color-border: #e5e7eb;\n --b316-color-danger: #991b1b;\n --b316-color-danger-bg: #fef2f2;\n --b316-color-success: #166534;\n --b316-radius: 12px;\n --b316-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --b316-font-size: 15px;\n --b316-spacing: 12px;\n\n font-family: var(--b316-font);\n font-size: var(--b316-font-size);\n line-height: 1.5;\n color: var(--b316-color-text);\n}\n\n.b316-card {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n padding: calc(var(--b316-spacing) * 1.6);\n background: var(--b316-color-background);\n}\n\n.b316-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--b316-spacing); }\n.b316-label { font-size: 0.87em; color: var(--b316-color-muted); }\n\n.b316-input {\n padding: 9px 11px;\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) / 1.6);\n font: inherit;\n color: inherit;\n background: var(--b316-color-background);\n}\n.b316-input:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n\n.b316-button {\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.b316-button:hover:not([disabled]) { filter: brightness(1.12); }\n.b316-button:active:not([disabled]) { transform: translateY(1px); }\n.b316-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n.b316-button[disabled] { opacity: .55; cursor: not-allowed; }\n\n.b316-button-secondary {\n width: auto;\n transition: background-color .12s ease;\n background: var(--b316-color-background);\n color: var(--b316-color-text);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n}\n\n.b316-button-link {\n width: auto;\n background: none;\n border: 0;\n padding: 0;\n color: var(--b316-color-primary);\n font: inherit;\n cursor: pointer;\n text-decoration: underline;\n}\n\n/*\n * An armed confirmation: the question and its way out, side by side.\n *\n * Inline rather than a dialog, because a sandboxed iframe does not get dialogs\n * and these components are meant to be embedded in one.\n */\n.b316-confirm {\n display: inline-flex;\n gap: .4rem;\n align-items: center;\n}\n\n.b316-error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-muted { color: var(--b316-color-muted); font-size: 0.87em; }\n.b316-success { color: var(--b316-color-success); }\n\n.b316-plans {\n display: grid;\n gap: calc(var(--b316-spacing) * 1.3);\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n align-items: stretch;\n}\n\n.b316-plan {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n/* The recommended plan. Lifted rather than merely tinted: on a pricing table\n the eye needs one obvious default, and colour alone does not survive being\n viewed in greyscale or by someone who cannot distinguish the accent. */\n.b316-plan-featured {\n border-color: var(--b316-color-primary);\n box-shadow: 0 0 0 1px var(--b316-color-primary);\n}\n\n.b316-plan-badge {\n display: inline-block;\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n border-radius: 999px;\n padding: 2px 9px;\n font-size: 0.75em;\n font-weight: 600;\n letter-spacing: .02em;\n margin-bottom: 8px;\n}\n\n/* Occupies the badge's height without drawing anything, so a featured card\n does not push its own price and features out of line with the others. */\n.b316-plan-badge-spacer {\n display: inline-block;\n padding: 2px 9px;\n font-size: 0.75em;\n margin-bottom: 8px;\n visibility: hidden;\n}\n\n.b316-plan-head { padding: calc(var(--b316-spacing) * 1.6); padding-bottom: 0; }\n.b316-plan-name { font-weight: 600; font-size: 1.06em; }\n.b316-plan-desc { color: var(--b316-color-muted); font-size: 0.87em; margin-top: 2px; }\n\n.b316-plan-pricing { padding: 0 calc(var(--b316-spacing) * 1.6) calc(var(--b316-spacing) * 1.4); }\n\n.b316-plan-price {\n font-size: 2.1em;\n font-weight: 640;\n letter-spacing: -.02em;\n margin-top: calc(var(--b316-spacing) * 0.7);\n /* Lining figures of even width, so prices do not shimmer between cards. */\n font-variant-numeric: tabular-nums lining-nums;\n}\n\n.b316-plan-cadence { color: var(--b316-color-muted); font-size: 0.87em; min-height: 1.35em; }\n.b316-plan-trial { color: var(--b316-color-success); font-size: 0.87em; min-height: 1.35em; }\n\n.b316-plan-features {\n list-style: none;\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n margin: 0;\n flex: 1;\n border-top: 1px solid var(--b316-color-border);\n}\n.b316-plan-feature {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 0;\n font-size: 0.94em;\n}\n.b316-plan-feature-value { color: var(--b316-color-muted); font-variant-numeric: tabular-nums; }\n\n.b316-plan-action {\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n border-top: 1px solid var(--b316-color-border);\n}\n\n/* The plan already held. A faded primary button reads as broken rather than\n as \"you are here\", so this is a flat, quiet, genuinely inert surface. */\n.b316-button-current,\n.b316-button-current[disabled] {\n background: transparent;\n color: var(--b316-color-muted);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n opacity: 1;\n cursor: default;\n}\n\n.b316-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; }\n\n/* Credential lists. A row is a thing plus the actions on it, and the actions\n stay put as names vary in length, so the eye tracks one column not two. */\n.b316-list { list-style: none; margin: 0; padding: 0; }\n\n.b316-list-item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n padding: 12px 0;\n border-top: 1px solid var(--b316-color-border);\n}\n\n.b316-list-item:first-child { border-top: none; }\n\n/* Carries a secret shown exactly once, so it has to read as different from the\n rest of the card rather than as another paragraph. */\n.b316-notice {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n background: var(--b316-color-subtle, rgba(0,0,0,0.03));\n padding: 12px;\n font-size: 0.93em;\n}\n\n.b316-checkbox {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n}\n\n.b316-checkbox input[disabled] { cursor: default; }\n.b316-checkbox.b316-muted { cursor: default; }\n";
53
+ export declare const STYLESHEET = "\n.b316-root {\n --b316-color-primary: #111827;\n --b316-color-primary-text: #ffffff;\n --b316-color-text: #111827;\n --b316-color-muted: #6b7280;\n --b316-color-background: #ffffff;\n --b316-color-border: #e5e7eb;\n --b316-color-danger: #991b1b;\n --b316-color-danger-bg: #fef2f2;\n --b316-color-success: #166534;\n --b316-radius: 12px;\n --b316-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --b316-font-size: 15px;\n --b316-spacing: 12px;\n\n font-family: var(--b316-font);\n font-size: var(--b316-font-size);\n line-height: 1.5;\n color: var(--b316-color-text);\n}\n\n.b316-card {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n padding: calc(var(--b316-spacing) * 1.6);\n background: var(--b316-color-background);\n}\n\n.b316-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--b316-spacing); }\n.b316-label { font-size: 0.87em; color: var(--b316-color-muted); }\n\n.b316-input {\n padding: 9px 11px;\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) / 1.6);\n font: inherit;\n color: inherit;\n background: var(--b316-color-background);\n}\n.b316-input:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n\n.b316-button {\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.b316-button:hover:not([disabled]) { filter: brightness(1.12); }\n.b316-button:active:not([disabled]) { transform: translateY(1px); }\n.b316-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n.b316-button[disabled] { opacity: .55; cursor: not-allowed; }\n\n.b316-button-secondary {\n width: auto;\n transition: background-color .12s ease;\n background: var(--b316-color-background);\n color: var(--b316-color-text);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n}\n\n.b316-button-link {\n width: auto;\n background: none;\n border: 0;\n padding: 0;\n color: var(--b316-color-primary);\n font: inherit;\n cursor: pointer;\n text-decoration: underline;\n}\n\n/*\n * An armed confirmation: the question and its way out, side by side.\n *\n * Inline rather than a dialog, because a sandboxed iframe does not get dialogs\n * and these components are meant to be embedded in one.\n */\n.b316-confirm {\n display: inline-flex;\n gap: .4rem;\n align-items: center;\n}\n\n.b316-error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-muted { color: var(--b316-color-muted); font-size: 0.87em; }\n.b316-success { color: var(--b316-color-success); }\n\n.b316-plans {\n display: grid;\n gap: calc(var(--b316-spacing) * 1.3);\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n align-items: stretch;\n}\n\n/* Messages above the cards span the row rather than taking a card's column. */\n.b316-plans-error,\n.b316-plans-managed { grid-column: 1 / -1; }\n\n.b316-plan {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n/* The recommended plan. Lifted rather than merely tinted: on a pricing table\n the eye needs one obvious default, and colour alone does not survive being\n viewed in greyscale or by someone who cannot distinguish the accent. */\n.b316-plan-featured {\n border-color: var(--b316-color-primary);\n box-shadow: 0 0 0 1px var(--b316-color-primary);\n}\n\n.b316-plan-badge {\n display: inline-block;\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n border-radius: 999px;\n padding: 2px 9px;\n font-size: 0.75em;\n font-weight: 600;\n letter-spacing: .02em;\n margin-bottom: 8px;\n}\n\n/* Occupies the badge's height without drawing anything, so a featured card\n does not push its own price and features out of line with the others. */\n.b316-plan-badge-spacer {\n display: inline-block;\n padding: 2px 9px;\n font-size: 0.75em;\n margin-bottom: 8px;\n visibility: hidden;\n}\n\n.b316-plan-head { padding: calc(var(--b316-spacing) * 1.6); padding-bottom: 0; }\n.b316-plan-name { font-weight: 600; font-size: 1.06em; }\n.b316-plan-desc { color: var(--b316-color-muted); font-size: 0.87em; margin-top: 2px; }\n\n.b316-plan-pricing { padding: 0 calc(var(--b316-spacing) * 1.6) calc(var(--b316-spacing) * 1.4); }\n\n.b316-plan-price {\n font-size: 2.1em;\n font-weight: 640;\n letter-spacing: -.02em;\n margin-top: calc(var(--b316-spacing) * 0.7);\n /* Lining figures of even width, so prices do not shimmer between cards. */\n font-variant-numeric: tabular-nums lining-nums;\n}\n\n.b316-plan-cadence { color: var(--b316-color-muted); font-size: 0.87em; min-height: 1.35em; }\n.b316-plan-trial { color: var(--b316-color-success); font-size: 0.87em; min-height: 1.35em; }\n\n.b316-plan-features {\n list-style: none;\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n margin: 0;\n flex: 1;\n border-top: 1px solid var(--b316-color-border);\n}\n.b316-plan-feature {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 0;\n font-size: 0.94em;\n}\n.b316-plan-feature-value { color: var(--b316-color-muted); font-variant-numeric: tabular-nums; }\n\n.b316-plan-action {\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n border-top: 1px solid var(--b316-color-border);\n}\n\n/* The plan already held. A faded primary button reads as broken rather than\n as \"you are here\", so this is a flat, quiet, genuinely inert surface. */\n.b316-button-current,\n.b316-button-current[disabled] {\n background: transparent;\n color: var(--b316-color-muted);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n opacity: 1;\n cursor: default;\n}\n\n.b316-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; }\n\n/* Credential lists. A row is a thing plus the actions on it, and the actions\n stay put as names vary in length, so the eye tracks one column not two. */\n.b316-list { list-style: none; margin: 0; padding: 0; }\n\n.b316-list-item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n padding: 12px 0;\n border-top: 1px solid var(--b316-color-border);\n}\n\n.b316-list-item:first-child { border-top: none; }\n\n/* Carries a secret shown exactly once, so it has to read as different from the\n rest of the card rather than as another paragraph. */\n.b316-notice {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n background: var(--b316-color-subtle, rgba(0,0,0,0.03));\n padding: 12px;\n font-size: 0.93em;\n}\n\n.b316-checkbox {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n}\n\n.b316-checkbox input[disabled] { cursor: default; }\n.b316-checkbox.b316-muted { cursor: default; }\n";
54
54
  /** Join the component's own class with any the host passed in. */
55
55
  export declare function cls(base: string, extra?: string): string;
56
56
  /**
@@ -59,5 +59,5 @@ export declare function cls(base: string, extra?: string): string;
59
59
  * Appended as a second block so the print rules stay next to the invoice they
60
60
  * apply to, rather than being buried in the middle of the component styles.
61
61
  */
62
- export declare const STYLESHEET_EXTRA = "\n.b316-pay__element { margin-bottom: var(--b316-spacing); min-height: 40px; }\n\n.b316-pay__submit {\n width: 100%;\n padding: 11px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: #fff;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n\n.b316-pay__submit[disabled] { opacity: 0.55; cursor: progress; }\n\n.b316-pay__error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-pay__done {\n background: var(--b316-color-success-bg, #f0fdf4);\n color: var(--b316-color-success);\n padding: 12px 14px;\n border-radius: calc(var(--b316-radius) / 2);\n text-align: center;\n margin: 0;\n}\n\n.b316-tabs { display: flex; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--b316-color-border); }\n.b316-tab {\n flex: 1; padding: 8px 4px; background: none; border: 0; cursor: pointer;\n font: inherit; font-size: .95em; color: var(--b316-color-muted);\n border-bottom: 2px solid transparent; margin-bottom: -1px;\n}\n.b316-tab-on { color: var(--b316-color-text); border-bottom-color: var(--b316-color-primary); }\n.b316-branding { display: flex; flex-direction: column; gap: 4px; }\n.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }\n.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }\n.b316-branding-tagline { color: var(--b316-color-muted); }\n\n.b316-invoice-table { width: 100%; border-collapse: collapse; font-size: 0.94em; }\n.b316-invoice-table th {\n text-align: left;\n font-weight: 500;\n color: var(--b316-color-muted);\n font-size: 0.85em;\n padding: 0 0 6px;\n border-bottom: 1px solid var(--b316-color-border);\n}\n.b316-invoice-table td { padding: 9px 0; border-bottom: 1px solid var(--b316-color-border); }\n/* Columns need breathing room or the amount runs straight into the action \u2014\n \"$49.00View\" \u2014 which is what happens when only the row has padding. */\n.b316-invoice-table th + th,\n.b316-invoice-table td + td { padding-left: 16px; }\n.b316-invoice-table td:last-child,\n.b316-invoice-table th:last-child { text-align: right; width: 1%; white-space: nowrap; }\n.b316-invoice-table tr:last-child td { border-bottom: 0; }\n.b316-num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.b316-invoice-view {\n margin-top: calc(var(--b316-spacing) * 1.4);\n border-top: 1px solid var(--b316-color-border);\n padding-top: calc(var(--b316-spacing) * 1.4);\n}\n.b316-invoice-actions { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: var(--b316-spacing); }\n.b316-invoice-doc { display: flex; flex-direction: column; gap: calc(var(--b316-spacing) * 1.4); }\n.b316-invoice-meta { display: grid; grid-template-columns: 1fr 1fr; gap: var(--b316-spacing); }\n.b316-invoice-totals { display: flex; flex-direction: column; gap: 6px; margin-left: auto; min-width: 240px; }\n.b316-invoice-total { font-weight: 650; border-top: 1px solid var(--b316-color-border); padding-top: 6px; }\n\n/* Printing an invoice emits the invoice alone, and printing anything else is\n none of this package's business.\n\n This used to start with a bare \"body * { visibility: hidden }\", which is the\n usual recipe for printing one element \u2014 and it is scoped to the document,\n not to us. The stylesheet is injected into the host page's head the first\n time any Base316 component mounts, so from that moment every print in the\n host application came out blank unless the content happened to sit inside\n .b316-invoice-doc. A customer printing their own page had no way to connect\n it back to us.\n\n Scoped to a root the invoice sets on <html> while it is being printed\n instead, so nothing applies unless an invoice asked for it. */\n@media print {\n [data-b316-printing] body * { visibility: hidden; }\n [data-b316-printing] .b316-invoice-doc,\n [data-b316-printing] .b316-invoice-doc * { visibility: visible; }\n [data-b316-printing] .b316-invoice-doc {\n position: absolute;\n inset: 0 auto auto 0;\n width: 100%;\n padding: 24px;\n }\n .b316-invoice-actions { display: none; }\n}\n\n/* --- Collections: tables, forms and detail views ------------------------- */\n\n.b316-table-wrap { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-table-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); flex-wrap: wrap; }\n.b316-table-actions { display: flex; align-items: center; gap: var(--b316-spacing); }\n\n/* The table scrolls inside its own box rather than pushing the page sideways:\n a collection with twenty fields is normal, and a horizontally scrolling page\n makes every other component on it unreachable. */\n.b316-table-scroll { overflow-x: auto; border: 1px solid var(--b316-color-border); border-radius: var(--b316-radius); }\n.b316-table { width: 100%; border-collapse: collapse; font-size: 0.95em; }\n.b316-table th, .b316-table td { padding: 10px 12px; text-align: left; vertical-align: top; white-space: nowrap; }\n.b316-table thead th { background: var(--b316-color-surface-muted, rgba(0,0,0,.03)); font-weight: 600; font-size: 0.87em; color: var(--b316-color-muted); border-bottom: 1px solid var(--b316-color-border); }\n.b316-table tbody tr + tr td { border-top: 1px solid var(--b316-color-border); }\n.b316-row-clickable { cursor: pointer; }\n.b316-row-clickable:hover td { background: var(--b316-color-surface-muted, rgba(0,0,0,.02)); }\n.b316-table-rowactions { text-align: right; white-space: nowrap; }\n.b316-table-more { display: flex; justify-content: center; }\n\n.b316-sort { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }\n.b316-sort:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n\n.b316-empty { padding: calc(var(--b316-spacing) * 2); text-align: center; color: var(--b316-color-muted); }\n\n.b316-button-quiet {\n background: none;\n border: 0;\n padding: 4px 6px;\n font: inherit;\n font-size: 0.9em;\n color: var(--b316-color-primary);\n cursor: pointer;\n border-radius: calc(var(--b316-radius) / 2);\n}\n.b316-button-quiet:hover:not([disabled]) { background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); }\n.b316-button-quiet:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n.b316-button-quiet[disabled] { opacity: .55; cursor: not-allowed; }\n.b316-danger { color: var(--b316-color-danger, #b42318); }\n\n.b316-chip {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--b316-color-surface-muted, rgba(0,0,0,.05));\n font-size: 0.87em;\n}\n.b316-chips { display: inline-flex; gap: 4px; flex-wrap: wrap; }\n\n.b316-form { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-form-title { margin: 0; font-size: 1.05em; }\n.b316-form-actions { display: flex; justify-content: flex-end; gap: 8px; }\n.b316-field { display: flex; flex-direction: column; gap: 4px; }\n.b316-hint { font-size: 0.82em; color: var(--b316-color-muted); }\n.b316-input-invalid { border-color: var(--b316-color-danger, #b42318); }\n.b316-choices { display: flex; flex-wrap: wrap; gap: 10px; }\n.b316-choice { display: inline-flex; align-items: center; gap: 6px; font-size: 0.95em; }\n.b316-suffixed { display: flex; align-items: center; gap: 8px; }\n.b316-address { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }\n\n.b316-relation-chosen { display: flex; align-items: center; gap: 8px; }\n.b316-relation-results {\n list-style: none;\n margin: 4px 0 0;\n padding: 4px;\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n max-height: 220px;\n overflow-y: auto;\n background: var(--b316-color-surface, #fff);\n}\n.b316-relation-result { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 6px 8px; font: inherit; cursor: pointer; border-radius: calc(var(--b316-radius) / 2); }\n.b316-relation-result:hover, .b316-relation-result:focus-visible { background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); outline: none; }\n.b316-relation-empty { padding: 6px 8px; }\n\n.b316-detail { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--b316-spacing); }\n.b316-detail-title { margin: 0; font-size: 1.1em; }\n.b316-detail-actions { display: flex; gap: 4px; }\n.b316-detail-fields { display: grid; grid-template-columns: minmax(120px, 200px) 1fr; gap: 8px var(--b316-spacing); margin: 0; }\n.b316-detail-row { display: contents; }\n.b316-detail-fields dd { margin: 0; }\n\n/* One column on a narrow screen. A label column of 200px beside a value leaves\n nothing for the value on a phone. */\n/* --- Teams --------------------------------------------------------------- */\n\n.b316-team { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-team-title { margin: 0; font-size: 1em; font-weight: 600; }\n.b316-team-subtitle { margin: 0; font-size: .9em; font-weight: 600; color: var(--b316-color-muted); }\n.b316-team-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }\n.b316-team-member { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); }\n.b316-team-member-side { display: flex; align-items: center; gap: 8px; }\n.b316-team-invite { display: flex; flex-direction: column; gap: 4px; }\n.b316-team-invite-row { display: flex; gap: 8px; }\n.b316-team-invite-row input { flex: 1; }\n/* Selectable and wrapping: this is copied by hand and pasted into an email. */\n.b316-team-link { display: flex; flex-direction: column; gap: 4px; }\n.b316-team-link code { word-break: break-all; user-select: all; padding: 8px; border: 1px solid var(--b316-color-border); border-radius: var(--b316-radius); }\n\n.b316-invitation { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-invitation-actions { display: flex; align-items: center; gap: var(--b316-spacing); }\n\n/* --- Sessions, two-factor and the password flows ------------------------- */\n\n.b316-sessions { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-sessions-head { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); flex-wrap: wrap; }\n.b316-sessions-title, .b316-mfa-title { margin: 0; font-size: 1em; font-weight: 600; }\n.b316-sessions-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }\n.b316-session { display: flex; flex-direction: column; gap: 2px; }\n.b316-session-device { display: flex; align-items: center; gap: 6px; font-size: 0.95em; }\n\n.b316-device { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-device-title { margin: 0; font-size: 1em; font-weight: 600; }\n/* What is being granted, listed rather than run together: somebody is deciding\n on this, and a comma-separated line is read as one thing. */\n.b316-device-scopes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }\n.b316-device-scopes li { padding: 2px 8px; border-radius: 999px; font-size: 0.85em; background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); }\n.b316-device-actions { display: flex; gap: 8px; }\n\n.b316-privacy { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-privacy-title { margin: 0; font-size: 1em; font-weight: 600; }\n/* Wraps rather than squeezes: the explanation beside each control is the part\n that matters, and on a narrow screen it belongs above the button. */\n.b316-privacy-row { display: flex; flex-wrap: wrap; align-items: start; justify-content: space-between; gap: 10px; }\n.b316-privacy-row p { margin: 0; }\n.b316-privacy-confirm { display: flex; flex-direction: column; gap: 8px; }\n.b316-privacy-actions { display: flex; justify-content: flex-end; gap: 8px; }\n\n.b316-mfa { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-mfa-enrol, .b316-mfa-codes, .b316-mfa-on, .b316-mfa-off { display: flex; flex-direction: column; gap: 10px; }\n.b316-mfa-actions { display: flex; justify-content: flex-end; gap: 8px; }\n/* Selectable and wrapping: this is copied by hand on the device that cannot\n scan its own screen. */\n.b316-mfa-secret code {\n display: block;\n padding: 10px;\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n font-size: 1.05em;\n letter-spacing: .08em;\n word-break: break-all;\n user-select: all;\n}\n.b316-mfa-uri { font-size: 0.9em; }\n.b316-mfa-code-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }\n.b316-mfa-code-list code { user-select: all; }\n\n@media (max-width: 560px) {\n .b316-mfa-code-list { grid-template-columns: 1fr; }\n .b316-detail-fields { grid-template-columns: 1fr; }\n .b316-detail-row { display: block; margin-bottom: 10px; }\n .b316-address { grid-template-columns: 1fr; }\n}\n\n/* --- Board --------------------------------------------------------------- */\n\n.b316-board-wrap { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n/* The board scrolls sideways inside itself. Six columns is normal and a page\n that scrolls horizontally puts everything else on it out of reach. */\n.b316-board { display: flex; gap: var(--b316-spacing); overflow-x: auto; align-items: flex-start; padding-bottom: 4px; }\n.b316-board-column {\n flex: 0 0 260px;\n background: var(--b316-color-surface-muted, rgba(0,0,0,.03));\n border: 1px solid transparent;\n border-radius: var(--b316-radius);\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.b316-board-over { border-color: var(--b316-color-primary); }\n.b316-board-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.b316-board-title { font-weight: 600; font-size: 0.92em; }\n.b316-board-cards { display: flex; flex-direction: column; gap: 8px; min-height: 40px; }\n.b316-board-card {\n background: var(--b316-color-surface, #fff);\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) * .8);\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n font-size: 0.9em;\n}\n.b316-board-card[draggable=\"true\"] { cursor: grab; }\n.b316-board-card-title { font-weight: 600; }\n.b316-board-card-field { display: flex; justify-content: space-between; gap: 8px; }\n.b316-board-move { display: flex; align-items: center; gap: 6px; margin-top: 2px; }\n.b316-board-move select { flex: 1; font-size: 0.9em; padding: 2px 4px; }\n.b316-board-empty { color: var(--b316-color-muted); font-size: 0.87em; padding: 6px 2px; }\n\n/* --- Chart --------------------------------------------------------------- */\n\n.b316-chart { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-chart-title { font-weight: 600; font-size: 0.95em; }\n.b316-chart-plot { display: flex; align-items: flex-end; gap: 4px; overflow-x: auto; }\n.b316-chart-col { flex: 1 0 24px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 4px; }\n.b316-chart-bar { width: 100%; background: var(--b316-color-primary); border-radius: 3px 3px 0 0; min-height: 2px; }\n.b316-chart-label { font-size: 0.7em; color: var(--b316-color-muted); white-space: nowrap; transform: rotate(-45deg); transform-origin: top left; height: 1.6em; }\n.b316-chart-data summary { cursor: pointer; font-size: 0.87em; color: var(--b316-color-muted); }\n.b316-chart-data table { margin-top: 8px; }\n";
62
+ export declare const STYLESHEET_EXTRA = "\n.b316-pay__element { margin-bottom: var(--b316-spacing); min-height: 40px; }\n\n.b316-pay__submit {\n width: 100%;\n padding: 11px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: #fff;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n\n.b316-pay__submit[disabled] { opacity: 0.55; cursor: progress; }\n\n.b316-pay__error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-pay__done {\n background: var(--b316-color-success-bg, #f0fdf4);\n color: var(--b316-color-success);\n padding: 12px 14px;\n border-radius: calc(var(--b316-radius) / 2);\n text-align: center;\n margin: 0;\n}\n\n.b316-tabs { display: flex; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--b316-color-border); }\n.b316-tab {\n flex: 1; padding: 8px 4px; background: none; border: 0; cursor: pointer;\n font: inherit; font-size: .95em; color: var(--b316-color-muted);\n border-bottom: 2px solid transparent; margin-bottom: -1px;\n}\n.b316-tab-on { color: var(--b316-color-text); border-bottom-color: var(--b316-color-primary); }\n.b316-branding { display: flex; flex-direction: column; gap: 4px; }\n.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }\n.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }\n.b316-branding-tagline { color: var(--b316-color-muted); }\n\n.b316-invoice-table { width: 100%; border-collapse: collapse; font-size: 0.94em; }\n.b316-invoice-table th {\n text-align: left;\n font-weight: 500;\n color: var(--b316-color-muted);\n font-size: 0.85em;\n padding: 0 0 6px;\n border-bottom: 1px solid var(--b316-color-border);\n}\n.b316-invoice-table td { padding: 9px 0; border-bottom: 1px solid var(--b316-color-border); }\n/* Columns need breathing room or the amount runs straight into the action \u2014\n \"$49.00View\" \u2014 which is what happens when only the row has padding. */\n.b316-invoice-table th + th,\n.b316-invoice-table td + td { padding-left: 16px; }\n.b316-invoice-table td:last-child,\n.b316-invoice-table th:last-child { text-align: right; width: 1%; white-space: nowrap; }\n.b316-invoice-table tr:last-child td { border-bottom: 0; }\n.b316-num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.b316-invoice-view {\n margin-top: calc(var(--b316-spacing) * 1.4);\n border-top: 1px solid var(--b316-color-border);\n padding-top: calc(var(--b316-spacing) * 1.4);\n}\n.b316-invoice-actions { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: var(--b316-spacing); }\n.b316-invoice-doc { display: flex; flex-direction: column; gap: calc(var(--b316-spacing) * 1.4); }\n.b316-invoice-meta { display: grid; grid-template-columns: 1fr 1fr; gap: var(--b316-spacing); }\n.b316-invoice-totals { display: flex; flex-direction: column; gap: 6px; margin-left: auto; min-width: 240px; }\n.b316-invoice-total { font-weight: 650; border-top: 1px solid var(--b316-color-border); padding-top: 6px; }\n\n/* Printing an invoice emits the invoice alone, and printing anything else is\n none of this package's business.\n\n This used to start with a bare \"body * { visibility: hidden }\", which is the\n usual recipe for printing one element \u2014 and it is scoped to the document,\n not to us. The stylesheet is injected into the host page's head the first\n time any Base316 component mounts, so from that moment every print in the\n host application came out blank unless the content happened to sit inside\n .b316-invoice-doc. A customer printing their own page had no way to connect\n it back to us.\n\n Scoped to a root the invoice sets on <html> while it is being printed\n instead, so nothing applies unless an invoice asked for it. */\n@media print {\n [data-b316-printing] body * { visibility: hidden; }\n [data-b316-printing] .b316-invoice-doc,\n [data-b316-printing] .b316-invoice-doc * { visibility: visible; }\n [data-b316-printing] .b316-invoice-doc {\n position: absolute;\n inset: 0 auto auto 0;\n width: 100%;\n padding: 24px;\n }\n .b316-invoice-actions { display: none; }\n}\n\n/* --- Collections: tables, forms and detail views ------------------------- */\n\n.b316-table-wrap { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-table-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); flex-wrap: wrap; }\n.b316-table-actions { display: flex; align-items: center; gap: var(--b316-spacing); }\n\n/* The table scrolls inside its own box rather than pushing the page sideways:\n a collection with twenty fields is normal, and a horizontally scrolling page\n makes every other component on it unreachable. */\n.b316-table-scroll { overflow-x: auto; border: 1px solid var(--b316-color-border); border-radius: var(--b316-radius); }\n.b316-table { width: 100%; border-collapse: collapse; font-size: 0.95em; }\n.b316-table th, .b316-table td { padding: 10px 12px; text-align: left; vertical-align: top; white-space: nowrap; }\n.b316-table thead th { background: var(--b316-color-surface-muted, rgba(0,0,0,.03)); font-weight: 600; font-size: 0.87em; color: var(--b316-color-muted); border-bottom: 1px solid var(--b316-color-border); }\n.b316-table tbody tr + tr td { border-top: 1px solid var(--b316-color-border); }\n.b316-row-clickable { cursor: pointer; }\n.b316-row-clickable:hover td { background: var(--b316-color-surface-muted, rgba(0,0,0,.02)); }\n.b316-table-rowactions { text-align: right; white-space: nowrap; }\n.b316-table-more { display: flex; justify-content: center; }\n\n.b316-sort { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }\n.b316-sort:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n\n.b316-empty { padding: calc(var(--b316-spacing) * 2); text-align: center; color: var(--b316-color-muted); }\n\n.b316-button-quiet {\n background: none;\n border: 0;\n padding: 4px 6px;\n font: inherit;\n font-size: 0.9em;\n color: var(--b316-color-primary);\n cursor: pointer;\n border-radius: calc(var(--b316-radius) / 2);\n}\n.b316-button-quiet:hover:not([disabled]) { background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); }\n.b316-button-quiet:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n.b316-button-quiet[disabled] { opacity: .55; cursor: not-allowed; }\n.b316-danger { color: var(--b316-color-danger, #b42318); }\n\n.b316-chip {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--b316-color-surface-muted, rgba(0,0,0,.05));\n font-size: 0.87em;\n}\n.b316-chips { display: inline-flex; gap: 4px; flex-wrap: wrap; }\n\n.b316-form { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-form-title { margin: 0; font-size: 1.05em; }\n.b316-form-actions { display: flex; justify-content: flex-end; gap: 8px; }\n.b316-field { display: flex; flex-direction: column; gap: 4px; }\n.b316-hint { font-size: 0.82em; color: var(--b316-color-muted); }\n.b316-input-invalid { border-color: var(--b316-color-danger, #b42318); }\n.b316-choices { display: flex; flex-wrap: wrap; gap: 10px; }\n.b316-choice { display: inline-flex; align-items: center; gap: 6px; font-size: 0.95em; }\n.b316-suffixed { display: flex; align-items: center; gap: 8px; }\n.b316-address { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }\n\n.b316-relation-chosen { display: flex; align-items: center; gap: 8px; }\n.b316-relation-results {\n list-style: none;\n margin: 4px 0 0;\n padding: 4px;\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n max-height: 220px;\n overflow-y: auto;\n background: var(--b316-color-surface, #fff);\n}\n.b316-relation-result { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 6px 8px; font: inherit; cursor: pointer; border-radius: calc(var(--b316-radius) / 2); }\n.b316-relation-result:hover, .b316-relation-result:focus-visible { background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); outline: none; }\n.b316-relation-empty { padding: 6px 8px; }\n\n.b316-detail { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--b316-spacing); }\n.b316-detail-title { margin: 0; font-size: 1.1em; }\n.b316-detail-actions { display: flex; gap: 4px; }\n.b316-detail-fields { display: grid; grid-template-columns: minmax(120px, 200px) 1fr; gap: 8px var(--b316-spacing); margin: 0; }\n.b316-detail-row { display: contents; }\n.b316-detail-fields dd { margin: 0; }\n\n/* One column on a narrow screen. A label column of 200px beside a value leaves\n nothing for the value on a phone. */\n/* --- Teams --------------------------------------------------------------- */\n\n.b316-team { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-team-title { margin: 0; font-size: 1em; font-weight: 600; }\n.b316-team-subtitle { margin: 0; font-size: .9em; font-weight: 600; color: var(--b316-color-muted); }\n.b316-team-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }\n.b316-team-member { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); }\n.b316-team-member-side { display: flex; align-items: center; gap: 8px; }\n.b316-team-invite { display: flex; flex-direction: column; gap: 4px; }\n.b316-team-invite-row { display: flex; gap: 8px; }\n.b316-team-invite-row input { flex: 1; }\n/* Selectable and wrapping: this is copied by hand and pasted into an email. */\n.b316-team-link { display: flex; flex-direction: column; gap: 4px; }\n.b316-team-link code { word-break: break-all; user-select: all; padding: 8px; border: 1px solid var(--b316-color-border); border-radius: var(--b316-radius); }\n\n.b316-invitation { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-invitation-actions { display: flex; align-items: center; gap: var(--b316-spacing); }\n\n/* --- Sessions, two-factor and the password flows ------------------------- */\n\n.b316-sessions { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-sessions-head { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); flex-wrap: wrap; }\n.b316-sessions-title, .b316-mfa-title { margin: 0; font-size: 1em; font-weight: 600; }\n.b316-sessions-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }\n.b316-session { display: flex; flex-direction: column; gap: 2px; }\n.b316-session-device { display: flex; align-items: center; gap: 6px; font-size: 0.95em; }\n\n.b316-device { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-device-title { margin: 0; font-size: 1em; font-weight: 600; }\n/* What is being granted, listed rather than run together: somebody is deciding\n on this, and a comma-separated line is read as one thing. */\n.b316-device-scopes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }\n.b316-device-scopes li { padding: 2px 8px; border-radius: 999px; font-size: 0.85em; background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); }\n.b316-device-actions { display: flex; gap: 8px; }\n\n.b316-privacy { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-privacy-title { margin: 0; font-size: 1em; font-weight: 600; }\n/* Wraps rather than squeezes: the explanation beside each control is the part\n that matters, and on a narrow screen it belongs above the button. */\n.b316-privacy-row { display: flex; flex-wrap: wrap; align-items: start; justify-content: space-between; gap: 10px; }\n.b316-privacy-row p { margin: 0; }\n.b316-privacy-confirm { display: flex; flex-direction: column; gap: 8px; }\n.b316-privacy-actions { display: flex; justify-content: flex-end; gap: 8px; }\n\n.b316-mfa { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-mfa-enrol, .b316-mfa-codes, .b316-mfa-on, .b316-mfa-off { display: flex; flex-direction: column; gap: 10px; }\n.b316-mfa-actions { display: flex; justify-content: flex-end; gap: 8px; }\n/* Selectable and wrapping: this is copied by hand on the device that cannot\n scan its own screen. */\n.b316-mfa-secret code {\n display: block;\n padding: 10px;\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n font-size: 1.05em;\n letter-spacing: .08em;\n word-break: break-all;\n user-select: all;\n}\n.b316-mfa-uri { font-size: 0.9em; }\n.b316-mfa-code-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }\n.b316-mfa-code-list code { user-select: all; }\n/* The enrolment choices: whole-width buttons with their explanation inside,\n so the explanation is part of what a screen reader announces. */\n.b316-mfa-methods { display: flex; flex-direction: column; gap: 8px; border: 0; margin: 0; padding: 0; min-width: 0; }\n.b316-mfa-method { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; text-align: left; }\n.b316-mfa-method .b316-muted { font-weight: 400; }\n/* Always on white with a margin: a QR code on a dark theme does not scan. */\n.b316-mfa-qr { align-self: center; width: 180px; height: 180px; padding: 8px; background: #fff; border-radius: var(--b316-radius); }\n\n@media (max-width: 560px) {\n .b316-mfa-code-list { grid-template-columns: 1fr; }\n .b316-detail-fields { grid-template-columns: 1fr; }\n .b316-detail-row { display: block; margin-bottom: 10px; }\n .b316-address { grid-template-columns: 1fr; }\n}\n\n/* --- Board --------------------------------------------------------------- */\n\n.b316-board-wrap { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n/* The board scrolls sideways inside itself. Six columns is normal and a page\n that scrolls horizontally puts everything else on it out of reach. */\n.b316-board { display: flex; gap: var(--b316-spacing); overflow-x: auto; align-items: flex-start; padding-bottom: 4px; }\n.b316-board-column {\n flex: 0 0 260px;\n background: var(--b316-color-surface-muted, rgba(0,0,0,.03));\n border: 1px solid transparent;\n border-radius: var(--b316-radius);\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.b316-board-over { border-color: var(--b316-color-primary); }\n.b316-board-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.b316-board-title { font-weight: 600; font-size: 0.92em; }\n.b316-board-cards { display: flex; flex-direction: column; gap: 8px; min-height: 40px; }\n.b316-board-card {\n background: var(--b316-color-surface, #fff);\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) * .8);\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n font-size: 0.9em;\n}\n.b316-board-card[draggable=\"true\"] { cursor: grab; }\n.b316-board-card-title { font-weight: 600; }\n.b316-board-card-field { display: flex; justify-content: space-between; gap: 8px; }\n.b316-board-move { display: flex; align-items: center; gap: 6px; margin-top: 2px; }\n.b316-board-move select { flex: 1; font-size: 0.9em; padding: 2px 4px; }\n.b316-board-empty { color: var(--b316-color-muted); font-size: 0.87em; padding: 6px 2px; }\n\n/* --- Chart --------------------------------------------------------------- */\n\n.b316-chart { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-chart-title { font-weight: 600; font-size: 0.95em; }\n.b316-chart-plot { display: flex; align-items: flex-end; gap: 4px; overflow-x: auto; }\n.b316-chart-col { flex: 1 0 24px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 4px; }\n.b316-chart-bar { width: 100%; background: var(--b316-color-primary); border-radius: 3px 3px 0 0; min-height: 2px; }\n.b316-chart-label { font-size: 0.7em; color: var(--b316-color-muted); white-space: nowrap; transform: rotate(-45deg); transform-origin: top left; height: 1.6em; }\n.b316-chart-data summary { cursor: pointer; font-size: 0.87em; color: var(--b316-color-muted); }\n.b316-chart-data table { margin-top: 8px; }\n\n/* --- Billing portal ------------------------------------------------------ */\n\n.b316-billing-portal { display: grid; gap: var(--b316-spacing); }\n.b316-billing-portal-section-title { font-weight: 600; font-size: 1em; margin: 0 0 8px; }\n.b316-billing-portal .b316-plans { margin: 0; }\n.b316-invoice-row-actions { white-space: nowrap; text-align: right; }\n.b316-invoice-row-actions .b316-button-link + .b316-button-link { margin-left: 8px; }\n.b316-review-table { width: 100%; border-collapse: collapse; font-size: 0.92em; margin: 8px 0; }\n.b316-review-table th, .b316-review-table td { text-align: left; padding: 6px 4px; border-top: 1px solid var(--b316-color-border, #e5e7eb); }\n.b316-review-table th { color: var(--b316-color-muted); font-weight: 500; border-top: 0; }\n.b316-review-gain { color: #065f46; }\n.b316-review-loss { color: var(--b316-color-danger); }\n.b316-review-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }\n@media (max-width: 560px) {\n .b316-invoice-table th:nth-child(2), .b316-invoice-table td:nth-child(2) { display: none; }\n .b316-review-actions .b316-button { flex: 1 1 100%; }\n}\n";
63
63
  //# sourceMappingURL=appearance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/appearance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,iBAAiB;IACjC,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAkBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAgB/E;AAED,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,o5NA0OtB,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,+gfAgT5B,CAAC"}
1
+ {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/appearance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,iBAAiB;IACjC,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAkBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAgB/E;AAED,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,yiOA8OtB,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,8xiBAyU5B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;GAIG;AACH,MAAM,MAAM,WAAW;AACtB,8EAA8E;AAC5E,SAAS;AACX,gFAAgF;GAC9E,YAAY;AACd,kDAAkD;GAChD,OAAO;AACT,mFAAmF;GACjF,gBAAgB;AAClB,mEAAmE;GACjE,aAAa,CAAC;AAEjB,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;IACxC,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAOD,eAAO,MAAM,QAAQ,EAAE,aAAa,EAqlBnC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;aACvB,KAAK,YACJ,qEAAqE,EACrE,yIAAyI,EACzI,2JAA2J,EAC3J,+QAA+Q,EAC/Q,0ZAA0Z,EAC1Z,4KAA4K;IAE7K,uDAAuD;aACvD,OAAO;CAyBE,CAAC;AAEX,2BAA2B;AAC3B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE,CAE7E"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;GAIG;AACH,MAAM,MAAM,WAAW;AACtB,8EAA8E;AAC5E,SAAS;AACX,gFAAgF;GAC9E,YAAY;AACd,kDAAkD;GAChD,OAAO;AACT,mFAAmF;GACjF,gBAAgB;AAClB,mEAAmE;GACjE,aAAa,CAAC;AAEjB,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;IACxC,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAOD,eAAO,MAAM,QAAQ,EAAE,aAAa,EAo3BnC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;aACvB,KAAK,YACJ,qEAAqE,EACrE,yIAAyI,EACzI,2JAA2J,EAC3J,+QAA+Q,EAC/Q,0ZAA0Z,EAC1Z,4KAA4K;IAE7K,uDAAuD;aACvD,OAAO;CAyBE,CAAC;AAEX,2BAA2B;AAC3B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE,CAE7E"}