/*
 * Folio — the Paysio design library. v1
 *
 *   <link rel="stylesheet" href="https://cdn.paysio.com/folio-1.css">
 *
 * A folio is a leaf of a ledger. Every screen an app draws is a page in the
 * merchant's book, and this is what makes it read as one.
 *
 * Versioned by URL: folio-1.css rolls forward within v1, folio-1.0.css pins
 * this design. A dashboard redesign reaches every app without anyone shipping
 * an upgrade. A pinned file is NEVER overwritten once published (browsers and
 * the edge cache it for a year); a changed design gets the next number.
 *
 * Every class below is transcribed from the Paysio dashboard's own components
 * — same geometry, same shadows, same type ramp — so an app built on them
 * reads as part of the dashboard, not as a page framed by it.
 *
 * ── Where an app lives ───────────────────────────────────────────────────
 *
 * The dashboard draws a 44px header bar ABOVE the app: the app's name as a
 * crumb back to Apps, and an About action. The app fills the content island
 * below it, edge to edge, on the island's own surface (--card). So a page
 * never repeats the app's name as a title, never draws its own header, and
 * never wraps itself in a border or card: the dashboard already framed it.
 * The merchant is already signed in, on the sandbox or live side they chose.
 * The first screen is the work.
 *
 * ── The design language ──────────────────────────────────────────────────
 *
 * TYPE    Inter everywhere. 13px/medium is the dashboard's working density
 *         (menu rows, table chrome, section titles); 14px is body copy and
 *         form controls; 16px/semibold with -0.04em tracking is actions and
 *         titles; 11px/medium is badges. Headings always tighten: -0.04em.
 *
 * SHAPE   A deliberate radius ramp, not one knob: pills (9999px) for buttons,
 *         12px for standalone surfaces (cards, tables, menus), 24px for
 *         popups, 12px for inputs, 8px for rows nested inside a 12px surface
 *         (inner radius = outer minus the 4px gap, so corners stay
 *         concentric). Buttons inside a popup square to 12px.
 *
 * EDGES   One hairline (--border) does the real work; --border-subtle is a
 *         highlight, not a line. Never stack a border on a tinted fill — the
 *         fill already separates.
 *
 * DEPTH   Three shadow recipes, used consistently:
 *           resting card    0 1px 0 rgba(26,26,26,.06), 0 8px 16px rgba(26,26,26,.08)
 *           floating menu   0 10px 28px -8px rgba(0,0,0,.16), 0 2px 6px -2px rgba(0,0,0,.08)
 *           modal popup     0 0 0 1px rgba(0,0,0,.04), 0 16px 48px -12px rgba(0,0,0,.26), 0 4px 12px -6px rgba(0,0,0,.12)
 *
 * SPACE   A 4px grid: 4/8/12/16/20/24. Pages pad 16px top, 24px sides and
 *         bottom. Sections breathe 24px apart; things inside a section 12px.
 *
 * MOTION  150ms for state changes, press feedback by scale(0.97), 200ms
 *         cubic-bezier(0.32,0.72,0,1) for popups. Loading is a shimmer
 *         sweeping a static bar — never a whole block pulsing.
 *
 * The values below are only fallbacks. Inside an embed, paysio-bridge-1.js
 * pushes the merchant's live tokens onto :root — including dark mode and any
 * white-label brand tint — so an app built on these classes follows the theme
 * with no work of its own.
 *
 * GENERATED by scripts/build-app-ui.ts from src/index.css and the components
 * under src/components/ui. Do not edit by hand.
 */

