:root {
  --color-navy: #102a43;
  --color-navy-strong: #0b2035;
  --color-primary: #1769aa;
  --color-primary-subtle: #2b78b6; /* quieter blue for secondary outline actions; about 4.7:1 on white, still readable text */
  --color-primary-hover: #12578d;
  --color-page: #f4f7fb;
  --color-surface: #ffffff;
  --color-surface-muted: #f8fafc;
  --color-border: #d9e2ec;
  --color-border-strong: #9fb3c8;
  --color-text: #1d2939;
  --color-muted: #52606d;
  --color-danger: #b42318;
  --color-danger-surface: #fee4e2;
  --color-success: #05603a;
  --color-success-surface: #dcfae6;
  --color-warning: #8a4b08;
  --color-warning-surface: #fef0c7;
  --color-info: #185fa5;
  --color-info-surface: #e5f0fb;
  --color-date-check-in: #4a86c5;
  --color-date-check-out: #cc5a52;
  --color-amount-total: #168a5b; /* soft green for total money values (Create Reservation summary) */
  --color-purple: #6b3fa0;
  --color-purple-surface: #f1e7fb;
  --color-indigo: #3f4fa8;
  --color-indigo-surface: #e8ebfa;
  --color-checkout-surface: #fdecea;
  --shadow-card: 0 1px 2px rgb(16 42 67 / 6%);
  /* Task33 Batch 1A foundation additions: reusing the existing scale rather than inventing a parallel one
     (one more radius/shadow step, and the z-index steps components.css needs for the mobile drawer
     backdrop and the header account dropdown, both above the sidebar/header but below the confirmation
     dialog, which is a native <dialog> and always topmost). */
  --radius-lg: 0.875rem;
  --shadow-dropdown: 0 12px 24px rgb(16 42 67 / 16%);
  --dropdown-gap: 0.3125rem;
  /* The one open-menu palette every PMS select and combobox popup uses (light, like the rest of the PMS). */
  --color-dropdown-surface: #ffffff;
  --color-dropdown-border: #d7e2ee;
  --color-dropdown-text: var(--color-navy);
  --color-dropdown-hover: #f1f6fa;
  --color-dropdown-selected: #e6f2fb;
  --color-dropdown-selected-text: var(--color-primary);
  --color-dropdown-disabled-text: var(--color-muted);
  --color-dropdown-disabled-surface: var(--color-surface-muted);
  --radius-sm: 0.375rem;
  --radius-md: 0.625rem;
  --radius-shell: 1rem; /* rounded top-left corner of the content area under the header (desktop) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-8: 3rem;
  --control-height: 2.5rem;
  /* Minimum widths of the filter-bar controls (see "Filter toolbars" in components.css): below these the bar scrolls sideways instead of squeezing. */
  --filter-min-search: 17.5rem;
  --filter-min-date: 15rem;
  --filter-min-select: 12.5rem;
  --header-height: 4rem;
  --z-sidebar: 10;
  --z-overlay: 9;
  --z-dropdown: 25;
  --z-header: 20;
  /* Task33 Batch 1B: above the header/sidebar/dropdown, below the native <dialog> top layer. */
  --z-toast: 30;
  /* Global Task33 icon-size standardization: a small role-based scale so every icon context picks one
     of these instead of an arbitrary per-rule rem value. Stroke weight itself is not a token -- it is
     the shared 1.8 baseline already set once on every fragment in layout/icons.html. */
  --icon-size-sm: 1rem; /* compact/metadata icons, e.g. the inline Guest link chevron */
  --icon-size-action: 1.125rem; /* buttons, tabs, the Back to Reservations link */
  --icon-size-section: 1.25rem; /* card/section heading icons (Guest Information, Room Details, ...) */
  /* Typography levels: the one place a semantic text level gets its size, so no page invents its own. Table BODY text has
     no token on purpose: it is the root 1rem, inherited by the shared td rule. */
  --font-size-page-title: clamp(1.5rem, 2vw, 2rem); /* h1 */
  --font-size-card-title: 1.0625rem; /* card / section headings */
  --font-size-summary-label: 0.8125rem; /* label of a summary strip item (Primary Guest, Room, Check-in ...) */
  --font-size-summary-value: 1rem; /* primary value of a summary strip item */
  --font-size-secondary: 0.8125rem; /* secondary values and helper text: room type, guest code, weekday, timeline meta */
  --font-size-field-label: 0.875rem; /* label column of a label / value row */
  --font-size-field-value: 1rem; /* value column of a label / value row */
  --font-size-table-head: 0.75rem; /* data-table column header (uppercase, see th) */
  --font-size-badge: 0.75rem; /* status chips */
  --color-card-title-icon: var(--color-primary); /* the one subtle blue every card/section title icon uses */
  --icon-size-nav: 1.25rem; /* sidebar navigation, header utilities, summary-strip, dropdown rows */
  color: var(--color-text);
  font-family:
    Inter,
    ui-sans-serif,
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    sans-serif;
  font-size: 16px;
  line-height: 1.5;
}

* {
  box-sizing: border-box;
}
body {
  background: var(--color-page);
  margin: 0;
}
a {
  color: var(--color-primary);
}
a:hover {
  color: var(--color-primary-hover);
}
:focus-visible {
  outline: 3px solid rgb(23 105 170 / 35%);
  outline-offset: 2px;
}
h1,
h2,
h3,
p {
  margin-top: 0;
}
h1 {
  font-size: var(--font-size-page-title);
  letter-spacing: -0.025em;
  line-height: 1.2;
  margin-bottom: var(--space-2);
}
h2 {
  font-size: 1.125rem;
  line-height: 1.3;
  margin-bottom: var(--space-4);
}
/* Page title with its module icon (templates/layout/module-icons.html :: pageTitle): the icon is the sidebar's icon for the module, 28px, in the
   title's own colour (it inherits from the row the H1 inherits from, so the two always match; the SVGs draw with currentColor), 12px before the
   H1 and centred on the title line. The row owns the space that used to sit under the H1, so the header is no taller than
   before; screens that already zero the H1 margin keep that rhythm through --page-title-gap. */
.page-title-row {
  align-items: center;
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--page-title-gap, var(--space-2));
  min-width: 0;
}
.page-title-row > h1 {
  margin: 0;
  min-width: 0;
}
.page-title-icon {
  align-items: center;
  color: inherit;
  display: inline-flex;
  flex: none;
  height: 1.75rem;
  justify-content: center;
  width: 1.75rem;
}
.page-title-icon svg {
  height: 100%;
  width: 100%;
}
.cor-title,
.cir-title,
.folio-header,
.walk-in-header,
.room-change-header,
.stay-extension-header {
  --page-title-gap: 0px;
}

p {
  color: var(--color-muted);
}

.app-shell {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  min-height: 100vh;
}
/* Desktop: the content area has a rounded top-left corner (16px, the others stay square) that reveals the dark
   header/sidebar colour. The page keeps scrolling normally (document scroll, sticky header and sidebar); the corner is
   a sticky pseudo-element pinned just under the header in the content column, so it never scrolls away or gets
   covered by content. As a grid item of the content column it follows the sidebar width, including the collapsed
   rail. It paints the dark colour OUTSIDE a quarter circle and ignores the pointer. Pages, .content, header and
   sidebar are untouched. Below 48rem the layout is a block and nothing is drawn. */
@media not all and (max-width: 48rem) {
  /* The corner piece shares the content's grid cell, so the content is placed there explicitly. */
  .app-shell > .content {
    grid-column: 2;
    grid-row: 2;
  }
  .app-shell::before {
    align-self: start;
    background: radial-gradient(
      circle at 100% 100%,
      transparent calc(var(--radius-shell) - 0.5px),
      var(--color-navy-strong) var(--radius-shell)
    );
    content: "";
    grid-column: 2;
    grid-row: 2;
    height: var(--radius-shell);
    justify-self: start;
    pointer-events: none;
    position: sticky;
    top: var(--header-height);
    width: var(--radius-shell);
    z-index: 1;
  }
}
.site-header {
  align-items: center;
  background: var(--color-navy-strong);
  display: flex;
  gap: var(--space-4);
  grid-column: 1 / -1;
  justify-content: space-between;
  min-height: var(--header-height);
  padding: var(--space-3) var(--space-5);
  position: sticky;
  top: 0;
  z-index: var(--z-header);
}
.brand {
  align-items: center;
  color: #fff;
  display: inline-flex;
  gap: 0.6875rem;
  font-size: 1.125rem;
  font-weight: 750;
  letter-spacing: -0.015em;
  text-decoration: none;
}
.brand:hover {
  color: #fff;
}
.brand-mark {
  display: inline-flex;
  flex: none;
  width: 2.875rem;
}
.brand-mark svg {
  display: block;
  height: auto;
  width: 100%;
}
.brand-name {
  white-space: nowrap;
}
/* The inline sidebar spans from the header to the bottom of the VISIBLE viewport: 100dvh follows the browser toolbars on Safari/iPad, 100vh is the
   fallback. It scrolls on its own and never sideways or together with the page. */
.sidebar {
  align-self: start;
  background: var(--color-navy-strong);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  height: calc(100vh - var(--header-height));
  height: calc(100dvh - var(--header-height));
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-5) var(--space-3);
  position: sticky;
  top: var(--header-height);
  z-index: var(--z-sidebar);
}
/* .sidebar-brand, .sidebar-brand-icon/-text/-name, .sidebar-brand-tagline, .sidebar-account,
   .sidebar-account-name, and .sidebar-logout were removed here: Task33 Batch 1A relocated the account
   area into the header, and a later Dashboard visual polish removed the sidebar's duplicate brand block
   in favor of the one already in the header (see static/css/common/components.css: .header-account*,
   .header-account-logout, and layout/header.html's .brand). */
