@import url("https://fonts.googleapis.com/css2?family=Noto+Serif+TC:wght@600;700&display=swap");

/* ============================================================
   Theme Palette — flat colour blocks on warm paper
   Single source of truth — change colors here only.
   Surfaces are told apart by tone, never by lines: --vault-border
   is transparent, "tonal" is the block colour used where a border
   would have been.
   ============================================================ */
:root {
  /* Layers, back to front: page < card < control. Each layer is
     lighter than the one behind it, so the eye reads depth by tone. */
  /* Palette keyed to the navbar: its warm dark brown is the primary
     and every neutral (page, edges, muted text) leans toward that
     hue. Cards stay near-white with 1px edges; a copper secondary
     carries hover and emphasis; status colours stay sky/green/
     amber/coral. DaisyUI "bumblebee" shapes and layering remain. */
  --vault-cream:       #f3f0ec;
  --vault-paper:       #fdfcfa;
  --vault-control:     #ffffff;
  --vault-dark:        #2a2521;
  --vault-dark-rgb:    42, 37, 33;
  --vault-primary:     #4a433c;
  --vault-primary-rgb: 74, 67, 60;
  --vault-primary-content: #f4f0eb;
  --vault-secondary:   #a8672c;
  --vault-secondary-rgb: 168, 103, 44;
  --vault-secondary-content: #ffffff;
  --vault-tan:         #c9a97e;
  --vault-muted:       #766d64;
  --vault-border:      #e5e0da;
  --vault-border-rgb:  42, 37, 33;
  --vault-tonal:       #f3f0ec;
  --vault-tonal-hover: #e9e4de;
  --vault-thead-bg:    #ddd6ce;
  /* 1px edges on cards, fields and menus */
  --vault-line:        #e5e0da;
  --vault-line-width:  1px;
  --vault-accent:      #4a433c;
  --vault-accent-rgb:  74, 67, 60;
  --vault-neutral:     #4a433c;
  --vault-neutral-rgb: 74, 67, 60;
  --vault-neutral-content: #ebe8e5;
  --vault-sage:        #1fc48a; /* = success */
  --vault-danger:      #ef5a55;

  /* Surfaces: solid blocks; a soft shadow only under floating layers */
  --glass-bg:          var(--vault-control);
  --glass-bg-strong:   var(--vault-control);
  --glass-border:      transparent;
  --glass-blur:        none;
  --glass-highlight:   none;
  --glass-shadow:      none;
  --glass-shadow-lift: none;
  /* Panels (cards, list groups, page tables) lift a touch off the page */
  --vault-panel-shadow:
    0 1px 2px rgba(var(--vault-dark-rgb), 0.05),
    0 6px 16px -8px rgba(var(--vault-dark-rgb), 0.2);

  /* Shape and rhythm (autumn: fields 0.5rem, boxes 1rem) */
  --radius-sm:         0.5rem;
  --radius-md:         0.75rem;
  --radius-lg:         1rem;
  --radius-pill:       999px;

  /* Bootstrap semantic colors — hex + rgb pairs */
  --bs-primary:        #4a433c;
  --bs-primary-rgb:    74, 67, 60;
  --bs-secondary:      #a8672c;
  --bs-secondary-rgb:  168, 103, 44;
  --bs-success:        #1fc48a;
  --bs-success-rgb:    31, 196, 138;
  --bs-info:           #39a7ee;
  --bs-info-rgb:       57, 167, 238;
  --bs-warning:        #f5b500;
  --bs-warning-rgb:    245, 181, 0;
  --bs-danger:         #ef5a55;
  --bs-danger-rgb:     239, 90, 85;
  --bs-dark:           #2a2521;
  --bs-dark-rgb:       42, 37, 33;
  --bs-light:          #f3f0ec;
  --bs-light-rgb:      243, 240, 236;

  /* Bootstrap emphasis / subtle / border variants */
  --bs-primary-text-emphasis:     var(--vault-primary);
  --bs-primary-bg-subtle:         rgba(74, 67, 60, 0.1);
  --bs-primary-border-subtle:     rgba(74, 67, 60, 0.3);
  --bs-secondary-text-emphasis:   var(--vault-secondary);
  --bs-secondary-bg-subtle:       rgba(168, 103, 44, 0.14);
  --bs-secondary-border-subtle:   var(--vault-border);
  --bs-success-text-emphasis:     #0f5a44;
  --bs-success-bg-subtle:         rgba(31, 196, 138, 0.16);
  --bs-success-border-subtle:     rgba(31, 196, 138, 0.4);
  --bs-info-text-emphasis:        #1d4d6b;
  --bs-info-bg-subtle:            rgba(57, 167, 238, 0.16);
  --bs-info-border-subtle:        rgba(57, 167, 238, 0.4);
  --bs-warning-text-emphasis:     #7a3d0f;
  --bs-warning-bg-subtle:         rgba(245, 181, 0, 0.18);
  --bs-warning-border-subtle:     rgba(245, 181, 0, 0.45);
  --bs-danger-text-emphasis:      #8d1f1f;
  --bs-danger-bg-subtle:          rgba(239, 90, 85, 0.14);
  --bs-danger-border-subtle:      rgba(239, 90, 85, 0.4);
  --bs-dark-text-emphasis:        var(--vault-dark);
  --bs-dark-bg-subtle:            rgba(var(--vault-dark-rgb), 0.08);
  --bs-dark-border-subtle:        rgba(var(--vault-dark-rgb), 0.2);
  --bs-light-text-emphasis:       var(--vault-dark);
  --bs-light-bg-subtle:           rgba(255, 255, 255, 0.5);
  --bs-light-border-subtle:       var(--vault-border);

  /* Bootstrap global overrides */
  --bs-body-bg:                var(--vault-cream);
  --bs-body-color:             var(--vault-dark);
  --bs-body-font-family:       -apple-system, BlinkMacSystemFont,
    "SF Pro Text", "Noto Sans TC", "PingFang TC", "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --bs-body-font-size:         0.9375rem;
  --bs-body-line-height:       1.6;
  --bs-heading-color:          var(--vault-dark);
  --bs-border-color:           var(--vault-border);
  --bs-border-width:           0;
  --bs-border-radius:          var(--radius-sm);
  --bs-border-radius-sm:       0.5rem;
  --bs-border-radius-lg:       var(--radius-md);
  --bs-secondary-color:        var(--vault-muted);
  --bs-tertiary-color:         rgba(var(--vault-dark-rgb), 0.45);
  --bs-tertiary-bg:            var(--vault-paper);
  --bs-link-color-rgb:         var(--vault-dark-rgb);
  --bs-link-hover-color-rgb:   var(--vault-secondary-rgb);
  --bs-link-decoration:        none;
  --bs-link-hover-decoration:  underline;
  --bs-emphasis-color:         var(--vault-dark);
  --bs-focus-ring-color:       rgba(var(--vault-primary-rgb), 0.28);
}

/* ============================================================
   Page Background — one flat tone; blocks sit on it by colour
   ============================================================ */