/* Inter is the dashboard's typeface, so an app that does nothing sits in the
   same face as the chrome around it. An app that would rather self-host Inter
   (or use its own face) overrides --folio-font and this costs it one cached
   request. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;450;500;550;600;650;700&display=swap');

:root {
  --background: lch(95.94% 0.5 282);
  --foreground: lch(9.894% 0 282);
  --muted: lch(95.94% 0.5 282);
  --muted-foreground: lch(39.576% 1.25 282);
  --primary: rgba(11, 87, 208, 1);
  --primary-foreground: rgba(255, 255, 255, 1);
  --secondary: rgba(234, 234, 237, 1);
  --secondary-foreground: rgba(48, 48, 48, 1);
  --border: lch(93.5% 0 282);
  --border-subtle: lch(97.6% 0 282);
  --radius: 0.5rem;
  --card: lch(98.94% 0.5 282);
  --card-foreground: lch(9.894% 0 282);
  --popover: lch(98.94% 0.5 282);
  --popover-foreground: lch(9.894% 0 282);
  --accent: rgba(0, 0, 0, 0.04);
  --accent-foreground: lch(9.894% 0 282);
  --destructive: rgba(199, 10, 36, 1);
  --destructive-foreground: rgba(255, 255, 255, 1);
  --input: color-mix(in srgb, var(--card) 87%, #000);
  --ring: rgba(0, 0, 0, 0.22);
  --dropdown: rgba(248, 248, 249, 1);
  --inverse: rgba(48, 48, 48, 1);
  --inverse-foreground: rgba(255, 255, 255, 1);
  --secondary-hover: rgba(223, 223, 227, 1);
  --row-hover: rgba(0, 0, 0, 0.04);
  --row-active: rgba(0, 0, 0, 0.065);
  --tertiary: rgba(233, 233, 235, 1);
  --tertiary-foreground: lch(9.894% 0 282);
  --success: rgba(175, 235, 191, 1);
  --success-foreground: rgba(1, 75, 64, 1);
  --warning: rgba(255, 214, 164, 1);
  --warning-foreground: rgba(74, 21, 4, 1);
  --info: rgba(196, 222, 255, 1);
  --info-foreground: rgba(0, 46, 105, 1);
  --skeleton-sheen: rgba(255, 255, 255, 0.3);
  --folio-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
  --skeleton-sweep: 1.5s;
  --skeleton-delay: 500ms;
  --skeleton-fade: 240ms;
}

/* Applied by the bridge when the merchant is in dark mode. */
.dark {
  --background: rgba(10, 10, 10, 1);
  --foreground: rgba(240, 240, 240, 1);
  --muted: rgba(32, 32, 32, 1);
  --muted-foreground: rgba(166, 166, 166, 1);
  --primary: rgba(11, 87, 208, 1);
  --primary-foreground: rgba(255, 255, 255, 1);
  --secondary: rgba(24, 24, 24, 1);
  --secondary-foreground: rgba(232, 232, 232, 1);
  --border: rgba(255, 255, 255, 0.09);
  --border-subtle: color-mix(in srgb, var(--border) 40%, transparent);
  --card: rgba(16, 16, 16, 1);
  --card-foreground: rgba(240, 240, 240, 1);
  --popover: rgba(16, 16, 16, 1);
  --popover-foreground: rgba(240, 240, 240, 1);
  --accent: rgba(255, 255, 255, 0.06);
  --accent-foreground: rgba(240, 240, 240, 1);
  --destructive: rgba(220, 38, 38, 1);
  --destructive-foreground: rgba(255, 255, 255, 1);
  --input: color-mix(in srgb, var(--card) 80%, #fff);
  --ring: rgba(255, 255, 255, 0.4);
  --dropdown: rgba(27, 27, 29, 1);
  --inverse: rgba(250, 250, 250, 1);
  --inverse-foreground: rgba(12, 12, 12, 1);
  --secondary-hover: rgba(38, 38, 38, 1);
  --row-hover: rgba(255, 255, 255, 0.05);
  --row-active: rgba(255, 255, 255, 0.085);
  --tertiary: rgba(38, 38, 41, 1);
  --tertiary-foreground: rgba(240, 240, 240, 1);
  --success: rgba(19, 56, 38, 1);
  --success-foreground: rgba(126, 232, 168, 1);
  --warning: rgba(64, 45, 14, 1);
  --warning-foreground: rgba(251, 202, 116, 1);
  --info: rgba(20, 43, 76, 1);
  --info-foreground: rgba(152, 196, 255, 1);
  --skeleton-sheen: rgba(255, 255, 255, 0.05);
}

/* ── Base ────────────────────────────────────────────────────────────────── */

/* --card, NOT --background. An app is framed INSIDE the dashboard's content
   island, and the island is --card (white-ish); --background is the canvas
   grey behind the island. Painting the canvas colour inside the island made
   every app sit in a grey box on a white page. */
.folio-app {
  background: var(--card);
  color: var(--card-foreground);
  font-family: var(--folio-font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* Native scrollbars hidden, as in the island's scroll region. Pair with
     .folio-scrollbar for the dashboard's floating thumb. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.folio-app::-webkit-scrollbar { display: none; }
html:has(> body.folio-app) { scrollbar-width: none; }
html:has(> body.folio-app)::-webkit-scrollbar { display: none; }

/* ── Selection ───────────────────────────────────────────────────────────
   Chrome is not text. A double or triple click on a button or a tab used to
   run the selection outward until the whole frame was one blue rectangle,
   which inside an iframe reads as the app glitching rather than as a stray
   selection, because the frame IS the page.

   Deny on CONTROLS, exactly as the dashboard does (see the matching rule in
   its index.css). Making the whole shell unselectable and opting content
   back in class by class was the first attempt and it was wrong twice over:
   the list of things worth copying is endless — an id, an amount, an email,
   a licence key, a row title — so anything not on the list silently became
   uncopyable, and the double-click that started all this was on the
   dashboard's own tabs, outside the frame, where no Folio rule reaches. */
.folio-app button,
.folio-app [role='button'],
.folio-app [role='tab'],
.folio-app [role='menuitem'],
.folio-app [role='menuitemcheckbox'],
.folio-app [role='menuitemradio'],
.folio-app [role='option'],
.folio-app .folio-lv-bar,
.folio-app .folio-sidebar {
  user-select: none;
  -webkit-user-select: none;
}
/* A control that holds real content opts back in. The dashboard's own rows
   are links, which the rule above never touches; Folio's LVRow and BlockRow
   become <button> when they open something, so without this a licence key in
   a clickable row would be the one thing on the page you could not copy. */
.folio-app .folio-lv-cell,
.folio-app .folio-block-row-title,
.folio-app .folio-block-row-sub,
.folio-app .folio-block-row-value,
.folio-app .folio-property-value,
.folio-app .folio-selectable {
  user-select: text;
  -webkit-user-select: text;
}
.folio-app *, .folio-app ::before, .folio-app ::after {
  border-color: var(--border);
}

/* Any scroll region: scrolls, shows no bar. */
.folio-scroll { scrollbar-width: none; -ms-overflow-style: none; }
.folio-scroll::-webkit-scrollbar { display: none; }

/* ── Floating scrollbar — from components/HomeScrollbar.tsx ─────────────
   Apple-style overlay: a fixed right-edge thumb, invisible at rest, fades in
   while scrolling, fades out ~1.2s after. Position/size the thumb from JS
   (height + translateY); toggle data-visible while scrolling. */
.folio-scrollbar {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 9999;
  width: 14px;
  height: 100vh;
  pointer-events: none;
}
.folio-scrollbar-thumb {
  position: absolute;
  top: 0;
  left: 50%;
  width: 8px;
  border-radius: 9999px;
  background: var(--foreground);
  opacity: 0;
  transform: translateX(-50%);
  transition: opacity 300ms;
}
.folio-scrollbar[data-visible='true'] .folio-scrollbar-thumb { opacity: 0.22; }

/* ── Shell — the iOS "stacked sheets" recede ────────────────────────────
   From workspace-layout.tsx + lib/layer-stack.ts. Wrap the app's page in
   .folio-shell and set data-layers to the number of open popups: each layer
   shrinks the shell 3% (capped at three) and rounds it to 18px. Receding takes
   300ms, springing back 220ms, both on the iOS sheet curve. The overlay does
   the dimming; the shell has no backdrop of its own. */
.folio-shell {
  /* 100vh, not 100%: inside the dashboard's frame the viewport IS the island,
     and a percentage needs a sized ancestor that html/body never are. With
     100% the shell ended where its content ended and the rest of the island
     sat empty under it. */
  min-height: 100vh;
  /* A column, so a page can grow to the bottom and an empty state can fill
     what is left of the island rather than stopping at its own minimum. */
  display: flex;
  flex-direction: column;
  background: var(--card);
  transition: scale 220ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 220ms cubic-bezier(0.32, 0.72, 0, 1);
}
.folio-shell[data-layers]:not([data-layers='0']) {
  transition: scale 300ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 300ms cubic-bezier(0.32, 0.72, 0, 1);
  border-radius: 18px;
  overflow: hidden;
}
.folio-shell[data-layers='1'] { scale: 0.97; }
.folio-shell[data-layers='2'] { scale: 0.9409; }
.folio-shell[data-layers='3'], .folio-shell[data-layers='4'], .folio-shell[data-layers='5'] { scale: 0.912673; }

/* ── Page structure ──────────────────────────────────────────────────────
   The dashboard's layout rhythm. A page has no padding of its own and no
   title row (the dashboard's bar is the header); a list runs edge to edge;
   sections carry 24px sides and sit 24px apart with 12px inside. Use these
   instead of inventing margins per screen — consistent breathing room is
   most of what makes a surface feel native. */

.folio-page {
  /* No padding of its own: a list runs edge to edge exactly as the
     dashboard's do (the bar and the rows carry their 12px), and sections
     bring their own 24px sides. Padding here put every app in a gutter the
     dashboard never has. */
  padding: 0 0 12px;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.folio-page > * + * { margin-top: 24px; }
.folio-page > .folio-section:first-child { padding-top: 16px; }
/* A list that is the page: give its wrapper .folio-lv-fill and the empty
   state inside it takes the whole remaining height of the island. */
.folio-lv-fill { display: flex; flex: 1 0 auto; flex-direction: column; }
.folio-lv-fill > .folio-lv-empty { flex: 1 0 auto; }

/* Title row: title left, actions right — mirror of the dashboard header bar. */
.folio-page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.folio-page-title {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.04em;
}
.folio-page-description {
  margin-top: 2px;
  font-size: 13px;
  color: var(--muted-foreground);
}

.folio-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0 24px;
}

/* ── Page kinds ──────────────────────────────────────────────────────────
   A list is one shape; these are the other three, taken from the pages the
   dashboard already runs. Reach for the one that matches what the screen is
   FOR, and the app lands on the dashboard's own proportions without anyone
   measuring anything.

   .folio-detail   one record: the 576px receipt on the left, the 264px
                   properties rail on the right (the transaction page).
   .folio-form     making or changing one record: a 440px scrolling form
                   column and a preview canvas (the payment link page).
   .folio-sidebar  a rail of your own inside the island, collapsing to
                   nothing on the same curve the dashboard's rail uses. */

/* ═══ Detail — from routes/transaction-detail.tsx, measured, not approximated.
   The dashboard's solo page is a 1024px column centred in the island with a
   576px receipt on the left and a 264px properties rail on the right. Every
   number below is that page's computed value; the island's own p-6 gutter is
   folded in because the app frame has none of its own. ═══ */

/* mx-auto w-full max-w-5xl pb-12 lg:grid lg:grid-cols-[minmax(0,1fr)_264px]
   lg:gap-16 lg:pt-6 — inside the island's p-4 md:p-6. */
.folio-detail { margin: 0 auto; width: 100%; max-width: 1024px; padding: 16px 16px 64px; }
@media (min-width: 768px) { .folio-detail { padding: 24px 24px 72px; } }
@media (min-width: 1024px) {
  .folio-detail { display: grid; grid-template-columns: minmax(0, 1fr) 264px; gap: 64px; padding-top: 48px; }
}
/* <section className="w-full max-w-xl space-y-7"> */
.folio-detail-main { display: flex; flex-direction: column; gap: 28px; width: 100%; min-width: 0; max-width: 576px; }
/* <aside className="mt-10 w-full space-y-6 lg:sticky lg:top-6 lg:mt-0 lg:self-start"> */
.folio-detail-aside { display: flex; flex-direction: column; gap: 24px; width: 100%; min-width: 0; margin-top: 40px; }
@media (min-width: 1024px) { .folio-detail-aside { margin-top: 0; position: sticky; top: 24px; align-self: start; } }

/* Hero: the order label and status on one line, then the amount at 44px with
   the date on its right. The label is text-xl muted; the amount is
   text-[2.75rem] leading-none tabular-nums. */
.folio-detail-hero { display: flex; flex-direction: column; gap: 16px; }
.folio-detail-hero-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.folio-detail-hero-label { font-size: 20px; font-weight: 600; letter-spacing: -0.025em; color: var(--muted-foreground); }
.folio-detail-hero-row { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px; }
.folio-detail-hero-title { font-size: 44px; font-weight: 600; line-height: 1; letter-spacing: -0.025em; font-variant-numeric: tabular-nums; }
.folio-detail-hero-meta { font-size: 14px; color: var(--muted-foreground); }

/* A block: SectionHeader (text-xs uppercase muted/70) over a rounded-xl
   bordered panel with the dashboard's BLOCK_SHADOW. */
.folio-block { display: flex; flex-direction: column; gap: 10px; }
.folio-block-header { display: flex; align-items: center; justify-content: space-between; }
.folio-block-title { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: color-mix(in srgb, var(--muted-foreground) 70%, transparent); }
.folio-block-body {
  overflow: hidden;
  border-radius: 12px;
  border: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), inset 0 -1px 0 rgba(0, 0, 0, 0.08), 0 1px 2px rgba(26, 26, 26, 0.06);
}
/* A panel with nothing drawn around it: the rows carry hairlines and that is
   all. The dashboard uses this for Activity — a border earns its place when
   a block holds sums or a form, not when it holds a short list. Prefer it
   over the bordered body whenever the content is just rows. */
.folio-block-body-flush { border: 0; border-radius: 0; box-shadow: none; overflow: visible; }
.folio-block-body-flush > .folio-block-row { padding-left: 8px; padding-right: 8px; }
.folio-block-body-flush > .folio-block-row + .folio-block-row { border-top-color: var(--border-subtle); }

/* Rows inside the panel: flex items-center gap-3 p-3, divide-y. */
.folio-block-row { display: flex; align-items: center; gap: 12px; padding: 12px; min-width: 0; }
/* A row that goes somewhere. Spelled out rather than left to a preflight,
   because Folio is linked on its own by apps that are not using Tailwind. */
button.folio-block-row, a.folio-block-row { width: 100%; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.folio-block-row + .folio-block-row { border-top: 1px solid var(--border); }
.folio-block-row-tile {
  display: flex; width: 44px; height: 44px; flex-shrink: 0; align-items: center; justify-content: center;
  border-radius: 6px; border: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  background: var(--muted); object-fit: cover; color: color-mix(in srgb, var(--muted-foreground) 50%, transparent);
}
.folio-block-row-tile > svg { width: 16px; height: 16px; }
.folio-block-row-main { min-width: 0; flex: 1; }
.folio-block-row-title { font-size: 14px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folio-block-row-sub { font-size: 12px; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folio-block-row-sub-dim { font-size: 12px; color: color-mix(in srgb, var(--muted-foreground) 70%, transparent); }
.folio-block-row-value { flex-shrink: 0; font-size: 14px; font-weight: 500; font-variant-numeric: tabular-nums; }
/* The totals band: border-t bg-muted/30 p-4 space-y-1.5. */
.folio-block-foot { display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--border); background: color-mix(in srgb, var(--muted) 30%, transparent); padding: 16px; }
.folio-block-line { display: flex; align-items: center; justify-content: space-between; font-size: 14px; }
.folio-block-line > :first-child { color: var(--muted-foreground); }
.folio-block-line > :last-child { font-variant-numeric: tabular-nums; }
.folio-block-line-total { border-top: 1px solid var(--border); padding-top: 8px; font-weight: 600; }
.folio-block-line-total > :first-child { color: var(--foreground); }
/* Plain body text inside a panel (the notes box): p-3, text-sm. */
.folio-block-text { padding: 12px; font-size: 14px; }

/* Rail actions: the RAIL_ACTION_CLASS chips — h-8 rounded-lg px-2.5
   text-[13px] medium, filled with --secondary, hover darkens. Destructive
   ones only turn red on hover. */
.folio-rail-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.folio-rail-action {
  display: inline-flex; height: 32px; align-items: center; gap: 8px; padding: 0 10px;
  border: 0; border-radius: 8px; background: var(--secondary); color: var(--muted-foreground);
  font-family: inherit; font-size: 13px; font-weight: 500; letter-spacing: 0; white-space: nowrap; cursor: pointer;
  transition: background-color 150ms, color 150ms, transform 150ms;
}
.folio-rail-action > svg { width: 15px; height: 15px; flex-shrink: 0; }
.folio-rail-action:hover { background: var(--secondary-hover); color: var(--foreground); }
.folio-rail-action:active { transform: scale(0.97); }
.folio-rail-action:disabled { opacity: 0.5; pointer-events: none; }
.folio-rail-action-destructive:hover { background: color-mix(in srgb, var(--destructive) 12%, transparent); color: var(--destructive); }

/* Properties: "PROPERTIES" at text-[11px] medium uppercase muted/60, then
   icon + value rows (h-4 glyph at muted/50, text-sm muted). The lead row —
   the customer — is text-sm medium foreground with a 20px mark. */
.folio-properties { display: flex; flex-direction: column; gap: 8px; }
.folio-properties-title { padding-bottom: 4px; font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: color-mix(in srgb, var(--muted-foreground) 60%, transparent); }
.folio-property { display: flex; align-items: center; gap: 8px; padding: 2px 0; min-width: 0; font-size: 14px; color: var(--muted-foreground); }
.folio-property-icon { display: flex; margin-left: 2px; width: 16px; height: 16px; flex-shrink: 0; align-items: center; justify-content: center; color: color-mix(in srgb, var(--muted-foreground) 50%, transparent); }
.folio-property-icon > svg { width: 16px; height: 16px; }
.folio-property-icon-lg { margin-left: 0; width: 20px; height: 20px; }
.folio-property-icon-lg > svg { width: 20px; height: 20px; }
.folio-property-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: inherit; text-decoration: none; transition: color 150ms; }
a.folio-property-value:hover { color: var(--foreground); text-decoration: underline; }
.folio-property-lead { padding: 4px 0; font-weight: 500; color: var(--foreground); }
/* A property that goes somewhere (the customer, the transaction): the
   dashboard's hover pill — -ml-1.5 rounded-lg py-1 pl-1.5 pr-2, a 10%
   foreground wash on hover — so a row that opens reads as one. */
.folio-property-link {
  margin-left: -6px; width: fit-content; max-width: 100%; padding: 4px 8px 4px 6px;
  border: 0; border-radius: 8px; background: transparent; font: inherit; color: inherit; text-align: left; cursor: pointer;
  transition: background-color 150ms;
}
.folio-property-link:hover { background: color-mix(in srgb, var(--foreground) 10%, transparent); }
.folio-property-link.folio-property-lead { padding: 4px 8px 4px 6px; }

/* The tiny copy glyph after ids: 16px hit area, 12px icon, muted/50. */
.folio-copy {
  display: inline-flex; margin-left: 4px; width: 16px; height: 16px; flex-shrink: 0; align-items: center; justify-content: center;
  border: 0; border-radius: 4px; padding: 0; background: transparent; cursor: pointer;
  color: color-mix(in srgb, var(--muted-foreground) 50%, transparent); transition: color 150ms;
}
.folio-copy:hover { color: var(--muted-foreground); }
.folio-copy > svg { width: 12px; height: 12px; }
.folio-copy[data-copied='true'] { color: #22c55e; }

/* Disclosures: -mx-2.5 bleed under a subtle hairline, h-9 trigger rows that
   hover like the activity list, chevron rotating 180 over 200ms, content
   sliding open on the same curve as collapsible-down. */
.folio-disclosures { display: flex; flex-direction: column; gap: 2px; margin: 0 -10px; border-top: 1px solid var(--border-subtle); padding-top: 12px; }
.folio-disclosure-trigger {
  display: flex; height: 36px; width: 100%; align-items: center; justify-content: space-between;
  border: 0; border-radius: 8px; padding: 0 10px; background: transparent; font-family: inherit; text-align: left; cursor: pointer;
  transition: background-color 150ms;
}
.folio-disclosure-trigger:hover { background: color-mix(in srgb, var(--accent) 40%, transparent); }
.folio-disclosure-title { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: color-mix(in srgb, var(--muted-foreground) 70%, transparent); }
.folio-disclosure-chevron { width: 16px; height: 16px; flex-shrink: 0; color: color-mix(in srgb, var(--muted-foreground) 40%, transparent); transition: transform 200ms; }
.folio-disclosure[data-open='true'] .folio-disclosure-chevron { transform: rotate(180deg); }
.folio-disclosure-content { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows 200ms ease-out, opacity 200ms ease-out; }
.folio-disclosure[data-open='true'] .folio-disclosure-content { grid-template-rows: 1fr; opacity: 1; }
.folio-disclosure-content > div { overflow: hidden; }
.folio-disclosure-inner { display: flex; flex-direction: column; gap: 12px; padding: 6px 10px 12px; }

/* Field: the label/value pair inside a disclosure — text-[11px] uppercase
   muted/50 over text-xs muted, with the copy glyph beside it. */
.folio-fact { min-width: 0; }
.folio-fact-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: color-mix(in srgb, var(--muted-foreground) 50%, transparent); }
.folio-fact-value { display: flex; margin-top: 2px; align-items: center; gap: 4px; font-size: 12px; color: var(--muted-foreground); }
.folio-fact-value > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ═══ Create & edit — from routes/payment-link-form.tsx and products-new.tsx.
   A scrolling 440px form column with a hairline on its right, and the rest
   of the island given to a preview on a dotted canvas. Sections are a 13px
   medium label over their control; grouped controls sit in a 14px-radius
   bordered card; toggles are 40px rows with a 24px icon tile. ═══ */

/* <section className="relative flex h-full min-h-0">. 100vh, not 100%: the
   shell only has a min-height, so a percentage here resolves to auto and the
   column ends where its fields end. Inside the dashboard the viewport IS the
   island, so 100vh is exactly "the whole canvas". */
.folio-form-layout { position: relative; display: flex; height: 100vh; height: 100dvh; min-height: 0; min-width: 0; }
/* relative flex h-full w-full min-w-0 flex-col lg:max-w-[440px] lg:border-r lg:border-border-subtle */
.folio-form { position: relative; display: flex; height: 100%; width: 100%; min-width: 0; flex-direction: column; }
@media (min-width: 1024px) { .folio-form { max-width: 440px; border-right: 1px solid var(--border-subtle); } }
/* min-h-0 flex-1 space-y-7 overflow-y-auto px-5 py-5, scrollbar hidden */
.folio-form-body { display: flex; min-height: 0; flex: 1; flex-direction: column; gap: 28px; overflow-y: auto; padding: 20px; scrollbar-width: none; -ms-overflow-style: none; }
.folio-form-body::-webkit-scrollbar { display: none; }
/* <div className="space-y-2"><Label className="text-[13px] font-medium"> */
.folio-form-section { display: flex; flex-direction: column; gap: 8px; }
.folio-form-section-title { font-size: 13px; font-weight: 500; line-height: 1.3; }
/* The form's fields drop the inset focus ring for a step to --muted, the way
   FIELD_CLASS does: focus-visible:bg-muted focus-visible:ring-0. */
.folio-form .folio-input:focus-visible, .folio-form .folio-textarea:focus-visible, .folio-form .folio-select-trigger:focus-visible { box-shadow: none; background: var(--muted); }
.folio-form .folio-textarea { min-height: 84px; border-radius: 12px; resize: none; font-size: 14px; }
.folio-form-hint { min-height: 16px; font-size: 11px; color: var(--muted-foreground); }
.folio-form-hint-error { color: var(--destructive); }
.folio-form-count { text-align: right; font-size: 11px; font-variant-numeric: tabular-nums; color: color-mix(in srgb, var(--muted-foreground) 60%, transparent); }
/* A card of grouped controls: rounded-[14px] border. Padded when it holds
   fields (p-3 space-y-2); flush when it holds option rows. */
.folio-form-card { display: flex; flex-direction: column; border-radius: 14px; border: 1px solid var(--border); }
.folio-form-card-padded { padding: 12px; gap: 8px; }
.folio-form-stack { display: flex; flex-direction: column; gap: 12px; }
/* The empty card: flex-col items-start gap-2 p-4. */
.folio-form-empty { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; border-radius: 14px; border: 1px solid var(--border); padding: 16px; }
.folio-form-empty-title { font-size: 13px; font-weight: 500; }
.folio-form-empty-sub { font-size: 12px; color: var(--muted-foreground); }
/* An option row (AdvancedRow): m-1 h-10 gap-2.5 px-2.5, the whole row
   toggles, hover on --row-hover, press to 0.985. Corners: 10px on the card's
   first/last, 6px between. */
.folio-option { display: flex; flex-direction: column; }
.folio-option-row {
  display: flex; margin: 4px; height: 40px; align-items: center; gap: 10px; padding: 0 10px;
  border: 0; border-radius: 6px; background: transparent; color: inherit; font-family: inherit; text-align: left; cursor: pointer;
  transition: background-color 100ms, transform 100ms;
}
.folio-option-row:hover { background: var(--row-hover); }
.folio-option-row:active { transform: scale(0.985); }
.folio-option:first-child > .folio-option-row { border-top-left-radius: 10px; border-top-right-radius: 10px; }
.folio-option:last-child > .folio-option-row { border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
/* A row that sits inside a padded card rather than a flush one: full width,
   12px radius, no margin (the "Let customers change quantity" row). */
.folio-form-card-padded > .folio-option > .folio-option-row { margin: 0; width: 100%; padding: 0 8px; border-radius: 12px; }
.folio-form-card-padded > .folio-option > .folio-option-children { padding: 4px 0 0; }
.folio-option-icon { display: flex; width: 24px; height: 24px; flex-shrink: 0; align-items: center; justify-content: center; border-radius: 6px; background: color-mix(in srgb, var(--foreground) 5%, transparent); color: var(--muted-foreground); }
.folio-option-icon > svg { width: 14px; height: 14px; }
.folio-option-label { flex: 1; min-width: 0; font-size: 13px; font-weight: 500; }
.folio-option-children { display: flex; flex-direction: column; gap: 12px; padding: 4px 14px 16px; }
/* The "+ Add product" button: h-8 w-full rounded-xl text-[12px] medium. */
.folio-form-add { height: 32px; width: 100%; border-radius: 12px; font-size: 12px; font-weight: 500; letter-spacing: 0; gap: 6px; }
.folio-form-add > svg { width: 14px; height: 14px; }
/* Segmented control (the pricing-type picker): grid on --secondary with
   2px padding, 32px segments at 7px radius, the active one lifted to --card. */
.folio-segmented { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); border-radius: 8px; background: var(--secondary); padding: 2px; }
.folio-segment { height: 32px; border: 0; border-radius: 7px; background: transparent; font-family: inherit; font-size: 13px; font-weight: 500; color: var(--muted-foreground); cursor: pointer; transition: color 150ms, background-color 150ms; }
.folio-segment:hover { color: var(--foreground); }
.folio-segment[aria-pressed='true'] { background: var(--card); color: var(--foreground); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
/* The preview canvas: the rest of the island, dotted at 16px, centred. Hidden
   under 1024px, where the form takes everything. */
.folio-form-preview {
  position: relative; display: none; min-height: 0; min-width: 0; flex: 1; align-items: center; justify-content: center; overflow: hidden;
  background-color: color-mix(in srgb, var(--background) 40%, transparent);
  background-image: radial-gradient(color-mix(in srgb, var(--foreground) 7%, transparent) 1px, transparent 1px);
  background-size: 16px 16px;
}
@media (min-width: 1024px) { .folio-form-preview { display: flex; } }
/* A pane of real content beside the form (a key pool, a file list) rather
   than a preview: plain, scrolling, no dots. Under 1024px it stacks beneath
   the form instead of vanishing, because unlike a preview it is the data. */
.folio-form-pane { min-height: 0; min-width: 0; flex: 1; overflow-y: auto; }
@media (max-width: 1023.98px) {
  .folio-form-layout:has(.folio-form-pane) { flex-direction: column; height: auto; }
  .folio-form-layout:has(.folio-form-pane) .folio-form { height: auto; }
  .folio-form-layout:has(.folio-form-pane) .folio-form-body { overflow: visible; }
}
/* Loading: the column's own skeleton, laid over the body. */
.folio-form-loading { position: absolute; inset: 0; z-index: 20; display: flex; flex-direction: column; gap: 28px; background: var(--card); padding: 20px; }

/* A rail of your own. Collapses to nothing rather than to icons: a 56px
   strip of glyphs is a quiz, and the dashboard already decided this. */
.folio-sidebar-layout { position: relative; display: flex; min-height: 100%; min-width: 0; }
.folio-sidebar {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex-shrink: 0;
  width: 220px;
  padding: 12px 8px;
  overflow: hidden;
  border-right: 1px solid var(--border);
  transition: width 200ms ease-out, padding 200ms ease-out, border-color 200ms ease-out;
}
.folio-sidebar[data-collapsed='true'] { width: 0; padding-left: 0; padding-right: 0; border-right-color: transparent; }
.folio-sidebar-content { flex: 1; min-width: 0; }
.folio-sidebar-group { display: flex; flex-direction: column; gap: 2px; }
.folio-sidebar-group + .folio-sidebar-group { margin-top: 16px; }
.folio-sidebar-group-title { padding: 0 8px 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-foreground); white-space: nowrap; }
.folio-sidebar-item {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 8px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted-foreground);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 120ms, color 120ms;
}
.folio-sidebar-item > svg { width: 16px; height: 16px; flex-shrink: 0; }
.folio-sidebar-item:hover { background: var(--row-hover); color: var(--foreground); }
.folio-sidebar-item[aria-current='page'] { background: var(--secondary); color: var(--foreground); }
/* A list inside a section sits flush with the section's text: the bar's own
   12px is the row inset the dashboard uses. */
.folio-section > .folio-lv-bar, .folio-section > .folio-lv-list { margin: 0 -12px; }
.folio-section-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* Label-over-control field; pair inside .folio-form-row for two-up grids. */
/* Label, control, hint: 8px apart, as the dashboard's forms (space-y-2)
   stack them. The label's own 4px bottom pad brings label-to-control to 12. */
.folio-field { display: flex; flex-direction: column; gap: 8px; }
.folio-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 560px) {
  .folio-form-row { grid-template-columns: 1fr; }
}

/* A hoverable list row — the pattern behind every clickable list in the
   dashboard. --row-hover/--row-active are the dashboard's own table states. */
.folio-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 6px 12px;
  border-radius: 8px;
  transition: background-color 120ms;
}
.folio-list-row:hover { background: var(--row-hover); }
.folio-list-row:active { background: var(--row-active); }

