/* ==========================================================================
   Anova Construction — application styles
   --------------------------------------------------------------------------
   The Airbnb idiom, applied to a construction back office.

   The rules that hold the whole thing together:

     1. White ground. Separation is space and hairlines, never a grey canvas.
     2. Coral is the primary action and nothing else. Not a heading, not a
        chart series, not an active tab.
     3. Corners are soft and consistent: 12px on panels, 16px on media.
     4. Type is tight at the top and loose in the body.
     5. Nothing floats unless it genuinely floats — the search pill, a
        dropdown, a sticky bar.

   Layout is containerless and fluid: a fixed navbar, a scrolling category
   rail beneath it, and content that runs to a wide measure with a generous
   gutter rather than being boxed into a fixed-width container.
   ========================================================================== */

@import url("tokens.css");

/* ==========================================================================
   Reset and base
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--chrome-height) + var(--space-4));
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--ink);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6, p, figure { margin: 0; }
h1, h2, h3, h4 { letter-spacing: var(--tracking-tight); }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

/* Links are ink with an underline, the way Airbnb sets them. Coral is an
   action you press, not a word you read. */
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}

/* Money and quantities line up down a column. */
.num, td.num, .metric-value, .amount, .listing__price {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Components below set display on themselves, which would otherwise beat the
   hidden attribute on specificity. Everything that toggles visibility in this
   app does it with [hidden], so it has to win. */
[hidden] { display: none !important; }

/* Icons default to the size of the text they sit beside. Components that want
   a specific size say so, and win on specificity. */
.icon { width: 1.15em; height: 1.15em; flex-shrink: 0; }

/* ==========================================================================
   Shell
   --------------------------------------------------------------------------
   No sidebar. A fixed navbar, a category rail under it, and the page below.
   ========================================================================== */

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

.page {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-8) var(--page-gutter) var(--space-16);
  flex: 1;
}

/* ==========================================================================
   Navbar
   ========================================================================== */

.navbar {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--surface);
  border-bottom: 1px solid var(--rule-soft);
}

.navbar__inner {
  max-width: var(--content-max);
  margin: 0 auto;
  height: var(--navbar-height);
  padding: 0 var(--page-gutter);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-4);
}

/* ---- Brand ---------------------------------------------------------------- */

.navbar__brand { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.navbar__brand:hover { text-decoration: none; }

.brandmark {
  width: 34px; height: 34px;
  flex-shrink: 0;
  display: grid; place-items: center;
  border-radius: var(--radius-md);
  background: var(--coral);
  color: #fff;
  font-weight: var(--weight-bold);
  font-size: var(--text-md);
  letter-spacing: -0.03em;
}

.brandmark__text { min-width: 0; line-height: 1.1; }
.brandmark__name {
  display: block;
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  color: var(--coral);
}
.brandmark__sub {
  display: block;
  font-size: var(--text-2xs);
  color: var(--muted);
  letter-spacing: 0.02em;
}

/* ---- Compound search pill ------------------------------------------------
   Collapsed it is a single pill with the current query summarised. Clicking
   it expands the segments, which is the interaction Airbnb's header is built
   around: one control that is small until you need it. */

.searchpill {
  justify-self: center;
  display: flex;
  align-items: center;
  height: 48px;
  padding: 0 var(--space-2) 0 var(--space-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow: var(--shadow-pill);
  transition: box-shadow var(--transition), background var(--transition);
  min-width: 0;
}
.searchpill:hover { box-shadow: var(--shadow-lg); }

.searchpill__seg {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-1) var(--space-5);
  border-radius: var(--radius-pill);
  min-width: 0;
  cursor: text;
  transition: background var(--transition);
}
.searchpill__seg:hover { background: var(--surface-sunken); }
.searchpill__seg:focus-within { background: var(--surface-sunken); }

.searchpill__label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  color: var(--ink);
  letter-spacing: 0.01em;
}

.searchpill__seg input,
.searchpill__seg select {
  border: 0;
  padding: 0;
  background: transparent;
  font-size: var(--text-base);
  color: var(--ink);
  width: 100%;
  min-width: 0;
  appearance: none;
}
.searchpill__seg input::placeholder { color: var(--muted); }
.searchpill__seg input:focus, .searchpill__seg select:focus { outline: none; box-shadow: none; }

.searchpill__divider {
  width: 1px;
  height: 26px;
  background: var(--rule);
  flex-shrink: 0;
}

.searchpill__go {
  width: 34px; height: 34px;
  flex-shrink: 0;
  display: grid; place-items: center;
  margin-left: var(--space-2);
  border: 0;
  border-radius: 50%;
  background: var(--coral);
  color: #fff;
  cursor: pointer;
  transition: background var(--transition), width var(--transition);
}
.searchpill__go:hover { background: var(--coral-pressed); }
.searchpill__go svg { width: 16px; height: 16px; }

/* Collapsed state: one segment, no dividers, tighter. */
.searchpill.is-collapsed .searchpill__seg--fold,
.searchpill.is-collapsed .searchpill__divider { display: none; }
.searchpill.is-collapsed .searchpill__label { display: none; }
.searchpill.is-collapsed .searchpill__seg { padding-block: 0; }

/* ---- Right cluster -------------------------------------------------------- */

.navbar__actions {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.navbar__link {
  display: none;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-pill);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  transition: background var(--transition);
}
.navbar__link:hover { background: var(--surface-sunken); text-decoration: none; }
@media (min-width: 1180px) { .navbar__link { display: block; } }

/* ---- Profile menu --------------------------------------------------------- */

.profile { position: relative; }

.profile__button {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: 44px;
  padding: 0 var(--space-2) 0 var(--space-4);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--surface);
  cursor: pointer;
  transition: box-shadow var(--transition);
}
.profile__button:hover { box-shadow: var(--shadow-md); }
.profile__button svg { width: 16px; height: 16px; color: var(--ink-soft); }

.avatar {
  width: 32px; height: 32px;
  flex-shrink: 0;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
}

.profile__dot {
  position: absolute;
  top: 4px; right: 6px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--coral);
  border: 2px solid var(--surface);
}

.profile__menu {
  position: absolute;
  top: calc(100% + var(--space-3));
  right: 0;
  width: 260px;
  padding: var(--space-2) 0;
  background: var(--surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 70;
}
.profile__menu[hidden] { display: none; }

.profile__head {
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-bottom: 1px solid var(--rule-soft);
  margin-bottom: var(--space-2);
}
.profile__name { font-weight: var(--weight-semibold); font-size: var(--text-base); }
.profile__role { font-size: var(--text-xs); color: var(--muted); margin-top: 2px; }

.profile__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-base);
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast);
}
.profile__item:hover { background: var(--surface-sunken); text-decoration: none; }
.profile__item svg { width: 16px; height: 16px; color: var(--muted); flex-shrink: 0; }
.profile__item--strong { font-weight: var(--weight-semibold); }
.profile__sep { height: 1px; background: var(--rule-soft); margin: var(--space-2) 0; }
.profile__count {
  margin-left: auto;
  min-width: 20px; height: 20px;
  padding: 0 6px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--coral);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
}

/* ==========================================================================
   Filter sub-bar
   --------------------------------------------------------------------------
   A horizontally scrollable icon rail carrying the sections this user may
   actually open, with a sticky Filters button pinned to the right.
   ========================================================================== */

.filterbar {
  position: sticky;
  top: var(--navbar-height);
  z-index: 50;
  background: var(--surface);
  border-bottom: 1px solid var(--rule-soft);
}

.filterbar__inner {
  max-width: var(--content-max);
  margin: 0 auto;
  height: var(--filterbar-height);
  padding: 0 var(--page-gutter);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
}

.rail {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
}

