/* ==========================================================================
   app.css — design tokens and components for the res application.

   Dark is the default surface and lives on :root, so it applies with no
   JavaScript and no flash of the wrong theme. Light is the opt-in, selected
   with the toggle in the navigation and remembered per browser.

   Nothing below the token block hardcodes a colour. Changing the palette
   should be an edit to :root and to [data-theme="light"], and nowhere else.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  color-scheme: dark;

  /* Surfaces, from furthest back to nearest front. */
  --bg:            #0c1116;
  --surface:       #141b22;
  --surface-2:     #1b232c;
  --surface-3:     #232d38;

  /* Lines. --border is for structure, --rule for hairlines inside a panel. */
  --border:        #262f3a;
  --border-strong: #364354;
  --rule:          #1f2731;
  /* Chart gridlines. Deliberately stronger than --rule: a gridline has to be
     readable across a wide plot, where a hairline disappears. */
  --grid:          #33404e;

  /* Text, from most to least prominent. */
  --text:          #e7edf3;
  --text-muted:    #9aa6b2;
  --text-faint:    #6f7c89;
  --text-invert:   #0c1116;

  /* Brand. A deep ocean teal rather than the default dashboard blue —
     Canareef is a Maldives resort, and it keeps the accent distinguishable
     from the semantic blue used for information. */
  --accent:        #35a4ae;
  --accent-hover:  #4dbcc6;
  --accent-soft:   #10333a;
  --accent-text:   #6fd0d9;

  /* Semantics. Deliberately not pure red/green: these sit next to figures
     all day and saturated hues are tiring. */
  --positive:      #3fbc8a;
  --positive-soft: #10312a;
  --negative:      #e2685c;
  --negative-soft: #3a1a1a;
  /* Negative figures in dense tables: a clearer red than --negative, which
     reads as coral at table size on this ground. */
  --negative-figure: #ff5c52;
  --warn:          #d3a04a;
  --warn-soft:     #33270f;
  --info:          #6ba3e8;
  --info-soft:     #14243b;

  /* Chart series: the Highcharts default palette, so charts here match the
     combinations used in the official Highcharts samples. */
  --series-1:      #2caffe;
  --series-2:      #544fc5;
  --series-3:      #00e272;
  --series-4:      #fe6a35;

  /* Report measures. One colour per measure, shared by table column bands and
     chart series so a colour means the same thing everywhere on a page. The
     values are the Highcharts brand palette, which brand-dark and brand-light
     share, so both themes use them unchanged. */
  --m-pickup:      #87B4E7;
  --m-cy:          #A3EDBA;
  --m-pybob:       #F19E53;
  --m-pyfull:      #8087E8;

  /* Precomputed mixes. Never color-mix() in this file: html2canvas, which the
     Screenshot and Download PDF buttons use, cannot parse the color() value it
     computes to and throws. Values = color-mix(in srgb, ...) of the tokens above. */
  --m-pickup-tint: #2a3746;   /* pickup 14% into --surface-2 */
  --m-cy-tint:     #2e3f40;   /* cy 14% into --surface-2 */
  --m-pybob-tint:  #393431;   /* pybob 14% into --surface-2 */
  --m-pyfull-tint: #293146;   /* pyfull 14% into --surface-2 */
  --surface-zebra:  #171f27;   /* --surface-2 45% into --surface */
  --warn-line:      rgba(211, 160, 74, 0.4);

  --shadow-sm:  0 1px 2px rgba(0, 0, 0, .4);
  --shadow:     0 1px 3px rgba(0, 0, 0, .5), 0 4px 12px rgba(0, 0, 0, .35);
  --shadow-lg:  0 8px 32px rgba(0, 0, 0, .55);

  --radius-sm: 6px;
  --radius:    10px;
  --radius-lg: 14px;

  /* A 4px spacing scale. */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px;

  /* Type scale. */
  --font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-num: "Inter", ui-sans-serif, system-ui, sans-serif;
  /* Figures in dense report tables, where Inter reads thin (loaded per page). */
  --font-figures: "Roboto", "Inter", ui-sans-serif, system-ui, sans-serif;
  --fs-xs: 11px; --fs-sm: 12px; --fs-base: 13px;
  --fs-md: 15px; --fs-lg: 18px; --fs-xl: 22px; --fs-2xl: 28px;

  --nav-h: 52px;
}

[data-theme="light"] {
  color-scheme: light;

  --bg:            #f4f6f8;
  --surface:       #ffffff;
  --surface-2:     #eef1f5;
  --surface-3:     #e4e9ef;

  --border:        #dde3ea;
  --border-strong: #c3ccd7;
  --rule:          #eaeef3;
  --grid:          #ccd4dd;

  --text:          #10161d;
  --text-muted:    #5a6672;
  --text-faint:    #8b95a1;
  --text-invert:   #ffffff;

  --accent:        #0d7680;
  --accent-hover:  #0a5d66;
  --accent-soft:   #e2f1f3;
  --accent-text:   #0a5d66;

  --positive:      #10714d;
  --positive-soft: #e2f2ea;
  --negative:      #a72b21;
  --negative-soft: #fbe9e7;
  --negative-figure: #b3261e;
  --warn:          #8a5a00;
  --warn-soft:     #fdf1dc;
  --info:          #1a5fb4;
  --info-soft:     #e6eefb;

  /* The Highcharts palette again, darkened just enough to keep 4.5:1 against
     a white ground where these colours are used as text. */
  --series-1:      #1a8fd0;
  --series-2:      #544fc5;
  --series-3:      #00994f;
  --series-4:      #d2521a;

  /* Precomputed mixes. Never color-mix() in this file: html2canvas, which the
     Screenshot and Download PDF buttons use, cannot parse the color() value it
     computes to and throws. Values = color-mix(in srgb, ...) of the tokens above. */
  --m-pickup-tint: #e0e8f3;   /* pickup 14% into --surface-2 */
  --m-cy-tint:     #e4f0ed;   /* cy 14% into --surface-2 */
  --m-pybob-tint:  #eee5de;   /* pybob 14% into --surface-2 */
  --m-pyfull-tint: #dfe2f3;   /* pyfull 14% into --surface-2 */
  --surface-zebra:  #f7f9fb;   /* --surface-2 45% into --surface */
  --warn-line:      rgba(138, 90, 0, 0.4);

  --shadow-sm:  0 1px 2px rgba(16, 22, 29, .06);
  --shadow:     0 1px 3px rgba(16, 22, 29, .08), 0 4px 12px rgba(16, 22, 29, .05);
  --shadow-lg:  0 8px 32px rgba(16, 22, 29, .14);
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

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

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.01em; }
p { margin: 0; }
a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }
img, svg { max-width: 100%; }

/* Every figure in this application is a number in a column next to other
   numbers, so tabular figures are the default rather than an opt-in. */
.num, td.num, th.num, .kpi-value, .data-table td, .data-table th {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 6px;
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }

/* --------------------------------------------------------------------------
   3. Application shell

   The shell is a full-height column: a fixed-height navigation bar and a main
   region that takes the rest. Pages that want to fit one screen set
   .app-main--fixed and manage their own internal scrolling; everything else
   scrolls normally.
   -------------------------------------------------------------------------- */

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

/* Pages that must fit one screen opt in with .app--fixed on the shell.
   The height comes from the flex column rather than calc(100vh - nav),
   so it stays correct whatever the navigation actually measures. */
.app--fixed { height: 100vh; overflow: hidden; }

.app-main {
  flex: 1;
  min-height: 0;
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
  width: 100%;
  max-width: 1720px;
  margin: 0 auto;
}

.app-main--fixed {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* Below this width there is no honest way to fit a dashboard on one screen,
   so stop pretending and let the page scroll. */
@media (max-width: 1100px), (max-height: 620px) {
  .app--fixed { height: auto; overflow: visible; }
  .app-main--fixed { flex: none; overflow: visible; }
}

/* --------------------------------------------------------------------------
   4. Navigation
   -------------------------------------------------------------------------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--nav-h);
  flex: 0 0 var(--nav-h);
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 0 var(--sp-5);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 650;
  font-size: var(--fs-md);
  color: var(--text);
  letter-spacing: -.02em;
  white-space: nowrap;
}
.nav-brand:hover { text-decoration: none; }
.nav-brand .bi { color: var(--accent); font-size: 18px; }

.nav-menu {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  flex: 1;
  min-width: 0;
}

.nav-group { position: relative; }

.nav-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 var(--sp-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.nav-trigger:hover { background: var(--surface-2); color: var(--text); }
.nav-trigger .chev { font-size: 10px; opacity: .6; transition: transform .15s; }

.nav-group[data-open="true"] .nav-trigger { background: var(--surface-2); color: var(--text); }
.nav-group[data-open="true"] .chev { transform: rotate(180deg); }

/* The active group is marked by the page, not by JavaScript reading the URL. */
.nav-trigger[aria-current="true"] {
  color: var(--accent-text);
  background: var(--accent-soft);
}

.nav-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 230px;
  padding: var(--sp-1);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .13s, transform .13s, visibility .13s;
}
.nav-group[data-open="true"] .nav-panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 7px var(--sp-3);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-weight: 500;
  white-space: nowrap;
}
.nav-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav-item .bi { width: 16px; font-size: 14px; color: var(--text-faint); }
.nav-item:hover .bi { color: var(--accent); }
.nav-item[aria-current="page"] { background: var(--accent-soft); color: var(--accent-text); }
.nav-item[aria-current="page"] .bi { color: var(--accent); }

.nav-right { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }

.nav-user {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 var(--sp-2) 0 var(--sp-3);
  color: var(--text-muted);
  font-weight: 500;
  border-left: 1px solid var(--border);
  height: 22px;
}

.nav-avatar {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-text);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); border-color: var(--border-strong); }

.nav-toggle { display: none; }

/* Mobile: the menu becomes a sheet below the bar. */
@media (max-width: 1100px) {
  .nav-toggle { display: grid; }
  .nav-menu {
    position: absolute;
    top: var(--nav-h);
    left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--sp-2);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow);
    max-height: calc(100vh - var(--nav-h));
    overflow-y: auto;
  }
  .nav-menu[hidden] { display: none; }
  .nav-trigger { width: 100%; justify-content: space-between; height: 40px; }
  .nav-panel {
    position: static;
    opacity: 1; visibility: visible; transform: none;
    border: none; box-shadow: none;
    padding: 0 0 var(--sp-2) var(--sp-5);
    min-width: 0;
    display: none;
  }
  .nav-group[data-open="true"] .nav-panel { display: block; }
  .nav-user span { display: none; }
}

