/* ==========================================================================
   Kautsar Design System
   Tokens -> Foundations -> Components -> Patterns -> Screens
   See docs/04-design/DESIGN_SYSTEM.md
   ========================================================================== */

:root {
    /* Color: primary scale */
    --color-primary-50: #eff6ff;
    --color-primary-100: #dbeafe;
    --color-primary-500: #2563eb;
    --color-primary-600: #1d4ed8;
    --color-primary-700: #1e40af;

    /* Color: neutral scale */
    --color-neutral-0: #ffffff;
    --color-neutral-50: #f8fafc;
    --color-neutral-100: #f1f5f9;
    --color-neutral-200: #e2e8f0;
    --color-neutral-300: #cbd5e1;
    --color-neutral-400: #94a3b8;
    --color-neutral-500: #64748b;
    --color-neutral-600: #475569;
    --color-neutral-700: #334155;
    --color-neutral-800: #1e293b;
    --color-neutral-900: #0f172a;
    --color-neutral-950: #0b1120;

    /* Color: semantic */
    --color-success-bg: #ecfdf3;
    --color-success-border: #abefc6;
    --color-success-text: #067647;
    --color-warning-bg: #fffaeb;
    --color-warning-border: #fedf89;
    --color-warning-text: #b54708;
    --color-error-bg: #fef3f2;
    --color-error-border: #fecdca;
    --color-error-text: #b42318;
    --color-info-bg: #eff8ff;
    --color-info-border: #b2ddff;
    --color-info-text: #175cd3;

    /* Color: decisive solid variants - status/action indicators use these instead of the soft
       tints above, per design direction: black/gray as the base language, with strong,
       unambiguous green for active and red for inactive/delete/reject. Not "colorful". */
    --color-success-solid: #15803d;
    --color-success-solid-hover: #166534;
    --color-error-solid: #b91c1c;
    --color-error-solid-hover: #991b1b;
    --color-dark-solid: var(--color-neutral-800);
    --color-dark-solid-hover: var(--color-neutral-900);

    /* Color: module accents (decorative, not status semantics) */
    --accent-blue-bg: #eff6ff;
    --accent-blue-fg: #2563eb;
    --accent-green-bg: #ecfdf5;
    --accent-green-fg: #059669;
    --accent-orange-bg: #fff7ed;
    --accent-orange-fg: #ea580c;
    --accent-purple-bg: #f5f3ff;
    --accent-purple-fg: #7c3aed;

    /* Surface + text */
    --surface: var(--color-neutral-0);
    --surface-subtle: var(--color-neutral-50);
    --border: var(--color-neutral-200);
    --border-strong: var(--color-neutral-300);
    --text: var(--color-neutral-900);
    --text-muted: var(--color-neutral-500);
    --text-inverse: var(--color-neutral-0);
    --bg: var(--color-neutral-100);
    --focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.35);

    /* Typography */
    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    --text-xs: 0.6875rem;
    --text-sm: 0.75rem;
    --text-md: 0.8125rem;
    --text-base: var(--text-md);
    --text-lg: 0.9375rem;
    --text-xl: 1.125rem;
    --text-2xl: 1.375rem;
    --text-3xl: 1.75rem;
    --leading-tight: 1.25;
    --leading-normal: 1.5;

    /* Spacing scale */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;

    /* Radius + elevation */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --radius-full: 999px;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow-md: 0 4px 16px rgba(15, 23, 42, 0.08);
    --shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.14);

    /* Layout */
    --topbar-height: 60px;
    --content-max-width: 1440px;
    --motion-fast: 150ms ease;
    --motion-normal: 200ms ease;
}

/* ==========================================================================
   Reset + base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* The [hidden] attribute must always win, even over elements whose class sets
   its own `display` (e.g. `.empty-state { display: flex }`) - otherwise author
   CSS silently overrides the browser's default `[hidden] { display: none }`. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; line-height: var(--leading-tight); color: var(--text); }
h1 { font-size: var(--text-2xl); letter-spacing: -0.01em; }
h2 { font-size: var(--text-lg); }
h3 { font-size: var(--text-md); }
p { margin: 0; }

@media (max-width: 599.98px) {
    h1 { font-size: var(--text-xl); }
}

a { color: var(--color-primary-600); }

:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
    border-radius: var(--radius-sm);
}

button, input, select, textarea { font: inherit; color: inherit; }

.muted { color: var(--text-muted); }
.small { font-size: var(--text-sm); }
.visually-hidden {
    position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0;
}

/* ==========================================================================
   Icons
   ========================================================================== */

.icon {
    width: 1.15em;
    height: 1.15em;
    flex-shrink: 0;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
    vertical-align: -0.2em;
}

.icon-lg { width: 1.6em; height: 1.6em; }
.icon-sm { width: 1em; height: 1em; }

/* ==========================================================================
   App shell: three independent floating surfaces + content
   -----------------------------------------------------------------------
   Left context node, floating navigation node and right utility node are
   deliberately three separate cards (own background/border/shadow each)
   inside a plain flex row that itself has none - never a single continuous
   header bar. Real gaps (--space-4) always separate them.
   ========================================================================== */

.app-shell { display: flex; flex-direction: column; min-height: 100vh; }

.main {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.shell-float-row {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    background: transparent;
    position: sticky;
    top: 0;
    z-index: 100;
}

@media (max-width: 599.98px) {
    .shell-float-row { padding: var(--space-3); gap: var(--space-2); }
}

/* -- Shared floating-card look for all three surfaces -- */
.shell-context,
.shell-nav-trigger,
.shell-utility {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

@keyframes mega-menu-in {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: translateY(0); }
}

/* -- LEFT: application/context node -- */

.shell-context {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    min-width: 0;
    height: 44px;
    flex-shrink: 0;
}

.shell-context-brand {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    text-decoration: none;
    color: var(--text);
    flex-shrink: 0;
}

.shell-context-name {
    font-weight: 650;
    font-size: var(--text-lg);
    color: var(--text);
    white-space: nowrap;
}

.shell-context-divider { width: 1px; height: 22px; background: var(--border); flex-shrink: 0; }

.shell-breadcrumb {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: 360px;
    overflow: hidden;
}

.shell-breadcrumb-item { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shell-breadcrumb-item.current { color: var(--text); font-weight: 600; }
.shell-breadcrumb-sep { flex-shrink: 0; color: var(--color-neutral-300); }

@media (max-width: 767.98px) {
    .shell-breadcrumb, .shell-context-divider { display: none; }
}

.topbar-brand-mark {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    background: linear-gradient(135deg, var(--color-primary-500), var(--color-primary-700));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: var(--text-md);
    flex-shrink: 0;
}

.topbar-brand-logo {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    object-fit: contain;
    flex-shrink: 0;
}

/* -- FLOATING NAVIGATION NODE: independent overlay panel, never a sidebar. Its trigger lives as
   a plain icon inside the right utility node's popover-host (see .shell-icon-btn); the panel
   itself still floats fully independently and never reflows content. -- */

.shell-nav-panel {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    display: flex;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 120;
    overflow: hidden;
    animation: mega-menu-in var(--motion-fast);
}

.shell-nav-col {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: 240px;
    padding: var(--space-2);
    overflow-y: auto;
    max-height: 65vh;
    border-right: 1px solid var(--border);
}

.shell-nav-col:last-child { border-right: none; }

.shell-nav-placeholder {
    padding: var(--space-4) var(--space-3);
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.shell-nav-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text);
    text-decoration: none;
    font-size: var(--text-sm);
    font-weight: 550;
    cursor: pointer;
    text-align: left;
    width: 100%;
}

.shell-nav-item:hover { background: var(--surface-subtle); }
.shell-nav-item.is-active { background: var(--color-primary-50); color: var(--color-primary-700); }
.shell-nav-item .icon:first-child { color: var(--color-neutral-400); flex-shrink: 0; }
.shell-nav-item:hover .icon:first-child { color: var(--text); }
.shell-nav-item.is-active .icon:first-child { color: var(--color-primary-600); }
.shell-nav-item-chevron { margin-left: auto; color: var(--color-neutral-300) !important; }
.shell-nav-item span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.shell-nav-group {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

/* -- Node 2/3 "page preview" - shown when the selected item has no further children -- */
.shell-nav-preview {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-3);
    width: 260px;
}

.shell-nav-preview-icon {
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    background: var(--accent-blue-bg);
    color: var(--accent-blue-fg);
    display: flex;
    align-items: center;
    justify-content: center;
}

.shell-nav-preview-title { font-weight: 650; font-size: var(--text-md); color: var(--text); }
.shell-nav-preview-desc { font-size: var(--text-sm); color: var(--text-muted); }

@media (max-width: 767.98px) {
    .shell-nav-panel {
        position: fixed;
        left: var(--space-3);
        right: var(--space-3);
        top: 84px;
        flex-direction: column;
        width: auto;
        max-height: calc(100vh - 104px);
    }

    .shell-nav-col {
        width: auto;
        max-height: 220px;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }

    .shell-nav-col:last-child { border-bottom: none; }
    .shell-nav-preview { width: auto; }
}

/* -- RIGHT: system/utility node -- */

.shell-utility {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0 var(--space-3);
    height: 44px;
    margin-left: auto;
    flex-shrink: 0;
}

.shell-clock {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: var(--text-sm);
    color: var(--text);
    min-width: 44px;
    text-align: center;
}

/* Connection status is always a real icon (not a decorative dot) so it stays visible/legible
   even when compressed - color communicates state, never opacity/visibility. */
[data-shell-status] { color: var(--color-neutral-400); transition: color var(--motion-normal); }
[data-shell-status].is-online { color: var(--color-success-solid); }
[data-shell-status].is-offline { color: var(--color-error-solid); }

@media (max-width: 899.98px) {
    .shell-clock { display: none; }
}

.shell-utility-divider { width: 1px; height: 22px; background: var(--border); flex-shrink: 0; }

.shell-popover-host { position: relative; display: flex; }

.shell-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
}

.shell-icon-btn:hover, .shell-icon-btn.is-open { background: var(--surface-subtle); color: var(--text); }
.shell-icon-btn { position: relative; }

/* Chat is a standalone entry point into a whole feature (not a passive status readout like the
   clock/connection dot), so it gets a filled, colored treatment instead of the other utility
   icons' plain muted-on-transparent look - meant to read as clearly clickable at a glance. */
.shell-icon-btn-accent { background: var(--accent-blue-bg); color: var(--color-primary-600); }
.shell-icon-btn-accent:hover, .shell-icon-btn-accent.is-open { background: var(--color-primary-500); color: #fff; }

/* Unread notification count dot on the bell icon (see _Layout.cshtml's notifications popover). */
.shell-icon-badge {
    position: absolute;
    top: 4px;
    right: 4px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    border-radius: var(--radius-full);
    background: var(--color-error-solid);
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
}

.shell-account-trigger {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    cursor: pointer;
    color: var(--text);
}

.shell-account-trigger:hover, .shell-account-trigger.is-open { background: var(--surface-subtle); }
.shell-account-trigger > .icon:last-child { color: var(--color-neutral-400); }

@media (max-width: 899.98px) {
    .shell-account-trigger .topbar-user-info { display: none; }
}

.topbar-user-info { display: flex; flex-direction: column; line-height: 1.2; }
.topbar-user-name { font-weight: 600; font-size: var(--text-sm); color: var(--text); }
.topbar-user-role { font-size: var(--text-xs); color: var(--text-muted); }

.topbar-avatar {
    width: 34px;
    height: 34px;
    border-radius: var(--radius-full);
    background: var(--color-primary-50);
    color: var(--color-primary-600);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.logout-form { display: flex; }

.shell-popover {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    min-width: 240px;
    max-width: 320px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 130;
    padding: var(--space-2);
    animation: mega-menu-in var(--motion-fast);
}

.shell-popover-header {
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    padding: var(--space-2) var(--space-3);
}

.shell-popover-empty {
    padding: var(--space-5) var(--space-3);
    text-align: center;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.shell-popover-link {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text);
    text-decoration: none;
    font-size: var(--text-sm);
    font-weight: 550;
    cursor: pointer;
    text-align: left;
}

.shell-popover-link:hover { background: var(--surface-subtle); }
.shell-popover-link.is-active { background: var(--color-primary-50); color: var(--color-primary-700); }
.shell-popover-link.danger { color: var(--color-error-solid); }
.shell-popover-link.danger:hover { background: var(--color-error-bg); }
.shell-popover-link .icon { color: var(--color-neutral-400); flex-shrink: 0; }

.shell-notification-list { display: flex; flex-direction: column; gap: 2px; max-height: 360px; overflow-y: auto; }
.shell-notification-item { display: block; width: 100%; padding: var(--space-2) var(--space-3); border: none; border-radius: var(--radius-sm); background: transparent; color: var(--text); text-decoration: none; text-align: left; cursor: pointer; }
.shell-notification-item:hover { background: var(--surface-subtle); }
.shell-notification-item.unread { background: var(--color-primary-50); }
.shell-notification-title { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); font-weight: 650; color: var(--text); }
.shell-notification-title .status-dot { width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--color-primary-500); flex-shrink: 0; }
.shell-notification-message { font-size: var(--text-xs); color: var(--text-muted); margin-top: 2px; }
.shell-notification-time { font-size: 10px; color: var(--text-muted); margin-top: 2px; }
.shell-popover-footer { border-top: 1px solid var(--border); margin-top: var(--space-1); padding-top: var(--space-1); }