.folio-empty {
  padding: 48px 16px;
  color: var(--muted-foreground);
  font-size: 13px;
  text-align: center;
}

.folio-muted { color: var(--muted-foreground); }

/* ── Button — from components/ui/button.tsx ─────────────────────────────
   Pills, semibold, tight tracking, press-scale. Primary is Paysio blue;
   secondary is the filled chip (NO bordered/outline button exists in the
   dashboard any more — reach for secondary). */

.folio-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  white-space: nowrap;
  height: 40px;
  padding: 0 18px;
  border: 0;
  border-radius: 9999px;
  background: var(--primary);
  color: var(--primary-foreground);
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.04em;
  cursor: pointer;
  outline: none;
  transition: background-color 150ms, color 150ms, transform 150ms;
}
.folio-btn:hover { background: color-mix(in srgb, var(--primary) 90%, transparent); }
.folio-btn:active { transform: scale(0.97); }
.folio-btn:disabled { pointer-events: none; opacity: 0.5; }
.folio-btn svg { width: 16px; height: 16px; flex-shrink: 0; pointer-events: none; }

.folio-btn-secondary {
  background: var(--secondary);
  color: var(--secondary-foreground);
}
.folio-btn-secondary:hover { background: var(--secondary-hover); }

.folio-btn-destructive {
  background: var(--destructive);
  color: var(--destructive-foreground);
}
.folio-btn-destructive:hover { background: color-mix(in srgb, var(--destructive) 90%, transparent); }

