/* ============================================================
   flux-ui.css — a faithful static reproduction of Flux's own UI
   layer, for use inside surface frames and component cards.

   THIS FILE IS A REPRODUCTION, NOT A REDESIGN.
   Every value here is resolved from the real product:
     - colours   src/app/globals.css        (:root, light theme)
     - radii     tailwind.config.ts         (--radius: 0.5rem)
     - classes   src/components/ui/*.tsx    (the shadcn layer)
     - type      src/app/layout.tsx         (Inter, weights 400-700)
   Tailwind utilities are resolved to their literal values (h-10
   -> 40px, p-6 -> 24px, text-sm -> 14px/20px) so the static page
   renders what the app renders.

   Do not "improve" anything in here. If a value looks wrong, it
   is probably wrong in the product too, which is a finding for
   showcase/README.md, not a thing to quietly fix. See
   "Faithful vs. approximated" in that file.
   ============================================================ */

/* TOKENS GO ON :root, NOT ON .fx.
   Scoping them to .fx looked tidier and was wrong: the surface frames carry
   .fx on the .shot wrapper, but the category pages put reproduced components
   inside .vbody with no .fx ancestor, so every var(--chart-2) / var(--primary)
   resolved to nothing and the entry blocks rendered with no background at all.
   Invisible, not broken — no error, nothing thrown. Caught by looking at the
   first captured card. Tokens are global; .fx stays a base/reset scope. */
:root {
  /* Flux's light theme, converted from the HSL in globals.css.
     NOTE: globals.css annotates --primary as #673AB7 and --accent as #009688,
     but the HSL values it actually ships (262 52% 47% / 174 100% 29%) resolve
     to #673AB6 and #009485. The comments are rounded; these are the pixels the
     user gets. Reproduced as shipped, logged in README under Discrepancies. */
  --background: #F5F5F5;
  --foreground: #09090B;
  --card: #FFFFFF;
  --card-foreground: #09090B;
  --popover: #FFFFFF;
  --popover-foreground: #09090B;
  --primary: #673AB6;
  --primary-foreground: #FAFAFA;
  --secondary: #EBEBEB;
  --secondary-foreground: #18181B;
  --muted: #EBEBEB;
  --muted-foreground: #71717A;
  --accent: #009485;
  --accent-foreground: #FAFAFA;
  --destructive: #EF4444;
  --destructive-foreground: #FAFAFA;
  --border: #E5E5E5;
  --input: #E5E5E5;
  --ring: #673AB6;
  --chart-1: #673AB6;
  --chart-2: #009485;
  --chart-3: #274754;
  --chart-4: #E8C468;
  --chart-5: #F4A462;
  --sidebar-background: #FFFFFF;
  --sidebar-foreground: #3F3F46;
  --sidebar-primary: #673AB6;
  --sidebar-primary-foreground: #FAFAFA;
  --sidebar-accent: #F5F5F5;
  --sidebar-accent-foreground: #18181B;
  --sidebar-border: #E5E5E5;
  --sidebar-ring: #673AB6;

  /* tailwind.config.ts: lg = var(--radius), md = calc(-2px), sm = calc(-4px) */
  --radius: 8px;
  --radius-md: 6px;
  --radius-sm: 4px;

  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);
}

/* .fx marks "inside here is reproduced product UI": it carries the app's type,
   the reset, and Lucide's default icon sizing. Put it on the .shot wrapper of
   a surface frame, and on every .vbody of a category page.
   It deliberately sets NO background — the container decides the stage, so
   .vbody / .vbody.dark-stage keep control without a specificity fight. */
.fx {
  font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  color: var(--foreground);
  -webkit-font-smoothing: antialiased;
  font-size: 16px;
  line-height: 1.5;
}
.fx *, .fx *::before, .fx *::after { box-sizing: border-box; }
.fx p, .fx h1, .fx h2, .fx h3, .fx h4, .fx ul, .fx ol, .fx figure { margin: 0; padding: 0; }
.fx ul, .fx ol { list-style: none; }
/* :where() zeroes this reset's specificity, so it never outranks a component
   rule. Written as `.fx button` it scores 0,1,1 and silently beat every
   .fx-btn--* variant (0,1,0), stripping the fill off filled buttons and the
   border off outline buttons. Caught by looking at the first captured frame:
   Quick Add, Add Entry and Capture all rendered as bare text. */
