/**
 * Generated by Luna. Do not edit by hand — this file is rewritten on
 * every Generate and any manual change is lost.
 *
 * Part 1  design tokens for this app (from the active theme)
 * Part 2  Tabler aliases derived from Part 1
 * Part 3  per-app rules from the theme, layout, and presentation settings
 * Part 4  the shared Luna component library (identical in every app)
 */
/* Part 1 — design tokens (per app, from the active theme) */
:root {
    --luna-primary-50: #f7f6f9;
    --luna-primary-100: #ede9f1;
    --luna-primary-200: #dacbe6;
    --luna-primary-300: #bf9bde;
    --luna-primary-400: #a154e3;
    --luna-primary-500: #8624db;
    --luna-primary-600: #7E22CE;
    --luna-primary-700: #501683;
    --luna-primary-800: #3b1060;
    --luna-primary-rgb: 126, 34, 206;
    --luna-neutral-50: #f8fafc;
    --luna-neutral-100: #f1f5f9;
    --luna-neutral-200: #e2e8f0;
    --luna-neutral-300: #cbd5e1;
    --luna-neutral-400: #94a3b8;
    --luna-neutral-500: #64748b;
    --luna-neutral-600: #475569;
    --luna-neutral-700: #334155;
    --luna-neutral-800: #1e293b;
    --luna-neutral-900: #0f172a;
    --luna-success-50: #f0fdf4;
    --luna-success-100: #dcfce7;
    --luna-success-200: #bbf7d0;
    --luna-success-500: #22c55e;
    --luna-success-600: #16a34a;
    --luna-success-700: #15803d;
    --luna-warning-50: #fffbeb;
    --luna-warning-100: #fef3c7;
    --luna-warning-200: #fde68a;
    --luna-warning-500: #f59e0b;
    --luna-warning-600: #d97706;
    --luna-warning-700: #b45309;
    --luna-danger-50: #fef2f2;
    --luna-danger-100: #fee2e2;
    --luna-danger-200: #fecaca;
    --luna-danger-500: #ef4444;
    --luna-danger-600: #dc2626;
    --luna-danger-700: #b91c1c;
    --luna-info-50: #eff6ff;
    --luna-info-100: #dbeafe;
    --luna-info-200: #bfdbfe;
    --luna-info-500: #3b82f6;
    --luna-info-600: #2563eb;
    --luna-info-700: #1d4ed8;
    --luna-border-color: #e0e0e0;
    --luna-border-strong: #cbd5e1;
    --luna-border-input: var(--luna-border-color);
    --luna-border-input-hover: var(--luna-border-strong);
    --luna-surface: #ffffff;
    --luna-surface-muted: #f8fafc;
    --luna-body-bg: #f8f9fa;
    --luna-text: #1a1a2e;
    --luna-text-muted: #64748b;
    --luna-text-muted-rgb: 100, 116, 139;
    --luna-overlay-bg: rgba(15, 23, 42, 0.45);
    --luna-focus-ring-width: 2px;
    --luna-focus-ring-color: var(--luna-primary-500);
    --luna-font-family: 'Roboto', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --luna-font-scale: 1rem;
    --luna-text-xs: calc(var(--luna-font-scale) * 0.75);
    --luna-text-sm: calc(var(--luna-font-scale) * 0.8125);
    --luna-text-md: var(--luna-font-scale);
    --luna-text-lg: calc(var(--luna-font-scale) * 1.125);
    --luna-text-xl: calc(var(--luna-font-scale) * 1.25);
    --luna-text-2xl: calc(var(--luna-font-scale) * 1.5);
    --luna-heading-weight: 600;
    --luna-heading-tracking: -0.011em;
    --luna-radius-sm: calc(4px * 0.5);
    --luna-radius-md: 4px;
    --luna-radius-lg: calc(4px * 1.25);
    --luna-radius-xl: calc(4px * 1.5);
    --luna-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
    --luna-shadow-md: 0 1px 3px rgba(15, 23, 42, 0.08);
    --luna-shadow-lg: 0 4px 12px rgba(15, 23, 42, 0.12);
    --luna-space-base: 1rem;
    --luna-space-1: calc(var(--luna-space-base) * 0.25);
    --luna-space-2: calc(var(--luna-space-base) * 0.5);
    --luna-space-3: calc(var(--luna-space-base) * 0.75);
    --luna-space-4: var(--luna-space-base);
    --luna-space-5: calc(var(--luna-space-base) * 1.25);
    --luna-space-6: calc(var(--luna-space-base) * 1.5);
}

/* Part 2 — Tabler compatibility aliases, derived from Part 1 */
:root {
    --tblr-primary: var(--luna-primary-600);
    --tblr-primary-rgb: var(--luna-primary-rgb);
    --tblr-primary-lt: var(--luna-primary-50);
    --tblr-primary-fg: var(--luna-surface);
    --tblr-border-color: var(--luna-border-color);
    --tblr-border-color-translucent: var(--luna-border-color);
    --tblr-border-radius: var(--luna-radius-md);
    --tblr-border-radius-sm: var(--luna-radius-sm);
    --tblr-border-radius-lg: var(--luna-radius-lg);
    --tblr-border-radius-xl: var(--luna-radius-xl);
    --tblr-card-border-radius: var(--luna-radius-xl);
    --tblr-card-inner-border-radius: calc(var(--luna-radius-xl) - 1px);
    --tblr-font-sans-serif: var(--luna-font-family);
    --tblr-body-color: var(--luna-text);
    --tblr-secondary-color: var(--luna-text-muted);
    --tblr-secondary: var(--luna-text-muted);
    --tblr-secondary-rgb: var(--luna-text-muted-rgb);
    --tblr-secondary-fg: var(--luna-surface);
    --tblr-box-shadow-sm: var(--luna-shadow-sm);
    --tblr-box-shadow: var(--luna-shadow-md);
    --tblr-box-shadow-lg: var(--luna-shadow-lg);
    --tblr-shadow-card: var(--luna-shadow-sm);
}

/* Part 2b — dark mode: the same token roles, re-pointed */
:root[data-bs-theme="dark"] {
    color-scheme: dark;
    --luna-primary-50: #3b1060;
    --luna-primary-100: #501683;
    --luna-primary-200: #681cab;
    --luna-primary-300: #8624db;
    --luna-primary-400: #a154e3;
    --luna-primary-500: #dacbe6;
    --luna-primary-600: #bf9bde;
    --luna-primary-700: #a154e3;
    --luna-primary-800: #8624db;
    --luna-primary-rgb: 191, 155, 222;
    --luna-neutral-50: #0c141f;
    --luna-neutral-100: #16202c;
    --luna-neutral-200: #25384f;
    --luna-neutral-300: #35506e;
    --luna-neutral-400: #94a6bb;
    --luna-neutral-500: #a8b6c8;
    --luna-neutral-600: #c3cedb;
    --luna-neutral-700: #dce1e7;
    --luna-neutral-800: #eef3f6;
    --luna-neutral-900: #f8fafc;
    --luna-success-50: #0c2a1c;
    --luna-success-100: #103a26;
    --luna-success-200: #1c5c3b;
    --luna-success-500: #34d399;
    --luna-success-600: #10b981;
    --luna-success-700: #6ee7b7;
    --luna-warning-50: #33240a;
    --luna-warning-100: #452f0b;
    --luna-warning-200: #6b4a10;
    --luna-warning-500: #fbbf24;
    --luna-warning-600: #f59e0b;
    --luna-warning-700: #fcd34d;
    --luna-danger-50: #3a1518;
    --luna-danger-100: #4b1a1e;
    --luna-danger-200: #6f272c;
    --luna-danger-500: #f87171;
    --luna-danger-600: #ef4444;
    --luna-danger-700: #fca5a5;
    --luna-info-50: #0d1f2d;
    --luna-info-100: #12293c;
    --luna-info-200: #1c4260;
    --luna-info-500: #60a5fa;
    --luna-info-600: #3b82f6;
    --luna-info-700: #93c5fd;
    --luna-border-color: #25384f;
    --luna-border-strong: #35506e;
    --luna-surface: #182433;
    --luna-surface-muted: #0c141f;
    --luna-body-bg: #040a11;
    --luna-text: #dce1e7;
    --luna-text-muted: #a8b6c8;
    --luna-text-muted-rgb: 168, 182, 200;
    --luna-overlay-bg: rgba(2, 6, 12, 0.66);
    --luna-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
    --luna-shadow-md: 0 4px 10px rgba(0, 0, 0, 0.45);
    --luna-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);
}