/* --------------------------------------------------------------------------
   5. Page header
   -------------------------------------------------------------------------- */

.page-head {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
  flex: 0 0 auto;
}

.page-title { font-size: var(--fs-xl); font-weight: 650; letter-spacing: -.02em; }
.page-sub { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 1px; }

.toolbar { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; flex-wrap: wrap; }

.field { display: inline-flex; align-items: center; gap: var(--sp-2); }
.field-label { color: var(--text-faint); font-size: var(--fs-sm); font-weight: 500; }
.field[hidden] { display: none; }

/* --------------------------------------------------------------------------
   6. Controls
   -------------------------------------------------------------------------- */

select, input[type="date"], input[type="text"], input[type="number"], input[type="search"],
input[type="password"] {
  height: 32px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 500;
  transition: border-color .12s, box-shadow .12s;
}
select:hover, input:hover { border-color: var(--border-strong); }
select:focus, input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
select {
  appearance: none;
  padding-right: 28px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) 14px, calc(100% - 10px) 14px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 550;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, border-color .12s, color .12s;
}
.btn:hover { background: var(--surface-2); border-color: var(--border-strong); text-decoration: none; }
.btn:active { background: var(--surface-3); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-invert);
}
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--text-invert); }

.btn--danger { color: var(--negative); border-color: var(--border); }
.btn--danger:hover { background: var(--negative-soft); border-color: var(--negative); }

.btn--sm { height: 28px; padding: 0 10px; font-size: var(--fs-sm); }

/* --------------------------------------------------------------------------
   7. Panels
   -------------------------------------------------------------------------- */

.panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--rule);
  flex: 0 0 auto;
}

.panel-title {
  font-size: var(--fs-md);
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.panel-title .bi { color: var(--accent); font-size: 15px; }

.panel-actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }

.panel-body { padding: var(--sp-4); flex: 1; min-height: 0; }
.panel-body--flush { padding: 0; }
.panel-body--scroll { overflow: auto; }

/* --------------------------------------------------------------------------
   8. KPI tiles
   -------------------------------------------------------------------------- */

.kpi-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-3);
  flex: 0 0 auto;
}
@media (max-width: 900px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }
.kpi-row[hidden] { display: none; }   /* display:grid above would beat the UA rule */

.kpi {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

/* A thin accent edge rather than a coloured card: at four tiles wide, full
   colour blocks compete with the charts below them. */
.kpi::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--kpi-accent, var(--accent));
}

.kpi-main { min-width: 0; flex: 1; }

.kpi-label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.kpi-label .bi { color: var(--kpi-accent, var(--accent)); font-size: 12px; }

.kpi-value {
  font-size: var(--fs-2xl);
  font-weight: 660;
  letter-spacing: -.025em;
  line-height: 1.15;
  margin-top: 2px;
}

/* The cards keep four across down to 900px, where a figure like
   $740,990.88 no longer fits the full size. */
@media (max-width: 1100px) { .kpi-value { font-size: var(--fs-xl); } }

.kpi-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0 6px; margin-top: 2px; font-size: var(--fs-sm); }
.kpi-foot .muted { color: var(--text-faint); }

.kpi-spark { width: 92px; height: 40px; flex: 0 0 auto; }
@media (max-width: 1280px) { .kpi-spark { display: none; } }

.delta { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }   /* arrow and figure stay together */
.delta--up { color: var(--positive); }
.delta--down { color: var(--negative); }
.delta--flat { color: var(--text-faint); }

/* --------------------------------------------------------------------------
   9. Dashboard grid

   Two columns: the charts carry the screen, the rail holds the gauges and the
   at-a-glance figures. Both scroll internally rather than growing the page.
   -------------------------------------------------------------------------- */

.dash-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--sp-3);
  flex: 1;
  min-height: 0;
}
@media (max-width: 1400px) { .dash-grid { grid-template-columns: minmax(0, 1fr) 280px; } }
@media (max-width: 1100px) { .dash-grid { grid-template-columns: minmax(0, 1fr); } }

.dash-rail {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  min-height: 0;
  overflow-y: auto;
}

/* --------------------------------------------------------------------------
   10. Tabs
   -------------------------------------------------------------------------- */

.tabs {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}

.tab {
  padding: 5px var(--sp-3);
  border: none;
  border-radius: 5px;
  background: none;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.tab:hover { color: var(--text); }
.tab[aria-selected="true"] {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

.tab-panel { display: flex; flex-direction: column; min-height: 0; height: 100%; }
.tab-panel[hidden] { display: none; }

/* --------------------------------------------------------------------------
   11. Charts and gauges
   -------------------------------------------------------------------------- */

.chart { width: 100%; flex: 1; min-height: 0; }

.gauge-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
.gauge { height: 132px; }
.gauge-caption {
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-top: -6px;
}

/* --------------------------------------------------------------------------
   12. Statistic list — the compact form of the old summary panels
   -------------------------------------------------------------------------- */

.stat-list { display: flex; flex-direction: column; }

.stat-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 7px 0;
  border-bottom: 1px solid var(--rule);
}
.stat-row:last-child { border-bottom: none; }
.stat-row dt { color: var(--text-muted); font-size: var(--fs-sm); }
.stat-row dd { margin: 0; font-weight: 650; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   13. Data tables
   -------------------------------------------------------------------------- */

.table-wrap { overflow: auto; max-width: 100%; }

.data-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-sm); }

.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .04em;
  text-align: right;
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.data-table thead th:first-child { text-align: left; }

.data-table td {
  padding: 7px var(--sp-3);
  border-bottom: 1px solid var(--rule);
  text-align: right;
  white-space: nowrap;
}
.data-table td:first-child { text-align: left; font-weight: 550; }
.data-table tbody tr:hover td { background: var(--surface-2); }
.data-table tbody tr:last-child td { border-bottom: none; }

.data-table tfoot td,
.data-table tr.is-total td {
  font-weight: 700;
  background: var(--surface-2);
  border-top: 1px solid var(--border-strong);
}

/* --------------------------------------------------------------------------
   14. Modal
   -------------------------------------------------------------------------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(9, 13, 17, .55);
  backdrop-filter: blur(2px);
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 201;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5);
}
.modal[hidden], .modal-overlay[hidden] { display: none; }

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

.modal-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--rule);
}
.modal-body { padding: var(--sp-4) var(--sp-5) var(--sp-5); overflow: auto; }

.summary-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.summary-cell {
  padding: var(--sp-3);
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}
.summary-cell .label {
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.summary-cell .value { font-size: var(--fs-lg); font-weight: 650; margin-top: 2px; }

/* --------------------------------------------------------------------------
   15. States
   -------------------------------------------------------------------------- */

.state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-10) var(--sp-5);
  color: var(--text-muted);
  text-align: center;
}
.state[hidden] { display: none; }
.state .bi { font-size: 26px; color: var(--text-faint); }

.spinner {
  width: 22px; height: 22px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 20px;
  font-size: var(--fs-xs);
  font-weight: 650;
}
.badge--info { background: var(--info-soft); color: var(--info); }
.badge--warn { background: var(--warn-soft); color: var(--warn); }
.badge--ok   { background: var(--positive-soft); color: var(--positive); }

.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ==========================================================================
   16. Legacy utility compatibility

   The dashboard's 1,500-line inline script toggles and writes Tailwind
   utility class names as behavioural state — classList.toggle('hidden'),
   className = 'bg-gradient-to-r from-blue-600 …', and generated table rows
   carrying class="px-4 py-2 text-right text-gray-300".

   Dropping the Tailwind CDN therefore removes classes the script depends on.
   Rewriting those 20-odd call sites is a logic change, and mixing a logic
   change into a restyle is precisely how a redesign turns into a debugging
   session — so the classes are redefined here in terms of our own tokens
   instead. Everything in this section is a bridge, not a pattern to copy:
   it disappears when the dashboard script is refactored to data- attributes.
   ========================================================================== */

/* Display state. .hidden must win over any component display rule, because
   the script uses it as the single show/hide mechanism. */
.hidden { display: none !important; }
.flex { display: flex; }

/* Semantic colours the script picks between at runtime. */
.text-green-400 { color: var(--positive); }
.text-red-400   { color: var(--negative); }
.text-blue-400  { color: var(--accent); }
.text-gray-100, .text-gray-200 { color: var(--text); }
.text-gray-300  { color: var(--text-muted); }
.text-gray-400  { color: var(--text-faint); }
.text-white     { color: var(--text-invert); }

/* The chart toggle buttons. The script swaps the whole className between an
   "active" gradient string and an "inactive" grey one; these two rules give
   both states the right appearance without the script knowing. */
[id$="Btn"].bg-gradient-to-r,
.bg-gradient-to-r.from-blue-600,
.bg-gradient-to-r.from-green-600 {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--text-invert);
  box-shadow: none;
}
.bg-gradient-to-r.from-green-600 { background: var(--positive); border-color: var(--positive); }

.bg-gray-700\/60 {
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

/* Shared sizing for those buttons, whichever state they are in. */
.from-blue-600, .from-green-600, .bg-gray-700\/60 {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 10px !important;
  border-radius: var(--radius-sm) !important;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background .12s, color .12s;
  transform: none !important;
}

/* Type utilities the script writes into generated markup. */
.text-xs { font-size: var(--fs-xs); }
.text-sm { font-size: var(--fs-sm); }
.text-lg { font-size: var(--fs-lg); }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.uppercase { text-transform: uppercase; }
.tracking-wider { letter-spacing: .04em; }
.items-center { align-items: center; }
.justify-end { justify-content: flex-end; }
.gap-1 { gap: var(--sp-1); }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }
.text-right { text-align: right; }
.text-left { text-align: left; }
.min-w-full { min-width: 100%; }
.overflow-x-auto { overflow-x: auto; }
.animate-spin { animation: spin .7s linear infinite; }
.opacity-50 { opacity: .5; }
.opacity-60 { opacity: .6; }
.cursor-not-allowed { cursor: not-allowed; }

