/* Bokun dashboard — validated dataviz palette + app chrome. */
:root {
  color-scheme: light;
  --surface-0: #f4f4f1;      /* page */
  --surface-1: #fcfcfb;      /* cards / chart surface */
  --surface-2: #f0efec;      /* subtle fills */
  --border:    #e3e2dd;
  --text-1:    #0b0b0b;
  --text-2:    #52514e;
  --text-3:    #85847e;
  /* categorical (light) — validated order */
  --s1:#2a78d6; --s2:#eb6834; --s3:#1baf7a; --s4:#eda100; --s5:#e87ba4; --s6:#008300;
  --good:#1baf7a; --warn:#eda100; --bad:#e34948;
  --accent:#2a78d6;
  --shadow: 0 1px 2px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.05);
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --surface-0:#121211; --surface-1:#1a1a19; --surface-2:#252523; --border:#333330;
    --text-1:#ffffff; --text-2:#c3c2b7; --text-3:#8f8e85;
    --s1:#3987e5; --s2:#d95926; --s3:#199e70; --s4:#c98500; --s5:#d55181; --s6:#008300;
    --good:#199e70; --warn:#c98500; --bad:#e66767; --accent:#3987e5;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 6px 20px rgba(0,0,0,.35);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-0:#121211; --surface-1:#1a1a19; --surface-2:#252523; --border:#333330;
  --text-1:#ffffff; --text-2:#c3c2b7; --text-3:#8f8e85;
  --s1:#3987e5; --s2:#d95926; --s3:#199e70; --s4:#c98500; --s5:#d55181; --s6:#008300;
  --good:#199e70; --warn:#c98500; --bad:#e66767; --accent:#3987e5;
  --shadow: 0 1px 2px rgba(0,0,0,.3), 0 6px 20px rgba(0,0,0,.35);
}

* { box-sizing: border-box; }
html, body { margin:0; padding:0; }
body {
  background: var(--surface-0);
  color: var(--text-1);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Nav */
.nav {
  position: sticky; top:0; z-index: 20;
  display:flex; align-items:center; gap:22px;
  padding: 12px 24px; background: var(--surface-1);
  border-bottom: 1px solid var(--border);
}
.brand { font-weight: 700; font-size: 15px; letter-spacing:.2px; display:flex; align-items:center; gap:9px; }
.brand .dot { width:10px; height:10px; border-radius:3px; background: var(--accent); display:inline-block; }
.nav .links { display:flex; gap:4px; }
.nav .links a {
  color: var(--text-2); padding:6px 12px; border-radius:8px; font-weight:500;
}
.nav .links a:hover { background: var(--surface-2); text-decoration:none; }
.nav .links a.active { color: var(--text-1); background: var(--surface-2); }
.nav .spacer { flex:1; }
.nav .meta { color: var(--text-3); font-size:12px; }
.themebtn {
  background: var(--surface-2); color: var(--text-2); border:1px solid var(--border);
  border-radius:8px; padding:6px 10px; cursor:pointer; font-size:13px;
}

.wrap { max-width: 1240px; margin: 0 auto; padding: 24px; }
.pagehead { margin: 4px 0 20px; }
.pagehead h1 { font-size: 22px; margin:0 0 4px; letter-spacing:-.01em; }
.pagehead p { margin:0; color: var(--text-2); }

/* KPI tiles */
.kpis { display:grid; grid-template-columns: repeat(auto-fit, minmax(180px,1fr)); gap:14px; margin-bottom:22px; }
.kpi {
  background: var(--surface-1); border:1px solid var(--border); border-radius:14px;
  padding:16px 18px; box-shadow: var(--shadow);
}
.kpi .label { color: var(--text-3); font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:.04em; }
.kpi .value { font-size:28px; font-weight:700; margin-top:6px; letter-spacing:-.02em; }
.kpi .value small { font-size:15px; font-weight:600; color: var(--text-2); }
.kpi .sub { color: var(--text-3); font-size:12px; margin-top:3px; }

/* Cards / charts */
.grid { display:grid; gap:16px; }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px){ .grid.cols-2, .grid.cols-3 { grid-template-columns: 1fr; } }
.card {
  background: var(--surface-1); border:1px solid var(--border); border-radius:14px;
  padding:18px; box-shadow: var(--shadow);
}
.card h3 { margin:0 0 2px; font-size:15px; }
.card .hint { color: var(--text-3); font-size:12px; margin:0 0 12px; }
.chart-holder { position: relative; height: 300px; }
.legend { display:flex; flex-wrap:wrap; gap:12px; margin-top:12px; }
.legend .item { display:flex; align-items:center; gap:6px; color: var(--text-2); font-size:12px; }
.legend .swatch { width:11px; height:11px; border-radius:3px; }