.shell-popover-account { min-width: 220px; }

.shell-popover-account-header {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-2) var(--space-3) var(--space-3);
    margin-bottom: var(--space-1);
    border-bottom: 1px solid var(--border);
}

.content {
    flex: 1;
    padding: var(--space-6);
}

@media (max-width: 599.98px) {
    .content { padding: var(--space-4); }
}

/* With the permanent sidebar gone, master data pages get (almost) the full viewport width -
   only the launcher (Home) keeps a comfortable reading width via .page-narrow. */
.page { width: 100%; max-width: none; margin: 0 auto; display: flex; flex-direction: column; gap: var(--space-5); }
.page-narrow { max-width: var(--content-max-width); }

.app-footer {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--border);
    font-size: var(--text-xs);
    color: var(--text-muted);
}

@media (max-width: 599.98px) {
    .app-footer { padding: var(--space-3) var(--space-4); flex-direction: column; align-items: flex-start; gap: var(--space-1); }
}

/* ==========================================================================
   Page header
   ========================================================================== */

.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
}

.page-header-text { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }

.module-page-heading { display: flex; align-items: center; gap: var(--space-3); }

.module-page-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--accent-blue-bg);
    color: var(--accent-blue-fg);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.module-page-icon.accent-green { background: var(--accent-green-bg); color: var(--accent-green-fg); }
.module-page-icon.accent-orange { background: var(--accent-orange-bg); color: var(--accent-orange-fg); }
.module-page-icon.accent-purple { background: var(--accent-purple-bg); color: var(--accent-purple-fg); }

.page-header p { color: var(--text-muted); font-size: var(--text-sm); }

.page-header-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 0.55rem 1rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: 650;
    line-height: 1.2;
    text-decoration: none;
    transition: background var(--motion-fast), border-color var(--motion-fast), box-shadow var(--motion-fast), transform var(--motion-fast);
    white-space: nowrap;
}

.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-primary { background: var(--color-primary-500); color: #fff; box-shadow: 0 1px 2px rgba(29, 78, 216, 0.25); }
.btn-primary:hover:not(:disabled) { background: var(--color-primary-600); box-shadow: 0 2px 6px rgba(29, 78, 216, 0.3); }
.btn-primary:focus-visible { box-shadow: var(--focus-ring); }

.btn-secondary { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.btn-secondary:hover:not(:disabled) { background: var(--surface-subtle); border-color: var(--color-neutral-400); }

.btn-ghost { background: transparent; color: var(--text-muted); border-color: transparent; }
.btn-ghost:hover:not(:disabled) { background: var(--surface-subtle); color: var(--text); }

/* Selected state for a row of otherwise-identical btn-ghost toggle buttons (e.g. OperationUpload's
   own All/Required/Invalid Format/... issue-category filter) - .btn-ghost alone has no visual
   "this one is currently chosen" state. */
.btn-ghost.is-active { background: var(--color-primary-50); color: var(--color-primary-700); }

.btn-outline-danger { background: var(--surface); color: var(--color-error-text); border-color: var(--color-error-border); }
.btn-outline-danger:hover:not(:disabled) { background: var(--color-error-bg); }

.btn-outline-primary { background: var(--surface); color: var(--color-primary-600); border-color: var(--color-primary-500); }
.btn-outline-primary:hover:not(:disabled) { background: var(--color-primary-50); }

.btn-danger { background: var(--color-error-solid); color: #fff; box-shadow: 0 1px 2px rgba(185, 28, 28, 0.25); }
.btn-danger:hover:not(:disabled) { background: var(--color-error-solid-hover); box-shadow: 0 2px 6px rgba(185, 28, 28, 0.3); }

.btn-sm { padding: 0.4rem 0.75rem; font-size: var(--text-xs); }
.btn-block { width: 100%; }

/* Save-in-progress: the clicked submit/action button (.btn or .action-icon-btn) keeps its size
   (avoids layout shift) but its label/icon is hidden and a small spinning ring takes its place -
   site.js adds/removes this class around every form submit. Defaults to a white ring (matches
   dark-background variants like btn-primary/btn-danger/action-icon-btn.danger); the light-
   background variants below override it to a dark ring instead. */
.is-loading { color: transparent !important; pointer-events: none; position: relative; }
.is-loading > * { visibility: hidden; }
.is-loading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 15px;
    height: 15px;
    margin: -7.5px 0 0 -7.5px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.45);
    border-top-color: #fff;
    animation: kautsar-spin 0.65s linear infinite;
}
.btn-secondary.is-loading::after,
.btn-ghost.is-loading::after,
.btn-outline-danger.is-loading::after,
.action-icon-btn.is-loading::after {
    border-color: var(--border-strong);
    border-top-color: var(--color-neutral-700);
}
.action-icon-btn.danger.is-loading::after, .action-icon-btn.success.is-loading::after {
    border-color: rgba(255, 255, 255, 0.45);
    border-top-color: #fff;
}

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

/* ==========================================================================
   Forms
   ========================================================================== */

.form-row { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.form-row + .form-row { margin-top: var(--space-4); }

@media (max-width: 599.98px) {
    .form-row { flex-direction: column; }
}

.form-group { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.form-group-wide { flex-basis: 100%; }

.form-group label {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text);
}

.form-group .hint { font-size: var(--text-xs); color: var(--text-muted); margin-top: 0.15rem; }

/* Void/Cancel Approve modals' read-only "workflow so far" info (see Operation.cshtml). */
.workflow-info-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.workflow-info-list li { font-size: var(--text-sm); color: var(--text); padding: var(--space-2) var(--space-3); background: var(--surface-subtle); border-radius: var(--radius-sm); }

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    font-size: var(--text-sm);
    color: var(--text);
    transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}

.form-group input:hover,
.form-group select:hover,
.form-group textarea:hover { border-color: var(--color-neutral-400); }

.form-group input:focus-visible,
.form-group select:focus-visible,
.form-group textarea:focus-visible {
    border-color: var(--color-primary-500);
    box-shadow: var(--focus-ring);
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
}

/* ==========================================================================
   Panels + disclosure (progressive create forms)
   ========================================================================== */

.panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.panel-body { padding: var(--space-6); }

.panel-header { padding: var(--space-5) var(--space-6) 0; }
.panel-header h3 { font-size: var(--text-md); font-weight: 700; color: var(--text); margin: 0; }
.panel-header + .panel-body { padding-top: var(--space-3); }

/* Two boxed panels side by side (e.g. Shipment Information / Schedule & Notes) - distinct from
   .field-row-grid, which splits columns *inside* one panel. */
.panel-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); align-items: start; }
@media (max-width: 860px) { .panel-grid { grid-template-columns: 1fr; } }

details.panel { padding: 0; }

details.panel > summary {
    list-style: none;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-5);
    cursor: pointer;
    font-weight: 650;
    font-size: var(--text-md);
    color: var(--text);
}

details.panel > summary::-webkit-details-marker { display: none; }

details.panel > summary .icon-plus { color: var(--color-primary-600); }

details.panel > summary::after {
    content: "";
    width: 0.8em;
    height: 0.8em;
    margin-left: auto;
    border-right: 2px solid var(--text-muted);
    border-bottom: 2px solid var(--text-muted);
    transform: rotate(45deg);
    transition: transform var(--motion-fast);
}

details.panel[open] > summary::after { transform: rotate(-135deg); }

details.panel > summary:hover { background: var(--surface-subtle); }
details.panel > summary:focus-visible { box-shadow: none; outline: 2px solid var(--color-primary-500); outline-offset: -2px; }

details.panel[open] > summary { border-bottom: 1px solid var(--border); }

/* ==========================================================================
   Alerts
   ========================================================================== */

.alert {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    border-left-width: 4px;
    font-size: var(--text-sm);
    font-weight: 550;
    margin-bottom: var(--space-3);
    box-shadow: var(--shadow-sm);
    animation: alert-in var(--motion-normal);
    transition: opacity var(--motion-normal), transform var(--motion-normal), max-height var(--motion-normal), margin var(--motion-normal), padding var(--motion-normal);
}

@keyframes alert-in {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}

.alert .icon { margin-top: 0.1em; }
.alert-error { background: var(--color-error-bg); border-color: var(--color-error-border); border-left-color: var(--color-error-solid); color: var(--color-error-text); }
.alert-success { background: var(--color-success-bg); border-color: var(--color-success-border); border-left-color: var(--color-success-solid); color: var(--color-success-text); }
.alert-info { background: var(--color-info-bg); border-color: var(--color-info-border); border-left-color: var(--color-neutral-600); color: var(--color-info-text); }

.alert > span { flex: 1; }

/* Every `.alert[role="alert"]` is converted into a SweetAlert2 toast by site.js (see below) -
   hidden by default so it never has a chance to paint/animate in first and then vanish right
   as the toast appears (that flash-then-toast is what reads as a "double notification"). If
   SweetAlert2 fails to load, site.js falls back to setting inline `display` back on so the
   banner still works exactly as before - see the fallback branch there. */
.alert[role="alert"] { display: none; }

/* -- SweetAlert2 branding: matches the app's type scale instead of the library's own default
   font stack. Notifications/confirmations render through this everywhere (see site.js). -- */
.kautsar-swal { font-family: var(--font-sans) !important; }
.kautsar-swal .swal2-title { font-size: var(--text-md) !important; }
.kautsar-swal .swal2-html-container { font-size: var(--text-sm) !important; }

/* -- Page loader: shown for the brief gap between clicking a link/submitting a form and the next
   page actually arriving (this app is server-rendered, full-page navigations - see site.js) - a
   full-screen dimmed backdrop with a centered spinning ring. -- */
.page-loader {
    position: fixed;
    inset: 0;
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(241, 245, 249, 0.6);
    backdrop-filter: blur(1px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--motion-fast), visibility var(--motion-fast);
}

.page-loader.is-active { opacity: 1; visibility: visible; }

.page-loader-spinner {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    border: 3px solid var(--color-neutral-200);
    border-top-color: var(--color-primary-600);
    animation: kautsar-spin 0.7s linear infinite;
}

/* ==========================================================================
   Badges
   ========================================================================== */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.65rem;
    border-radius: var(--radius-full);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.01em;
    border: 1px solid transparent;
    white-space: nowrap;
}

/* Two different jobs, two different palettes:
   - Status/lifecycle (active, inactive, deleted, rejected) is decisive and solid: green/red/
     dark only, never soft-pastel, so the state reads unambiguously at a glance.
   - Category/classification tags (module type, tenant type, role) are soft pastel pills with
     one hue per distinct value (like the Office column reference) - they're a "which group"
     label, not a state, so variety here aids scanning instead of causing visual noise. */
.badge-success { background: var(--color-success-solid); color: #fff; }
.badge-error { background: var(--color-error-solid); color: #fff; }
.badge-warning { background: var(--color-neutral-600); color: #fff; }
.badge-dark { background: var(--color-dark-solid); color: #fff; }
.badge-info { background: var(--color-info-bg); color: var(--color-info-text); border-color: var(--color-info-border); }
.badge-neutral { background: var(--color-neutral-100); color: var(--color-neutral-600); border-color: var(--border); }

/* A <button> reusing the .badge visual (see _PricingLineStatus.cshtml) needs the browser's own
   button chrome neutralized - .badge itself already overrides background/border via its modifier
   classes, so only appearance/cursor/font need resetting here. */
.badge.status-link { appearance: none; -webkit-appearance: none; cursor: pointer; font: inherit; font-weight: 700; }

/* Plain colored text (no pill) for a status column - used where a badge would be too heavy,
   e.g. Operation's job-stage column: blue while in progress, green once billing has started,
   red reserved for a voided/cancelled state. */
.stage-text { font-weight: 700; }
.stage-text.stage-blue { color: var(--color-primary-600); }
.stage-text.stage-green { color: var(--color-success-text); }
.stage-text.stage-red { color: var(--color-error-text); }

/* ==========================================================================
   Grand total banner - sums every line-section (Detail of Charges,
   Reimbursement, RC, ...) on a Pricing/Marketing page into one figure, shown
   as a single row (one "GRAND TOTAL" label, USD then IDR side by side - never
   two separate "Grand Total" blocks) right-aligned under the section tables'
   own Total row. Recomputed fresh from the database on every render so it
   always reflects the current lines regardless of add/remove/edit. Invoice
   has only one section, so its grand total is a second row in that table's
   own <tfoot> instead of a separate banner - see the "TOTAL" rules below.
   ========================================================================== */

.grand-total-box {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
    background: var(--surface-subtle);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-5);
    margin: var(--space-2) 0 var(--space-5);
}

.grand-total-box .gt-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    font-weight: 700;
    margin-right: var(--space-2);
}

.grand-total-box .gt-value {
    min-width: 11ch;
    text-align: right;
    font-size: var(--text-md);
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

/* Detail table's own totals row (subtable tfoot) - a second row labeled
   GRAND TOTAL directly beneath TOTAL keeps both figures aligned under the
   same USD/IDR columns instead of a separate box drifting off to one side. */
.subtable tfoot .grand-total-row td { border-top: 2px solid var(--border-strong); font-weight: 700; }

/* Numeric cells/inputs right-align app-wide (Operation/Pricing/Marketing/MasterData tables and
   forms) - .num was already used pervasively on <td> throughout these tables but only had a
   matching rule inside the print-only .invp-table/.jsp-table stylesheets, so on-screen numbers
   were left-aligned like any other text. Every type="number" input (Qty, unit price, ...) gets
   the same right alignment while being typed, not just once the value is a computed/read cell. */
.num { text-align: right; font-variant-numeric: tabular-nums; }
input[type="number"] { text-align: right; }

/* ==========================================================================
   Job Sheet - a printed-document look (dotted field separators, all-caps
   values) distinct from the rest of the app's editable forms, since this
   page is explicitly read-only/print-only.
   ========================================================================== */

.jobsheet-header .field-row { border-bottom-style: dashed; }
.jobsheet-header .fval { text-transform: uppercase; }
.jobsheet-header .fval small { text-transform: none; display: block; margin-top: 2px; }

.gross-profit-box {
    display: flex;
    align-items: baseline;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-8);
    background: var(--color-neutral-900);
    color: #fff;
    border-radius: var(--radius-md);
    padding: var(--space-4) var(--space-5);
    margin-top: var(--space-5);
    text-align: center;
}

.gross-profit-box .gp-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: rgba(255, 255, 255, 0.7);
    font-weight: 700;
    margin-right: var(--space-2);
}

.gross-profit-box .gp-value { font-size: var(--text-lg); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Company Profile - logo upload dropzone (Masters/CompanyProfile)
   ========================================================================== */

.logo-upload-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 160px;
    height: 160px;
    border: 1.5px dashed var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface-subtle);
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 600;
    cursor: pointer;
    overflow: hidden;
    margin-bottom: var(--space-5);
    transition: border-color var(--motion-fast), background var(--motion-fast);
}

