/* ==========================================================================
   Reluty client portal
   The "Modern Boutique" system from the public site (portal/css/site.css),
   carried into the signed-in app: Fraunces over Manrope, navy and cream,
   blue for state and gold for the one action that matters on a screen.
   Design tokens first, then primitives, then the two layouts (auth + app).
   ========================================================================== */

:root {
  /* Brand core, identical to site.css -- the two stylesheets are skins of one
     palette, not two palettes that happen to look similar. */
  --navy-900: #0B1629;
  --navy-800: #0F1F3D;
  --navy-700: #16294F;
  --navy-600: #1E3A6E;
  --gold-500: #C9A24A;
  --gold-400: #D9B865;
  --gold-300: #E8D39A;
  --gold-ink: #6E5318;
  --gold-em:  #A17C2E;
  --gold-grad: linear-gradient(135deg, #E8D39A 0%, #C9A24A 45%, #A8822E 100%);
  --ice:   #EEF3F8;
  --ice-2: #DCE6F0;
  --ice-3: #BFD0E3;
  /* Warnings keep the site's burnt amber: it is a status, not the brand. */
  --amber-600: #8F5A18;
  --amber-100: #F7EEE3;
  --cream:  #F7F4EE;
  --ivory:  #FBF9F5;
  --on-dark: #F1EDE4;
  --on-dark-muted: #A8B0BF;

  --bg:            var(--cream);
  --bg-sunken:     #EDE9E1;
  --surface:       #ffffff;
  --surface-alt:   var(--ivory);
  --surface-hover: var(--ice);
  --border:        #E3E7EC;
  --border-strong: #CBD4DF;

  --text:          var(--navy-800);
  --text-muted:    #566173;
  --text-faint:    #8A93A2;
  --text-invert:   #ffffff;

  /* Blue carries selection, links and anything "you are here" -- the navy-600
     the site's links and focused inputs turn on hover. */
  --accent:        var(--navy-600);
  --accent-hover:  var(--navy-700);
  --accent-soft:   var(--ice);
  --accent-border: var(--ice-3);
  --accent-ink:    #ffffff;

  /* Gold owns the primary action, with a navy label -- the site's btn--gold,
     and for the same contrast reason: white on gold fails. */
  --action:        var(--gold-500);
  --action-hover:  var(--gold-400);
  --action-ink:    var(--navy-900);

  /* Gold as type: eyebrows in the darker ink that clears 4.5:1 on cream, and
     the italic accent in headings at the site's display weight. */
  --brand-ink:     var(--gold-ink);
  --brand-em:      var(--gold-em);

  /* The dark chrome: sidebar, and anything else that quotes the site's navy
     panels. Fixed rather than themed, so it looks the same in both modes. */
  --chrome:        var(--navy-800);
  --chrome-deep:   var(--navy-900);
  --chrome-line:   rgba(201, 162, 74, .22);
  --chrome-text:   var(--on-dark);
  --chrome-muted:  var(--on-dark-muted);

  --danger:        #A3352B;
  --danger-soft:   #FBEEEC;
  --danger-border: #EBC9C4;
  --success:       #3B6B4E;
  --success-soft:  #ECF3EE;
  --success-border:#C2D8CA;
  --warn:          var(--amber-600);
  --warn-soft:     var(--amber-100);
  --warn-border:   #E5CBAA;

  --radius:    14px;
  --radius-sm: 10px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(15, 31, 61, .06);
  --shadow:    0 1px 2px rgba(15, 31, 61, .06), 0 4px 14px rgba(15, 31, 61, .05);
  --shadow-lg: 0 24px 60px rgba(15, 31, 61, .14);

  --display: 'Fraunces', 'Iowan Old Style', Georgia, serif;
  --sans: 'Manrope', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --sidebar-w: 252px;
  --header-h:  64px;

  color-scheme: light;
}

/* The dark palette lives here once, keyed on an explicit attribute rather than
   on the media query. A small script in base.html resolves "follow the system"
   into `data-theme` before first paint and keeps it in step afterwards, so
   there is one dark palette rather than two that drift apart.

   Dark mode is the same brand after sundown: the navy the sidebar already
   wears spreads to the whole page, and the blue lightens wherever a
   light-ground colour would sink into it. */
:root[data-theme="dark"] {
    --bg:            var(--navy-900);
    --bg-sunken:     #070F1C;
    --surface:       #101F38;
    --surface-alt:   #14243F;
    --surface-hover: #1A2E4E;
    --border:        #22344F;
    --border-strong: #35486A;

    --text:          var(--on-dark);
    --text-muted:    var(--on-dark-muted);
    --text-faint:    #7C8798;
    --text-invert:   var(--navy-900);

    --accent:        #9DB6DA;
    --accent-hover:  #BFD0E3;
    --accent-soft:   #16294F;
    --accent-border: #2C4A78;
    --accent-ink:    var(--navy-900);

    --action:        var(--gold-500);
    --action-hover:  var(--gold-400);
    --action-ink:    var(--navy-900);

    --brand-ink:     var(--gold-400);
    --brand-em:      var(--gold-400);

    --chrome:        #0A1425;
    --chrome-deep:   #070F1C;

    --danger:        #E9968C;
    --danger-soft:   #2C1512;
    --danger-border: #6B2A22;
    --success:       #8CC6A3;
    --success-soft:  #10251A;
    --success-border:#2C543B;
    --warn:          var(--gold-400);
    --warn-soft:     #2A2010;
    --warn-border:   #6B531F;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow:    0 1px 3px rgba(0, 0, 0, .5), 0 1px 2px rgba(0, 0, 0, .4);
    --shadow-lg: 0 24px 60px rgba(0, 0, 0, .6);

    color-scheme: dark;
}

/* Only `color-scheme`, so a browser with scripting off still gets native
   controls that match the system rather than a blinding white select on a dark
   page. The colours themselves come from the attribute above. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}

/* Text on an accent-coloured background. The accent lightens in dark mode, so
   these need the dark ink rather than white -- one rule rather than five
   identical ones scattered down the file. */
:root[data-theme="dark"] :is(
  .nav-badge,
  .chat-unread,
  .bubble-row.mine .bubble,
  .mention-me
) { color: var(--navy-900); }

/* --------------------------------------------------------------------------
   Reset and base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: lining-nums;
}

/* Fraunces is the voice of the brand, but only where it is read as a title.
   Below ~18px its optical sizing turns into texture, so the small headings
   that label a card or a panel stay in Manrope. */
h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.3; letter-spacing: -.01em; }
h1, h2, .display {
  font-family: var(--display);
  font-weight: 400;
  font-variation-settings: "SOFT" 100;
  letter-spacing: -.015em;
  line-height: 1.12;
}
p { margin: 0 0 .75em; }
p:last-child { margin-bottom: 0; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; }
.mono { font-family: var(--mono); font-size: .92em; }

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

.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;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 17px;
  font: inherit; font-weight: 600; font-size: 13.5px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: background .18s ease, border-color .18s ease, color .18s ease, opacity .12s ease;
}
/* Hover states are scoped to enabled buttons. A blanket `.btn[disabled]:hover`
   reset used to repaint the background without touching the variant's text
   colour, which turned a disabled primary button white-on-white the moment the
   cursor sat on it -- the Send button vanishing mid-compose. */
.btn:not([disabled]):hover {
  background: var(--surface-hover); border-color: var(--accent-border);
  text-decoration: none;
}
.btn:not([disabled]):active { transform: translateY(.5px); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }

/* Amber fill, navy label -- the site's primary action, unchanged. A fill dark
   enough to carry white text goes brown and loses the warmth the whole palette
   is built on. */
.btn-primary {
  background: var(--action); border-color: var(--action); color: var(--action-ink);
}
.btn-primary:not([disabled]):hover {
  background: var(--action-hover); border-color: var(--action-hover); color: var(--action-ink);
}