/* Tables the script regenerates: styled by structure so the utility classes
   in the generated rows do not need to carry the design. */
#yearlyComparisonTableContainer table,
.modal table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
#yearlyComparisonTableContainer thead th,
.modal thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .04em;
  text-align: right;
  padding: var(--sp-2) var(--sp-3) !important;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
#yearlyComparisonTableContainer thead th:first-child,
.modal thead th:first-child { text-align: left; }

#yearlyComparisonTableContainer tbody td,
.modal tbody td {
  padding: 7px var(--sp-3) !important;
  border-bottom: 1px solid var(--rule);
  text-align: right;
  white-space: nowrap;
}
#yearlyComparisonTableContainer tbody td:first-child,
.modal tbody td:first-child { text-align: left; font-weight: 550; }
#yearlyComparisonTableContainer tbody tr:hover td,
.modal tbody tr:hover td { background: var(--surface-2); }

/* The year figures in the comparison table open the breakdown modal. */
.breakdown-trigger {
  width: 100%;
  padding: 2px 4px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font: inherit;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.breakdown-trigger:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-text);
}

/* Elements the script decorates but which we lay out ourselves. */
.divide-y > * + * { border-top: 1px solid var(--rule); }
.border-b-2 { border-bottom-width: 2px; }

/* The breakdown modal's two tabs: the script swaps bg-blue-600/bg-gray-800
   and text-white/text-gray-300 to mark the selection. */
.bg-blue-600 { background: var(--accent) !important; border-color: var(--accent) !important; }
.bg-gray-800 { background: var(--surface-2) !important; border-color: var(--border) !important; }

/* showNotification() builds a toast out of utility classes and slides it in by
   removing .translate-x-full. */
.fixed { position: fixed; }
.top-4 { top: var(--sp-4); }
.right-4 { right: var(--sp-4); }
.z-50 { z-index: 300; }
.p-4 { padding: var(--sp-3) var(--sp-4); }
.rounded-lg { border-radius: var(--radius); }
.shadow-lg { box-shadow: var(--shadow-lg); }
.transition-all { transition: all .3s ease; }
.duration-300 { transition-duration: .3s; }
.transform { transform: translateZ(0); }
.translate-x-full { transform: translateX(calc(100% + var(--sp-5))); }
.bg-blue-600.fixed, .bg-green-600.fixed, .bg-red-600.fixed {
  color: var(--text-invert);
  font-weight: 550;
  border: 1px solid transparent;
}
.bg-green-600 { background: var(--positive) !important; }
.bg-red-600 { background: var(--negative) !important; }

/* Toolbar row inside a panel body, above a chart. */
.panel-toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--rule);
  flex: 0 0 auto;
  flex-wrap: wrap;
}
.panel-toolbar .spacer { margin-left: auto; }

/* ==========================================================================
   17. Report pages

   Appended after the legacy layer on purpose: several containers on migrated
   pages keep utility classes such as "flex gap-2" because page scripts select
   them, and these rules must win over those same-specificity utilities.
   ========================================================================== */

/* Normal (scrolling) pages space their sections; fixed pages use flex gap. */
.app-main:not(.app-main--fixed) > * + * { margin-top: var(--sp-4); }

.kpi-sub { margin-top: 4px; color: var(--text-faint); font-size: var(--fs-xs); }

/* Colour key for measures. */
.measure-key {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 500;
}
.measure-key li { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.measure-key li::before {
  content: "";
  width: 10px; height: 10px;
  border-radius: 2px;
  background: var(--m);
}

.search-field { position: relative; display: inline-flex; align-items: center; }
.search-field .bi { position: absolute; left: 10px; color: var(--text-faint); pointer-events: none; font-size: 12px; }
.search-field input { width: 200px; padding-left: 30px; }

/* Segmented control. The page script marks the selection with .active. */
.seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}
.seg-btn {
  padding: 4px 10px;
  border: none;
  border-radius: 5px;
  background: none;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background .12s, color .12s;
}
.seg-btn:hover { color: var(--text); }
.seg-btn.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

/* Two charts side by side; one column only when the window is too narrow for
   two plots to be legible. */
.chart-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
@media (max-width: 1100px) { .chart-pair { grid-template-columns: minmax(0, 1fr); } }
.chart-body { height: 400px; padding: var(--sp-2) var(--sp-3) var(--sp-3); }
.chart-body .chart { height: 100%; }

/* --------------------------------------------------------------------------
   Pickup table: 21 numeric columns in four measure groups.

   What makes it readable rather than what makes it pretty:
   - a coloured band per group, matching the chart series, instead of a border
     around every one of the 400 cells
   - a single rule where each group starts, so the eye finds a group at once
   - tabular figures, right-aligned, so magnitudes line up down a column
   - the month column pinned while the figures scroll sideways
   - negative pickup in the negative colour, so a cancellation reads as one
   -------------------------------------------------------------------------- */
.pickup-wrap { border-top: 1px solid var(--rule); }

.pickup-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.pickup-table th,
.pickup-table td {
  padding: 7px 10px;
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}

.pickup-table thead th {
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .03em;
}
.pickup-table .col-row th { text-transform: uppercase; padding-top: 5px; padding-bottom: 6px; border-bottom-color: var(--border); }

.pickup-table .grp {
  text-align: center;
  color: var(--text);
  font-weight: 650;
  border-top: 3px solid var(--m);
  background: var(--m-tint, var(--surface-2));
}

.pickup-table .g-start { border-left: 1px solid var(--border-strong); }

.pickup-table .col-month {
  position: sticky;
  left: 0;
  z-index: 1;
  text-align: left;
  font-weight: 600;
  background: var(--surface);
  box-shadow: inset -1px 0 0 var(--border);
}
.pickup-table thead .col-month { z-index: 3; background: var(--surface-2); vertical-align: bottom; }
.pickup-table thead .col-inv { vertical-align: bottom; }
.pickup-table .col-inv { color: var(--text-muted); }

.pickup-table tbody tr:nth-child(even) td { background: var(--surface-zebra); }
.pickup-table tbody tr:hover td { background: var(--surface-2); }
.pickup-table tbody tr.highlight-row td { background: var(--accent-soft); }

.pickup-table .neg { color: var(--negative); }

/* The Daily Pick-Up forecast table: figures in Roboto at a medium weight, and
   negative pickup in a red that stands out on the dark ground as clearly as
   the light theme's red does on white. The page loads Roboto itself. */
.pickup-table--figures { font-family: var(--font-figures); font-size: var(--fs-base); }
.pickup-table--figures td { font-weight: 500; }
.pickup-table--figures .col-month { font-weight: 600; }
.pickup-table--figures .neg { color: var(--negative-figure); font-weight: 600; }
.pickup-table--figures tfoot td { font-weight: 700; }

.pickup-table tfoot td {
  font-weight: 700;
  color: var(--text);
  background: var(--surface-2);
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}
.pickup-table tfoot .col-month { background: var(--surface-2); }

@media print {
  .nav, .toolbar, .search-field, .seg, .measure-key { display: none !important; }
  .app-main { max-width: none; padding: 0; }
  .panel { box-shadow: none; }
  .pickup-wrap { overflow: visible; }
}

/* Inline notice, for a state the reader would otherwise mistake for a fault. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  line-height: 1.5;
}
.notice[hidden] { display: none; }   /* display:flex above would beat the UA rule */
.notice .bi { margin-top: 2px; }
.notice--warn {
  background: var(--warn-soft);
  border-color: var(--warn-line);
  color: var(--text);
}
.notice--warn .bi { color: var(--warn); }

/* Measure groups in report tables: the band colour and its precomputed tint. */
.grp--pickup { --m: var(--m-pickup); --m-tint: var(--m-pickup-tint); }
.grp--cy     { --m: var(--m-cy);     --m-tint: var(--m-cy-tint); }
.grp--pybob  { --m: var(--m-pybob);  --m-tint: var(--m-pybob-tint); }
.grp--pyfull { --m: var(--m-pyfull); --m-tint: var(--m-pyfull-tint); }

/* ==========================================================================
   18. List pages (Entered, Canceled)

   The page scripts on these pages create table rows themselves after an add,
   using Tailwind class strings, so every rule here styles by structure —
   column position, last row, last cell — and applies identically to rows the
   server rendered and rows the script inserted.
   ========================================================================== */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
}
.filter-field { display: flex; flex-direction: column; gap: 4px; }
.filter-field > span { color: var(--text-muted); font-size: var(--fs-xs); font-weight: 600; }

.chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
.chip {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 11px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: 550;
  white-space: nowrap;
}
.chip:hover { color: var(--text); border-color: var(--border-strong); text-decoration: none; }
.chip[aria-current="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); }

/* The list panel must not clip: its header row sticks under the navigation
   as the page scrolls, and a sticky element stops at any ancestor that has
   overflow set. Horizontal scrolling returns only where the table cannot fit. */
.panel--list { overflow: visible; }
.panel--list .panel-head { flex-wrap: wrap; }
.list-wrap { overflow: visible; }
@media (max-width: 1100px) {
  .list-wrap { overflow-x: auto; }
  /* Once the wrapper scrolls sideways it also becomes the sticky container,
     so top: var(--nav-h) would push the header 52px down inside it, over the
     first rows. Where the table scrolls sideways, the header scrolls too.
     Two classes deep on purpose: the base .list-table th rule comes later in
     this file, and at equal specificity it would win. */
  .list-wrap .list-table th { position: static; }
}

.list-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.list-table th {
  position: sticky;
  top: var(--nav-h);
  z-index: 2;
  padding: 9px 12px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-align: left;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
.list-table td {
  padding: 7px 12px;
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
}
.list-table tbody tr:nth-child(even) td { background: var(--surface-zebra); }
.list-table tbody tr:hover td { background: var(--surface-2); }

/* Totals: the last row of the body — the page script finds it that way. */
.list-table tbody tr:last-child td {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}

/* Actions: always the last column. */
.list-table th:last-child,
.list-table td:last-child { width: 1%; text-align: right; white-space: nowrap; }
.list-table td:last-child > div { display: inline-flex; align-items: center; gap: 2px; }
.list-table td:last-child form { display: inline; margin: 0; }
.list-table td:last-child button {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .12s, color .12s;
}
.list-table td:last-child button:hover { background: var(--surface-3); color: var(--text); }
.list-table td:last-child button[title^="Edit"]:hover { color: var(--accent-text); }
.list-table td:last-child button[title="Delete"]:hover { background: var(--negative-soft); color: var(--negative); }

/* Column roles, by position. Entered: Arrival, Agent, Nights, Country, Offer
   Code, Entered, Actions. Canceled: Arrival, Departure, Agent, Nights, Country,
   PAX, Rooms, Market, Rate Code, Rate Loss, Cancel Reason, Actions. */
.list-table--entered :is(th, td):nth-child(3),
.list-table--canceled :is(th, td):is(:nth-child(4), :nth-child(6), :nth-child(7), :nth-child(10)) {
  text-align: right;
}
.list-table--entered td:is(:nth-child(1), :nth-child(6)),
.list-table--canceled td:is(:nth-child(1), :nth-child(2)) { white-space: nowrap; }
.list-table--entered td:nth-child(5),
.list-table--canceled td:is(:nth-child(8), :nth-child(9)) { color: var(--text-muted); font-size: var(--fs-xs); letter-spacing: .02em; }
.list-table--canceled td:nth-child(11) { min-width: 180px; color: var(--text-muted); }
.list-table tbody tr:last-child td { color: var(--text); font-size: var(--fs-sm); }

/* Modals with forms. The modal element is itself the backdrop: the page
   script closes it when a click lands on it rather than on the box. */
.modal--backdrop { background: rgba(9, 13, 17, .6); }
.modal-box--form { width: min(480px, 100%); }
.modal-box--wide { width: min(700px, 100%); }
.modal-title { display: flex; flex: 1; align-items: center; gap: var(--sp-2); font-size: var(--fs-lg); font-weight: 650; }
.modal-title .bi { color: var(--accent); }

.form-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
.form-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3) var(--sp-4); }
@media (max-width: 560px) { .form-grid--2 { grid-template-columns: minmax(0, 1fr); } }
.form-field { display: flex; flex-direction: column; gap: 5px; }
.form-field > span { color: var(--text-muted); font-size: var(--fs-xs); font-weight: 600; }
.form-field input, .form-field select, .form-field textarea { width: 100%; }
.form-field--full { grid-column: 1 / -1; }
.form-actions { display: flex; justify-content: flex-end; gap: var(--sp-2); margin-top: var(--sp-5); }

textarea {
  min-height: 76px;
  padding: 8px var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  resize: vertical;
}
textarea:hover { border-color: var(--border-strong); }
textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ==========================================================================
   19. Print

   Paper is white and browsers skip background colours by default, so a page
   printed from the dark theme came out as near-white text on white paper.
   Printing always uses the light palette, whichever theme is on screen.
   ========================================================================== */
@media print {
  :root {
    color-scheme: light;
    --bg: #ffffff; --surface: #ffffff; --surface-2: #f1f3f6; --surface-3: #e7ebf0;
    --border: #d5dbe2; --border-strong: #b9c2cc; --rule: #e3e7ec; --grid: #ccd4dd;
    --text: #10161d; --text-muted: #4a5561; --text-faint: #6b7682; --text-invert: #ffffff;
    --accent: #0d7680; --accent-text: #0a5d66; --accent-soft: #e2f1f3;
    --positive: #10714d; --negative: #a72b21; --negative-figure: #b3261e; --warn: #8a5a00; --warn-soft: #fdf1dc;
    --surface-zebra: #f7f9fb; --warn-line: rgba(138, 90, 0, 0.4);
    --m-pickup-tint: #e0e8f3; --m-cy-tint: #e4f0ed; --m-pybob-tint: #eee5de; --m-pyfull-tint: #dfe2f3;
  }
  body { background: #ffffff; }
  .nav, .toolbar, .filter-bar, .chips, [data-print-hide], .modal, .modal-overlay { display: none !important; }
  .app-main { max-width: none; padding: 0; }
  .panel { border-color: var(--border); box-shadow: none; }
  .list-table th { position: static; }
  thead { display: table-header-group; }        /* repeat column headers on every sheet */
  tr { break-inside: avoid; }
  .list-table th:last-child, .list-table td:last-child { display: none; }   /* actions */
}

/* ==========================================================================
   20. Raw Data

   A year of stay dates in one table that scrolls inside its panel, with the
   column headers pinned at the top and the totals pinned at the bottom — the
   page fits the screen and the table takes whatever height is left.
   ========================================================================== */

.raw-panel { flex: 1; min-height: 0; }
.raw-scroll { flex: 1; min-height: 0; overflow: auto; border-top: 1px solid var(--rule); }
@media (max-width: 1100px), (max-height: 620px) { .raw-scroll { flex: none; max-height: 70vh; } }

.raw-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.raw-table th,
.raw-table td {
  padding: 6px 10px;
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.raw-table th:first-child,
.raw-table td:first-child { text-align: left; }

.raw-table thead { position: sticky; top: 0; z-index: 3; }
.raw-table thead th {
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .03em;
  text-transform: uppercase;
}
.raw-table thead tr:last-child th { border-bottom-color: var(--border); }
.raw-table thead th[rowspan] { vertical-align: bottom; }
.raw-table .grp {
  text-align: center;
  color: var(--text);
  border-top: 3px solid var(--m);
  background: var(--m-tint, var(--surface-2));
}
.raw-table .g-start { border-left: 1px solid var(--border-strong); }

.raw-table tbody tr:nth-child(even) td { background: var(--surface-zebra); }
.raw-table tbody tr:hover td { background: var(--surface-2); }
/* A rule where each month begins: a year of days scans by month. */
.raw-table tbody tr.month-start td { border-top: 1px solid var(--border-strong); }
/* Today's stay date, so the eye has somewhere to start. */
.raw-table tbody tr.is-today td { background: var(--accent-soft); }
.raw-table tbody tr.is-today td:first-child { box-shadow: inset 3px 0 0 var(--accent); font-weight: 650; }

.raw-table .zero { color: var(--text-faint); }
.raw-table .pos { color: var(--positive); font-weight: 600; }
.raw-table .neg { color: var(--negative); font-weight: 600; }

.raw-table tfoot { position: sticky; bottom: 0; z-index: 3; }
.raw-table tfoot td {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}
.raw-table tfoot td.zero { color: var(--text-faint); }

@media print {
  /* One-screen layouts are fixed to the viewport height; on paper the whole
     page has to flow, or everything below the first screen is cut. */
  .app--fixed, .app-main--fixed { height: auto !important; overflow: visible !important; display: block !important; }
  .raw-scroll { max-height: none; overflow: visible; }
  .raw-table thead, .raw-table tfoot { position: static; }
}

/* ==========================================================================
   21. Pickup History
   ========================================================================== */

/* A labelled pair of date inputs inside a filter bar, marked with the colour
   of the measure it filters. */
.filter-group {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-2);
  margin: 0;
  padding: 6px var(--sp-3) var(--sp-2);
  border: 1px solid var(--border);
  border-top: 3px solid var(--m, var(--border));
  border-radius: var(--radius-sm);
}
.filter-group legend {
  padding: 0 4px;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .03em;
  text-transform: uppercase;
}
.pickup-table .zero { color: var(--text-faint); }

/* ==========================================================================
   22. Profile Production
   ========================================================================== */

.kpi-row--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1280px) { .kpi-row--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .kpi-row--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.filter-actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; align-self: flex-end; }
.spinner--sm { width: 16px; height: 16px; }
.spinner--sm[hidden] { display: none; }

/* A filter panel whose popover opens below it must not clip it, and must sit
   above the panels that follow. */
.panel--overflow { position: relative; z-index: 5; overflow: visible; }