body {
  background-color: var(--vault-cream);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ============================================================
   Base Typography
   ============================================================ */
img {
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: 600;
  letter-spacing: -0.01em;
}

main h2 {
  font-size: 1.75rem;
  letter-spacing: -0.02em;
}

a {
  transition: color 0.2s;
}

::selection {
  background-color: rgba(var(--vault-primary-rgb), 0.28);
  color: var(--vault-dark);
}

/* Numbers line up in tables and tiles */
.table,
.fs-4,
.detail-props,
.detail-file-props {
  font-variant-numeric: tabular-nums;
}

.text-muted,
.form-text {
  color: var(--vault-muted) !important;
}

small,
.small {
  font-size: 0.8125rem;
}

/* ============================================================
   Bootstrap Icons (button alignment)
   ============================================================ */
.btn:has(.bi) {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}
.btn .bi {
  flex-shrink: 0;
}

/* ============================================================
   Buttons — capsule glass; primary is the one filled control
   ============================================================ */
.btn {
  --bs-btn-border-width: var(--vault-line-width);
  --bs-btn-border-radius: var(--radius-pill);
  --bs-btn-font-weight: 500;
  --bs-btn-padding-x: 1rem;
  --bs-btn-focus-box-shadow:
    0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.28);
  transition: background-color 0.2s, border-color 0.2s, color 0.2s,
    box-shadow 0.2s;
}
.btn-sm {
  --bs-btn-padding-x: 0.8rem;
}
.btn-lg {
  --bs-btn-padding-x: 1.5rem;
  --bs-btn-border-radius: var(--radius-pill);
}

/* Primary — bumblebee yellow with dark-brown text */
.btn-primary {
  --bs-btn-bg:                 var(--vault-primary);
  --bs-btn-border-color:       var(--vault-primary);
  --bs-btn-color:              var(--vault-primary-content);
  --bs-btn-hover-bg:           #3d3731;
  --bs-btn-hover-border-color: #3d3731;
  --bs-btn-hover-color:        var(--vault-primary-content);
  --bs-btn-active-bg:          #322d28;
  --bs-btn-active-border-color:#322d28;
  --bs-btn-active-color:       var(--vault-primary-content);
  --bs-btn-disabled-bg:        rgba(var(--vault-primary-rgb), 0.22);
  --bs-btn-disabled-border-color: transparent;
  --bs-btn-disabled-color:     rgba(255, 255, 255, 0.75);
}
.btn-secondary {
  --bs-btn-bg:                 var(--vault-secondary) !important;
  --bs-btn-border-color:       var(--vault-secondary) !important;
  --bs-btn-color:              var(--vault-secondary-content) !important;
  --bs-btn-hover-bg:           #955a25 !important;
  --bs-btn-hover-border-color: #955a25 !important;
  --bs-btn-hover-color:        var(--vault-secondary-content) !important;
}
.btn-dark {
  --bs-btn-bg:                 var(--vault-neutral);
  --bs-btn-border-color:       var(--vault-neutral);
  --bs-btn-color:              var(--vault-neutral-content);
  --bs-btn-hover-bg:           #5b544c;
  --bs-btn-hover-border-color: #5b544c;
}

/* Glass buttons: outline variants become translucent capsules */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-dark,
.btn-light,
.btn-secondary {
  --bs-btn-bg:                 var(--vault-control);
  --bs-btn-border-color:       var(--vault-line);
  --bs-btn-hover-bg:           var(--vault-thead-bg);
  --bs-btn-hover-border-color: var(--vault-line);
  --bs-btn-active-bg:          var(--vault-cream);
  --bs-btn-active-border-color:var(--vault-line);
  --bs-btn-disabled-bg:        rgba(255, 255, 255, 0.5);
  --bs-btn-disabled-border-color: var(--vault-line);
  --bs-btn-disabled-color:     rgba(var(--vault-dark-rgb), 0.35);
}
.btn-outline-primary {
  --bs-btn-color:              var(--vault-primary);
  --bs-btn-hover-bg:           rgba(var(--vault-primary-rgb), 0.1);
  --bs-btn-hover-color:        var(--vault-primary);
  --bs-btn-active-color:       var(--vault-primary);
}
.btn-outline-secondary,
.btn-light,
.btn-secondary {
  --bs-btn-color:              var(--vault-dark);
  --bs-btn-hover-color:        var(--vault-dark);
  --bs-btn-active-color:       var(--vault-dark);
}
.btn-outline-dark {
  --bs-btn-color:              var(--vault-dark);
  --bs-btn-hover-color:        var(--vault-dark);
  --bs-btn-active-color:       var(--vault-dark);
}
.btn-outline-danger {
  --bs-btn-color:              #8d1f1f;
  --bs-btn-bg:                 var(--vault-control);
  --bs-btn-border-color:       var(--vault-line);
  --bs-btn-hover-bg:           var(--vault-danger);
  --bs-btn-hover-border-color: var(--vault-danger);
  --bs-btn-hover-color:        #8d1f1f;
}
.btn-danger {
  --bs-btn-bg:                 var(--vault-danger);
  --bs-btn-color:              #8d1f1f;
  --bs-btn-hover-color:        #8d1f1f;
}
.btn-danger {
  --bs-btn-border-color:       transparent;
  --bs-btn-hover-border-color: transparent;
}
.btn-link {
  --bs-btn-border-radius: var(--radius-sm);
}
.btn-close {
  --bs-btn-close-opacity: 0.5;
}

/* ============================================================
   Navbar — floating glass bar, dark text on paper
   ============================================================ */
.navbar-vault {
  background: var(--vault-neutral);
  --bs-navbar-color:            rgba(235, 232, 229, 0.8);
  --bs-navbar-hover-color:      #fff;
  --bs-navbar-active-color:     #fff;
  --bs-navbar-brand-color:      #fff;
  --bs-navbar-brand-hover-color: var(--vault-tan);
  --bs-navbar-toggler-border-color: transparent;
  --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.8%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

.navbar-vault .navbar-brand {
  font-family: "Noto Serif TC", "Songti TC", "PMingLiU", Georgia, serif;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #fff;
}

.navbar-vault .nav-link {
  color: rgba(235, 232, 229, 0.8);
  border-radius: var(--radius-pill);
  padding: 0.35rem 0.75rem;
  transition: color 0.2s, background-color 0.2s;
}

.navbar-vault .nav-link:hover,
.navbar-vault .nav-link:focus {
  color: #fff;
  background-color: rgba(255, 255, 255, 0.1);
}

/* The primary is the navbar itself, so the active pill lightens */
.navbar-vault .nav-link.active {
  color: #fff;
  background-color: rgba(255, 255, 255, 0.18);
}

.navbar-vault .dropdown-toggle {
  color: rgba(235, 232, 229, 0.8);
}

.navbar-vault .navbar-toggler:focus {
  box-shadow: 0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.22);
}

/* ============================================================
   Cards — glass panels with a lit top edge
   ============================================================ */
.card {
  --bs-card-bg:            var(--vault-paper);
  --bs-card-border-width:  var(--vault-line-width);
  --bs-card-border-color:  var(--vault-line);
  --bs-card-border-radius: var(--radius-lg);
  --bs-card-inner-border-radius: calc(var(--radius-lg) - 1px);
  --bs-card-cap-bg:        var(--vault-thead-bg);
  --bs-card-cap-color:     var(--vault-dark);
  --bs-card-cap-padding-y: 0.7rem;
  box-shadow: var(--vault-panel-shadow);
}

.card-header {
  border-bottom: var(--vault-line-width) solid var(--vault-line);
  font-weight: 600;
}

.card-footer {
  border-top: 0;
  background: var(--vault-thead-bg);
}

.auth-card {
  box-shadow: none;
}

.auth-card .card-body {
  padding: 2.5rem 2rem;
}

/* ============================================================
   Tables — a tinted header block and tinted hover; no rules
   ============================================================ */