.folio-btn-ghost { background: transparent; color: var(--foreground); }
.folio-btn-ghost:hover { background: var(--accent); color: var(--accent-foreground); }

.folio-btn-link {
  background: transparent;
  color: var(--primary);
  text-underline-offset: 4px;
}
.folio-btn-link:hover { background: transparent; text-decoration: underline; }

.folio-btn-sm { height: 32px; padding: 0 14px; font-size: 14px; }
.folio-btn-lg { height: 44px; padding: 0 24px; }
.folio-btn-icon { width: 40px; height: 40px; padding: 0; }

/* ── Inputs — from components/ui/input.tsx / select.tsx / textarea.tsx ──
   40px, 12px radius, 18px side padding, hairline --input border, a whisper of
   bottom shadow, and an INSET focus ring. The select trigger is deliberately
   identical to the input: they are peers in a form and sit adjacent. */

.folio-input,
.folio-select-trigger {
  display: block;
  width: 100%;
  height: 40px;
  appearance: none;
  padding: 0 18px;
  /* A filled field, not an outlined one: the secondary chip at rest, no
     border and no shadow, and the inset ring only when focused. */
  border: 1px solid transparent;
  border-radius: 12px;
  background: var(--secondary);
  color: var(--foreground);
  font-family: inherit;
  font-size: 14px;
  transition: background-color 150ms, box-shadow 150ms;
}
.folio-input:hover:not(:disabled):not(:focus-visible),
.folio-select-trigger:hover:not(:disabled):not(:focus-visible) { background: var(--secondary-hover, var(--secondary)); }
.folio-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  white-space: nowrap;
  cursor: pointer;
  text-align: left;
}
.folio-select-trigger > svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--muted-foreground); }
.folio-input::placeholder { color: color-mix(in srgb, var(--muted-foreground) 90%, transparent); }
.folio-input:focus-visible,
.folio-select-trigger:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--ring);
}
.folio-input:disabled,
.folio-select-trigger:disabled { cursor: not-allowed; opacity: 0.5; }