.logo-upload-box:hover { border-color: var(--color-primary-500); background: var(--color-primary-50); }
.logo-upload-box img { width: 100%; height: 100%; object-fit: contain; padding: var(--space-2); }
.logo-upload-box svg { width: 32px; height: 32px; opacity: 0.6; }

/* Wider preview for the Login page background photo - shown as a cropped cover thumbnail
   (matching how it renders behind the Login screen) rather than the logo's contained square. */
.login-bg-upload-box { width: 280px; height: 160px; }
.login-bg-upload-box img { object-fit: cover; padding: 0; }

/* ==========================================================================
   Module launcher (Home)
   ========================================================================== */

.launcher {
    max-width: 1080px;
    margin: 0 auto;
    padding: var(--space-8) var(--space-4) var(--space-4);
}

@media (max-width: 599.98px) {
    .launcher { padding-top: var(--space-6); }
}

.launcher-hero {
    text-align: center;
    max-width: 640px;
    margin: 0 auto var(--space-8);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.launcher-hero h1 { font-size: var(--text-3xl); }

@media (max-width: 599.98px) {
    .launcher-hero h1 { font-size: var(--text-2xl); }
}

.launcher-subtitle {
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--text-muted);
}

.launcher-hint {
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.launcher-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-5);
}

@media (max-width: 991.98px) {
    .launcher-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 599.98px) {
    .launcher-grid { grid-template-columns: 1fr; }
}

.module-feature-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--space-5);
}

.module-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-6) var(--space-5) var(--space-5);
    text-decoration: none;
    color: var(--text);
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--motion-fast), border-color var(--motion-fast), transform var(--motion-fast);
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-4);
}

.stat-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}

.stat-card-label { font-size: var(--text-xs); font-weight: 650; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.stat-card-value { font-size: 1.75rem; font-weight: 700; color: var(--text); }
.stat-card-hint { font-size: var(--text-xs); color: var(--text-muted); }

a.module-card:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); transform: translateY(-2px); }
a.module-card:focus-visible { box-shadow: var(--shadow-md), var(--focus-ring); }

.module-card.is-disabled {
    color: var(--text-muted);
    cursor: default;
}

.module-card-icon {
    width: 56px;
    height: 56px;
    border-radius: var(--radius-md);
    background: var(--accent-blue-bg);
    color: var(--accent-blue-fg);
    display: flex;
    align-items: center;
    justify-content: center;
}

.module-card-icon .icon { width: 1.75em; height: 1.75em; }

.module-card.accent-green .module-card-icon { background: var(--accent-green-bg); color: var(--accent-green-fg); }
.module-card.accent-orange .module-card-icon { background: var(--accent-orange-bg); color: var(--accent-orange-fg); }
.module-card.accent-purple .module-card-icon { background: var(--accent-purple-bg); color: var(--accent-purple-fg); }
.module-card.accent-red .module-card-icon { background: var(--color-error-bg); color: var(--color-error-text); }

.module-card.is-disabled .module-card-icon {
    background: var(--color-neutral-100);
    color: var(--color-neutral-400);
}

.module-card-title { font-weight: 650; font-size: var(--text-lg); }

.module-card-desc {
    color: var(--text-muted);
    font-size: var(--text-sm);
    flex: 1;
}

.module-card-footer {
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
}

.module-card-action {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--color-primary-600);
    font-weight: 600;
    font-size: var(--text-sm);
}

/* ==========================================================================
   Tables
   ========================================================================== */

.table-wrap {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
}

.table-scroll { overflow-x: auto; }

.table { width: 100%; border-collapse: collapse; font-size: var(--text-xs); }

.table th, .table td {
    text-align: left;
    padding: 0.5rem 1rem;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

.table th {
    background: var(--surface);
    font-size: var(--text-sm);
    font-weight: 700;
    text-transform: none;
    letter-spacing: normal;
    color: var(--text);
    border-bottom: 1px solid var(--border);
}

.table tbody tr { transition: background var(--motion-fast); }
.table tbody tr:nth-child(even) { background: var(--surface-subtle); }
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--color-primary-50); }
.cell-strong { font-weight: 700; color: var(--text); }

/* Operation's index grid only (opt-in via .table-dashed-rows, not app-wide) - dashed row
   separators for header and detail rows alike, matching the printed-document look used by the
   Job Sheet page's own field-row separators (see .jobsheet-header .field-row above). */
.table-dashed-rows th, .table-dashed-rows td { border-bottom-style: dashed; }

/* Operation's own create/edit/detail panels (scoped via .operation-page, not app-wide - .field-row
   and .subtable are shared by many other pages/forms) - same dashed separators as the index grid
   above, on both the read-only detail view's field-row/subtable rows and the create/edit form's
   own (same markup, just editable) field-row/subtable rows. */
.operation-page .field-row { border-bottom-style: dashed; }
.operation-page .subtable th, .operation-page .subtable td { border-bottom-style: dashed; }

/* -- Data table: card header + toolbar (search, status filter) -- */

.data-card-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    background: var(--surface-subtle);
    border-bottom: 1px solid var(--border);
}

.data-card-title { display: flex; flex-direction: column; gap: 0.15rem; }
.data-card-title h2 { font-size: var(--text-md); font-weight: 700; }

.data-card-count {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.data-card-toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

.table-search {
    position: relative;
    display: flex;
    align-items: center;
}

.table-search .icon {
    position: absolute;
    left: 0.65rem;
    color: var(--text-muted);
    pointer-events: none;
}

.table-search input {
    padding: 0.5rem 0.7rem 0.5rem 2.1rem;
    min-width: 220px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    background: var(--surface);
    color: var(--text);
}

.table-search input:focus-visible { border-color: var(--color-primary-500); box-shadow: var(--focus-ring); outline: none; }

.table-page-size {
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    background: var(--surface);
    color: var(--text);
}

/* -- Data table: sortable column headers -- */

.table th[data-sort-key] { user-select: none; }

.sort-indicator {
    display: inline-flex;
    align-items: center;
    margin-left: 0.3rem;
    vertical-align: middle;
    color: var(--color-neutral-400);
    cursor: pointer;
    border-radius: var(--radius-sm);
    padding: 0.1rem;
}

.sort-indicator:hover { color: var(--text); background: var(--color-neutral-100); }
.sort-indicator .sort-icon-asc, .sort-indicator .sort-icon-desc { display: none; }
.table th.is-sorted-asc .sort-indicator .sort-icon-default,
.table th.is-sorted-desc .sort-indicator .sort-icon-default { display: none; }
.table th.is-sorted-asc .sort-indicator .sort-icon-asc { display: inline-block; color: var(--color-primary-600); }
.table th.is-sorted-desc .sort-indicator .sort-icon-desc { display: inline-block; color: var(--color-primary-600); }

.column-menu-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-left: 0.15rem;
    padding: 0;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-neutral-400);
    cursor: pointer;
    vertical-align: middle;
}

.column-menu-trigger:hover { background: var(--color-neutral-100); color: var(--text); }

/* Column menu popover: rendered as a fixed-position body child (not a DOM child of the
   scrollable header cell) so it is never clipped by .table-scroll's overflow. */
.column-menu {
    z-index: 300;
    min-width: 210px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-2);
    font-size: var(--text-sm);
}

.column-menu-title {
    padding: 0.35rem 0.6rem;
    font-weight: 700;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.column-menu-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    padding: 0.4rem 0.6rem;
    border: none;
    background: transparent;
    color: var(--text);
    font-size: var(--text-sm);
    font-weight: 500;
    text-align: left;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.column-menu-item:hover { background: var(--surface-subtle); }
.column-menu-item-spacer { display: inline-block; width: 1.15em; flex-shrink: 0; }
.column-menu-divider { height: 1px; background: var(--border); margin: var(--space-1) 0.2rem; }

/* -- Data table: per-column filter row -- */

.table-filter-row th {
    background: var(--surface);
    padding: 0.5rem 0.6rem;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
    cursor: default;
    border-bottom: 1px solid var(--border);
}

.column-filter-input,
.column-filter-select {
    width: 100%;
    min-width: 100px;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-size: var(--text-xs);
    font-weight: 400;
    text-transform: none;
}

.column-filter-input:focus-visible,
.column-filter-select:focus-visible { border-color: var(--color-primary-500); box-shadow: var(--focus-ring); outline: none; }

/* -- Data table: row status + actions -- */

.status-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: currentColor;
}

/* Role chips: one soft pastel hue per role for quick visual scanning (category tags, not status). */
.badge-role-blue { background: var(--accent-blue-bg); color: var(--accent-blue-fg); border-color: transparent; }
.badge-role-green { background: var(--accent-green-bg); color: var(--accent-green-fg); border-color: transparent; }
.badge-role-orange { background: var(--accent-orange-bg); color: var(--accent-orange-fg); border-color: transparent; }
.badge-role-purple { background: var(--accent-purple-bg); color: var(--accent-purple-fg); border-color: transparent; }
.badge-role-pink { background: #fdf2f8; color: #be185d; border-color: transparent; }
.badge-role-slate { background: var(--color-neutral-100); color: var(--color-neutral-600); border-color: var(--border); }

.action-icon-group { display: flex; align-items: center; gap: var(--space-1); }

/* Neutral (view/edit/manage) actions are gray, never blue - only decisive green/red is
   reserved for a genuine activate/deactivate-class outcome (see .danger/.success below). */
.action-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--color-neutral-600);
    cursor: pointer;
    transition: background var(--motion-fast), border-color var(--motion-fast), color var(--motion-fast);
}

.action-icon-btn:hover:not(:disabled) { background: var(--color-neutral-100); border-color: var(--border-strong); color: var(--text); }
.action-icon-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.action-icon-btn.danger { background: var(--color-error-solid); color: #fff; border-color: var(--color-error-solid); }
.action-icon-btn.danger:hover:not(:disabled) { background: var(--color-error-solid-hover); border-color: var(--color-error-solid-hover); color: #fff; }
.action-icon-btn.success { background: var(--color-success-solid); color: #fff; border-color: var(--color-success-solid); }
.action-icon-btn.success:hover:not(:disabled) { background: var(--color-success-solid-hover); border-color: var(--color-success-solid-hover); color: #fff; }
.action-icon-btn.circular { border-radius: var(--radius-full); width: 26px; height: 26px; }

/* ==========================================================================
   Field row (label : value grid) - dense header/detail forms
   ========================================================================== */

.field-row {
    display: grid;
    grid-template-columns: 170px 14px 1fr;
    align-items: center;
    gap: 2px var(--space-2);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border);
}

.field-row.align-top { align-items: flex-start; padding-top: var(--space-3); }
.field-row.full { grid-column: 1 / -1; }
.field-row .flabel { font-size: var(--text-sm); font-weight: 650; color: var(--text); }
.field-row .fsep { color: var(--text-muted); }
.field-row .fval { font-size: var(--text-sm); color: var(--text); padding: 2px 0; line-height: var(--leading-normal); }
.field-row .fval.muted { color: var(--text-muted); font-style: italic; }

.field-row input[type="text"],
.field-row input[type="date"],
.field-row input[type="number"],
.field-row select,
.field-row textarea {
    width: 100%;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    font-family: var(--font-sans);
    background: var(--surface);
    color: var(--text);
}

.field-row textarea { resize: vertical; min-height: 72px; }

.field-row input:focus-visible,
.field-row select:focus-visible,
.field-row textarea:focus-visible { outline: none; border-color: var(--color-primary-500); box-shadow: var(--focus-ring); }

/* A repeatable field-row that carries its own trailing add/remove button (e.g. Customer) - same
   3 columns as .field-row plus a 4th, content-sized one for the button. */
.field-row.with-action { grid-template-columns: 170px 14px 1fr auto; }

.field-row-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-8); }

@media (max-width: 860px) {
    .field-row-grid { grid-template-columns: 1fr; }
    .field-row { grid-template-columns: 140px 10px 1fr; }
}

/* ==========================================================================
   Section label - uppercase heading with a trailing divider line
   ========================================================================== */

.section-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-primary-600);
    margin: var(--space-5) 0 var(--space-3);
}

