/*
 * tokens.css
 *
 * App-wide visual system for Vexperio CMS. Defines the palette, typography,
 * radii, component defaults, and a small set of reusable utilities on top of
 * Bootstrap 5. Load after Bootstrap and after badges.css.
 *
 * No new colors are introduced here beyond what already exists in badges.css.
 */

:root {
  /* Brand / accent */
  --bs-primary:               #2945c4;
  --bs-primary-rgb:           41, 69, 196;
  --bs-primary-bg-subtle:     #e0e6ff;
  --bs-primary-text-emphasis: #1c317a;
  --bs-primary-border-subtle: #c9d2f7;

  /* Semantic (aligned to badges.css pastel palette) */
  --bs-success:               #2e6a37;
  --bs-success-rgb:           46, 106, 55;
  --bs-success-bg-subtle:     #e8f5e6;
  --bs-success-border-subtle: #cfe4cb;
  --bs-success-text-emphasis: #1f4a24;

  --bs-danger:                #8a3c32;
  --bs-danger-rgb:            138, 60, 50;
  --bs-danger-bg-subtle:      #f6e3e0;
  --bs-danger-border-subtle:  #e8c6c0;
  --bs-danger-text-emphasis:  #5e2921;

  --bs-warning:               #8a5a1a;
  --bs-warning-rgb:           138, 90, 26;
  --bs-warning-bg-subtle:     #fbf0d8;
  --bs-warning-border-subtle: #efdcb2;
  --bs-warning-text-emphasis: #5e3d10;

  /* Bright gold for "favorite"/starred affordances - the warning palette above is a
     muted brown, so stars need their own accent (matches the Port Schedules design). */
  --star-gold:                #f5b301;

  --bs-info:                  #2d5080;
  --bs-info-rgb:              45, 80, 128;
  --bs-info-bg-subtle:        #e2ebf5;
  --bs-info-border-subtle:    #c9d7eb;

  --bs-secondary:             #4b5161;
  --bs-secondary-rgb:         75, 81, 97;
  --bs-secondary-bg-subtle:   #ececf0;
  --bs-secondary-border-subtle: #dedfe4;

  /* Accent violet — used where we need a pastel distinct from primary/info/success.
     Follows the same light-bg / mid-border / deep-text pattern as the semantic tokens. */
  --bs-accent:                #6a44a8;
  --bs-accent-rgb:            106, 68, 168;
  --bs-accent-bg-subtle:      #ece4f5;
  --bs-accent-border-subtle:  #d2c1e6;
  --bs-accent-text-emphasis:  #4b2e75;

  --bs-dark:                  #1b1f2a;
  --bs-dark-rgb:              27, 31, 42;

  /* Surfaces / ink
     --bs-body-bg is the default surface that Bootstrap components inherit
     from (offcanvas, form-control, nav-tabs-active, dropdown-menu, etc.).
     Keeping it white means none of those components silently paint
     themselves grey. The grey workspace color is applied explicitly via
     .app-content on the block wrapping {% block content %} in base.html. */
  --bs-body-bg:               #ffffff;
  --bs-body-color:            #1b1f2a;
  --bs-body-secondary-color:  #6a6f7d;
  --bs-body-tertiary-color:   #9aa0ac;
  --bs-body-secondary-bg:     #fafbfc;
  --bs-secondary-bg-rgb:      250, 251, 252;
  --bs-body-tertiary-bg:      #f6f7f9;
  --bs-tertiary-bg-rgb:       246, 247, 249;

  --bs-border-color:             #e7e8ee;
  --bs-border-color-translucent: rgba(27, 31, 42, 0.08);
  --bs-border-radius:            0.5rem;
  --bs-border-radius-sm:         0.375rem;
  --bs-border-radius-lg:         0.625rem;

  /* Typography */
  --bs-font-sans-serif: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
                        Roboto, 'Helvetica Neue', Arial, sans-serif;
  --bs-font-monospace:  'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo,
                        Monaco, Consolas, 'Courier New', monospace;
  --bs-body-font-size:      0.8125rem;
  --bs-body-font-weight:    400;
  --bs-body-line-height:    1.5;
  --bs-heading-font-weight: 600;

  --bs-link-color:       #2945c4;
  --bs-link-hover-color: #1c317a;

  /* Shadows (flatter than Bootstrap defaults) */
  --bs-box-shadow-sm: 0 1px 2px rgba(27, 31, 42, 0.04);
  --bs-box-shadow:    0 2px 8px rgba(27, 31, 42, 0.06);
  --bs-box-shadow-lg: 0 8px 24px rgba(27, 31, 42, 0.10);

  /* Design tokens consumable by feature-scoped CSS (e.g.
     availability/calendar_timeline.css). Prefer the --bs-* equivalents where
     they exist - these are only for shades that don't map cleanly to a
     Bootstrap variable. */
  --vx-ink-2:   #3a3f4c;
  --vx-line-2:  #eef0f5;
}