.btn-danger { color: var(--danger); border-color: var(--danger-border); background: var(--danger-soft); }
.btn-danger:not([disabled]):hover { background: var(--danger-soft); border-color: var(--danger); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn-ghost:not([disabled]):hover { background: var(--surface-hover); color: var(--text); }

.btn-sm { padding: 5px 13px; font-size: 12.5px; }
.btn-block { width: 100%; }

/* --------------------------------------------------------------------------
   Form fields
   -------------------------------------------------------------------------- */
.field { display: block; margin-bottom: 16px; }
.field:last-of-type { margin-bottom: 20px; }
.field-label {
  display: block; margin-bottom: 6px;
  font-size: 12.5px; font-weight: 700; color: var(--text);
}
.field-label .req { color: var(--danger); margin-left: 2px; }
.field-help { display: block; margin-top: 4px; font-size: 12px; color: var(--text-faint); }
.field-error { display: block; margin-top: 4px; font-size: 12.5px; color: var(--danger); }
.field-row { display: flex; gap: 12px; }
.field-row > .field { flex: 1; min-width: 0; }

input[type="text"], input[type="password"], input[type="email"], input[type="url"],
input[type="tel"], input[type="number"], input[type="date"], input[type="time"],
input[type="datetime-local"], input[type="search"], select, textarea {
  width: 100%;
  padding: 9px 13px;
  font: inherit; font-size: 14px;
  color: var(--text);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--accent-hover);
  box-shadow: 0 0 0 4px rgba(30, 58, 110, .12);
}
input.has-error, select.has-error, textarea.has-error { border-color: var(--danger); }
input.has-error:focus { box-shadow: 0 0 0 3px var(--danger-soft); }
input::placeholder, textarea::placeholder { color: var(--text-faint); }
input[disabled], select[disabled], textarea[disabled] {
  background: var(--surface-alt); color: var(--text-faint); cursor: not-allowed;
}
textarea { min-height: 88px; resize: vertical; line-height: 1.55; }
select { appearance: none; padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
                    linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: calc(100% - 15px) 55%, calc(100% - 10px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
input[type="color"] {
  width: 46px; height: 34px; padding: 2px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); cursor: pointer;
}
input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

.checkbox-field { display: flex; align-items: center; gap: 9px; }
.checkbox-field input { margin: 0; flex: none; }

/* --------------------------------------------------------------------------
   Flashes, badges, chips
   -------------------------------------------------------------------------- */
.flash {
  padding: 11px 15px; margin-bottom: 16px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-alt);
  font-size: 13.5px;
}
.flash p { margin: 0 0 4px; }
.flash p:last-child { margin: 0; }
.flash-error   { background: var(--danger-soft);  border-color: var(--danger-border);  color: var(--danger); }
.flash-success { background: var(--success-soft); border-color: var(--success-border); color: var(--success); }
.flash-warning { background: var(--warn-soft);    border-color: var(--warn-border);    color: var(--warn); }

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 10px;
  font-size: 11.5px; font-weight: 600; line-height: 1.7;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface-alt); color: var(--text-muted);
  white-space: nowrap;
}
.badge-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.badge-terminal { text-decoration: none; opacity: .85; }
.badge-deleted { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 11px; margin: 0 4px 4px 0;
  font-size: 12.5px; font-weight: 600;
  background: var(--accent-soft); color: var(--accent-hover);
  border: 1px solid var(--accent-border); border-radius: 999px;
}
.chip button {
  border: 0; background: none; padding: 0; margin-left: 1px;
  color: inherit; cursor: pointer; font-size: 14px; line-height: 1; opacity: .7;
}
.chip button:hover { opacity: 1; }

.avatar {
  width: 24px; height: 24px; border-radius: 50%; object-fit: cover; flex: none;
  background: var(--bg-sunken); border: 1px solid var(--border);
}
.avatar-lg { width: 40px; height: 40px; }
.avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 600; color: var(--text-muted);
  background: var(--bg-sunken);
}
.avatar-fallback.avatar-lg { font-size: 15px; }