.nav-section {
  display: grid;
  gap: var(--space-1);
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  width: 100%;
}
.nav-section-label {
  color: #9fb3c8;
  font-size: 0.6875rem;
  font-weight: 750;
  letter-spacing: 0.09em;
  margin: 0 var(--space-3) var(--space-1);
  text-transform: uppercase;
}
.sidebar-nav-link {
  align-items: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  box-sizing: border-box;
  color: #d9e2ec;
  display: flex;
  font-size: 0.9375rem;
  font-weight: 600;
  gap: var(--space-3);
  line-height: 1.5;
  min-height: var(--control-height);
  max-width: 100%;
  padding: var(--space-2) var(--space-3);
  text-decoration: none;
  width: 100%;
}
.sidebar-nav-link:hover,
.sidebar-nav-link:focus-visible {
  background: rgb(255 255 255 / 10%);
  color: #fff;
}
.sidebar-nav-icon {
  align-items: center;
  color: #9fb3c8;
  display: flex;
  flex: none;
  justify-content: center;
}
.sidebar-nav-icon svg {
  height: var(--icon-size-nav);
  width: var(--icon-size-nav);
}
.sidebar-nav-link:hover .sidebar-nav-icon,
.sidebar-nav-link:focus-visible .sidebar-nav-icon {
  color: #fff;
}
.app-shell.page-dashboard .nav-dashboard,
.app-shell.page-reports .nav-reports,
.app-shell.page-check-in .nav-front-desk,
.app-shell.page-check-out .nav-front-desk,
.app-shell.page-reservations .nav-reservations,
.app-shell.page-reservation-create .nav-reservations,
.app-shell.page-guests .nav-guests,
.app-shell.page-rooms .nav-room-list,
.app-shell.page-front-desk .nav-front-desk,
.app-shell.page-housekeeping .nav-housekeeping,
.app-shell.page-expenses .nav-expenses,
.app-shell.page-additional-revenues .nav-additional-revenues,
.app-shell.page-staff .nav-staff,
.app-shell.page-work-records .nav-work-records,
.app-shell.page-users .nav-users,
.app-shell.page-roles .nav-roles {
  background: var(--color-primary);
  color: #fff;
}
.app-shell.page-dashboard .nav-dashboard .sidebar-nav-icon,
.app-shell.page-reports .nav-reports .sidebar-nav-icon,
.app-shell.page-check-in .nav-front-desk .sidebar-nav-icon,
.app-shell.page-check-out .nav-front-desk .sidebar-nav-icon,
.app-shell.page-reservations .nav-reservations .sidebar-nav-icon,
.app-shell.page-reservation-create .nav-reservations .sidebar-nav-icon,
.app-shell.page-guests .nav-guests .sidebar-nav-icon,
.app-shell.page-rooms .nav-room-list .sidebar-nav-icon,
.app-shell.page-front-desk .nav-front-desk .sidebar-nav-icon,
.app-shell.page-housekeeping .nav-housekeeping .sidebar-nav-icon,
.app-shell.page-expenses .nav-expenses .sidebar-nav-icon,
.app-shell.page-additional-revenues .nav-additional-revenues .sidebar-nav-icon,
.app-shell.page-staff .nav-staff .sidebar-nav-icon,
.app-shell.page-work-records .nav-work-records .sidebar-nav-icon,
.app-shell.page-users .nav-users .sidebar-nav-icon,
.app-shell.page-roles .nav-roles .sidebar-nav-icon {
  color: #fff;
}
.app-shell.page-dashboard .nav-dashboard:hover,
.app-shell.page-reports .nav-reports:hover,
.app-shell.page-check-in .nav-front-desk:hover,
.app-shell.page-check-out .nav-front-desk:hover,
.app-shell.page-reservations .nav-reservations:hover,
.app-shell.page-reservation-create .nav-reservations:hover,
.app-shell.page-guests .nav-guests:hover,
.app-shell.page-rooms .nav-room-list:hover,
.app-shell.page-front-desk .nav-front-desk:hover,
.app-shell.page-housekeeping .nav-housekeeping:hover,
.app-shell.page-expenses .nav-expenses:hover,
.app-shell.page-additional-revenues .nav-additional-revenues:hover,
.app-shell.page-staff .nav-staff:hover,
.app-shell.page-work-records .nav-work-records:hover,
.app-shell.page-users .nav-users:hover,
.app-shell.page-roles .nav-roles:hover {
  background: var(--color-primary);
  color: #fff;
}
.content {
  margin: 0 auto;
  max-width: 140rem;
  padding: var(--space-6);
  width: 100%;
}
.content > * + * {
  margin-top: var(--space-6);
}

/* Shared Page Header (Task33): the first block of every application screen (breadcrumb, title, description and header actions, already
   standardized by layout/breadcrumb and .page-header) sits on one banner: the Sunset House reception photograph, faded by a bottom
   gradient into the page colour. It is a layer behind the content area, so no screen repeats any markup or style for it, the text
   keeps its normal colours (the picture is very light on the text side), and the area above the title is tighter than the content
   padding used below the header. Login, error pages, dialogs and print output have no .content area / are excluded below. */
.app-shell > .content {
  isolation: isolate;
  padding-top: var(--space-4);
  position: relative;
}
.app-shell > .content::before {
  /* The whole width of the picture is shown at its own proportions (never stretched, never cropped left or right, at every width,
     phones included). The box is as high as 62% of the picture at the content width, so only the top and bottom of the picture are
     trimmed; the picture is placed 85% of the way down its overflow, which lifts the HOTEL sign (about 35-50% down the picture) into
     the top of the header band, clear of the action button row, instead of behind it or the fade. Both the box and the picture scale
     with the width, so this holds at every width. The bottom gradient fades the rest into the page colour. A floor of 10rem keeps the
     banner from collapsing on narrow content areas; where the picture is then shorter than the floor (phones) the strip above it is
     the page colour, which the picture's own pale top edge blends into. */
  background:
    linear-gradient(to bottom, rgb(244 247 251 / 0%) 0%, rgb(244 247 251 / 0%) 45%, var(--color-page) 100%),
    url("/images/backgrounds/sunset-house-page-header-bg-c5476e2733261c4a3b89e9813a3a7d68.webp") center 85% / 100% auto no-repeat;
  content: "";
  inset: 0 0 auto 0;
  /* The height is 450/2172 of the width (the picture's proportions, with the 10rem floor), made with a percentage padding rather than aspect-ratio +
     min-height: WebKit turned that min-height into a minimum WIDTH (160px -> 772px) and the page scrolled sideways on Safari. */
  height: 0;
  padding-top: max(var(--page-header-bg-min-height, 10rem), 20.718%);
  pointer-events: none;
  position: absolute;
  width: 100%;
  z-index: -1;
}
@media (max-width: 40rem) {
  .app-shell > .content {
    padding-top: var(--space-3);
  }
  /* Phones: the full-width picture is shorter than the 10rem floor, so it is anchored to the top and the leftover strip is at the
     bottom, inside the fade into the page colour, instead of a hard edge under the breadcrumb. Size stays 100% auto (no crop). */
  .app-shell > .content::before {
    background-position: 0 0, center top;
  }
}
@media print {
  .app-shell > .content::before {
    display: none;
  }
}

.page-header,
.page-heading {
  align-items: flex-start;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
}
.page-header-copy > :last-child,
.page-heading > div > :last-child {
  margin-bottom: 0;
}
.page-description {
  font-size: 0.9375rem;
}
.back-link {
  background: none;
  border: none;
  color: var(--color-muted);
  cursor: pointer;
  display: inline-flex;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: var(--space-3);
  padding: 0;
  text-decoration: none;
}
.back-link:hover {
  color: var(--color-primary);
  text-decoration: underline;
}
/* Task33 CHECKED_IN Reservation Detail: the approved mockup's "Back to Reservations" is Task33
   primary-blue with a leading arrow icon, not the shared .back-link neutral default used by the
   other ~37 pages' back links. Opt-in modifier, scoped to this page only. */