.section-label::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* ==========================================================================
   Subtable - repeatable rows (line items) inside a form
   ========================================================================== */

.subtable {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-bottom: var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.subtable thead th {
    background: var(--surface-subtle);
    border: none;
    border-bottom: 1px solid var(--border);
    padding: var(--space-3);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    white-space: nowrap;
    text-align: left;
}
.subtable thead th.col-x { width: 42px; }
.subtable thead th.col-num { width: 42px; text-align: center; }
.subtable tbody td.cell-num { text-align: center; color: var(--text-muted); }
.subtable tbody td { border: none; border-bottom: 1px solid var(--border); padding: var(--space-3); background: var(--surface); vertical-align: middle; transition: background var(--motion-fast); }
.subtable tbody tr:last-child td { border-bottom: none; }
.subtable tbody tr:not([hidden]):hover td { background: var(--surface-subtle); }
.subtable tbody tr[hidden] { display: none; }
.subtable input, .subtable select {
    width: 100%;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    padding: 0.5rem 0.6rem;
    font-size: var(--text-sm);
    font-family: var(--font-sans);
    transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}
.subtable input:focus-visible, .subtable select:focus-visible { outline: none; border-color: var(--color-primary-500); box-shadow: var(--focus-ring); }

/* Detail of Charges rows shared with Operation (see PricingLine.OperationJobChargeId) get a
   subtle accent so it's visually clear an edit/delete here also affects Operation's own data. */
.subtable tbody tr.from-operation-row td:first-child { box-shadow: inset 3px 0 0 var(--color-primary-500); }
.subtable .badge { margin-left: var(--space-2); vertical-align: middle; }

/* Shared "financial detail table" summary treatment (Invoice's Detail of Charges, Marketing's
   Receivable/Reimbursement/RC read-only views) - a scoped class so this doesn't also restyle
   Pricing's identical-looking plain .subtable/.grand-total-row rows. Net Value/VAT/Grand Total
   are ordinary rows of the SAME table (colspan over the descriptive columns, one real cell per
   currency total column) rather than a separate summary card, so the summary can never drift out
   of alignment with the detail rows above it regardless of how many there are. The final Grand
   Total row gets a distinct highlight instead of just a top border, so it reads as the one figure
   that matters. */
.charges-detail-table tfoot .subtotal-row td,
.charges-detail-table tfoot .grand-total-row td {
    background: var(--surface-subtle);
}
.charges-detail-table tfoot .muted-cell { color: var(--text-muted); font-weight: 400; }
.charges-detail-table tfoot .grand-total-row td {
    background: var(--accent-blue-bg);
    color: var(--accent-blue-fg);
}
.charges-detail-table tfoot .grand-total-row .muted-cell { color: var(--accent-blue-fg); opacity: 0.65; }

/* Not-yet-uploaded file picks (Invoice's own Attachment section) - each entry opens the same
   attachment preview modal as an already-saved file, via a local blob URL. */
.pending-attachments-list {
    list-style: none;
    margin: var(--space-2) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.pending-attachments-list:empty { display: none; }
.pending-attachments-list li a { font-size: var(--text-sm); }

.add-row-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    background: var(--surface);
    border: 1.5px dashed var(--border-strong);
    color: var(--text);
    padding: 0.5rem 1rem;
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    font-weight: 650;
    cursor: pointer;
    margin-bottom: var(--space-2);
}
.add-row-btn:hover { border-color: var(--color-primary-500); color: var(--color-primary-600); background: var(--color-primary-50); }
.add-row-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ==========================================================================
   Lookup field - readonly display input + search button that opens the
   master-data lookup modal (see .lookup-overlay below). Replaces a plain
   <select> wherever the options come from a master-data table.
   ========================================================================== */

.lookup-field { display: flex; align-items: center; gap: var(--space-2); width: 100%; }
.lookup-field .lookup-display { flex: 1 1 auto; min-width: 0; cursor: pointer; caret-color: transparent; background: var(--surface); }
.lookup-field .action-icon-btn { flex: 0 0 auto; }
.lookup-field.has-error .lookup-display { border-color: var(--color-error-solid); }

/* ==========================================================================
   Lookup modal - filterable, paginated picker fed by a page's own
   ?handler=Lookup&type=... JSON endpoint (see .lookup-field above).
   ========================================================================== */

.lookup-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: var(--space-4);
}

.lookup-dialog {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: 720px;
    max-height: min(640px, 90vh);
    display: flex;
    flex-direction: column;
}

.lookup-dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--border);
}

.lookup-dialog-header h3 { margin: 0; font-size: var(--text-base); font-weight: 700; }

.lookup-close {
    border: none;
    background: transparent;
    font-size: 1.2rem;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    padding: var(--space-1);
}

.lookup-close:hover { color: var(--text); }

.lookup-dialog-body {
    padding: var(--space-4) var(--space-5);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.lookup-table-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-md); }
.lookup-table-scroll .table { margin: 0; }
.lookup-table-scroll tbody tr { cursor: pointer; }
.lookup-table-scroll tbody tr:hover { background: var(--color-primary-50); }

.lookup-pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.lookup-pagination span { font-size: var(--text-sm); color: var(--text-muted); }

/* ==========================================================================
   Advanced filter modal - a friendlier alternative to the grid's per-column
   filter row, opened from the funnel icon next to the search box. Each field
   has its own checkbox: only checked fields are applied when Search is
   pressed (see the trigger's inline logic in site.js).
   ========================================================================== */

.filter-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: var(--space-4);
}

.filter-dialog {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: 940px;
    max-height: min(760px, 90vh);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.filter-dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) var(--space-6);
    background: var(--surface-subtle);
    border-bottom: 1px solid var(--border);
}

.filter-dialog-title { display: flex; align-items: center; gap: var(--space-2); color: var(--color-primary-600); }

.filter-dialog-header h3 {
    margin: 0;
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
}

.filter-dialog-body { padding: var(--space-6); overflow-y: auto; background: var(--surface-subtle); }

.filter-dialog-body .section-label { margin: 0 0 var(--space-3); }
.filter-dialog-body .section-label:not(:first-child) { margin-top: var(--space-6); }

.filter-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3) var(--space-6);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4) var(--space-5);
}

.filter-field { display: flex; align-items: center; gap: var(--space-3); min-height: 34px; min-width: 0; }

/* Date-range fields (two date inputs + "to") need more room than half a 2-column grid cell
   gives them - span the full row instead of squeezing in and overlapping the next column. */
.filter-field-wide { grid-column: 1 / -1; }

.filter-check {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    font-weight: 650;
    color: var(--text);
    width: 180px;
    flex: 0 0 180px;
    cursor: pointer;
}

.filter-check input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--color-primary-500); cursor: pointer; flex: 0 0 auto; }

.filter-field input[type="text"],
.filter-field input[type="date"],
.filter-field select {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-size: var(--text-sm);
    font-family: var(--font-sans);
    transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}

.filter-field input:disabled, .filter-field select:disabled { background: var(--surface-subtle); color: var(--text-muted); cursor: not-allowed; }

.filter-field input:focus-visible, .filter-field select:focus-visible { outline: none; border-color: var(--color-primary-500); box-shadow: var(--focus-ring); }

.filter-daterange { display: flex; align-items: center; gap: var(--space-2); flex: 1 1 auto; min-width: 0; }
.filter-daterange input { flex: 1 1 auto; min-width: 0; }
.filter-daterange span { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; flex: 0 0 auto; }

.filter-dialog-footer {
    display: flex;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-6);
    background: var(--surface);
    border-top: 1px solid var(--border);
}

@media (max-width: 720px) {
    .filter-grid { grid-template-columns: 1fr; }
    .filter-check { width: auto; flex: 0 0 auto; }
}

/* ==========================================================================
   Radio group
   ========================================================================== */

.radio-group { display: flex; align-items: center; gap: var(--space-5); padding: var(--space-1) 0; }
.radio-opt { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); font-weight: 500; color: var(--text); cursor: pointer; }
.radio-opt input { width: 16px; height: 16px; accent-color: var(--color-primary-500); }

/* ==========================================================================
   Term-of-payment grid - a wrapped grid of single-select radio options
   ========================================================================== */

.term-payment-grid { display: grid; grid-auto-flow: column; grid-template-rows: repeat(5, auto); gap: var(--space-2) var(--space-6); padding: var(--space-2) 0; }
.term-opt { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--text); white-space: nowrap; cursor: pointer; }
.term-opt input { width: 15px; height: 15px; accent-color: var(--color-primary-500); }

/* ==========================================================================
   Tabs (form detail sections)
   ========================================================================== */

.tabs-panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); margin-top: var(--space-5); overflow: hidden; box-shadow: var(--shadow-sm); }
.tab-bar { display: flex; background: var(--surface-subtle); border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.tab-btn {
    padding: var(--space-3) var(--space-5);
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-right: 1px solid var(--border);
    cursor: pointer;
    position: relative;
    transition: background var(--motion-fast), color var(--motion-fast);
}
.tab-btn::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2.5px; background: transparent; transition: background var(--motion-fast); }
.tab-btn.active { color: var(--text); background: var(--surface); }
.tab-btn.active::after { background: var(--color-primary-500); }
.tab-btn:hover:not(.active) { color: var(--text); background: var(--color-neutral-100); }
.tab-panels { padding: var(--space-6); }
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* -- Data table: pagination -- */

.pagination-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border);
}

.pagination-size { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); }

.pagination-controls { display: flex; align-items: center; gap: 0.25rem; }

.pagination-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text-muted);
    cursor: pointer;
}

.pagination-nav:hover:not(:disabled) { background: var(--surface-subtle); color: var(--text); }
.pagination-nav:disabled { opacity: 0.4; cursor: not-allowed; }

.pagination-pages { display: flex; align-items: center; gap: 0.25rem; }

.pagination-page {
    min-width: 30px;
    height: 30px;
    padding: 0 0.4rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-sm);
    cursor: pointer;
}

.pagination-page:hover { background: var(--surface-subtle); }
.pagination-page.is-active { background: var(--color-primary-500); color: #fff; font-weight: 650; }

@media (max-width: 599.98px) {
    .data-card-header { flex-direction: column; align-items: stretch; }
    .data-card-toolbar { flex-direction: column; align-items: stretch; }
    .table-search input { min-width: 0; width: 100%; }
    .pagination-bar { flex-direction: column; align-items: stretch; }
}

/* ==========================================================================
   Dialog
   ========================================================================== */

dialog.dialog {
    border: none;
    border-radius: var(--radius-lg);
    padding: 0;
    width: 100%;
    max-width: 520px;
    box-shadow: var(--shadow-lg);
    color: var(--text);
}

dialog.dialog::backdrop { background: rgba(15, 23, 42, 0.55); }

.dialog-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-5) var(--space-4);
    border-bottom: 1px solid var(--border);
}

.dialog-header h2 { font-size: var(--text-lg); }
.dialog-header p { color: var(--text-muted); font-size: var(--text-sm); margin-top: 0.2rem; }

.dialog-close {
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0.2rem;
    border-radius: var(--radius-sm);
    flex-shrink: 0;
}

.dialog-close:hover { background: var(--surface-subtle); color: var(--text); }

.dialog-body { padding: var(--space-5); }

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

@media (max-width: 599.98px) {
    dialog.dialog { max-width: calc(100vw - 2rem); }
}

/* Wide variant for a dialog that hosts data-dense content (e.g. Role Detail's Manage
   Permissions access-matrix, which has 20+ action columns) - the body still scrolls
   horizontally within itself via .table-scroll rather than the dialog overflowing the
   viewport. */
dialog.dialog.dialog-wide { max-width: min(1240px, calc(100vw - 2rem)); }
dialog.dialog.dialog-wide .dialog-body { max-height: 70vh; overflow-y: auto; }

/* ==========================================================================
   Access configuration table (Role Detail)
   ========================================================================== */

.access-message-body { padding-bottom: 0; }

.access-table { table-layout: fixed; }
.access-table .access-table-menu-name { white-space: normal; }

.access-table-menu-col { width: 220px; }
.access-table-col-action { width: 68px; }

.access-table-action-col {
    text-align: center;
    white-space: nowrap;
}

.access-table-action-col input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--color-primary-500);
}

.access-table-action-col input[type="checkbox"]:disabled { opacity: 0.35; }

.access-table-na { color: var(--color-neutral-300); }

.access-table-group-header {
    text-align: center;
    border-bottom: 1px solid var(--border);
}

.access-table-module-row td {
    background: var(--surface-subtle);
    font-weight: 650;
    font-size: var(--text-sm);
    color: var(--text);
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
}

.access-table-module-row .icon { color: var(--color-primary-600); vertical-align: -0.2em; margin-right: var(--space-2); }