.folio-textarea {
  display: block;
  width: 100%;
  min-height: 80px;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--secondary);
  color: var(--foreground);
  font-family: inherit;
  font-size: 14px;
  line-height: 1.5;
  box-shadow: 0 1px 0 rgba(26, 26, 26, 0.04);
  resize: vertical;
}
.folio-textarea::placeholder { color: color-mix(in srgb, var(--muted-foreground) 90%, transparent); }
.folio-textarea:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--ring), 0 1px 0 rgba(26, 26, 26, 0.04);
}

.folio-label {
  display: inline-block;
  padding-bottom: 4px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
}

/* ── Checkbox & switch — from checkbox.tsx / switch.tsx ─────────────────
   Native inputs restyled, so they work without JS. 16px 6px-radius box that
   fills primary when checked; 36x20 pill track whose thumb slides 16px. */

.folio-checkbox {
  appearance: none;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin: 0;
  border: 1px solid var(--input);
  border-radius: 6px;
  background: var(--background);
  box-shadow: 0 1px 0 rgba(26, 26, 26, 0.06);
  cursor: pointer;
  transition: background-color 150ms, border-color 150ms;
}
.folio-checkbox:checked {
  border-color: var(--primary);
  background-color: var(--primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: 12px;
  background-position: center;
  background-repeat: no-repeat;
}
.folio-checkbox:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ring); }
.folio-checkbox:disabled { cursor: not-allowed; opacity: 0.5; }

.folio-switch {
  appearance: none;
  position: relative;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
  margin: 0;
  border: 1px solid var(--input);
  border-radius: 9999px;
  background: var(--secondary);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
  cursor: pointer;
  transition: background-color 150ms, border-color 150ms;
}
.folio-switch::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 1px;
  width: 16px;
  height: 16px;
  border-radius: 9999px;
  background: var(--background);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.25);
  transform: translateY(-50%);
  transition: transform 150ms;
}
.folio-switch:checked { border-color: var(--primary); background: var(--primary); }
.folio-switch:checked::after { transform: translateY(-50%) translateX(16px); }
.folio-switch:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ring); }
.folio-switch:disabled { cursor: not-allowed; opacity: 0.5; }

/* ── Badge — from components/ui/badge.tsx ───────────────────────────────
   A label, not a click target. Default is the inverse chip (near-black in
   light, near-white in dark) — emphasis without claiming to be an action. */

.folio-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border: 1px solid transparent;
  border-radius: 9999px;
  background: var(--inverse);
  color: var(--inverse-foreground);
  font-size: 11px;
  font-weight: 500;
  line-height: 20px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.folio-badge-secondary { background: var(--secondary); color: var(--secondary-foreground); box-shadow: none; }
.folio-badge-outline { border-color: var(--input); background: var(--background); color: var(--foreground); box-shadow: none; }
.folio-badge-destructive { background: var(--destructive); color: var(--destructive-foreground); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); }
.folio-badge-success { background: var(--success); color: var(--success-foreground); box-shadow: none; }
.folio-badge-warning { background: var(--warning); color: var(--warning-foreground); box-shadow: none; }
.folio-badge-info { background: var(--info); color: var(--info-foreground); box-shadow: none; }

/* ── Card — from components/ui/card.tsx ─────────────────────────────────── */