/* Part 3 — per-app rules from theme, layout, and presentation settings */
/*
 * Auto-generated by Luna, do not edit by hand.
 * Theme: Serene Orchid (id=11)
 * Tabler: 1.0.0-beta21
 *
 * To override these tokens, add rules in app.css *after* the
 * @import line, your overrides will win.
 */
:root {
  --tblr-primary: #7E22CE;
  --tblr-primary-lt: #ede9f1;
  --tblr-font-sans-serif: 'Roboto', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --tblr-primary-rgb: 126,34,206;
  --tblr-border-radius: 4px;
  --tblr-border-radius: 4px;
  --tblr-border-radius-sm: calc(4px * 0.75);
  --tblr-border-radius-lg: calc(4px * 1.5);
  --tblr-shadow-card: rgba(var(--tblr-body-color-rgb, 15, 23, 42), 0.04) 0 2px 4px 0;
}

/* --luna-* aliases (brand tokens for generated-app components) */
:root {
  --luna-color-primary: var(--tblr-color-primary, #0054a6);
  --luna-color-primary-rgb: var(--tblr-color-primary-rgb, 0, 84, 166);
  --luna-color-secondary: var(--tblr-color-secondary, #616876);
  --luna-overlay-bg: rgba(var(--tblr-body-color-rgb, 15, 23, 42), 0.45);
  --luna-border-radius: 4px;
}

/* Generated by Luna. Do not edit manually. */
:root {
  /* Font: sourced from active theme (ThemeEditor > Typography).
     --tblr-font-sans-serif is set in theme-tokens.css (ThemeCssPublisher);
     --app-font-family mirrors it so non-Tabler elements stay in sync. */
  --app-font-family: 'Roboto', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --app-font-scale: 1rem;
  --app-density-spacing: 1rem;
}

body {
  font-family: var(--app-font-family);
  font-size: var(--app-font-scale);
}

/* Centered ~50% content column (Centered Focus). Full width with gutters
   on small screens; caps to a readable measure and centres on wide ones
   (~50% at common desktop widths). */
.luna-content-half {
  width: 100%;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 1rem;
  padding-right: 1rem;
}

/* Nav item icons set in Builder > Menus. Visible alongside the title in
   normal mode; remain visible as the sole visual in the icon-rail preset
   (where nav-link-title is hidden by the media query below).

   The margin is NOT optional. .nav-link sets no gap and the renderer
   emits the icon and the title as adjacent siblings with no whitespace
   between them, so without it the glyph butts straight against the first
   letter of the label ("[icon]Keyword Profiles"). Logical property so an
   RTL app mirrors it. Matches Tabler's own .nav-link-icon spacing. The
   rail preset zeroes it again below, where the title is hidden and the
   icon is the only child. */
.luna-nav-icon {
  flex: 0 0 auto;
  margin-inline-end: 0.5rem;
  opacity: 0.65;
}

/* Brand wordmark — the app code (config('luna.runtime.app_code')), a
   lowercase [a-z0-9]{2,20} slug, rendered in Proper Case ("testapp" →
   "Testapp") so it reads as a system mark rather than a stray
   identifier, without shouting at the reader from every page. The full
   app name stays on the anchor's title and on the mobile offcanvas
   header. Bounded by the 15rem sidebar, so a 20-char code still needs
   the inherited .text-truncate as a floor. */
.luna-brand-text {
  text-transform: capitalize;
  letter-spacing: 0.02em;
}

/* First-letter badges — hidden everywhere except the Icon Rail preset. */
.luna-nav-letter,
.luna-brand-letter {
  display: none;
  flex: 0 0 auto;
  width: 1.75rem;
  height: 1.75rem;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  font-weight: 600;
  font-size: 0.8rem;
  /* currentColor at 12%: a black wash disappears on a dark sidebar, and
     the letter avatar sits on surfaces of both tones (the rail inherits
     the sidebar surface, which can be brand / dark / light). Deriving the
     chip from the text colour keeps it visible on every one of them. */
  background: rgba(127, 127, 127, 0.14);
  background: color-mix(in srgb, currentColor 12%, transparent);
}

/* Icon Rail sidebar — desktop only; collapses to the normal labelled
   navbar on mobile (< 992px) where the toggler + full titles return. */
/* Trigger visibility is a CLASS, never Alpine's x-show. x-show sets a
   NON-important inline `display:none`, which loses to Bootstrap's
   `.d-lg-flex { display: flex !important }`, so a wrapper carrying a d-*
   display utility could not be hidden and BOTH triggers rendered at once.
   Written to be ORDER-INDEPENDENT: the shown state is the unqualified
   base, and both hidden states are !important, so no later same-specificity
   rule can cancel them. An earlier attempt put the base `display:none`
   after the min-width block and silently hid every trigger at all widths.
   Desktop-only, because below 992px the .luna-rail / .luna-sidebar-hidden
   rules are inactive and the sidebar is reached through the hamburger. */
.luna-trigger-slot { display: flex; }
.luna-trigger-slot--off { display: none !important; }
@media (max-width: 991.98px) { .luna-trigger-slot { display: none !important; } }

@media (min-width: 992px) {
  .luna-rail.navbar-vertical { width: 4.5rem; }
  .luna-rail.navbar-vertical ~ .page-wrapper { margin-left: 4.5rem; }
  .luna-rail .nav-link-title,
  .luna-rail .luna-brand-text { display: none; }
  .luna-rail .luna-nav-letter,
  .luna-rail .luna-brand-letter { display: inline-flex; }
  /* MUST out-specify Tabler's own
     `.navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav .nav-link`
     (0,5,0), which sets `padding: .5rem 16px; justify-content: flex-start`.
     The old `.luna-rail .nav-link` was only (0,2,0) and lost, so in the
     rail every row kept 16px of side padding. On a 40px .nav-link that
     leaves an 8px content box, and the icon was boxed into it: measured
     8.45px on a deployed app while `width: 24px` was set and
     flex-shrink was 0. It read as "icons get smaller when collapsed",
     and it was never a size or opacity problem at all. Six classes here
     beats Tabler's five outright rather than relying on source order. */
  .luna-rail.navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav .nav-link,
  .luna-rail .nav-link {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  .luna-rail .navbar-brand { justify-content: center; }
  /* A 4.5rem rail cannot show a nested group, so collapse the whole
     sub-list and its caret rather than letting the children wrap. The
     parent row stays, and expanding the sidebar brings them back. */
  .luna-rail [id^="luna-nav-group-"] { display: none !important; }
  .luna-rail .nav-link-toggle { display: none; }
  /* Icons carry a baked width/height from <x-luna.icon :size>, which is
     sized for a labelled row and reads as tiny once it is the only thing
     in the row. Scale them up for the rail. */
  /* Full strength in the rail. The base rule dims the glyph to .65
     because beside a label it is a quiet accent and the WORDS carry
     the row. Collapsed, the icon IS the label, and .65 on a dark
     sidebar reads washed out, which is perceived as "too small" even
     at 24px. Measured: the size rule was applying correctly the whole
     time; opacity was the actual complaint. */
  .luna-rail .luna-nav-icon { width: 24px; height: 24px; opacity: 1; }
  .luna-rail .luna-nav-letter, .luna-rail .luna-brand-letter { width: 30px; height: 30px; font-size: .85rem; }
  /* Desktop sidebar collapse control (Appearance -> Desktop Sidebar).
     The caret is drawn from borders rather than an icon font so the
     control has no asset dependency (air-gap safe). currentColor keeps
     it legible on every sidebar surface -- the same trap that made the
     mobile hamburger invisible on a dark sidebar. */
  /* Collapse control. currentColor everywhere so the glyph stays legible
     on any Style -> Sidebar surface; a fixed colour is what made the
     mobile hamburger invisible on a dark sidebar. */
  .luna-sidebar-collapse-btn {
    border: 0; background: transparent; color: inherit; padding: 0;
    width: 2rem; height: 2rem; display: inline-flex;
    align-items: center; justify-content: center; border-radius: 6px;
  }
  .luna-sidebar-collapse-btn:hover { background: rgba(128, 128, 128, .16); }
  .luna-trigger-bar { padding: .5rem .75rem 0; color: var(--tblr-body-color); }
  /* 'Hide completely': slide the fixed sidebar off the left edge and give
     its 15rem back to the content. Mirrors Tabler's own
     `.navbar-vertical ~ .page-wrapper { margin-left: 15rem }`. */
  .luna-sidebar-hidden.navbar-vertical { margin-left: -15rem; }
  .luna-sidebar-hidden.navbar-vertical ~ .page-wrapper { margin-left: 0; }
  .navbar-vertical { transition: width .2s ease, margin-left .2s ease; }
  .navbar-vertical ~ .page-wrapper { transition: margin-left .2s ease; }
  /* The title is hidden here, so the icon's trailing margin would push
     the only remaining child off-centre in a 4.5rem rail. */
  .luna-rail .luna-nav-icon { margin-inline-end: 0; }
}

/* Mobile horizontal-overflow guard. A card grid's negative row gutters,
   an unbroken token, or a wide child must never push the page past the
   viewport (reported: a sidebar page scrolled to 394px on a 390px screen).
   `clip` (not `hidden`) trims the few px of gutter slop without creating a
   scroll container, so position:sticky chrome keeps working. The grid
   children also get min-width:0 so a wide cell shrinks instead of pushing. */
@media (max-width: 991.98px) {
  .page-wrapper { overflow-x: clip; }
  .card-grid-block,
  .card-grid-block > .row > [class*="col"] { min-width: 0; }
}
/**
 * Presentation tokens, generated by Luna.
 * Do not hand-edit.
 * page_preset=standard, page_background=default
 */
:root {
    --app-page-preset: 'standard';
    --app-content-surface: 'cards';
    --app-panel-shadow: var(--tblr-box-shadow-sm);
    --app-panel-radius: var(--tblr-border-radius-lg);
    --app-panel-body-padding: 1rem 1.25rem;

}

/* ── Panel body padding (Style → Panel padding) ───────────────────────── */
.luna-panel .card-body,
.luna-panel .luna-panel-body {
    padding: var(--app-panel-body-padding);
}

/* ── Table row hover (Style → Table row hover) ────────────────────────── */
.luna-panel .table tbody tr:hover { background-color: var(--luna-surface-muted); }

/* ── Generated-app breadcrumbs (.luna-breadcrumbs) ───────────────────── */
/* Separator rendered via CSS ::before — no explicit separator <li> needed */

/* Contained breadcrumb bar — radius follows Appearance settings; the
   shadow is pinned to the Tabler card token so the bar matches the
   .luna-panel/.card surface directly below it (issue #122). */
.luna-breadcrumbs-bar {
    display: flex;
    align-items: center;
    padding: 9px 14px;
    background: var(--tblr-card-bg, #fff);
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: var(--app-panel-radius);
    box-shadow: var(--tblr-shadow-card, 0 0 4px rgba(0, 0, 0, 0.04));
    margin-bottom: 1rem;
    min-width: 0;
}

.luna-breadcrumbs-nav {
    min-width: 0;
    flex: 1;
}

.luna-breadcrumbs.breadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    padding: 0;
    margin-bottom: 0;
    list-style: none;
    /* em (not rem) so crumbs track the app font-scale and stay
       proportionate with the menu/body; ~14px at the default scale,
       matching the 14px home icon. */
    font-size: 0.875em;
    gap: 0;
}

.luna-breadcrumbs .breadcrumb-item {
    display: inline-flex;
    align-items: center;
    padding-left: 0;
}

.luna-breadcrumbs .breadcrumb-item + .breadcrumb-item::before {
    content: "";
    float: none;
    display: inline-block;
    width: 5px;
    height: 5px;
    border-top: 1.5px solid var(--tblr-border-color, #d0d5dd);
    border-right: 1.5px solid var(--tblr-border-color, #d0d5dd);
    transform: rotate(45deg);
    padding: 0;
    margin: 0 6px;
    flex-shrink: 0;
    background: transparent;
    vertical-align: middle;
}

.luna-breadcrumbs .breadcrumb-link {
    color: var(--tblr-secondary-color, var(--tblr-muted, #6b7280));
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    line-height: 1;
}

.luna-breadcrumbs .breadcrumb-link:hover {
    color: var(--tblr-primary);
    text-decoration: underline;
}

.luna-breadcrumbs .breadcrumb-item.active {
    color: var(--tblr-body-color);
    font-weight: 600;
}

/* ── Show / Detail view layout (generated by Luna) */
.luna-detail-group {
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: var(--app-panel-radius, 6px);
    overflow: hidden;
}

.luna-detail-group-header {
    padding: 0.5rem 1rem;
    background: var(--tblr-bg-surface-secondary, #f6f8fb);
    border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tblr-secondary, #6c757d);
}

.luna-detail-row {
    display: grid;
    grid-template-columns: minmax(120px, 38%) 1fr;
    padding: 0.625rem 1rem;
    border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
    min-width: 0;
    gap: 0.75rem;
    align-items: start;
}

.luna-detail-row:last-child {
    border-bottom: none;
}

.luna-detail-label {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--tblr-secondary, #6c757d);
    min-width: 0;
    overflow-wrap: anywhere;
    padding-top: 1px;
}

.luna-detail-value {
    font-size: 0.875rem;
    color: var(--tblr-body-color, #1d273b);
    min-width: 0;
    overflow-wrap: anywhere;
}

.luna-detail-value--rich {
    padding: 0.125rem 0;
}

.luna-detail-empty {
    color: var(--tblr-muted, #adb5bd);
}

@media (max-width: 480px) {
    .luna-detail-row {
        grid-template-columns: 1fr;
        gap: 0.125rem;
        padding: 0.5rem 0.875rem;
    }
    .luna-detail-label {
        font-size: 0.75rem;
    }
}

/* GEN-DESIGN-PACK Phase 1 — status-pill glyphs, avatar cells,
   note callouts, show-header meta. */
.luna-pill-glyph {
    /* An inline <svg> contributes NOTHING to its inline-block parent's
       min-content width, so a squeezed table column sizes a status pill
       as if the glyph were zero-wide — and Tabler's `.badge` is
       `overflow: hidden`, so the LABEL is then silently clipped rather
       than overflowing ("Completed" rendered as a cut-off "Complete").
       Reserving the glyph's box puts it back into the intrinsic width.
       It must be a LENGTH: min-width fit-content / max-content resolve
       to 0 on a replaced element and fix nothing. Kept equal to the
       SVG's own width attribute via StatusPillGlyphs::GLYPH_PX. */
    min-width: 12px;
    margin-right: 0.3em;
    vertical-align: -0.125em;
}

/* Safety net for the same trap: if a pill is still narrower than its
   label (a long label in a hard-constrained cell), truncate visibly
   instead of cutting the word off mid-glyph. Inert unless the badge is
   already overflowing, so it changes nothing that fits. */
.badge {
    text-overflow: ellipsis;
}

.luna-avatar-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.luna-avatar-cell .avatar {
    flex-shrink: 0;
    background: var(--tblr-secondary-lt, #e9ecef);
    color: var(--tblr-secondary, #6c757d);
    font-weight: 600;
}

.luna-callout {
    background: var(--tblr-warning-lt, #fdf3d8);
    border-radius: var(--tblr-border-radius, 0.375rem);
    padding: 0.625rem 0.875rem;
}

.luna-show-meta {
    font-size: 0.8125rem;
    line-height: 1.6;
    flex-shrink: 0;
}

        /* ── Page background (Style → Page background) ── */
        body, .page-wrapper { background-color: var(--tblr-bg-surface-secondary, #f6f8fb); }

        /* ── Sidebar surface (Style → Sidebar surface) — overrides theme ── */
        .navbar-vertical { background-color: var(--luna-surface) !important; }
        .navbar-vertical .nav-link, .navbar-vertical .navbar-brand, .navbar-vertical .nav-link-title, .navbar-vertical .navbar-toggler, .navbar-vertical .luna-sidebar-collapse-btn { color: var(--luna-text) !important; }

        /* ── Active nav item — readable fill, computed ink ── */
        .navbar-vertical .nav-link.active { background: #7E22CE !important; color: #ffffff !important; }
        .navbar-vertical .nav-link.active .luna-nav-icon { opacity: 1; }
        .navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav .nav-item.active:after { display: none; }

        /* ── Active nav item, dark rail — brand fill would vanish ── */
        [data-bs-theme="dark"] .navbar-vertical .nav-link.active,
        .navbar-vertical[data-bs-theme="dark"] .nav-link.active { background: rgba(255, 255, 255, 0.16) !important; color: #ffffff !important; }

        /* ── Sidebar depth: glow (Style → Sidebar depth) ── */
        .navbar-vertical .nav-link { border-radius: 12px; margin: 3px 0.5rem; transition: box-shadow .18s ease, transform .18s ease, background-color .18s ease; }
        .navbar-vertical .nav-link:hover { box-shadow: 0 3px 10px rgba(0, 0, 0, 0.10); }
        .navbar-vertical .nav-link.active { box-shadow: 0 0 0 1px rgba(var(--tblr-primary-rgb, 27, 42, 74), 0.35), 0 6px 18px -2px rgba(var(--tblr-primary-rgb, 27, 42, 74), 0.55); transform: translateY(-1px); }

        /* ── Panel presets (Style → Panel style) ── */
        .luna-panel.luna-panel-flat { box-shadow: none; }
        .luna-panel.luna-panel-sectioned { box-shadow: none; }
        .luna-panel.luna-panel-sectioned > .luna-panel-header { border-bottom: 1px solid var(--tblr-border-color, #e6e7e9); }
        .luna-panel.luna-panel-compact > .luna-panel-header { padding-top: 0.5rem; padding-bottom: 0.5rem; }
        .luna-panel.luna-panel-compact .luna-panel-title { font-size: 0.875rem; }
        .luna-panel.luna-panel-muted_header > .luna-panel-header { background: var(--tblr-bg-surface-secondary, #f6f8fb); }
        .luna-panel.luna-panel-frameless { border: none; box-shadow: none; border-radius: 0; }
        .luna-panel.luna-panel-frameless > .luna-panel-header { display: none; }
        .luna-panel.luna-panel-sticky_actions > .luna-panel-footer { position: sticky; bottom: 0; background: var(--tblr-card-bg, #ffffff); z-index: 5; }


/* Part 4 — Luna component library (identical in every generated app) */
/**
 * luna-ui.css — static component CSS for generated apps.
 *
 * GENERATED-APP-UI-KIT-V1 §5 Part 2 / §7.4.
 *
 * CONTRACT (enforced by LunaCssTokenContractTest):
 *   - Every visual value (colour, radius, shadow, spacing, type size) resolves
 *     from a var(--luna-*) token declared by App\Support\Theming\LunaTokens.
 *     No hex, no rgba(), no px for a visual property. Hairline widths and
 *     structural values (flex, grid, position) are literal by design: they
 *     define shape, not skin.
 *   - Class prefix is luna-* throughout. The platform LP Kit keeps lp-* until
 *     the rename pass (GENERATED-APP-UI-KIT-V1 §10).
 *   - Standalone CSS. No Sass, no PostCSS, no build step, no @import, and no
 *     external host of any kind (rule R4). Fonts arrive via the vendored
 *     per-family stylesheet, never an @font-face here.
 *
 * This file is copied VERBATIM into every generated app's public/css/luna.css.
 * It is byte-identical across every app regardless of theme, which is what lets
 * the per-app token block be the only thing that differs.
 */

/* ── Icon ─────────────────────────────────────────────────────────────────── */

.luna-icon {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    vertical-align: -0.125em;
    stroke-width: 1.75;
}

/* ── Button ───────────────────────────────────────────────────────────────── */

/* Same geometry as Tabler's .btn above, so a kit button and a generated
   Tabler button are indistinguishable side by side. */
.luna-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 34px;
    padding: 0 14px;
    border: 1px solid transparent;
    border-radius: var(--luna-radius-lg);
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}

.luna-btn:focus-visible {
    outline: var(--luna-focus-ring-width) solid var(--luna-focus-ring-color);
    outline-offset: 2px;
}

.luna-btn:disabled,
.luna-btn.is-disabled {
    opacity: .55;
    cursor: not-allowed;
}

.luna-btn--primary {
    background: var(--luna-primary-600);
    border-color: var(--luna-primary-600);
    color: var(--luna-surface);
}

.luna-btn--primary:hover:not(:disabled) {
    background: var(--luna-primary-700);
    border-color: var(--luna-primary-700);
}

.luna-btn--secondary {
    background: var(--luna-surface);
    border-color: var(--luna-border-strong);
    color: var(--luna-text);
}

.luna-btn--secondary:hover:not(:disabled) {
    background: var(--luna-neutral-50);
}

.luna-btn--ghost {
    background: transparent;
    border-color: transparent;
    color: var(--luna-text-muted);
}

.luna-btn--ghost:hover:not(:disabled) {
    background: var(--luna-neutral-100);
    color: var(--luna-text);
}

.luna-btn--danger {
    background: var(--luna-danger-600);
    border-color: var(--luna-danger-600);
    color: var(--luna-surface);
}

.luna-btn--danger:hover:not(:disabled) {
    background: var(--luna-danger-700);
    border-color: var(--luna-danger-700);
}

.luna-btn--danger-outline {
    background: transparent;
    border-color: var(--luna-danger-200);
    color: var(--luna-danger-600);
}

.luna-btn--danger-outline:hover:not(:disabled) {
    background: var(--luna-danger-50);
}

.luna-btn--link {
    background: transparent;
    border-color: transparent;
    color: var(--luna-primary-600);
    padding-left: 0;
    padding-right: 0;
}

.luna-btn--link:hover:not(:disabled) {
    text-decoration: underline;
}

.luna-btn--sm {
    height: 28px;
    padding: 0 10px;
    font-size: 12px;
    gap: 4px;
}

.luna-btn--xs {
    padding: var(--luna-space-1) var(--luna-space-2);
    font-size: var(--luna-text-xs);
}

.luna-btn--icon {
    padding: var(--luna-space-2);
}

/* Loading state. Alpine toggles .is-loading via x-bind:class — never a
   Livewire directive, which does not exist in a generated app. */
.luna-btn.is-loading {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}

.luna-btn.is-loading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 1em;
    height: 1em;
    margin: -0.5em 0 0 -0.5em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    color: var(--luna-surface);
    animation: luna-spin .6s linear infinite;
}

.luna-btn--secondary.is-loading::after,
.luna-btn--ghost.is-loading::after,
.luna-btn--link.is-loading::after {
    color: var(--luna-text-muted);
}

@keyframes luna-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .luna-btn { transition: none; }
    .luna-btn.is-loading::after { animation-duration: 2s; }
}

/* ── Status pill ──────────────────────────────────────────────────────────── */

.luna-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--luna-space-1);
    padding: var(--luna-space-1) var(--luna-space-3);
    border-radius: var(--luna-radius-lg);
    font-size: var(--luna-text-xs);
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
}

.luna-pill--neutral { background: var(--luna-neutral-100); color: var(--luna-neutral-700); }
.luna-pill--primary { background: var(--luna-primary-50);  color: var(--luna-primary-700); }
.luna-pill--success { background: var(--luna-success-50);  color: var(--luna-success-700); }
.luna-pill--warning { background: var(--luna-warning-50);  color: var(--luna-warning-700); }
.luna-pill--danger  { background: var(--luna-danger-50);   color: var(--luna-danger-700); }
.luna-pill--info    { background: var(--luna-info-50);     color: var(--luna-info-600); }

/* ── Panel ────────────────────────────────────────────────────────────────── */

/* :where() holds this base rule at ZERO specificity. `.luna-panel` is ALREADY
   emitted on every generated card alongside Tabler's `.card` (the panel
   component emits "card luna-panel luna-panel-radius-{x} …"), so an unscoped
   rule here would silently outrank both Tabler's card styling and the per-app
   panel-preset CSS in Part 3 — a Creator who set a panel radius would have it
   overridden by the component library. At zero specificity any real rule wins,
   so the kit supplies defaults without ever fighting per-app settings.

   NO overflow:hidden. Tabler's .card deliberately omits it, and clipping every
   panel would trap absolutely-positioned children (menus, popovers, focus
   rings) at the panel edge. Corner rounding is handled by the inner-radius
   :where() rules below, which is exactly why the spec chose Pattern A. */
:where(.luna-panel) {
    background: var(--luna-surface);
    border: 1px solid var(--luna-border-color);
    border-radius: var(--luna-radius-xl);
    box-shadow: var(--luna-shadow-sm);
}

/* Inner-radius pattern A: the first and last direct children inherit the
   panel's corner rounding so a flush table or list never square-corners
   against a rounded panel. :where() keeps specificity at zero so any
   component rule can still override it. */
.luna-panel > :where(:first-child) {
    border-top-left-radius: calc(var(--luna-radius-xl) - 1px);
    border-top-right-radius: calc(var(--luna-radius-xl) - 1px);
}

.luna-panel > :where(:last-child) {
    border-bottom-left-radius: calc(var(--luna-radius-xl) - 1px);
    border-bottom-right-radius: calc(var(--luna-radius-xl) - 1px);
}

.luna-panel__head {
    display: flex;
    align-items: flex-start;
    gap: var(--luna-space-3);
    padding: var(--luna-space-4) var(--luna-space-5);
    border-bottom: 1px solid var(--luna-border-color);
}

.luna-panel__icon {
    flex-shrink: 0;
    color: var(--luna-text-muted);
}

.luna-panel__heading {
    flex: 1;
    min-width: 0;
}

.luna-panel__title {
    margin: 0;
    font-size: var(--luna-text-md);
    font-weight: var(--luna-heading-weight);
    letter-spacing: var(--luna-heading-tracking);
    color: var(--luna-text);
}

.luna-panel__subtitle {
    margin: var(--luna-space-1) 0 0;
    font-size: var(--luna-text-sm);
    color: var(--luna-text-muted);
}

.luna-panel__actions {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    gap: var(--luna-space-2);
}

.luna-panel__body {
    padding: var(--luna-space-5);
}

.luna-panel__foot {
    display: flex;
    align-items: center;
    gap: var(--luna-space-2);
    padding: var(--luna-space-4) var(--luna-space-5);
    border-top: 1px solid var(--luna-border-color);
    background: var(--luna-surface-muted);
}

.luna-panel--flush .luna-panel__body { padding: 0; }

/* ── Empty state ──────────────────────────────────────────────────────────── */

.luna-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--luna-space-6) var(--luna-space-5);
    color: var(--luna-text-muted);
}

.luna-empty__icon {
    margin-bottom: var(--luna-space-3);
    color: var(--luna-neutral-400);
}

.luna-empty__title {
    margin: 0 0 var(--luna-space-1);
    font-size: var(--luna-text-md);
    font-weight: var(--luna-heading-weight);
    color: var(--luna-text);
}

.luna-empty__body {
    margin: 0;
    font-size: var(--luna-text-sm);
    max-width: 42ch;
}

.luna-empty__actions { margin-top: var(--luna-space-4); }

/* ── Avatar ───────────────────────────────────────────────────────────────── */

.luna-avatar {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-weight: 600;
    line-height: 1;
    overflow: hidden;
}

.luna-avatar--soft  { background: var(--luna-primary-50); color: var(--luna-primary-700); }
.luna-avatar--solid { background: var(--luna-primary-600); color: var(--luna-surface); }

.luna-avatar--sm { width: 1.75rem; height: 1.75rem; font-size: var(--luna-text-xs); }
.luna-avatar--md { width: 2.25rem; height: 2.25rem; font-size: var(--luna-text-sm); }
.luna-avatar--lg { width: 3rem;    height: 3rem;    font-size: var(--luna-text-md); }

.luna-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* ── Stats ────────────────────────────────────────────────────────────────── */

.luna-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: var(--luna-space-4);
}

.luna-stat {
    padding: var(--luna-space-4);
    background: var(--luna-surface);
    border: 1px solid var(--luna-border-color);
    border-radius: var(--luna-radius-lg);
}

.luna-stat__label {
    font-size: var(--luna-text-xs);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--luna-text-muted);
}

.luna-stat__value {
    margin-top: var(--luna-space-1);
    font-size: var(--luna-text-2xl);
    font-weight: var(--luna-heading-weight);
    letter-spacing: var(--luna-heading-tracking);
    color: var(--luna-text);
    font-variant-numeric: tabular-nums;
}

.luna-stat__hint {
    margin-top: var(--luna-space-1);
    font-size: var(--luna-text-sm);
    color: var(--luna-text-muted);
}

/* ── Notice ───────────────────────────────────────────────────────────────── */

/* LOCK: .luna-notice is flex-row, exactly like Tabler's .alert. Every piece of
   content MUST sit inside ONE inner div (.luna-notice__body), with at most one
   .luna-notice__icon sibling before it. Dropping several block children
   straight in turns them into horizontal flex columns and visually clips the
   last one. Same trap as the Tabler .alert rule in root CLAUDE.md. */
.luna-notice {
    display: flex;
    flex-direction: row;
    gap: var(--luna-space-3);
    padding: var(--luna-space-4);
    border: 1px solid var(--luna-border-color);
    border-radius: var(--luna-radius-md);
    background: var(--luna-surface);
    color: var(--luna-text);
    font-size: var(--luna-text-sm);
}

.luna-notice__icon { flex-shrink: 0; }
.luna-notice__body { flex: 1; min-width: 0; }

.luna-notice__title {
    margin: 0 0 var(--luna-space-1);
    font-weight: var(--luna-heading-weight);
}

.luna-notice--info    { background: var(--luna-info-50);    border-color: var(--luna-info-200);    color: var(--luna-info-600); }
.luna-notice--success { background: var(--luna-success-50); border-color: var(--luna-success-200); color: var(--luna-success-700); }
.luna-notice--warning { background: var(--luna-warning-50); border-color: var(--luna-warning-200); color: var(--luna-warning-700); }
.luna-notice--danger  { background: var(--luna-danger-50);  border-color: var(--luna-danger-200);  color: var(--luna-danger-700); }

/* ── Field ────────────────────────────────────────────────────────────────── */

.luna-field { margin-bottom: var(--luna-space-4); }

.luna-field__label {
    display: block;
    margin-bottom: var(--luna-space-1);
    font-size: var(--luna-text-sm);
    font-weight: 500;
    color: var(--luna-text);
}

.luna-field__required {
    margin-left: 0.15em;
    color: var(--luna-danger-600);
}

.luna-field__hint {
    margin-top: var(--luna-space-1);
    font-size: var(--luna-text-xs);
    color: var(--luna-text-muted);
}

.luna-field__error {
    margin-top: var(--luna-space-1);
    font-size: var(--luna-text-xs);
    color: var(--luna-danger-600);
}

/* ── Breadcrumbs ──────────────────────────────────────────────────────────── */

.luna-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--luna-space-1);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--luna-text-sm);
}

.luna-crumbs__item {
    display: inline-flex;
    align-items: center;
    gap: var(--luna-space-1);
    color: var(--luna-text-muted);
}

.luna-crumbs__link {
    color: var(--luna-text-muted);
    text-decoration: none;
}

.luna-crumbs__link:hover { color: var(--luna-primary-600); text-decoration: underline; }

/* The last crumb is the current page: never a link, and visually settled. */
.luna-crumbs__item[aria-current="page"] {
    color: var(--luna-text);
    font-weight: 500;
}

/* ── Modal ────────────────────────────────────────────────────────────────── */

/* Bootstrap JS owns show/hide here. That is SAFE in a generated app: Zone B has
   no Livewire and therefore no morphdom pass to wipe Bootstrap's DOM state.
   Zone A must use Alpine instead — see the root CLAUDE.md rule. */
.luna-modal__dialog {
    background: var(--luna-surface);
    border-radius: var(--luna-radius-xl);
    box-shadow: var(--luna-shadow-lg);
}

.luna-modal__head {
    display: flex;
    align-items: center;
    gap: var(--luna-space-3);
    padding: var(--luna-space-4) var(--luna-space-5);
    border-bottom: 1px solid var(--luna-border-color);
}

.luna-modal__title {
    margin: 0;
    font-size: var(--luna-text-lg);
    font-weight: var(--luna-heading-weight);
    letter-spacing: var(--luna-heading-tracking);
}

.luna-modal__body { padding: var(--luna-space-5); }

.luna-modal__foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--luna-space-2);
    padding: var(--luna-space-4) var(--luna-space-5);
    border-top: 1px solid var(--luna-border-color);
}

/* ── Page header ──────────────────────────────────────────────────────────── */

/* Emitted by App\Services\Presentation\PageHeaderRenderer — the ONE page-header
   producer (VISUAL-UPLIFT-V1 R3). Breadcrumbs sit ABOVE the title; the bar below
   carries the eyebrow, title, record count, status, description and actions. */
:where(.luna-pagehead) {
    padding-bottom: var(--luna-space-4);
    margin-bottom: var(--luna-space-4);
    border-bottom: 1px solid var(--luna-border-color);
}

.luna-pagehead__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--luna-space-3);
}

/* actions.placement = below */
.luna-pagehead__bar--stack { flex-direction: column; }

.luna-pagehead__main { flex: 1; min-width: 0; }

.luna-pagehead__eyebrow {
    font-size: var(--luna-text-xs);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--luna-text-muted);
    margin-bottom: var(--luna-space-1);
}

.luna-pagehead__titlerow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--luna-space-2);
    min-width: 0;
}

/* Also carries Tabler's .page-title, whose own rules still apply; these win on
   the properties they set because luna.css loads last. */
.luna-pagehead__title {
    margin: 0;
    font-size: var(--luna-text-2xl);
    font-weight: var(--luna-heading-weight);
    letter-spacing: var(--luna-heading-tracking);
    color: var(--luna-text);
    min-width: 0;
    overflow-wrap: anywhere;
}

.luna-pagehead__count {
    padding: var(--luna-space-1) var(--luna-space-2);
    border-radius: var(--luna-radius-sm);
    background: var(--luna-neutral-100);
    color: var(--luna-text-muted);
    font-size: var(--luna-text-xs);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.luna-pagehead__description {
    margin: var(--luna-space-1) 0 0;
    font-size: var(--luna-text-sm);
    color: var(--luna-text-muted);
    max-width: 70ch;
}

.luna-pagehead__meta {
    margin-top: var(--luna-space-1);
    font-size: var(--luna-text-xs);
    color: var(--luna-text-muted);
}

.luna-pagehead__actions {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    gap: var(--luna-space-2);
}

/* Compact / minimal styles tighten the same markup rather than changing it. */
.luna-pagehead--compact { padding-bottom: var(--luna-space-2); margin-bottom: var(--luna-space-3); }
.luna-pagehead--compact .luna-pagehead__title { font-size: var(--luna-text-xl); }
.luna-pagehead--minimal { border-bottom: none; padding-bottom: 0; }
.luna-pagehead--split .luna-pagehead__bar { justify-content: space-between; }

/* No title block was rendered, so the divider and the padding beneath it have
   nothing to divide — without this the breadcrumb trail sits above a stray rule. */
.luna-pagehead--hidden { border-bottom: none; padding-bottom: 0; }

/* The breadcrumb bar sits inside the header now, so it drops its own framing
   and spacing — two stacked bordered boxes read as a mistake. */
.luna-pagehead .luna-breadcrumbs-bar {
    padding: 0;
    margin-bottom: var(--luna-space-2);
    background: transparent;
    border: 0;
    box-shadow: none;
}

/* With no title block the trail also drops its own gap: the wrapper's
   margin-bottom is already the space before the content. This MUST stay below
   the rule above — both selectors are specificity (0,2,0), so the tie is broken
   by source order and hoisting this up the file silently kills it. */
.luna-pagehead--hidden .luna-breadcrumbs-bar { margin-bottom: 0; }

/* With the title block suppressed the page's actions still render, on their own
   rail. A style option must not delete function: "+ Add User" lives in the
   header slot, so dropping it made the only way to create a user unreachable.
   Right-aligned, and spaced off the trail above it since the trail zeroes its
   own margin under --hidden. */
.luna-pagehead__actionbar {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--luna-space-2);
}

@media (max-width: 575.98px) {
    .luna-pagehead__actions--collapse {
        width: 100%;
    }
    .luna-pagehead__actions--collapse > * { flex: 1; }
}


/* ── Data table polish ────────────────────────────────────────────────────── */

/* VISUAL-UPLIFT-V1 §8.4/§8.5. All :where()-scoped at zero specificity: these
   selectors target Tabler's own .table inside a Luna panel, and a per-app rule
   or a Creator override must always win over the component library. */

/* NO global sticky-header rule here, deliberately.
   A per-list `sticky_header` display setting already exists and is honoured by
   DataTablesListBladeGenerator::buildStylesPush(), which emits a table-scoped
   inline style only when the Creator turns it on. A global rule here made that
   control a no-op — the table was sticky whether the toggle was on or off —
   which is the "control the generator ignores" defect in reverse. It also broke
   the column-header search: both <thead> rows would anchor to top:0 and overlap,
   because sticky siblings do not auto-stack. */

/* Row hover gets a brand accent bar rather than only a wash, so the pointed-at
   row is identifiable at a glance on a wide table. box-shadow rather than a
   border, so the row height never shifts on hover. */
:where(.luna-panel .table tbody tr) {
    transition: background-color .12s ease;
}

:where(.luna-panel .table tbody tr:hover td:first-child) {
    box-shadow: inset 3px 0 0 var(--luna-primary-600);
}

/* Numbers line up only with tabular figures; proportional digits make a column
   of amounts ragged and hard to compare down the page.

   Typography ONLY — deliberately no text-align. Column alignment is an explicit
   Creator control (AppListField::alignment) with an "auto" default, and a
   generator silently right-aligning numerics would override a setting the
   Creator had made. Same mistake as the global sticky-header rule removed
   above. */
:where(.luna-panel .table td.luna-num),
:where(.luna-panel .table th.luna-num) {
    font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
    :where(.luna-panel .table tbody tr) { transition: none; }
}


/* Row actions. A cell of buttons must be measured by its RENDERED buttons, not
   by its text: DataTables sizes every column from a tag-stripped string
   (_fnGetMaxLenString), so an actions cell is measured as its bare labels —
   "ViewEdit" — with no allowance for button padding, icons or the flex gap, and
   that under-measured width is written into the table's <colgroup>. The flex
   row then has to fit a width that was never meant for it: labels clip at the
   cell edge, icons collapse, or the row spills past the cell and is cut off by
   the panel. A min-content floor pins the cell to what the buttons actually
   need, which outranks the colgroup guess; a table too wide for its container
   still falls through to the .table-responsive scroller. */
.luna-row-actions {
    min-width: max-content;
}

.luna-row-actions > * {
    flex-shrink: 0;
}


/* ── Data-table toolbar ───────────────────────────────────────────────────── */

/* The length select, search box, info line and pagination that DataTables emits
   around the table (VISUAL-UPLIFT-V1 §8.6). Class names are the DataTables 2.x
   layout markup (.dt-length / .dt-search / .dt-info / .dt-paging) that the
   vendored dataTables.bootstrap5 build produces.

   Presentation ONLY. Whether these controls exist at all is already decided by
   Creator settings (page_length_menu, the search box, column_header_search), and
   the strings inside them come from ListEmptyStateCompiler. Styling the
   container changes none of that. All :where()-scoped so a per-app rule wins,
   and all scoped INSIDE .luna-panel so nothing leaks to a table elsewhere. */

:where(.luna-panel .dt-layout-start),
:where(.luna-panel .dt-layout-end) {
    display: flex;
    align-items: center;
    gap: var(--luna-space-2);
}

/* Small, quiet labels — these are chrome, not content, and should not compete
   with the data below them. */
:where(.luna-panel .dt-length label),
:where(.luna-panel .dt-search label),
:where(.luna-panel .dt-info) {
    color: var(--luna-text-muted);
    font-size: var(--luna-text-sm);
    margin-bottom: 0;
}

:where(.luna-panel .dt-length select),
:where(.luna-panel .dt-search input) {
    border: 1px solid var(--luna-border-color);
    border-radius: var(--luna-radius-md);
    background: var(--luna-surface);
    color: var(--luna-text);
    font-size: var(--luna-text-sm);
    padding: var(--luna-space-1) var(--luna-space-2);
}

:where(.luna-panel .dt-length select:focus),
:where(.luna-panel .dt-search input:focus) {
    outline: var(--luna-focus-ring-width) solid var(--luna-focus-ring-color);
    outline-offset: 1px;
    border-color: var(--luna-primary-600);
}

:where(.luna-panel .dt-search input)::placeholder {
    color: var(--luna-neutral-400);
}

/* Pagination reads as one connected control rather than scattered links. */
:where(.luna-panel .dt-paging .page-link) {
    border-color: var(--luna-border-color);
    color: var(--luna-text);
    font-size: var(--luna-text-sm);
}

:where(.luna-panel .dt-paging .page-item.active .page-link) {
    background: var(--luna-primary-600);
    border-color: var(--luna-primary-600);
    color: var(--luna-surface);
}

:where(.luna-panel .dt-paging .page-item.disabled .page-link) {
    color: var(--luna-neutral-400);
}


/* ── Form controls ────────────────────────────────────────────────────────── */

/* An input's border is what tells a user the field is editable, so WCAG 1.4.11
   sets a 3:1 floor for it — unlike a panel edge, which is decoration and is
   allowed to be faint. Tabler ships #dce1e7 (1.32:1) and the generated forms
   consequently read as borderless. --luna-border-input clears the floor.

   Deliberately NOT driven by the Style tab's border-strength control: that moves
   the decorative hairline, and an accessibility floor is not a style preference.

   :where() keeps this at zero specificity so the `input_style` control still
   wins — its `underline` mode legitimately removes the box border, and `filled`
   changes the fill. This sets the COLOUR those modes draw with, not the shape. */
/* NOT :where() here, and that distinction is the whole fix. Tabler's own
   `.form-control` rule sets `border: ... solid var(--tblr-border-color)` at
   specificity (0,1,0). A :where()-wrapped rule is (0,0,0), so it LOSES to
   Tabler no matter what order the files load in — the first version of this
   fix shipped and did nothing at all.

   Matching Tabler's (0,1,0) means source order decides, and luna.css loads
   after tabler.min.css, so this wins. The input_style control still overrides
   it because that uses `.luna-panel :is(.form-control, …)` at (0,2,0). */
.form-control,
.form-select,
.form-check-input,
textarea.form-control {
    border-color: var(--luna-border-input);
}

.form-control:hover,
.form-select:hover {
    border-color: var(--luna-border-input-hover);
}

/* ── Buttons (Tabler .btn parity with the Builder) ────────────────────────── */

/* Generated views emit Tabler's `.btn btn-primary`, not the kit class, so the
   geometry has to land on `.btn` for the app to match the Builder. Mirrors the
   platform's own .btn block (app.css): 34px tall, 13px/500, 14px side padding,
   inline-flex with a gap.

   COLOUR IS NOT COPIED. The Builder's button is platform purple; a generated
   app's button must stay the AGENCY's brand, which var(--luna-primary-600)
   already resolves to. Copying the Builder's hue here would repaint every
   customer's app in Luna's colours. */
/* Also NOT :where(): Tabler's `.btn` is (0,1,0) and would outrank a
   zero-specificity rule. See the form-control note above. */
.btn {
    height: 34px;
    padding: 0 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 500;
    border-radius: var(--luna-radius-lg);
}

/* Row actions use .btn-sm and must stay compact — a blanket 34px would make a
   table row chunky. Tabler does not set a height of its own, so without this the
   rule above would apply to them too. */
.btn-sm {
    height: 28px;
    padding: 0 10px;
    font-size: 12px;
    gap: 4px;
}

/* An icon-only button should be square, not a 34x34 pill with a stretched glyph. */
.btn-icon {
    width: 34px;
    padding: 0;
}

.btn-sm.btn-icon {
    width: 28px;
}


/* ── Confirm dialog ───────────────────────────────────────────────────────── */

/* Emitted by App\Support\Generate\ConfirmDialog. Generated apps have no
   Livewire, so this is the Zone B equivalent of <x-luna.confirm-button>:
   pure Alpine, with the full ARIA dialog contract. Native confirm() is banned
   (it can be permanently suppressed by the browser, after which destructive
   actions fire silently). */
:where(.luna-confirm-backdrop) {
    position: fixed;
    inset: 0;
    z-index: 1060;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--luna-space-4);
    background: var(--luna-overlay-bg);
}

:where(.luna-confirm) {
    width: 100%;
    max-width: 32rem;
    text-align: left;
}


/* ── Auth shell ───────────────────────────────────────────────────────────── */

/*
 * The chrome shared by every generated-app auth page (OTP login, password
 * login, forgot, reset, register). One capped, centred row: brand on the left,
 * the form card on the right. Below the stack breakpoint the brand column is
 * hidden and `.luna-auth__compact` takes over above the card, which is the
 * single-column layout these pages have always had on a phone.
 *
 * Every colour resolves from the app's own primary/neutral tokens, so a
 * Creator's theme drives the page. Nothing here is Luna-purple.
 */

.luna-auth {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    background: var(--luna-body-bg);
}

/* Decorative wash. Flat token tints rather than an opacity on a strong colour,
   so the fill stays theme-derived and needs no rgba(). */
.luna-auth::before,
.luna-auth::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    background: var(--luna-primary-100);
    pointer-events: none;
}

.luna-auth::before {
    top: -8rem;
    right: -8rem;
    width: 27rem;
    height: 27rem;
}

.luna-auth::after {
    bottom: -5rem;
    left: -5rem;
    width: 19rem;
    height: 19rem;
}

.luna-auth__body {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--luna-space-6) var(--luna-space-4);
    position: relative;
    z-index: 2;
}

/* Caps the row so the brand and the card stay one centred block instead of
   drifting to opposite edges of a wide monitor. */
.luna-auth__inner {
    width: 100%;
    max-width: 58.75rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--luna-space-6);
}