/* Freeze the menu-name column so it stays visible while scrolling through the
   wide Record/Workflow/Data/Utility action columns. Scoped to :first-child since a
   module row can now carry its own action checkboxes too (e.g. Freight Forwarding's
   own "view") - only its label cell should stick, not every action cell in the row. */
.access-table thead th:first-child,
.access-table tbody td.access-table-menu-name,
.access-table tbody tr.access-table-module-row td:first-child {
    position: sticky;
    left: 0;
    box-shadow: 2px 0 0 var(--border);
}

.access-table thead th:first-child { z-index: 2; }
.access-table tbody td.access-table-menu-name,
.access-table tbody tr.access-table-module-row td:first-child { z-index: 1; background: var(--surface); }
.access-table tbody tr.access-table-module-row td:first-child { background: var(--surface-subtle); }
.access-table tbody tr:hover td.access-table-menu-name { background: var(--surface-subtle); }

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

/* Simple tab widget ([data-tabs] > [data-tab-trigger] buttons switching [data-tab-panel]
   sections) - used by Invoice Receipt's Detail of Charges/Bank/References panel. Toggled by
   site.js; this only styles the button bar and active state. */
.doc-tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--border); margin-bottom: var(--space-4); }

.doc-tab-btn {
    appearance: none;
    border: none;
    background: none;
    cursor: pointer;
    padding: var(--space-3) var(--space-4);
    font-size: var(--text-sm);
    font-weight: 650;
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.doc-tab-btn.is-active { color: var(--color-primary-600); border-bottom-color: var(--color-primary-600); }

/* Generic vertical checkbox list (e.g. Users "Manage Roles" dialog). */
.checkbox-list { display: flex; flex-direction: column; gap: var(--space-2); }

.checkbox-list-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--text-sm);
    cursor: pointer;
}

.checkbox-list-item input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--color-primary-500); }

/* ==========================================================================
   Empty state
   ========================================================================== */

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-8) var(--space-4);
    text-align: center;
    color: var(--text-muted);
}

.empty-state .icon { width: 2.25rem; height: 2.25rem; color: var(--color-neutral-300); }
.empty-state-title { font-weight: 600; color: var(--text); }

/* ==========================================================================
   Login
   ========================================================================== */

.login-shell {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: var(--bg);
    padding: var(--space-6);
}

.login-card-frame {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(360px, 0.85fr);
    width: 100%;
    max-width: 1180px;
    max-height: calc(100vh - var(--space-6) * 2);
    min-height: 620px;
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

/* --- Left: brand/marketing panel ------------------------------------- */

.login-visual {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: var(--space-10) var(--space-10) var(--space-8);
    overflow: hidden;
    color: #fff;
    background-repeat: no-repeat;
    background-position: center;
    /* The tenant's uploaded photo (--login-hero-photo, set inline by Login.cshtml from Company
       Profile > Login Background) sits between the readability overlay and the two accent
       gradients, above the base navy gradient. Unset, it resolves to "none" (transparent) and the
       base gradient shows through unchanged - that gradient IS the default background, not just a
       loading fallback, so no photo means today's exact look. */
    background-size: auto, cover, auto, auto, auto;
    background-image:
        linear-gradient(160deg, rgba(11, 17, 32, 0.35), rgba(11, 17, 32, 0.82) 65%, rgba(11, 17, 32, 0.95)),
        var(--login-hero-photo, none),
        radial-gradient(circle at 20% 15%, rgba(37, 99, 235, 0.55), transparent 45%),
        radial-gradient(circle at 85% 30%, rgba(30, 64, 175, 0.5), transparent 40%),
        linear-gradient(200deg, #1e3a8a 0%, #0f172a 55%, #0b1120 100%);
}

.login-visual::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        radial-gradient(circle at 12% 88%, rgba(96, 165, 250, 0.18), transparent 35%),
        repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.035) 0 2px, transparent 2px 46px);
    pointer-events: none;
}

.login-visual > * { position: relative; z-index: 1; }

.login-visual-brand {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.login-visual-brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.login-visual-brand-text strong { font-size: var(--text-2xl); font-weight: 750; }
.login-visual-brand-text span {
    font-size: 0.65rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.6);
}

.login-visual-body { max-width: 34rem; }

.login-visual-eyebrow {
    display: block;
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--color-primary-100);
    margin-bottom: var(--space-4);
}

.login-visual-headline {
    font-size: clamp(2rem, 3.2vw, 2.75rem);
    font-weight: 800;
    line-height: 1.12;
    margin: 0 0 var(--space-4);
    color: #fff;
}

.login-visual-sub {
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    color: rgba(255, 255, 255, 0.78);
    margin: 0 0 var(--space-6);
    max-width: 30rem;
}

.login-feature-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
    list-style: none;
    margin: 0;
    padding: 0;
}

.login-feature-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    width: 6.5rem;
    text-align: center;
    font-size: var(--text-xs);
    font-weight: 600;
    color: rgba(255, 255, 255, 0.85);
}

.login-feature-icon {
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    border: 1px solid rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
}

.login-feature-icon .icon { width: 20px; height: 20px; color: #fff; }

.login-visual-footer {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.login-visual-tagline {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-xs);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.65);
}

.login-visual-tagline::before {
    content: "";
    width: 2rem;
    height: 1px;
    background: rgba(255, 255, 255, 0.4);
}

.login-visual-copyright {
    font-size: var(--text-xs);
    color: rgba(255, 255, 255, 0.45);
}

/* --- Right: login form panel ------------------------------------------ */

.login-panel {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    padding: var(--space-6) var(--space-8) var(--space-8);
    overflow-y: auto;
}

.login-topbar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    margin-bottom: var(--space-8);
    flex-shrink: 0;
}

.login-panel-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-6);
}

.login-signal {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--color-success-solid);
}

.login-signal-bars { display: flex; align-items: flex-end; gap: 2px; height: 12px; }

.login-signal-bars i {
    display: block;
    width: 3px;
    background: var(--color-neutral-300);
    border-radius: 1px;
}

.login-signal-bars i:nth-child(1) { height: 25%; }
.login-signal-bars i:nth-child(2) { height: 50%; }
.login-signal-bars i:nth-child(3) { height: 75%; }
.login-signal-bars i:nth-child(4) { height: 100%; }

.login-signal[data-level="1"] .login-signal-bars i:nth-child(1) { background: currentColor; }
.login-signal[data-level="2"] .login-signal-bars i:nth-child(-n+2) { background: currentColor; }
.login-signal[data-level="3"] .login-signal-bars i:nth-child(-n+3) { background: currentColor; }
.login-signal[data-level="4"] .login-signal-bars i:nth-child(-n+4) { background: currentColor; }
.login-signal[data-status="offline"] { color: var(--color-error-solid); }
.login-signal[data-status="slow"] { color: var(--color-warning-text); }

.login-lang { position: relative; }

.login-lang-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0.4rem 0.65rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-size: var(--text-xs);
    font-weight: 650;
    cursor: pointer;
}

.login-lang-toggle .icon { width: 15px; height: 15px; color: var(--text-muted); }
.login-lang-toggle .icon-chevron { width: 12px; height: 12px; transition: transform var(--motion-fast); }
.login-lang[data-open="true"] .icon-chevron { transform: rotate(180deg); }

.login-lang-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 9rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    padding: var(--space-1);
    z-index: 20;
}

.login-lang[data-open="false"] .login-lang-menu { display: none; }

.login-lang-option {
    display: flex;
    width: 100%;
    align-items: center;
    gap: var(--space-2);
    padding: 0.45rem 0.6rem;
    border: none;
    background: transparent;
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    color: var(--text);
    cursor: pointer;
    text-align: left;
}

.login-lang-option:hover { background: var(--surface-subtle); }
.login-lang-option[aria-selected="true"] { color: var(--color-primary-600); font-weight: 650; }

.login-card { width: 100%; max-width: 360px; margin: 0 auto; }

/* Only .login-visual-brand (the hero panel's top-left mark) uses these now - the card's own
   duplicate logo/label above "Selamat Datang" was removed per design feedback, so this is
   sized to read clearly as the hero panel's brand mark rather than a small inline icon. */
.login-logo {
    width: 68px;
    height: 68px;
    border-radius: var(--radius-md);
    object-fit: contain;
    background: var(--surface-subtle);
    border: 1px solid var(--border);
}

.login-mark {
    width: 68px;
    height: 68px;
    border-radius: var(--radius-md);
    background: linear-gradient(135deg, var(--color-primary-500), var(--color-primary-700));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: var(--text-2xl);
    flex-shrink: 0;
}

.login-welcome { margin: 0 0 var(--space-6); }
.login-welcome h1 { font-size: var(--text-2xl); margin: 0 0 var(--space-1); }
.login-welcome p { margin: 0; color: var(--text-muted); font-size: var(--text-sm); line-height: var(--leading-normal); }

.login-card form { display: flex; flex-direction: column; gap: var(--space-4); }

.login-field { position: relative; }

.login-field .icon {
    position: absolute;
    left: 0.85rem;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 17px;
    color: var(--text-muted);
    pointer-events: none;
}

.login-field input {
    width: 100%;
    padding: 0.7rem 0.85rem 0.7rem 2.6rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    font-size: var(--text-sm);
    color: var(--text);
    transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}

.login-field input:focus-visible { border-color: var(--color-primary-500); box-shadow: var(--focus-ring); outline: none; }

.login-field-toggle {
    position: absolute;
    right: 0.6rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: none;
    background: transparent;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    cursor: pointer;
}

.login-field-toggle:hover { background: var(--surface-subtle); color: var(--text); }
.login-field-toggle .icon { width: 16px; height: 16px; }

.login-row { display: flex; align-items: center; justify-content: space-between; font-size: var(--text-sm); }

.login-remember { display: flex; align-items: center; gap: var(--space-2); color: var(--text); cursor: pointer; }
.login-remember input { width: 15px; height: 15px; accent-color: var(--color-primary-500); }

.login-link { color: var(--color-primary-600); font-weight: 600; text-decoration: none; }
.login-link:hover { text-decoration: underline; }

.login-card .btn-block { padding: 0.75rem 1rem; font-size: var(--text-md); }
.login-card .btn-block .icon { width: 16px; height: 16px; }

.login-divider { display: flex; align-items: center; gap: var(--space-3); color: var(--text-muted); font-size: var(--text-xs); margin: var(--space-1) 0; }
.login-divider::before, .login-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }

.login-sso-btn { display: flex; align-items: center; justify-content: center; gap: var(--space-2); }
.login-sso-btn .icon { width: 16px; height: 16px; }

.login-footnote {
    display: flex;
    justify-content: center;
    gap: var(--space-6);
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid var(--border);
}

.login-footnote-link {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    color: var(--text-muted);
    text-decoration: none;
    font-size: var(--text-xs);
    text-align: center;
}

.login-footnote-link .icon { width: 20px; height: 20px; color: var(--text-muted); }
.login-footnote-link:hover { color: var(--color-primary-600); }
.login-footnote-link:hover .icon { color: var(--color-primary-600); }
.login-footnote-link small { color: var(--color-neutral-400); font-weight: 600; }

.login-copyright { text-align: center; color: var(--text-muted); font-size: var(--text-xs); }

@media (max-width: 959.98px) {
    .login-shell { padding: 0; }
    .login-card-frame { grid-template-columns: 1fr; max-width: none; max-height: none; min-height: 100vh; border-radius: 0; box-shadow: none; }
    .login-visual { display: none; }
    .login-panel { padding: var(--space-5); }
}

/* ==========================================================================
   Coming soon (placeholder for not-yet-built entry points)
   ========================================================================== */

.coming-soon-shell {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background:
        radial-gradient(circle at 15% 15%, rgba(37, 99, 235, 0.16), transparent 45%),
        radial-gradient(circle at 85% 85%, rgba(29, 78, 216, 0.14), transparent 45%),
        var(--color-neutral-950);
    padding: var(--space-4);
}

.coming-soon-card {
    width: 100%;
    max-width: 420px;
    background: var(--surface);
    border-radius: var(--radius-lg);
    padding: var(--space-8) var(--space-6);
    box-shadow: var(--shadow-lg);
    text-align: center;
}

.coming-soon-brand { display: flex; align-items: center; justify-content: center; gap: var(--space-2); margin-bottom: var(--space-6); }
.coming-soon-brand img { width: 28px; height: 28px; border-radius: var(--radius-sm); object-fit: contain; }
.coming-soon-brand strong { font-size: var(--text-lg); font-weight: 700; color: var(--text); }

.coming-soon-icon {
    width: 64px;
    height: 64px;
    border-radius: var(--radius-full);
    background: var(--color-primary-50);
    color: var(--color-primary-600);
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto var(--space-5);
}

.coming-soon-icon .icon { width: 28px; height: 28px; }

.coming-soon-badge {
    display: inline-block;
    padding: 0.25rem 0.7rem;
    border-radius: var(--radius-full);
    background: var(--color-warning-bg);
    color: var(--color-warning-text);
    border: 1px solid var(--color-warning-border);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: var(--space-3);
}

.coming-soon-card h1 { margin: 0 0 var(--space-2); }
.coming-soon-card p { color: var(--text-muted); margin: 0 0 var(--space-6); line-height: var(--leading-normal); }

/* ==========================================================================
   Print - used by Invoice and Job Sheet "Print" buttons (window.print()).
   Hides navigation chrome and interactive controls; an element can also opt
   out individually with .no-print.
   ========================================================================== */