.table {
  --bs-table-bg: var(--vault-control);
  --bs-table-color: var(--vault-dark);
  --bs-table-striped-bg: #faf8f6;
  --bs-table-hover-bg: var(--vault-tonal-hover);
  --bs-table-hover-color: var(--vault-dark);
  --bs-table-border-color: var(--vault-line);
  --bs-table-border-width: 0;
  border-collapse: separate;
  border-spacing: 0;
  border: var(--vault-line-width) solid var(--vault-line);
  border-radius: var(--radius-md);
}
/* Rounded corners without overflow: hidden, which would stop the
   sticky header from sticking. */
.table > thead > tr:first-child > th:first-child {
  border-top-left-radius: calc(var(--radius-md) - 1px);
}
.table > thead > tr:first-child > th:last-child {
  border-top-right-radius: calc(var(--radius-md) - 1px);
}
.table > tbody > tr:last-child > td:first-child {
  border-bottom-left-radius: calc(var(--radius-md) - 1px);
}
.table > tbody > tr:last-child > td:last-child {
  border-bottom-right-radius: calc(var(--radius-md) - 1px);
}
/* Every table is striped and hoverable, through Bootstrap's own
   cell-shadow mechanism so it works whatever the row markup. */
.table > tbody > tr:nth-of-type(even) > * {
  --bs-table-bg-type: var(--bs-table-striped-bg);
}
.table > tbody > tr:hover > * {
  --bs-table-bg-state: var(--bs-table-hover-bg);
}

.table > thead {
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
}

.table > thead th {
  border: 0;
  border-bottom: var(--vault-line-width) solid #cdc5bc;
  font-weight: 600;
  color: var(--vault-dark);
}

.table > tbody > tr > td {
  border: 0;
  padding-top: 0.65rem;
  padding-bottom: 0.65rem;
}

.table > tbody > tr {
  transition: background-color 0.15s;
}

.table-light {
  --bs-table-bg: var(--vault-thead-bg);
  --bs-table-color: var(--vault-muted);
  --bs-table-border-color: transparent;
}

/* ============================================================
   Forms — frosted fields, brown focus halo
   ============================================================ */
.form-control,
.form-select {
  background-color: var(--vault-control);
  border: var(--vault-line-width) solid var(--vault-line);
  border-radius: var(--radius-sm);
  padding-top: 0.45rem;
  padding-bottom: 0.45rem;
  transition: box-shadow 0.2s, background-color 0.2s;
}
.form-control-sm,
.form-select-sm {
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
}
.form-control::placeholder {
  color: rgba(var(--vault-dark-rgb), 0.4);
}
.form-control:hover,
.form-select:hover {
  border-color: #d2cbc3;
}
.form-control:focus,
.form-select:focus {
  background-color: var(--vault-control);
  border-color: var(--vault-primary);
  box-shadow: 0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.22);
}
.form-control:disabled,
.form-select:disabled {
  background-color: rgba(255, 255, 255, 0.5);
}

.form-label {
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--vault-muted);
  margin-bottom: 0.3rem;
}

.form-check-input {
  border: var(--vault-line-width) solid var(--vault-line);
  background-color: var(--vault-control);
}
.form-check-input:checked {
  background-color: var(--vault-accent);
  border-color: var(--vault-accent);
}

.form-check-input:focus {
  box-shadow: 0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.28);
}

/* Toggle switches read as clickable */
.form-switch .form-check-input,
.form-switch .form-check-label {
  cursor: pointer;
}

/* ============================================================
   Badges — quiet pills; the tint carries the meaning
   ============================================================ */
.badge {
  --bs-badge-border-radius: var(--radius-pill);
  --bs-badge-padding-x: 0.6em;
  --bs-badge-padding-y: 0.32em;
  --bs-badge-font-weight: 500;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.badge.text-bg-secondary,
.badge.bg-secondary,
.badge.text-bg-dark,
.badge.bg-dark {
  background-color: var(--vault-neutral) !important;
  color: var(--vault-neutral-content) !important;
}

.badge.text-bg-info {
  background-color: var(--vault-primary) !important;
  color: var(--vault-primary-content);
}

.badge.text-bg-light,
.badge.bg-light {
  background-color: var(--vault-tonal-hover) !important;
  color: var(--vault-dark);
  border: 0 !important;
}

.badge.text-bg-success,
.badge.bg-success {
  background-color: var(--bs-success) !important;
  color: var(--bs-success-text-emphasis) !important;
}

.badge.text-bg-danger,
.badge.bg-danger {
  background-color: var(--bs-danger) !important;
  color: var(--bs-danger-text-emphasis) !important;
}

.badge.bg-warning {
  background-color: var(--bs-warning) !important;
  color: var(--bs-warning-text-emphasis) !important;
}

.badge.bg-info {
  background-color: var(--bs-info) !important;
  color: var(--bs-info-text-emphasis) !important;
}

/* ============================================================
   Nav (shared link color for pills + tabs)
   ============================================================ */
.nav {
  --bs-nav-link-color: var(--vault-muted);
  --bs-nav-link-hover-color: var(--vault-dark);
}

.nav-pills {
  --bs-nav-pills-border-radius: var(--radius-pill);
  --bs-nav-pills-link-active-bg: var(--vault-primary);
  --bs-nav-pills-link-active-color: var(--vault-primary-content);
}

/* Tabs read as a segmented control */
.nav-tabs {
  --bs-nav-tabs-border-width: 0;
  --bs-nav-tabs-border-radius: var(--radius-pill);
  --bs-nav-tabs-link-active-color: var(--vault-dark);
  --bs-nav-tabs-link-active-bg: var(--vault-control);
  --bs-nav-tabs-link-active-border-color: transparent;
  --bs-nav-tabs-link-hover-border-color: transparent;
  display: inline-flex;
  gap: 0.125rem;
  padding: 0.25rem;
  border-radius: var(--radius-pill);
  background: var(--vault-tonal);
  border-bottom: 0;
}
.nav-tabs .nav-link {
  border-radius: var(--radius-pill);
  padding: 0.35rem 0.9rem;
  font-size: 0.875rem;
  transition: background-color 0.2s, color 0.2s, box-shadow 0.2s;
}
.nav-tabs .nav-link.active {
  box-shadow: none;
}
/* A page-level table is a panel too; one inside a card already has one */
.table-responsive:not(.card *) {
  border-radius: var(--radius-md);
  box-shadow: var(--vault-panel-shadow);
}
/* Floating layers cast no shadow; they are told apart by tone */
.dropdown-menu,
.toast,
.preview-popup-float,
.tagify__dropdown,
.tooltip-inner,
.popover {
  box-shadow: none !important;
}
.dropdown-menu,
.tagify__dropdown {
  background: var(--vault-control);
}

/* ============================================================
   Pagination — one glass capsule
   ============================================================ */
.pagination {
  --bs-pagination-color:            var(--vault-dark);
  --bs-pagination-bg:               var(--vault-control);
  --bs-pagination-border-width:     var(--vault-line-width);
  --bs-pagination-border-color:     var(--vault-line);
  --bs-pagination-hover-color:      var(--vault-dark);
  --bs-pagination-hover-bg:         var(--vault-thead-bg);
  --bs-pagination-hover-border-color: transparent;
  --bs-pagination-focus-box-shadow:
    0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.28);
  --bs-pagination-active-bg:        var(--vault-primary);
  --bs-pagination-active-border-color: var(--vault-primary);
  --bs-pagination-active-color:     var(--vault-primary-content);
  --bs-pagination-disabled-color:   rgba(var(--vault-dark-rgb), 0.35);
  --bs-pagination-disabled-bg:      rgba(var(--vault-dark-rgb), 0.03);
  --bs-pagination-disabled-border-color: transparent;
  --bs-pagination-border-radius:    var(--radius-pill);
}

/* ============================================================
   Dropdowns — floating glass sheet
   ============================================================ */