/* Clickable legend: clicking an entry drops that series from the chart. Opacity
   rather than hiding the row, so the chart never reflows under the pointer and
   the entry stays there to click back on. */
.legend .item.click { cursor:pointer; user-select:none; }
.legend .item.click:hover { color: var(--text-1); }
.legend .item.click.off { opacity:.35; }

/* The booking-window figure sits inside the card's h3 so it inherits that font
   exactly; only colour and weight set it apart as the control it is. */
/* Filter bar (price changes). Fields sit on one row on a wide screen and stack
   on a narrow one; the multi-selects keep a fixed height so the row does not
   jump as options are chosen. */
.filters { display:flex; flex-wrap:wrap; gap:18px; align-items:flex-start;
           background:var(--surface-1); border:1px solid var(--border);
           border-radius:12px; padding:14px 16px; margin-bottom:14px; }
.filters .field { display:flex; flex-direction:column; gap:6px; }
.filters label { font-size:12px; font-weight:600; color:var(--text-2); }
.filters .range { display:flex; align-items:center; gap:8px; }
.filters .range .to { font-size:12px; color:var(--text-3); }
.filters input[type=date], .filters select {
  background:var(--surface-2, var(--surface-1)); color:var(--text-1);
  border:1px solid var(--border); border-radius:8px; padding:7px 9px; font:inherit; font-size:13px; }
.filters .sel { font-weight:600; color:var(--accent); font-size:11.5px; }
.filters input[type=date]:focus, .filters select:focus {
  outline:none; border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent); }
.filters .actions { justify-content:flex-end; gap:10px; }
.filters .check { display:flex; align-items:center; gap:6px; font-weight:500; color:var(--text-2); }
.filters button { background:var(--accent); color:#fff; border:1px solid transparent;
  border-radius:8px; padding:8px 16px; font:inherit; font-weight:600; cursor:pointer; }
.filters button:hover { filter:brightness(1.08); }
.filters .reset { font-size:12.5px; color:var(--text-3); align-self:center; }

/* Checkbox picker — replaces <select multiple>, which renders an OS listbox with
   a system scrollbar and a grey selection colour that ignores the theme. */
/* Collapsed dropdown. The panel floats so opening it never reflows the filter
   bar or pushes the table down the page. */
.picker { position:relative; width:268px; }
.picker > summary { list-style:none; cursor:pointer; display:flex; align-items:center;
  gap:8px; padding:7px 10px; border:1px solid var(--border); border-radius:8px;
  background:var(--surface-1); color:var(--text-1); font-size:13px; }