.rail__scroll {
  display: flex;
  align-items: stretch;
  gap: var(--space-6);
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding: var(--space-2) 0;
  mask-image: linear-gradient(to right, transparent 0, #000 24px,
                              #000 calc(100% - 24px), transparent 100%);
}
.rail__scroll::-webkit-scrollbar { display: none; }

/* The fade only belongs on the edge that actually has more behind it. */
.rail.is-at-start .rail__scroll { mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent 100%); }
.rail.is-at-end .rail__scroll { mask-image: linear-gradient(to right, transparent 0, #000 24px); }
.rail.is-at-start.is-at-end .rail__scroll { mask-image: none; }

.railitem {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding-bottom: var(--space-2);
  color: var(--muted);
  border-bottom: 2px solid transparent;
  opacity: 0.75;
  transition: opacity var(--transition), color var(--transition), border-color var(--transition);
  white-space: nowrap;
}
.railitem:hover {
  opacity: 1;
  color: var(--ink);
  text-decoration: none;
  border-bottom-color: var(--rule);
}
.railitem.is-active {
  opacity: 1;
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.railitem__icon { position: relative; }
.railitem__icon svg { width: 22px; height: 22px; stroke-width: 1.6; }

.railitem__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
}

.railitem__badge {
  position: absolute;
  top: -5px; right: -9px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--coral);
  color: #fff;
  font-size: 10px;
  font-weight: var(--weight-bold);
}

/* Rail arrows, shown only where the rail actually overflows. */
.rail__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 30px; height: 30px;
  display: none;
  place-items: center;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  color: var(--ink);
}
.rail__arrow:hover { box-shadow: var(--shadow-md); }
.rail__arrow svg { width: 14px; height: 14px; }
.rail__arrow--prev { left: -6px; }
.rail__arrow--next { right: -6px; }
.rail.is-overflowing .rail__arrow { display: grid; }
.rail.is-at-start .rail__arrow--prev,
.rail.is-at-end .rail__arrow--next { display: none; }

/* ---- Rail menus -------------------------------------------------------------
   A labelled group opens a panel rather than spilling its children onto the
   bar. The trigger is styled as a rail item so a menu and a destination read
   as the same kind of thing until you click one. */

.railmenu { position: relative; flex-shrink: 0; }

.railmenu__trigger {
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
}

.railmenu__caret {
  display: inline-flex;
  margin-left: 3px;
  vertical-align: middle;
  transition: transform var(--transition-fast);
}
.railmenu__caret svg { width: 11px; height: 11px; }
.railmenu.is-open .railmenu__caret { transform: rotate(180deg); }

.railmenu.is-open .railmenu__trigger { opacity: 1; color: var(--ink); }

/* Fixed, not absolute. The rail scrolls horizontally and carries a mask, and
   both of those clip an absolutely positioned child — the panel was being cut
   down to a sliver at the top of the bar. Its coordinates are set on open by
   the script, which also keeps it inside the viewport at either end. */
.railmenu__panel {
  position: fixed;
  z-index: 70;
  min-width: 232px;
  padding: var(--space-2);
  background: var(--surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

.railmenu__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  color: var(--ink);
  white-space: nowrap;
  transition: background var(--transition-fast);
}
.railmenu__item:hover { background: var(--surface-sunken); text-decoration: none; }
.railmenu__item.is-active { background: var(--surface-sunken); font-weight: var(--weight-semibold); }

.railmenu__icon { display: grid; place-items: center; color: var(--muted); flex-shrink: 0; }
.railmenu__icon svg { width: 17px; height: 17px; }
.railmenu__item.is-active .railmenu__icon { color: var(--ink); }

.railmenu__count {
  min-width: 20px; height: 20px;
  padding: 0 6px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--coral);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
}

/* ---- Filters button (sticky right) ---------------------------------------- */

.filterbar__actions { flex-shrink: 0; display: flex; align-items: center; gap: var(--space-3); }

.filters-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 46px;
  padding: 0 var(--space-4);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color var(--transition), box-shadow var(--transition);
}
.filters-button:hover { border-color: var(--ink); text-decoration: none; }
.filters-button svg { width: 15px; height: 15px; }
.filters-button__count {
  min-width: 20px; height: 20px;
  padding: 0 6px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--ink);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
}

/* ==========================================================================
   Mobile navigation drawer
   ========================================================================== */

.icon-button {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink);
  cursor: pointer;
  position: relative;
  transition: background var(--transition-fast);
}
.icon-button:hover { background: var(--surface-sunken); text-decoration: none; }
.icon-button svg { width: 18px; height: 18px; }

.navbar__menu { display: none; }

.drawer {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(320px, 86vw);
  z-index: 90;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  transform: translateX(-100%);
  transition: transform var(--transition);
  overflow-y: auto;
}
.app.is-drawer-open .drawer { transform: none; box-shadow: var(--shadow-lg); }

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--rule-soft);
  position: sticky;
  top: 0;
  background: var(--surface);
}

.drawer__nav { padding: var(--space-4) var(--space-3) var(--space-8); }

.scrim {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(0, 0, 0, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition);
}
.app.is-drawer-open .scrim { opacity: 1; pointer-events: auto; }

.nav-group + .nav-group { margin-top: var(--space-5); }

.nav-group__label {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--ink);
  transition: background var(--transition-fast);
}
.nav-link:hover { background: var(--surface-sunken); text-decoration: none; }
.nav-link.is-active { background: var(--surface-sunken); font-weight: var(--weight-semibold); }

.nav-link__icon { display: grid; place-items: center; flex-shrink: 0; color: var(--muted); }
.nav-link__icon svg { width: 18px; height: 18px; }
.nav-link.is-active .nav-link__icon { color: var(--ink); }

.nav-link__badge {
  margin-left: auto;
  min-width: 20px; height: 20px;
  padding: 0 6px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--coral);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
}

.notification-dot {
  position: absolute;
  top: 9px; right: 10px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--coral);
  border: 2px solid var(--surface);
}

/* ==========================================================================
   Page header
   ========================================================================== */

.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-bottom: var(--space-8);
}

.page-header__titles { min-width: 0; }

.page-title {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
  line-height: 1.15;
  color: var(--ink);
}

.page-subtitle {
  margin-top: var(--space-2);
  font-size: var(--text-md);
  color: var(--muted);
  max-width: 76ch;
}

.page-header__actions { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

.breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  font-size: var(--text-base);
  color: var(--muted);
}
.breadcrumb a { text-decoration: underline; }
.breadcrumb a:hover { color: var(--ink); }
.breadcrumb__sep { color: var(--subtle); }

/* ==========================================================================
   Grid
   --------------------------------------------------------------------------
   Twelve columns with a dense auto-flow. Tiles of different weights knit
   together without leaving holes.
   ========================================================================== */

.bento {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--bento-gap);
  grid-auto-flow: row dense;
  align-items: start;
}

/*
   Dashboard only. Sixty-odd other pages use .bento for ordinary page furniture
   where a card should be its own height, so equalising rows there would stretch
   short panels for no reason. On the dashboard the tiles are arranged into rows
   of like kind, and a row of figures that finishes level reads as one band
   rather than four unrelated cards.
*/
.bento--dash {
  align-items: stretch;
  grid-auto-flow: row;
}

.bento--dash > .card { display: flex; flex-direction: column; }
.bento--dash > .card > .card__body { display: flex; flex-direction: column; flex: 1; }

/* Cards in a row now finish level, which leaves the shorter ones with room at
   the bottom. Dropping the link into that room reads as a footer rather than as
   a card that ran out of content halfway down. */
.bento--dash > .card > .card__body > .btn { margin-top: auto; align-self: flex-start; }

.span-2  { grid-column: span 2; }
.span-3  { grid-column: span 3; }
.span-4  { grid-column: span 4; }
.span-5  { grid-column: span 5; }
.span-6  { grid-column: span 6; }
.span-7  { grid-column: span 7; }
.span-8  { grid-column: span 8; }
.span-9  { grid-column: span 9; }
.span-12 { grid-column: span 12; }