.fx :where(button) { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
.fx :where(a) { color: inherit; text-decoration: none; }
.fx svg { display: block; }

/* Lucide's own defaults, as lucide-react emits them. */
.fx .lucide {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  flex: none;
}
.fx .lucide-lg { width: 20px; height: 20px; }
.fx .lucide-xl { width: 24px; height: 24px; }
.fx .lucide-sm { width: 14px; height: 14px; }
.fx .lucide-xs { width: 12px; height: 12px; }

/* ── Card — "rounded-lg border bg-card text-card-foreground shadow-sm" ── */
.fx-card {
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--card-foreground);
  box-shadow: var(--shadow-sm);
}
/* "flex flex-col space-y-1.5 p-6" */
.fx-card-header { display: flex; flex-direction: column; gap: 6px; padding: 24px; }
/* "text-2xl font-semibold leading-none tracking-tight" */
.fx-card-title { font-size: 24px; font-weight: 600; line-height: 1; letter-spacing: -.025em; }
/* "text-sm text-muted-foreground" */
.fx-card-description { font-size: 14px; line-height: 20px; color: var(--muted-foreground); }
/* "p-6 pt-0" */
.fx-card-content { padding: 24px; padding-top: 0; }
/* "flex items-center p-6 pt-0" */
.fx-card-footer { display: flex; align-items: center; padding: 24px; padding-top: 0; }
/* Compact variants: the app frequently passes p-4 / text-lg overrides. */
.fx-card-header.pad-4 { padding: 16px; }
.fx-card-content.pad-4 { padding: 16px; padding-top: 0; }
.fx-card-title.t-lg { font-size: 18px; line-height: 1.2; }
.fx-card-title.t-base { font-size: 16px; line-height: 1.2; }
.fx-card-title.t-sm { font-size: 14px; line-height: 1.2; }

/* ── Button — src/components/ui/button.tsx ────────────────── */
/* base: "inline-flex items-center justify-center gap-2 whitespace-nowrap
   rounded-md text-sm font-medium transition-colors …[&_svg]:size-4" */
.fx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  white-space: nowrap; border-radius: var(--radius-md);
  font-size: 14px; line-height: 20px; font-weight: 500;
  transition: background-color .15s, color .15s, border-color .15s;
  /* size default: "h-10 px-4 py-2" */
  height: 40px; padding: 8px 16px;
}
.fx-btn .lucide { width: 16px; height: 16px; }
.fx-btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.fx-btn[disabled], .fx-btn.is-disabled { pointer-events: none; opacity: .5; }

.fx-btn--default { background: var(--primary); color: var(--primary-foreground); }
.fx-btn--default:hover { background: rgba(103, 58, 182, .9); }
.fx-btn--destructive { background: var(--destructive); color: var(--destructive-foreground); }
.fx-btn--destructive:hover { background: rgba(239, 68, 68, .9); }
.fx-btn--outline { border: 1px solid var(--input); background: var(--background); }
.fx-btn--outline:hover { background: var(--accent); color: var(--accent-foreground); }
.fx-btn--secondary { background: var(--secondary); color: var(--secondary-foreground); }
.fx-btn--secondary:hover { background: rgba(235, 235, 235, .8); }
.fx-btn--ghost { background: transparent; }
.fx-btn--ghost:hover { background: var(--accent); color: var(--accent-foreground); }
.fx-btn--link { color: var(--primary); text-underline-offset: 4px; }
.fx-btn--link:hover { text-decoration: underline; }

/* size sm: "h-9 rounded-md px-3" | lg: "h-11 rounded-md px-8" | icon: "h-10 w-10" */
.fx-btn--sm { height: 36px; padding-left: 12px; padding-right: 12px; }
.fx-btn--lg { height: 44px; padding-left: 32px; padding-right: 32px; }
.fx-btn--icon { height: 40px; width: 40px; padding: 0; }
/* SidebarTrigger is size="icon" but passes className="h-7 w-7", and
   tailwind-merge lets that override the size, so it ships at 28px, not 40.
   The two icon buttons in the app header are therefore DIFFERENT sizes: the
   sidebar trigger is 28 and the theme toggle is a plain 40. That looks like a
   mistake in a reproduction, which is exactly why it is named and commented. */