/* Multi-select agent picker: a button that opens a searchable checklist. */
.agent-picker { position: relative; }
.agent-picker-btn {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 280px;
  height: 32px;
  padding: 0 10px 0 var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.agent-picker-btn:hover { border-color: var(--border-strong); }
.agent-picker-btn[aria-expanded="true"],
.agent-picker-btn:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.agent-picker-btn > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-picker-btn .bi { flex: 0 0 auto; color: var(--text-faint); font-size: 12px; }

.agent-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  width: min(420px, calc(100vw - 16px));
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg, 0 16px 40px rgba(0, 0, 0, .35));
}
.agent-pop-search { display: flex; padding: var(--sp-2); border-bottom: 1px solid var(--rule); }
.agent-pop-search input { width: 100%; }
.agent-pop-list { max-height: 320px; overflow-y: auto; padding: 4px; }
.agent-option {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.agent-option:hover { background: var(--surface-2); }
.agent-option input { flex: 0 0 auto; margin: 0; accent-color: var(--accent); }
.agent-option span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-option:has(input:checked) { color: var(--accent-text); font-weight: 600; }
/* Agents with reservations carry their count; the rest are quieter, since
   picking one gives a table of zeros. */
.agent-option > input + span { flex: 1 1 auto; min-width: 0; }
.agent-option:not(.agent-option--has):not([data-agent="all agents"]) { color: var(--text-muted); }
.agent-count {
  flex: 0 0 auto;
  min-width: 24px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-text);
  font-size: var(--fs-xs);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.agent-pop-tools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: 6px var(--sp-3);
  border-bottom: 1px solid var(--rule);
  color: var(--text-muted);
  font-size: var(--fs-xs);
}
.agent-pop-note b { color: var(--accent-text); }
.agent-pop-toggle { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.agent-pop-toggle input { margin: 0; accent-color: var(--accent); }
.agent-option[data-agent="all agents"] { margin-bottom: 4px; border-bottom: 1px solid var(--rule); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }

/* Results fade while a new filter loads, instead of blanking. */
.pp-results > * + * { margin-top: var(--sp-4); }
.pp-busy { opacity: .55; pointer-events: none; transition: opacity .15s; }
.pp-agent-tables:empty { display: none; }
.pp-agent-tables > * + * { margin-top: var(--sp-4); }

.chart-body--wide { height: 340px; }

.pp-table .pos { color: var(--positive); font-weight: 600; }
.pp-table .neg { font-weight: 600; }
.pickup-table td.pp-cell-note { padding: var(--sp-5); text-align: center; color: var(--text-faint); }

@media print {
  .pp-busy { opacity: 1; }
}

/* ==========================================================================
   23. Market Production
   ========================================================================== */

/* A results area whose sections are spaced like the page's own, and which
   fades while a new filter loads instead of blanking. */
.report-stack > * + * { margin-top: var(--sp-4); }
.is-busy { opacity: .55; pointer-events: none; transition: opacity .15s; }

.panel-note { margin-left: auto; color: var(--text-faint); font-size: var(--fs-sm); white-space: nowrap; }

/* A KPI whose value is a name, not a figure. */
.kpi-value--text { display: block; overflow: hidden; font-size: 22px; text-overflow: ellipsis; white-space: nowrap; }

/* The monthly chart needs the width; the share chart does not. */
.chart-pair--wide-left { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .chart-pair--wide-left { grid-template-columns: minmax(0, 1fr); } }

/* Months are groups of two columns; a neutral band, and the total in accent. */
.mp-table .grp { --m: var(--border-strong); }
.mp-table .grp--total { --m: var(--accent); --m-tint: var(--accent-soft); }
.mp-table td:nth-last-child(-n+2) { font-weight: 600; }

/* Pie labels sit outside the pie, on the panel, so they take the page's muted
   text colour. brand-dark gives every series type's labels a dark grey that
   all but disappears on its background, and in Highcharts 13 that series-wide
   colour beats a pie-specific one, so an options override does not reach
   them. The stylesheet does, and follows the theme toggle by itself. */
.highcharts-pie-series .highcharts-data-label text { fill: var(--text-muted) !important; }

@media print {
  .is-busy { opacity: 1; }
}

/* ==========================================================================
   24. Agent Production
   ========================================================================== */

/* A select of 225 agent names: wide enough to read one, not the whole bar. */
.filter-field--wide select { width: 320px; max-width: 100%; }

/* ==========================================================================
   25. Market Intelligence
   ========================================================================== */

/* A list of records — a rate, an alert — where a table would be too rigid:
   each row is a name, a line of detail, and a figure. */
.mi-list { display: flex; flex-direction: column; }
.mi-list > * + * { border-top: 1px solid var(--rule); }

.mi-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 10px var(--sp-4);
  border-left: 3px solid var(--m, transparent);
}
.mi-item:hover { background: var(--surface-2); }
.mi-item-main { flex: 1; min-width: 0; }
.mi-item-title { font-weight: 600; }
.mi-item-sub { margin-top: 2px; color: var(--text-muted); font-size: var(--fs-xs); }
.mi-item-value {
  flex: 0 0 auto;
  text-align: right;
  font-size: var(--fs-md);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.mi-item-delta { display: block; margin-top: 2px; font-size: var(--fs-xs); font-weight: 600; }
.mi-item-delta.pos { color: var(--negative); }   /* a competitor raising its rate is good for us */
.mi-item-delta.neg { color: var(--positive); }

/* Alert severity, as the database records it. */
.mi-item--critical { --m: var(--negative); }
.mi-item--high     { --m: var(--warn); }
.mi-item--medium   { --m: var(--accent); }
.mi-item--low      { --m: var(--border-strong); }

.mi-star { margin-left: 6px; color: var(--warn); font-size: var(--fs-xs); font-weight: 600; }
.mi-sub-cell { display: block; margin-top: 2px; color: var(--text-muted); font-size: var(--fs-xs); font-weight: 400; }
.pickup-table td.muted-cell { color: var(--text-muted); font-size: var(--fs-xs); }

/* ==========================================================================
   26. TA Calculator

   A spreadsheet rebuilt as a web page: fixed column widths, 20px rows and
   colour-coded cells. The colours were hardcoded (black labels, white cells,
   lime borders, beige and gold) and inline on the elements; they are tokens
   here, so the sheet follows the theme. The geometry is still the page's own.
   ========================================================================== */

.calc-panel { padding: var(--sp-4); overflow-x: auto; }

.calc-sheet-row { display: flex; gap: var(--sp-4); align-items: flex-start; }

/* Every cell in the sheet. */
.main-table, .guest-details-table, .passenger-table, .conf-number-table {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.main-table td, .main-table th,
.guest-details-table td, .guest-details-table th,
.passenger-table td, .passenger-table th,
.conf-number-table td, .conf-number-table th {
  border: 1px solid var(--rule);
  padding: 2px 4px;
}

/* Column headings. */
.table-header, .guest-details-header {
  background: var(--surface-3);
  color: var(--text);
  font-weight: 650;
  text-align: center;
  letter-spacing: .02em;
}
.guest-details-header { font-size: var(--fs-sm); padding: 6px !important; }
.guest-details-header-row {
  background: var(--m-pybob-tint);
  color: var(--text);
  font-weight: 650;
  text-align: center;
}

/* Row labels — the black and beige columns. */
.label-cell-black, .code-cell-black, .passenger-label-beige, .passenger-label-yellow, .conf-number-label {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
  text-align: left;
}
.label-cell-white { background: var(--surface); color: var(--text); text-align: left; }

/* Value cells. */
.code-cell-white, .guest-details-cell, .passenger-value-white, .conf-number-value {
  background: var(--surface);
  color: var(--text);
  text-align: center;
}
.details-cell { background: var(--accent-soft); color: var(--accent-text); }

/* Cells the sheet colours to group them. */
.code-cell-yellow { background: var(--warn-soft); color: var(--text); text-align: center; }
.code-cell-orange { background: var(--m-pybob-tint); color: var(--text); text-align: center; }
.code-cell-blue   { background: var(--m-pickup-tint); color: var(--text); text-align: center; }
.code-cell-pink   { background: var(--negative-soft); color: var(--text); text-align: center; }
.code-cell-gray   { background: var(--surface-2); color: var(--text-muted); text-align: center; }

/* A filled passenger count stays highlighted: the script swaps this class. */
.passenger-value-green { background: var(--m-cy-tint); color: var(--text); text-align: center; font-weight: 600; }

/* Inputs sit inside their cell and take its colour. */
.calc-panel input, .calc-panel select,
.input-field, .guest-details-input, .passenger-input, .conf-number-input {
  width: 100%;
  height: auto;
  padding: 1px 2px;
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 11px;
}
.calc-panel input:focus, .calc-panel select:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  box-shadow: none;
}
.calc-panel input[readonly] { color: var(--text-muted); }
/* Chromium paints a native dropdown from the select's own background, so a
   transparent select gives a white popup with our near-white text: unreadable
   in the dark theme. The select and its options carry the surface colour. */
.calc-panel select {
  appearance: auto;
  background-color: var(--surface);
  background-image: none;
  color: var(--text);
  padding-right: 2px;
  cursor: pointer;
}
.calc-panel select option,
.calc-panel select optgroup {
  background-color: var(--surface);
  color: var(--text);
}
.calc-panel input::placeholder { color: var(--text-faint); }

/* Summary tiles under the calculation table. */
.calc-panel .code-cell-black, .calc-panel .code-cell-white { border: 1px solid var(--rule); }

/* Select2, used for the flight lists, in the page's own type size. */
.flight-select2 .select2-container--default .select2-selection--single {
  height: 20px !important;
  border: none !important;
  border-radius: 0 !important;
  background: transparent !important;
}
.flight-select2 .select2-container--default .select2-selection--single .select2-selection__rendered {
  line-height: 18px !important;
  padding-left: 2px !important;
  font-size: 11px !important;
  color: var(--text) !important;
}
.flight-select2 .select2-container--default .select2-selection--single .select2-selection__arrow { height: 18px !important; }
.select2-container--default .select2-dropdown {
  background: var(--surface) !important;
  border-color: var(--border-strong) !important;
  color: var(--text);
}
.select2-container--default .select2-results__option { font-size: 11px !important; padding: 3px 8px !important; color: var(--text); }
.select2-container--default .select2-results__option--highlighted[aria-selected] { background: var(--accent) !important; color: var(--text-invert) !important; }
.select2-container--default .select2-search--dropdown .select2-search__field {
  background: var(--surface-2) !important;
  border: 1px solid var(--border) !important;
  color: var(--text) !important;
  font-size: 11px !important;
}

/* ==========================================================================
   27. Empty pages

   A page that has nothing behind it yet says so in the middle of a panel,
   in sentences rather than a shrug.
   ========================================================================== */
.state--page { padding: var(--sp-10) var(--sp-5); gap: var(--sp-2); }
.state--page p { max-width: 62ch; margin: 0; }
.state-title { color: var(--text); font-size: var(--fs-lg); font-weight: 650; }

/* ==========================================================================
   28. Contract
   ========================================================================== */

/* Page-level actions, sitting opposite the page title. */
.page-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-left: auto; }

/* Rates read down the column, so the money is right-aligned. */
.list-table--contract :is(th, td):nth-child(n+3):nth-child(-n+7) { text-align: right; }
.list-table--contract td:nth-child(n+3):nth-child(-n+7) { font-variant-numeric: tabular-nums; }
.list-table--contract td:first-child { font-weight: 600; }

/* The file input in the upload modal. */
.form-field input[type="file"] {
  width: 100%;
  padding: 7px var(--sp-3);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font: inherit;
  font-size: var(--fs-sm);
}
.form-field input[type="file"]::file-selector-button {
  margin-right: var(--sp-3);
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}
.form-field small.muted { font-size: var(--fs-xs); line-height: 1.5; }

/* Chips can be a list: it is a set of links, and a screen reader should hear
   how many. The markers are not wanted. */
.chips { list-style: none; margin-left: auto; padding: 0; }
.chips li { display: contents; }

/* A contract date belongs on one line. */
.list-table--contract td:nth-child(2) { white-space: nowrap; }

/* ==========================================================================
   29. TA Confirmation

   The confirmation letter. These are the page's own styles, moved here
   unchanged and scoped to the document: it is a letter on white paper with
   black rules, and it stays that way in both themes because this is exactly
   what gets copied to the clipboard and printed. Only the chrome around it
   follows the theme.
   ========================================================================== */

.conf-panel { padding: var(--sp-4); overflow-x: auto; }

.confirmation-document {
  background: white;
  color: #000;
  max-width: 1200px;
  width: 100%;
  margin: 0 auto;
  padding: 30px 40px 40px 40px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, .3);
  min-height: 600px;
  border: 2px solid #000;
  display: block;
  box-sizing: border-box;
  overflow: visible;
  position: relative;
}
@media screen and (min-width: 1400px) {
  .confirmation-document { max-width: 1400px; }
}