@media (max-width: 1280px) {
  .span-2, .span-3 { grid-column: span 4; }
  .span-5 { grid-column: span 6; }
  .span-7 { grid-column: span 6; }
  .span-9 { grid-column: span 12; }
}

@media (max-width: 900px) {
  .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8 { grid-column: span 6; }
}

@media (max-width: 640px) {
  .bento > * { grid-column: span 12 !important; }
}

/* ---- Split layout --------------------------------------------------------
   A scrolling content column beside a panel that stays put. Used on detail
   screens where the figure being discussed has to remain in view while the
   evidence under it is read. */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: var(--space-12);
  align-items: start;
}

.split__main { min-width: 0; display: grid; gap: var(--bento-gap); }

.split__aside {
  position: sticky;
  top: calc(var(--chrome-height) + var(--space-6));
  display: grid;
  gap: var(--space-4);
  min-width: 0;
}

@media (max-width: 1100px) {
  .split { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .split__aside { position: static; }
}

/* ==========================================================================
   Card
   ========================================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  overflow: hidden;
  min-width: 0;
}

a.card { display: block; transition: box-shadow var(--transition), transform var(--transition); }
a.card:hover { box-shadow: var(--shadow-md); text-decoration: none; }

.card--pad { padding: var(--space-6); }
.card--flush { border: 0; border-radius: 0; background: transparent; overflow: visible; }

/* A card that carries the screen's verdict rather than one of its figures. */
.card--brand { border-color: var(--ink); }
.card--accent { border-color: var(--accent-500); background: var(--accent-100); }
.card--danger { border-color: var(--danger); background: var(--danger-wash); }

.card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--rule-soft);
}
.card__header--plain { border-bottom: 0; padding-bottom: 0; }

.card__title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.card__subtitle { font-size: var(--text-base); color: var(--muted); margin-top: 2px; }

.card__body { padding: var(--space-6); }
.card__body--tight { padding: var(--space-4); }
.card__body--flush { padding: 0; }

.card__footer {
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--rule-soft);
  background: var(--surface-sunken);
  font-size: var(--text-base);
  color: var(--muted);
}

/* ==========================================================================
   Listing grid — image-led cards
   --------------------------------------------------------------------------
   The signature Airbnb collection: a responsive grid of borderless cards,
   each a media frame with a carousel and a short stack of text beneath it.
   ========================================================================== */

.listing-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6) var(--space-6);
}

@media (min-width: 640px)  { .listing-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .listing-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1440px) { .listing-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.listing { min-width: 0; }
.listing:hover { text-decoration: none; }
.listing:hover .listing__title { text-decoration: underline; }

.listing__body { padding-top: var(--space-3); }

.listing__title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--ink);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.listing__meta {
  font-size: var(--text-base);
  color: var(--muted);
  margin-top: 2px;
}

.listing__price { margin-top: var(--space-2); font-size: var(--text-base); color: var(--ink); }
.listing__price strong { font-weight: var(--weight-semibold); }

/* ---- Carousel ------------------------------------------------------------
   Scroll-snap rather than a script-driven transform, so it works with a
   trackpad swipe, a keyboard, and no JavaScript at all. The buttons and dots
   are enhancement on top. */

.carousel { position: relative; border-radius: var(--radius-lg); overflow: hidden; }

.carousel__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.carousel__track::-webkit-scrollbar { display: none; }

.carousel__slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  aspect-ratio: 20 / 19;          /* Airbnb's card ratio */
  background: var(--surface-sunken);
  position: relative;
}
.carousel__slide img { width: 100%; height: 100%; object-fit: cover; }

.carousel__slide--empty {
  display: grid;
  place-items: center;
  color: var(--subtle);
}
.carousel__slide--empty svg { width: 34px; height: 34px; }

.carousel__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: var(--shadow-sm);
  color: var(--ink);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--transition), background var(--transition);
}
.carousel:hover .carousel__nav { opacity: 1; }
.carousel__nav:focus-visible { opacity: 1; }
.carousel__nav:hover { background: #fff; transform: translateY(-50%) scale(1.06); }
.carousel__nav svg { width: 14px; height: 14px; }
.carousel__nav--prev { left: var(--space-3); }
.carousel__nav--next { right: var(--space-3); }
.carousel__nav[disabled] { display: none; }

.carousel__dots {
  position: absolute;
  bottom: var(--space-3);
  left: 0; right: 0;
  display: flex;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
}
.carousel__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
  transition: background var(--transition), transform var(--transition);
}
.carousel__dot.is-active { background: #fff; transform: scale(1.15); }

/* A status ribbon on the media, the way a listing badges "Guest favourite". */
.media-badge {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 1;
  padding: 5px var(--space-3);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.94);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}

/* ==========================================================================
   Metric
   ========================================================================== */

.metric { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }

.metric-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.02em;
  color: var(--muted);
}

.metric-value {
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
  line-height: 1.1;
  color: var(--ink);
}
.metric-value--sm { font-size: var(--text-xl); }
.metric-value--hero { font-size: var(--text-4xl); }

.metric-note { font-size: var(--text-base); color: var(--muted); }

.metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-6);
}

.delta { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-base); font-weight: var(--weight-semibold); }
.delta--up { color: var(--success); }
.delta--down { color: var(--danger); }
.delta--flat { color: var(--muted); }
.delta svg { width: 14px; height: 14px; }

/* ==========================================================================
   Progress and utilisation
   ========================================================================== */

.bar {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--series-track);
  overflow: hidden;
}
.bar--tall { height: 10px; }

.bar__fill {
  /* Block, because the dashboard draws its fills as spans and an inline
     element silently ignores both width and height — the bar renders as an
     empty groove and the tile says nothing. */
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--ink);
  transition: width var(--transition);
}
.bar__fill--ok { background: var(--success); }
.bar__fill--warn { background: var(--warning); }
.bar__fill--danger { background: var(--danger); }
.bar__fill--accent { background: var(--series-committed); }

.bar--stacked { display: flex; }
.bar--stacked .bar__fill { border-radius: 0; }

.bar-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-4);
  font-size: var(--text-xs);
  color: var(--muted);
}
.bar-legend span { display: inline-flex; align-items: center; gap: 6px; }
.bar-legend i {
  width: 9px; height: 9px;
  border-radius: 2px;
  background: currentColor;
}

.sparkline { display: block; width: 100%; height: 34px; }

/* A sparkline beside a figure: fixed and small, so the number stays the
   headline and the shape is the aside. */
.spark-wrap { width: 120px; flex-shrink: 0; }
.spark { display: block; width: 100%; height: 32px; overflow: visible; }

/* ==========================================================================
   Badges and chips
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
  white-space: nowrap;
  background: var(--surface-sunken);
  color: var(--ink-soft);
}

.badge--neutral { background: var(--surface-sunken); color: var(--ink-soft); }
.badge--brand   { background: var(--ink); color: #fff; }
.badge--accent  { background: var(--accent-100); color: var(--accent-700); }
.badge--success { background: var(--success-wash); color: var(--success); }
.badge--warning { background: var(--warning-wash); color: var(--warning); }
.badge--danger  { background: var(--danger-wash); color: var(--danger); }
.badge--info    { background: var(--info-wash); color: var(--info); }

.badge svg { width: 12px; height: 12px; }
.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }

/* ==========================================================================
   Buttons
   --------------------------------------------------------------------------
   Coral is the primary action and appears once per screen. Secondary is an
   outlined pill in ink; ghost carries no chrome until hovered.
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 48px;
  padding: 0 var(--space-6);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  letter-spacing: 0;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition), border-color var(--transition),
              box-shadow var(--transition), transform var(--transition-fast);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: scale(0.985); }
.btn svg { width: 16px; height: 16px; }
.btn[disabled] { opacity: 0.4; cursor: not-allowed; }

.btn--primary { background: var(--coral); color: #fff; }
.btn--primary:hover { background: var(--coral-pressed); }

.btn--secondary { background: var(--surface); border-color: var(--ink); color: var(--ink); }
.btn--secondary:hover { background: var(--surface-sunken); }

.btn--ghost { background: transparent; color: var(--ink); text-decoration: underline; }
.btn--ghost:hover { background: var(--surface-sunken); text-decoration: underline; }

.btn--danger { background: var(--danger); color: #fff; }
.btn--danger:hover { background: #A32B10; }

.btn--accent { background: var(--ink); color: #fff; }
.btn--accent:hover { background: #000; }

.btn--sm { height: 36px; padding: 0 var(--space-4); font-size: var(--text-base); }
.btn--lg { height: 56px; padding: 0 var(--space-8); font-size: var(--text-md); }
.btn--block { width: 100%; }
.btn--icon { width: 44px; padding: 0; }

.btn-group { display: inline-flex; gap: var(--space-2); flex-wrap: wrap; }

/* ==========================================================================
   Forms
   ========================================================================== */