.folio-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  color: var(--card-foreground);
  box-shadow: 0 1px 0 rgba(26, 26, 26, 0.06), 0 8px 16px rgba(26, 26, 26, 0.08);
}
.folio-card-header { display: flex; flex-direction: column; gap: 6px; padding: 20px; }
.folio-card-title { font-weight: 600; letter-spacing: -0.025em; line-height: 1; }
.folio-card-description { font-size: 14px; color: var(--muted-foreground); }
.folio-card-content { padding: 20px; padding-top: 0; }
.folio-card-footer { display: flex; align-items: center; padding: 20px; padding-top: 0; }

/* ── Menu — from components/ui/dropdown-menu.tsx (Linear proportions) ───
   The floating surface: 12px radius, hairline border, the --dropdown fill (a
   step off --popover), ambient + contact shadow. Rows: 32px min, 13px medium,
   8px radius (12 minus the 4px padding, so corners stay concentric), with a
   2px breath between rows so adjacent hovers stay separate targets.
   Position it yourself (or with your popover library); this is the look. */

.folio-menu {
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 11rem;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--dropdown);
  color: var(--popover-foreground);
  box-shadow: 0 10px 28px -8px rgba(0, 0, 0, 0.16), 0 2px 6px -2px rgba(0, 0, 0, 0.08);
}
.folio-menu-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 6px 8px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: default;
  user-select: none;
  outline: none;
  transition: background-color 120ms;
}
.folio-menu-item:hover, .folio-menu-item:focus-visible {
  background: var(--accent);
  color: var(--accent-foreground);
}
.folio-menu-item[disabled], .folio-menu-item[aria-disabled='true'] { pointer-events: none; opacity: 0.5; }
/* Icons dim relative to the row's own text colour — a destructive item's glyph
   goes soft red instead of staying grey. */
.folio-menu-item > svg { width: 16px; height: 16px; flex-shrink: 0; opacity: 0.6; }
.folio-menu-item-destructive { color: var(--destructive); }
.folio-menu-label { padding: 6px 8px; font-size: 12px; font-weight: 500; color: var(--muted-foreground); }
.folio-menu-separator { height: 1px; margin: 2px -4px; background: var(--border); }
.folio-menu-shortcut { margin-left: auto; padding-left: 16px; font-size: 12px; color: var(--muted-foreground); }

/* ── Popup — from components/ui/popup.tsx ───────────────────────────────
   The dashboard's dialog: centered, 440px, 24px radius, layered frosted
   shadow, scale-in. Footer stacks full-width actions (cancel first, confirm
   below) and buttons inside a popup square to 12px — both exactly as the
   dashboard does it. */

.folio-popup-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(1px);
  animation: popup-fade-in 200ms ease-out;
}
.folio-popup-overlay[data-state='closed'] { animation: popup-fade-out 160ms ease-in forwards; }

/* The flared silhouette — from the [data-slot='popup-content'] block in the
   dashboard's index.css. The box is widened by --popup-flare on each side and
   the clip takes it back at the top, so the top edge is the original width
   and the bottom is wider: a wedge. Padding grows by the same flare so the
   content column does not move. Each corner is 7 vertices along a quarter
   circle (15-degree steps); border-radius is off because the polygon IS the
   silhouette. clip-path clips box-shadow away, so the depth is re-expressed
   as drop-shadow filters, which follow the clipped alpha shape. */
.folio-popup {
  --popup-flare: 6px;
  --popup-rt: 28px;
  --popup-rb: 24px;
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 50;
  display: grid;
  gap: 20px;
  width: calc(100% - 2rem + 2 * var(--popup-flare));
  max-width: calc(440px + 2 * var(--popup-flare));
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
  scrollbar-width: none;
  padding: 24px calc(24px + var(--popup-flare));
  border-radius: 0;
  background: var(--popover);
  color: var(--foreground);
  transform: translate(-50%, -50%);
  outline: none;
  animation: popup-in 200ms cubic-bezier(0.32, 0.72, 0, 1);
  filter:
    drop-shadow(0 0 0.5px var(--border))
    drop-shadow(0 12px 28px rgba(0, 0, 0, 0.22));
  clip-path: polygon(
    var(--popup-flare) var(--popup-rt),
    calc(var(--popup-flare) + var(--popup-rt) * 0.034) calc(var(--popup-rt) * 0.741),
    calc(var(--popup-flare) + var(--popup-rt) * 0.134) calc(var(--popup-rt) * 0.5),
    calc(var(--popup-flare) + var(--popup-rt) * 0.293) calc(var(--popup-rt) * 0.293),
    calc(var(--popup-flare) + var(--popup-rt) * 0.5) calc(var(--popup-rt) * 0.134),
    calc(var(--popup-flare) + var(--popup-rt) * 0.741) calc(var(--popup-rt) * 0.034),
    calc(var(--popup-flare) + var(--popup-rt)) 0,
    calc(100% - var(--popup-flare) - var(--popup-rt)) 0,
    calc(100% - var(--popup-flare) - var(--popup-rt) * 0.741) calc(var(--popup-rt) * 0.034),
    calc(100% - var(--popup-flare) - var(--popup-rt) * 0.5) calc(var(--popup-rt) * 0.134),
    calc(100% - var(--popup-flare) - var(--popup-rt) * 0.293) calc(var(--popup-rt) * 0.293),
    calc(100% - var(--popup-flare) - var(--popup-rt) * 0.134) calc(var(--popup-rt) * 0.5),
    calc(100% - var(--popup-flare) - var(--popup-rt) * 0.034) calc(var(--popup-rt) * 0.741),
    calc(100% - var(--popup-flare)) var(--popup-rt),
    100% calc(100% - var(--popup-rb)),
    calc(100% - var(--popup-rb) * 0.034) calc(100% - var(--popup-rb) * 0.741),
    calc(100% - var(--popup-rb) * 0.134) calc(100% - var(--popup-rb) * 0.5),
    calc(100% - var(--popup-rb) * 0.293) calc(100% - var(--popup-rb) * 0.293),
    calc(100% - var(--popup-rb) * 0.5) calc(100% - var(--popup-rb) * 0.134),
    calc(100% - var(--popup-rb) * 0.741) calc(100% - var(--popup-rb) * 0.034),
    calc(100% - var(--popup-rb)) 100%,
    var(--popup-rb) 100%,
    calc(var(--popup-rb) * 0.741) calc(100% - var(--popup-rb) * 0.034),
    calc(var(--popup-rb) * 0.5) calc(100% - var(--popup-rb) * 0.134),
    calc(var(--popup-rb) * 0.293) calc(100% - var(--popup-rb) * 0.293),
    calc(var(--popup-rb) * 0.134) calc(100% - var(--popup-rb) * 0.5),
    calc(var(--popup-rb) * 0.034) calc(100% - var(--popup-rb) * 0.741),
    0 calc(100% - var(--popup-rb))
  );
}
.folio-popup::-webkit-scrollbar { display: none; }
.folio-popup[data-state='closed'] { animation: popup-out 160ms ease-in forwards; }
/* Stacked: a popup with another on top recedes like the shell does. Set
   data-layers-above from your layer stack. scale is the independent
   property, so it composes with the centering transform. */
.folio-popup { transition: scale 220ms cubic-bezier(0.32, 0.72, 0, 1); }
.folio-popup[data-layers-above='1'] { scale: 0.97; transition-duration: 300ms; }
.folio-popup[data-layers-above='2'] { scale: 0.9409; transition-duration: 300ms; }
.folio-popup > * { min-width: 0; }

/* ── Popup frames — the body of a dashboard-rendered popup ─────────────
   paysio.popup.open({ path }) makes the DASHBOARD render its own popup and
   load that page of the app inside it: flare, scrim, recede, stacking and
   viewport centring are all the dashboard's, so this is not an imitation of a
   native popup. The page only paints the content. The bridge marks the root
   with data-paysio-frame="popup"; the dashboard supplies the padding and the
   close button, so the page must not add its own. */
html[data-paysio-frame='popup'] { scrollbar-width: none; }
html[data-paysio-frame='popup']::-webkit-scrollbar { display: none; }
[data-paysio-frame='popup'] body { margin: 0; background: var(--popover); }
[data-paysio-frame='popup'] .folio-app { background: var(--popover); }
[data-paysio-frame='popup'] .folio-shell { min-height: 0; }
/* 3px of breathing room on every side. A popup body is its own document, so
   the frame's edge is a hard clip: a control sitting flush against it loses
   the outer half of anything it paints outside its box — a focus ring, a
   hover shadow. The dashboard's own padding sits outside this iframe and
   cannot help. */