.dropdown-menu {
  --bs-dropdown-bg:               var(--vault-control);
  --bs-dropdown-border-width:     var(--vault-line-width);
  --bs-dropdown-border-color:     var(--vault-line);
  --bs-dropdown-border-radius:    var(--radius-md);
  --bs-dropdown-inner-border-radius: calc(var(--radius-md) - 1px);
  --bs-dropdown-padding-y:        0.4rem;
  --bs-dropdown-item-padding-x:   0.9rem;
  --bs-dropdown-link-hover-bg:    rgba(var(--vault-dark-rgb), 0.06);
  --bs-dropdown-link-hover-color: var(--vault-dark);
  --bs-dropdown-link-active-bg:   var(--vault-primary);
  --bs-dropdown-link-active-color: var(--vault-primary-content);
  --bs-dropdown-divider-bg:       var(--vault-tonal-hover);
  box-shadow: var(--glass-shadow-lift);
}
.dropdown-item {
  border-radius: var(--radius-sm);
  margin: 0 0.4rem;
  width: auto;
}

/* ============================================================
   List Group
   ============================================================ */
.list-group {
  box-shadow: var(--vault-panel-shadow);
  --bs-list-group-bg:                   var(--vault-control);
  --bs-list-group-border-width:         var(--vault-line-width);
  --bs-list-group-border-color:         var(--vault-line);
  --bs-list-group-border-radius:        var(--radius-md);
  --bs-list-group-active-bg:            var(--vault-primary);
  --bs-list-group-active-border-color:  var(--vault-primary);
  --bs-list-group-active-color:         var(--vault-primary-content);
  --bs-list-group-action-hover-bg:      rgba(var(--vault-dark-rgb), 0.04);
}

/* ============================================================
   Misc Components
   ============================================================ */
hr {
  border: none;
  height: 4px;
  border-radius: 2px;
  background: var(--vault-thead-bg);
  opacity: 1;
}

.toast {
  --bs-toast-bg:              var(--vault-control);
  --bs-toast-border-width:    var(--vault-line-width);
  --bs-toast-border-color:    var(--vault-line);
  --bs-toast-border-radius:   var(--radius-md);
  --bs-toast-box-shadow:      var(--glass-shadow-lift);
}
.toast.text-bg-success,
.toast.text-bg-danger,
.toast.text-bg-primary {
  color: #fff;
}

.modal {
  --bs-modal-bg:                   var(--vault-control);
  --bs-modal-border-width:         var(--vault-line-width);
  --bs-modal-border-color:         var(--vault-line);
  --bs-modal-border-radius:        var(--radius-lg);
  --bs-modal-inner-border-radius:  calc(var(--radius-lg) - 1px);
  --bs-modal-header-border-width:  0;
  --bs-modal-footer-border-width:  0;
  --bs-backdrop-opacity:           0.4;
}

.modal-header,
.modal-footer {
  background: var(--vault-thead-bg);
}

.modal-content {
  box-shadow: none;
}

.alert {
  --bs-alert-border-radius: var(--radius-md);
  --bs-alert-border-color: transparent;
  border: 0;
}

.tooltip {
  --bs-tooltip-bg: var(--vault-neutral);
  --bs-tooltip-border-radius: var(--radius-sm);
  --bs-tooltip-padding-x: 0.7rem;
  --bs-tooltip-padding-y: 0.45rem;
}

.progress {
  --bs-progress-bg: rgba(var(--vault-dark-rgb), 0.08);
  --bs-progress-bar-bg: var(--vault-primary);
  --bs-progress-bar-color: var(--vault-primary-content);
  --bs-progress-border-radius: var(--radius-pill);
}

.accordion {
  --bs-accordion-border-width: 0;
  --bs-accordion-border-color: transparent;
  --bs-accordion-border-radius: var(--radius-md);
  --bs-accordion-btn-focus-box-shadow:
    0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.28);
}

/* ============================================================
   Footer
   ============================================================ */
.footer-vault {
  border-top: var(--vault-line-width) solid var(--vault-line);
  color: var(--vault-muted);
  font-size: 0.8125rem;
}

/* ============================================================
   Accessibility — honour reduced motion / transparency
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* ============================================================
   Upload Drop Zone
   ============================================================ */
.border-dashed {
  border-style: dashed !important;
}

/* Multi-asset upload rows */
.upload-asset-row .card-header input {
  border: none;
  background: transparent;
  box-shadow: none;
}
.upload-asset-row .card-header input:focus {
  box-shadow: none;
}

.upload-dropzone {
  transition: border-color 0.2s, background-color 0.2s;
}

.upload-ghost-row {
  opacity: 0.5;
  transition: opacity 0.2s;
}
.upload-ghost-row:hover,
.upload-ghost-row:focus-within {
  opacity: 0.8;
}

/* File card (shared base for upload + edit file thumbnails) */
.file-card {
  width: 110px;
  text-align: center;
  position: relative;
  cursor: grab;
  transition: opacity 0.2s;
}
.file-card:active { cursor: grabbing; }
.file-card-inner {
  width: 110px;
  height: 110px;
  border: var(--vault-line-width) solid var(--vault-line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--vault-cream);
  position: relative;
}
.file-card-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
/* A thumb with a large preview opens the viewer, so it takes clicks. */
.file-card-thumb[role="button"] {
  pointer-events: auto;
  cursor: zoom-in;
}
.file-card-icon {
  font-size: 2rem;
  color: var(--vault-muted);
}
.file-card-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 0.625rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s;
  cursor: pointer;
}
.file-card:hover .file-card-remove { opacity: 1; }
/* The fade lives on the toggle, not the wrapper: a faded wrapper
   would form a stacking context that traps the open menu. */
.file-card-menu {
  position: absolute;
  top: 4px;
  left: 4px;
}
.file-card-menu-toggle {
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 0.75rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s;
}
.file-card:hover .file-card-menu-toggle,
.file-card-menu-toggle.show { opacity: 1; }
/* Titles wrap rather than truncate so the whole target is readable. */
.file-card-menu .dropdown-menu {
  min-width: 12rem;
  max-width: 24rem;
}
.file-card-menu .dropdown-item {
  white-space: normal;
  overflow-wrap: anywhere;
}
.file-card-remove:disabled {
  cursor: not-allowed;
  opacity: 0 !important;
}
.file-card-label {
  margin-top: 0.25rem;
  font-size: 0.75rem;
  line-height: 1.3;
}

/* ============================================================
   Preview Popup
   ============================================================ */
.preview-popup-float {
  display: none;
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  padding: 6px;
  border-radius: var(--radius-md);
  background: var(--vault-control);
  border: var(--vault-line-width) solid var(--vault-line);
  box-shadow: var(--glass-shadow-lift);
}
/* The popup is a preview, not a viewer: whatever the source (the 512px
   preview tier, or the full original while an upload is still local),
   it is capped at the hover-popup display size. */
.preview-popup-float img {
  display: block;
  max-width: 300px;
  max-height: 300px;
  width: auto;
  height: auto;
  border-radius: calc(var(--radius-md) - 4px);
}

.spinner-border.text-secondary {
  color: var(--vault-muted) !important;
}

/* ============================================================
   Tagify Overrides
   ============================================================ */