.form-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-5);
}

.field { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }

/* The full scale. A partial one is worse than none: a field given a width the
   stylesheet does not define silently collapses to a single column, which is
   how a project name ends up in a box narrower than the word. */
.field--1  { grid-column: span 1; }
.field--2  { grid-column: span 2; }
.field--3  { grid-column: span 3; }
.field--4  { grid-column: span 4; }
.field--5  { grid-column: span 5; }
.field--6  { grid-column: span 6; }
.field--7  { grid-column: span 7; }
.field--8  { grid-column: span 8; }
.field--9  { grid-column: span 9; }
.field--10 { grid-column: span 10; }
.field--11 { grid-column: span 11; }
.field--12 { grid-column: span 12; }

@media (max-width: 900px) {
  .field--1, .field--2, .field--3, .field--4, .field--5 { grid-column: span 6; }
  .field--7, .field--8, .field--9, .field--10, .field--11 { grid-column: span 12; }
}
@media (max-width: 640px) {
  .form-grid > .field { grid-column: span 12; }
}

.label {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.input, .select, .textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--text-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.input::placeholder, .textarea::placeholder { color: var(--muted); }

.input:hover, .select:hover, .textarea:hover { border-color: var(--subtle); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

.textarea { min-height: 120px; resize: vertical; line-height: 1.55; }

.select {
  appearance: none;
  padding-right: var(--space-10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23222222' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
}

.input-group { display: flex; align-items: stretch; }
.input-group .input { border-radius: 0; }
.input-group > :first-child { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); }
.input-group > :last-child { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }
.input-group__addon {
  display: grid;
  place-items: center;
  padding: 0 var(--space-4);
  border: 1px solid var(--rule);
  background: var(--surface-sunken);
  color: var(--muted);
  font-size: var(--text-base);
  white-space: nowrap;
}
.input-group .input + .input-group__addon,
.input-group__addon + .input { border-left: 0; }

.hint { font-size: var(--text-base); color: var(--muted); }

/* ---- Suggesting as somebody types ---------------------------------------
   A field that proposes rather than corrects. Built here rather than taken
   from the provider's own widget: that one arrives with its own typeface,
   its own shadow and its own idea of a rounded corner, and lands in the
   middle of a form that has settled all three already. */

.combo { position: relative; }

.combo__list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  max-height: 300px;
  overflow-y: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-md);
}
.combo__list[hidden] { display: none; }

.combo__option {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.combo__option:hover,
.combo__option.is-active { background: var(--surface-sunken); }

.combo__label { font-size: var(--text-base); font-weight: var(--weight-medium); color: var(--ink); }
.combo__detail { font-size: var(--text-xs); color: var(--muted); }

/* A hint under a checkbox is a second line, not a continuation of its label. */
.check__hint { display: block; margin-top: 2px; font-size: var(--text-xs); color: var(--muted); }

.check { display: flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; }
.check input {
  width: 20px; height: 20px;
  margin-top: 2px;
  accent-color: var(--ink);
  flex-shrink: 0;
}
.check__text { font-size: var(--text-base); }

.fieldset-title {
  /* Full width. Without this a heading dropped into a twelve-column form grid
     takes one column and wraps mid-phrase between two inputs. */
  grid-column: 1 / -1;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--rule-soft);
}

/* ---- Form sections --------------------------------------------------------
   A long record form reads as a wall unless it is broken into the questions a
   person actually answers in order. Each section says what it is for, so the
   fields under it do not have to. */

.formsection + .formsection {
  margin-top: var(--space-8);
  padding-top: var(--space-8);
  border-top: 1px solid var(--rule-soft);
}

.formsection__title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.formsection__hint {
  margin-top: var(--space-1);
  max-width: 62ch;
  font-size: var(--text-base);
  color: var(--muted);
}

.formsection__body { margin-top: var(--space-5); }

/* The one mark that says a field cannot be left alone. */
.req { color: var(--danger); font-weight: var(--weight-semibold); }

/* ---- File drop --------------------------------------------------------------
   A bare file input renders as an unstyled grey button that says "Choose file"
   and nothing about what it wants. */

.drop {
  position: relative;
  display: grid;
  place-items: center;
  gap: var(--space-2);
  padding: var(--space-6);
  text-align: center;
  border: 1px dashed var(--rule);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.drop:hover { border-color: var(--ink); background: var(--surface); }
.drop:focus-within { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }

.drop input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

.drop__icon { color: var(--muted); }
.drop__icon svg { width: 22px; height: 22px; }
.drop__title { font-size: var(--text-base); font-weight: var(--weight-semibold); }
.drop__hint { font-size: var(--text-xs); color: var(--muted); }

/* ---- Live preview -----------------------------------------------------------
   The card as it will appear in the projects grid, filled in as the form is.
   A record form that shows nothing until it is saved makes people save to
   find out what they made. */

.preview__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--muted);
  margin-bottom: var(--space-3);
}

.preview__frame {
  aspect-ratio: 20 / 19;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-sunken);
  display: grid;
  place-items: center;
  position: relative;
}
.preview__frame img { width: 100%; height: 100%; object-fit: cover; }
.preview__frame .empty__icon { color: var(--subtle); }

.preview__placeholder { color: var(--subtle); }

.form-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: 1px solid var(--rule-soft);
}
.form-actions--split { justify-content: space-between; }

.validation-message, .validation-summary-errors {
  color: var(--danger);
  font-size: var(--text-base);
}
.validation-summary-errors ul { list-style: disc; padding-left: var(--space-5); }

/* Inside an alert the icon already marks it as a problem; a bullet as well is
   one marker too many, and for a single message it reads as a stray dot. */
.alert .validation-summary-errors,
.alert .validation-summary-errors ul { list-style: none; padding-left: 0; color: inherit; }
.validation-summary-valid { display: none; }

/* ==========================================================================
   Tables
   --------------------------------------------------------------------------
   Airbnb has little use for a dense table; a construction ledger has nothing
   but. The compromise: keep the row rhythm and hairline rules of the idiom,
   drop the vertical rules entirely, and let the type do the separating.
   ========================================================================== */

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

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-base);
}

.table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
  text-align: left;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.02em;
  color: var(--muted);
  white-space: nowrap;
}

.table tbody td {
  padding: var(--space-4);
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: middle;
}

.table tbody tr:last-child td { border-bottom: 0; }

.table tfoot td {
  padding: var(--space-4);
  border-top: 1px solid var(--rule);
  font-weight: var(--weight-semibold);
  background: var(--surface-sunken);
  white-space: nowrap;
}

.table .num, .table th.num { text-align: right; }
.table .tight { width: 1%; white-space: nowrap; }

.table__primary { font-weight: var(--weight-semibold); color: var(--ink); }
.table__secondary { font-size: var(--text-xs); color: var(--muted); margin-top: 2px; }

.table--rows-clickable tbody tr { cursor: pointer; transition: background var(--transition-fast); }
.table--rows-clickable tbody tr:hover { background: var(--surface-sunken); }