.back-link--primary {
  color: var(--color-primary);
  gap: 0.4rem;
  display: flex;
  align-items: center;
}
.back-link--primary svg {
  flex: none;
  height: var(--icon-size-action);
  width: var(--icon-size-action);
}
.back-link--primary:hover {
  color: var(--color-primary-hover);
}
.breadcrumb {
  align-items: center;
  display: flex;
  font-size: 0.875rem;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.breadcrumb a {
  font-weight: 600;
  text-decoration: none;
}
.breadcrumb a:hover {
  text-decoration: underline;
}
.breadcrumb-separator {
  color: var(--color-border-strong);
}
.breadcrumb-current {
  color: var(--color-muted);
  font-weight: 600;
}
.card,
.detail-grid > div,
fieldset {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.card {
  padding: var(--space-5);
}
.card > :last-child {
  margin-bottom: 0;
}
.summary-card {
  padding: var(--space-5);
}
.summary-card dt {
  color: var(--color-muted);
  font-size: 0.8125rem;
  font-weight: 700;
}
.summary-card dd,
.summary-card__secondary {
  font-size: 1.75rem;
  font-weight: 750;
  letter-spacing: -0.03em;
  line-height: 1.2;
}
.summary-card dd {
  color: var(--color-navy);
  margin: var(--space-2) 0 0;
}
.summary-card__kpis {
  align-items: start;
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--space-2);
}
.summary-card__kpis > * + * {
  border-left: 1px solid var(--color-border);
  padding-left: var(--space-3);
}
.summary-card__kpis dd {
  margin-top: 0;
}
.summary-card__secondary {
  margin: 0;
}
.summary-card__secondary--info {
  color: #2563eb;
}
.summary-card__secondary--available {
  color: #16a34a;
}
.summary-card__secondary--attention {
  color: #d97706;
}
.summary-card__label {
  color: var(--color-muted);
  font-size: 0.6875rem;
  font-weight: 750;
  letter-spacing: 0.04em;
  margin: var(--space-1) 0 0;
  text-transform: uppercase;
}
.summary-card .action-row {
  border-top: 1px solid var(--color-border);
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
}
@media (max-width: 30rem) {
  .summary-card__kpis {
    grid-template-columns: 1fr;
  }
  .summary-card__kpis > * + * {
    border-left: 0;
    border-top: 1px solid var(--color-border);
    padding-left: 0;
    padding-top: var(--space-3);
  }
}
/* Task33 final Dashboard (spec sec. 9.1): operational-first KPI cards, a two-column operational
   layout (worklist table + Room Status donut, then two more worklist tables), Recent Reservations,
   and Quick Actions tiles. Reuses .card/.kpi-grid/.table-wrap/.button/.status-badge rather than a
   parallel component set; the rules below are the small amount of layout genuinely specific to this
   page's KPI/donut/tile composition. */
/* Breadcrumb -> title gap shared with Front Desk, Reservation List and Create Reservation (--space-5). */
.page-dashboard .content > .breadcrumb + .page-header {
  margin-top: var(--space-5);
}
/* The greeting and the subtitle are two description lines under the title, close together. */
.dashboard-header-copy .page-description {
  font-weight: 400;
  margin-bottom: 0;
}
.dashboard-header-copy .page-description + .page-description {
  margin-top: var(--space-1);
}
.dashboard-date {
  color: var(--color-muted);
  font-weight: 600;
  margin: 0;
}
.card-header-row {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  margin-bottom: var(--space-4);
}
.card-header-row h2 {
  margin-bottom: 0;
}
.kpi-card {
  align-items: flex-start;
  display: flex;
  container-type: inline-size;
  gap: var(--space-4);
  position: relative;
}
/* KPI label: one step up from the generic summary label so it reads at a glance, still clearly below the value. */
.kpi-card .summary-card__label {
  color: var(--color-navy);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.3;
}
/* Decorative calendar in the lower-right of the Arrivals / Departures cards: background only (no interaction, no text),
   kept behind the body, and scaled down with the card width so it never reaches the text. */
.kpi-card__decor {
  bottom: var(--space-3);
  height: 4.25rem;
  opacity: 0.32;
  pointer-events: none;
  position: absolute;
  right: var(--space-4);
  width: 4.25rem;
  z-index: 0;
}
/* Container widths below are the card's content box (the card width minus its padding). */
@container (max-width: 18rem) {
  .kpi-card__decor {
    bottom: var(--space-2);
    height: 3rem;
    right: var(--space-3);
    width: 3rem;
  }
}
@container (max-width: 13.75rem) {
  .kpi-card__decor {
    height: 2.25rem;
    width: 2.25rem;
  }
}
.kpi-card__decor svg {
  display: block;
  height: 100%;
  width: 100%;
}
.kpi-card__decor--purple {
  color: var(--color-purple);
}
.kpi-card__decor--danger {
  color: var(--color-danger);
}
.kpi-card__decor--info {
  color: var(--color-info);
}
.kpi-card__decor--success {
  color: var(--color-success);
}
.kpi-card__decor--warning {
  color: var(--color-warning);
}
/* Dashboard KPI cards follow the Additional Revenue KPI cards: Currently Staying white; Vacant, Arrivals and Departures a very light
   tint of their accent (Arrivals uses the same tint as the Additional Revenue Top Category card; the green and orange tints are the
   existing success / warning surfaces thinned with white), and one decorative-icon size, position and opacity on all four. */
.kpi-card--success {
  background: color-mix(in srgb, var(--color-success-surface) 35%, #ffffff);
}
.kpi-card--purple {
  background: #faf7ff;
}
.kpi-card--warning {
  background: color-mix(in srgb, var(--color-warning-surface) 35%, #ffffff);
}
/* The description lines stop short of the decorative icon, so it never sits under text at any card width. */
.page-dashboard .kpi-card__secondary,
.page-dashboard .kpi-card__trend {
  padding-right: calc(2.5rem + var(--space-3));
}
.page-dashboard .kpi-card__decor {
  bottom: var(--space-2);
  height: 2.5rem;
  opacity: 0.22;
  right: var(--space-3);
  width: 2.5rem;
}
.kpi-card__icon,
.kpi-card__body {
  position: relative;
  z-index: 1;
}
.kpi-card__icon {
  align-items: center;
  border-radius: 999px;
  display: flex;
  flex-shrink: 0;
  height: 2.75rem;
  justify-content: center;
  width: 2.75rem;
}
.kpi-card__icon--info {
  background: var(--color-info-surface);
  color: var(--color-info);
}
.kpi-card__icon--success {
  background: var(--color-success-surface);
  color: var(--color-success);
}
.kpi-card__icon--purple {
  background: var(--color-purple-surface);
  color: var(--color-purple);
}
.kpi-card__icon--warning {
  background: var(--color-warning-surface);
  color: var(--color-warning);
}
.kpi-card__body {
  min-width: 0;
}
.kpi-card__value {
  color: var(--color-navy);
  font-size: 1.75rem;
  font-weight: 750;
  letter-spacing: -0.03em;
  line-height: 1.2;
  margin: var(--space-2) 0 0;
}
.kpi-card__unit {
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 600;
}
.kpi-card__secondary {
  color: var(--color-muted);
  font-size: 0.8125rem;
  margin: var(--space-1) 0 0;
}
.kpi-card__trend {
  font-size: 0.8125rem;
  font-weight: 700;
  margin: var(--space-1) 0 0;
}
.kpi-card__trend--up {
  color: var(--color-success);
}
.kpi-card__trend--down {
  color: var(--color-danger);
}
.kpi-card__trend--flat {
  color: var(--color-muted);
}
/* One typography scale for the six Dashboard cards (Quick Actions, Room Status, Arrivals, Departures, Currently Staying, Recent
   Reservations). Every size below reads from these four tokens; the rest of the app keeps its own scale. */
.page-dashboard {
  --dashboard-title-size: 1.1875rem; /* card titles, 19px */
  --dashboard-primary-size: 1rem; /* guest name, reservation number, quick action title, legend label, 16px */
  --dashboard-secondary-size: 0.875rem; /* guest code, room type, dates, source, nights, descriptions, 14px */
  --dashboard-badge-size: 0.8125rem; /* status badges, 13px */
  /* The record structure shared by the four list cards: [avatar | identity | status | chevron]. The identity side (avatar included)
     is about 65% of the row and the status side about 35%; the status column is a share of the row, never the width of any
     record's own text, so its left edge forms one straight line down every card. The 11rem floor is about the width of the longest
     single-line badge, so a badge stays as wide as its label (never stretched or wrapped) when the card is narrow. */
  --dashboard-avatar-col: 2.5rem;
  --dashboard-chevron-col: 1.125rem;
  --dashboard-status-col: max(calc(35% - var(--dashboard-chevron-col) - var(--space-3)), 11rem);
}
.dashboard-operational-grid .card > h2,
.dashboard-operational-grid .card-header-row h2 {
  font-size: var(--dashboard-title-size);
  font-weight: 700;
}
/* Dashboard card title icon (dashboard/fragments :: titleIcon): the shared light-blue rounded title container at the Dashboard size, 32px with
   a 20px icon, 8px radius, 12px before the title (.card-title-heading). The doubled class outranks the generic .card-title-icon rule below. */
/* The icon makes the title wider, so the header row stays on one line instead of dropping the "View all" action under the title: the
   title text wraps inside its own space, the action keeps its size and stays at the right edge. */
.dashboard-operational-grid .card-header-row {
  flex-wrap: nowrap;
}
.dashboard-operational-grid .card-header-row h2.card-title-heading {
  min-width: 0;
}
.dashboard-operational-grid .card-header-row .dashboard-view-all {
  flex: none;
  margin-left: auto;
}
.card-title-icon.dashboard-title-icon {
  background: #e7f1fc;
  border-radius: 0.5rem;
  color: #1d6fb5;
  height: 2rem;
  padding: 0.375rem;
  width: 2rem;
}
.dashboard-operational-grid {
  align-items: stretch;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.dashboard-operational-grid > * {
  min-width: 0;
}
.dashboard-operational-grid > .card {
  height: 100%;
}
.room-status-layout {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
}
/* Layering: the Chart.js tooltip is painted on the canvas itself, so it can only sit above the centre label if the whole
   canvas sits above that HTML label. The canvas is transparent in the donut hole, so the label stays visible beneath it,
   and an opaque tooltip drawn over the hole covers it. isolation keeps these z-index values inside the chart wrapper. */
.room-status-donut-wrap {
  flex-shrink: 0;
  height: 11rem;
  isolation: isolate;
  position: relative;
  width: 11rem;
}
.room-status-donut-wrap canvas {
  height: 100%;
  position: relative;
  width: 100%;
  z-index: 1;
}
.room-status-donut-total {
  left: 50%;
  pointer-events: none;
  position: absolute;
  z-index: 0;
  text-align: center;
  top: 50%;
  transform: translate(-50%, -50%);
}
.room-status-donut-total dd {
  color: var(--color-navy);
  font-size: 1.5rem;
  font-weight: 750;
  margin: 0;
}
.room-status-donut-total dt {
  color: var(--color-muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
}
.room-status-legend {
  display: grid;
  flex: 1;
  min-width: 10rem;
}
/* A subtle divider between status rows, only inside the legend (never under the donut, none after the last row). The row
   padding replaces the former grid gap, so the row spacing stays the same. */
.room-status-legend-row {
  align-items: center;
  border-bottom: 1px solid var(--color-border);
  display: flex;
  font-size: var(--dashboard-primary-size);
  font-weight: 600;
  gap: var(--space-2);
  justify-content: space-between;
  padding: var(--space-1) 0;
}
.room-status-legend-row:last-child {
  border-bottom: 0;
}
.room-status-legend-label {
  align-items: center;
  display: flex;
  gap: var(--space-2);
}
.room-status-legend-dot {
  border-radius: 999px;
  flex-shrink: 0;
  height: 0.625rem;
  width: 0.625rem;
}
.room-status-legend-count {
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}
/* Same colors as the equivalent .status-badge--<status> modifiers, so the donut/legend and any
   status badge elsewhere always agree on what each RoomStatus looks like. */
.room-status-legend-dot--available {
  background: var(--color-success);
}
.room-status-legend-dot--occupied {
  background: var(--color-info);
}
.room-status-legend-dot--dirty {
  background: var(--color-warning);
}
.room-status-legend-dot--cleaning {
  background: #08798c;
}
.room-status-legend-dot--maintenance {
  background: #a04300;
}
.room-status-legend-dot--out_of_order {
  background: var(--color-danger);
}
/* Dashboard worklists (Arrivals, Currently Staying, Departures, Recent Reservations): one compact list row per record that
   always fits its card, never a table. Each row is a single link (avatar or icon, identity, optional meta, status, chevron).
   The list is a size container so a row re-flows to the width of its own card: wide rows keep one line, narrow ones stack the
   meta and status under the identity. Nothing is clipped or scrolled. */
.dashboard-list {
  container-type: inline-size;
  list-style: none;
  margin: 0;
  padding: 0;
}
.dashboard-list > li + li {
  border-top: 1px solid var(--color-border);
}
/* Equal-height rows (Today's Arrivals): the list is a grid whose rows all take the height of the tallest record, so a row with
   a readiness warning no longer makes the others look short. Each row's content stays vertically centred and nothing is
   clipped. Narrow screens use natural heights. */
.dashboard-list--equal {
  display: grid;
  grid-auto-rows: 1fr;
}
.dashboard-list--equal > li {
  display: grid;
}
@media (max-width: 40rem) {
  .dashboard-list--equal {
    grid-auto-rows: auto;
  }
}
.dashboard-row {
  align-items: center;
  border-radius: var(--radius-sm);
  color: inherit;
  display: grid;
  gap: var(--space-1) var(--space-3);
  grid-template-areas: "a m s c";
  grid-template-columns: var(--dashboard-avatar-col) minmax(0, 1fr) var(--dashboard-status-col) var(--dashboard-chevron-col);
  padding: var(--space-3) var(--space-2);
  text-decoration: none;
}
/* A row with its meta directly in the grid (Currently Staying, Recent Reservations): the meta sits under the identity, with the
   status and chevron centred against both lines. */
.dashboard-row--inline {
  grid-template-areas: "a m s c" "a t s c";
}
/* The whole row is the link, so the whole row shows the hand: set on the row and on every descendant (avatar, text, meta, badge,
   chevron), in every state, so no child, visited link, focus or history restore can bring back the default or text cursor. A plain
   stylesheet rule, not script state. */
.dashboard-row,
.dashboard-row:hover,
.dashboard-row:focus,
.dashboard-row:active,
.dashboard-row:visited,
.dashboard-row * {
  cursor: pointer;
}
.dashboard-row:hover {
  background: var(--color-surface-muted);
}
.dashboard-row:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}
.dashboard-row--urgent {
  box-shadow: inset 3px 0 0 var(--color-danger);
}
.dashboard-avatar,
.dashboard-row__icon {
  align-items: center;
  border-radius: 50%;
  display: inline-flex;
  flex: none;
  grid-area: a;
  height: 2.5rem;
  justify-content: center;
  width: 2.5rem;
}
.dashboard-avatar {
  background: var(--color-indigo-surface);
  color: var(--color-indigo);
  font-size: 0.8125rem;
  font-weight: 700;
}
.dashboard-row__icon {
  background: var(--color-info-surface);
  border-radius: var(--radius-sm);
  color: var(--color-primary);
}
.dashboard-row__icon svg {
  height: 1.125rem;
  width: 1.125rem;
}
.dashboard-row__main {
  display: grid;
  gap: 0.125rem;
  grid-area: m;
  min-width: 0;
}
.dashboard-row__title {
  color: var(--color-navy);
  font-size: var(--dashboard-primary-size);
  font-weight: 700;
  overflow-wrap: anywhere;
}
.dashboard-row__sub {
  color: var(--color-muted);
  font-size: var(--dashboard-secondary-size);
  font-weight: 500;
  overflow-wrap: anywhere;
}
.dashboard-row__meta {
  color: var(--color-text);
  display: flex;
  flex-wrap: wrap;
  font-size: var(--dashboard-secondary-size);
  font-weight: 500;
  gap: var(--space-1) var(--space-4);
  margin-top: 0.125rem;
}
/* Only a meta that is a direct child of the row (Currently Staying, Recent Reservations) takes a grid area; elsewhere it
   sits inside the identity block. */
.dashboard-row--inline > .dashboard-row__meta {
  grid-area: t;
  margin-top: 0;
}
.dashboard-row__meta-item {
  align-items: center;
  display: inline-flex;
  gap: 0.375rem;
  white-space: nowrap;
}
.dashboard-row__meta-item svg {
  color: var(--color-muted);
  flex: none;
  height: 1rem;
  width: 1rem;
}
.dashboard-row__status {
  display: grid;
  gap: var(--space-1);
  grid-area: s;
  justify-items: start;
  min-width: 0;
}
.dashboard-row__note {
  color: var(--color-muted);
  font-size: var(--dashboard-secondary-size);
  font-weight: 500;
  line-height: 1.35;
}
.dashboard-list .status-badge {
  font-size: var(--dashboard-badge-size);
  font-weight: 700;
  /* a badge never widens the status column: when its label does not fit it wraps inside the pill */
  height: auto;
  max-width: 100%;
  min-height: 1.75rem;
  padding: 0.25rem 0.75rem;
  text-align: center;
  white-space: normal;
}
/* Today's Arrivals "ready" badge: one line. Like every other Dashboard badge it starts at the left edge of the shared status column
   (justify-items: start on .dashboard-row__status), never centred, so it lines up with the badges of the other cards. */
.dashboard-list .status-badge.dashboard-row__badge--ready {
  white-space: nowrap;
}
.dashboard-row__note--danger {
  color: var(--color-danger);
}
.dashboard-row__chevron {
  color: var(--color-muted);
  display: inline-flex;
  grid-area: c;
}
.dashboard-row__chevron svg {
  height: 1.125rem;
  width: 1.125rem;
}
/* Narrow card (phone, narrow tablet): the identity keeps the row, then the meta and the status stack under it. */
@container (max-width: 30rem) {
  .dashboard-row {
    grid-template-areas: "a m c" ". s s";
    grid-template-columns: var(--dashboard-avatar-col) minmax(0, 1fr) var(--dashboard-chevron-col);
  }
  .dashboard-row--inline {
    grid-template-areas: "a m c" ". t t" ". s s";
  }
}
/* Dashboard "View all" (dashboard/fragments :: viewAll): the shared compact outline button, one step larger to sit with the
   Dashboard scale. */
.button.dashboard-view-all {
  font-size: var(--dashboard-badge-size);
  height: 2rem;
}
.button.dashboard-view-all svg {
  height: 1rem;
  width: 1rem;
}
/* Two tiles per row when the card is wide enough for both, one per row otherwise (never squeezed so tight that a title spills). */
.quick-actions-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}
.quick-action-tile {
  align-items: center;
  color: inherit;
  display: flex;
  gap: var(--space-3);
  text-decoration: none;
}
.quick-action-tile:hover {
  border-color: var(--color-border-strong);
}
.quick-action-tile__icon {
  align-items: center;
  border-radius: 999px;
  display: flex;
  flex-shrink: 0;
  height: 2.5rem;
  justify-content: center;
  width: 2.5rem;
}
.quick-action-tile__text {
  display: block;
  min-width: 0;
}
.quick-action-tile__title {
  display: block;
  font-size: var(--dashboard-primary-size);
  font-weight: 700;
  overflow-wrap: anywhere;
}
.quick-action-tile__subtitle {
  color: var(--color-muted);
  display: block;
  font-size: var(--dashboard-secondary-size);
  font-weight: 500;
  margin-top: var(--space-1);
  overflow-wrap: anywhere;
}
.quick-action-tile__chevron {
  color: var(--color-muted);
  margin-left: auto;
}
@media (max-width: 48rem) {
  .dashboard-operational-grid,
  .quick-actions-grid {
    grid-template-columns: 1fr;
  }
  .room-status-layout {
    justify-content: center;
  }
}

.button {
  align-items: center;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 700;
  gap: 0.4rem;
  height: var(--control-height);
  justify-content: center;
  line-height: 1.25;
  padding: 0.625rem 0.875rem;
  text-decoration: none;
  transition:
    background-color 150ms ease,
    border-color 150ms ease,
    color 150ms ease;
}
.button svg {
  flex: none;
  height: var(--icon-size-action);
  width: var(--icon-size-action);
}
.button-primary {
  background: var(--color-primary);
  color: #fff;
}
.button-primary:hover {
  background: var(--color-primary-hover);
  color: #fff;
}
.button-secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-navy);
}
.button-secondary:hover {
  background: #edf2f7;
  color: var(--color-navy);
}
/* Task33 outline-blue secondary action (Edit/Add/Change on the CHECKED_IN Reservation Detail hub):
   white background, Task33 primary-blue border/text/icon, matching the approved mockup. A distinct
   opt-in modifier rather than a change to the shared .button-secondary default, so pages/actions
   outside this approved mockup keep their existing neutral treatment. */
.button-outline-primary {
  background: var(--color-surface);
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.button-outline-primary:hover {
  background: var(--color-info-surface);
  border-color: var(--color-primary-hover);
  color: var(--color-primary-hover);
}
/* Subtle outline-blue: a quieter sibling of .button-outline-primary for the secondary action beside a primary-blue one (white
   background; border, text and icon in the same subtle blue). Hover: very light blue background and the stronger primary blue. */
.button-outline-subtle {
  background: var(--color-surface);
  border-color: var(--color-primary-subtle);
  color: var(--color-primary-subtle);
}
.button-outline-subtle:hover {
  background: var(--color-info-surface);
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.button-danger {
  background: var(--color-danger);
  color: #fff;
}
.button-danger:hover {
  background: #8f1d15;
  color: #fff;
}
.button-link {
  background: transparent;
  color: var(--color-primary);
  height: auto;
  min-height: auto;
  padding: var(--space-2);
}
/* Compact secondary action placed inside a dense card header (Task33 CHECKED_IN hub) rather than
   the page-level action-row, so it must not take the same visual weight as a primary hub action. */
.button-compact {
  flex: none;
  font-size: 0.75rem;
  height: 1.875rem;
  padding: 0.3rem 0.65rem;
  white-space: nowrap;
}
.button-link:hover {
  background: #eaf1f8;
}
.button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.table-action {
  font-size: 0.875rem;
  font-weight: 700;
  white-space: nowrap;
}
.action-row,
.form-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.form-actions {
  border-top: 1px solid var(--color-border);
  justify-content: flex-end;
  margin-top: var(--space-6);
  padding-top: var(--space-4);
}
.actions {
  display: grid;
  gap: var(--space-4);
}
.actions > h2 {
  margin-bottom: 0;
}
.actions form {
  display: inline-flex;
}
.additional-revenue-void-copy {
  color: var(--color-muted);
  margin: 0;
}
.actions form.additional-revenue-void-form {
  display: grid;
  gap: var(--space-4);
  width: 100%;
}
.additional-revenue-void-form .form-field {
  margin-bottom: 0;
}
.additional-revenue-void-form__actions {
  display: flex;
  justify-content: flex-end;
}
.actions form.reservation-reason-form {
  display: grid;
  gap: var(--space-4);
  width: 100%;
}
.reservation-reason-form .form-field {
  margin-bottom: 0;
}

.confirmation-dialog {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgb(16 42 67 / 24%);
  color: var(--color-text);
  max-width: min(32rem, calc(100% - 2 * var(--space-4)));
  padding: 0;
  width: 100%;
}
.confirmation-dialog::backdrop {
  background: rgb(11 32 53 / 52%);
}
.confirmation-dialog__content {
  padding: var(--space-5);
}
.confirmation-dialog__content h2 {
  margin-bottom: var(--space-2);
}
.confirmation-dialog__content p {
  margin-bottom: var(--space-5);
}
.confirmation-dialog__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: flex-end;
}
.confirmation-dialog[data-confirm-severity="WARNING"] {
  border-color: #f5cc72;
}
.confirmation-dialog[data-confirm-severity="WARNING"]
  .confirmation-dialog__confirm {
  background: var(--color-warning);
  color: #fff;
}
.confirmation-dialog[data-confirm-severity="WARNING"]
  .confirmation-dialog__confirm:hover {
  background: #6f3c06;
  color: #fff;
}
.confirmation-dialog[data-confirm-severity="DANGER"] {
  border-color: #f9b4ae;
}
.confirmation-dialog[data-confirm-severity="DANGER"]
  .confirmation-dialog__confirm {
  background: var(--color-danger);
  color: #fff;
}
.confirmation-dialog[data-confirm-severity="DANGER"]
  .confirmation-dialog__confirm:hover {
  background: #8f1d15;
  color: #fff;
}

.message {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  margin: 0;
  padding: var(--space-3) var(--space-4);
}
.message-success {
  background: var(--color-success-surface);
  border-color: #a6e9bf;
  color: var(--color-success);
}
.message-error {
  background: var(--color-danger-surface);
  border-color: #f9b4ae;
  color: var(--color-danger);
}
.message-warning {
  background: var(--color-warning-surface);
  border-color: #f5cc72;
  color: var(--color-warning);
}
.field-error {
  color: var(--color-danger);
  font-size: 0.8125rem;
  font-weight: 600;
  margin: 0;
}

.table-wrap {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow-x: auto;
}
table {
  background: var(--color-surface);
  border-collapse: collapse;
  min-width: 38rem;
  width: 100%;
}
th,
td {
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-3) var(--space-4);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}
th {
  background: var(--color-surface-muted);
  color: var(--color-muted);
  font-size: var(--font-size-table-head);
  font-weight: 750;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Shared Task33 table rule: cell values stay on one line (identifiers, names, dates, money, statuses,
   usernames, counts, descriptions) and the table scrolls horizontally (.table-wrap already sets
   overflow-x: auto, and table already sets a min-width) instead of wrapping. Opt out only for a
   column that is genuinely designed to show long multi-line free text (e.g. Notes), with
   .table-cell-wrap -- not currently used by any Task33 table, but kept available for one that needs it. */
.table-cell-wrap {
  white-space: normal;
}
tbody tr {
  transition: background-color 150ms ease;
}
tbody tr:hover {
  background: #f8fbff;
}
tbody tr:last-child td {
  border-bottom: 0;
}
.table-number,
.table-date {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.text-center {
  text-align: center;
}
.table-actions {
  text-align: right;
  white-space: nowrap;
  width: 1%;
}
.table-actions .action-row {
  flex-wrap: nowrap;
}
.table-reference {
  max-width: 12rem;
}
/* The one PMS status badge (Reservation Detail's approved look): compact uppercase pill. The status only chooses the colour
   (.status-badge--<status> below); size, type and shape are the same on every screen. --small is the same badge for tight
   places such as table cells and inline sentences. A screen never resizes or restyles the badge. */
.status,
.status-badge {
  align-items: center;
  background: #eaf1f8;
  border: 1px solid transparent;
  border-radius: 999px;
  color: #334e68;
  display: inline-flex;
  font-size: 0.8125rem;
  font-weight: 750;
  height: 1.75rem;
  justify-content: center;
  letter-spacing: 0.03em;
  line-height: 1.25;
  padding: 0 0.75rem;
  text-transform: uppercase;
  white-space: nowrap;
}
.status-badge--small {
  font-size: var(--font-size-badge);
  height: 1.5rem;
  padding: 0 0.625rem;
}
.status-badge--confirmed,
.status-badge--submitted {
  background: #e5f0fb;
  color: #185fa5;
}
.status-badge--checked_in,
.status-badge--occupied,
.status-badge--available,
.status-badge--approved,
.status-badge--recorded,
.status-badge--current,
.status-badge--active,
.status-badge--paid {
  background: var(--color-success-surface);
  color: var(--color-success);
}
.status-badge--cancelled,
.status-badge--out_of_order,
.status-badge--rejected,
.status-badge--voided,
.status-badge--failed {
  background: var(--color-danger-surface);
  color: var(--color-danger);
}
.status-badge--dirty,
.status-badge--pending {
  background: var(--color-warning-surface);
  color: var(--color-warning);
}
.status-badge--no_show {
  background: #fde9c4;
  color: #a0520a;
}
.status-badge--retained {
  background: #fde9c4;
  color: #a0520a;
}
.status-badge--cleaning {
  background: #dff7fa;
  color: #08798c;
}
.status-badge--maintenance {
  background: #ffead5;
  color: #a04300;
}
.status-badge--posted,
.status-badge--refunded {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-muted);
}
.status-badge--draft {
  background: #e6e9ee;
  color: #475467;
}
.status-badge--checked_out {
  background: #e3e8ee;
  border-color: #cdd6df;
  color: #3e4c59;
}

.detail-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
}
.detail-grid > div {
  padding: var(--space-4);
}
.detail-list {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  display: grid;
  grid-template-columns: minmax(9rem, 0.4fr) 1fr;
  margin: 0;
  overflow: hidden;
}
.detail-list dt,
.detail-list dd {
  border-bottom: 1px solid var(--color-border);
  margin: 0;
  padding: var(--space-3) var(--space-4);
}
.detail-list dt {
  background: var(--color-surface-muted);
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 700;
}
.detail-list dd {
  background: var(--color-surface);
}
.detail-list > :nth-last-child(-n + 2) {
  border-bottom: 0;
}
dt {
  color: var(--color-muted);
  font-weight: 700;
}

/* Read-only label/value rows: a light-gray label cell and a white value cell, each filling its row. The convention for
   <dl class="label-value-rows"><div><dt/><dd/></div></dl> across the PMS; --divided adds a rule between rows. */
.label-value-rows {
  margin: 0;
}
.label-value-rows > div {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
}
.label-value-rows > div[hidden] {
  display: none;
}
.label-value-rows dt,
.label-value-rows dd {
  margin: 0;
  padding: var(--space-2) var(--space-3);
}
.label-value-rows dt {
  background: var(--color-surface-muted);
  color: var(--color-muted);
  font-size: var(--font-size-field-label);
  font-weight: 600;
  line-height: 1.4;
}
.label-value-rows dd {
  align-content: start;
  background: var(--color-surface);
  min-width: 0;
  overflow-wrap: anywhere;
}
.label-value-rows--strong dd {
  color: var(--color-navy);
  font-size: 0.9375rem;
  font-weight: 700;
}
.label-value-rows--divided > div {
  border-bottom: 1px solid var(--color-border);
}
.label-value-rows--divided > div:last-child {
  border-bottom: 0;
}
/* --fit: the label column is as wide as the longest label in the list (never wrapping), shared by every row. Set
   --label-value-label-width to give several lists (e.g. two cards) the exact same label width instead. */
.label-value-rows--fit {
  display: grid;
  grid-template-columns: var(--label-value-label-width, max-content) minmax(0, 1fr);
}
.label-value-rows--fit > div {
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
}
.label-value-rows--fit dt {
  white-space: nowrap;
}
/* --info: the compact bordered information table of the PMS guest cards (the look of Reservation Detail's Guest Information):
   rounded outer border, muted-gray label cells, white value cells, medium-weight type at the normal field sizes, content
   centred vertically. Combine with --divided (row rules) and --fit (label column = longest label). */
.label-value-rows--info {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.label-value-rows--info dt,
.label-value-rows--info dd {
  align-content: center;
  padding: 0.375rem var(--space-3);
}
.label-value-rows--info dt {
  color: var(--color-muted);
  font-size: var(--font-size-field-label);
  font-weight: 500;
}
.label-value-rows--info dd {
  color: var(--color-navy);
  font-size: var(--font-size-field-value);
  font-weight: 500;
}

dd {
  margin: var(--space-1) 0 0;
}

.form-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: var(--space-5);
}
.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.form-field[hidden] {
  display: none;
}
.form-field label,
legend {
  color: var(--color-text);
  font-size: 0.875rem;
  font-weight: 700;
}
.form-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
}
.profile-document-existing {
  margin-bottom: var(--space-4);
}
.profile-document-existing h3 {
  color: var(--color-muted);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  margin: 0 0 var(--space-2);
  text-transform: uppercase;
}
.profile-document-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.profile-document-actions form {
  margin: 0;
}
.form-hint {
  font-size: 0.875rem;
  margin: 0;
}
.reservation-filter-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.reservation-filter-actions,
.room-filter-actions,
.expense-filter-actions {
  justify-content: flex-end;
}
.reservation-results,
.guest-results,
.room-results,
.expense-results {
  display: grid;
  gap: var(--space-4);
}
.results-toolbar {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
}
.results-toolbar > p {
  margin-bottom: 0;
}
.table-sort-link {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}
.table-sort-link:hover {
  text-decoration: underline;
}
.pagination {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0;
}
.pagination__segment {
  align-items: center;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  box-sizing: border-box;
  color: var(--color-primary);
  display: inline-flex;
  font-size: 0.875rem;
  font-weight: 700;
  height: var(--control-height);
  justify-content: center;
  line-height: 1.25;
  min-width: var(--control-height);
  padding: 0 0.875rem;
  text-decoration: none;
}
.pagination__segment + .pagination__segment {
  border-left: 0;
}
.pagination__segment:first-child {
  border-bottom-left-radius: var(--radius-sm);
  border-top-left-radius: var(--radius-sm);
}
.pagination__segment:last-child {
  border-bottom-right-radius: var(--radius-sm);
  border-top-right-radius: var(--radius-sm);
}
.pagination__segment:hover {
  background: #edf2f7;
  color: var(--color-primary-hover);
}
.pagination__segment--current {
  background: var(--color-primary);
  color: #fff;
}
.pagination__segment--current:hover {
  background: var(--color-primary);
  color: #fff;
}
.pagination__segment--ellipsis {
  color: var(--color-muted);
  cursor: default;
  pointer-events: none;
}