/* Surface hierarchy - single source of truth.

   Two distinct regions, each with ONE class. Don't use bg-white, bg-light,
   or bg-body-* on structural containers - reach for one of these instead so
   the whole app stays consistent.

     .app-shell    -> #ffffff  sidebar column + top search bar + cards
                                (the white surfaces where UI chrome lives)
     .app-content  -> #f6f7f9  the workspace behind cards (the grey gutter)

   Body is white so any transparent container is visually safe and we never
   need to guess what shows through. The base.html scaffold applies these
   classes on the correct containers; nothing else should override them.

   Separation between same-colored regions (sidebar vs cards) comes from the
   border-end on the sidebar and the grey gutter of app-content around cards.
*/
body {
  background-color: #fff;
  font-feature-settings: 'cv11', 'ss01';
  -webkit-font-smoothing: antialiased;
}
.app-shell {
  background-color: #fff;
}
.app-content {
  background-color: #f6f7f9;
}
.card,
.card-header,
.list-group,
.list-group-item,
.table {
  background-color: #fff;
}

/* Buttons: tighter, softer radius */
.btn {
  --bs-btn-font-size: 0.78125rem;
  --bs-btn-padding-y: 0.3125rem;
  --bs-btn-padding-x: 0.75rem;
  --bs-btn-border-radius: 0.5rem;
  --bs-btn-font-weight: 500;
  letter-spacing: 0;
}
.btn-sm {
  --bs-btn-font-size: 0.75rem;
  --bs-btn-padding-y: 0.25rem;
  --bs-btn-padding-x: 0.625rem;
}

.btn-primary {
  --bs-btn-color: #fff;
  --bs-btn-bg: #2945c4;
  --bs-btn-border-color: #2945c4;
  --bs-btn-hover-bg: #243db0;
  --bs-btn-hover-border-color: #243db0;
  --bs-btn-active-bg: #1f348f;
  --bs-btn-active-border-color: #1f348f;
}

.btn-dark {
  --bs-btn-bg: #1b1f2a;
  --bs-btn-border-color: #1b1f2a;
  --bs-btn-hover-bg: #000;
  --bs-btn-hover-border-color: #000;
}

.btn-outline-secondary {
  --bs-btn-color: #3a3f4c;
  --bs-btn-border-color: #e7e8ee;
  --bs-btn-bg: #fff;
  --bs-btn-hover-bg: #f1f2f6;
  --bs-btn-hover-color: #1b1f2a;
  --bs-btn-hover-border-color: #e7e8ee;
}

/* Forms */
.form-control,
.form-select {
  font-size: 0.8125rem;
  border-color: var(--bs-border-color);
  border-radius: 0.5rem;
  padding: 0.375rem 0.625rem;
}
.form-control:focus,
.form-select:focus {
  border-color: #c9d2f7;
  box-shadow: 0 0 0 3px rgba(41, 69, 196, 0.12);
}
.form-label {
  font-size: 0.75rem;
  color: var(--bs-body-secondary-color);
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 500;
}
.form-check-input:checked {
  background-color: #2945c4;
  border-color: #2945c4;
}
/* Django's CheckboxSelectMultiple renders as <fieldset><legend>; Bootstrap 5's
   default legend is oversized and floated vs. our .form-label. Match .form-label
   so grouped checkboxes inside filter dropdowns read as a single form field. */
.dropdown-menu fieldset > legend {
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.5;
  color: var(--bs-body-secondary-color);
  text-transform: uppercase;
  letter-spacing: .06em;
  float: none;
  width: auto;
  padding: 0;
  margin-bottom: 0.5rem;
}