.row--over { background: var(--danger-wash); }
.row--over:hover { background: #FBE5DF !important; }
.row--void { opacity: 0.5; text-decoration: line-through; }

/* ==========================================================================
   Pagination
   --------------------------------------------------------------------------
   Airbnb pages its search results with a centred numeric pager: circular
   page buttons, the current one filled in ink, and a plain-language count
   underneath. Rendered from Views/Shared/_Pagination.cshtml.
   ========================================================================== */

.pager {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-6) var(--space-4);
  border-top: 1px solid var(--rule-soft);
}

.pager__controls { display: flex; align-items: center; gap: var(--space-1); }

.pager__btn,
.pager__page {
  min-width: 36px;
  height: 36px;
  padding: 0 var(--space-2);
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink);
  font-size: var(--text-base);
  font-weight: var(--weight-normal);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--transition-fast);
}
.pager__btn:hover, .pager__page:hover { background: var(--surface-sunken); text-decoration: none; }

.pager__page.is-current {
  background: var(--ink);
  color: #fff;
  font-weight: var(--weight-semibold);
}
.pager__page.is-current:hover { background: var(--ink); }

.pager__btn svg { width: 14px; height: 14px; }
.pager__btn[aria-disabled="true"] {
  color: var(--subtle);
  pointer-events: none;
}

.pager__gap { min-width: 22px; text-align: center; color: var(--muted); user-select: none; }

.pager__summary { font-size: var(--text-base); color: var(--muted); }
.pager__summary strong { color: var(--ink); font-weight: var(--weight-semibold); }

/* A pager sitting directly under a table inside a card loses the extra rule. */
.card > .pager { border-top: 1px solid var(--rule-soft); }

/* ==========================================================================
   Empty, alert and toast states
   ========================================================================== */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-16) var(--space-6);
  gap: var(--space-3);
}

.empty__icon {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  color: var(--subtle);
}
.empty__icon svg { width: 32px; height: 32px; }

.empty__title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.empty__body { font-size: var(--text-md); color: var(--muted); max-width: 56ch; }

.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  color: var(--ink-soft);
  background: var(--surface);
}
.alert svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 1px; }
.alert__title { font-weight: var(--weight-semibold); color: var(--ink); margin-bottom: 2px; }

.alert--success { border-color: var(--success); background: var(--success-wash); }
.alert--success svg { color: var(--success); }
.alert--warning { border-color: var(--warning); background: var(--warning-wash); }
.alert--warning svg { color: var(--warning); }
.alert--danger  { border-color: var(--danger); background: var(--danger-wash); }
.alert--danger svg { color: var(--danger); }
.alert--info    { border-color: var(--info); background: var(--info-wash); }
.alert--info svg { color: var(--info); }

.toast-stack {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 100;
  display: grid;
  gap: var(--space-3);
}
.toast {
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  background: var(--ink);
  color: #fff;
  box-shadow: var(--shadow-lg);
  font-size: var(--text-base);
}

/* ==========================================================================
   Filters sheet
   --------------------------------------------------------------------------
   The Filters button reveals the page's own filter form. It sits inline
   rather than in a modal: on a back-office screen the filters and the result
   are read together.
   ========================================================================== */

.sheet {
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  background: var(--surface);
  padding: var(--space-6);
  margin-bottom: var(--space-6);
}
.sheet[hidden] { display: none; }

.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--rule-soft);
}
.sheet__title { font-size: var(--text-lg); font-weight: var(--weight-semibold); }

/* ==========================================================================
   Charts
   ========================================================================== */

.chart { width: 100%; height: auto; overflow: visible; }
.chart__grid { stroke: var(--rule-soft); stroke-width: 1; }
.chart__axis { fill: var(--muted); font-size: 11px; }
.chart__planned { fill: none; stroke: var(--series-planned); stroke-width: 2; stroke-dasharray: 4 4; }
.chart__actual { fill: none; stroke: var(--series-actual); stroke-width: 2.5; stroke-linecap: round; }
.chart__actual-area { fill: var(--surface-sunken); }
.chart__committed { fill: none; stroke: var(--series-committed); stroke-width: 2; }
.chart__point { fill: var(--series-actual); }

/* ==========================================================================
   Photo wall
   ========================================================================== */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: var(--space-4);
}

.photo-tile {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-sunken);
}
.photo-tile img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--transition); }
.photo-tile:hover img { transform: scale(1.03); }

.photo-tile__caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--space-6) var(--space-3) var(--space-3);
  background: linear-gradient(to top, rgba(0, 0, 0, 0.62), transparent);
  color: #fff;
  font-size: var(--text-xs);
}

/* ==========================================================================
   Definition list
   ========================================================================== */

.dl { display: grid; grid-template-columns: minmax(140px, auto) 1fr; gap: var(--space-3) var(--space-6); }
.dl dt { font-size: var(--text-base); color: var(--muted); }
.dl dd { margin: 0; font-size: var(--text-base); color: var(--ink); }
.dl--stacked { grid-template-columns: 1fr; gap: var(--space-1); }
.dl--stacked dt { font-size: var(--text-xs); }
.dl--stacked dd + dt { margin-top: var(--space-4); }

/* ==========================================================================
   Timeline
   ========================================================================== */

.timeline { display: grid; gap: var(--space-5); position: relative; padding-left: var(--space-6); }
.timeline::before {
  content: "";
  position: absolute;
  left: 5px; top: 6px; bottom: 6px;
  width: 2px;
  background: var(--rule-soft);
}
.timeline__item { position: relative; }
.timeline__dot {
  position: absolute;
  left: calc(var(--space-6) * -1);
  top: 5px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--rule);
}
.timeline__dot--done { background: var(--success); border-color: var(--success); }
.timeline__dot--active { background: var(--ink); border-color: var(--ink); }
.timeline__dot--late { background: var(--danger); border-color: var(--danger); }

/* ==========================================================================
   Activity trail
   --------------------------------------------------------------------------
   The audit log read as an account rather than as a table. Four tables record
   what happens to a record — the log, the corrections, the approval chain and
   the evidence — and the person at the desk wants one answer from all four:
   what happened to this payment, in order, and who did it.

   One mark per action on a rail, the person beside it, and underneath it the
   figures that actually moved. The before-and-after JSON that used to be
   printed into a truncated table cell is translated on the way in.
   ========================================================================== */

.trail { display: block; }

.trail__day {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin: var(--space-1) 0 var(--space-5);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.trail__day::after { content: ""; flex: 1; height: 1px; background: var(--rule-soft); }
.trail__day:first-child { margin-top: 0; }

.trail__item {
  position: relative;
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  gap: var(--space-4);
  padding-bottom: var(--space-6);
}

/* The rail is drawn by each entry down to the next rather than once behind the
   whole list, so it stops cleanly at a date heading instead of running through
   it, and never dangles past the last entry. */
.trail__item::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 36px;
  bottom: 0;
  width: 2px;
  background: var(--rule-soft);
}
.trail__item:last-child::before { display: none; }
.trail__item:has(+ .trail__day)::before { display: none; }

.trail__mark {
  position: relative;
  z-index: 1;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--surface);
  color: var(--muted);
}
.trail__mark svg { width: 15px; height: 15px; }

.trail__mark--recorded  { border-color: var(--ink); color: var(--ink); }
.trail__mark--submitted { background: var(--info-wash); border-color: var(--info); color: var(--info); }
.trail__mark--approved  { background: var(--success-wash); border-color: var(--success); color: var(--success); }
.trail__mark--rejected  { background: var(--danger-wash); border-color: var(--danger); color: var(--danger); }
.trail__mark--voided    { background: var(--danger-wash); border-color: var(--danger); color: var(--danger); }
.trail__mark--corrected { background: var(--warning-wash); border-color: var(--warning); color: var(--warning); }
.trail__mark--waiting   { background: var(--ink); border-color: var(--ink); color: #fff; }

.trail__body { min-width: 0; padding-top: 5px; }

.trail__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
}