.tagify {
  --tags-border-color: var(--vault-line);
  --tags-hover-border-color: var(--vault-line);
  --tags-focus-border-color: var(--vault-line);
  --tag-bg: rgba(var(--vault-primary-rgb), 0.12);
  --tag-hover: rgba(var(--vault-primary-rgb), 0.2);
  --tag-text-color: var(--vault-dark);
  --tag-remove-btn-color: var(--vault-muted);
  --tag-remove-btn-color--hover: var(--vault-dark);
  --tag-pad: 0.1rem 0.5rem;
  --tag-border-radius: 999px;
  min-height: 0;
  padding: 0;
  font-size: 0.875rem;
  border-radius: var(--radius-sm);
  font-family: var(--bs-body-font-family);
  background: var(--vault-control);
  border-width: var(--vault-line-width);
  transition: background-color 0.2s, box-shadow 0.2s;
}
.tagify:hover {
  --tags-hover-border-color: #d2cbc3;
}

.tagify > .tagify__input {
  margin: 1px;
  padding: 0.2rem 0.5rem;
  min-height: 0;
  line-height: 1.5;
}

.tagify--focus {
  --tags-focus-border-color: var(--vault-primary);
  box-shadow: 0 0 0 0.2rem rgba(var(--vault-primary-rgb), 0.22);
}