.luna-auth__brand {
    flex: 1 1 0;
    min-width: 0;
    max-width: 26.25rem;
}

.luna-auth__logo {
    display: block;
    max-height: 3.5rem;
    max-width: 10.625rem;
    margin-bottom: var(--luna-space-4);
}

.luna-auth__name {
    margin: 0 0 var(--luna-space-2);
    font-size: var(--luna-text-2xl);
    font-weight: var(--luna-heading-weight);
    letter-spacing: var(--luna-heading-tracking);
    color: var(--luna-primary-600);
    word-break: break-word;
}

.luna-auth__tagline {
    margin: 0;
    max-width: 22.5rem;
    font-size: var(--luna-text-md);
    line-height: 1.6;
    color: var(--luna-text-muted);
}

/* The illustration is drawn in currentColor, so this one declaration themes it. */
.luna-auth__art {
    margin-top: var(--luna-space-5);
    color: var(--luna-primary-600);
}

.luna-auth__art svg {
    width: 100%;
    max-width: 18.75rem;
    height: auto;
}

/* Branded artwork variant (config luna.runtime.hero_artwork_portrait). Same
   footprint as the SVG so the brand column's height does not jump between the
   two shapes. Rounded + hairline so a full-bleed image reads as a deliberate
   panel rather than a stray screenshot; `display:block` kills the inline-image
   baseline gap that would otherwise offset it from the tagline above. */