.trail__title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--ink);
}

.trail__when {
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.trail__who { margin-top: 2px; font-size: var(--text-base); color: var(--muted); }

/* A reason or a comment is somebody's own words, so it is set as a quotation
   rather than as another line of metadata. */
.trail__note {
  margin-top: var(--space-3);
  padding-left: var(--space-4);
  border-left: 2px solid var(--rule);
  font-size: var(--text-base);
  color: var(--ink-soft);
}

.trail__changes { margin-top: var(--space-3); display: grid; gap: var(--space-2); }

.trail__change {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  width: fit-content;
  max-width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  font-size: var(--text-sm);
}
.trail__change svg { width: 13px; height: 13px; color: var(--subtle); }
.trail__field { color: var(--muted); }
.trail__from { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--subtle); }
.trail__to { font-weight: var(--weight-semibold); color: var(--ink); }

/* The one entry that has not happened yet. */
@media (prefers-reduced-motion: no-preference) {
  .trail__mark--waiting::after {
    content: "";
    position: absolute;
    inset: -5px;
    border-radius: 50%;
    border: 1px solid var(--ink);
    animation: trail-pulse 2.6s ease-out infinite;
  }

  @keyframes trail-pulse {
    0%        { transform: scale(0.86); opacity: 0.45; }
    70%, 100% { transform: scale(1.2);  opacity: 0; }
  }
}

/* ==========================================================================
   Facts
   --------------------------------------------------------------------------
   A record's fields as a grid of small label-and-value pairs. Eleven rows of
   a two-column definition list is a form; the same eleven facts laid across
   the page can be found at a glance, which is what a summary is for.
   ========================================================================== */

.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-5) var(--space-6);
}

.fact { min-width: 0; }

.fact__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.02em;
  color: var(--muted);
  margin-bottom: 3px;
}

.fact__value { font-size: var(--text-md); color: var(--ink); }
.fact__note { margin-top: 2px; font-size: var(--text-xs); color: var(--muted); }

/* Inside a side sheet the pairs stack rather than compete for a narrow width. */
.facts--tight { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--space-4); }

/* ==========================================================================
   Site map
   --------------------------------------------------------------------------
   Feature document 6.1: every Anova site on one map. The map is an
   enhancement over a list that already works, so nothing here assumes the
   tiles arrived.
   ========================================================================== */

.map-canvas {
  width: 100%;
  height: clamp(400px, calc(100vh - 420px), 720px);
  background: var(--surface-sunken);
}

/* Google paints its own white cards inside the canvas; the hairline keeps the
   map a panel on the page rather than a hole in it. */
.map-canvas .gm-style { font-family: var(--font-sans); }

.map-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--muted);
}
.map-key span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.map-key i { width: 9px; height: 9px; border-radius: 50%; }

.site-list { max-height: clamp(320px, calc(100vh - 420px), 720px); overflow-y: auto; }

.site-list__state {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--space-3) var(--space-5);
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--rule-soft);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.site-list__item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border: 0;
  border-bottom: 1px solid var(--rule-soft);
  background: none;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast);
}
.site-list__item:hover { background: var(--surface-sunken); }
.site-list__item svg { width: 15px; height: 15px; color: var(--subtle); flex-shrink: 0; }

.site-list__dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--muted); }
.site-list__dot--inprogress { background: var(--ink); }
.site-list__dot--planning { background: var(--info); }
.site-list__dot--completed { background: var(--success); }
.site-list__dot--onhold { background: var(--warning); }
.site-list__dot--suspended,
.site-list__dot--cancelled { background: var(--danger); }

.site-list__name { display: block; font-size: var(--text-base); font-weight: var(--weight-medium); color: var(--ink); }
.site-list__meta { display: block; font-size: var(--text-xs); color: var(--muted); }

/* ==========================================================================
   Evidence
   --------------------------------------------------------------------------
   The receipt, beside the figures it supports. The frame is square because a
   phone photograph carries its rotation in EXIF and is turned here with a
   transform: a square is the one shape that still fills its box afterwards.
   ========================================================================== */

.evidence { display: grid; gap: var(--space-3); }

.evidence__item {
  display: block;
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface);
  transition: box-shadow var(--transition);
}
.evidence__item:hover { box-shadow: var(--shadow-md); text-decoration: none; }

.evidence__frame {
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--surface-sunken);
}
.evidence__frame img { width: 100%; height: 100%; object-fit: cover; }
.evidence__frame svg { width: 30px; height: 30px; color: var(--subtle); }

.evidence__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--rule-soft);
  font-size: var(--text-xs);
  color: var(--muted);
}
.evidence__name { color: var(--ink); font-weight: var(--weight-medium); }

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

.row { display: flex; align-items: center; gap: var(--space-3); }
.row--between { justify-content: space-between; }
.row--end { justify-content: flex-end; }
.row--top { align-items: flex-start; }
.row--wrap { flex-wrap: wrap; }
.row-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-4); }

.grow { flex: 1; min-width: 0; }
.stack { display: grid; }
.stack-1 { display: grid; gap: var(--space-1); }
.stack-2 { display: grid; gap: var(--space-2); }
.stack-3 { display: grid; gap: var(--space-3); }
.stack-4 { display: grid; gap: var(--space-4); }
.stack-5 { display: grid; gap: var(--space-5); }

.divider { height: 1px; background: var(--rule-soft); border: 0; margin: var(--space-6) 0; }

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.text-xs { font-size: var(--text-xs); }
.text-sm { font-size: var(--text-base); }
.text-lg { font-size: var(--text-lg); }
.text-center { text-align: center; }
.text-right { text-align: right; }

.text-ink { color: var(--ink); }
.text-muted { color: var(--muted); }
.text-subtle { color: var(--subtle); }
.text-brand { color: var(--ink); }
.text-success { color: var(--success); }
.text-warning { color: var(--warning); }
.text-danger { color: var(--danger); }

.medium { font-weight: var(--weight-medium); }
.semibold { font-weight: var(--weight-semibold); }

.mt-0 { margin-top: 0; }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }

.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--space-1); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-5 { margin-bottom: var(--space-5); }
.mb-6 { margin-bottom: var(--space-6); }

/* Prose, given a reading measure. */
.text-md {
  font-size: var(--text-md);
  line-height: 1.65;
  max-width: 68ch;
  color: var(--ink-soft);
}

/* ==========================================================================
   User chip (drawer footer)
   ========================================================================== */

.user-chip {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  transition: background var(--transition-fast);
}
.user-chip:hover { background: var(--surface-sunken); text-decoration: none; }
.user-chip__meta { min-width: 0; }
.user-chip__name {
  display: block;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.user-chip__role { display: block; font-size: var(--text-xs); color: var(--muted); }

/* ==========================================================================
   Sign in
   --------------------------------------------------------------------------
   Side by side: the product on the left, the task on the right. The form
   column is the one that scrolls and the one that gets focus; the panel is
   there to say whose system this is before anybody types a password into it.

   The previous split was dropped because it hid its entire left half on a
   phone and left the form floating with no identity on it. This one does not
   disappear — below 900px the panel becomes a short branded header above the
   form, so the mark and the name are on screen at every width.

   Fields are joined into one bordered group, which is the pattern the rest of
   the redesign uses: two inputs sharing a border read as one thing to fill in,
   and a label that starts inside its field and rises out of the way keeps the
   field named while it is being typed into.
   ========================================================================== */

.auth-body { background: var(--surface); }

.auth {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
}

/* ---- Left: the panel ------------------------------------------------------ */

.auth__aside {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-8);
  padding: var(--space-12);
  background: var(--ink);
  color: #fff;
  overflow: hidden;
  isolation: isolate;
}

/* Artwork sits behind the copy, whether that is a photograph the company has
   supplied or the drawn fallback. */