.tagify__dropdown {
  /* Tagify paints its own blue accent on the list frame and the active
     row; hand it the theme colours instead. */
  --tagify-dd-color-primary: var(--vault-primary);
  --tagify-dd-text-color: var(--vault-dark);
  --tagify-dd-bg-color: transparent;
  --tagify-dd-item-pad: 0.4em 0.7em;
  background: var(--vault-paper);
  border: var(--vault-line-width) solid var(--vault-line);
  box-shadow: var(--glass-shadow-lift);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.tagify__dropdown__wrapper {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.tagify__dropdown__item {
  border-radius: var(--radius-sm);
  margin: 0 0.3rem;
}

.tagify__dropdown__item--active {
  background: rgba(var(--vault-primary-rgb), 0.12);
  color: var(--vault-dark);
}

.filter-form .tagify {
  overflow: hidden;
}

/* ============================================================
   User Scope Roles — read-only hints, expandable 2x2 matrix
   ============================================================ */
.scope-hint {
  display: flex;
  gap: 0.5rem;
  max-width: 22rem;
  font-size: 0.8125rem;
  line-height: 1.6;
}
.scope-hint-key {
  flex-shrink: 0;
  color: var(--vault-muted);
}
.scope-hint-key .bi {
  margin-right: 0.25rem;
}
.scope-hint-names {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.scope-toggle {
  font-size: 0.8125rem;
  color: var(--vault-secondary);
  text-decoration: none;
}
.scope-toggle:hover {
  color: var(--vault-primary);
}
.scope-toggle .bi-chevron-down {
  font-size: 0.75em;
  transition: transform 0.2s;
}
.scope-toggle[aria-expanded="true"] .bi-chevron-down {
  transform: rotate(180deg);
}
.table > tbody > .scope-panel-row > .scope-panel-cell {
  padding: 0;
  border-bottom-width: 0;
}
.table-hover > tbody > .scope-panel-row:hover > * {
  --bs-table-bg-state: transparent;
}
.scope-panel {
  /* Stays in view while the table scrolls sideways on phones */
  position: sticky;
  left: 0.75rem;
  max-width: calc(100vw - 3rem);
  margin: 0 0.75rem 0.75rem;
  padding: 1rem;
  background: var(--vault-tonal);
  border-radius: var(--radius-md);
}
.user-role-select {
  min-width: 8.5rem;
}
.scope-matrix {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.5rem 1rem;
  align-items: center;
  max-width: 52rem;
}
.scope-matrix-cell .tagify {
  width: 100%;
}
.scope-matrix-head {
  font-weight: 600;
  font-size: 0.875rem;
}
.scope-matrix-head .bi,
.scope-matrix-rowhead .bi {
  margin-right: 0.375rem;
  color: var(--vault-muted);
}
.scope-matrix-head small {
  margin-left: 0.25rem;
  font-weight: 400;
}
.scope-matrix-rowhead {
  font-weight: 600;
  font-size: 0.875rem;
  padding-right: 0.5rem;
}
/* Only shown once the matrix collapses to one column */
.scope-matrix-cell-label {
  display: none;
}
.scope-panel-note {
  margin: 0.75rem 0 0;
  font-size: 0.8125rem;
  color: var(--vault-muted);
}
@media (max-width: 575.98px) {
  .scope-matrix {
    grid-template-columns: minmax(0, 1fr);
  }
  .scope-matrix-corner,
  .scope-matrix-head,
  .scope-matrix-rowhead {
    display: none;
  }
  .scope-matrix-cell-label {
    display: block;
    margin-bottom: 0.25rem;
    font-size: 0.8125rem;
    color: var(--vault-muted);
  }
}

/* ============================================================
   Semantic Utilities
   ============================================================ */

/* Public-facing field accent */
.field-public {
  background: rgba(var(--bs-success-rgb), 0.1);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.75rem;
}
.field-public-form {
  border: 0;
  border-radius: var(--radius-md);
  padding: 0.75rem;
  background: rgba(var(--bs-success-rgb), 0.05);
}
.field-public-label {
  color: var(--vault-sage);
  font-weight: 600;
}
.field-public-row {
  background: rgba(var(--bs-success-rgb), 0.08);
}

/* Download page preview column */
.download-preview-col { width: 60px; }
@media (min-width: 768px) {
  .download-preview-col { width: 100px; }
}

/* Detail page two-column property list */
.detail-props {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0;
}
.detail-props dt {
  padding: 0.5rem 0.75rem;
  border-bottom: 0;
  font-weight: 500;
  color: var(--vault-muted);
  white-space: nowrap;
}
.detail-props dd {
  padding: 0.5rem 0.75rem 0.5rem 0;
  border-bottom: 0;
  margin-bottom: 0;
  overflow-wrap: break-word;
  word-break: break-word;
  min-width: 0;
}
.detail-props dt:nth-of-type(even),
.detail-props dd:nth-of-type(even) {
  background: var(--vault-tonal);
}
.detail-props dt:nth-of-type(even) {
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.detail-props dd:nth-of-type(even) {
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* Collapsed technical details: present but visually secondary */
.tech-details summary {
  font-size: 0.8125rem;
  color: var(--vault-muted);
  cursor: pointer;
  list-style: none;
}
.tech-details summary::before {
  content: "\203A";
  display: inline-block;
  width: 1em;
  transition: transform 0.15s;
}
.tech-details[open] summary::before { transform: rotate(90deg); }
.tech-details .detail-file-props {
  font-size: 0.8125rem;
  color: var(--vault-muted);
}
.tech-details .detail-file-props dt { color: var(--vault-muted); }

/* Audit change log (異動紀錄) */
/* Every record a revision touched, one row per line: its title
   (skipped on the record's own page), a whole-record row such as
   新增資產, then one labelled row per changed field. */
.audit-record + .audit-record {
  margin-top: 0.5rem;
}
.audit-object {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--vault-dark);
}
.audit-object a {
  color: inherit;
  text-decoration: none;
}
.audit-object a:hover {
  text-decoration: underline;
}
.audit-summary {
  font-size: 0.875rem;
  color: var(--vault-dark);
  overflow-wrap: anywhere;
}
/* Borderless table so field labels and values line up across rows */
.audit-changes {
  margin-top: 0.15rem;
  border-collapse: collapse;
  font-size: 0.8125rem;
  color: rgba(var(--vault-dark-rgb), 0.78);
}
.audit-changes td {
  padding: 0.1rem 0.4rem 0.1rem 0;
  border: 0;
  background: transparent;
  vertical-align: baseline;
  overflow-wrap: anywhere;
}
.audit-changes td:first-child {
  width: 1%;
  white-space: nowrap;
}
/* Label chip shared by the model name and the field name */
.audit-chip {
  display: inline-block;
  margin-right: 0.3rem;
  padding: 0 0.45rem;
  border-radius: var(--radius-pill);
  background: rgba(var(--vault-dark-rgb), 0.06);
  color: var(--vault-muted);
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.5;
  vertical-align: 1px;
}
.audit-old {
  color: var(--vault-muted);
  text-decoration: line-through;
}
.audit-arrow {
  color: var(--vault-muted);
}

/* Detail page sticky title bar — opaque page background when pinned */
.detail-title-bar {
  background: var(--vault-control);
  border: var(--vault-line-width) solid var(--vault-line);
  border-radius: var(--radius-md);
  padding-left: 1rem;
  padding-right: 1rem;
}

/* Detail page carousel preview */
.detail-preview-panel {
  min-height: 200px;
}
.detail-carousel-slide {
  height: 640px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.detail-carousel-img {
  max-height: 600px;
  max-width: 100%;
  object-fit: contain;
}
.detail-preview-panel .carousel-control-prev,
.detail-preview-panel .carousel-control-next {
  width: 2.5rem;
  opacity: 0.6;
}
.detail-preview-panel .carousel-control-prev:hover,
.detail-preview-panel .carousel-control-next:hover {
  opacity: 1;
}
.detail-preview-panel .carousel-control-prev-icon,
.detail-preview-panel .carousel-control-next-icon {
  filter: none;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  background-size: 50%;
}

/* Detail page file property list (compact) */
.detail-file-props {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0;
  font-size: 0.875rem;
}
.detail-file-props dt {
  padding: 0.25rem 0.75rem 0.25rem 0;
  font-weight: 500;
  color: var(--vault-muted);
  white-space: nowrap;
}
.detail-file-props dd {
  padding: 0.25rem 0;
  margin-bottom: 0;
  overflow-wrap: break-word;
  word-break: break-all;
  min-width: 0;
}

/* Detail page thumbnail strip (multi-file assets) */
.detail-thumb-strip {
  position: relative;
  z-index: 3;
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  /* Room for the 3px selection ring: the scroller clips everything
     outside its box, so the strip keeps a margin on every side. */
  padding: 4px 4px 0.5rem;
  margin: -4px -4px 0;
  scrollbar-width: thin;
}
.detail-thumb-strip::-webkit-scrollbar {
  height: 4px;
}
.detail-thumb-btn {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  opacity: 0.6;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--vault-tonal);
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.detail-thumb-btn:hover {
  opacity: 1;
}
.detail-thumb-active {
  opacity: 1;
  box-shadow: 0 0 0 3px var(--vault-primary);
}
.detail-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.detail-thumb-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--vault-muted);
  font-size: 1.25rem;
}

/* Thumbnail component (polaroid card fan, bottom-left pivot)
 *
 * Image: 60x45 + 3px border = 66x51 rendered.
 * Rotations: ±15deg around bottom-left, ±20px horizontal shift.
 * Container sized to enclose all rotated corners:
 *   width  = 132  (leftmost -33 to rightmost +97, offset left:34)
 *   height =  86  (topmost  -15 to bottommost +68, offset bottom:18)
 */
.thumbnail {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 132px;
  height: 86px;
}
.thumbnail img,
.thumbnail-protected {
  pointer-events: none;
}
/* A print: white edge, hairline outline and a small drop shadow (the
   one place the flat theme lets a shadow through) */
.thumbnail img {
  width: 60px;
  height: 45px;
  object-fit: cover;
  border-radius: 4px;
  border: 3px solid #fff;
  background: #fff;
  box-shadow:
    0 0 0 1px rgba(var(--vault-dark-rgb), 0.16),
    0 1px 3px rgba(var(--vault-dark-rgb), 0.28);
}
.thumbnail-two > a,
.thumbnail-three > a {
  position: absolute;
  bottom: 18px;
  left: 34px;
  transform-origin: bottom left;
  transition: transform 0.3s ease;
  cursor: pointer;
}
.thumbnail-two > a:nth-child(1) {
  z-index: 1;
  transform: translateX(-20px) rotate(-15deg);
}
.thumbnail-two > a:nth-child(2) {
  z-index: 2;
}
.thumbnail-three > a:nth-child(1) {
  z-index: 1;
  transform: translateX(20px) rotate(15deg);
}
.thumbnail-three > a:nth-child(2) {
  z-index: 2;
  transform: translateX(-20px) rotate(-15deg);
}
.thumbnail-three > a:nth-child(3) {
  z-index: 3;
}

/* Chart containers */
.chart-container {
  position: relative;
  height: 280px;
}
.chart-container-tall {
  height: 400px;
}

/* Stats table sortable headers */
.stats-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color 0.2s;
}
.stats-sortable:hover {
  color: var(--vault-secondary);
}
.stats-sort-active {
  color: var(--vault-secondary);
}

/* Content formatting */
.formatted-text { white-space: pre-line; }

/* Narrow page containers */
.container-narrow { max-width: 600px; }
.container-xs { max-width: 480px; }

/* Preview images (tables, edit forms) */
.preview-xs { max-height: 50px; }

/* Card cover images / placeholders (fixed height) */
.card-cover-sm { height: 160px; }

/* Import-review file preview: larger inline preview, shown as a wrapping
   gallery beside the raw/parsed table */
/* Review card images: first scan full-size, the rest as a thumbnail list. */
.review-first-tile { max-width: 360px; }
/* Fixed box (reserved via aspect-ratio) so the card does not reflow when the
   lazily-signed image replaces the placeholder; object-fit-contain fits any
   real aspect inside without distortion. */
.review-first-preview {
  width: 360px;
  max-width: 100%;
  aspect-ratio: 3 / 4;
  cursor: pointer;
}
.review-rest-list { max-width: 220px; }
/* Let the filename caption shrink and wrap instead of widening the image list
   (flex children default to min-width:auto, which ignores the list's cap). */
.review-rest-list li { min-width: 0; }
.caption { min-width: 0; overflow-wrap: anywhere; }
/* Person field label sits inline with its input at a fixed width. */
.review-field-label { flex: 0 0 3rem; }
/* Fixed column widths so long values (e.g. 特別記載) wrap and the table never
   grows past its bounds, whatever the content. */
.review-parse-table {
  table-layout: fixed;
  width: 33rem;
  max-width: 100%;
}
.review-parse-table td,
.review-parse-table th { overflow-wrap: anywhere; }
.review-parse-table td:nth-child(1),
.review-parse-table th:nth-child(1) { width: 4.5rem; }
.review-parse-table td:nth-child(2),
.review-parse-table th:nth-child(2) { width: 11rem; }
/* Sender / receiver panels sit below the table at the same width; equal
   columns with the swap between. min-width:0 lets the inputs shrink to fit. */
.review-persons { width: 33rem; max-width: 100%; }
.review-person-panel { min-width: 0; }
.review-swap-col { flex: 0 0 auto; }
/* Keep the person tag input on the tags' row; Tagify's 110px default
   min-width forces it to wrap in the narrow panel, doubling the height. */
.review-person-panel .tagify__input { min-width: 2rem; }
.review-thumb {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  cursor: pointer;
}

/* Import review: keyboard selection, owner highlight, action countdown */
[x-cloak] { display: none !important; }
/* Person names are emphasised by weight only (no background); the owner
   additionally goes blue. Reset the <mark> default background/padding. */
.review-highlight {
  background-color: transparent;
  padding: 0;
  font-weight: 600;
}
.review-owner {
  color: var(--bs-info-text-emphasis);
}
.review-key {
  display: inline-block;
  min-width: 1.5em;
  margin: 0 0.15em;
  padding: 0.1em 0.4em;
  font-size: 0.8em;
  line-height: 1.3;
  text-align: center;
  color: var(--vault-dark);
  background-color: #fff;
  border: 1px solid var(--vault-border);
  border-radius: 4px;
  box-shadow: 0 1px 0 var(--vault-border);
}
/* Decision tints: the whole card reflects its confirm/reject state so a
   reviewer can scan decisions at a glance. Rejected uses a muted rose (not an
   alarming red). Selection is an outline (not a background) so it stays
   distinct from both the .card:hover shadow and these state tints. */
.review-confirmed {
  background-color: rgba(var(--bs-success-rgb), 0.1);
}
.review-rejected {
  background-color: rgba(var(--bs-danger-rgb), 0.06);
}
.review-selected {
  outline: 3px solid var(--vault-primary);
  outline-offset: 1px;
}
.review-countdown { position: relative; overflow: hidden; }
.review-countdown-fill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.45);
  pointer-events: none;
}
/* Fixed dock of queued confirm/reject countdowns; a tall card's own
   countdown button can sit below the fold, this one never does. */