.fx-btn--icon-7 { height: 28px; width: 28px; padding: 0; }
/* Call sites that pass className="h-8 w-8" over size="icon" (e.g. the Now
   page's duration stepper). */
.fx-btn--icon-8 { height: 32px; width: 32px; padding: 0; }
.fx-btn--icon-6 { height: 24px; width: 24px; padding: 0; }

/* ── Badge — src/components/ui/badge.tsx ──────────────────── */
/* "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold" */
.fx-badge {
  display: inline-flex; align-items: center; gap: 4px;
  border-radius: 9999px; border: 1px solid transparent;
  padding: 2px 10px; font-size: 12px; line-height: 16px; font-weight: 600;
}
.fx-badge .lucide { width: 12px; height: 12px; }
.fx-badge--default { background: var(--primary); color: var(--primary-foreground); }
.fx-badge--secondary { background: var(--secondary); color: var(--secondary-foreground); }
.fx-badge--destructive { background: var(--destructive); color: var(--destructive-foreground); }
.fx-badge--outline { color: var(--foreground); border-color: var(--border); }

/* ── Input / Textarea / Label ─────────────────────────────── */
/* input: "flex h-10 w-full rounded-md border border-input bg-background px-3
   py-2 text-base … md:text-sm" — the showcase renders at desktop width, so
   the md: breakpoint applies and text is 14px. */
.fx-input {
  display: flex; height: 40px; width: 100%;
  border-radius: var(--radius-md); border: 1px solid var(--input);
  background: var(--background); padding: 8px 12px;
  font-size: 14px; line-height: 20px; color: var(--foreground);
}
.fx-input::placeholder { color: var(--muted-foreground); }
.fx-input:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.fx-input[disabled], .fx-input.is-disabled { cursor: not-allowed; opacity: .5; }
/* textarea: "min-h-[80px] w-full rounded-md border px-3 py-2" */
.fx-textarea {
  display: flex; min-height: 80px; width: 100%;
  border-radius: var(--radius-md); border: 1px solid var(--input);
  background: var(--background); padding: 8px 12px;
  font-size: 14px; line-height: 20px; color: var(--foreground);
  resize: vertical; font-family: inherit;
}
.fx-textarea::placeholder { color: var(--muted-foreground); }
/* label: "text-sm font-medium leading-none" */
.fx-label { font-size: 14px; font-weight: 500; line-height: 1; display: inline-block; }

/* ── Separator ────────────────────────────────────────────── */
.fx-sep { background: var(--border); height: 1px; width: 100%; border: 0; margin: 0; flex: none; }
.fx-sep--v { width: 1px; height: auto; align-self: stretch; }

/* ── Skeleton — "animate-pulse rounded-md bg-muted" ───────── */
.fx-skeleton { border-radius: var(--radius-md); background: var(--muted); animation: fx-pulse 2s cubic-bezier(.4,0,.6,1) infinite; }
@keyframes fx-pulse { 50% { opacity: .5; } }
@media (prefers-reduced-motion: reduce) { .fx-skeleton { animation: none; } }

/* ── Alert — "rounded-lg border p-4" ──────────────────────── */
.fx-alert {
  position: relative; border-radius: var(--radius); border: 1px solid var(--border);
  padding: 16px; display: grid; grid-template-columns: 16px 1fr; gap: 4px 12px;
  background: var(--background);
}
.fx-alert > .lucide { width: 16px; height: 16px; grid-row: span 2; margin-top: 2px; }
.fx-alert-title { font-size: 14px; font-weight: 500; line-height: 1; letter-spacing: -.01em; margin-bottom: 4px; }
.fx-alert-desc { font-size: 14px; line-height: 20px; color: var(--muted-foreground); }
.fx-alert--destructive { border-color: rgba(239, 68, 68, .5); color: var(--destructive); }
.fx-alert--destructive .fx-alert-desc { color: var(--destructive); }

/* ── Tabs ─────────────────────────────────────────────────── */
/* list: "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1
   text-muted-foreground" */
.fx-tabs-list {
  display: inline-flex; height: 40px; align-items: center; justify-content: center;
  border-radius: var(--radius-md); background: var(--muted); padding: 4px;
  color: var(--muted-foreground);
}
/* trigger: "…rounded-sm px-3 py-1.5 text-sm font-medium"; active adds
   "bg-background text-foreground shadow-sm" */