.luna-auth__art img {
    display: block;
    width: 100%;
    max-width: 18.75rem;
    height: auto;
    border-radius: var(--luna-radius-lg);
    border: 1px solid var(--luna-border-color);
}

.luna-auth__panel {
    flex: 0 0 26.25rem;
    width: 100%;
    max-width: 26.25rem;
}

.luna-auth__compact { display: none; }

/* 860px: the illustration plus the card stop fitting side by side. */
@media (max-width: 53.75rem) {
    .luna-auth__body { padding: var(--luna-space-5) var(--luna-space-4); }

    .luna-auth__inner {
        flex-direction: column;
        gap: 0;
        max-width: 26.25rem;
    }

    .luna-auth__brand { display: none; }

    .luna-auth__compact {
        display: block;
        text-align: center;
        margin-bottom: var(--luna-space-5);
    }

    .luna-auth__panel { flex: 1 1 auto; }
}

/* ── Auth shell: Login page designer (LOGIN-PAGE-DESIGNER-V1) ───────────────
 *
 * Layout modifiers come from config/luna/login.php via the shell's runtime
 * class list. `luna-auth--split` is the original look and needs no rules of
 * its own. Colours are custom properties set inline from that config
 * (--login-*) or existing theme tokens, never literals, so dark mode and
 * the Creator's theme keep working. Text never sits directly on a photo: in
 * the background layout the header gets its own surface card.
 */