.folio-popup-frame { display: grid; gap: 20px; min-width: 0; padding: 3px; }
.folio-popup-frame > * { min-width: 0; }
/* Room for the dashboard's close button, which sits over the top-right. */
.folio-popup-frame .folio-popup-header { padding-right: 32px; }
/* Buttons square inside a popup, exactly as they do natively. */
[data-paysio-frame='popup'] .folio-btn:not(.folio-btn-icon),
[data-paysio-frame='popup'] [data-slot='button']:not([data-size='icon']) { border-radius: 12px; }

/* Mobile: the same popup as a bottom sheet, keyboard-aware in the dashboard
   (lift it with the bottom offset from the VisualViewport). Grab handle included. */
.folio-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
  max-width: 640px;
  max-height: calc(100dvh - 2.5rem);
  margin: 0 auto;
  overflow-y: auto;
  padding: 16px;
  padding-bottom: max(1rem, env(safe-area-inset-bottom));
  border-radius: 24px 24px 0 0;
  background: var(--popover);
  color: var(--foreground);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04), 0 -8px 40px -8px rgba(0, 0, 0, 0.25);
  outline: none;
  animation: sheet-in 300ms cubic-bezier(0.32, 0.72, 0, 1);
}
.folio-sheet[data-state='closed'] { animation: sheet-out 200ms ease-in forwards; }
.folio-sheet-handle {
  width: 40px;
  height: 4px;
  flex-shrink: 0;
  margin: 0 auto;
  border-radius: 9999px;
  background: color-mix(in srgb, var(--muted-foreground) 30%, transparent);
}
@keyframes sheet-in { from { transform: translateY(100%); } }
@keyframes sheet-out { to { transform: translateY(100%); } }
.folio-popup-header { display: flex; flex-direction: column; gap: 2px; }
.folio-popup-title { font-size: 24px; font-weight: 600; letter-spacing: -0.04em; }
.folio-popup-description { font-size: 14px; font-weight: 600; letter-spacing: -0.04em; color: var(--muted-foreground); }
.folio-popup-footer { display: flex; flex-direction: column; gap: 8px; }
.folio-popup-footer > * { width: 100%; }
/* Squared popup buttons — mirror of the [data-slot='popup-content'] rule in
   the dashboard's index.css. Icon buttons keep their circle. */
.folio-popup .folio-btn:not(.folio-btn-icon),
.folio-popup-footer > * { border-radius: 12px; }
.folio-popup-close {
  position: absolute;
  right: 16px;
  top: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  outline: none;
  transition: background-color 150ms, color 150ms;
}
.folio-popup-close:hover { background: var(--accent); color: var(--foreground); }
.folio-popup-close svg { width: 20px; height: 20px; }

@keyframes popup-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.96); }
}
@keyframes popup-out {
  to { opacity: 0; transform: translate(-50%, -50%) scale(0.96); }
}
@keyframes popup-fade-in {
  from { opacity: 0; }
}
@keyframes popup-fade-out {
  to { opacity: 0; }
}

/* ── List view — from components/list-view.tsx ──────────────────────────
   THE dashboard table (Transactions is the reference): not a <table> at all.
   A 40px bar of preset pills, active-filter chips and the funnel/display
   menus, then transparent full-width rows — 44px, 13px, 8px radius, hover
   band — with no column header. Rows are CSS grid; the page owns the
   column template (set grid-template-columns on .folio-lv-row). */

.folio-lv-bar {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 12px;
  overflow-x: auto;
  scrollbar-width: none;
}
.folio-lv-bar::-webkit-scrollbar { display: none; }
.folio-lv-preset {
  flex-shrink: 0;
  height: 28px;
  padding: 0 12px;
  border: 1px solid var(--border-subtle);
  border-radius: 9999px;
  background: var(--secondary);
  color: var(--muted-foreground);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: color 150ms, background-color 150ms, border-color 150ms;
}
.folio-lv-preset:hover { color: var(--foreground); }
.folio-lv-preset[aria-pressed='true'] {
  border-color: var(--border);
  background: var(--tertiary);
  color: var(--foreground);
}
.folio-lv-divider { width: 1px; height: 16px; flex-shrink: 0; background: var(--border); }
.folio-lv-chip {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  height: 28px;
  max-width: 100%;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 9999px;
  background: var(--card);
  font-size: 12px;
  line-height: 1;
}
.folio-lv-chip-dimension {
  flex-shrink: 0;
  padding: 8px 8px 8px 10px;
  border-right: 1px solid var(--border-subtle);
  color: var(--muted-foreground);
}
.folio-lv-chip-value {
  min-width: 0;
  max-width: 260px;
  overflow: hidden;
  padding: 0 8px;
  font-weight: 500;
  color: var(--foreground);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.folio-lv-chip-remove {
  display: flex;
  height: 100%;
  flex-shrink: 0;
  align-items: center;
  padding: 4px 8px 4px 6px;
  border: 0;
  border-left: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  transition: background-color 150ms, color 150ms;
}
.folio-lv-chip-remove:hover { background: var(--accent); color: var(--foreground); }
.folio-lv-chip-remove svg { width: 12px; height: 12px; }
.folio-lv-tools { display: flex; flex-shrink: 0; align-items: center; gap: 2px; margin-left: auto; padding-left: 8px; }
/* The funnel / display icon buttons: 28px ghost squares, muted until hover. */
.folio-lv-tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  transition: background-color 150ms, color 150ms;
}
.folio-lv-tool:hover { background: var(--accent); color: var(--foreground); }
.folio-lv-tool svg { width: 16px; height: 16px; }

.folio-lv-list { padding: 0 6px 6px; }
.folio-lv-row {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  column-gap: 12px;
  width: 100%;
  min-width: 0;
  height: 44px;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 75ms;
  content-visibility: auto;
  contain-intrinsic-size: auto 44px;
}
.folio-lv-row:hover { background: var(--row-hover); }
.folio-lv-row:active { background: var(--row-active); }
.folio-lv-cell {
  overflow: hidden;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.folio-lv-cell-muted { color: var(--muted-foreground); }
.folio-lv-cell-bold { font-weight: 500; }
.folio-lv-cell-right { text-align: right; }
.folio-lv-cell-mono { font-variant-numeric: tabular-nums; }

/* A status pill with a leading icon — StatusBadge in entity-rows.tsx. */
/* A status pill is a badge with a leading glyph — the same height as every
   other badge, not a size up. The extra vertical padding it used to carry
   made the pills in list rows taller than the chips beside them. */
.folio-status-badge { gap: 4px; }
.folio-status-badge svg { width: 12px; height: 12px; flex-shrink: 0; }

/* The 24px thumbnail tile rows lead with (ROW_TILE): ring in the row's own
   background so stacked tiles cut a clean edge out of each other. */
.folio-row-tile {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
  object-fit: cover;
  box-shadow: 0 0 0 2px var(--card);
}
.folio-lv-row:hover .folio-row-tile { box-shadow: 0 0 0 2px var(--muted); }

/* Row skeletons while the list loads: five 40px bars. */
.folio-lv-skeletons { display: flex; flex-direction: column; gap: 4px; padding: 12px; }
.folio-lv-skeletons > * { height: 40px; }

/* The pager, as the dashboard's lists carry it: a row RANGE and two 28px
   chevrons, nothing else. "51–100 of 320" says where you are in the data;
   "2 of 7" only says where you are in the UI. Numbered page buttons are a
   row of targets nobody aims at — Previous and Next are the whole gesture. */
.folio-pager { display: flex; align-items: center; gap: 2px; }
.folio-pager-range { padding-right: 2px; font-size: 12px; font-variant-numeric: tabular-nums; color: var(--muted-foreground); white-space: nowrap; }
.folio-pager-btn {
  display: inline-flex; width: 28px; height: 28px; flex-shrink: 0; align-items: center; justify-content: center;
  border: 0; border-radius: 8px; background: transparent; color: var(--muted-foreground);
  cursor: pointer; transition: background-color 150ms, color 150ms;
}
.folio-pager-btn:hover:not(:disabled) { background: var(--accent); color: var(--foreground); }
.folio-pager-btn:disabled { opacity: 0.4; pointer-events: none; }
.folio-pager-btn > svg { width: 16px; height: 16px; }

/* The empty state every table shares (LVEmptyState): borderless, a narrow
   left-aligned column centred in the region. A dashed box around nothing
   draws the eye to the absence rather than to what to do about it. */
.folio-lv-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 340px;
  height: 100%;
  padding: 64px 24px;
}
.folio-lv-empty-inner { width: 100%; max-width: 280px; }
.folio-lv-empty-icons {
  display: grid;
  grid-template-columns: repeat(2, 36px);
  gap: 8px;
  margin-bottom: 24px;
}
.folio-lv-empty-icons > * {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: color-mix(in srgb, var(--muted-foreground) 35%, transparent);
}
.folio-lv-empty-icons > *:last-child { color: color-mix(in srgb, var(--foreground) 70%, transparent); }
.folio-lv-empty-icons svg { width: 36px; height: 36px; }
.folio-lv-empty-title { font-size: 13px; font-weight: 600; color: var(--foreground); }
.folio-lv-empty-description { margin-top: 6px; font-size: 13px; line-height: 1.6; color: var(--muted-foreground); }
.folio-lv-empty-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; }