.review-pending-dock {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1050;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
  max-width: calc(100vw - 2rem);
}
/* Each countdown hugs its label; only a very long one truncates. */
.review-pending-dock button {
  max-width: 20rem;
}
/* Collapsed by default: only the newest countdown (last child) shows;
   hovering the dock expands the earlier ones upward. */
.review-pending-dock:not(:hover) button:not(:last-child) {
  display: none;
}

/* Caption-sized text */
.caption { font-size: 0.75rem; }

/* File strip (shared upload + edit) */
.file-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: flex-start;
}
.file-card-grip {
  position: absolute;
  bottom: 4px;
  right: 4px;
  color: var(--vault-muted);
  font-size: 0.75rem;
  opacity: 0;
  transition: opacity 0.2s;
  cursor: grab;
  touch-action: none;
}
.file-card:hover .file-card-grip { opacity: 1; }
@media (hover: none) {
  .file-card-grip { opacity: 0.5; }
}
.file-card-deleted {
  opacity: 0.45;
}
.file-card-deleted .file-card-inner {
  border-style: dashed;
}
.file-card-deleted:hover .file-card-remove {
  opacity: 1 !important;
}

/* 對應圖檔 manual matching board */
.match-thumb {
  width: 96px;
  height: 96px;
}
.match-dropzone {
  min-height: 122px;
  padding: 0.5rem;
  border: 1px dashed var(--vault-border);
  border-radius: 0.5rem;
  transition: background-color 0.15s, border-color 0.15s;
}
/* While a tile is dragging, hint every drop zone and highlight the one the
   SortableJS ghost is hovering (the drop target). */
body:has(.sortable-ghost) .match-dropzone {
  border-color: var(--vault-primary);
}
.match-dropzone:has(.sortable-ghost) {
  border-style: solid;
  background-color: rgba(var(--vault-primary-rgb), 0.08);
}
.match-tile-name {
  line-height: 1.2;
  margin-top: 0.25rem;
  word-break: break-all;
}
.match-dropzone-empty {
  padding: 0.75rem;
  text-align: center;
}
/* Hide the "drag here" hint once the zone holds an image (:has re-evaluates
   live as SortableJS moves tiles in and out). */
.match-dropzone:has(.match-tile) + .match-dropzone-empty {
  display: none;
}
/* The 多餘圖檔 pool tracks the reviewer down the (long) record list. */
.match-pool-wrap {
  position: sticky;
  top: 1rem;
}
/* Once a stray image is placed (matched or built into an asset) its pool group
   has no tiles left, so drop it — nothing remains to act on. */
.match-pool-group:not(:has(.match-tile)) {
  display: none;
}
.match-pool {
  max-height: calc(100vh - 8rem);
  overflow-y: auto;
}
.file-card-lock {
  position: absolute;
  bottom: 4px;
  right: 4px;
  color: var(--vault-muted);
  font-size: 0.75rem;
  opacity: 0.7;
}

/* Upload dropzone in edit file strip */
.upload-dropzone .file-card-inner {
  border: 2px dashed var(--vault-border);
  background: transparent;
  color: var(--vault-muted);
  font-size: 1.5rem;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.upload-dropzone:hover .file-card-inner {
  border-color: var(--vault-primary);
  color: var(--vault-primary);
}

/* File viewer (modal) */
.viewer-container {
  width: 100%;
  height: calc(100vh - 56px);
  background: #1a1a1a;
  user-select: none;
  -webkit-user-drag: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
.viewer-container canvas {
  user-select: none;
  -webkit-user-drag: none;
}
.viewer-container video {
  max-width: 100%;
  max-height: 100%;
}
.viewer-container audio { width: 60%; }
.viewer-container pre {
  color: #e0e0e0;
  background: transparent;
  padding: 2rem;
  overflow: auto;
  width: 100%;
  height: 100%;
  user-select: none;
  margin: 0;
}

/* File viewer (standalone page) */
.viewer-standalone {
  width: 100%;
  height: calc(100vh - 200px);
  background: #1a1a1a;
  user-select: none;
  -webkit-user-drag: none;
}

/* Table column sizing */
.col-action { width: 40px; }

/* Expired/disabled table rows */
.row-expired {
  opacity: 0.55;
}
.row-expired:hover {
  opacity: 0.75;
}

/* Empty cell placeholder */
.cell-empty {
  color: var(--vault-border);
}


/* ============================================================
   Scrollbar
   ============================================================ */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(var(--vault-dark-rgb), 0.22);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--vault-primary);
}

/* ============================================================
   Help Tooltips
   ============================================================ */
.help-tip {
  color: var(--vault-muted);
  font-size: 0.75em;
  cursor: help;
  vertical-align: middle;
  margin-left: 0.25em;
  transition: color 0.2s;
}
h1 .help-tip,
h2 .help-tip,
h3 .help-tip,
h4 .help-tip,
h5 .help-tip,
h6 .help-tip {
  font-size: 0.875rem;
  font-weight: 400;
}

.help-tip:hover {
  color: var(--vault-primary);
}

.tooltip-inner {
  text-align: left;
}

/* ============================================================
   Sticky Table Headers (desktop only — mobile needs scroll)
   ============================================================ */
@media (min-width: 768px) {
  .table-responsive {
    overflow: visible;
  }
  .table > tbody {
    position: relative;
    z-index: 0;
  }
  .table > thead > tr > th {
    position: sticky;
    top: -1px;
    z-index: 2;
  }
}
.table > thead > tr > th,
.table-light > thead > tr > th,
.table > thead.table-light > tr > th {
  background-color: var(--vault-thead-bg);
}

/* ============================================================
   Expandable Help Panels
   ============================================================ */
.help-panel {
  width: fit-content;
  max-width: 100%;
  margin-left: auto;
}

.help-panel .accordion-button {
  padding: 0.5rem 0.75rem;
  font-size: 0.8125rem;
  color: var(--vault-muted);
  background: transparent;
  box-shadow: none;
  justify-content: flex-start;
  gap: 0;
}

.help-panel .accordion-button:not(.collapsed) {
  color: var(--vault-primary);
  background: transparent;
}

.help-panel .accordion-button::after {
  width: 0.875rem;
  height: 0.875rem;
  background-size: 0.875rem;
  margin-left: 0.5rem;
  flex-shrink: 0;
}

.help-panel .accordion-body {
  padding: 0.5rem 0.75rem;
  font-size: 0.8125rem;
  color: var(--vault-dark);
}