.user-ref { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.user-ref span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --------------------------------------------------------------------------
   Auth layout
   -------------------------------------------------------------------------- */
.auth-page { background: var(--bg); }
.auth-shell { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; }

/* The aside is the site's navy proof panel, watermarked with the same mark it
   carries there, so signing in reads as one step further into Reluty rather
   than as arriving at somebody else's software. */
.auth-aside {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; justify-content: center;
  gap: 20px;
  padding: 56px 8vw;
  background: linear-gradient(150deg, var(--navy-900) 0%, var(--navy-800) 55%, #17325C 100%);
  color: var(--on-dark);
}
.auth-aside::before {
  content: ""; position: absolute; right: -70px; bottom: -80px;
  width: 340px; height: 340px;
  background: url("../img/reluty-mark-dark.png") center / contain no-repeat;
  filter: invert(1); opacity: .06; pointer-events: none;
}
.auth-aside > * { position: relative; }
.auth-brand { margin-bottom: 10px; }
.auth-brand img { height: 40px; width: auto; }
.auth-eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  margin-bottom: 14px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-400);
}
.auth-eyebrow::before {
  content: ""; width: 22px; height: 2px; border-radius: 2px; flex: none;
  background: linear-gradient(135deg, #E8D39A 0%, #C9A24A 45%, #A8822E 100%);
}
.auth-pitch {
  font-family: var(--display); font-weight: 300;
  font-variation-settings: "SOFT" 100;
  font-size: 38px; line-height: 1.1; letter-spacing: -.02em;
  color: #fff; max-width: 13em;
}
.auth-pitch em { font-style: italic; color: var(--gold-400); }
.auth-pitch-body { font-size: 15.5px; line-height: 1.6; color: var(--on-dark-muted); max-width: 34em; }
.auth-points { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 0; font-size: 14px; }
.auth-points li { display: flex; align-items: flex-start; gap: 10px; color: var(--on-dark); }
.auth-points svg { width: 16px; height: 16px; flex: none; margin-top: 3px; color: var(--gold-400); }
.auth-facts { margin: 14px 0 0; font-size: 12px; }
.auth-facts div { display: flex; flex-direction: column; gap: 2px; }
.auth-facts dt { color: var(--on-dark-muted); letter-spacing: .06em; text-transform: uppercase; font-size: 10.5px; }
.auth-facts dd { margin: 0; color: var(--on-dark); word-break: break-all; }

.auth-main {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 40px 24px; background: var(--bg);
}
.auth-card {
  width: 100%; max-width: 400px;
  padding: 34px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.auth-card h2 {
  font-family: var(--display); font-weight: 400; font-variation-settings: "SOFT" 100;
  font-size: 30px; line-height: 1.1; letter-spacing: -.02em; margin-bottom: 6px;
}
.auth-sub { color: var(--text-muted); font-size: 14px; margin-bottom: 24px; }
.auth-alt { margin-top: 20px; font-size: 13.5px; color: var(--text-muted); text-align: center; }
.auth-back {
  display: inline-flex; align-items: center; gap: 8px;
  margin-bottom: 22px;
  font-size: 13px; font-weight: 600; color: var(--text-muted);
}
.auth-back:hover { color: var(--text); text-decoration: none; }
.auth-back svg { width: 15px; height: 15px; }
.auth-foot { margin-top: 22px; font-size: 12.5px; color: var(--text-faint); text-align: center; }
.auth-foot a { color: var(--text-muted); }

@media (max-width: 860px) {
  .auth-shell { grid-template-columns: 1fr; }
  .auth-aside { padding: 36px 24px; gap: 14px; }
  .auth-pitch { font-size: 28px; }
  .auth-pitch-body { font-size: 14px; }
  .auth-points, .auth-facts { display: none; }
  .auth-card { padding: 26px 20px; border: 0; box-shadow: none; background: transparent; }
}

/* --------------------------------------------------------------------------
   Boot / empty / error states
   -------------------------------------------------------------------------- */
.boot {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; min-height: 70vh; padding: 40px 20px;
  color: var(--text-muted); text-align: center;
}
.boot-error h1 {
  font-family: var(--display); font-weight: 400; font-variation-settings: "SOFT" 100;
  font-size: 26px; color: var(--text); margin-bottom: 6px;
}
.boot pre {
  padding: 10px 14px; background: var(--surface-alt);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 12.5px; overflow-x: auto; max-width: 100%;
}
.boot-spinner {
  width: 26px; height: 26px;
  border: 2.5px solid var(--border-strong); border-top-color: var(--action);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .boot-spinner { animation-duration: 2.5s; }
}

.empty {
  padding: 44px 24px; text-align: center; color: var(--text-muted);
}
.empty h3 {
  font-family: var(--display); font-weight: 400; font-variation-settings: "SOFT" 100;
  font-size: 22px; color: var(--text); margin-bottom: 6px;
}
.empty p { font-size: 13.5px; max-width: 44ch; margin-inline: auto; }

/* --------------------------------------------------------------------------
   App shell
   -------------------------------------------------------------------------- */
.app-page { background: var(--bg); }

.shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

/* Navy, in both themes. The site uses navy panels for the places it wants you
   to read as "this is Reluty speaking" -- the proof band, the footer -- and
   the sidebar is the app's version of that. It also means the chrome does not
   change colour when the theme does, which is what you want from furniture. */
.sidebar {
  display: flex; flex-direction: column;
  background: var(--chrome);
  color: var(--chrome-text);
  border-right: 1px solid rgba(0, 0, 0, .2);
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.sidebar-head {
  display: flex; align-items: center; gap: 9px;
  height: var(--header-h); padding: 0 18px;
  border-bottom: 1px solid var(--chrome-line);
  flex: none;
}
.sidebar-head img { height: 26px; width: auto; }
a.sidebar-head { color: inherit; }
a.sidebar-head:hover { background: rgba(255, 255, 255, .05); text-decoration: none; }
.sidebar-mark {
  font-family: var(--display); font-size: 20px; font-weight: 400;
  font-variation-settings: "SOFT" 100;
  color: var(--gold-400); letter-spacing: -.01em;
}
.sidebar-sub {
  font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--chrome-muted);
}

.sidebar-nav { padding: 14px 12px; flex: 1; }
.nav-section-title {
  padding: 16px 10px 6px;
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-400);
}
.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; margin-bottom: 2px;
  border-radius: var(--radius-pill);
  font-size: 13.5px; font-weight: 600; color: var(--chrome-muted);
  cursor: pointer; border: 0; background: none; width: 100%; text-align: left;
  font-family: inherit;
  transition: background .18s ease, color .18s ease;
}
.nav-item:hover { background: rgba(255, 255, 255, .07); color: #fff; text-decoration: none; }
.nav-item.active { background: var(--navy-600); color: #fff; font-weight: 700; }
.nav-swatch { width: 8px; height: 8px; border-radius: 50%; background: var(--chrome-muted); flex: none; }
.nav-item:hover .nav-swatch { background: var(--gold-300); }
.nav-item.active .nav-swatch { background: var(--gold-400); }
.nav-item .nav-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-count {
  font-size: 11.5px; font-weight: 600; color: var(--chrome-muted);
  font-variant-numeric: tabular-nums;
}
.nav-item.active .nav-count { color: var(--gold-400); }

.sidebar-foot { padding: 12px; border-top: 1px solid var(--chrome-line); flex: none; }

/* Shaped like a nav item because it is one, but marked as leaving the app:
   it opens Django's admin on the upstream API in a new tab. */
.sidebar-admin {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; margin-bottom: 4px;
  border-radius: var(--radius-pill);
  font-size: 13.5px; font-weight: 600; color: var(--chrome-muted);
}
.sidebar-admin:hover { background: rgba(255, 255, 255, .07); color: #fff; text-decoration: none; }
.sidebar-admin .nav-label { flex: 1; min-width: 0; }
.sidebar-admin-hint { flex: none; font-size: 11px; color: var(--chrome-muted); }

.sidebar-user {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--radius);
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--chrome-line);
  color: var(--chrome-text);
}
.sidebar-user:hover { background: rgba(255, 255, 255, .1); text-decoration: none; }
.sidebar-user .avatar { border-color: var(--chrome-line); background: rgba(255, 255, 255, .08); }
.sidebar-user .avatar-fallback { color: var(--gold-400); background: rgba(255, 255, 255, .08); }
.sidebar-user-meta { display: block; min-width: 0; flex: 1; }
.sidebar-user-name {
  display: block;
  font-size: 13px; font-weight: 700; color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar-user-sub {
  display: block;
  font-size: 11.5px; color: var(--chrome-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.main { min-width: 0; display: flex; flex-direction: column; }

/* Translucent and blurred, like the site header it is quoting. */
.topbar {
  display: flex; align-items: center; gap: 12px;
  height: var(--header-h); padding: 0 24px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
.topbar-search { flex: 1; max-width: 460px; position: relative; }
.topbar-search input { padding-left: 36px; border-radius: var(--radius-pill); }
.topbar-search::before {
  content: "⌕"; position: absolute; left: 14px; top: 50%; transform: translateY(-52%);
  color: var(--text-faint); font-size: 16px; pointer-events: none; z-index: 1;
}
.topbar-spacer { flex: 1; }
.topbar-actions { display: flex; align-items: center; gap: 8px; }

.live-dot {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-faint);
  padding: 4px 11px; border: 1px solid var(--border); border-radius: var(--radius-pill);
}
.live-dot i { width: 6px; height: 6px; border-radius: 50%; background: var(--text-faint); }
.live-dot.on i { background: var(--success); }
.live-dot.off i { background: var(--warn); }

.content { padding: 26px 24px 40px; flex: 1; min-width: 0; }
/* A screen that fills the viewport instead of growing the page, for the ones
   that scroll inside themselves -- see FULL_HEIGHT_SCREENS in App.jsx. The
   page-head keeps its natural height and whatever follows takes the rest, so
   nothing here has to guess how tall the heading came out. */
/* A screen that fills the viewport instead of growing the page -- see
   FULL_HEIGHT_SCREENS in App.jsx.

   The height has to be *definite*, not `flex: 1`: nothing above this is
   height-constrained (`.shell` sets a minimum, not a maximum), so a flex child
   with nothing but `flex-grow` sees unlimited free space and takes its content
   height. One viewport minus the topbar is the one number available here, and
   `--header-h` is the same variable the topbar is drawn from rather than a
   measurement copied by hand. What is *below* the topbar -- the heading, which
   wraps -- is then the flex algorithm's problem and not a constant. */
.content-fill {
  flex: none;
  height: calc(100vh - var(--header-h));
  display: flex; flex-direction: column;
  padding-bottom: 24px;
}
.content-fill > .page-head { flex: none; }
.content-narrow { max-width: 780px; }

.page-head {
  display: flex; align-items: flex-start; gap: 16px;
  margin-bottom: 22px; flex-wrap: wrap;
}
.page-head-text { flex: 1; min-width: 240px; }
.page-title {
  font-family: var(--display); font-weight: 400; font-variation-settings: "SOFT" 100;
  font-size: 32px; line-height: 1.1; letter-spacing: -.02em;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.page-title em { font-style: italic; color: var(--brand-em); }
.page-sub { margin-top: 6px; font-size: 13.5px; color: var(--text-muted); }
.page-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* The site's eyebrow rule, for a screen that wants one. */
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px; margin-bottom: 10px;
  font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--brand-ink);
}
.eyebrow::before {
  content: ""; width: 20px; height: 2px; border-radius: 2px; flex: none;
  background: var(--gold-grad);
}

.breadcrumbs {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-bottom: 12px; font-size: 12.5px; font-weight: 600; color: var(--text-muted);
}
.breadcrumbs a { color: var(--text-muted); }
.breadcrumbs a:hover { color: var(--accent-hover); }
.breadcrumbs .sep { color: var(--text-faint); }

/* --------------------------------------------------------------------------
   Cards, panels, tables
   -------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  margin-bottom: 18px;
  overflow: hidden;
}
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
}
.card-head h3 {
  font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent-hover);
}
.card-head .spacer { flex: 1; }
.card-body { padding: 18px; }
.card-body.tight { padding: 0; }

.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.data th, table.data td {
  padding: 9px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
table.data thead th {
  position: sticky; top: 0;
  background: var(--surface-alt);
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
  z-index: 1;
}
table.data thead th.sortable { cursor: pointer; user-select: none; }
table.data thead th.sortable:hover { color: var(--text); }
table.data thead th .sort-arrow { margin-left: 4px; color: var(--accent); }
table.data tbody tr:hover { background: var(--surface-hover); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.data td.shrink { width: 1%; white-space: nowrap; }
table.data .row-name { font-weight: 500; }
table.data tr.is-deleted td { opacity: .55; }

.cell-clip {
  display: block; max-width: 40ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cell-wrap { display: block; max-width: 52ch; }

.dl-grid { display: grid; grid-template-columns: minmax(140px, 190px) 1fr; gap: 1px; background: var(--border); }
.dl-grid > div { background: var(--surface); padding: 10px 16px; min-width: 0; }
.dl-grid dt {
  font-size: 12.5px; font-weight: 600; color: var(--text-muted);
  display: flex; align-items: center; gap: 6px;
}
.dl-grid dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.dl-empty { color: var(--text-faint); font-style: italic; font-size: 13px; }
@media (max-width: 640px) {
  .dl-grid { grid-template-columns: 1fr; }
  .dl-grid > div:nth-child(odd) { padding-bottom: 0; }
}

/* --------------------------------------------------------------------------
   Filters
   -------------------------------------------------------------------------- */
.filterbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 11px 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); margin-bottom: 14px;
}
.filterbar .grow { flex: 1; min-width: 170px; }
.filterbar select,
.filterbar input:not([type="checkbox"]) { width: auto; min-width: 120px; }
.filterbar input[type="checkbox"] { width: 16px; min-width: 0; flex: none; }
.filter-row {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding: 9px 14px; border-top: 1px dashed var(--border);
}
.filter-row select,
.filter-row input:not([type="checkbox"]) { min-width: 110px; }
.filter-row .val { flex: 1; min-width: 140px; }

.active-filters { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }

.pager {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 16px; border-top: 1px solid var(--border);
  font-size: 13px; color: var(--text-muted);
  background: var(--surface-alt);
}
.pager .spacer { flex: 1; }
.pager-info { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Detail view bits
   -------------------------------------------------------------------------- */
.state-badge { border-width: 1px; border-style: solid; font-weight: 500; }

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 22px; }
/* The site's stat tile: a Fraunces numeral over a quiet label, which is the
   one place the display face earns its keep at a glance. */
.stat {
  display: block; padding: 18px 20px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.stat-label { font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--accent-hover); }
.stat-value {
  font-family: var(--display); font-weight: 300; font-variation-settings: "SOFT" 100;
  font-size: 40px; line-height: 1.05; margin-top: 8px;
  font-variant-numeric: lining-nums tabular-nums; letter-spacing: -.02em;
  color: var(--text);
}
.stat-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 6px; }
a.stat:hover {
  text-decoration: none; border-color: var(--accent-border);
  transform: translateY(-3px); box-shadow: var(--shadow);
}
@media (prefers-reduced-motion: reduce) { a.stat:hover { transform: none; } }

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  position: relative;
  padding: 10px 16px 10px 40px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.timeline li:last-child { border-bottom: 0; }