/* Image position, shared by the brand-column image and the backdrop. */
.luna-auth--pos-top .luna-auth__art img,
.luna-auth--pos-top .luna-auth__mobile-banner img { object-position: center top; }
.luna-auth--pos-bottom .luna-auth__art img,
.luna-auth--pos-bottom .luna-auth__mobile-banner img { object-position: center bottom; }
.luna-auth--pos-top .luna-auth__backdrop { background-position: center top; }
.luna-auth--pos-bottom .luna-auth__backdrop { background-position: center bottom; }

/* Split + uploaded image: the photo fills the brand column's art slot. */
.luna-auth--has-image .luna-auth__art img {
    max-width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    box-shadow: var(--luna-shadow-md);
}

/* Split + custom panel colour: the brand column becomes a coloured panel. */
.luna-auth--panel .luna-auth__brand {
    background: var(--login-panel-bg);
    color: var(--login-panel-fg);
    padding: var(--luna-space-6);
    border-radius: var(--luna-radius-xl);
    box-shadow: var(--luna-shadow-md);
}

.luna-auth--panel .luna-auth__name,
.luna-auth--panel .luna-auth__tagline,
.luna-auth--panel .luna-auth__art { color: inherit; }

.luna-auth--panel .luna-auth__tagline { opacity: 0.88; }