.confirmation-document .fixed-text { color: #000; }

/* Fields someone fills in are pink; fields filled from the calculator are
   blue and read-only, as in the sheet this letter came from. */
.confirmation-document .editable-field {
  background: #FFE4E1;
  border: 1px solid #FF6B6B;
  padding: 4px 8px;
  min-width: 200px;
  color: #000;
}
.confirmation-document .editable-field:focus { outline: 2px solid #FF6B6B; background: #FFF; }
.confirmation-document .editable-field[readonly] {
  background: #E8F4F8;
  border: 1px solid #4A90E2;
  cursor: default;
}
.confirmation-document .editable-field[readonly]:focus { outline: 2px solid #4A90E2; background: #E8F4F8; }
.confirmation-document textarea.editable-field {
  font-family: inherit;
  font-size: 15px;
  resize: vertical;
  line-height: 1.4;
  white-space: pre-line;
  padding: 8px;
}
.confirmation-document .editable-textarea {
  background: #FFE4E1;
  border: 1px solid #FF6B6B;
  padding: 4px 8px;
  width: 100%;
  min-height: 60px;
  color: #000;
  font-family: inherit;
  font-size: 15px;
  resize: vertical;
  line-height: 1.4;
  box-sizing: border-box;
  word-wrap: break-word;
  white-space: pre-wrap;
}
.confirmation-document .editable-textarea:focus { outline: 2px solid #FF6B6B; background: #FFF; }
.confirmation-document .editable-paragraph {
  background: #FFE4E1;
  border: 1px solid #FF6B6B;
  padding: 8px;
  width: 100%;
  min-height: 40px;
  color: #000;
  margin-bottom: 10px;
}
.confirmation-document .editable-paragraph:focus { outline: 2px solid #FF6B6B; background: #FFF; }

.confirmation-document .booking-details-table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
  border: 1px solid #000;
  table-layout: fixed;
}
.confirmation-document .booking-details-table td { padding: 8px; vertical-align: top; border: 1px solid #000; }
.confirmation-document .booking-details-table td:first-child { width: 200px; font-weight: 500; }
.confirmation-document .booking-details-table td:last-child { width: auto; }

.confirmation-document .section-heading {
  margin: 20px 0 10px;
  color: #000;
  font-size: 16px;
  font-weight: bold;
  text-align: center;
  text-transform: uppercase;
}
.confirmation-document .meal-plan-legend { margin-top: 10px; font-size: 11px; text-align: left; }
.confirmation-document .remarks-list { padding-left: 0; list-style: none; }
.confirmation-document .remarks-list li { margin: 8px 0; }
.confirmation-document .remarks-list li::before { content: "* "; margin-right: 5px; }

.confirmation-document .logo-container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  margin: 0 auto 30px;
  text-align: center;
}
.confirmation-document .logo-container img { display: block; max-width: 180px; height: auto; margin: 0 auto; }

@media print {
  @page { size: landscape; margin: 1cm; }
  .confirmation-document { max-width: 100%; padding: 20px; box-shadow: none; }
  .conf-panel { padding: 0; border: none; box-shadow: none; overflow: visible; }
}

/* ==========================================================================
   30. Profile Report

   The summary tab and the operators modal are still written by the script as
   Tailwind markup. Rather than redefine dozens of utilities, those containers
   style what they are given: a table inside one of them gets the app's table
   treatment whatever classes it carries. The operators tab has its own table
   (section 31) and is deliberately not covered here.
   ========================================================================== */

.report-panel { flex: 1; min-height: 0; overflow: hidden; }
.report-scroll { flex: 1; min-height: 0; overflow: auto; }
.report-scroll[hidden], .report-scroll.hidden { display: none; }

/* Tabs. The page's script marks the active one by adding text-blue-400 and
   border-blue-400, so the active state keys off those classes. */
.tabs-row { gap: var(--sp-1, 4px); padding: 0 var(--sp-4); }
.tab-btn {
  padding: 10px var(--sp-3);
  border: none;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  transition: color .12s, border-color .12s;
}
.tab-btn:hover { color: var(--text); }
.tab-btn.text-blue-400 { color: var(--accent-text); border-bottom-color: var(--accent); }

/* The operators modal is still script-written Tailwind markup, so its table is
   styled by its container. The summary tab's own table is a .pr-table now
   (section 31) and is deliberately left out of these rules. */
#operators-modal-content table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
#operators-modal-content th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 8px 10px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .03em;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
#operators-modal-content td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--rule);
  color: var(--text);
}
#operators-modal-content tbody tr:nth-child(even) td { background: var(--surface-zebra); }
#operators-modal-content tbody tr:hover td { background: var(--surface-2); }

/* The summary's KPI cards: the app's own .kpi-row, with the page's padding. */
.summary-kpis { padding: var(--sp-4) var(--sp-4) 0; }

/* The market table sits on a card of its own, with the screenshot button in
   its header — the button is part of what gets captured, so it belongs there. */
.summary-wrap { padding: var(--sp-4); }
.summary-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.summary-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--rule);
}
.summary-card-title { margin: 0; font-size: var(--fs-md); font-weight: 650; }
.summary-card-head .btn { margin-left: auto; }
.summary-scroll { overflow-x: auto; }

/* Every market row is a market: no heavier rule between them than the rest. */
.summary-table .pr-market th, .summary-table .pr-market td { background: none; border-top: none; }
.summary-table .pr-market:hover th, .summary-table .pr-market:hover td { background: var(--surface-2); }

/* The operators count opens the market's operators. */
.pr-ops-btn {
  padding: 2px 6px;
  border: none;
  border-radius: var(--radius-sm, 4px);
  background: none;
  color: var(--accent-text);
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}
.pr-ops-btn .bi { font-size: 10px; opacity: .7; }
.pr-ops-btn:hover { background: var(--accent-soft); }

/* The operators modal (partials/operators_modal.php, used by this page only). */
/* The partial positions itself with Tailwind's inset-0 and bg-black, which
   this stylesheet does not define, so the overlay is described here. */
#operators-modal {
  position: fixed;
  inset: 0;
  z-index: 201;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5);
  background: rgba(9, 13, 17, .6);
}
#operators-modal > div {
  display: flex;
  flex-direction: column;
  width: min(1100px, 100%);
  max-height: min(86vh, 800px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
#operators-modal h2 { font-size: var(--fs-lg); font-weight: 650; color: var(--text); }
#operators-modal #close-operators-modal { background: none; border: none; color: var(--text-muted); cursor: pointer; }
#operators-modal #close-operators-modal:hover { color: var(--text); }

/* ==========================================================================
   31. Profile Report — operators view

   Markets largest first, operators inside them, and the twelve months one
   click away on the row you care about.
   ========================================================================== */

.pr-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--rule);
}
.pr-toggle { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: var(--fs-sm); cursor: pointer; }
.pr-toggle input { margin: 0; accent-color: var(--accent); }
.pr-count { margin-left: auto; color: var(--text-faint); font-size: var(--fs-sm); }

.pr-wrap { padding: 0 var(--sp-4) var(--sp-4); }

.pr-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.pr-table th, .pr-table td { padding: 7px 10px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--rule); }
.pr-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .03em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.pr-table th.pr-name, .pr-table tbody th, .pr-table tfoot th { text-align: left; }

/* A market and its operators. */
.pr-table .pr-market th, .pr-table .pr-market td {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 650;
  border-top: 1px solid var(--border-strong);
}
.pr-table .pr-op th { font-weight: 500; padding-left: 0; }
.pr-table .pr-op:hover td, .pr-table .pr-op:hover th { background: var(--surface-2); }
.pr-table .pr-op.is-open td, .pr-table .pr-op.is-open th { background: var(--accent-soft); }

.pr-expand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 2px 10px 2px var(--sp-4);
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.pr-expand .bi { color: var(--text-faint); font-size: 11px; transition: transform .12s; }
.pr-expand[aria-expanded="true"] .bi { transform: rotate(90deg); color: var(--accent-text); }
.pr-expand:hover { color: var(--accent-text); }

.pr-sub { display: block; color: var(--text-faint); font-size: var(--fs-xs); font-weight: 500; }
.pr-table .pos { color: var(--positive); font-weight: 600; }
.pr-table .neg { color: var(--negative); font-weight: 600; }
.pr-table .zero { color: var(--text-faint); }

/* Share of nights, as a figure with its own bar. */
.pr-share { position: relative; min-width: 92px; }
.pr-bar {
  position: absolute;
  left: 10px; right: 10px; bottom: 6px;
  height: 3px;
  border-radius: 2px;
  background: var(--surface-3);
}
.pr-bar::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 0%);
  border-radius: 2px;
  background: var(--accent);
}
.pr-share-num { display: inline-block; padding-bottom: 6px; }

.pr-table tfoot th, .pr-table tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}
.pr-empty { text-align: center !important; padding: var(--sp-6) !important; color: var(--text-faint); }

/* The month strip inside an opened row. */
.pr-months > td { padding: 0 !important; background: var(--surface-2); }
.pr-strip { padding: var(--sp-3) var(--sp-4) var(--sp-4) calc(var(--sp-4) * 2); overflow-x: auto; }
.pr-strip table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-xs); }
.pr-strip th, .pr-strip td { padding: 4px 8px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--rule); }
.pr-strip thead th { color: var(--text-muted); font-weight: 650; text-transform: uppercase; }
.pr-strip tbody th { text-align: left; color: var(--text-muted); font-weight: 600; }
.pr-strip tbody tr:last-child th, .pr-strip tbody tr:last-child td { border-bottom: none; }

/* ==========================================================================
   32. ADR Report

   A night per row, three measures across, each against the same date a year
   earlier. The header is two rows — the measure, then the three columns under
   it — and both rows stay under the navigation as the table scrolls.
   ========================================================================== */

.adr-table { font-variant-numeric: tabular-nums; }
.adr-table th, .adr-table td { text-align: right; white-space: nowrap; }
.adr-table thead tr:first-child th { height: 30px; }
.adr-table thead tr:nth-child(2) th { top: calc(var(--nav-h) + 30px); }
.adr-table .adr-group { text-align: center; border-left: 1px solid var(--border); }
.adr-table thead tr:nth-child(2) th:nth-child(3n + 1) { border-left: 1px solid var(--border); }
.adr-table tbody td:nth-child(2), .adr-table tfoot td:nth-child(2),
.adr-table tbody td:nth-child(5), .adr-table tfoot td:nth-child(5),
.adr-table tbody td:nth-child(8), .adr-table tfoot td:nth-child(8) { border-left: 1px solid var(--rule); }