.check-in-review-warning {
  background: var(--color-warning-surface);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-warning);
  padding: var(--space-4);
}
.check-in-review-warning h2 {
  color: var(--color-warning);
  font-size: 1rem;
  margin-bottom: var(--space-2);
}
.check-in-review-warning p {
  color: inherit;
  margin-bottom: 0;
}
.check-in-review-blocked {
  background: var(--color-danger-surface);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-danger);
  padding: var(--space-4);
}
.check-in-review-blocked h2 {
  color: var(--color-danger);
  font-size: 1rem;
  margin-bottom: var(--space-2);
}
.check-in-review-blocked p {
  color: inherit;
  margin-bottom: 0;
}
.reservation-detail {
  display: grid;
  gap: var(--space-5);
}
.reservation-detail-section {
  display: grid;
  gap: var(--space-4);
}
.reservation-detail-section-header {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
}
.reservation-detail-section-header h2 {
  margin-bottom: 0;
}
.reservation-detail-section-header p {
  font-size: 0.875rem;
  margin: var(--space-1) 0 0;
}
.reservation-detail-section > .table-wrap {
  box-shadow: none;
}
/* Card/section title icon, emitted by templates/layout/card-icons.html. The single source of truth for how a title icon
   looks on every screen: transparent background (no coloured tile), one blue, one size, one stroke weight (set on the
   shared SVGs in layout/icons.html). Per-page stylesheets must not restyle it. */