/* Centered + background: one column, header above the card at every width. */
.luna-auth--centered .luna-auth__inner,
.luna-auth--background .luna-auth__inner {
    justify-content: center;
    max-width: 26.25rem;
}

.luna-auth--centered .luna-auth__brand,
.luna-auth--background .luna-auth__brand { display: none; }

.luna-auth--centered .luna-auth__compact,
.luna-auth--background .luna-auth__compact {
    display: block;
    text-align: center;
    margin-bottom: var(--luna-space-5);
}

/* Background: the image fills the page behind a brand-tinted overlay. */
.luna-auth__backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* The overlay DARKENS in both themes. Painted from a stop that stays dark:
   the deep brand stop in light, the near-black page background in dark (dark
   mode lifts the primary ramp, so a primary-based overlay would wash the photo
   lighter instead). Opacity is the Creator's "Darken image" value. */
.luna-auth__backdrop::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--luna-primary-800);
    opacity: var(--login-overlay, 0.3);
}

[data-bs-theme="dark"] .luna-auth__backdrop::after {
    background: var(--luna-body-bg);
}

.luna-auth--background::before,
.luna-auth--background::after { display: none; }

.luna-auth--background .luna-auth__compact {
    background: var(--luna-surface);
    border-radius: var(--luna-radius-xl);
    padding: var(--luna-space-5) var(--luna-space-4) var(--luna-space-4);
    box-shadow: var(--luna-shadow-md);
}