.auth__art {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Whatever is behind — drawing or photograph — the copy sits on a darker
   ground towards the bottom left, so white type holds without having to know
   what the artwork is doing. */
.auth__aside::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(155deg,
              rgba(34, 34, 34, 0.15) 0%,
              rgba(34, 34, 34, 0.55) 45%,
              rgba(34, 34, 34, 0.92) 100%);
}

/* A photograph needs more of it laid back than a line drawing does. */
.auth__art--photo ~ .auth__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(0, 0, 0, 0.45);
}

.auth__brand { display: flex; align-items: center; gap: var(--space-3); }

.auth__mark {
  width: 42px; height: 42px;
  flex-shrink: 0;
  display: grid; place-items: center;
  border-radius: var(--radius-md);
  background: var(--coral);
  color: #fff;
  font-weight: var(--weight-bold);
  font-size: var(--text-xl);
  letter-spacing: -0.03em;
}

.auth__wordmark { line-height: 1.2; }

.auth__name {
  display: block;
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  color: #fff;
}

.auth__tagline {
  display: block;
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.65);
}

.auth__headline {
  max-width: 18ch;
  font-size: clamp(1.75rem, 2.9vw, 2.75rem);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
  line-height: 1.1;
  text-wrap: balance;
}

.auth__blurb {
  margin-top: var(--space-4);
  max-width: 44ch;
  font-size: var(--text-md);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.78);
}

.auth__meta {
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.55);
}

/* ---- Right: the form ------------------------------------------------------ */

.auth__panel {
  display: grid;
  place-items: center;
  padding: var(--space-12) var(--space-8);
  background: var(--surface);
}

.auth__form { width: 100%; max-width: 400px; }

.auth__title {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
}

.auth__sub {
  margin-top: var(--space-2);
  font-size: var(--text-md);
  color: var(--muted);
}

/* ---- The joined field group ---------------------------------------------- */

.authgroup { display: grid; margin-top: var(--space-6); }

.authfield {
  position: relative;
  border: 1px solid var(--rule);
  background: var(--surface);
  margin-top: -1px;              /* adjacent borders collapse to one hairline */
  transition: border-color var(--transition-fast);
}

.authfield:first-child {
  margin-top: 0;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.authfield:last-child { border-radius: 0 0 var(--radius-md) var(--radius-md); }
.authfield:only-child { border-radius: var(--radius-md); }

/* The focused field lifts out of the group and takes its own full radius. */
.authfield:focus-within {
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
  border-radius: var(--radius-md);
  z-index: 2;
}

.authfield.has-error { border-color: var(--danger); z-index: 1; }
.authfield.has-error:focus-within { box-shadow: 0 0 0 1px var(--danger); }

.authfield input {
  width: 100%;
  height: 58px;
  padding: 22px var(--space-3) 6px;
  border: 0;
  background: transparent;
  font-size: var(--text-md);
  color: var(--ink);
  border-radius: inherit;
}
.authfield input:focus { outline: none; box-shadow: none; }

/* Chrome paints autofill with its own yellow; keep the field on the page's
   palette and let the floating label still know there is a value. */
.authfield input:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
}

.authfield label {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  font-size: var(--text-md);
  pointer-events: none;
  transition: top var(--transition-fast), font-size var(--transition-fast),
              transform var(--transition-fast);
}

.authfield input:focus + label,
.authfield input:not(:placeholder-shown) + label {
  top: 9px;
  transform: none;
  font-size: var(--text-xs);
}

/* ---- Password reveal ------------------------------------------------------
   Masked by default and re-masked on submit. The eye is an affordance for
   somebody typing a long password on a site laptop, not a preference that
   should survive the page. */

.authfield--action input { padding-right: 52px; }

.authfield__reveal {
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.authfield__reveal:hover { background: var(--surface-sunken); color: var(--ink); }
.authfield__reveal svg { width: 18px; height: 18px; }

/* ---- Messages and actions -------------------------------------------------- */

/* One message per line, and nothing at all from the fields that are fine.
   field-validation-valid is what the framework puts on an empty placeholder
   span, so it is also the cleanest thing to hide on. */
.auth__error {
  display: block;
  margin-top: var(--space-3);
  font-size: var(--text-base);
  color: var(--danger);
}
.auth__error.field-validation-valid { display: none; }

.auth__submit { margin-top: var(--space-5); }

.auth__foot {
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid var(--rule-soft);
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.6;
}

.auth__by { margin-top: var(--space-4); font-size: var(--text-xs); color: var(--subtle); }

/* ---- Responsive -----------------------------------------------------------
   The panel does not vanish; it becomes a header. */

@media (max-width: 900px) {
  /* Auto for the banner, the rest to the form. Two auto rows in a 100vh grid
     stretch to share the height, which inflated the collapsed banner and left
     the form floating in the middle of the page. */
  .auth {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
  }

  .auth__aside {
    padding: var(--space-6);
    gap: var(--space-5);
  }

  .auth__headline { font-size: var(--text-xl); }
  .auth__blurb, .auth__meta { display: none; }

  /* The form starts at the top of what is left rather than centring in it. */
  .auth__panel {
    align-items: start;
    padding: var(--space-8) var(--space-5) var(--space-12);
  }
}

@media (max-width: 480px) {
  .auth__aside { padding: var(--space-5); }
  .auth__pitch { display: none; }
}

/* ==========================================================================
   Dashboard tones
   --------------------------------------------------------------------------
   A role dashboard says how urgent each tile is. The accent is a left edge
   rather than a filled panel: twelve coloured cards would shout at each other
   and none of them would be read.
   ========================================================================== */

.card.tone--good    { box-shadow: inset 3px 0 0 var(--success); }
.card.tone--warning { box-shadow: inset 3px 0 0 var(--warning); }
.card.tone--bad     { box-shadow: inset 3px 0 0 var(--danger); }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1024px) {
  :root {
    --page-gutter: 24px;
    --navbar-height: 72px;
    --chrome-height: 132px;
  }

  .navbar__inner { grid-template-columns: auto 1fr auto; }
  .navbar__menu { display: grid; }
  /* Scoped to the bar. The drawer reuses the same brand block and has room
     for the name, so hiding it there was collateral damage. */
  .navbar .navbar__brand .brandmark__text { display: none; }

  .searchpill { width: 100%; max-width: none; }
  .searchpill .searchpill__seg--fold,
  .searchpill .searchpill__divider { display: none; }
  .searchpill .searchpill__label { display: none; }
  .searchpill .searchpill__seg { padding-block: 0; }

  .profile__button { padding-left: var(--space-2); }
  .profile__button > svg { display: none; }

  .split { grid-template-columns: minmax(0, 1fr); }
}

@media (min-width: 1025px) {
  .drawer { display: none; }
  .scrim { display: none; }
}

@media (max-width: 640px) {
  :root { --page-gutter: 16px; --bento-gap: 16px; }

  .page { padding-top: var(--space-6); }
  .page-title { font-size: var(--text-xl); }
  .metric-value { font-size: var(--text-xl); }
  .metric-value--hero { font-size: var(--text-3xl); }
  .card--pad { padding: var(--space-4); }
  .card__header, .card__body { padding: var(--space-4); }
  .table tbody td, .table thead th { padding: var(--space-3); }
  .form-actions { flex-direction: column; align-items: stretch; }
  .form-actions .btn { width: 100%; }
}