/* Nav-pills (sidebar): subtle active state on indigo, not full fill */
.nav-pills {
  --bs-nav-pills-link-active-color: #2945c4;
  --bs-nav-pills-link-active-bg: #e0e6ff;
  --bs-nav-link-color: #3a3f4c;
  --bs-nav-link-hover-color: #1b1f2a;
  --bs-nav-link-font-size: 0.84375rem;
  --bs-nav-link-font-weight: 500;
}
.nav-pills .nav-link { border-radius: 0.5rem; padding: 0.375rem 0.75rem; }
.nav-pills .nav-link:hover:not(.active) { background: #f1f2f6; }

/* Cards: flat, hairline border, always white against the light body bg */
.card {
  --bs-card-bg: #fff;
  --bs-card-border-color: var(--bs-border-color);
  --bs-card-border-radius: 0.625rem;
  --bs-card-inner-border-radius: 0.625rem;
  --bs-card-box-shadow: none;
  --bs-card-cap-bg: #fff;
  --bs-card-cap-padding-y: 0.75rem;
}

/* List-group: Bootstrap 5.3 defaults this to var(--bs-body-bg), which picks
   up our light grey body instead of white. Force white so list-group-flush
   inside a card stays consistent with the card background. */
.list-group {
  --bs-list-group-bg: #fff;
  --bs-list-group-border-color: var(--bs-border-color);
}
.card.shadow-sm {
  box-shadow: 0 1px 0 rgba(27, 31, 42, 0.03) !important;
}

/* Tabs: ink underline, inline count pills */
.nav-tabs {
  --bs-nav-tabs-border-color: var(--bs-border-color);
  --bs-nav-tabs-link-active-color: #1b1f2a;
  --bs-nav-tabs-link-active-bg: transparent;
  --bs-nav-tabs-link-active-border-color: transparent transparent #1b1f2a transparent;
  --bs-nav-link-font-size: 0.84375rem;
  --bs-nav-link-font-weight: 500;
  --bs-nav-link-color: #6a6f7d;
  --bs-nav-link-hover-color: #3a3f4c;
  border-bottom-width: 1px;
}
.nav-tabs .nav-link {
  border-width: 0 0 2px 0;
  border-radius: 0;
  padding: 0.625rem 0.875rem;
  margin-bottom: -1px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.nav-tabs .nav-link.active {
  font-weight: 600;
  border-bottom-color: #1b1f2a;
}
.nav-tabs .nav-link .badge {
  font-size: 0.71875rem;
  font-weight: 500;
}

/* Tables */
.table {
  --bs-table-color: var(--bs-body-color);
  --bs-table-bg: #fff;
  --bs-table-border-color: #eef0f5;
  --bs-table-hover-bg: #fafbfd;
  font-size: 0.8125rem;
}
.table > thead > tr > th {
  background: #fafbfc;
  color: var(--bs-body-secondary-color);
  font-weight: 500;
  font-size: 0.71875rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  border-bottom-color: #eef0f5;
  padding: 0.5625rem 0.875rem;
}
.table > tbody > tr > td {
  padding: 0.6875rem 0.875rem;
  vertical-align: middle;
}
.table-sm > :not(caption) > * > * {
  padding: 0.4375rem 0.75rem;
}

/* Breadcrumbs */
.breadcrumb {
  --bs-breadcrumb-divider-color: #9aa0ac;
  --bs-breadcrumb-item-active-color: #1b1f2a;
  --bs-breadcrumb-font-size: 0.78125rem;
  font-size: 0.78125rem;
}
.breadcrumb a {
  color: #6a6f7d;
  text-decoration: none;
}
.breadcrumb a:hover {
  color: #2945c4;
}

/* Alerts */
.alert {
  --bs-alert-border-radius: 0.625rem;
  --bs-alert-padding-y: 0.625rem;
  --bs-alert-padding-x: 0.875rem;
  font-size: 0.8125rem;
  border: 1px solid transparent;
}
.alert-info    { background: #e2ebf5; color: #2d5080; border-color: #c9d7eb; }
.alert-success { background: #e8f5e6; color: #2e6a37; border-color: #cfe4cb; }
.alert-warning { background: #fbf0d8; color: #8a5a1a; border-color: #efdcb2; }
.alert-danger  { background: #f6e3e0; color: #8a3c32; border-color: #e8c6c0; }

/* Dropdowns */
.dropdown-menu {
  --bs-dropdown-border-color: var(--bs-border-color);
  --bs-dropdown-border-radius: 0.5rem;
  --bs-dropdown-font-size: 0.8125rem;
  --bs-dropdown-link-color: #1b1f2a;
  --bs-dropdown-link-hover-bg: #f1f2f6;
  --bs-dropdown-link-active-bg: #e0e6ff;
  --bs-dropdown-link-active-color: #2945c4;
  box-shadow: 0 8px 24px rgba(27, 31, 42, 0.10);
}

/* Pagination */
.pagination {
  --bs-pagination-color: #3a3f4c;
  --bs-pagination-bg: #fff;
  --bs-pagination-border-color: var(--bs-border-color);
  --bs-pagination-hover-bg: #f1f2f6;
  --bs-pagination-active-bg: #2945c4;
  --bs-pagination-active-border-color: #2945c4;
  --bs-pagination-font-size: 0.8125rem;
  --bs-pagination-border-radius: 0.5rem;
}

/* Focus ring */
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(41, 69, 196, 0.22);
  border-radius: 6px;
}

/* Reusable utilities used across the app. Bootstrap covers 95% of layout,
   these fill the small gaps that come up repeatedly. */

/* Two-column dl with a dashed hairline under every row except the last.
   Works on Bootstrap's dl.row (<dt> and <dd> alternate; :last-of-type
   matches the final dt and final dd, which is what we want). */
.dl-dashed > dt,
.dl-dashed > dd {
  border-bottom: 1px dashed var(--bs-border-color);
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  margin-bottom: 0;
}
.dl-dashed > dt:last-of-type,
.dl-dashed > dd:last-of-type {
  border-bottom: 0;
}

.font-mono {
  font-family: var(--bs-font-monospace);
  font-feature-settings: normal;
}
.tabular-nums {
  font-variant-numeric: tabular-nums;
}

/* Bright gold for starred/favorite glyphs - Bootstrap's .text-warning is the muted
   brown warning tone here, so stars get their own accent. */
.text-star {
  color: var(--star-gold) !important;
}

/* Half-step spacing for the tight rhythm between dense nav rows. Bootstrap's
   scale jumps from 0 to 0.25rem (mt-1); this fills the gap at 0.125rem. */
.mt-h { margin-top: 0.125rem !important; }

/* Narrow number input for inline quantity fields (e.g. relative schedule offset). */
.input-narrow { width: 4.5rem; }

/* Tighter, lighter variant of .section-label for sidebar group headings -
   smaller font, wider tracking, tertiary grey so it reads as a whisper,
   not a heading. */
.nav-section-label {
  font-size: 0.625rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--bs-tertiary-color);
}
/* Tight uppercase section label - used for both section heads inside cards
   (h6.section-label) and small KPI/stat labels. Muted grey, no font-weight
   so it reads as a label not a heading; add fw-semibold only when heading-like. */
.section-label {
  font-size: 0.71875rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--bs-body-secondary-color);
}
h6.section-label,
.section-label.fw-semibold {
  font-weight: 600;
  letter-spacing: .08em;
}

/* Thin 6px progress bar - reuse anywhere we need a slim fill indicator
   (Readiness header, KPI cards, etc.). Pair with bg-* on .progress-bar. */
.progress-thin {
  height: 6px;
  border-radius: 999px;
}

/* Tiny 6px status dot - pair with bg-* for color (status chips, sidebar
   brand, nav indicators). */
.status-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
}
/* Circular icon chip for status rows (Readiness-style). Combine with
   .bg-success-subtle / .text-success etc. to get the color variant. */
.icon-chip {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-grid;
  place-items: center;
  font-size: 12px;
  flex-shrink: 0;
}

/* Chevron that rotates 90deg when its toggle host has aria-expanded="true".
   Pair with a host element that carries aria-expanded (e.g. a row with
   data-bs-toggle="collapse"). */
/* inline-block is required: a .bi icon element is display:inline (only its
   ::before is inline-block), and CSS transforms are ignored on inline boxes. */
.chevron-toggle { display: inline-block; transition: transform 0.15s ease; }
[aria-expanded="true"] > .chevron-toggle,
[aria-expanded="true"] .chevron-toggle { transform: rotate(90deg); }

/* Tiny 10px square swatch used in legends above data grids (Tour / TO
   Departures). Pair with the variant classes below, or drop them in and
   apply a bg-* utility directly for a solid fill. */
.legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  border: 1px solid var(--bs-border-color);
}
.legend-swatch-active {
  background: var(--bs-success-bg-subtle);
  border-color: var(--bs-success-border-subtle);
}
.legend-swatch-sold {
  background: var(--bs-danger-bg-subtle);
  border-color: var(--bs-danger-border-subtle);
}
.legend-swatch-blocked {
  background: repeating-linear-gradient(
    45deg,
    var(--bs-info-bg-subtle),
    var(--bs-info-bg-subtle) 3px,
    var(--bs-info-border-subtle) 3px,
    var(--bs-info-border-subtle) 6px
  );
  border-color: var(--bs-info-border-subtle);
}
.legend-swatch-inactive,
.legend-swatch-empty {
  background: var(--bs-body-tertiary-bg);
}
.legend-swatch-over {
  background: var(--bs-danger);
  border-color: var(--bs-danger);
}
.legend-swatch-taken {
  background: var(--bs-primary-bg-subtle);
  border-color: var(--bs-primary-border-subtle);
}

/* Tiny 7px filled circle for "unseen" / "new" indicators in lists and timelines.
   Pair with bg-* for the colour. */
.dot-indicator {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

/* 32px circular icon container next to card titles (transport cards, etc.).
   Bigger sibling of .icon-chip - pair with a bg-*-subtle utility. */
.icon-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: inline-grid;
  place-items: center;
  font-size: 16px;
  flex-shrink: 0;
}

/* Row-action icon for table last columns (view / edit / delete / gear / etc.).
   Quiet grey at rest; the box hugs the glyph so a cluster sits tight. On hover
   the icon takes its accent colour and a soft tinted circle grows OUTWARD via a
   spread box-shadow - it has no layout footprint, so the hover never reflows the
   row or pushes neighbouring icons. Defaults to the primary accent; add
   .icon-action-danger / .icon-action-warning / .icon-action-success for other
   intents. Works on both <a> and <button>. Wrap the cluster in .icon-actions. */
.icon-action {
  --vx-icon-action-color: var(--bs-primary);
  --vx-icon-action-bg: var(--bs-primary-bg-subtle);
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: transparent;
  color: var(--bs-secondary-color);
  font-size: 1rem;
  line-height: 1;
  text-decoration: none;
  transition: background-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
}
.icon-action:hover,
.icon-action:focus-visible {
  background-color: var(--vx-icon-action-bg);
  color: var(--vx-icon-action-color);
  box-shadow: 0 0 0 5px var(--vx-icon-action-bg);
  text-decoration: none;
}
.icon-action-danger {
  --vx-icon-action-color: var(--bs-danger);
  --vx-icon-action-bg: var(--bs-danger-bg-subtle);
}
.icon-action-warning {
  --vx-icon-action-color: var(--bs-warning-text-emphasis);
  --vx-icon-action-bg: var(--bs-warning-bg-subtle);
}
.icon-action-success {
  --vx-icon-action-color: var(--bs-success);
  --vx-icon-action-bg: var(--bs-success-bg-subtle);
}

/* Cluster of .icon-action items in a table cell. inline-flex so it right-aligns
   inside a .text-end cell; the small gap lets the glyphs sit close while leaving
   just enough room that adjacent hover halos don't visibly collide. */
.icon-actions {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  justify-content: flex-end;
}

/* Pill-shaped chip for quick filters / tabs / segmented links. Add .is-active
   for the selected state. Pair with .vx-chip-count for a trailing count like
   "Shared ·12". Used by the Departures quick filters; reuse anywhere a
   quiet pill is the right affordance. */
.vx-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0.25rem 0.625rem;
  border-radius: 999px;
  background-color: #fff;
  border: 1px solid var(--bs-border-color);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--vx-ink-2);
  text-decoration: none;
  line-height: 1.4;
  cursor: pointer;
  transition: background-color 0.1s ease, border-color 0.1s ease, color 0.1s ease;
}
.vx-chip:hover {
  background-color: var(--bs-body-tertiary-bg);
  color: var(--vx-ink-2);
  text-decoration: none;
}
.vx-chip.is-active {
  background-color: var(--bs-primary-bg-subtle);
  border-color: var(--bs-primary-border-subtle);
  color: var(--bs-primary);
}
.vx-chip-count {
  font-size: 0.65625rem;
  opacity: 0.7;
}
.vx-chip-filters.dropdown-toggle::after { display: none; }