.luna-auth--background .luna-auth__help {
    background: var(--luna-surface);
    border-radius: var(--luna-radius-md);
    padding: var(--luna-space-2) var(--luna-space-3);
}

/* Notice above the card, help line under it. */
.luna-auth__notice {
    margin-bottom: var(--luna-space-4);
    padding: var(--luna-space-3) var(--luna-space-4);
    border-radius: var(--luna-radius-md);
    border: 1px solid var(--luna-info-200);
    background: var(--luna-info-50);
    color: var(--luna-info-700);
    font-size: var(--luna-text-sm);
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.luna-auth__notice--warning {
    border-color: var(--luna-warning-200);
    background: var(--luna-warning-50);
    color: var(--luna-warning-700);
}

.luna-auth__help {
    margin: var(--luna-space-4) 0 0;
    text-align: center;
    font-size: var(--luna-text-sm);
    color: var(--luna-text-muted);
    overflow-wrap: anywhere;
}

/* Split image on phones, opt-in: a short banner above the compact header. */
.luna-auth__mobile-banner { display: none; }

@media (max-width: 53.75rem) {
    .luna-auth--mobile-image .luna-auth__mobile-banner {
        display: block;
        margin-bottom: var(--luna-space-4);
    }

    .luna-auth__mobile-banner img {
        display: block;
        width: 100%;
        height: 8.75rem;
        object-fit: cover;
        border-radius: var(--luna-radius-lg);
    }
}

/* ── Print ────────────────────────────────────────────────────────────────── */

@media print {
    .luna-btn,
    .luna-panel__actions,
    .luna-crumbs { display: none !important; }

    .luna-panel {
        border-color: var(--luna-neutral-300);
        box-shadow: none;
    }
}