.fx-tab {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  white-space: nowrap; border-radius: var(--radius-sm);
  padding: 6px 12px; font-size: 14px; line-height: 20px; font-weight: 500;
}
.fx-tab[aria-selected="true"], .fx-tab.is-active {
  background: var(--card); color: var(--foreground); box-shadow: var(--shadow-sm);
}

/* ── Switch ───────────────────────────────────────────────── */
/* "h-6 w-11 rounded-full border-2 border-transparent"; thumb "h-5 w-5" */
.fx-switch {
  display: inline-flex; align-items: center; flex: none;
  height: 24px; width: 44px; border-radius: 9999px;
  border: 2px solid transparent; background: var(--input);
  padding: 0; transition: background-color .15s;
}
.fx-switch .thumb {
  height: 20px; width: 20px; border-radius: 9999px; background: var(--card);
  box-shadow: var(--shadow-lg); transition: transform .15s;
  transform: translateX(0);
}
.fx-switch.is-on { background: var(--primary); }
.fx-switch.is-on .thumb { transform: translateX(20px); }
@media (prefers-reduced-motion: reduce) { .fx-switch, .fx-switch .thumb { transition: none; } }

/* ── Checkbox — "h-4 w-4 rounded-sm border border-primary" ── */
.fx-check {
  height: 16px; width: 16px; flex: none;
  border-radius: var(--radius-sm); border: 1px solid var(--primary);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--primary-foreground); background: transparent;
}
.fx-check.is-on { background: var(--primary); }
.fx-check .lucide { width: 14px; height: 14px; stroke-width: 3; }
.fx-check.is-disabled { opacity: .5; cursor: not-allowed; }

/* ── Radio — "h-4 w-4 rounded-full border border-primary" ─── */
.fx-radio {
  height: 16px; width: 16px; flex: none;
  border-radius: 9999px; border: 1px solid var(--primary);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--primary); background: transparent;
}
.fx-radio .dot { height: 9px; width: 9px; border-radius: 9999px; background: var(--primary); }

/* ── Progress — "h-4 w-full rounded-full bg-secondary" ────── */
.fx-progress { position: relative; height: 16px; width: 100%; overflow: hidden; border-radius: 9999px; background: var(--secondary); }
.fx-progress .bar { height: 100%; background: var(--primary); border-radius: 9999px; }
.fx-progress--thin { height: 8px; }

/* ── Slider ───────────────────────────────────────────────── */
.fx-slider { position: relative; display: flex; align-items: center; width: 100%; height: 20px; }
.fx-slider .track { position: relative; height: 8px; width: 100%; border-radius: 9999px; background: var(--secondary); overflow: hidden; }
.fx-slider .range { position: absolute; inset: 0 auto 0 0; height: 100%; background: var(--primary); }
.fx-slider .thumb {
  position: absolute; height: 20px; width: 20px; border-radius: 9999px;
  border: 2px solid var(--primary); background: var(--card); box-shadow: var(--shadow-sm);
  transform: translateX(-50%);
}

/* ── Table ────────────────────────────────────────────────── */
.fx-table { width: 100%; caption-side: bottom; font-size: 14px; border-collapse: collapse; }
.fx-table thead tr { border-bottom: 1px solid var(--border); }
.fx-table th {
  height: 48px; padding: 0 16px; text-align: left; vertical-align: middle;
  font-weight: 500; color: var(--muted-foreground); font-size: 14px;
}
.fx-table td { padding: 16px; vertical-align: middle; }
.fx-table tbody tr { border-bottom: 1px solid var(--border); }
.fx-table tbody tr:last-child { border-bottom: 0; }
.fx-table--compact th { height: 36px; padding: 0 12px; font-size: 12px; }
.fx-table--compact td { padding: 9px 12px; font-size: 13px; }

/* ── Avatar — "h-10 w-10 rounded-full" ───────────────────── */
.fx-avatar {
  position: relative; display: flex; height: 40px; width: 40px; flex: none;
  overflow: hidden; border-radius: 9999px;
  align-items: center; justify-content: center;
  background: var(--muted); color: var(--muted-foreground);
  font-size: 14px; font-weight: 500;
}
.fx-avatar--sm { height: 32px; width: 32px; font-size: 12px; }
.fx-avatar--lg { height: 80px; width: 80px; font-size: 24px; }