.cursor-pointer { cursor: pointer; }
.cursor-help { cursor: help; }

/* Card-as-link hover: lifts shadow and darkens border. Attach to an <a class="card card-link">. */
.card-link {
  transition: box-shadow 0.12s ease, border-color 0.12s ease;
}
.card-link:hover {
  box-shadow: 0 4px 14px rgba(27, 31, 42, 0.08);
  border-color: var(--bs-secondary-border-subtle);
}
/* Nudge the hub arrow icon 2px right on card hover. */
.card-link:hover .hub-arrow {
  transform: translateX(2px);
  transition: transform 0.12s ease;
}
.hub-arrow {
  transition: transform 0.12s ease;
}

/* Menu body for the chip-triggered Filters dropdown. */
.vx-filters-menu {
  width: min(360px, 90vw);
  border-radius: var(--bs-border-radius-lg);
  border-color: var(--bs-border-color);
}
.vx-filters-menu .form-group { margin-bottom: 0.5rem; }
.vx-filters-menu .asteriskField { display: none; }

/* Pastel-fill "View" action button used next to Blocked badges to deep-link
   into the blocked-dates filter. Mirrors the pastel pattern used by the
   Departures row Open/Close buttons; lives in tokens.css because the same
   button now appears on Departures, /tours/<id>/dates/, and the variant
   Departures tab. */