.help-panel .accordion-item {
  border: none;
  background: transparent;
}

/* ============================================================
   Login Page — Split layout with full-screen background
   ============================================================ */
.login-page {
  margin: 0;
  padding: 0;
  height: 100vh;
  overflow: hidden;
  background-color: var(--vault-dark);
}

/* Background image — full viewport */
.login-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
}

.login-bg-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Overlay — heavier on the left panel for card readability */
.login-overlay {
  position: fixed;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    to right,
    rgba(40, 32, 26, 0.82) 0%,
    rgba(40, 32, 26, 0.65) 45%,
    rgba(40, 32, 26, 0.30) 70%,
    rgba(40, 32, 26, 0.15) 100%
  );
}

/* Split layout — left panel + right hero (transparent) */
.login-layout {
  position: relative;
  z-index: 2;
  display: flex;
  height: 100vh;
}

.login-panel {
  width: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.login-hero {
  width: 50%;
}

/* Glassmorphism card */
.login-card {
  width: 100%;
  max-width: 380px;
  border-radius: 1rem;
  background: rgba(253, 250, 245, 0.10);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border: 1px solid rgba(253, 250, 245, 0.15);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.3),
    0 1px 0 rgba(255, 255, 255, 0.06) inset;
  display: flex;
  flex-direction: column;
  animation: login-card-enter 0.6s ease-out;
}

@keyframes login-card-enter {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.login-card-inner {
  padding: 3rem 2.5rem 2rem;
  text-align: center;
}

/* Brand icon */
.login-brand {
  margin-bottom: 1.25rem;
}

.login-brand-icon {
  font-size: 2.5rem;
  color: var(--vault-cream);
  opacity: 0.85;
}

/* Title in serif */
.login-title {
  font-family: "Noto Serif TC", "Noto Sans TC", serif;
  font-weight: 700;
  font-size: 1.75rem;
  letter-spacing: 0.08em;
  color: var(--vault-cream);
  margin-bottom: 0.5rem;
}

.login-subtitle {
  font-family: "Noto Sans TC", sans-serif;
  font-size: 0.875rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: rgba(245, 241, 232, 0.65);
  margin-bottom: 0;
}

/* Decorative divider */
.login-divider {
  width: 48px;
  height: 1px;
  margin: 1.75rem auto;
  background: linear-gradient(
    to right,
    transparent,
    rgba(245, 241, 232, 0.4),
    transparent
  );
}

/* Google login button */
.login-btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  width: 100%;
  padding: 0.75rem 1.25rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--vault-dark);
  background: rgba(253, 250, 245, 0.92);
  border: 1px solid rgba(253, 250, 245, 0.6);
  border-radius: 0.5rem;
  transition: all 0.25s ease;
  text-decoration: none;
}

.login-btn-google:hover {
  background: rgba(253, 250, 245, 1);
  color: var(--vault-dark);
  text-decoration: none;
}

.login-google-icon {
  flex-shrink: 0;
}

/* Dev login separator */
.login-dev-separator {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.25rem 0;
  color: rgba(245, 241, 232, 0.35);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.login-dev-separator::before,
.login-dev-separator::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(245, 241, 232, 0.15);
}

/* Dev login button */
.login-btn-dev {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.625rem 1.25rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: rgba(245, 241, 232, 0.65);
  background: rgba(245, 241, 232, 0.06);
  border: 1px solid rgba(245, 241, 232, 0.12);
  border-radius: 0.5rem;
  transition: all 0.25s ease;
  text-decoration: none;
}

.login-btn-dev:hover {
  color: rgba(245, 241, 232, 0.9);
  background: rgba(245, 241, 232, 0.12);
  border-color: rgba(245, 241, 232, 0.25);
  text-decoration: none;
}

/* Card footer */
.login-card-footer {
  padding: 0.875rem 2.5rem;
  text-align: center;
  border-top: 1px solid rgba(245, 241, 232, 0.08);
  color: rgba(245, 241, 232, 0.3);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
}

/* Mobile — centered card over full-bleed background */
@media (max-width: 767.98px) {
  .login-bg-img {
    object-position: 70% center;
  }

  .login-overlay {
    background: rgba(40, 32, 26, 0.7);
  }

  .login-layout {
    justify-content: center;
  }

  .login-panel {
    width: 100%;
    padding: 1.5rem;
  }

  .login-hero {
    display: none;
  }

  .login-card {
    max-width: 100%;
    border-radius: 0.875rem;
  }

  .login-card-inner {
    padding: 2rem 1.75rem 1.5rem;
  }

  .login-title {
    font-size: 1.5rem;
  }

  .login-card-footer {
    padding: 0.75rem 1.75rem;
  }
}

/* Filter collapse: always visible on sm+ */
@media (min-width: 576px) {
  .filter-collapse {
    display: block !important;
  }
}

/* ============================================================
   Mobile Responsive (iPhone 16 — 390px)
   ============================================================ */
@media (max-width: 575.98px) {
  /* Tighter container padding */
  main.container {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  /* Smaller page headings */
  main h2 {
    font-size: 1.35rem;
  }

  /* Filter form: full-width inputs, override size attr */
  .filter-form input[size] {
    width: 100% !important;
  }
  .filter-form .btn {
    width: 100%;
  }

  /* Tables: smaller text on mobile */
  .table {
    font-size: 0.8125rem;
  }
  .table th,
  .table td {
    padding: 0.4rem 0.35rem;
  }

  /* Tabs: smaller text */
  .nav-tabs .nav-link {
    font-size: 0.8125rem;
    padding: 0.375rem 0.5rem;
  }

  /* Cards: reduce padding */
  .card-body {
    padding: 0.75rem;
  }
}

/* ============================================================
   Asset Relationship Timeline
   ============================================================ */
.asset-timeline {
  position: relative;
  padding-left: 0.5rem;
}

.timeline-item {
  display: flex;
  gap: 0.75rem;
  min-height: 4rem;
}

.timeline-marker {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  width: 1rem;
  padding-top: 0.25rem;
}

.timeline-dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background: rgba(var(--vault-dark-rgb), 0.25);
  flex-shrink: 0;
}

.timeline-dot-current {
  width: 0.75rem;
  height: 0.75rem;
  background: var(--vault-accent);
  border-color: var(--vault-accent);
}

.timeline-line {
  width: 2px;
  flex-grow: 1;
  background: var(--vault-tonal-hover);
  margin-top: 0.25rem;
}

.timeline-content {
  flex-grow: 1;
  padding-bottom: 1rem;
}

.timeline-date {
  font-size: 0.75rem;
  color: var(--vault-muted);
  margin-bottom: 0.25rem;
}

.timeline-card {
  padding: 0.6rem 0.85rem;
  border: var(--vault-line-width) solid var(--vault-line);
  border-radius: var(--radius-sm);
  background: var(--vault-control);
  font-size: 0.875rem;
}

a.timeline-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s;
}

a.timeline-card-link:hover {
  background: var(--vault-tonal-hover);
}

.timeline-card-current {
  background: rgba(var(--vault-primary-rgb), 0.1);
  border-color: var(--vault-primary);
}

.timeline-arrow {
  color: var(--vault-muted);
  font-size: 0.875rem;
}

/* Heading that folds its section; the chevron turns when open */
.section-toggle {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
}
.section-toggle .bi-chevron-down {
  font-size: 0.75em;
  transition: transform 0.2s;
}
.section-toggle[aria-expanded="true"] .bi-chevron-down {
  transform: rotate(180deg);
}

/* Boxes marked bg-light sit on the paper as soft glass, not cream */
.bg-light {
  background-color: var(--vault-paper) !important;
}