/* ── Popover / Dialog / Sheet surfaces ────────────────────── */
/* popover: "rounded-md border bg-popover p-4 shadow-md" */
.fx-popover {
  border-radius: var(--radius-md); border: 1px solid var(--border);
  background: var(--popover); color: var(--popover-foreground);
  padding: 16px; box-shadow: var(--shadow-md);
}
/* dialog: "border bg-background p-6 shadow-lg sm:rounded-lg" */
.fx-dialog {
  border: 1px solid var(--border); background: var(--background);
  padding: 24px; box-shadow: var(--shadow-lg); border-radius: var(--radius);
  display: flex; flex-direction: column; gap: 16px;
}
.fx-dialog-title { font-size: 18px; font-weight: 600; line-height: 1; letter-spacing: -.025em; }
.fx-dialog-desc { font-size: 14px; line-height: 20px; color: var(--muted-foreground); }
/* sheet: side panel, "bg-background p-6 shadow-lg" */
.fx-sheet {
  background: var(--background); padding: 24px; box-shadow: var(--shadow-lg);
  border-left: 1px solid var(--border); display: flex; flex-direction: column; gap: 16px;
}
/* tooltip: "rounded-md border bg-popover px-3 py-1.5 text-sm shadow-md" */
.fx-tooltip {
  border-radius: var(--radius-md); border: 1px solid var(--border);
  background: var(--popover); color: var(--popover-foreground);
  padding: 6px 12px; font-size: 14px; box-shadow: var(--shadow-md);
}

/* ── Select trigger — "h-10 w-full rounded-md border px-3 py-2" ── */
.fx-select {
  display: flex; height: 40px; width: 100%; align-items: center; justify-content: space-between;
  border-radius: var(--radius-md); border: 1px solid var(--input);
  background: var(--background); padding: 8px 12px; font-size: 14px; line-height: 20px;
}
.fx-select .lucide { width: 16px; height: 16px; opacity: .5; }

/* ── Accordion ────────────────────────────────────────────── */
.fx-acc-item { border-bottom: 1px solid var(--border); }
.fx-acc-trigger {
  display: flex; flex: 1; width: 100%; align-items: center; justify-content: space-between;
  padding: 16px 0; font-size: 14px; font-weight: 500; text-align: left;
}
.fx-acc-trigger .chev { transition: transform .2s; opacity: .5; }
.fx-acc-trigger[aria-expanded="true"] .chev { transform: rotate(180deg); }
.fx-acc-content { padding-bottom: 16px; font-size: 14px; line-height: 20px; }
@media (prefers-reduced-motion: reduce) { .fx-acc-trigger .chev { transition: none; } }

/* ── Toast — "rounded-md border p-6 pr-8 shadow-lg" ───────── */
.fx-toast {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  border-radius: var(--radius-md); border: 1px solid var(--border);
  background: var(--background); padding: 24px 32px 24px 24px; box-shadow: var(--shadow-lg);
}
.fx-toast--destructive { border-color: var(--destructive); background: var(--destructive); color: var(--destructive-foreground); }
.fx-toast-title { font-size: 14px; font-weight: 600; }
.fx-toast-desc { font-size: 14px; opacity: .9; }

/* ── App shell: sidebar ───────────────────────────────────── */
/* SIDEBAR_WIDTH 16rem; SIDEBAR_WIDTH_ICON is 3.25rem in Flux's fork of the
   shadcn sidebar (stock is 3rem). sidebar.tsx is the ONLY meaningfully
   customised file in the ui/ layer; the other 34 are stock. (An earlier
   version of this comment said "one of exactly two" and was wrong.) */
.fx-sidebar {
  width: 256px; flex: none; display: flex; flex-direction: column;
  background: var(--sidebar-background); color: var(--sidebar-foreground);
  border-right: 1px solid var(--sidebar-border);
}
.fx-sidebar--icon { width: 52px; }
/* SidebarHeader: "flex flex-col gap-2 p-2" */
.fx-sb-header { padding: 8px; display: flex; flex-direction: column; gap: 8px; }
/* Flux renders no SidebarContent: it puts <SidebarMenu className="h-full p-2">
   directly under the header. SidebarMenu is "flex w-full min-w-0 flex-col gap-1". */