/* THE section-title icon: every icon placed immediately before a card / section title (templates call
   layout/card-icons :: title('<concept>') or titleIcon('<icon>')) is a compact light-blue rounded square with the primary-blue icon
   centred in it. Decorative only (no hover, no cursor, no border). Not for page titles, tabs, buttons, table or status icons. */
.card-title-icon {
  align-items: center;
  background: var(--color-info-surface);
  border-radius: var(--radius-sm);
  box-sizing: border-box;
  color: var(--color-card-title-icon);
  display: inline-flex;
  flex: none;
  height: 1.75rem;
  justify-content: center;
  padding: 0.3125rem;
  width: 1.75rem;
}
.card-title-icon svg {
  height: 100%;
  width: 100%;
}
/* Main list card title icon (layout/module-icons :: cardTitle): the module icon at 20px in the same 28px container. */
.card-title-icon--module {
  padding: 0.25rem;
}
/* A heading that carries its title icon inline (icon, then text on one centred line). */
.card-title-heading {
  align-items: center;
  display: flex;
  gap: var(--space-3);
}
.reservation-info-value {
  color: var(--color-navy);
  font-size: 0.9375rem;
  font-weight: 700;
  margin: var(--space-1) 0 0;
  overflow-wrap: anywhere;
}
.reservation-info-secondary {
  color: var(--color-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  margin: var(--space-1) 0 0;
  overflow-wrap: anywhere;
}
/* Vertical timeline: spacing between events lives on .hub-timeline-content's own margin-bottom (not
   on .hub-timeline's gap), because a flex item's margin contributes to its row's auto height, which
   is what .hub-timeline-rail (align-items: stretch) actually stretches to match. .hub-timeline-connector
   -- a flex:1 sibling of the dot inside that same per-item rail -- then fills the rail's full stretched
   height, running through that spacing to visually join this event's dot to the next one, without
   extending past the final event (it is simply not rendered for the last item; see
   reservation/detail.html). */
.hub-timeline {
  display: flex;
  flex-direction: column;
  list-style: none;
  margin: 0;
  padding: 0;
}
.hub-timeline-item {
  display: flex;
  gap: var(--space-3);
}
.hub-timeline-rail {
  align-items: center;
  display: flex;
  flex: none;
  flex-direction: column;
  width: 0.625rem;
}
.hub-timeline-dot {
  background: var(--color-border-strong);
  border-radius: 999px;
  flex: none;
  height: 0.625rem;
  margin-top: 0.3rem;
  width: 0.625rem;
}
.hub-timeline-item:first-child .hub-timeline-dot {
  background: var(--color-success);
}
.hub-timeline-connector {
  background: var(--color-border-strong);
  flex: 1 1 auto;
  margin-top: 0.25rem;
  width: 2px;
}
.hub-timeline-content {
  flex: 1;
  margin-bottom: var(--space-4);
  min-width: 0;
}
.hub-timeline-item:last-child .hub-timeline-content {
  margin-bottom: 0;
}
.hub-timeline-label {
  font-size: 0.875rem;
  font-weight: 700;
  margin: 0;
}
.hub-timeline-meta {
  color: var(--color-muted);
  font-size: 0.75rem;
  margin: var(--space-1) 0 0;
}
/* Section tab bar of the Folio and Check-out Review pages (links between sections of the same workflow).
   Reservation Detail has its own tab bar in css/reservation/detail.css. */
.detail-tabs {
  border-bottom: 1px solid var(--color-border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin-bottom: var(--space-5);
}
.detail-tab {
  align-items: center;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--color-muted);
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 700;
  gap: 0.4rem;
  padding: var(--space-3) 0;
  text-decoration: none;
}
.detail-tab svg {
  flex: none;
  height: var(--icon-size-action);
  width: var(--icon-size-action);
}
.detail-tab:hover,
.detail-tab:focus-visible {
  text-decoration: none;
}
.detail-tab:hover {
  color: var(--color-navy);
}
.detail-tab--active {
  border-bottom-color: var(--color-primary);
  color: var(--color-primary);
}
.table-total-row td {
  background: var(--color-surface-muted);
  font-weight: 750;
}
.table-total-row--outstanding td {
  background: var(--color-success-surface);
  color: var(--color-success);
}
@media (max-width: 64rem) {
}
.profile-document-list {
  display: grid;
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}
.profile-document-row {
  align-items: center;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  padding: var(--space-3) 0;
}
.profile-document-row:first-child {
  border-top: 0;
}
.profile-document-label {
  color: var(--color-navy);
  font-size: 0.9375rem;
  font-weight: 600;
}
.passport-document-item {
  align-items: flex-start;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  display: flex;
  gap: var(--space-4);
  padding: var(--space-4);
}
.passport-document-visual {
  align-items: center;
  background: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-muted);
  display: flex;
  flex: none;
  flex-direction: column;
  gap: var(--space-2);
  height: 5.5rem;
  justify-content: center;
  width: 4.25rem;
}
.passport-document-visual svg {
  height: 1.75rem;
  width: 1.75rem;
}
.passport-document-visual-label {
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.passport-document-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.passport-document-title {
  color: var(--color-navy);
  font-size: 0.9375rem;
  font-weight: 700;
  margin: 0;
}
.passport-document-description {
  color: var(--color-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  margin: 0;
}
.passport-document-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.passport-document-actions form {
  display: inline-flex;
}
.room-image-thumb {
  background: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  flex: none;
  height: 5.5rem;
  overflow: hidden;
  width: 5.5rem;
}
.room-image-thumb img {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
}
.passport-document-actions .button {
  gap: var(--space-2);
}
.passport-document-actions .button svg {
  flex: none;
  height: var(--icon-size-action);
  width: var(--icon-size-action);
}
.reservation-secondary-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.reservation-secondary-grid--single {
  grid-template-columns: 1fr;
}
/* Clickable record identifiers (guest code, room number): standard blue link text, underlined on hover and focus.
   Plain text rather than a button, so table rows and summary cards keep their height. */
.record-link {
  color: var(--color-primary);
  text-decoration: none;
}
.record-link:hover,
.record-link:focus-visible {
  text-decoration: underline;
}
.reservation-info-link {
  color: var(--color-primary);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}
.reservation-info-link:hover {
  text-decoration: underline;
}
.reservation-info-link-icon {
  color: var(--color-muted);
  display: inline-flex;
  margin-left: var(--space-1);
}
.reservation-info-link-icon svg {
  height: var(--icon-size-sm);
  width: var(--icon-size-sm);
}
.message-compact {
  margin-top: var(--space-3);
  padding-bottom: var(--space-2);
  padding-top: var(--space-2);
}
.text-muted {
  color: var(--color-muted);
}
fieldset {
  border: 1px solid var(--color-border);
  margin: var(--space-5) 0 0;
  padding: var(--space-4);
}
legend {
  padding: 0 var(--space-2);
}
.room-row {
  align-items: end;
  border-bottom: 1px solid var(--color-border);
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-4);
}
.room-row:last-child {
  border-bottom: 0;
}
.room-row .form-field {
  margin-bottom: 0;
  min-width: 0;
}
.room-row .remove-room {
  justify-self: start;
  white-space: nowrap;
}
.reservation-form-section + .reservation-form-section {
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-5);
  padding-top: var(--space-5);
}
.reservation-form-section > h2 {
  margin-bottom: var(--space-4);
}
.reservation-details-grid,
.room-fields-three-column-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.reservation-details-grid .form-field {
  margin-bottom: 0;
  min-width: 0;
}
.reservation-notes {
  margin-bottom: 0;
  margin-top: var(--space-4);
}
.reservation-notes textarea {
  min-height: 5rem;
}
.reservation-guest-actions {
  align-items: flex-start;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
}
.reservation-guest-actions .inline-link {
  background: none;
  border: none;
  color: var(--color-primary);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.875rem;
  margin-left: auto;
  padding-top: var(--space-3);
  text-decoration: underline;
  white-space: nowrap;
}
.reservation-guest-actions .inline-link:hover {
  color: var(--color-primary-hover);
}
.reservation-rooms-section {
  margin-bottom: 0;
}
.reservation-details-row,
.reservation-rooms-section .room-row {
  grid-template-columns: minmax(0, 1fr) auto;
}
.reservation-details-row {
  align-items: end;
  display: grid;
  gap: var(--space-4);
}
.reservation-details-row__spacer {
  visibility: hidden;
  white-space: nowrap;
}
.room-fields-three-column-grid {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
}
.room-fields-three-column-grid .form-field {
  margin-bottom: 0;
  min-width: 0;
}
.room-currency-field {
  min-width: 0;
}
.room-currency-spacer {
  min-width: 0;
}
.guest-information {
  background: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-4);
  padding: var(--space-3);
}
.reservation-guest-actions .guest-information {
  flex: 0 1 22rem;
  margin-bottom: 0;
}
.guest-information summary {
  align-items: center;
  color: var(--color-navy);
  cursor: pointer;
  display: flex;
  font-size: 0.875rem;
  font-weight: 700;
  justify-content: space-between;
  list-style: none;
}
.guest-information summary::-webkit-details-marker {
  display: none;
}
.guest-information summary::after {
  color: var(--color-muted);
  content: ">";
  font-size: 1rem;
}
.guest-information[open] summary::after {
  content: "⌄";
}
.guest-information__list {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
}
.guest-information__list > div {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: minmax(7rem, 0.75fr) minmax(0, 1.25fr);
}
.guest-information__list dt {
  font-size: 0.8125rem;
}
.guest-information__list dd {
  color: var(--color-text);
  font-size: 0.875rem;
  margin: 0;
  overflow-wrap: anywhere;
}
input,
select,
textarea {
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font: inherit;
  min-height: 2.5rem;
  padding: 0.55rem 0.65rem;
  width: 100%;
}
.js-date-picker:not([type="hidden"]) {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2352606d' stroke-width='1.8'%3E%3Crect x='3.5' y='5.5' width='17' height='15' rx='2'/%3E%3Cpath d='M7.5 3.5v4M16.5 3.5v4M3.5 10h17'/%3E%3C/svg%3E");
  background-position: right var(--space-3) center;
  background-repeat: no-repeat;
  background-size: 1.125rem;
  cursor: pointer;
  padding-right: 2.5rem;
}
textarea {
  min-height: 7rem;
  resize: vertical;
}
/* Native selects: where the browser supports customizable selects, the open menu is anchored below the control with a
   small gap (never over it), overlays the page from the top layer, and flips above only when there is no room below.
   Other browsers keep their built-in menu. Closed-control styling above is unchanged. This block is the ONE definition of
   the open menu for every native select in the PMS (light panel, hover, selected + check mark, disabled): a screen never
   restyles it, and a new select gets it automatically. Palette: the --color-dropdown-* tokens in :root. */