/* ── Table — from components/ui/table.tsx ───────────────────────────────
   The framed <table> for dense tabular data inside a page (a settings
   breakdown, a fee schedule). For a list of records use the list view above.
   12px radius, --card fill, contact shadow, uppercase muted headers. */

.folio-table-frame {
  position: relative;
  width: 100%;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  box-shadow: 0 1px 0 rgba(26, 26, 26, 0.06);
}
.folio-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.folio-table thead { background: color-mix(in srgb, var(--secondary) 60%, transparent); }
.folio-table th {
  height: 40px;
  padding: 0 12px;
  text-align: left;
  vertical-align: middle;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted-foreground);
  border-bottom: 1px solid var(--border);
}
.folio-table td {
  padding: 12px;
  vertical-align: middle;
  border-bottom: 1px solid var(--border);
}
.folio-table tbody tr { transition: background-color 120ms; }
.folio-table tbody tr:hover { background: var(--row-hover); }
.folio-table tbody tr:last-child td { border-bottom: 0; }

/* ── Tabs — from components/ui/tabs.tsx ─────────────────────────────────
   Segmented control: a filled 32px track; the active segment lifts to
   --background with one soft contact shadow. Segments stretch to the track's
   inner height so they hug rather than float. Mark the active trigger with
   aria-selected="true" (or data-state="active"). */

.folio-tabs {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 3px;
  border-radius: 9px;
  background: var(--secondary);
  color: var(--muted-foreground);
}
.folio-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;
  white-space: nowrap;
  padding: 0 12px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  outline: none;
  transition: background-color 150ms, color 150ms, box-shadow 150ms;
}
.folio-tab:hover { color: var(--foreground); }
.folio-tab[aria-selected='true'], .folio-tab[data-state='active'] {
  background: var(--background);
  color: var(--foreground);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.08), 0 0 0 1px rgba(26, 26, 26, 0.04);
}
.folio-tab:disabled { pointer-events: none; opacity: 0.5; }

/* ── Tooltip — from components/ui/tooltip.tsx ───────────────────────────── */

.folio-tooltip {
  z-index: 50;
  overflow: hidden;
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--inverse);
  color: var(--inverse-foreground);
  font-size: 12px;
  box-shadow: 0 4px 8px rgba(26, 26, 26, 0.2);
}

/* ── Separator ───────────────────────────────────────────────────────────── */

.folio-separator { height: 1px; width: 100%; flex-shrink: 0; background: var(--border); }
.folio-separator-vertical { width: 1px; height: 100%; flex-shrink: 0; background: var(--border); }

/* ── Skeleton — from index.css's .skeleton ──────────────────────────────
   A shimmer, not a pulse: a light band sweeping a static bar reads as
   "something is arriving" instead of the whole block throbbing. The sheen
   rides ::after over whatever fill you set, so tinted skeletons keep working.
   --skeleton-sheen is themed (0.3 white in light, 0.05 in dark). */

.folio-skeleton {
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  background: var(--muted);
}
.folio-skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--skeleton-sheen), rgba(255, 255, 255, 0));
  animation: skeleton-shimmer var(--skeleton-sweep) linear infinite;
}
/* Inside the shell the skeleton is held back, exactly as the dashboard holds
   its own: invisible at rest, fading in only after --skeleton-delay. On a
   fast connection the data lands first and the placeholder is never painted,
   so a quick page never flashes. A popup body has no shell and shows its
   skeleton at once (a popup that visibly opened and shows nothing reads as
   broken). .folio-skeleton-instant opts a shell skeleton out of the delay,
   for a partial refetch inside a page you are already looking at. */
.folio-shell .folio-skeleton {
  opacity: 0;
  animation: folio-skeleton-in var(--skeleton-fade, 240ms) ease-out var(--skeleton-delay, 500ms) forwards;
}
.folio-shell .folio-skeleton-instant { opacity: 1; animation: none; }
@keyframes folio-skeleton-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes skeleton-shimmer {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .folio-skeleton::after { content: none; }
}

/* ── Error & warning notes — from error-note.tsx and .warning-note ──────
   Tinted fill, NO border on top of it, text mixed toward --foreground so one
   expression reads correctly on every theme (deep crimson on a pale wash in
   light, light red on near-black in dark). */

.folio-error-note {
  padding: 10px 12px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--destructive) 10%, transparent);
}
.folio-error-note > * + * { margin-top: 4px; }
.folio-error-note-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: color-mix(in srgb, var(--destructive) 80%, var(--foreground));
}
.folio-error-note-title svg { width: 14px; height: 14px; flex-shrink: 0; }
.folio-error-note-body {
  font-size: 12px;
  font-weight: 500;
  line-height: 1.6;
  color: color-mix(in srgb, var(--destructive) 68%, var(--foreground));
}

.folio-warning-note {
  padding: 10px 12px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--warning) 45%, transparent);
  color: color-mix(in srgb, var(--warning-foreground) 88%, var(--foreground));
  font-size: 12px;
  font-weight: 500;
  line-height: 1.6;
}

/* ── Calendar ──────────────────────────────────────────────────────────
   The dashboard's date picker: a field that opens a month grid.

   The grid is ported from src/components/ui/date-picker.tsx exactly — 32px
   cells, 11px weekday headers, 6px cell radius (--radius minus 2), the
   selected day filled with the primary colour and today marked by weight
   rather than a ring. The TRIGGER is a .folio-input instead of the picker's
   older bordered button, because every other field in a Folio form is
   filled and a lone outlined control reads as a mistake.

   A date is the single most common field an app asks for after a name, and
   <input type="date"> renders as a different control in every browser — a
   grey Chrome pill on Windows, nothing at all on some Linux builds. */
.folio-calendar-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border: none;
  border-radius: 12px;
  background: var(--secondary);
  color: var(--foreground);
  font-family: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: background-color 120ms ease;
}
.folio-calendar-trigger:hover:not(:disabled) { background: var(--secondary-hover, var(--secondary)); }
.folio-calendar-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--ring); }
.folio-calendar-trigger:disabled { opacity: 0.5; cursor: default; }
.folio-calendar-trigger[data-empty='true'] { color: var(--muted-foreground); }
.folio-calendar-trigger svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--muted-foreground); }

.folio-calendar {
  width: auto;
  padding: 12px;
  border-radius: 16px;
  background: var(--dropdown);
  color: var(--popover-foreground);
  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
}
.folio-calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.folio-calendar-title { font-size: 14px; font-weight: 500; }
.folio-calendar-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  transition: background-color 120ms ease;
}
.folio-calendar-nav:hover { background: var(--muted); }
.folio-calendar-nav svg { width: 16px; height: 16px; }
.folio-calendar-grid { display: grid; grid-template-columns: repeat(7, 32px); }
.folio-calendar-weekday {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  font-size: 11px;
  font-weight: 500;
  color: var(--muted-foreground);
}
.folio-calendar-day {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  width: 32px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  transition: background-color 120ms ease;
}
.folio-calendar-day:hover:not(:disabled) { background: var(--muted); }
.folio-calendar-day:disabled { opacity: 0.35; cursor: default; }
.folio-calendar-day[data-today='true'] { font-weight: 600; color: var(--primary); }
.folio-calendar-day[data-selected='true'] {
  background: var(--primary);
  color: var(--primary-foreground);
  font-weight: 500;
}
.folio-calendar-day[data-selected='true']:hover { background: var(--primary); }
.folio-calendar-foot {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
.folio-calendar-foot button {
  border: none;
  background: transparent;
  color: var(--muted-foreground);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: color 120ms ease;
}
.folio-calendar-foot button:hover { color: var(--foreground); }