/* The date, and underneath it the weekday and the date it is measured against
   — a year earlier is not always the same weekday, and around a leap day it is
   not even the same day of the month. */
.adr-table .adr-date { text-align: left; font-weight: 600; }
.adr-table tbody th.adr-date { color: var(--text); }
.adr-sub { display: block; color: var(--text-faint); font-size: var(--fs-xs); font-weight: 500; }

.adr-table .pos { color: var(--positive); font-weight: 600; }
.adr-table .neg { color: var(--negative); font-weight: 600; }
.adr-table .zero, .adr-table .muted { color: var(--text-faint); }

/* Totals sit in a real footer here, so they need the weight the list table
   gives its last body row. */
.adr-table tfoot th, .adr-table tfoot td {
  position: sticky;
  bottom: 0;
  padding: 9px 12px;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}

/* The list table makes every th a sticky, uppercased column heading. Here the
   row headings are dates, so they are neither. */
.adr-table tbody th.adr-date, .adr-table tfoot th.adr-date {
  position: static;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-sm);
}
.adr-table tfoot th.adr-date { position: sticky; bottom: 0; }
.adr-sub { text-transform: none; letter-spacing: 0; }

/* ==========================================================================
   33. Weekly Report

   A month per column, a week of the month per row, and the year, the year
   before and the change on tabs — instead of three twenty-five column tables
   stacked on one page.
   ========================================================================== */

.wr-legend { margin-left: auto; color: var(--text-faint); font-size: var(--fs-sm); }
.wr-wrap { padding: 0 var(--sp-4) var(--sp-4); }

.wr-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.wr-table th, .wr-table td {
  padding: 8px 10px;
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.wr-table thead th {
  position: sticky;
  top: var(--nav-h);
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.wr-table tbody th, .wr-table tfoot th { text-align: left; font-weight: 650; }
.wr-table tbody tr:hover td, .wr-table tbody tr:hover th { background: var(--surface-2); }

/* The revenue sits under the nights that earned it. */
.wr-sub { display: block; color: var(--text-faint); font-size: var(--fs-xs); font-weight: 500; }
.wr-table .pos { color: var(--positive); font-weight: 600; }
.wr-table .neg { color: var(--negative); font-weight: 600; }
.wr-table .zero, .wr-table .muted { color: var(--text-faint); font-weight: 500; }
.wr-sub.pos { color: var(--positive); }
.wr-sub.neg { color: var(--negative); }

.wr-table tfoot th, .wr-table tfoot td {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}
.wr-table tfoot .wr-sub { color: var(--text-muted); font-weight: 600; }

/* Tabs that say which one is current without borrowing Tailwind's classes. */
.tab-btn[aria-selected="true"] { color: var(--accent-text); border-bottom-color: var(--accent); }

/* Thirteen columns fit a desktop; below that the table scrolls sideways and
   becomes its own sticky container, where top: var(--nav-h) would push the
   header down over the first week instead of holding it up. */
@media (max-width: 1100px) {
  .wr-wrap { overflow-x: auto; }
  .wr-table thead th { top: 0; }
}

/* ==========================================================================
   34. Summary Report

   Four views of the same twelve months — on the books, a year ago, and the
   two the page cannot fill — one at a time instead of twenty-five columns
   across one table.
   ========================================================================== */

.sr-flag {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--text-faint);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
}
.tab-btn[aria-selected="true"] .sr-flag { background: var(--warn-soft, var(--surface-3)); color: var(--warn, var(--text-muted)); }

.sr-note { margin: 0; padding: var(--sp-3) var(--sp-4) 0; color: var(--text-muted); font-size: var(--fs-sm); }
.sr-note strong { color: var(--text); font-weight: 650; }
.sr-wrap { padding: var(--sp-3) var(--sp-4) var(--sp-4); overflow-x: auto; }

.sr-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.sr-table th, .sr-table td {
  padding: 9px 12px;
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.sr-table thead th {
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.sr-table .sr-month { text-align: left; font-weight: 650; }
.sr-table tbody tr:hover td, .sr-table tbody tr:hover th { background: var(--surface-2); }
.sr-table .sr-none { text-align: center; color: var(--text-faint); font-style: italic; }

.sr-table tfoot th, .sr-table tfoot td {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}

/* ==========================================================================
   35. Nationality Report

   Top ten countries as one table rather than three side by side, and the
   month grid with the nights on the line and the revenue underneath, so a
   year fits in thirteen columns instead of twenty-seven.
   ========================================================================== */

.nr-legend { margin-left: auto; color: var(--text-faint); font-size: var(--fs-sm); }
.nr-wrap { padding: 0 var(--sp-4) var(--sp-4); overflow-x: auto; }

.nr-top, .nr-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.nr-top th, .nr-top td, .nr-table th, .nr-table td {
  padding: 8px 10px;
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.nr-top thead th, .nr-table thead th {
  position: sticky;
  top: var(--nav-h);
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.nr-top .nr-name, .nr-table .nr-name { text-align: left; }
.nr-top tbody th, .nr-table tbody th, .nr-table tfoot th { font-weight: 650; color: var(--text); }
.nr-top tbody tr:hover td, .nr-top tbody tr:hover th,
.nr-table tbody tr:hover td, .nr-table tbody tr:hover th { background: var(--surface-2); }

/* The revenue sits under the nights that earned it. */
.nr-sub { display: block; color: var(--text-faint); font-size: var(--fs-xs); font-weight: 500; }
.nr-top .pos, .nr-table .pos { color: var(--positive); font-weight: 600; }
.nr-top .neg, .nr-table .neg { color: var(--negative); font-weight: 600; }
.nr-top .zero, .nr-table .zero, .nr-table .muted { color: var(--text-faint); font-weight: 500; }

/* A share, as a figure with its own bar. */
.nr-share { position: relative; min-width: 86px; }
.nr-bar {
  position: absolute;
  left: 10px; right: 10px; bottom: 6px;
  height: 3px;
  border-radius: 2px;
  background: var(--surface-3);
}
.nr-bar::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 0%);
  border-radius: 2px;
  background: var(--accent);
}
.nr-share-num { display: inline-block; padding-bottom: 6px; }

/* A night with bookings behind it. */
.nr-table .rmn-clickable { cursor: pointer; border-bottom: 1px dotted var(--text-faint); }
.nr-table .rmn-clickable:hover { color: var(--accent-text); border-bottom-color: var(--accent); }

.nr-table .nr-total { background: var(--surface-2); font-weight: 650; }
.nr-table tfoot th, .nr-table tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}

/* An agent inside the bookings modal, its stays one click away. */
.nr-agent { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: var(--sp-2); overflow: hidden; }
.nr-agent-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3);
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.nr-agent-head:hover { background: var(--surface-2); }
.nr-agent-head .bi { color: var(--text-faint); font-size: 11px; transition: transform .12s; }
.nr-agent-head[aria-expanded="true"] .bi { transform: rotate(90deg); color: var(--accent-text); }
.nr-agent-name { flex: 1; font-weight: 600; }
.nr-agent-figs { text-align: right; font-weight: 650; font-variant-numeric: tabular-nums; }
.nr-agent-body { border-top: 1px solid var(--rule); padding: var(--sp-3); }
.nr-bookings { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.nr-bookings th, .nr-bookings td { padding: 6px 8px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--rule); }
.nr-bookings th:first-child, .nr-bookings td:first-child,
.nr-bookings th:nth-child(2), .nr-bookings td:nth-child(2),
.nr-bookings th:nth-child(3), .nr-bookings td:nth-child(3) { text-align: left; }
.nr-bookings thead th { color: var(--text-muted); font-size: var(--fs-xs); font-weight: 650; text-transform: uppercase; }
.nr-bookings tbody tr:last-child td { border-bottom: none; }

/* Below a desktop the grids scroll sideways and become their own sticky
   container, where top: var(--nav-h) would push the header over the rows. */
@media (max-width: 1400px) {
  .nr-top thead th, .nr-table thead th { top: 0; }
}

/* ==========================================================================
   36. Region Report

   A month per column with the revenue under the nights, and a region that
   opens to show the countries inside it.
   ========================================================================== */

.rr-wrap { padding: 0 var(--sp-4) var(--sp-4); overflow-x: auto; }

.rr-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.rr-table th, .rr-table td {
  padding: 7px 10px;
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.rr-table thead th {
  position: sticky;
  top: var(--nav-h);
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.rr-table .rr-name, .rr-table tbody th, .rr-table tfoot th { text-align: left; }

/* A region, and the countries it opens. */
.rr-table .rr-region th, .rr-table .rr-region td {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 650;
  border-top: 1px solid var(--border-strong);
}
.rr-table .rr-region th { padding: 0; }
.rr-table .rr-country th { padding-left: var(--sp-6); font-weight: 500; color: var(--text); }
.rr-table .rr-country:hover th, .rr-table .rr-country:hover td { background: var(--surface-2); }

.rr-expand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 7px 10px;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 650;
  text-align: left;
  cursor: pointer;
}
.rr-expand .bi { color: var(--text-faint); font-size: 11px; transition: transform .12s; }
.rr-expand[aria-expanded="true"] .bi { transform: rotate(90deg); color: var(--accent-text); }
.rr-expand:hover { color: var(--accent-text); }

.rr-sub { display: block; color: var(--text-faint); font-size: var(--fs-xs); font-weight: 500; }
.rr-table .muted { color: var(--text-faint); }
.rr-table .rr-total { background: var(--surface-2); font-weight: 650; }

.rr-table tfoot th, .rr-table tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}
.rr-table tfoot .rr-sub { color: var(--text-muted); font-weight: 600; }

/* Below a desktop the table scrolls sideways and becomes its own sticky
   container, where top: var(--nav-h) would push the header over the rows. */
@media (max-width: 1400px) {
  .rr-table thead th { top: 0; }
}

/* ==========================================================================
   37. Admin

   User management, the activity monitor and the change-password form. The
   rights checkboxes are grouped the way the navigation is, so granting
   somebody "Sales" reads the same here as it does in the menu.
   ========================================================================== */

/* A confirmation that something worked, alongside .notice--warn. */
.notice--ok {
  background: var(--positive-soft, var(--surface-2));
  border-color: var(--positive);
  color: var(--text);
}
.notice--ok .bi { color: var(--positive); }

/* A small label: a right somebody holds, where a session came from. */
.tag {
  display: inline-block;
  margin: 1px 3px 1px 0;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 550;
  white-space: nowrap;
}
.tag--muted { color: var(--text-faint); border-style: dashed; }
.tag--live { background: var(--positive-soft, var(--surface-2)); border-color: var(--positive); color: var(--positive); }
.tag--stale { background: var(--negative-soft, var(--surface-2)); border-color: var(--negative); color: var(--negative); }

/* ------------------------------------------------------ user management -- */

.list-table--users .um-id { width: 1%; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.list-table--users .um-name { font-weight: 650; }
.list-table--users .um-rights { max-width: 460px; white-space: normal; }
/* Delete is a form post now, so it is the last-child button rule that
   styles it; it only needs its own hover colour. */
.list-table--users td:last-child button[title^="Delete"]:hover { background: var(--negative-soft); color: var(--negative); }

/* The rights, grouped as the navigation groups them. */
.rights-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  max-height: 320px;
  padding: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  overflow-y: auto;
}
@media (max-width: 560px) { .rights-grid { grid-template-columns: minmax(0, 1fr); } }
.rights-group h3 {
  margin: 0 0 6px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--rule);
  color: var(--accent-text);
  font-size: var(--fs-xs);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.right-box {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 0;
  color: var(--text);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.right-box input { margin: 0; accent-color: var(--accent); }
.right-box:hover { color: var(--accent-text); }

/* ------------------------------------------------------ activity monitor -- */

.ua-toggle { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: var(--fs-sm); cursor: pointer; }
.ua-toggle input { margin: 0; accent-color: var(--accent); }
.ua-wrap { padding: 0 var(--sp-4) var(--sp-4); overflow-x: auto; }

.ua-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
}
.ua-table th, .ua-table td {
  padding: 8px 10px;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.ua-table thead th {
  position: sticky;
  top: var(--nav-h);
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.ua-table tbody th { font-weight: 650; color: var(--text); }
.ua-table tbody tr:hover td, .ua-table tbody tr:hover th { background: var(--surface-2); }
.ua-table tbody tr:last-child td, .ua-table tbody tr:last-child th { border-bottom: none; }
.ua-ip { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* The date on the line, the time under it: two rows compare at a glance. */
.ua-time { display: inline-block; }
.ua-sub { display: block; color: var(--text-faint); font-size: var(--fs-xs); }

/* Somebody who is signed in right now. */
.ua-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--positive);
}

@media (max-width: 1100px) { .ua-table thead th { top: 0; } }

/* ------------------------------------------------------ change password --- */

.panel--narrow { width: min(520px, 100%); margin: 0 auto; }
.panel--narrow .panel-body { padding: var(--sp-5); }
.panel--narrow .notice { margin-bottom: var(--sp-4); }
.field-hint { color: var(--text-faint); font-size: var(--fs-xs); }
.form-actions .btn { text-decoration: none; }

/* Rights summarised by section, opening to the full list: twenty-six tags in
   a table cell turned every row into a paragraph. */
.um-details > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  list-style: none;
  cursor: pointer;
}
.um-details > summary::-webkit-details-marker { display: none; }
.um-details > summary::after {
  content: "\F282";                      /* bootstrap-icons chevron-right */
  font-family: "bootstrap-icons";
  color: var(--text-faint);
  font-size: 10px;
  transition: transform .12s;
}
.um-details[open] > summary::after { transform: rotate(90deg); color: var(--accent-text); }
.um-details > summary:hover { color: var(--accent-text); }
.um-sections { color: var(--text-muted); font-size: var(--fs-xs); }
.um-of { color: var(--text-faint); }
.um-all { margin-top: 6px; max-width: 520px; }

/* A checkbox inside a form field must not take the field's full width: the
   .form-field rule sizes text inputs, and a checkbox is not one. */
.right-box input[type="checkbox"] { flex: 0 0 auto; width: auto; height: auto; }

/* ==========================================================================
   38. Sign in

   The form alone, on a card in the middle of the page, with the resort's
   logo above it. The page follows the light/dark theme like every other.
   ========================================================================== */

.login {
  flex: 1;
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: clamp(18px, 4vw, 48px);
  background: #dff3fb url("../assets/img/login-bg.jpg") center / cover no-repeat;
}

.lg-panel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
  width: min(440px, 100%);
}