.fx-sb-content { flex: 1; display: flex; flex-direction: column; gap: 4px; padding: 8px; overflow: hidden; min-height: 0; }
.fx-sb-footer { padding: 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--sidebar-border); }
/* The brand lockup, verbatim: <Waves className="w-8 h-8 text-primary" /> beside
   a "text-lg font-semibold" span, in a "flex items-center gap-2 p-2" div. The
   mark is 32px, not the 20px a sidebar glyph would suggest. */
.fx-sb-brand { display: flex; align-items: center; gap: 8px; padding: 8px; font-size: 18px; font-weight: 600; color: var(--foreground); }
.fx-sb-brand .lucide { width: 32px; height: 32px; color: var(--primary); }
/* SidebarMenuButton base: "flex w-full items-center gap-2 overflow-hidden
   rounded-md p-2 text-left text-sm" + size default "h-8 text-sm".
   Icons are "[&>svg]:size-5" = 20px, NOT the 16px used elsewhere in the app. */
.fx-sb-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  height: 32px; padding: 8px; border-radius: var(--radius-md);
  font-size: 14px; line-height: 1; color: var(--sidebar-foreground);
  text-decoration: none; overflow: hidden; white-space: nowrap; text-align: left;
}
.fx-sb-item .lucide { width: 20px; height: 20px; }
/* SidebarMenuButton variant="outline": a 1px ring drawn as a shadow rather
   than a border, so it does not affect layout. Quick Add adds border-dashed
   and justify-start on top. */
.fx-sb-item--outline {
  background: var(--background);
  box-shadow: 0 0 0 1px var(--sidebar-border);
  justify-content: flex-start;
  border: 1px dashed var(--sidebar-border);
}
.fx-sb-item:hover { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); }
.fx-sb-item.is-active { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); font-weight: 500; }
/* The "Preview" group renders at opacity-70 in sidebar.tsx — reproduced. */
.fx-sb-item.is-preview { opacity: .7; }
.fx-sb-group-label {
  font-size: 12px; font-weight: 500; color: var(--muted-foreground);
  padding: 8px; display: flex; align-items: center; justify-content: space-between;
}

/* ── App shell: header — layout/header.tsx ────────────────── */
/* "flex items-center justify-between gap-4 py-2 border-b bg-card sticky
   top-0 z-10 h-12" — 48px on the card surface, not the page surface. */
.fx-header {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  height: 48px; padding: 8px 0; flex: none;
  border-bottom: 1px solid var(--border); background: var(--card);
}
.fx-header .left { display: flex; align-items: center; gap: 8px; padding-left: 8px; }
.fx-header .right { display: flex; align-items: center; gap: 8px; padding-right: 24px; }
/* "text-base font-semibold tracking-tight" / "text-xs text-muted-foreground" */
.fx-header .title { font-size: 16px; font-weight: 600; letter-spacing: -.025em; line-height: 1.25; }
.fx-header .desc { font-size: 12px; line-height: 16px; color: var(--muted-foreground); }
/* DailyCountdown: "flex items-end font-mono", text-xl bold + text-sm muted.
   Hidden on the Now page (pathname !== '/'). */
.fx-countdown { display: flex; align-items: flex-end; font-family: monospace; }
.fx-countdown .m { font-size: 20px; font-weight: 700; line-height: 1; }
.fx-countdown .s { font-size: 14px; color: var(--muted-foreground); margin-left: 4px; line-height: 1.1; }
.fx-main { flex: 1; overflow: hidden; background: var(--background); }

/* ── BetaBanner — src/components/shared/beta-banner.tsx ─────
   The app's honesty mechanism, and the component most worth getting exactly
   right. Base class, verbatim:
     "flex items-center gap-2 px-3 py-1.5 text-xs border rounded-md"
   plus a per-variant bg/border pair and a text colour. Note it is a FULL 1px
   border with a 6px radius, and an ALPHA tint over whatever is behind it, not
   a solid fill with a bottom rule.

   POSITION: (app)/layout.tsx renders <BetaBanner /> as a sibling BEFORE
   {children}, and AppHeader lives inside {children}. So the banner sits ABOVE
   the header, not under it. Frames must reproduce that DOM order.

   Six variants keyed by RouteStatus. `live` has an empty label and the
   component returns null before rendering: it produces NO element at all. So
   there is deliberately no .fx-banner--live class here.

   Colours are Tailwind's amber/blue/red/slate 500 at /10 and /30, with the
   600 shade for text. Resolved to literals because the showcase ships no
   Tailwind. */