@supports (appearance: base-select) {
  select:not([multiple]):not([size]),
  select:not([multiple]):not([size])::picker(select) {
    appearance: base-select;
  }
  select:not([multiple]):not([size])::picker(select) {
    background: var(--color-dropdown-surface);
    border: 1px solid var(--color-dropdown-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-dropdown);
    color: var(--color-dropdown-text);
    margin-block: var(--dropdown-gap);
    max-block-size: 20rem;
    min-inline-size: anchor-size(width);
    padding: var(--space-1);
    position-area: block-end span-inline-end;
    position-try-fallbacks: flip-block;
  }
  select:not([multiple]):not([size]) option {
    border-radius: var(--radius-sm);
    color: var(--color-dropdown-text);
    padding: var(--space-2) var(--space-3);
  }
  select:not([multiple]):not([size]) option:hover,
  select:not([multiple]):not([size]) option:focus-visible {
    background: var(--color-dropdown-hover);
  }
  /* Selected: keeps its tint while hovered or focused; a keyboard-focused selected option gets a ring so the cursor shows. */
  select:not([multiple]):not([size]) option:checked {
    background: var(--color-dropdown-selected);
    color: var(--color-dropdown-selected-text);
    font-weight: 600;
  }
  select:not([multiple]):not([size]) option:checked:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
  }
  select:not([multiple]):not([size]) option::checkmark,
  select:not([multiple]):not([size]) option:checked::checkmark {
    color: var(--color-dropdown-selected-text);
  }
  /* Disabled: muted text on a subtle surface, and no hover or focus highlight that would suggest it can be chosen. */
  select:not([multiple]):not([size]) option:disabled,
  select:not([multiple]):not([size]) option:disabled:hover,
  select:not([multiple]):not([size]) option:disabled:focus-visible {
    background: var(--color-dropdown-disabled-surface);
    color: var(--color-dropdown-disabled-text);
    cursor: not-allowed;
    font-weight: 400;
  }
  /* Selects that draw their own trailing chevron (Front Desk and Reservation List filters) must not get a second one. */
  select:has(+ [class$="__chevron"])::picker-icon {
    display: none;
  }
}
input:focus,
select:focus,
textarea:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgb(23 105 170 / 15%);
  outline: 0;
}
input:invalid:not(:placeholder-shown),
select:invalid,
textarea:invalid:not(:placeholder-shown) {
  border-color: var(--color-danger);
}
input:disabled,
select:disabled,
textarea:disabled {
  background: var(--color-surface-muted);
  border-color: var(--color-border);
  color: var(--color-muted);
  cursor: not-allowed;
}
/* Number Stepper (static/js/common/number-stepper.js): [ - ] [ editable whole number ] [ + ] for quantity / count fields.
   The input stays the bordered control, so every existing focus / invalid / disabled style still applies to it; the two
   compact buttons sit inside its left and right edges. */