.picker > summary::-webkit-details-marker { display:none; }
.picker > summary:hover { border-color:var(--accent); }
.picker[open] > summary { border-color:var(--accent); }
.picker .ptitle { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.picker.has .ptitle { font-weight:600; color:var(--accent); }
.picker .pcaret { color:var(--text-3); font-size:10px; }
.picker[open] .pcaret { transform:rotate(180deg); }
.picker .ppanel { position:absolute; z-index:30; top:calc(100% + 6px); left:0; right:0;
  border:1px solid var(--border); border-radius:10px; background:var(--surface-1);
  box-shadow:var(--shadow); overflow:hidden; }
.picker .psearch { width:100%; border:0; border-bottom:1px solid var(--border);
  background:transparent; color:var(--text-1); font:inherit; font-size:12.5px;
  padding:8px 10px; }
.picker .psearch:focus { outline:none; background:color-mix(in oklab, var(--accent) 6%, transparent); }
.picker .plist { max-height:168px; overflow-y:auto; padding:4px; }
.picker .opt { display:flex; align-items:center; gap:8px; padding:5px 8px;
  border-radius:6px; cursor:pointer; font-size:13px; color:var(--text-1); }
.picker .opt:hover { background:var(--surface-2); }
.picker .opt.on { background:color-mix(in oklab, var(--accent) 13%, transparent);
                  font-weight:600; }
.picker .opt input { accent-color:var(--accent); margin:0; flex:none; }
.picker .opt .lbl { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.picker .opt .n { margin-left:auto; font-size:11px; color:var(--text-3); flex:none; }
.picker .pfoot { border-top:1px solid var(--border); padding:5px 8px; text-align:right; }
.picker .pclear { background:none; border:0; color:var(--text-3); font:inherit;
  font-size:11.5px; padding:2px 4px; cursor:pointer; }
.picker .pclear:hover { color:var(--accent); text-decoration:underline; }

/* Slim, theme-aware scrollbar so the picker does not show a system one. */
.picker .plist { scrollbar-width:thin; scrollbar-color:var(--border) transparent; }
.picker .plist::-webkit-scrollbar { width:8px; }
.picker .plist::-webkit-scrollbar-track { background:transparent; }
.picker .plist::-webkit-scrollbar-thumb { background:var(--border); border-radius:8px; }
.picker .plist::-webkit-scrollbar-thumb:hover { background:var(--text-3); }

/* --- Category drill-down ------------------------------------------------- */
.catopen { background:none; border:0; padding:0; font:inherit; font-weight:700;
  color:var(--text-1); cursor:pointer; display:flex; align-items:center; gap:7px; }
.catopen:hover { color:var(--accent); }
.catopen .caret { color:var(--text-3); font-size:11px; width:10px; }
.catdrill > td { background:var(--surface-2); padding:0 !important; }
.drillbox { padding:14px 16px; }
.drillhead { display:flex; justify-content:space-between; align-items:baseline;
             gap:16px; margin-bottom:10px; font-size:13px; color:var(--text-2); }
.drilltable { width:100%; border-collapse:collapse; font-size:13px; }
.drilltable th { text-align:left; font-size:11px; letter-spacing:.04em;
  text-transform:uppercase; color:var(--text-3); padding:6px 10px; font-weight:600; }
.drilltable td { padding:7px 10px; border-top:1px solid var(--border); }
.drilltable th.num, .drilltable td.num { text-align:right; }
.booklink { font-size:12.5px; font-weight:600; white-space:nowrap; }

/* --- Category extended view ---------------------------------------------- */
.minihead { font-size:12px; font-weight:600; color:var(--text-2); margin-bottom:6px; }
.minihead strong { color:var(--text-1); }
.kpiline { margin-bottom:22px; }
.kpiline .label { font-size:12px; font-weight:600; color:var(--text-2); }
.kpiline .big { font-size:34px; font-weight:700; letter-spacing:-.02em; line-height:1.15; }
.kpiline .sub { font-size:12.5px; color:var(--text-3); }

/* One dimension, so one axis. The bar IS the min..max range; the mark is the
   median. A y axis here would imply a distribution shape we do not measure. */
.spread { margin-bottom:20px; }
.spreadhead { display:flex; justify-content:space-between; align-items:baseline;
              margin-bottom:7px; }
.spreadhead .t { font-size:12px; font-weight:600; color:var(--text-2); }
.spreadhead .med { font-size:17px; font-weight:700; }
.spread .track { position:relative; height:10px; border-radius:6px;
  background:linear-gradient(90deg,
    color-mix(in oklab, var(--accent) 22%, transparent),
    color-mix(in oklab, var(--accent) 55%, transparent)); }
.spread .marker { position:absolute; top:-4px; width:3px; height:18px;
  border-radius:2px; background:var(--s4); transform:translateX(-1.5px);
  box-shadow:0 0 0 2px color-mix(in oklab, var(--surface-1) 70%, transparent); }
.spread .ends { display:flex; justify-content:space-between;
  font-size:11.5px; color:var(--text-3); margin-top:5px; }

.grainpick { display:flex; gap:4px; }
.grainpick button { width:28px; height:26px; border-radius:7px; cursor:pointer;
  border:1px solid var(--border); background:var(--surface-1);
  color:var(--text-2); font:inherit; font-size:12px; font-weight:700; }
.grainpick button:hover { color:var(--accent); border-color:var(--accent); }
.grainpick button.on { background:var(--accent); border-color:var(--accent); color:#fff; }

.excl { display:flex; align-items:center; gap:10px; }
.excl .sel { font-size:11.5px; font-weight:600; color:var(--accent); }
.excl button { background:var(--accent); color:#fff; border:1px solid transparent;
  border-radius:8px; padding:7px 14px; font:inherit; font-size:13px;
  font-weight:600; cursor:pointer; white-space:nowrap; }
.excl button:hover { filter:brightness(1.08); }
th.tick, td.tick { width:34px; text-align:center; }
td.tick input { accent-color:var(--accent); }

/* --- Head-to-head inside one category ------------------------------------ */
a.catlink { color:inherit; display:inline-flex; align-items:center; gap:6px; }
a.catlink .go { color:var(--text-3); font-size:12px; }
a.catlink:hover { color:var(--accent); }
a.catlink:hover .go { color:var(--accent); }

.matchpick { display:flex; align-items:center; gap:10px; }
.matchpick .lbl { font-size:12px; font-weight:600; color:var(--text-2); }
.matchpick .seg { display:flex; border:1px solid var(--border); border-radius:8px; overflow:hidden; }
.matchpick .seg button { border:0; background:var(--surface-1); color:var(--text-2);
  font:inherit; font-size:12.5px; font-weight:600; padding:6px 13px; cursor:pointer; }
.matchpick .seg button + button { border-left:1px solid var(--border); }
.matchpick .seg button:hover { color:var(--accent); }
.matchpick .seg button.on { background:var(--accent); color:#fff; }
.matchpick .tol { display:flex; align-items:center; gap:3px; font-size:12.5px; color:var(--text-2); }
.matchpick .tol input { width:52px; background:var(--surface-1); color:var(--text-1);
  border:1px solid var(--border); border-radius:7px; padding:5px 6px; font:inherit; font-size:12.5px; }
.matchpick .tol .unit { color:var(--text-3); }
.matchpick .tagsonly { display:flex; align-items:center; gap:6px; font-size:12.5px;
  color:var(--text-2); white-space:nowrap; cursor:pointer; }
.matchpick .tagsonly input { accent-color:var(--accent); margin:0; }
.schedmode button { border:0; background:var(--surface-1); color:var(--text-2);
  font:inherit; font-size:12.5px; font-weight:600; padding:6px 13px; cursor:pointer; }
.schedmode { border:1px solid var(--border); border-radius:8px; overflow:hidden; }
.schedmode button + button { border-left:1px solid var(--border); }
.schedmode button:hover { color:var(--accent); }
.schedmode button.on { background:var(--accent); color:#fff; }
.matchpick .apply { background:var(--accent); color:#fff; border:1px solid transparent;
  border-radius:8px; padding:6px 13px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }

/* A vertical rule where one metric block ends and the next begins, so ten numeric
   columns still read as three groups. */
#pairTable th.sep, #pairTable td.sep { border-left:1px solid var(--border); }
#pairTable th small { display:block; font-weight:500; font-size:10.5px;
  text-transform:none; letter-spacing:0; color:var(--text-3); margin-top:2px; }
/* Continuation rows: hairline instead of a full rule, so a group of three reads
   as one block rather than three unrelated products. */
#pairTable tr.grouped > td { border-top-color:color-mix(in oklab, var(--border) 45%, transparent); }
#pairTable tr.nomatch { background:color-mix(in oklab, var(--s4) 7%, transparent); }
#pairTable .none { color:var(--text-3); font-style:italic; font-size:12.5px; }

/* A heading that is also a link should not look like body copy turned blue. */
h3 a.plain { color:inherit; }
h3 a.plain:hover { color:var(--accent); text-decoration:underline; }

.bwlink { color: var(--accent); font-weight:700; cursor:pointer; }
.bwlink:hover, .bwlink:focus-visible { text-decoration: underline; }
.bwlink.on { text-decoration: underline; }

/* Tables */
.toolbar { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin-bottom:14px; }
.toolbar input[type=search], .toolbar select {
  background: var(--surface-1); color: var(--text-1); border:1px solid var(--border);
  border-radius:9px; padding:8px 11px; font-size:13px; min-width:150px;
}
.toolbar input[type=search]{ min-width: 240px; }
.count { color: var(--text-3); font-size:13px; margin-left:auto; }
table { width:100%; border-collapse: collapse; font-size:13px; }
thead th {
  text-align:left; color: var(--text-3); font-weight:600; font-size:11.5px;
  text-transform:uppercase; letter-spacing:.03em; padding:10px 12px;
  border-bottom:1px solid var(--border); position: sticky; top:0; background: var(--surface-1); cursor: default;
}
tbody td { padding:11px 12px; border-bottom:1px solid var(--border); vertical-align: middle; }
tbody tr:hover { background: var(--surface-2); }
.num { text-align:right; font-variant-numeric: tabular-nums; }

/* Sortable numeric columns (static/tablesort.js). The caret is always present on
   a sortable header, faint until it is the active column — a control that only
   appears on hover is a control nobody finds. */
thead th.sortable { cursor:pointer; user-select:none; }
thead th.sortable::after {
  content:'\2195'; margin-left:6px; font-size:10px; opacity:.3;
  display:inline-block; vertical-align:baseline; }
thead th.sortable:hover { color: var(--text-2); }
thead th.sortable:hover::after { opacity:.65; }
thead th.sortable:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
thead th.sortable[aria-sort="descending"],
thead th.sortable[aria-sort="ascending"] { color: var(--text-1); }
thead th.sortable[aria-sort="descending"]::after { content:'\2193'; opacity:1; color: var(--accent); }
thead th.sortable[aria-sort="ascending"]::after  { content:'\2191'; opacity:1; color: var(--accent); }
.tablecard { background: var(--surface-1); border:1px solid var(--border); border-radius:14px; box-shadow: var(--shadow); overflow:hidden; }
.tablecard .scroll { overflow-x:auto; max-height: 72vh; overflow-y:auto; }

/* Chips / badges */
.chip { display:inline-block; padding:2px 8px; border-radius:999px; font-size:11.5px; font-weight:600; border:1px solid transparent; }
.chip.dom { background: var(--surface-2); color: var(--text-2); }
/* Minimum party size — flags a listing you cannot buy a single seat on. */
.chip.group { background: color-mix(in oklab, var(--warn) 16%, var(--surface-1)); color: var(--text-1); }
.badge { display:inline-flex; align-items:center; gap:5px; font-size:12px; font-weight:600; }
.badge::before { content:""; width:8px; height:8px; border-radius:50%; }
.badge.available::before { background: var(--good); }
.badge.sold_out::before, .badge.booked::before { background: var(--bad); }
.badge.limited::before, .badge.price_change::before { background: var(--warn); }
.badge.released::before, .badge.reopened::before { background: var(--s1); }
.season { color: var(--text-2); font-size:12px; }
.muted { color: var(--text-3); }
.price { font-weight:700; font-variant-numeric: tabular-nums; }
.extlink { font-size:12px; }

/* ------------------------------------------------------------------ market UI */

/* Nav region picker */
.regionpick { display:flex; align-items:center; gap:8px; font-size:12px; color: var(--text-3); }
.regionpick select, .pickfield select {
  background: var(--surface-2); color: var(--text-1); border:1px solid var(--border);
  border-radius:8px; padding:6px 9px; font-size:13px;
}
.pickfield { display:flex; align-items:center; gap:8px; }
.pickfield > span { font-size:12px; color: var(--text-3); font-weight:600;
  text-transform:uppercase; letter-spacing:.04em; }

/* Page header date stamp */
.stamp {
  font-size:12px; font-weight:600; color: var(--text-3); background: var(--surface-2);
  border:1px solid var(--border); border-radius:999px; padding:3px 10px;
  vertical-align:middle; margin-left:8px; letter-spacing:.02em;
}

/* Hero KPI emphasis */
.kpi.hero { background: linear-gradient(180deg, var(--surface-1), var(--surface-2)); }
.kpi.hero .value { font-size:38px; }
.kpis.two { grid-template-columns: repeat(auto-fit, minmax(300px,1fr)); }
.kpi.me   { border-left:3px solid var(--s1); }
.kpi.them { border-left:3px solid var(--s2); }
.profgrid { display:grid; grid-template-columns: repeat(3, 1fr); gap:12px 16px; margin-top:12px; }
.profgrid .k { display:block; color: var(--text-3); font-size:11px; text-transform:uppercase;
  letter-spacing:.03em; font-weight:600; }
.profgrid .v { display:block; font-size:17px; font-weight:700; margin-top:2px;
  font-variant-numeric: tabular-nums; }

/* Direction of change — paired with an explicit +/- sign, never colour alone */
.trend { font-weight:700; font-variant-numeric: tabular-nums; }
.trend.up   { color: var(--s1); }
.trend.down { color: var(--s2); }
.up { color: var(--s1); font-weight:700; }
.down { color: var(--s2); font-weight:700; }

/* Card header with an action on the right */
.cardhead { display:flex; align-items:flex-start; gap:16px; margin-bottom:10px; }
.cardhead > div:first-child { flex:1; }
.cardhead.pad { padding:18px 18px 0; }
.cardhead h3 { margin:0 0 2px; font-size:15px; }
.more { font-size:12.5px; font-weight:600; white-space:nowrap; }

/* Secondary line inside a table cell */
.sub2 { color: var(--text-3); font-size:11.5px; margin-top:3px; }

/* Toggle pills */
.pill {
  display:inline-block; padding:6px 12px; border-radius:999px; font-size:12.5px;
  font-weight:600; border:1px solid var(--border); color: var(--text-2);
  background: var(--surface-1);
}
.pill:hover { text-decoration:none; background: var(--surface-2); }
.pill.on { background: var(--accent); border-color: var(--accent); color:#fff; }

/* Compare tabs */
.comparebar { gap:16px; }
.tabs { display:flex; gap:4px; background: var(--surface-2); padding:3px; border-radius:10px; }
.tab { padding:7px 14px; border-radius:8px; font-size:13px; font-weight:600; color: var(--text-2); }
.tab:hover { text-decoration:none; color: var(--text-1); }
.tab.on { background: var(--surface-1); color: var(--text-1); box-shadow: var(--shadow); }

/* Overlap chips */
.chip.match     { background: color-mix(in oklab, var(--s3) 16%, var(--surface-1)); color: var(--text-1); }
.chip.only-me   { background: color-mix(in oklab, var(--s1) 16%, var(--surface-1)); color: var(--text-1); }
.chip.only-them { background: color-mix(in oklab, var(--s2) 16%, var(--surface-1)); color: var(--text-1); }
.chip.new       { background: var(--surface-2); color: var(--text-2); }

/* Table scroll region inside a plain card */
.card .scroll { overflow-x:auto; max-height: 460px; overflow-y:auto; }

/* Calendar heatmap — diverging: ahead (blue) / level (surface) / behind (orange) */
.calwrap { margin-top:6px; }
.cal { display:flex; flex-wrap:wrap; gap:20px; }
.calmonth { min-width:210px; }
.calmonth-h { font-size:12.5px; font-weight:700; color: var(--text-2); margin-bottom:8px; }
.caldow, .caldays { display:grid; grid-template-columns: repeat(7, 26px); gap:3px; }
.caldow span { text-align:center; font-size:10px; color: var(--text-3); font-weight:600; }
.calcell {
  height:26px; display:flex; align-items:center; justify-content:center;
  border-radius:5px; font-size:11px; font-variant-numeric: tabular-nums;
  color: var(--text-2); border:1px solid var(--border); cursor:default;
}
.calcell:hover { outline:2px solid var(--accent); outline-offset:1px; }
.calcell.ahead { color: var(--text-1); font-weight:600; }
.callegend { margin-top:16px; }
.callegend .swatch { border:1px solid var(--border); }

/* Table-view disclosure under a chart (accessibility fallback) */
.tableview { margin-top:14px; border-top:1px solid var(--border); padding-top:12px; }
.tableview summary { cursor:pointer; font-size:12.5px; font-weight:600; color: var(--text-2); }
.tableview summary:hover { color: var(--text-1); }

/* Explanatory note under a page */
.footnote {
  color: var(--text-3); font-size:12.5px; line-height:1.65; margin:18px 0 0;
  padding:14px 16px; background: var(--surface-1); border:1px solid var(--border);
  border-radius:12px;
}
.footnote strong { color: var(--text-2); }

/* Inline caveat under a page title */
.notice {
  margin-top:10px; padding:10px 14px; border-radius:10px; font-size:12.5px;
  color: var(--text-2); background: color-mix(in oklab, var(--warn) 12%, var(--surface-1));
  border:1px solid color-mix(in oklab, var(--warn) 32%, var(--border));
}

/* Footer */
.foot {
  max-width:1240px; margin:8px auto 40px; padding:0 24px;
  color: var(--text-3); font-size:12px;
}

/* Detail */
.detailhead { display:flex; flex-wrap:wrap; gap:20px; align-items:flex-start; margin-bottom:20px; }
.detailhead .facts { display:flex; flex-wrap:wrap; gap:22px; margin-top:10px; }
.detailhead .facts div .k { color: var(--text-3); font-size:11.5px; text-transform:uppercase; letter-spacing:.03em; }
.detailhead .facts div .v { font-size:15px; font-weight:600; margin-top:2px; }
.backlink { color: var(--text-2); font-size:13px; }

/* Activity detail — upcoming availability header (date window + view switch) */
.availhead { display:flex; flex-wrap:wrap; gap:12px; align-items:flex-end;
             justify-content:space-between; padding:16px 18px 10px; }
.availtools { display:flex; flex-wrap:wrap; gap:10px; align-items:center; }
.daterange { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
.daterange label { display:flex; gap:6px; align-items:center;
                   font-size:12px; font-weight:600; color: var(--text-3); }
.daterange input[type="date"] {
  font: inherit; font-size:13px; color: var(--text-1);
  background: var(--surface-2); border:1px solid var(--border);
  border-radius:8px; padding:6px 8px; }
.daterange input[type="date"]:focus-visible { outline:2px solid var(--s1); outline-offset:1px; }
.daterange button {
  font: inherit; font-size:13px; font-weight:600; cursor:pointer;
  color: var(--text-1); background: var(--surface-2);
  border:1px solid var(--border); border-radius:8px; padding:6px 12px; }
.daterange button:hover { background: var(--surface-1); }

/* .tab is styled for anchors; the view switch uses real buttons. */
button.tab { border:none; background:transparent; font-family:inherit; cursor:pointer; }

/* --------------------------------------------------------------- login page */
/* Standalone screen — no nav, no footer, so it centres in the viewport
   rather than sitting under app chrome the visitor has no access to yet. */
.loginbody { min-height:100vh; display:flex; }
.loginwrap { margin:auto; width:100%; max-width:380px; padding:24px; }
.logincard {
  background: var(--surface-1); border:1px solid var(--border); border-radius:14px;
  padding:26px 24px 24px; box-shadow: var(--shadow);
  display:flex; flex-direction:column; gap:14px;
}
.logincard .brand { font-weight:700; font-size:15px; display:flex; align-items:center; gap:9px; }
.logincard .brand .dot { width:10px; height:10px; border-radius:3px; background:var(--accent); }
.loginhint { margin:-6px 0 2px; color:var(--text-3); font-size:12.5px; line-height:1.45; }
.loginfield { display:flex; flex-direction:column; gap:5px; }
.loginfield span { font-size:12px; font-weight:600; color:var(--text-2); }
.loginfield input {
  font:inherit; color:var(--text-1); background:var(--surface-0);
  border:1px solid var(--border); border-radius:9px; padding:9px 11px; width:100%;
}
.loginfield input:focus {
  outline:none; border-color:var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
}
.loginbtn {
  margin-top:4px; font:inherit; font-weight:600; cursor:pointer;
  background:var(--accent); color:#fff; border:1px solid transparent;
  border-radius:9px; padding:10px 14px; width:100%;
}
.loginbtn:hover { filter:brightness(1.06); }
.loginbtn:focus-visible { outline:2px solid var(--text-1); outline-offset:2px; }
/* Failure is stated in words as well as colour — red alone is not a message. */
.loginerr {
  background: color-mix(in oklab, var(--bad) 12%, var(--surface-1));
  border:1px solid color-mix(in oklab, var(--bad) 40%, var(--surface-1));
  color:var(--text-1); border-radius:9px; padding:9px 11px; font-size:12.5px; line-height:1.45;
}
.loginerr code { background:var(--surface-2); border-radius:4px; padding:1px 5px; font-size:11.5px; }
.loginfoot { text-align:center; color:var(--text-3); font-size:11.5px; margin:14px 0 0; }

/* Sign-out sits with the theme toggle at the far end of the nav. */
.navuser { color:var(--text-3); font-size:12px; margin-right:2px; }
.logoutform { display:inline; }

/* Browse: the all-future availability count is off by default — it reaches years
   out and is rarely what a coordinator is deciding on. Hidden with CSS rather
   than removed so toggling it needs no refetch and it returns to the same place. */
.allfuture { display: none; }
body.show-allfuture .allfuture { display: table-cell; }

/* Price-change badge on the product detail header. A link, not a label: it jumps
   to the history chart that explains it. */
.pricebadge { display:inline-flex; align-items:center; gap:6px; margin-left:8px;
  padding:2px 9px; border-radius:999px; font-size:11.5px; font-weight:600;
  background:color-mix(in oklab, var(--s4) 18%, transparent);
  color:var(--text-1); vertical-align:middle; }
.pricebadge:hover { text-decoration:none; background:color-mix(in oklab, var(--s4) 30%, transparent); }
.pricebadge .d { color:var(--text-2); font-weight:700; }
.pricebadge.flat { background:var(--surface-2); color:var(--text-2); font-weight:500; }
.pricebadge.flat:hover { background:var(--border); }
.pricebadge.flat .d { color:var(--text-3); font-weight:600; }

/* Operator column on the price-change log. The pill wrapped to two lines on long
   agency names and doubled every row's height; this is the same information as
   plain text, clipped to one line with the full name on hover. */
.opcell { max-width:190px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  color:var(--text-2); font-weight:600; font-size:12.5px; }
.nowrap { white-space:nowrap; }

/* ========================================================================== *
 * Portal (client) and admin portal.
 *
 * Everything below reuses the tokens defined at the top of this file rather
 * than naming a colour, so these screens follow the light/dark toggle for free.
 * The first version of the portal shipped with hardcoded #0f172a slate inline
 * in its templates, which meant it stayed dark when the rest of the dashboard
 * went light and ignored the validated palette entirely.
 * ========================================================================== */
.navorg { display:inline-block; margin-left:6px; padding:1px 7px; border-radius:999px;
  background: var(--surface-2); color: var(--text-2); font-weight:600; }

.portal { display:grid; grid-template-columns: 208px 1fr; gap:22px; align-items:start; }
@media (max-width: 820px) { .portal { grid-template-columns: 1fr; } }

.sidenav { background: var(--surface-1); border:1px solid var(--border);
  border-radius:14px; padding:10px; position:sticky; top:16px; }
.sidenav a { display:block; padding:9px 11px; border-radius:9px; font-size:13.5px;
  color: var(--text-2); text-decoration:none; font-weight:600; }
.sidenav a:hover { background: var(--surface-2); color: var(--text-1); }
.sidenav a.on { background: var(--surface-2); color: var(--text-1);
  box-shadow: inset 3px 0 0 var(--accent, var(--s1)); }
.sidenav .grouphead { padding:10px 11px 4px; font-size:11px; font-weight:700;
  text-transform:uppercase; letter-spacing:.05em; color: var(--text-3); }

.panel { background: var(--surface-1); border:1px solid var(--border);
  border-radius:14px; padding:18px 20px; margin-bottom:18px; }
.panel > h2 { font-size:16px; margin:0 0 4px; }
.panel > .lede { margin:0 0 16px; color: var(--text-2); font-size:13px; }

/* Quota meter. Colour is a threshold read, not decoration: amber from 80%,
   red at the ceiling, because "am I about to be cut off" is the only question
   this bar exists to answer. */
.meter { height:8px; border-radius:999px; background: var(--surface-2);
  overflow:hidden; margin-top:9px; }
.meter > span { display:block; height:100%; background: var(--good); border-radius:999px; }
.meter.warn > span { background: var(--warn); }
.meter.over > span { background: var(--bad); }

.tokenrow { display:flex; align-items:center; justify-content:space-between;
  gap:14px; padding:12px 0; border-bottom:1px solid var(--border); }
.tokenrow:last-child { border-bottom:0; }
.tokenrow .meta { color: var(--text-3); font-size:12px; margin-top:3px; }
code.mono, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size:12.5px; }

/* The one-time token reveal. Deliberately loud — it is the only moment the
   value exists, and a customer who scrolls past it has to mint a new one. */
.reveal { border:1px solid var(--good); border-radius:12px; padding:16px 18px;
  margin-bottom:18px; background: color-mix(in oklab, var(--good) 8%, var(--surface-1)); }
.reveal h3 { margin:0 0 6px; font-size:14px; }
.reveal .value { display:block; margin:10px 0; padding:12px 14px; border-radius:9px;
  background: var(--surface-0, var(--surface-2)); border:1px solid var(--border);
  word-break:break-all; }

.form { display:grid; gap:12px; max-width:520px; }
.form.wide { max-width:none; grid-template-columns: repeat(auto-fit, minmax(210px,1fr)); }
.form label { display:block; font-size:12px; font-weight:600; color: var(--text-2);
  margin-bottom:5px; }
.form input[type=text], .form input[type=email], .form input[type=number],
.form input[type=date], .form select, .form textarea {
  width:100%; padding:9px 11px; border-radius:9px; border:1px solid var(--border);
  background: var(--surface-2); color: var(--text-1); font:inherit; font-size:13px; }
.form .scopes { display:flex; flex-wrap:wrap; gap:10px; }
.form .scopes label { display:flex; align-items:center; gap:6px; font-weight:500;
  margin:0; color: var(--text-1); font-size:13px; }

/* Region grant picker on the admin customer page. Spans every column of the
   auto-fit form grid — sixty regions in a 210px column would be a scroll bar
   with a checkbox in it. */
.form .grantrow { grid-column: 1 / -1; }
.form .grantgrid { display:grid; gap:2px 14px; max-height:210px; overflow-y:auto;
  grid-template-columns: repeat(auto-fill, minmax(180px,1fr));
  border:1px solid var(--border); border-radius:9px; padding:10px 12px;
  background: var(--surface-2); }
.form .grantgrid label { display:flex; align-items:center; gap:7px; margin:0;
  font-weight:500; font-size:13px; color: var(--text-1); padding:2px 0; }
.form .grantgrid label .muted { margin-left:auto; font-size:11.5px; }

.btn { border:1px solid var(--border); background: var(--surface-2); color: var(--text-1);
  border-radius:9px; padding:9px 14px; font:inherit; font-size:13px; font-weight:600;
  cursor:pointer; }
.btn:hover { border-color: var(--text-3); }
.btn.primary { background: var(--accent, var(--s1)); border-color: transparent; color:#fff; }
.btn.danger { color: var(--bad); }
.btn.sm { padding:5px 10px; font-size:12px; }

.chip.ok      { background: color-mix(in oklab, var(--good) 16%, var(--surface-1)); color: var(--text-1); }
.chip.warnish { background: color-mix(in oklab, var(--warn) 18%, var(--surface-1)); color: var(--text-1); }
.chip.off     { background: var(--surface-2); color: var(--text-3); }
.chip.bad     { background: color-mix(in oklab, var(--bad) 16%, var(--surface-1)); color: var(--text-1); }

.plancards { display:grid; gap:14px; grid-template-columns: repeat(auto-fit, minmax(230px,1fr)); }
.plancard { background: var(--surface-1); border:1px solid var(--border);
  border-radius:14px; padding:16px 18px; }
.plancard.current { border-color: var(--accent, var(--s1)); box-shadow:0 0 0 1px var(--accent, var(--s1)); }
.plancard .price { font-size:24px; font-weight:700; margin:2px 0 8px; }
.plancard ul { margin:10px 0 0; padding-left:18px; color: var(--text-2); font-size:12.5px; }

/* Setup snippet. pre wraps rather than scrolls: a customer copies this whole
   block into a config file, and a horizontally clipped JSON body is the classic
   way to paste something that does not parse. */
pre.snippet { background: var(--surface-2); border:1px solid var(--border);
  border-radius:10px; padding:14px 16px; overflow-x:auto; font-size:12.5px;
  line-height:1.55; margin:10px 0; }
.copybtn { float:right; }

.navuser a { color: inherit; text-decoration: none; border-bottom: 1px dotted var(--border); }
.navuser a:hover { color: var(--text-1); }