@media print {
  .navbar, .filterbar, .drawer, .scrim,
  .page-header__actions, .btn, .pager, .sheet { display: none !important; }
  .page { padding: 0; max-width: none; }
  .card { break-inside: avoid; box-shadow: none; border-color: #ccc; }
  body { background: #fff; }
}

/* The note under a field explaining what it is for. Block, so a sentence
   wraps inside its container instead of running off the edge of a dialog. */
.field__hint {
  display: block;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--muted);
}

/* ==========================================================================
   Modal

   Built on the native <dialog>, which brings focus trapping, Escape to close
   and an inert background with no script of our own. A panel opened inside a
   table cell pushed every row below it down the page and left the reader
   hunting for where the form went; this opens over the table and closes back
   to the same row.
   ========================================================================== */

.modal {
  width: min(520px, calc(100vw - 2 * var(--space-5)));
  max-height: calc(100vh - 2 * var(--space-6));
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 24px 48px -12px rgba(13, 23, 40, 0.35);
  overflow: hidden;

  /* A dialog is written inside the row it belongs to, and the top layer changes
     where it paints, not what it inherits. Without this reset an actions cell
     carrying `white-space: nowrap` runs every line of the form off the edge. */
  white-space: normal;
  text-align: left;
  vertical-align: baseline;
  font-size: var(--text-md);
  line-height: 1.5;
  font-weight: var(--weight-normal);
  letter-spacing: normal;
}

/* A twelve-column form needs room to stay twelve columns. */
.modal--wide { width: min(880px, calc(100vw - 2 * var(--space-5))); }

.modal::backdrop {
  background: rgba(13, 23, 40, 0.45);
}

.modal__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--rule-soft);
}

.modal__title { font-size: var(--text-lg); font-weight: var(--weight-semibold); }
.modal__sub { font-size: var(--text-sm); color: var(--muted); margin-top: 2px; }

.modal__close {
  margin-left: auto;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 0; border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  font-size: 20px; line-height: 1;
  cursor: pointer;
}
.modal__close:hover { background: var(--canvas); color: var(--ink); }

/*
   A single-column grid defaults to an auto track, which sizes to its content
   and will happily push past a fixed-width dialog. Pinning the track to
   minmax(0, 1fr) makes the text wrap inside the box instead.
*/
.modal__body,
.modal__body .stack-2,
.modal__body .stack-3 { min-width: 0; }
.modal__body .stack-2,
.modal__body .stack-3 { grid-template-columns: minmax(0, 1fr); }

/* Scrolls inside the dialog rather than the page behind it. */
.modal__body {
  padding: var(--space-5);
  overflow-y: auto;
  max-height: calc(100vh - 220px);
}

/* ---- The side sheet ------------------------------------------------------
   The same <dialog> as a modal, docked to the right edge, so it keeps the
   focus trap, the Escape key and the backdrop click the modal already has.

   Written after .modal rather than beside the site map it is used on. Both
   selectors weigh the same, so whichever is read last wins every property
   they share: from up there this rule set its width and .modal quietly set
   it back.
   ========================================================================== */

.modal--side {
  width: min(420px, calc(100vw - var(--space-6)));
  max-width: none;
  max-height: 100vh;
  height: 100vh;
  margin: 0 0 0 auto;
  border-radius: 0;
  border-width: 0 0 0 1px;
}

/*
   Only while it is open. A dialog is hidden by the browser's own
   dialog:not([open]) { display: none }, and an author rule beats that whether
   the dialog is open or not: a plain display:flex here leaves the panel on
   screen permanently, and closing it — by the backdrop, by Escape, by the
   close button — does exactly nothing anyone can see.
*/
.modal--side[open] {
  display: flex;
  flex-direction: column;
}

.modal--side .modal__body {
  flex: 1;
  max-height: none;

  /* Taller than its content by design. Without this the grid stretches its
     rows to fill the sheet and six facts drift a hand's width apart. */
  align-content: start;
}

@media (prefers-reduced-motion: no-preference) {
  .modal--side[open] { animation: sheet-in var(--transition) ease-out; }

  @keyframes sheet-in {
    from { transform: translateX(100%); }
    to   { transform: none; }
  }
}

@media (max-width: 640px) {
  .modal--side {
    width: 100vw;
    height: auto;
    max-height: 88vh;
    margin: auto 0 0;
    border-width: 1px 0 0;
    border-top-left-radius: var(--radius-lg);
    border-top-right-radius: var(--radius-lg);
  }

  @media (prefers-reduced-motion: no-preference) {
    .modal--side[open] { animation: sheet-up var(--transition) ease-out; }

    @keyframes sheet-up {
      from { transform: translateY(100%); }
      to   { transform: none; }
    }
  }
}

/* ==========================================================================
   The help assistant
   --------------------------------------------------------------------------
   Bottom left, because the bottom right is where toasts land and a panel that
   covers the confirmation of what somebody just saved is a panel they learn to
   close and stop opening.

   Deliberately quiet: a hairline panel in the same idiom as everything else,
   not a coloured bubble with a face on it. It is a reference tool sitting in
   the corner of a ledger, and it should look like one.
   ========================================================================== */

.helper {
  position: fixed;
  left: var(--space-6);
  bottom: var(--space-6);
  z-index: 95;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
}

.helper__launch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 44px;
  padding: 0 var(--space-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  box-shadow: var(--shadow-pill);
  transition: box-shadow var(--transition), transform var(--transition);
}
.helper__launch:hover { box-shadow: var(--shadow-lg); }
.helper__launch:active { transform: translateY(1px); }
.helper__launch svg { width: 16px; height: 16px; color: var(--muted); }

.helper__panel {
  width: min(380px, calc(100vw - var(--space-8)));
  max-height: min(560px, calc(100vh - 160px));
  display: flex;
  flex-direction: column;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.helper__panel[hidden] { display: none; }

.helper__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--rule-soft);
}

.helper__title { font-size: var(--text-md); font-weight: var(--weight-semibold); }
.helper__sub { font-size: var(--text-xs); color: var(--muted); margin-top: 1px; }

.helper__close {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border: 0; border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  font-size: 20px; line-height: 1;
  cursor: pointer;
}
.helper__close:hover { background: var(--surface-sunken); color: var(--ink); }

.helper__log {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  font-size: var(--text-base);
  line-height: 1.55;
}

.helper__msg {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  max-width: 92%;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.helper__msg--bot { background: var(--surface-sunken); color: var(--ink); align-self: flex-start; }
.helper__msg--you { background: var(--ink); color: #fff; align-self: flex-end; }
.helper__msg--failed { background: var(--warning-wash); color: var(--warning); align-self: flex-start; }

/* The three dots while it is thinking. Restrained, and off entirely for
   anybody who has asked for less motion. */
.helper__thinking { display: inline-flex; gap: 4px; align-items: center; padding: var(--space-1) 0; }
.helper__thinking i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--subtle);
}
@media (prefers-reduced-motion: no-preference) {
  .helper__thinking i { animation: helper-blink 1.3s ease-in-out infinite; }
  .helper__thinking i:nth-child(2) { animation-delay: .18s; }
  .helper__thinking i:nth-child(3) { animation-delay: .36s; }

  @keyframes helper-blink {
    0%, 60%, 100% { opacity: .25; }
    30% { opacity: 1; }
  }
}

.helper__suggestions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.helper__chip {
  padding: 5px var(--space-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-soft);
  font-family: inherit;
  font-size: var(--text-xs);
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition);
}
.helper__chip:hover { border-color: var(--ink); color: var(--ink); }

.helper__ask {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--rule-soft);
  background: var(--surface);
}

.helper__input {
  flex: 1;
  min-width: 0;
  height: 38px;
  padding: 0 var(--space-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--text-base);
}
.helper__input:focus { outline: 0; border-color: var(--ink); }

.helper__send {
  width: 38px; height: 38px;
  flex-shrink: 0;
  display: grid; place-items: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--coral);
  color: #fff;
  cursor: pointer;
}
.helper__send:hover { background: var(--coral-pressed); }
.helper__send:disabled { background: var(--subtle); cursor: default; }
.helper__send svg { width: 16px; height: 16px; }

@media (max-width: 640px) {
  .helper { left: var(--space-4); right: var(--space-4); bottom: var(--space-4); }
  .helper__panel { width: 100%; max-height: min(70vh, 520px); }
}

/* ==========================================================================
   Reading a receipt
   ========================================================================== */

.receipt-read {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.receipt-read__status { font-size: var(--text-xs); color: var(--muted); flex: 1; min-width: 0; }