.timeline li::before {
  content: ""; position: absolute; left: 19px; top: 16px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--border-strong); border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--border-strong);
}
.timeline li::after {
  content: ""; position: absolute; left: 22.5px; top: 26px; bottom: -2px;
  width: 1px; background: var(--border);
}
.timeline li:last-child::after { display: none; }
.timeline li.act-create::before { background: var(--success); box-shadow: 0 0 0 1px var(--success); }
.timeline li.act-delete::before { background: var(--danger);  box-shadow: 0 0 0 1px var(--danger); }
.timeline li.act-restore::before { background: var(--warn);   box-shadow: 0 0 0 1px var(--warn); }
.timeline-meta { color: var(--text-faint); font-size: 11.5px; margin-top: 2px; }
.timeline-diff { margin-top: 4px; font-size: 12.5px; }
.timeline-diff .old { color: var(--danger); text-decoration: line-through; opacity: .8; }
.timeline-diff .new { color: var(--success); }

.json-block {
  margin: 0; padding: 11px 13px;
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: 12px; line-height: 1.55;
  overflow-x: auto; max-height: 320px;
}

.color-swatch {
  display: inline-flex; align-items: center; gap: 7px;
}
.color-swatch i {
  width: 14px; height: 14px; border-radius: 3px;
  border: 1px solid var(--border-strong); flex: none;
}

.file-value { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.file-thumb {
  width: 56px; height: 56px; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--bg-sunken);
}

/* --------------------------------------------------------------------------
   Autocomplete picker
   -------------------------------------------------------------------------- */
.picker { position: relative; }
.picker-menu {
  position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; right: 0;
  max-height: 260px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
}
.picker-option {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 11px; cursor: pointer; font-size: 13.5px;
  border: 0; background: none; width: 100%; text-align: left; font-family: inherit; color: var(--text);
}
.picker-option:hover, .picker-option.highlight { background: var(--accent-soft); color: var(--accent); }
.picker-option .sub { color: var(--text-faint); font-size: 12px; margin-left: auto; }
.picker-status { padding: 9px 11px; font-size: 12.5px; color: var(--text-faint); }
.picker-selected {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  background: var(--surface-alt); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 13.5px;
}
.picker-selected .spacer { flex: 1; }

/* --------------------------------------------------------------------------
   Modal
   -------------------------------------------------------------------------- */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(15, 17, 21, .5);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  backdrop-filter: blur(2px);
}
.modal {
  width: 100%; max-width: 460px;
  max-height: calc(100vh - 48px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
}
.modal-head { padding: 16px 18px 0; }
.modal-head h3 { font-size: 16px; }
.modal-body { padding: 12px 18px; font-size: 13.5px; color: var(--text-muted); }
.modal-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 12px 18px 16px;
}

/* --------------------------------------------------------------------------
   Toasts
   -------------------------------------------------------------------------- */
/* Top right, not bottom right: the assistant launcher owns the bottom corner,
   and a toast that appears under a floating button is a toast nobody reads.

   Below the header rather than level with it -- at top: 18px a toast covers
   sign-out and the notification bell for as long as it is up, which is a way
   of interrupting somebody rather than informing them. */
.toasts {
  position: fixed; z-index: 200; right: 18px; top: calc(var(--header-h) + 12px);
  display: flex; flex-direction: column; gap: 8px;
  max-width: min(380px, calc(100vw - 36px));
  /* The column spans the page actions beneath it, so it must not swallow
     their clicks: only the toasts themselves are clickable, not the gaps
     between them or the empty space the column reserves. */
  pointer-events: none;
}
.toast { pointer-events: auto; }
.toast {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 13px;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--text-faint);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
  font-size: 13px;
  animation: toast-in .18s ease-out;
}
.toast.ok    { border-left-color: var(--success); }
.toast.error { border-left-color: var(--danger); }
.toast.info  { border-left-color: var(--accent); }
.toast .spacer { flex: 1; }
.toast button { border: 0; background: none; cursor: pointer; color: var(--text-faint); font-size: 15px; line-height: 1; padding: 0; }
@keyframes toast-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

/* --------------------------------------------------------------------------
   Skeletons
   -------------------------------------------------------------------------- */
.skeleton {
  background: linear-gradient(90deg, var(--surface-hover) 25%, var(--bg-sunken) 37%, var(--surface-hover) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
  border-radius: 4px;
  height: 12px;
}
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar {
    position: static; height: auto;
    border-right: 0; border-bottom: 1px solid var(--chrome-line);
  }
  .sidebar-nav { display: flex; gap: 4px; overflow-x: auto; padding: 8px 10px; }
  .nav-section-title { display: none; }
  .nav-item { width: auto; white-space: nowrap; }
  .sidebar-foot { display: none; }
  .content { padding: 16px; }
  .topbar { padding: 0 16px; }
}

/* --------------------------------------------------------------------------
   Messages
   -------------------------------------------------------------------------- */
.nav-badge {
  min-width: 18px; padding: 1px 6px;
  font-size: 11px; font-weight: 600; line-height: 1.5;
  text-align: center;
  color: var(--action-ink); background: var(--action);
  border-radius: 999px;
}

/* The pane pair fills whatever `.content-fill` has left below the heading, so
   the thread scrolls inside itself rather than the page growing and the
   composer sliding away. It used to subtract a guessed 96px from the viewport
   for the heading above it; the heading is taller than that and wraps at
   narrow widths, so the panel overhung the fold and the page scrolled for the
   difference. Now the flex parent does the arithmetic. */