.dep-row-btn-view {
  background-color: var(--bs-info-bg-subtle);
  color: var(--bs-info);
  border: 1px solid transparent;
}
.dep-row-btn-view:hover {
  background-color: var(--bs-info-border-subtle);
  color: var(--bs-info-text-emphasis);
}

/* Blue striped fill applied to any container that represents one day on a
   blocked date. Matches the .dep-mini-cell.state-blocked treatment used on
   /tours/<id>/dates/ so blocked dates read the same way across the variant
   list/calendar/timeline views and the tour Dates grid. */
.is-day-blocked {
  background: repeating-linear-gradient(
    45deg,
    var(--bs-info-bg-subtle),
    var(--bs-info-bg-subtle) 5px,
    var(--bs-info-border-subtle) 5px,
    var(--bs-info-border-subtle) 10px
  );
  border-color: var(--bs-info-border-subtle);
}

/* -------------------------------------------------------
   Error pages (404 / 500 / 403) - centered card layout.
   Shared by all HTTP error templates.
   ------------------------------------------------------- */
.err-page-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
  padding: 2rem 1.5rem;
}
.err-page-card {
  width: 100%;
  max-width: 640px;
}
.err-card-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 4rem 2.5rem 3.5rem;
}
.err-glyph { margin-bottom: 1.5rem; }
.err-code {
  font-family: var(--bs-font-monospace);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  color: var(--bs-body-tertiary-color);
  text-transform: uppercase;
  margin-bottom: 0.5rem;
}
.err-title {
  font-size: 1.625rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 0.625rem;
}
.err-desc {
  font-size: 0.875rem;
  color: var(--bs-body-secondary-color);
  max-width: 460px;
  margin: 0;
  line-height: 1.55;
}
.err-meta {
  margin-top: 2.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--bs-border-color);
  width: 100%;
  display: grid;
  gap: 1.5rem;
}
.err-meta-cols-2 { grid-template-columns: repeat(2, 1fr); }
.err-meta-single {
  grid-template-columns: 1fr;
  max-width: 240px;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}
.err-meta dt {
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bs-body-tertiary-color);
  margin: 0 0 4px;
}
.err-meta dd {
  margin: 0;
  font-family: var(--bs-font-monospace);
  font-size: 0.75rem;
  color: var(--bs-body-color);
}
@keyframes errFadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.err-fade { animation: errFadeIn 0.22s ease; }