/* Pins the printed page to A4 portrait with the reference document's own margins - without this,
   page size/margins fall back to whatever the browser's print dialog last had configured, which
   made "one A4 page, matching the reference" unreliable across machines/printers. */
@page { size: A4 portrait; margin: 14mm 12mm; }

@media print {
    .shell-float-row, .app-footer, .pagination-bar,
    .data-card-toolbar, .table-filter-row, .lookup-overlay, .filter-modal-overlay, .no-print { display: none !important; }

    .page-header a, .form-actions, details.panel,
    .add-row-btn, .action-icon-btn, .action-icon-group { display: none !important; }

    .panel, .table-wrap { border: none; box-shadow: none; }
    body { background: #fff; }
    .content { padding: 0; max-width: none; }

    /* Long tables (Detail of Charges, Reimbursement, ...) repeat their header row on every
       printed page instead of only the first, and never split a row across a page break. */
    .subtable, .table { page-break-inside: auto; }
    .subtable thead, .table thead { display: table-header-group; }
    .subtable tr, .table tr { page-break-inside: avoid; }

    /* Printers ignore background colors by default - force the grand-total banner's tint
       through so it still stands out as a summary on the printed page. */
    .grand-total-box { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

    /* Invoice print (.print-invoice-doc) replaces the on-screen editing layout (.screen-invoice-view)
       entirely when printing - a purpose-built formal document, not a printout of the edit form.
       flex (not block) so .invp-closing's margin-top:auto can pin Remarks/Notes/Bank/company
       footer to the bottom of the page - see .print-invoice-doc's own base rule below. */
    .screen-invoice-view { display: none !important; }
    .print-invoice-doc { display: flex !important; }

    /* Job Sheet print (.print-jobsheet-doc) replaces the on-screen report layout
       (.screen-jobsheet-view) the same way. flex (not block) so .jsp-signoff's
       margin-top:auto can pin Remarks/signature to the bottom of the page - see
       .print-jobsheet-doc's own base rule below. */
    .screen-jobsheet-view { display: none !important; }
    .print-jobsheet-doc { display: flex !important; }
}

/* ==========================================================================
   Invoice print document (.print-invoice-doc) - a formal export-invoice layout,
   built to match a specific reference document 1:1 (logo/company header, shipper
   block, a labelled references grid, a bordered charges table with NET VALUE/VAT/
   AMOUNT DUE, remarks, and a bank/company footer). Hidden on screen; shown only
   under @media print above. Uses its own plain black-bordered table style rather
   than .subtable's rounded app-UI look, since this is a printed business document.
   ========================================================================== */

/* flex-direction:column + min-height give .invp-closing (Remarks/Notes/Bank/company footer) a
   full page to push itself against via margin-top:auto (see .invp-closing below) - without this,
   a short invoice (few detail rows) leaves that block floating wherever the table happens to
   end, instead of anchored to the bottom of the page like a real printed invoice.
   min-height is a floor, not a cap: it does NOT reserve space for .invp-closing's own content, so
   this is deliberately a little short of a full A4 page (293mm = 297mm minus InvoicePdf.cshtml's
   own @@page rule's 2mm top/bottom margins - the two must move together if either changes) - the
   closing block's actual height (remarks + notes + bank + company footer, several lines each)
   still has to fit within whatever's left on the page above that ceiling, or it spills onto a
   second page instead of anchoring to the bottom of the first. The exact value below was found
   empirically (rendering to PDF and counting pages, breaking point 294mm), not calculated -
   Chromium's own box-model rounding eats a few mm that a pure 297-2-2 subtraction doesn't
   account for. */
.print-invoice-doc { display: none; flex-direction: column; min-height: 290mm; font-family: "Calibri Light", Calibri, var(--font-sans); color: #000; font-size: 7.5pt; line-height: 1.4; }

.invp-header { text-align: center; margin-bottom: 14px; }
.invp-logo { max-height: 64px; max-width: 220px; margin: 0 auto 6px; display: block; }
.invp-company-name { font-size: 13pt; font-weight: 700; letter-spacing: 0.03em; }
.invp-title { font-size: 9pt; font-weight: 700; margin-top: 4px; padding-bottom: 2pt; text-transform: uppercase; border-bottom: 1pt solid #000; }

.invp-meta { display: flex; justify-content: space-between; gap: 24px; margin-bottom: 12px; }
.invp-meta-shipper { flex: 1 1 62%; }
.invp-meta-right { flex: 0 0 32%; }
.invp-kv { display: flex; gap: 6px; }
.invp-kv + .invp-kv { margin-top: 2px; }
.invp-kv .invp-k { width: 55px; flex: 0 0 auto; font-weight: 700; }
.invp-kv .invp-v { flex: 1 1 auto; }
/* Reference RDLC has the SHIPPER label at Normal weight (only the value is bold) - scoped so the
   rest of .invp-k's usages (DATE/TERMS, POL/POD/etc., bank details) keep their existing weight. */
.invp-meta-shipper .invp-k { font-weight: 400; }
.invp-shipper-name { font-weight: 700; }
.invp-shipper-address { white-space: pre-line; margin-left: 61px; }

.invp-section-title { font-weight: 700; text-decoration: underline; margin: 0 0 6px; }

/* The rule line that used to sit above "References" (as .invp-meta's own bottom border) now
   runs the full width below the whole reference block instead, per review feedback. */
.invp-ref { display: flex; gap: 12px; padding-bottom: 8px; margin-bottom: 12px; border-bottom: 1px solid #000; }
.invp-ref-col { flex: 1 1 0; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.invp-ref-col-wide { flex-grow: 1.3; }
.invp-ref-col-narrow { flex-grow: 0.75; }
.invp-ref-line { display: flex; gap: 4px; }
.invp-ref-line .invp-k { min-width: 88px; flex: 0 0 auto; white-space: nowrap; }
.invp-ref-line.invp-indent .invp-k { width: auto; }
.invp-ref-line .invp-v { flex: 1 1 auto; word-break: break-word; }
.invp-ref-line.invp-indent { padding-left: 16px; }

/* Reference design has no boxed grid (no vertical/outer borders) - each row is set off only by a
   rule under its own text, full width. Header labels must never wrap to a second line regardless
   of column width, hence the explicit nowrap. Net Value/VAT/Amount Due are rows of this SAME
   table (see _InvoicePrintDocument.cshtml's own tfoot) rather than a separate table with its own
   column widths - a separate table can drift out of alignment with the columns above it the
   moment either table's widths change; one table can't. */
.invp-table { width: 100%; border-collapse: collapse; margin-bottom: 4px; }
.invp-table th, .invp-table td { border: none; padding: 4px 7px; }
.invp-table thead th { border-bottom: 1px solid #000; text-align: center; font-weight: 700; white-space: nowrap; }
.invp-table td.num, .invp-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Itemized charge rows have no rule between them (review feedback removed the earlier dashed
   style) - only the header row above and the summary section below are ruled. */
.invp-table tbody.invp-summary td { border-bottom: 1px solid #000; font-weight: 700; }
/* Marks the line directly above NET VALUE solid, separating the itemized (now borderless) rows
   above from the totals section below. */
.invp-table tbody.invp-summary tr:first-child td { border-top: 1px solid #000; }
.invp-table tbody.invp-summary tr:last-child td { border-bottom: none; }

/* A detail row (or a summary row) must never split across a page break mid-row on a multi-page
   invoice - matches the same rule already applied to .subtable/.table under @media print. */
.invp-table tr { page-break-inside: avoid; break-inside: avoid; }

/* Pins Remarks/Notes/Bank/company footer to the bottom of the page (see .print-invoice-doc's own
   flex/min-height doc comment) - margin-top:auto only works when this element is itself a direct
   flex item, so it wraps that whole block as one rather than relying on it being spread across
   several of .print-invoice-doc's own children. */
.invp-closing { margin-top: auto; }

.invp-remarks { margin-top: 12px; }
.invp-remarks-title { font-weight: 700; text-decoration: underline; margin-bottom: 3px; }
.invp-remarks-body { white-space: pre-line; }

/* Remarks, notes, and bank details stack top-to-bottom as their own full-width blocks, in that
   order - not side-by-side columns - per review feedback that bank details specifically must
   fall below the remarks group, not next to it. */
.invp-footer-notes { margin-top: 16px; font-size: 6.5pt; }
.invp-footer-notes p { margin: 2px 0; }
.invp-footer-bank { margin-top: 12px; font-size: 6.5pt; }
.invp-footer-bank .invp-kv .invp-k { width: 80px; }

.invp-company-footer { text-align: center; font-size: 6pt; margin-top: 28px; border-top: 1px solid #000; padding-top: 6px; }
.invp-company-footer p { margin: 2px 0; }
.invp-company-footer p:first-child { letter-spacing: 0.22em; font-weight: 700; }

/* ==========================================================================
   Job Sheet print document (.print-jobsheet-doc) - built to match a specific
   reference document 1:1: a centered title with a print-date stamp, a
   borderless shipper/reference header block set off by a rule (no boxed
   grid), RECEIVABLE and PAYABLES sections (each a line-ruled charges table
   grouped by invoice/vendor with its own SUBTOTAL), and a Remarks/signature
   closing block pinned to the bottom of the page. Hidden on screen; shown
   only under @media print above. Shares the Invoice print document's type
   scale, "rule line, not boxed grid" visual language, and bottom-pinned
   closing block (.invp-*) so the two exports read as one document family.
   ========================================================================== */

/* flex-direction:column + min-height give .jsp-signoff (Remarks + signature block) a full page to
   push itself against via margin-top:auto (see .jsp-signoff below) - without this, a short job
   sheet (few charge lines) leaves that block floating wherever the tables happen to end, instead
   of anchored to the bottom of the page. Same min-height as .print-invoice-doc, kept in sync with
   JobSheetPdf.cshtml's own @@page rule (2mm top/bottom margin) - see that rule's own doc comment
   for why 290mm, not a plain 297-2-2 subtraction. */
.print-jobsheet-doc { display: none; flex-direction: column; min-height: 290mm; font-family: var(--font-sans); color: #000; font-size: 5.5pt; line-height: 1.4; }

.jsp-title-row { display: flex; align-items: baseline; justify-content: center; position: relative; border-bottom: 2px solid #000; padding-bottom: 6px; margin-bottom: 10px; }
/* +2pt over the document's own 5.5pt/7pt scale (review feedback) - the JOB SHEET title only,
   nothing else on the page. */
.jsp-title { font-size: 9pt; font-weight: 700; text-align: center; }
.jsp-print-date { position: absolute; right: 0; bottom: 4px; font-size: 4.5pt; }

/* No boxed grid (no outer/vertical borders) - matches the Invoice print document's reference
   design (.invp-meta/.invp-ref): the block is set off only by a rule beneath it, full width. */
.jsp-meta { display: flex; padding-bottom: 8px; margin-bottom: 12px; border-bottom: 1px solid #000; }
.jsp-meta-col { padding: 6px 8px; }
.jsp-meta-col-main { flex: 1 1 50%; }
.jsp-meta-col-mid { flex: 1 1 28%; }
.jsp-meta-col-side { flex: 0 0 22%; display: flex; flex-direction: column; justify-content: space-between; gap: 8px; }
.jsp-kv { display: flex; gap: 4px; margin-bottom: 2px; }
.jsp-kv .jsp-k { min-width: 105px; flex: 0 0 auto; white-space: nowrap; }
.jsp-kv .jsp-v { flex: 1 1 auto; }
.jsp-kv .jsp-v.jsp-strong { font-weight: 700; }
.jsp-meta-col-mid .jsp-kv .jsp-k { min-width: 82px; }
.jsp-meta-col-side .jsp-kv .jsp-k { min-width: 38px; }

.jsp-section-band { font-weight: 700; text-transform: uppercase; padding-bottom: 3px; margin-bottom: 4px; border-bottom: 1px solid #000; }

/* No boxed grid (no vertical/outer borders) - each row is set off only by a rule under it, full
   width, matching the Invoice print document's .invp-table. Plain solid rule under every row
   (review feedback removed the dashed detail-row treatment tried earlier) - back to the same
   "long line, not a box" style used everywhere else on this page. */
.jsp-table { width: 100%; border-collapse: collapse; margin-bottom: 16px; }
.jsp-table th, .jsp-table td { border: none; border-bottom: 1px solid #000; padding: 3px 6px; }
.jsp-table thead th { text-align: left; font-weight: 700; }
.jsp-table thead th.num { text-align: right; }
.jsp-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.jsp-table tbody tr.jsp-group-header td { font-weight: 700; padding-bottom: 1px; }
.jsp-table tfoot td { border-bottom: none; padding: 3px 6px; }
.jsp-table tfoot tr.jsp-subtotal td { border-top: 1px solid #000; font-weight: 700; }
.jsp-table tfoot tr.jsp-gross-profit td { border-top: 2px solid #000; font-weight: 700; }

/* Pinned to the bottom of the page (see .print-jobsheet-doc's own flex/min-height doc comment) -
   margin-top:auto only works because this element is itself a direct flex item of
   .print-jobsheet-doc, wrapping Remarks and the signature columns as one block. */
.jsp-signoff { display: flex; justify-content: space-between; margin-top: auto; }
.jsp-signoff-remarks { flex: 1 1 55%; }
.jsp-signoff-cols { flex: 0 0 40%; display: flex; justify-content: space-between; text-align: center; }
.jsp-signoff-cols div { flex: 1 1 50%; }
.jsp-signoff-title { font-weight: 700; margin-bottom: 40px; }
.jsp-signoff-name { border-top: 1px solid #000; padding-top: 3px; display: inline-block; min-width: 90px; }

/* ==========================================================================
   Operation print document (.print-operation-doc) - "Export to PDF" for the
   Operation job itself (see OperationModel.OnGetExportPdfAsync). Deliberately
   the same design language as Invoice/Job Sheet's own print documents (.invp-* /
   .jsp-* : centered company header, a borderless labelled meta block set off by
   a rule, plain line-ruled tables) so the three read as one document family -
   but with NO price/unit-price/total/VAT columns or summary rows anywhere,
   since Operation never carries money amounts (that starts at Pricing). Shown
   only by OperationPdf.cshtml's own page (never under the normal @media print
   rules above - there is no on-screen equivalent layout to swap out).
   ========================================================================== */

/* Same min-height/font baseline as .print-invoice-doc/.print-jobsheet-doc - see
   .print-invoice-doc's own doc comment for why 265mm. */
.print-operation-doc { display: none; flex-direction: column; min-height: 265mm; font-family: var(--font-sans); color: #000; font-size: 5.5pt; line-height: 1.4; }

.opp-header { text-align: center; margin-bottom: 14px; }
.opp-logo { max-height: 64px; max-width: 220px; margin: 0 auto 6px; display: block; }
.opp-company-name { font-size: 11pt; font-weight: 700; letter-spacing: 0.03em; }
.opp-title { font-size: 7pt; font-weight: 700; margin-top: 4px; padding-bottom: 2pt; text-transform: uppercase; border-bottom: 1pt solid #000; }

/* No boxed grid (no outer/vertical borders) - matches Invoice/Job Sheet's own reference design:
   each row is set off only by a rule beneath it, full width. */
/* Same two-column split as .invp-meta/.invp-meta-shipper/.invp-meta-right (main block + a
   narrower side block, no rule beneath it) - see that rule's own doc comment. */
.opp-meta { display: flex; justify-content: space-between; gap: 24px; margin-bottom: 12px; }
.opp-meta-main { flex: 1 1 62%; }
.opp-meta-side { flex: 0 0 32%; }
.opp-kv { display: flex; gap: 6px; }
.opp-kv + .opp-kv { margin-top: 2px; }
.opp-kv .opp-k { min-width: 92px; flex: 0 0 auto; white-space: nowrap; font-weight: 700; }
.opp-kv .opp-v { flex: 1 1 auto; word-break: break-word; }

.opp-section-title { font-weight: 700; text-decoration: underline; margin: 0 0 6px; }

/* Same "labelled columns set off by a rule beneath them" block as .invp-ref/.invp-ref-col -
   Operation's own shipment fields (POL/POD/ETD/ETA/...) rather than Invoice's references. */
.opp-ref { display: flex; gap: 12px; padding-bottom: 8px; margin-bottom: 12px; border-bottom: 1px solid #000; }
.opp-ref-col { flex: 1 1 0; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.opp-ref-line { display: flex; gap: 4px; }
.opp-ref-line .opp-k { min-width: 88px; flex: 0 0 auto; white-space: nowrap; font-weight: 700; }
.opp-ref-line .opp-v { flex: 1 1 auto; word-break: break-word; }

.opp-table { width: 100%; border-collapse: collapse; margin-bottom: 4px; }
.opp-table th, .opp-table td { border: none; border-bottom: 1px solid #000; padding: 4px 7px; }
.opp-table thead th { text-align: left; font-weight: 700; white-space: nowrap; }
.opp-table td.num, .opp-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.opp-table tr { page-break-inside: avoid; break-inside: avoid; }

.opp-closing { margin-top: auto; }
.opp-remarks { margin-top: 12px; }
.opp-remarks-title { font-weight: 700; text-decoration: underline; margin-bottom: 3px; }
.opp-remarks-body { white-space: pre-line; }

.opp-company-footer { text-align: center; font-size: 4pt; margin-top: 28px; border-top: 1px solid #000; padding-top: 6px; }
.opp-company-footer p { margin: 2px 0; }
.opp-company-footer p:first-child { letter-spacing: 0.22em; font-weight: 700; }

/* ==========================================================================
   Chat
   ========================================================================== */

.btn-link {
    background: none;
    border: none;
    padding: 0;
    color: var(--color-primary-600);
    cursor: pointer;
    font: inherit;
    text-decoration: underline;
}
.btn-link:hover { color: var(--color-primary-700); }

/* The chat page fills the available content height instead of scrolling as a document -
   :has() is supported by every evergreen browser this platform targets. */
.content:has(.chat-shell) { padding: 0; display: flex; }
.page-chat { flex: 1; min-height: 0; display: flex; }

.chat-shell {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: 320px 1fr 300px;
    background: var(--surface);
    border-top: 1px solid var(--border);
}

.chat-list-panel, .chat-info-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-right: 1px solid var(--border);
}
.chat-info-panel { border-right: none; border-left: 1px solid var(--border); }

.chat-list-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) var(--space-4) var(--space-3);
}
.chat-list-header h1 { font-size: var(--text-xl); }

.chat-search {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 var(--space-4) var(--space-3);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface-subtle);
}
.chat-search .icon { color: var(--text-muted); flex-shrink: 0; }
.chat-search input {
    border: none;
    background: none;
    outline: none;
    font: inherit;
    width: 100%;
    color: var(--text);
}

.chat-filters {
    display: flex;
    gap: var(--space-1);
    padding: 0 var(--space-4) var(--space-3);
    flex-wrap: wrap;
}
.chat-filter-tab {
    border: 1px solid transparent;
    background: none;
    border-radius: var(--radius-full);
    padding: 0.3rem 0.75rem;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
}
.chat-filter-tab:hover { background: var(--surface-subtle); }
.chat-filter-tab.active { background: var(--color-primary-500); color: #fff; }

.chat-conversation-list { flex: 1; overflow-y: auto; padding-bottom: var(--space-4); }

.chat-list-section-label {
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.chat-list-empty { padding: var(--space-6) var(--space-4); text-align: center; color: var(--text-muted); }

.chat-conversation-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-2) var(--space-4);
    border: none;
    background: none;
    text-align: left;
    cursor: pointer;
    position: relative;
}
.chat-conversation-item:hover { background: var(--surface-subtle); }
.chat-conversation-item.active { background: var(--accent-blue-bg); }

.chat-avatar {
    flex-shrink: 0;
    width: 42px;
    height: 42px;
    border-radius: var(--radius-full);
    background: var(--color-neutral-200);
    color: var(--color-neutral-700);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: var(--text-sm);
}
.chat-avatar-group { background: var(--accent-purple-bg); color: var(--accent-purple-fg); }
.chat-avatar-sm { width: 28px; height: 28px; font-size: var(--text-xs); }
.chat-avatar .icon { width: 1.2em; height: 1.2em; }

.chat-conversation-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.2rem; }
.chat-conversation-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.chat-conversation-name { font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-conversation-time { font-size: var(--text-xs); color: var(--text-muted); flex-shrink: 0; }
.chat-conversation-preview { font-size: var(--text-sm); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chat-unread-badge {
    flex-shrink: 0;
    background: var(--color-primary-500);
    color: #fff;
    border-radius: var(--radius-full);
    min-width: 1.3rem;
    height: 1.3rem;
    padding: 0 0.35rem;
    font-size: var(--text-xs);
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.chat-pin-indicator { position: absolute; top: var(--space-2); right: var(--space-3); width: 0.9rem; height: 0.9rem; color: var(--text-muted); }

.chat-workspace-panel { display: flex; flex-direction: column; min-height: 0; }
.chat-empty-state { flex: 1; align-items: center; justify-content: center; }

.chat-thread { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.chat-thread-header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border);
}
.chat-thread-title { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.chat-thread-name { font-weight: 650; }
.chat-thread-meta { font-size: var(--text-sm); color: var(--text-muted); }
.chat-back-btn { display: none; }

.chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    background: var(--surface-subtle);
}

.chat-load-older { align-self: center; }

.chat-message { display: flex; flex-direction: column; max-width: 70%; align-items: flex-start; }
.chat-message.mine { align-self: flex-end; align-items: flex-end; }
.chat-message-sender { font-size: var(--text-xs); font-weight: 700; color: var(--accent-purple-fg); margin-bottom: 0.2rem; }
.chat-message-bubble {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 0.55rem 0.85rem;
    white-space: pre-wrap;
    word-break: break-word;
}
.chat-message.mine .chat-message-bubble { background: var(--color-primary-500); color: #fff; border-color: var(--color-primary-500); }
.chat-message-time { font-size: var(--text-xs); color: var(--text-muted); margin-top: 0.2rem; }

.chat-composer {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--border);
}
.chat-composer-input {
    flex: 1;
    resize: none;
    max-height: 6.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-3);
    font: inherit;
}
.chat-send-btn { background: var(--color-primary-500); color: #fff; border-color: var(--color-primary-500); flex-shrink: 0; }
.chat-send-btn:hover { background: var(--color-primary-600); }

.chat-info-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4); border-bottom: 1px solid var(--border); }
.chat-info-body { flex: 1; overflow-y: auto; padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-5); }
.chat-info-section h3 { margin-bottom: 0.2rem; }
.chat-info-section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }

.chat-member-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.chat-member-item { display: flex; align-items: center; gap: var(--space-2); }
.chat-member-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-admin-badge { font-size: var(--text-xs); }

.chat-user-picker-results { display: flex; flex-direction: column; gap: 0.15rem; max-height: 260px; overflow-y: auto; margin-top: var(--space-2); }
.chat-user-picker-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    border: none;
    background: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-align: left;
    width: 100%;
}
.chat-user-picker-row:hover { background: var(--surface-subtle); }
.chat-user-picker-name { flex: 1; }

.chat-selected-members { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.chat-member-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: var(--accent-blue-bg);
    color: var(--accent-blue-fg);
    border-radius: var(--radius-full);
    padding: 0.25rem 0.5rem 0.25rem 0.75rem;
    font-size: var(--text-sm);
}
.chat-member-chip button { background: none; border: none; color: inherit; cursor: pointer; font-size: 1rem; line-height: 1; padding: 0; }

@media (max-width: 899.98px) {
    .chat-shell { grid-template-columns: 280px 1fr; }
    .chat-info-panel { position: fixed; inset: var(--topbar-height) 0 0 0; z-index: 20; background: var(--surface); }
}

@media (max-width: 599.98px) {
    /* Grid's implicit row-track sizing leaves a large gap above the visible panel once the
       other two grid children are display:none/[hidden] (only one panel is ever visible on a
       phone) - flex avoids that entirely and is the right model when only one child renders. */
    .chat-shell { display: flex; }
    .chat-list-panel { display: flex; flex: 1; min-height: 0; }
    .chat-workspace-panel { display: none; }
    .chat-info-panel { position: fixed; inset: var(--topbar-height) 0 0 0; z-index: 20; }
    .chat-shell.chat-mobile-thread-open .chat-list-panel { display: none; }
    .chat-shell.chat-mobile-thread-open .chat-workspace-panel { display: flex; flex: 1; min-height: 0; }
    .chat-back-btn { display: inline-flex; }
    .chat-message { max-width: 85%; }
}

/* ==========================================================================
   Chat - floating utility panel (opened from the shell's right utility node,
   see _Layout.cshtml's [data-popover-trigger="chat"]). Overlays the current
   page without navigating away from it or pushing its content.
   ========================================================================== */

.chat-list-header-actions { display: flex; align-items: center; gap: var(--space-1); }

/* The "open full page" shortcut only makes sense from the floating panel. */
.page-chat .chat-expand-btn { display: none; }

.chat-floating-panel {
    padding: 0;
    width: min(760px, calc(100vw - 2rem));
    max-width: none;
    height: min(600px, calc(100vh - 140px));
    overflow: hidden;
    display: flex;
}

.chat-floating-panel .chat-shell {
    flex: 1;
    min-height: 0;
    width: 100%;
    border-top: none;
    border-radius: var(--radius-lg);
    /* A floating panel is narrow by nature - always use the single-active-panel layout
       (list OR thread, toggled by the back button) regardless of viewport width, the same
       behavior the full page only switches to below 599.98px. */
    display: flex;
}
.chat-floating-panel .chat-list-panel { display: flex; flex: 1; min-height: 0; }
.chat-floating-panel .chat-workspace-panel { display: none; }
.chat-floating-panel .chat-shell.chat-mobile-thread-open .chat-list-panel { display: none; }
.chat-floating-panel .chat-shell.chat-mobile-thread-open .chat-workspace-panel { display: flex; flex: 1; min-height: 0; }
.chat-floating-panel .chat-back-btn { display: inline-flex; }
.chat-floating-panel .chat-info-panel {
    position: absolute;
    inset: 0;
    z-index: 5;
    background: var(--surface);
    border-radius: var(--radius-lg);
}

@media (max-width: 599.98px) {
    .chat-floating-panel {
        position: fixed;
        inset: var(--topbar-height) 0 0 0;
        top: var(--topbar-height);
        right: 0;
        width: auto;
        height: auto;
        max-width: none;
        border-radius: 0;
    }
    .chat-floating-panel .chat-shell { border-radius: 0; }
}

/* ==========================================================================
   Chat - "create a group" row, reply-to-message, and @mention
   ========================================================================== */

.chat-create-group-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    margin-top: var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface);
    cursor: pointer;
    text-align: left;
}
.chat-create-group-row:hover { background: var(--surface-subtle); border-color: var(--border-strong); }
.chat-create-group-icon {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-full);
    background: var(--accent-purple-bg);
    color: var(--accent-purple-fg);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.chat-create-group-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.chat-create-group-title { font-weight: 650; }
.chat-create-group-chevron { color: var(--text-muted); flex-shrink: 0; }

/* Reply-to-message */

.chat-message-bubble-wrap { position: relative; display: flex; align-items: flex-end; gap: var(--space-1); }
.chat-message.mine .chat-message-bubble-wrap { flex-direction: row-reverse; }

.chat-message-reply-btn {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border);
    border-radius: var(--radius-full);
    background: var(--surface);
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--motion-fast);
}
.chat-message-reply-btn .icon { width: 0.9em; height: 0.9em; }
.chat-message:hover .chat-message-reply-btn,
.chat-message-reply-btn:focus-visible { opacity: 1; }
.chat-message-reply-btn:hover { background: var(--surface-subtle); color: var(--text); }

.chat-message-reply-quote {
    display: block;
    margin-bottom: 0.35rem;
    padding: 0.3rem 0.55rem;
    border-left: 3px solid var(--color-primary-500);
    border-radius: var(--radius-sm);
    background: rgba(37, 99, 235, 0.08);
    cursor: pointer;
}
.chat-message.mine .chat-message-reply-quote { background: rgba(255, 255, 255, 0.18); border-left-color: #fff; }
.chat-message-reply-quote-sender { display: block; font-size: var(--text-xs); font-weight: 700; }
.chat-message-reply-quote-body {
    display: block;
    font-size: var(--text-xs);
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 260px;
}

.chat-message.highlight .chat-message-bubble { animation: chat-message-highlight 1.6s ease; }
@keyframes chat-message-highlight {
    0%, 100% { box-shadow: none; }
    20% { box-shadow: 0 0 0 3px var(--color-primary-500); }
}

.chat-reply-banner {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    background: var(--surface-subtle);
    border-top: 1px solid var(--border);
}
.chat-reply-banner-icon { color: var(--color-primary-600); flex-shrink: 0; }
.chat-reply-banner-content { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.chat-reply-banner-label { font-size: var(--text-xs); font-weight: 700; color: var(--color-primary-600); }
.chat-reply-banner-preview {
    font-size: var(--text-sm);
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* @mention */

.chat-mention { font-weight: 700; color: var(--color-primary-600); }
.chat-message.mine .chat-mention { color: #fff; text-decoration: underline; }

.chat-mention-menu {
    position: relative;
    z-index: 5;
    margin: 0 var(--space-4);
    padding: var(--space-1);
    list-style: none;
    max-height: 180px;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}
.chat-mention-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2);
    border: none;
    border-radius: var(--radius-sm);
    background: none;
    cursor: pointer;
    text-align: left;
}
.chat-mention-menu-item:hover, .chat-mention-menu-item.is-active { background: var(--surface-subtle); }

/* ==========================================================================
   AI Assistant (Pages/AiAssistant/*, wwwroot/js/ai-assistant.js, ai-monitoring.js)
   Same token language as Chat; green is the AI accent (the "Asisten AI" pill, user bubbles).
   ========================================================================== */

.shell-ai-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: 34px;
    padding: 0 var(--space-3);
    border: none;
    border-radius: var(--radius-full);
    background: var(--color-success-solid);
    color: #fff;
    font: inherit;
    font-size: var(--text-sm);
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}
.shell-ai-btn:hover, .shell-ai-btn.is-open { background: var(--color-success-solid-hover); }
.shell-ai-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
@media (max-width: 767.98px) { .shell-ai-label { display: none; } .shell-ai-btn { padding: 0 var(--space-2); } }

.ai-floating-panel {
    padding: 0;
    width: min(460px, calc(100vw - 2rem));
    max-width: none;
    height: min(640px, calc(100vh - 140px));
    overflow: hidden;
    display: flex;
}

.page-ai-assistant { flex: 1; min-height: 0; display: flex; }

.ai-shell {
    display: flex;
    flex: 1;
    min-height: 0;
    width: 100%;
    background: var(--surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.ai-shell-page { flex: none; border: 1px solid var(--border); box-shadow: var(--shadow-md); height: calc(100vh - 170px); min-height: 420px; }

.ai-sidebar {
    width: 260px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--border);
    background: var(--surface-subtle);
    min-height: 0;
}
.ai-sidebar-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); }
.ai-sidebar-title { font-weight: 700; font-size: var(--text-sm); }
.ai-conversation-list { flex: 1; overflow-y: auto; padding: var(--space-2); display: flex; flex-direction: column; gap: 2px; }
.ai-list-empty { padding: var(--space-3); }
.ai-conv-item { display: flex; align-items: center; border-radius: var(--radius-sm); }
.ai-conv-item:hover { background: var(--surface); }
.ai-conv-item.is-active { background: var(--color-success-bg); }
.ai-conv-open {
    flex: 1;
    min-width: 0;
    border: none;
    background: none;
    text-align: left;
    padding: var(--space-2);
    font: inherit;
    font-size: var(--text-sm);
    color: var(--text);
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ai-conv-delete { opacity: 0; }
.ai-conv-item:hover .ai-conv-delete, .ai-conv-delete:focus-visible { opacity: 1; }

.ai-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }

.ai-header { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); }
.ai-header-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: var(--radius-full);
    background: var(--color-success-bg); color: var(--color-success-solid); flex-shrink: 0;
}
.ai-header-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ai-title { font-weight: 700; font-size: var(--text-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-status { font-size: var(--text-xs); color: var(--text-muted); }
.ai-status[data-status="Ready"]::before { content: "● "; color: var(--color-success-solid); }
.ai-status[data-status="Starting"]::before, .ai-status[data-status="Degraded"]::before { content: "● "; color: var(--color-warning-text); }
.ai-status[data-status="Unavailable"]::before { content: "● "; color: var(--color-error-solid); }
.ai-header-actions { display: flex; gap: var(--space-1); }

.ai-banner {
    margin: var(--space-2) var(--space-4) 0;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    background: var(--color-info-bg);
    color: var(--color-info-text);
    border: 1px solid var(--color-info-border);
}
.ai-banner-warning { background: var(--color-warning-bg); color: var(--color-warning-text); border-color: var(--color-warning-border); }
.ai-banner-error { background: var(--color-error-bg); color: var(--color-error-text); border-color: var(--color-error-border); }
.ai-mon-alerts .ai-banner { margin: 0 0 var(--space-2); }

.ai-messages { flex: 1; overflow-y: auto; padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); min-height: 0; }

.ai-empty { margin: auto; text-align: center; max-width: 440px; display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
.ai-empty-icon { color: var(--color-success-solid); }
.ai-empty-title { font-weight: 700; font-size: var(--text-lg); }
.ai-muted { color: var(--text-muted); font-size: var(--text-sm); }
.ai-suggestions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); margin-top: var(--space-2); }
.ai-suggestion {
    border: 1px solid var(--border);
    background: var(--surface);
    border-radius: var(--radius-full);
    padding: var(--space-1) var(--space-3);
    font: inherit;
    font-size: var(--text-sm);
    color: var(--text);
    cursor: pointer;
}
.ai-suggestion:hover { border-color: var(--color-success-solid); color: var(--color-success-solid); }

.ai-msg { display: flex; gap: var(--space-2); max-width: 100%; }
.ai-msg-user { justify-content: flex-end; }
.ai-bubble {
    max-width: 80%;
    background: var(--color-success-solid);
    color: #fff;
    padding: var(--space-2) var(--space-4);
    border-radius: 18px 18px 4px 18px;
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    overflow-wrap: anywhere;
}
.ai-avatar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: var(--radius-full); flex-shrink: 0;
    background: var(--color-success-bg); color: var(--color-success-solid);
}
.ai-card {
    min-width: 0;
    max-width: 100%;
    flex: 1;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 4px 16px 16px 16px;
    padding: var(--space-3) var(--space-4);
    box-shadow: var(--shadow-sm);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
}
.ai-msg-denied .ai-card { background: var(--color-warning-bg); border-color: var(--color-warning-border); }
.ai-msg-failed .ai-card { background: var(--color-error-bg); border-color: var(--color-error-border); }

.ai-md > :first-child { margin-top: 0; }
.ai-md > :last-child { margin-bottom: 0; }
.ai-md p, .ai-md ul { margin: 0 0 var(--space-2); }
.ai-md ul { padding-left: 1.25rem; }
.ai-md-heading { font-size: var(--text-lg); font-weight: 700; margin: 0 0 var(--space-2); }
.ai-md code { font-family: var(--font-mono); font-size: 0.95em; background: var(--surface-subtle); padding: 0 4px; border-radius: 4px; }
.ai-md-source { color: var(--text-muted); font-size: var(--text-sm); border-top: 1px solid var(--border); padding-top: var(--space-2); }
.ai-table-wrap { overflow-x: auto; margin: 0 0 var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.ai-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.ai-table th, .ai-table td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.ai-table th { background: var(--surface-subtle); font-weight: 700; }
.ai-table tbody tr:last-child td { border-bottom: none; }

.ai-msg-footer { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.ai-chip {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: var(--text-xs); padding: 2px 8px; border-radius: var(--radius-full);
    background: var(--color-success-bg); color: var(--color-success-text); border: 1px solid var(--color-success-border);
}
.ai-chip-muted { background: var(--surface-subtle); color: var(--text-muted); border-color: var(--border); }

.ai-msg-pending .ai-card { display: flex; align-items: center; gap: var(--space-2); color: var(--text-muted); font-size: var(--text-sm); }
.ai-typing { display: inline-flex; gap: 3px; }
.ai-typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--color-success-solid); animation: ai-typing 1.2s infinite ease-in-out; }
.ai-typing i:nth-child(2) { animation-delay: 0.15s; }
.ai-typing i:nth-child(3) { animation-delay: 0.3s; }
@keyframes ai-typing { 0%, 80%, 100% { opacity: 0.25; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .ai-typing i { animation: none; opacity: 0.6; } }

.ai-composer {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
    margin: 0 var(--space-4);
    padding: var(--space-2);
    border: 1.5px solid var(--color-success-solid);
    border-radius: 16px;
    background: var(--surface);
}
.ai-composer:focus-within { box-shadow: 0 0 0 3px rgba(21, 128, 61, 0.2); }
.ai-input {
    flex: 1;
    border: none;
    resize: none;
    outline: none;
    font: inherit;
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    padding: 6px var(--space-2);
    max-height: 160px;
    background: transparent;
    color: var(--text);
}
.ai-send {
    width: 36px; height: 36px; flex-shrink: 0;
    border: none; border-radius: var(--radius-full);
    background: var(--color-success-solid); color: #fff; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
}
.ai-send:hover { background: var(--color-success-solid-hover); }
.ai-send:disabled { opacity: 0.5; cursor: wait; }
.ai-footnote { text-align: center; font-size: var(--text-xs); color: var(--text-muted); padding: var(--space-2) var(--space-4) var(--space-3); margin: 0; }

.ai-shell-floating .ai-messages { padding: var(--space-3); }
.ai-shell-floating .ai-bubble { max-width: 88%; }

@media (max-width: 767.98px) {
    .ai-sidebar { display: none; }
    .ai-bubble { max-width: 92%; }
    .ai-messages { padding: var(--space-3); }
    .ai-composer { margin: 0 var(--space-3); }
}

/* Monitoring */
.ai-monitoring-controls { align-items: center; }
.ai-select { font: inherit; font-size: var(--text-sm); padding: 6px 10px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--text); }
.ai-mon-section { margin-bottom: var(--space-6); min-width: 0; }
.ai-mon-section h2 { font-size: var(--text-lg); font-weight: 700; margin: 0 0 var(--space-3); }
.ai-mon-section .table-wrap { margin-bottom: var(--space-3); }
.ai-mon-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: var(--space-4); }
@media (max-width: 599.98px) { .ai-mon-grid { grid-template-columns: 1fr; } }
.ai-mon-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-3); }
.ai-mon-card {
    display: flex; flex-direction: column; gap: 2px;
    background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--border-strong);
    border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); box-shadow: var(--shadow-sm);
}
.ai-mon-card-label { font-size: var(--text-xs); color: var(--text-muted); font-weight: 600; }
.ai-mon-card-value { font-size: var(--text-xl); font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.ai-mon-card-hint { font-size: var(--text-xs); color: var(--text-muted); }
.ai-mon-healthy { border-left-color: var(--color-success-solid); }
.ai-mon-warning { border-left-color: var(--color-warning-text); }
.ai-mon-critical { border-left-color: var(--color-error-solid); }

/* AI Assistant: application-scope rejections read as neutral information, not errors; same-site menu links. */
.ai-msg-scope .ai-card { background: var(--surface-subtle); }
.ai-md .ai-link { color: var(--color-success-text); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