/* ------------------------------------------------------------------- card -- */

.lg-card {
  position: relative;
  padding: clamp(26px, 3vw, 38px);
  border: 1px solid rgba(255, 255, 255, .7);
  border-radius: 22px;
  background: rgba(255, 255, 255, .72);
  box-shadow: 0 24px 60px rgba(14, 92, 120, .18);
  backdrop-filter: blur(18px) saturate(1.2);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
  animation: lg-rise .5s cubic-bezier(.2, .8, .2, 1) both;
}
.has-error .lg-card { animation: lg-rise .5s cubic-bezier(.2, .8, .2, 1) both, lg-shake .42s .5s both; }


/* The resort's logo, centred and on its own. The file is drawn in black, so
   it is used as a mask and takes the theme's text colour. */
.lg-logo {
  display: block;
  width: 230px;
  height: 230px;
  margin: -40px auto -8px;    /* the file has wide empty margins around the artwork */
  background: var(--text);
  -webkit-mask: url("../assets/img/logo.svg") center / contain no-repeat;
          mask: url("../assets/img/logo.svg") center / contain no-repeat;
}


.lg-error { margin-bottom: 18px; }

.lg-form { display: grid; gap: 16px; }
.lg-form .form-field > span:first-child { font-size: var(--fs-xs); letter-spacing: .02em; }

/* A field with its icon inside it. */
.lg-input { position: relative; display: block; }
.lg-input > .bi {
  position: absolute;
  top: 50%;
  left: 14px;
  color: var(--text-faint);
  font-size: 15px;
  transform: translateY(-50%);
  pointer-events: none;
  transition: color .15s;
}
.lg-input input[type="text"],
.lg-input input[type="password"] {
  width: 100%;
  height: 48px;
  padding: 0 44px 0 40px;
  border-radius: 12px;
  font-size: var(--fs-md);
}
.lg-input:focus-within > .bi { color: var(--accent-text); }

.lg-reveal {
  position: absolute;
  top: 50%;
  right: 7px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 9px;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
  transform: translateY(-50%);
}
.lg-reveal:hover { background: var(--surface-2); color: var(--text); }
.lg-reveal:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.lg-caps { display: inline-flex; align-items: center; gap: 5px; color: var(--warn); font-size: var(--fs-xs); font-weight: 600; }
.lg-caps[hidden] { display: none; }

.form-field.is-missing input { border-color: var(--negative); box-shadow: 0 0 0 3px var(--negative-soft); }

.lg-submit {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  height: 50px;
  margin-top: 6px;
  border: none;
  border-radius: 12px;
  background: var(--accent);
  color: var(--text-invert);
  font: inherit;
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: .01em;
  cursor: pointer;
  overflow: hidden;
  transition: background .15s, transform .15s;
}
.lg-submit:hover { background: var(--accent-hover); }
.lg-submit:active { transform: translateY(1px); }
.lg-submit:focus-visible { outline: 3px solid var(--accent-soft); outline-offset: 2px; }
.lg-submit .bi { transition: transform .18s; }
.lg-submit:hover .bi { transform: translateX(4px); }
.lg-submit:disabled { cursor: progress; opacity: .85; }
.lg-submit.is-busy::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, .25) 50%, transparent 80%);
  animation: lg-sheen 1.1s linear infinite;
}



/* ------------------------------------------------------------- movement -- */

@keyframes lg-rise { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes lg-shake {
  20%, 60% { transform: translateX(-6px); }
  40%, 80% { transform: translateX(6px); }
}
@keyframes lg-sheen { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

@media (prefers-reduced-motion: reduce) {
  .lg-card, .has-error .lg-card { animation: none; }
  .lg-submit.is-busy::after { animation: none; }
}

@media (max-width: 480px) {
  .lg-card { border-radius: 18px; }
  .lg-logo { width: 190px; height: 190px; margin: -36px auto -18px; }
}

/* ==========================================================================
   39. Activity Log (admin/activity_log.php)

   A long list read by scanning down the "What changed" column, so that column
   carries the weight and everything beside it stays quiet. The before-and-after
   of an edit is folded away until asked for.
   ========================================================================== */

/* The log is a list of equals: no totals row, and no sticky header to sit over
   the first line of it (.list-table styles both for the data pages). */
.al-table tbody tr:last-child td {
  background: inherit;
  font-weight: inherit;
  border-top: 0;
  border-bottom: 1px solid var(--rule);
}
.al-table tbody tr:nth-child(even):last-child td { background: var(--surface-zebra); }
.al-table th { position: static; }
.al-table td { vertical-align: top; }
.al-table th:last-child,
.al-table td:last-child { width: 1%; text-align: right; }
.al-table .al-when { white-space: nowrap; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.al-table .al-ip { white-space: nowrap; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.al-table .al-what { max-width: 60ch; }

.al-detail { margin-top: 2px; }
.al-detail summary {
  cursor: pointer;
  color: var(--accent-text);
  font-size: var(--fs-xs);
  list-style: none;
}
.al-detail summary::-webkit-details-marker { display: none; }
.al-detail summary::before { content: "\F282"; font-family: "bootstrap-icons"; margin-right: 4px; font-size: 10px; }
.al-detail[open] summary::before { content: "\F286"; }

.al-fields {
  margin: 4px 0 0;
  padding: var(--sp-2);
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 2px var(--sp-3);
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
}
.al-fields dt { color: var(--text-muted); }
.al-fields dd { margin: 0; }
.al-fields .al-from { color: var(--negative); text-decoration: line-through; }
.al-fields .al-to { color: var(--positive); }
.al-fields .al-pair { margin-right: var(--sp-3); white-space: nowrap; }

.al-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border-top: 1px solid var(--rule);
}