.number-stepper {
  position: relative;
  width: 100%;
}
.number-stepper > .number-stepper__input[data-stepper] {
  padding-inline: 2.5rem;
  text-align: center;
}
.number-stepper__button {
  align-items: center;
  background: transparent;
  border: 0;
  color: var(--color-primary);
  cursor: pointer;
  display: inline-flex;
  height: calc(100% - 2px);
  justify-content: center;
  margin: 0;
  padding: 0;
  position: absolute;
  top: 1px;
  width: 2.25rem;
}
.number-stepper__button--decrease {
  border-radius: calc(var(--radius-sm) - 1px) 0 0 calc(var(--radius-sm) - 1px);
  border-right: 1px solid var(--color-border);
  left: 1px;
}
.number-stepper__button--increase {
  border-left: 1px solid var(--color-border);
  border-radius: 0 calc(var(--radius-sm) - 1px) calc(var(--radius-sm) - 1px) 0;
  right: 1px;
}
.number-stepper__button:hover:not(:disabled) {
  background: var(--color-info-surface);
}
.number-stepper__button:focus-visible {
  background: var(--color-info-surface);
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}
.number-stepper__button:disabled {
  color: var(--color-muted);
  cursor: not-allowed;
  opacity: 0.45;
}
.exchange-rate-inline {
  align-items: center;
  display: flex;
  gap: var(--space-2);
}
.exchange-rate-inline input {
  flex: 1 1 auto;
  min-width: 0;
}
.exchange-rate-inline span {
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
}
.payment-refund-form {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.payment-refund-reason {
  min-height: auto;
  padding: 0.4rem 0.6rem;
  width: 11rem;
}
output {
  color: var(--color-navy);
  display: block;
  font-size: 1.0625rem;
  font-weight: 750;
  min-height: 2.5rem;
  padding: 0.55rem 0;
}

.flatpickr-calendar {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 0.75rem 1.75rem rgb(16 42 67 / 16%);
  color: var(--color-text);
  font-family: inherit;
  overflow: hidden;
  width: 20.75rem;
}
/* An anchored calendar (date-picker.js) never exceeds the viewport, so it can always be positioned inside it on a phone. */
.flatpickr-calendar.date-picker--anchored {
  max-width: calc(100vw - 1rem);
}
.flatpickr-months {
  align-items: center;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  min-height: 3rem;
  padding: 0 var(--space-2);
}
.flatpickr-current-month {
  align-items: center;
  color: var(--color-navy);
  display: flex;
  font-size: 1rem;
  font-weight: 750;
  height: 3rem;
  justify-content: center;
  left: 2.5rem;
  padding: 0;
  top: 0;
  width: calc(100% - 5rem);
}
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year {
  color: var(--color-navy);
  font-size: 1rem;
  font-weight: 750;
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
  appearance: auto;
  background: transparent;
}
/* Month select and Year input share one centered, non-wrapping line with identical box height and typography; the vendor rules
   (inline-block + 6ch wrapper, -1px select margin, differing paddings and line-height) left the Year sitting below the Month. */
.flatpickr-current-month {
  flex-wrap: nowrap;
  gap: 0.625rem;
  line-height: 1;
  white-space: nowrap;
}
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month .numInputWrapper,
.flatpickr-current-month input.cur-year {
  height: 2rem;
  line-height: 2rem;
  margin: 0;
  min-height: 0;
  vertical-align: middle;
}
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year {
  padding: 0 0.25rem;
}
.flatpickr-current-month .numInputWrapper {
  align-items: center;
  display: flex;
  flex: none;
  width: 4.5rem;
}
.flatpickr-current-month input.cur-year {
  text-align: left;
}
.flatpickr-prev-month,
.flatpickr-next-month {
  align-items: center;
  color: var(--color-muted);
  display: flex;
  height: 3rem;
  justify-content: center;
  padding: 0;
  width: 2.5rem;
}
/* The vendor sheet sets a 34px height on the month wrapper (which positions and clips the Month/Year group) and on the arrows,
   with higher specificity than the rules above; all three share the 3rem header row so they are centered on the same line. */
.flatpickr-months .flatpickr-month,
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
  height: 3rem;
  top: 0;
}
.flatpickr-prev-month:hover,
.flatpickr-next-month:hover {
  color: var(--color-primary);
}
.flatpickr-prev-month svg,
.flatpickr-next-month svg {
  fill: currentColor;
}
.flatpickr-rContainer {
  width: 100%;
}
.flatpickr-weekdays {
  background: var(--color-surface-muted);
  padding: 0 var(--space-3);
}
span.flatpickr-weekday {
  background: var(--color-surface-muted);
  color: var(--color-muted);
  font-size: 0.6875rem;
  font-weight: 750;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.flatpickr-days {
  padding: var(--space-2) var(--space-3);
  width: 100%;
}
.flatpickr-days .dayContainer {
  max-width: 100%;
  min-width: 100%;
  width: 100%;
}
.flatpickr-day {
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-weight: 600;
  line-height: 2rem;
  margin: 0.0625rem 0;
  max-width: calc(14.2857143% - 0.125rem);
}
.flatpickr-day:hover,
.flatpickr-day:focus {
  background: #eaf1f8;
  border-color: transparent;
  color: var(--color-primary);
}
.flatpickr-day.today {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
  color: var(--color-border-strong);
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
  color: var(--color-border);
}
.date-picker__footer {
  border-top: 1px solid var(--color-border);
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
  padding: var(--space-2) var(--space-3);
}
.date-picker__clear,
.date-picker__today {
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 750;
  padding: var(--space-1) var(--space-2);
}
.date-picker__clear {
  color: var(--color-muted);
}
.date-picker__clear:hover {
  background: var(--color-surface-muted);
  color: var(--color-text);
}
.date-picker__today {
  color: var(--color-primary);
}
.date-picker__today:hover {
  background: #eaf1f8;
  color: var(--color-primary-hover);
}
.empty-state {
  align-items: center;
  background: var(--color-surface);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  color: var(--color-muted);
  display: flex;
  /* Task33 Batch 1B: column + gap added so the richer emptyState/noResults fragments (icon, message,
     optional action) stack cleanly. A single bare text node -- the ~17 pre-existing plain-paragraph
     usages -- is unaffected, since direction/gap are no-ops with only one flex item. */
  flex-direction: column;
  gap: var(--space-3);
  justify-content: center;
  margin: 0;
  min-height: 9rem;
  padding: var(--space-5);
  text-align: center;
}
.empty-state-icon {
  color: var(--color-border-strong);
}
.empty-state-message {
  margin: 0;
}
.visually-hidden {
  height: 1px;
  margin: -1px;
  overflow: hidden;
  position: absolute;
  width: 1px;
}
/* Task33 Batch 1A: the mobile drawer backdrop stays hidden at every viewport unless the <=48rem media
   query below both shows it and gives it the dimmed, fixed-position treatment; this keeps it inert on
   desktop/tablet even if it were ever rendered open there. */
.sidebar-backdrop {
  display: none;
}
/* The header's mobile nav toggle follows the same base-hide/media-show pattern as the backdrop above,
   and must live in this same file (not components.css, which loads after this one and would otherwise
   win the cascade with an unconditional `display` of its own -- see components.css's comment on
   .header-nav-toggle for the bug this fixes). */
.header-nav-toggle {
  display: none;
}
/* Desktop sidebar collapse (static/js/common/sidebar-collapse.js). The row and its button stay out of the
   layout on the mobile drawer, which uses the header toggle instead; the rules that show them and narrow the
   sidebar are scoped to above the 48rem breakpoint below. */
.sidebar-collapse-row,
.sidebar-collapse-toggle {
  display: none;
}
@media not all and (max-width: 48rem) {
  /* The row is taken out of the sidebar's flex column (position: absolute on the sticky .sidebar), so it reserves
     no height or gap and never moves Dashboard or any menu item. It floats at the right edge, vertically centred. */
  .sidebar-collapse-row {
    display: flex;
    position: absolute;
    right: var(--space-1);
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
  }
  .sidebar-collapse-toggle {
    align-items: center;
    background: transparent;
    border: 0;
    border-radius: var(--radius-sm);
    color: #7f96ad;
    cursor: pointer;
    display: inline-flex;
    justify-content: center;
    padding: var(--space-1);
  }
  .sidebar-collapse-toggle svg {
    height: 1.875rem;
    width: 0.875rem;
  }
  .sidebar-collapse-toggle:hover,
  .sidebar-collapse-toggle:focus-visible {
    background: rgb(255 255 255 / 10%);
    color: #fff;
  }
  .sidebar-collapse-icon {
    display: inline-flex;
  }
  .sidebar-collapse-toggle[aria-expanded="true"] .sidebar-collapse-icon--expand,
  .sidebar-collapse-toggle[aria-expanded="false"] .sidebar-collapse-icon--collapse {
    display: none;
  }
  .app-shell {
    transition: grid-template-columns 0.2s ease-in-out;
  }
  html.sidebar-collapsed .app-shell {
    grid-template-columns: 4.5rem minmax(0, 1fr);
  }
  /* Collapsed rail: headings take zero height, and group separation is the sidebar's own gap (12px) instead of the
     expanded section spacing. Items inside a group keep the expanded .nav-section gap, so the rhythm matches. */
  html.sidebar-collapsed .sidebar {
    gap: var(--space-3);
    padding: var(--space-5) var(--space-2);
  }
  html.sidebar-collapsed .nav-section-label {
    display: none;
  }
  /* Labels stay in the DOM (visually hidden) so each link keeps its accessible name. */
  html.sidebar-collapsed .sidebar-nav-label {
    height: 1px;
    margin: -1px;
    overflow: hidden;
    position: absolute;
    width: 1px;
  }
  html.sidebar-collapsed .sidebar-nav-link {
    justify-content: center;
    padding: var(--space-2) 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .app-shell {
    transition: none;
  }
}

@media (max-width: 64rem) {
  .app-shell {
    grid-template-columns: 13rem minmax(0, 1fr);
  }
  .content {
    padding: var(--space-5);
  }
  .reservation-secondary-grid {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 48rem) {
  /* Task33 Batch 1A: below this breakpoint the sidebar becomes a keyboard-accessible off-canvas drawer
     (toggled by the header's hamburger button, static/js/common/nav-toggle.js) instead of the previous
     always-visible inline nav bar stacked above the content. The header's brand covers the "brand
     visible while the drawer is closed" need (the sidebar's own brand block was later removed as a
     duplicate — see layout/sidebar.html). */
  .app-shell {
    display: block;
  }
  /* align-self: stretch: the base align-self: start also applies to a fixed box and made the drawer shrink to its content (taller than the screen when
     the menu is long, with no way to scroll to its last items); top + bottom now give it the full visible height. */
  .sidebar {
    align-self: stretch;
    background: var(--color-navy-strong);
    bottom: 0;
    height: auto;
    left: 0;
    overflow-y: auto;
    padding: var(--space-5) var(--space-4);
    position: fixed;
    top: var(--header-height);
    transform: translateX(-100%);
    transition: transform 0.2s ease-in-out;
    width: min(85vw, 18rem);
  }
  .sidebar[data-open="true"] {
    transform: translateX(0);
  }
  .sidebar-backdrop[data-open="true"] {
    background: rgb(16 42 67 / 45%);
    bottom: 0;
    display: block;
    left: 0;
    position: fixed;
    right: 0;
    top: var(--header-height);
    z-index: var(--z-overlay);
  }
  .header-nav-toggle {
    display: inline-flex;
  }
  .content {
    padding: var(--space-4);
  }
  .detail-list {
    grid-template-columns: 1fr;
  }
  .detail-list dt {
    border-bottom: 0;
    padding-bottom: var(--space-1);
  }
  .detail-list dd {
    padding-top: var(--space-1);
  }
  .detail-list > :nth-last-child(-n + 2) {
    border-bottom: 1px solid var(--color-border);
  }
  .detail-list > :last-child {
    border-bottom: 0;
  }
  .dashboard-chart-grid {
    grid-template-columns: 1fr;
  }
  .room-row {
    grid-template-columns: 1fr;
  }
  .reservation-details-grid {
    grid-template-columns: 1fr;
  }
  .reservation-details-grid .form-field {
    margin-bottom: var(--space-4);
  }
  .reservation-details-grid .form-field:last-child {
    margin-bottom: 0;
  }
  .reservation-guest-actions {
    flex-direction: column;
    gap: var(--space-2);
  }
  .reservation-guest-actions .guest-information {
    width: 100%;
  }
  .reservation-guest-actions .inline-link {
    margin-left: 0;
    padding-top: 0;
  }
  .reservation-rooms-section .room-row,
  .room-fields-three-column-grid,
  .reservation-details-row {
    grid-template-columns: 1fr;
  }
  .room-currency-spacer {
    display: none;
  }
  .reservation-details-row__spacer {
    display: none;
  }
  .reservation-filter-grid {
    grid-template-columns: 1fr;
  }
  .results-toolbar {
    align-items: flex-start;
    flex-direction: column;
  }
  .passport-document-item {
    flex-wrap: wrap;
  }
}

.housekeeping-summary a {
  color: inherit;
  display: block;
  text-decoration: none;
}
.housekeeping-group {
  margin-top: var(--space-5);
}
.housekeeping-urgent {
  background: var(--color-danger-surface);
  color: var(--color-danger);
  font-weight: 750;
}
.housekeeping-row-urgent td:first-child {
  box-shadow: inset 4px 0 0 var(--color-danger);
}
.housekeeping-inline-form {
  display: inline;
}

.readiness-issues {
  display: grid;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
.readiness-issues strong {
  margin-right: var(--space-2);
}
.readiness-issue--blocker strong {
  color: var(--color-danger);
}
.readiness-issue--warning strong {
  color: var(--color-warning);
}
.readiness-issue--info strong {
  color: var(--color-muted);
}

.front-desk-secondary {
  color: var(--color-muted);
  display: block;
  font-size: 0.8125rem;
}

.accompanying-guests__add {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.accompanying-guests__list {
  display: grid;
  gap: var(--space-2);
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
}
.accompanying-guests__list li {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Semantic summary icon (the Review Check-in fact icon, made shared): one soft pastel circle per business concept, the
   icon in a darker shade of the same hue. Size and glyph size are identical for every concept, so a summary strip reads
   as one family; the concept alone picks the colour. Use with a concept modifier. */
.semantic-icon {
  align-items: center;
  border-radius: 999px;
  display: inline-flex;
  flex: none;
  height: 2.25rem;
  justify-content: center;
  width: 2.25rem;
}
.semantic-icon svg {
  height: 1.125rem;
  width: 1.125rem;
}
.semantic-icon--guest,
.semantic-icon--nights {
  background: var(--color-purple-surface);
  color: var(--color-purple);
}
.semantic-icon--room {
  background: var(--color-indigo-surface);
  color: var(--color-indigo);
}
.semantic-icon--source {
  background: var(--color-success-surface);
  color: var(--color-success);
}
.semantic-icon--checkin {
  background: var(--color-info-surface);
  color: var(--color-info);
}
.semantic-icon--checkout {
  background: var(--color-checkout-surface);
  color: var(--color-date-check-out);
}
.semantic-icon--guests {
  background: var(--color-warning-surface);
  color: var(--color-warning);
}

/* PMS date convention: check-in value subtle green (the green of the CHECKED IN / success status), check-out value (and any overdue
   text) light red. --color-date-check-in stays the shared soft blue, which other non-date notes reuse. */
.label-value-rows dd.date-value--check-in,
.stay-extension-table td.date-value--check-in,
.folio-facts dd.date-value--check-in,
.cor-facts dd.date-value--check-in,
.walk-in-summary-table td.date-value--check-in,
.rd-summary__value.date-value--check-in,
.rc-summary__stay .date-value--check-in {
  color: var(--color-success);
}

.label-value-rows dd.date-value--check-out,
.stay-extension-table td.date-value--check-out,
.stay-extension-summary__range .date-value--check-out,
.folio-facts dd.date-value--check-out,
.cor-facts dd.date-value--check-out,
.walk-in-summary-table td.date-value--check-out,
.rd-summary__value.date-value--check-out,
.rc-summary__stay .date-value--check-out {
  color: var(--color-date-check-out);
}

/* Summary bar: the overdue text sits on its own compact line under the check-out date, slightly smaller. */
.folio-facts .reservation-overdue--below,
.label-value-rows .reservation-overdue--below {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.2;
}

/* Tablet (the inline 13rem sidebar, 769px - 1024px): "Doanh thu bổ sung" must stay on one line without a smaller font or an ellipsis, so the labels
   never wrap and the sidebar and link side padding shrink from 12px to 8px (16px more room for the label; the icon, its gap and the sidebar width
   are unchanged). The group headings keep the same inset as the labels. The collapsed rail has its own, higher-specificity padding. */
@media (min-width: 48.0625rem) and (max-width: 64rem) {
  .sidebar {
    padding-inline: var(--space-2);
  }
  .sidebar-nav-link {
    padding-inline: var(--space-2);
  }
  .sidebar-nav-label {
    white-space: nowrap;
  }
  .nav-section-label {
    margin-inline: var(--space-2);
  }
}