.fx-banner {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px; font-size: 12px; line-height: 16px;
  border: 1px solid transparent; border-radius: var(--radius-md);
  /* Frames reconstruct SidebarInset as a flex column, where the banner would
     otherwise be free to stretch. Central rather than per-frame: it is about
     the banner's own box, it is inert outside a flex parent, and leaving it
     out means every new frame rediscovers a tall banner for itself. */
  flex: none;
}
.fx-banner .lucide { width: 14px; height: 14px; flex: none; }
/* "font-semibold" on the label, "opacity-75" on the honesty text. */
.fx-banner b { font-weight: 600; }
.fx-banner .why { opacity: .75; }
.fx-banner--shallow   { background: rgba(245, 158, 11, .10); border-color: rgba(245, 158, 11, .30); color: #D97706; }
.fx-banner--partial   { background: rgba(59, 130, 246, .10); border-color: rgba(59, 130, 246, .30); color: #2563EB; }
.fx-banner--broken    { background: rgba(239, 68, 68, .10);  border-color: rgba(239, 68, 68, .30);  color: #DC2626; }
.fx-banner--reference { background: rgba(100, 116, 139, .10); border-color: rgba(100, 116, 139, .30); color: #475569; }
.fx-banner--hidden    { background: rgba(239, 68, 68, .10);  border-color: rgba(239, 68, 68, .30);  color: #DC2626; }

/* ── Calendar grid primitives ─────────────────────────────── */
/* START_HOUR = 7, TOTAL_HOURS = 15 (7am to 10pm) — task-block.tsx */
.fx-cal { position: relative; display: flex; height: 100%; }
.fx-cal-gutter { width: 56px; flex: none; }
.fx-cal-gutter .h {
  height: 48px; font-size: 11px; color: var(--muted-foreground);
  text-align: right; padding-right: 8px; transform: translateY(-6px);
}
.fx-cal-grid { position: relative; flex: 1; border-left: 1px solid var(--border); }
.fx-cal-grid .row { height: 48px; border-bottom: 1px solid var(--border); }
.fx-entry {
  position: absolute; border-radius: var(--radius-md); padding: 4px 8px;
  font-size: 12px; line-height: 1.35; overflow: hidden; color: #FFFFFF;
  border: 1px solid transparent;
}
.fx-entry .t { font-weight: 600; }
.fx-entry .time { opacity: .85; font-size: 11px; }
.fx-entry--atomic { background: var(--chart-2); }
.fx-entry--container { background: var(--chart-3); }
.fx-entry--child { border-style: dashed; border-color: rgba(255, 255, 255, .6); opacity: .9; }
.fx-entry--conflict { outline: 2px solid var(--destructive); outline-offset: -2px; }
.fx-entry--timeconflict { border-color: var(--destructive); border-width: 2px; }
.fx-nowline { position: absolute; left: 0; right: 0; height: 2px; background: var(--destructive); z-index: 3; }
.fx-nowline::before {
  content: ""; position: absolute; left: -4px; top: -3px;
  width: 8px; height: 8px; border-radius: 9999px; background: var(--destructive);
}

/* ── Utility scaffolding (layout only, no new visual language) ── */
.fx-row { display: flex; align-items: center; gap: 8px; }
.fx-row.between { justify-content: space-between; }
.fx-col { display: flex; flex-direction: column; gap: 8px; }
.fx-grow { flex: 1; min-width: 0; }
.fx-muted { color: var(--muted-foreground); }
.fx-xs { font-size: 12px; line-height: 16px; }
.fx-sm { font-size: 14px; line-height: 20px; }
.fx-mono { font-family: monospace; }
.fx-trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 32px 16px; text-align: center;
  color: var(--muted-foreground); font-size: 14px;
}
.fx-empty .lucide { width: 24px; height: 24px; opacity: .4; }