.chat {
  display: grid;
  grid-template-columns: minmax(240px, 300px) 1fr;
  flex: 1; min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

/* Grid and flex children default to min-height:auto, which is their *content*
   height. Without this the message list pushes the whole panel taller than the
   height set above: the page scrolls instead of the thread, and the composer
   and conversation list drift off screen. */
.chat > * { min-height: 0; }

.chat-list {
  border-right: 1px solid var(--border);
  overflow-y: auto;
  background: var(--surface-alt);
}
.chat-list-empty { padding: 20px 16px; font-size: 13px; color: var(--text-muted); }

.chat-row {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%; padding: 11px 13px;
  border: 0; border-bottom: 1px solid var(--border);
  background: none; cursor: pointer; text-align: left;
  font-family: inherit; color: var(--text);
}
.chat-row:hover { background: var(--surface-hover); }
.chat-row.active { background: var(--accent-soft); }
.chat-row.active .chat-row-title { color: var(--accent); }
.chat-row-body { flex: 1; min-width: 0; }
.chat-row-top { display: flex; align-items: baseline; gap: 8px; }
.chat-row-title {
  flex: 1; min-width: 0;
  font-size: 13.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-row-time { font-size: 11px; color: var(--text-faint); white-space: nowrap; }
.chat-row-preview {
  display: block; margin-top: 2px;
  font-size: 12.5px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-unread {
  min-width: 18px; padding: 1px 6px; margin-top: 2px;
  font-size: 11px; font-weight: 600; line-height: 1.5; text-align: center;
  color: #fff; background: var(--accent); border-radius: 999px;
}

.chat-thread { display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.chat-head {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px; border-bottom: 1px solid var(--border);
  background: var(--surface-alt); flex: none;
}
.chat-head h2 { font-size: 15px; }
.chat-head-sub {
  margin: 2px 0 0; font-size: 12px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.chat-messages {
  flex: 1; min-height: 0; overflow-y: auto; padding: 16px 18px;
  display: flex; flex-direction: column; gap: 2px;
}
.chat-more {
  text-align: center; font-size: 12px; color: var(--text-faint);
  padding-bottom: 10px; margin: 0;
}

.bubble-row { display: flex; align-items: flex-end; gap: 8px; margin-top: 10px; }
.bubble-row.grouped { margin-top: 2px; }
.bubble-row.mine { flex-direction: row-reverse; }
.bubble-spacer { width: 24px; flex: none; }
.bubble-stack { display: flex; flex-direction: column; max-width: min(560px, 76%); min-width: 0; }
.bubble-row.mine .bubble-stack { align-items: flex-end; }

.bubble-author {
  font-size: 11.5px; font-weight: 600; color: var(--text-muted);
  margin: 0 0 3px 2px;
}
.bubble {
  padding: 8px 12px;
  background: var(--surface-hover);
  border: 1px solid var(--border);
  border-radius: 14px 14px 14px 4px;
  font-size: 13.5px; line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.bubble-row.mine .bubble {
  background: var(--accent); border-color: var(--accent); color: #fff;
  border-radius: 14px 14px 4px 14px;
}
.bubble-row.grouped .bubble { border-radius: 14px; }
.bubble.pending { opacity: .6; }
.bubble.failed { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.bubble-gone {
  background: transparent; border-style: dashed;
  color: var(--text-faint); font-style: italic;
}
.bubble-editing { width: 100%; background: var(--surface); }
.bubble-editing textarea { min-height: 54px; font-size: 13.5px; }

.bubble-meta {
  margin: 3px 2px 0;
  font-size: 11px; color: var(--text-faint);
}
.bubble-action {
  border: 0; background: none; padding: 0;
  font: inherit; font-size: 11px; color: var(--text-faint);
  cursor: pointer; text-decoration: underline;
}
.bubble-action:hover { color: var(--accent); }

.chat-typing {
  height: 20px; padding: 0 18px; flex: none;
  font-size: 12px; color: var(--text-muted);
}
.chat-dots { display: inline-flex; gap: 2px; margin-left: 5px; vertical-align: middle; }
.chat-dots i {
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--text-faint);
  animation: chat-dot 1.2s infinite ease-in-out;
}
.chat-dots i:nth-child(2) { animation-delay: .15s; }
.chat-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes chat-dot { 0%, 60%, 100% { opacity: .3; } 30% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .chat-dots i { animation: none; } }

.chat-composer {
  display: flex; gap: 8px; align-items: flex-end;
  padding: 12px 18px; border-top: 1px solid var(--border);
  background: var(--surface-alt); flex: none;
}
.chat-composer textarea {
  flex: 1; min-height: 38px; max-height: 160px;
  padding: 9px 12px; border-radius: 18px; resize: none; line-height: 1.45;
}
.chat-composer .btn { border-radius: 18px; padding-inline: 18px; }

@media (max-width: 900px) {
  /* One pane at a time on a phone: the list until a thread is open, and the
     thread once it is, which is what the URL already distinguishes. */
  .chat { grid-template-columns: 1fr; height: auto; }
  .chat-list { max-height: 220px; border-right: 0; border-bottom: 1px solid var(--border); }
  .chat-thread { min-height: 60vh; }
  .bubble-stack { max-width: 86%; }
}

/* Where a viewport-high panel would be unusably short -- a phone, or a window
   dragged down to a strip -- the page goes back to growing and scrolling.
   Squeezing the composer and the thread into 200px is worse than a scrollbar,
   which is the thing being avoided everywhere else on this screen. */
@media (max-width: 900px), (max-height: 620px) {
  .content-fill { display: block; height: auto; padding-bottom: 40px; }
}
/* On a short *wide* window the panes stay side by side at a fixed height; the
   phone rules above already stack them, and applying both would give a 460px
   box asked to hold a 220px list above a 60vh thread. */
@media (min-width: 901px) and (max-height: 620px) {
  .content-fill > .chat { flex: none; height: 460px; }
}

/* --------------------------------------------------------------------------
   Chat toasts
   -------------------------------------------------------------------------- */
.toast-close {
  border: 0; background: none; cursor: pointer;
  color: var(--text-faint); font-size: 15px; line-height: 1; padding: 0;
  flex: none;
}
.toast-close:hover { color: var(--text); }

/* The notification body is the primary action, so it is a real button --
   full-width, inheriting the toast's type rather than a button's. */
.toast-body {
  flex: 1; min-width: 0;
  display: block; text-align: left;
  padding: 0; border: 0; background: none;
  font: inherit; color: inherit; cursor: pointer;
}
.toast.clickable { padding-right: 10px; }
.toast.clickable:hover { border-color: var(--accent-border); }

.toast-chat { display: flex; align-items: flex-start; gap: 9px; }
.toast-chat-text { min-width: 0; flex: 1; }
.toast-chat-name {
  display: block;
  font-size: 12.5px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.toast-chat-body {
  display: block; margin-top: 1px;
  font-size: 12.5px; color: var(--text-muted); line-height: 1.4;
  /* Two lines of preview, then ellipsis -- enough to know whether it can wait. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
}

/* Participant strip in the thread header. */
.chat-head-text { min-width: 0; flex: 1; }
.chat-head-people { display: flex; flex: none; }
.chat-head-people > * { margin-left: -6px; box-shadow: 0 0 0 2px var(--surface-alt); }
.chat-head-people > *:first-child { margin-left: 0; }
@media (max-width: 640px) {
  .chat-head-people { display: none; }
}

/* --------------------------------------------------------------------------
   Notifications
   -------------------------------------------------------------------------- */
.bell { position: relative; }
.bell-button {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  font-size: 15px; line-height: 1;
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  cursor: pointer;
}
.bell-button:hover { background: var(--surface-hover); border-color: var(--border); }
/* The messages button is an anchor rather than a button -- it goes to a
   screen -- so it has to be talked out of looking like body copy. */
a.bell-button { text-decoration: none; color: inherit; }
.bell-button.active { background: var(--surface-hover); border-color: var(--border); }
.bell-count {
  position: absolute; top: -3px; right: -4px;
  min-width: 16px; padding: 0 4px;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  color: #fff; background: var(--danger);
  border: 2px solid var(--surface); border-radius: 999px;
}

.bell-panel {
  position: absolute; z-index: 60; top: calc(100% + 8px); right: 0;
  width: min(380px, calc(100vw - 32px));
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.bell-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border);
  background: var(--surface-alt); font-size: 13.5px;
}
.bell-head .spacer { flex: 1; }
.bell-list { max-height: min(60vh, 420px); overflow-y: auto; }
.bell-empty { padding: 22px 16px; font-size: 13px; color: var(--text-muted); text-align: center; }
.bell-foot { padding: 8px; border-top: 1px solid var(--border); background: var(--surface-alt); }

/* One row, shared by the panel and the full screen. */
.note-row {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%; padding: 11px 13px;
  border: 0; border-bottom: 1px solid var(--border);
  background: none; text-align: left; cursor: pointer;
  font-family: inherit; color: var(--text);
}
.note-row:hover { background: var(--surface-hover); }
.note-row:last-child { border-bottom: 0; }
.note-row.unread { background: var(--accent-soft); }
.note-row.unread:hover { background: var(--accent-soft); filter: brightness(.98); }

.note-body { flex: 1; min-width: 0; }
.note-title { display: block; font-size: 13.5px; font-weight: 600; line-height: 1.35; }
.note-text {
  display: block; margin-top: 2px;
  font-size: 12.5px; color: var(--text-muted); line-height: 1.45;
  overflow-wrap: anywhere;
}
.note-meta {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin-top: 4px; font-size: 11.5px; color: var(--text-faint);
}
.note-kind {
  margin-left: auto; padding: 0 5px;
  font-size: 10.5px; line-height: 1.6;
  border: 1px solid var(--border); border-radius: 4px; color: var(--text-faint);
}
.note-dot {
  width: 7px; height: 7px; margin-top: 6px; flex: none;
  background: var(--accent); border-radius: 50%;
}
.note-list { display: flex; flex-direction: column; }

.toast-bell {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex: none; font-size: 14px;
}

@media (max-width: 640px) {
  .bell-panel { position: fixed; top: calc(var(--header-h) + 6px); right: 12px; left: 12px; width: auto; }
}

/* The row is a container; the opening action inside it is the button. */
.note-open {
  display: flex; align-items: flex-start; gap: 10px;
  flex: 1; min-width: 0; padding: 0;
  border: 0; background: none; text-align: left; cursor: pointer;
  font: inherit; color: inherit;
}
.note-toggle {
  flex: none; align-self: center;
  padding: 3px 8px;
  font: inherit; font-size: 11.5px;
  color: var(--text-faint); background: none;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: pointer; opacity: 0; transition: opacity .12s ease;
}
.note-row:hover .note-toggle, .note-toggle:focus-visible { opacity: 1; }
.note-toggle:hover { color: var(--text); border-color: var(--border-strong); }
@media (hover: none) {
  /* No hover to reveal it on a touch screen. */
  .note-toggle { opacity: 1; }
}

/* A result set being replaced: visibly not the answer to what was just asked. */
.table-wrap.is-updating {
  opacity: .45;
  transition: opacity .12s ease;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Message reactions
   -------------------------------------------------------------------------- */
.reactions {
  position: relative;
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin-top: 4px;
}
.bubble-row.mine .reactions { justify-content: flex-end; }

.reaction {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px;
  font: inherit; font-size: 12px; line-height: 1.7;
  background: var(--surface); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 999px;
  cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}
.reaction:hover { border-color: var(--border-strong); background: var(--surface-hover); }
.reaction.mine {
  background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent);
  font-weight: 600;
}
.reaction-emoji { font-size: 13px; line-height: 1; }
.reaction-count { font-variant-numeric: tabular-nums; }

/* Revealed on hover so a quiet thread is not a field of + buttons, but always
   present for keyboard and touch, which have no hover to reveal it. */
.reaction-add { opacity: 0; padding-inline: 8px; font-weight: 600; }
.bubble-row:hover .reaction-add,
.reaction-add:focus-visible,
.reaction-add[aria-expanded="true"] { opacity: 1; }
@media (hover: none) { .reaction-add { opacity: 1; } }

/* One horizontal row, deliberately not wrapping. It used to wrap inside a
   260px box, which put the palette two rows tall and made it tall enough to be
   clipped by the scrolling message list above it. A quick-pick row is a row. */
.reaction-palette {
  position: absolute; z-index: 45; bottom: calc(100% + 6px); left: 0;
  display: flex; align-items: center; gap: 2px; flex-wrap: nowrap;
  width: max-content; max-width: none; padding: 5px 6px;
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: 999px;
  box-shadow: var(--shadow-lg);
}
.bubble-row.mine .reaction-palette { left: auto; right: 0; }
.reaction-palette button {
  padding: 4px 6px; font-size: 17px; line-height: 1;
  background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer;
}
.reaction-palette button:hover { background: var(--surface-hover); }
.reaction-palette button.held { background: var(--accent-soft); }

/* --------------------------------------------------------------------------
   Mentions
   -------------------------------------------------------------------------- */
.mention {
  padding: 0 2px; border-radius: 3px;
  font-weight: 600; color: var(--accent);
  background: var(--accent-soft);
}
/* Your own name reads differently on purpose: in a busy group the question is
   "was that aimed at me", and a uniform highlight does not answer it. */
.mention-me { color: #fff; background: var(--accent); }
.bubble-row.mine .mention { background: rgba(255, 255, 255, .22); color: inherit; }
.bubble-row.mine .mention-me { background: rgba(255, 255, 255, .35); }

.composer-field { position: relative; flex: 1; display: flex; }
.composer-field textarea { flex: 1; }

.mention-menu {
  position: absolute; z-index: 50; bottom: calc(100% + 6px); left: 0;
  width: min(320px, 100%);
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.mention-option {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 7px 10px;
  border: 0; background: none; cursor: pointer; text-align: left;
  font: inherit; font-size: 13.5px; color: var(--text);
}
.mention-option.highlight { background: var(--accent-soft); color: var(--accent); }
.mention-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mention-username { font-size: 12px; color: var(--text-faint); }
.mention-option.highlight .mention-username { color: var(--accent); }

/* --------------------------------------------------------------------------
   Conversation name
   -------------------------------------------------------------------------- */
.chat-title-static { font-size: 15px; font-weight: 600; }

.chat-title {
  display: flex; align-items: baseline; gap: 8px;
  max-width: 100%; padding: 2px 6px; margin-left: -6px;
  font: inherit; font-size: 15px; font-weight: 600;
  color: var(--text); background: none;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  cursor: text; text-align: left;
}
.chat-title:hover { background: var(--surface-hover); border-color: var(--border); }
.chat-title > span:first-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-title.unnamed > span:first-child { color: var(--text-muted); font-weight: 500; }

/* The affordance is always visible, just quiet. It used to appear only on
   hover, on the theory that a permanent "Rename" beside every title is
   clutter -- but a heading that looks exactly like static text is a control
   nobody finds, and hover is not a thing that exists on a touch screen. It
   brightens on hover instead of appearing. */
.chat-title-hint {
  flex: none; font-size: 11.5px; font-weight: 500; color: var(--text-faint);
  opacity: .65; transition: opacity .12s ease;
}
.chat-title:hover .chat-title-hint,
.chat-title:focus-visible .chat-title-hint,
.chat-title.unnamed .chat-title-hint { opacity: 1; }

.chat-title-edit { display: block; }
.chat-title-edit input {
  width: min(360px, 100%); padding: 3px 8px;
  font: inherit; font-size: 15px; font-weight: 600;
}

/* The name stays an <h2> whether or not it is editable, so the heading's own
   margins and weight must not fight the control inside it. */
.chat-title-wrap, .chat-title-edit { margin: 0; font-size: inherit; font-weight: inherit; }

/* --------------------------------------------------------------------------
   Boards
   -------------------------------------------------------------------------- */

/* Visually hidden, still read aloud. The move control on a card is a bare
   select; its label belongs to screen readers, not to the layout. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* The site's tab pill: one track, and the current view is a filled pill
   inside it rather than two buttons welded together. */
.view-toggle {
  display: inline-flex; gap: 3px; padding: 3px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}
.view-toggle .btn { border-color: transparent; background: transparent; color: var(--text-muted); }
.view-toggle .btn:not([disabled]):hover { background: var(--surface-hover); border-color: transparent; color: var(--text); }
.view-toggle .btn.is-current,
.view-toggle .btn.is-current:not([disabled]):hover {
  background: var(--accent-hover); border-color: var(--accent-hover);
  color: var(--accent-ink); font-weight: 700;
}

/* The board scrolls sideways as a whole and each column scrolls on its own.
   min-height on the track is what stops a tall column from pushing the page
   instead of scrolling inside itself. */
.board {
  display: flex; gap: 12px; align-items: flex-start;
  overflow-x: auto; padding-bottom: 8px;
}
.board.is-updating { opacity: .65; transition: opacity .12s ease; }

.board-col {
  flex: 0 0 300px; max-width: 300px;
  display: flex; flex-direction: column; min-height: 0;
  background: var(--surface-sunken, var(--surface-hover));
  border: 1px solid var(--border); border-radius: var(--radius);
}
/* The drop target has to be obvious while a card is in the air, since the
   cursor is the only other thing saying where it would land. */
.board-col.is-over {
  border-color: var(--accent-border); background: var(--accent-soft);
}

.board-col-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border);
}
.board-col-dot {
  flex: none; width: 9px; height: 9px; border-radius: 999px;
  background: var(--text-faint);
}
.board-col-title {
  flex: 1; min-width: 0; margin: 0;
  font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-col-count {
  flex: none; padding: 1px 7px; border-radius: 999px;
  font-size: 11.5px; font-variant-numeric: tabular-nums;
  background: var(--surface); border: 1px solid var(--border); color: var(--text-muted);
}

.board-col-body {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px; overflow-y: auto; max-height: 68vh; min-height: 90px;
}
.board-col-empty {
  margin: 0; padding: 12px 4px; text-align: center;
  font-size: 12.5px; color: var(--text-faint);
}
.board-more { align-self: stretch; }

.board-card {
  display: flex; flex-direction: column; gap: 5px;
  padding: 9px 10px;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: grab;
}
.board-card:hover { border-color: var(--border-strong); }
.board-card:active { cursor: grabbing; }
/* A card mid-save is not draggable and says so, rather than accepting a
   second move that would race the first. */
.board-card.is-busy { opacity: .55; cursor: progress; }

.board-card-name { font-size: 13px; font-weight: 600; }
.board-card-key { font-size: 11px; color: var(--text-faint); }

.board-card-fields { display: grid; gap: 2px; margin: 2px 0 0; }
.board-card-fields > div { display: flex; gap: 6px; align-items: baseline; }
.board-card-fields dt {
  flex: none; font-size: 11px; color: var(--text-faint);
  max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-card-fields dd {
  margin: 0; min-width: 0; font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.board-card-move select {
  width: 100%; margin-top: 4px; padding: 2px 6px;
  font-size: 11.5px; color: var(--text-muted);
}

/* On a narrow screen the columns stack: a 300px track beside another is a
   horizontal scroll inside a horizontal scroll, and dragging between two
   columns you cannot see at once is not a feature. */
@media (max-width: 640px) {
  .board { flex-direction: column; overflow-x: visible; }
  .board-col { flex: 1 1 auto; max-width: 100%; width: 100%; }
  .board-col-body { max-height: none; }
}

/* --------------------------------------------------------------------------
   Export
   -------------------------------------------------------------------------- */
.export-wrap { position: relative; display: inline-flex; }
.export-menu {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0;
  width: 290px; padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  text-align: left;
}
.export-note {
  margin: 2px 4px 8px; font-size: 11.5px; color: var(--text-muted); line-height: 1.45;
}
.export-warn { color: var(--warning, var(--text-muted)); }

.export-choice {
  display: flex; flex-direction: column; gap: 1px; width: 100%;
  padding: 7px 8px; margin-bottom: 2px;
  font: inherit; text-align: left; cursor: pointer;
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--text);
}
.export-choice:hover:not([disabled]) {
  background: var(--surface-hover); border-color: var(--border);
}
.export-choice[disabled] { opacity: .5; cursor: default; }
.export-choice strong { font-size: 13px; font-weight: 600; }
.export-choice span { font-size: 11.5px; color: var(--text-faint); }

/* --------------------------------------------------------------------------
   The assistant
   -------------------------------------------------------------------------- */
.assistant-launcher {
  position: fixed; z-index: 190; right: 20px; bottom: 20px;
  width: 46px; height: 46px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--action); border-radius: 999px;
  background: var(--action); color: var(--action-ink);
  box-shadow: var(--shadow-lg); cursor: pointer;
  font-size: 22px; line-height: 1;
  transition: transform .12s ease, background .12s ease;
}
.assistant-launcher:hover { transform: translateY(-1px); }
.assistant-launcher.is-open { background: var(--surface); color: var(--text-muted); border-color: var(--border-strong); }
@media (prefers-reduced-motion: reduce) { .assistant-launcher { transition: none; } }

.assistant-panel {
  position: fixed; z-index: 190; right: 20px; bottom: 78px;
  width: min(400px, calc(100vw - 40px));
  /* Bounded by the viewport rather than a fixed height, so a short window does
     not push the composer off the bottom of the screen. */
  max-height: min(620px, calc(100vh - 110px));
  display: flex; flex-direction: column; min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

.assistant-head {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 10px 9px 14px; border-bottom: 1px solid var(--border); flex: none;
}
.assistant-head h2 { margin: 0; font-size: 14px; font-weight: 600; }
.assistant-head .spacer { flex: 1; }
.assistant-close {
  border: 0; background: none; cursor: pointer;
  color: var(--text-faint); font-size: 18px; line-height: 1; padding: 0 4px;
}

.assistant-notice {
  margin: 0; padding: 8px 14px; flex: none;
  font-size: 11.5px; line-height: 1.45; color: var(--text-muted);
  background: var(--surface-hover); border-bottom: 1px solid var(--border);
}

.assistant-body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 12px 14px; display: flex; flex-direction: column; gap: 10px;
}
.assistant-empty, .assistant-thinking {
  margin: 0; font-size: 12.5px; color: var(--text-faint); text-align: center; padding: 8px;
}

.assistant-opening { font-size: 12.5px; color: var(--text-muted); line-height: 1.5; }
.assistant-opening p { margin: 0 0 8px; }
.assistant-hint { display: flex; flex-direction: column; gap: 4px; }
.assistant-hint code {
  align-self: flex-start; padding: 2px 6px;
  background: var(--surface-hover); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 11.5px;
}

.assistant-turn { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.assistant-turn.mine { align-items: flex-end; }
.assistant-bubble {
  max-width: 88%; padding: 8px 11px;
  background: var(--surface-hover); border-radius: 12px;
  font-size: 13px; line-height: 1.5; white-space: pre-wrap;
}
.assistant-turn.mine .assistant-bubble { background: var(--accent); color: #fff; }
:root[data-theme="dark"] .assistant-turn.mine .assistant-bubble { color: var(--navy-900); }
.assistant-when { font-size: 10.5px; color: var(--text-faint); }

/* A proposal is set apart from the conversation on purpose: it is the one
   thing on this panel that can change data, and it should not read as more
   chat. */
.proposal {
  align-self: stretch; margin-top: 2px;
  padding: 10px 11px;
  background: var(--surface);
  border: 1px solid var(--accent-border); border-left-width: 3px;
  border-radius: var(--radius-sm);
}
.proposal-applied   { border-color: var(--success, var(--border)); opacity: .85; }
.proposal-discarded { border-color: var(--border); opacity: .6; }
.proposal-failed    { border-color: var(--danger, var(--border)); }

.proposal-head { display: flex; align-items: baseline; gap: 7px; margin-bottom: 4px; }
.proposal-kind {
  flex: none; padding: 1px 6px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
  font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.proposal-target { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.proposal-summary { margin: 0 0 6px; font-size: 12.5px; }

.proposal-changes { display: grid; gap: 2px; margin: 0 0 8px; }
.proposal-changes > div { display: flex; gap: 8px; align-items: baseline; }
.proposal-changes dt { flex: none; min-width: 74px; font-size: 11px; color: var(--text-faint); }
.proposal-changes dd { margin: 0; font-size: 12px; min-width: 0; word-break: break-word; }

.proposal-actions { display: flex; gap: 6px; }
.proposal-outcome { margin: 0; font-size: 11.5px; color: var(--text-muted); }

.assistant-composer {
  flex: none; display: flex; gap: 6px; align-items: flex-end;
  padding: 9px 10px; border-top: 1px solid var(--border);
}
.assistant-composer textarea {
  flex: 1; min-height: 34px; max-height: 120px; resize: vertical;
  padding: 7px 9px; font: inherit; font-size: 13px;
}

.assistant-history { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; }
.assistant-history-row { display: flex; align-items: center; gap: 4px; }
.assistant-history-row.is-current { background: var(--accent-soft); border-radius: var(--radius-sm); }
.assistant-history-open {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px;
  padding: 7px 8px; text-align: left;
  background: none; border: 0; border-radius: var(--radius-sm);
  cursor: pointer; font: inherit; color: inherit;
}
.assistant-history-open:hover { background: var(--surface-hover); }
.assistant-history-title {
  font-size: 12.5px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.assistant-history-when { font-size: 10.5px; color: var(--text-faint); }
.assistant-history-delete {
  flex: none; border: 0; background: none; cursor: pointer;
  color: var(--text-faint); font-size: 15px; line-height: 1; padding: 0 6px;
}

/* On a phone the panel is the screen, and the launcher would sit on top of its
   own composer. */
@media (max-width: 520px) {
  .assistant-panel {
    right: 8px; left: 8px; bottom: 8px; width: auto;
    max-height: calc(100vh - 80px);
  }
  .assistant-launcher { right: 12px; bottom: 12px; }
  .assistant-launcher.is-open { display: none; }
}

/* --------------------------------------------------------------------------
   Reports
   -------------------------------------------------------------------------- */
.report-list {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.report-card {
  display: flex; flex-direction: column; gap: 4px;
  padding: 13px 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); color: inherit;
}
.report-card:hover { border-color: var(--accent-border); text-decoration: none; }
.report-card.is-broken { opacity: .75; border-style: dashed; }
.report-card-name { font-size: 14px; font-weight: 600; }
.report-card-desc { font-size: 12.5px; color: var(--text-muted); line-height: 1.45; }
.report-card-meta { font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }
.report-card-error { margin: 6px 0 0; font-size: 11.5px; color: var(--danger, var(--text-muted)); }

.page-crumb { margin: 0 0 2px; font-size: 12px; }

.report-params .card-body { display: flex; flex-direction: column; gap: 2px; }
.report-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }

.report-result-head { display: flex; align-items: flex-start; gap: 8px; }
.report-result-head .spacer { flex: 1; }
.report-result-head h3 { margin: 0; }

/* What the report was run with. Without it a printed table of numbers has no
   stated scope, which is how the wrong quarter gets into a board pack. */
.report-scope { margin: 3px 0 0; font-size: 11.5px; color: var(--text-muted); }
.report-scope-item + .report-scope-item::before { content: ' · '; color: var(--text-faint); }

.report-notes {
  margin: 0; padding: 9px 16px;
  font-size: 12.5px; color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}
.report-truncated {
  margin: 0; padding: 9px 16px;
  font-size: 12.5px; color: var(--warning, var(--text));
  background: var(--surface-hover); border-bottom: 1px solid var(--border);
}

.report-table .align-right { text-align: right; }
.report-table tfoot td {
  font-weight: 600;
  border-top: 2px solid var(--border-strong);
  background: var(--surface-hover);
}

/* The parameter builder on the new-report form. Each row is one parameter, so
   it is boxed: a flat list of inputs gives no clue where one ends. */
.param-row {
  display: flex; flex-direction: column; gap: 6px;
  padding: 9px 10px; margin-bottom: 8px;
  background: var(--surface-hover);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.param-row-head { display: flex; gap: 6px; align-items: center; }
.param-row-head input:first-child { flex: 0 0 110px; }
.param-row-head input:nth-child(2) { flex: 1; min-width: 0; }
.param-row-head select { flex: 0 0 140px; }

.param-row-body { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
/* Its own line inside a modal: at the width this sits in, sharing a row with
   the two checkboxes truncates it to "No choices — a plain con". */
.param-row-body select { flex: 1 1 100%; min-width: 0; }
.param-row-body .checkbox-field { margin: 0; font-size: 12.5px; white-space: nowrap; }
.param-row input, .param-row select { font-size: 12.5px; }
.param-help { width: 100%; }

.param-remove {
  flex: none; border: 0; background: none; cursor: pointer;
  color: var(--text-faint); font-size: 16px; line-height: 1; padding: 0 5px;
}
.param-remove:hover { color: var(--danger, var(--text)); }

.param-choices {
  display: flex; flex-direction: column; gap: 4px;
  padding: 7px 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.param-choice { display: flex; gap: 6px; align-items: center; }
.param-choice input:first-child { flex: 0 0 120px; }
.param-choice input:nth-child(2) { flex: 1; min-width: 0; }

@media (max-width: 560px) {
  .param-row-head { flex-wrap: wrap; }
  .param-row-head input:first-child, .param-row-head select { flex: 1 1 100%; }
}

/* --------------------------------------------------------------------------
   Contracts, receivables and the ledger
   -------------------------------------------------------------------------- */
.field-inline {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text-muted); white-space: nowrap;
}
.field-inline input { font-size: 12.5px; }

.money-cards {
  display: grid; gap: 10px; margin-bottom: 14px;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
.money-card {
  display: flex; flex-direction: column; gap: 3px;
  padding: 13px 15px;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong); border-radius: var(--radius);
}
.money-card-label {
  font-size: 11px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-faint);
}
.money-card-value { font-size: 21px; font-weight: 600; font-variant-numeric: tabular-nums; }
/* A balance is the number people look for, so it says which way it went. */
.money-card.owing { border-left-color: var(--danger, var(--text)); }
.money-card.owing .money-card-value { color: var(--danger, inherit); }
.money-card.clear { border-left-color: var(--success, var(--text)); }

.align-right { text-align: right; }
table.data tr.is-selected > td { background: var(--accent-soft); }

.ledger-head { display: flex; align-items: center; gap: 8px; }
.ledger-head .spacer { flex: 1; }
.ledger-note {
  margin: 0; padding: 8px 16px;
  font-size: 11.5px; color: var(--text-muted);
  background: var(--surface-hover); border-bottom: 1px solid var(--border);
}
.ledger-table tfoot td {
  font-weight: 600;
  border-top: 2px solid var(--border-strong);
  background: var(--surface-hover);
}
.badge.debit  { color: var(--danger, var(--text)); border-color: var(--danger, var(--border)); }
.badge.credit { color: var(--success, var(--text)); border-color: var(--success, var(--border)); }

/* Eight money fields side by side rather than eight stacked rows: they are
   read as a block on an invoice, not as a questionnaire. */
.money-grid {
  display: grid; gap: 0 10px;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}
.row-actions { display: flex; gap: 5px; justify-content: flex-end; }

.documents { display: grid; gap: 14px; }
.document { display: flex; flex-direction: column; gap: 4px; }
.document-held { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }

/* --------------------------------------------------------------------------
   Publishing
   -------------------------------------------------------------------------- */
/* One card per activity, so a heading and its lines read as a unit rather
   than as rows in a single long table that has lost its grouping. */
.activity-card { margin-bottom: 12px; }
.activity-head { display: flex; align-items: flex-start; gap: 8px; }
.activity-head .spacer { flex: 1; }
.activity-head h3 { margin: 0; }
.activity-section { margin: 2px 0 0; font-size: 12px; color: var(--text-muted); }

/* --------------------------------------------------------------------------
   Theme control
   -------------------------------------------------------------------------- */
.theme-wrap { position: relative; display: inline-flex; }
.theme-button {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--text-muted); cursor: pointer;
}
.theme-button:hover { background: var(--surface-hover); color: var(--text); border-color: var(--border); }

.theme-menu {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0;
  width: 190px; padding: 5px;
  background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}
.theme-choice {
  display: flex; flex-direction: column; gap: 1px; width: 100%;
  padding: 6px 8px;
  font: inherit; text-align: left; cursor: pointer;
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--text);
}
.theme-choice:hover { background: var(--surface-hover); }
.theme-choice.is-current { background: var(--accent-soft); color: var(--accent); }
.theme-choice-label { font-size: 13px; font-weight: 500; }
.theme-choice-hint { font-size: 11px; color: var(--text-faint); }
.theme-choice.is-current .theme-choice-hint { color: var(--accent); opacity: .8; }

/* --------------------------------------------------------------------------
   Contacts
   -------------------------------------------------------------------------- */
.contact-address { font-size: 12.5px; }
.contact-reach { display: flex; flex-direction: column; gap: 1px; font-size: 12.5px; }

.contact-panels {
  display: grid; gap: 12px; margin-bottom: 12px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
/* An address is written one line per line, which is the whole point of the
   server assembling them in writing order. */
.contact-lines { display: flex; flex-direction: column; font-style: normal; font-size: 13.5px; }
.contact-directions {
  margin: 10px 0 0; padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-muted);
}
