
:root {
  /* System stacks stand in for the self-hosted Satoshi/Instrument faces. */
  --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-display: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --bg: #FFFFFF;
  --bg-secondary: #FCFCFC;
  --bg-hover: #EEEEEC;
  --text: #111827;
  --text-secondary: #4B5563;
  --text-muted: #636970;

  /* Controls stay neutral (LazyLips brand): --accent is the dark control color.
     Accent color only where it carries meaning — the brand trio below. */
  --accent: #111827;
  --accent-hover: #1E293B;
  --brand: #0a86ff;     /* blue   — primary / live */
  --accent-2: #7c49d7;  /* purple — secondary */
  --positive: #0d9f6e;  /* green  — positive / paying */

  --border: #E5E7EB;
  --border-light: #F3F4F6;

  --success-bg: #E9F7F1;
  --success-text: #0d7a56;
  --success-border: rgba(13, 159, 110, 0.14);
  --error-bg: #FEF2F2;
  --error-text: #991B1B;
  --error-border: rgba(153, 27, 27, 0.1);
  --warning-bg: #FFFBEB;
  --warning-text: #92400E;
  --warning-border: rgba(146, 64, 14, 0.1);
  --info-bg: #E8F2FF;
  --info-text: #0a6fd6;
  --info-border: rgba(10, 134, 255, 0.14);

  --green: #0d9f6e;
  --yellow: #EAB308;
  --red: #EF4444;

  --radius-xs: 4px;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
}

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; height: 100%; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
}

h1, h2, h3, h4 { color: var(--text); line-height: 1.2; font-weight: 700; font-family: var(--font-display); }
a { color: var(--accent); text-decoration: none; transition: color 0.15s; }
a:hover { color: var(--text-secondary); }
code, kbd, .mono { font-family: var(--font-mono); font-size: 0.85em; }

/* Layout utils */
.flex { display: flex; align-items: center; }
.col { flex-direction: column; }
.wrap { flex-wrap: wrap; }
.grow { flex: 1; min-width: 0; }
.gap-h { gap: 0.5rem; }
.gap-1 { gap: 1rem; }
.gap-2 { gap: 1.5rem; }
.between { justify-content: space-between; }
.g2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.g3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.g4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }

/* Spacing */
.mb-h { margin-bottom: 0.5rem; }
.mb-1 { margin-bottom: 1rem; }
.mb-2 { margin-bottom: 1.5rem; }
.mb-3 { margin-bottom: 2rem; }
.mt-h { margin-top: 0.5rem; }
.mt-1 { margin-top: 1rem; }
.mt-2 { margin-top: 1.5rem; }
.p-1 { padding: 1rem; }
.p-2 { padding: 1.5rem; }

/* Text */
.t2 { color: var(--text-secondary); }
.t3 { color: var(--text-muted); }
.sm { font-size: 0.8rem; }
.xs { font-size: 0.75rem; }
.label {
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-muted);
}
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.center { text-align: center; }

/* Buttons — full-pill radius matches the auth/marketing CTAs and the status
   pills used throughout the dashboard, so every interactive surface shares
   one rounded vocabulary. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.375rem;
  padding: 0.5rem 1rem; border-radius: var(--radius-pill);
  font-family: inherit; font-size: 0.875rem; font-weight: 500;
  cursor: pointer; border: none; text-decoration: none; transition: all 0.15s;
  white-space: nowrap; line-height: 1;
}
.btn:hover { text-decoration: none; }
.btn-p { background: var(--accent); color: #FFF; font-weight: 600; }
.btn-p:hover { background: #1E293B; color: #FFF; }
.btn-g { background: var(--bg); border: 1px solid var(--border); color: var(--text-secondary); }
.btn-g:hover { border-color: var(--text-muted); color: var(--text); background: var(--bg); }
.btn-d { background: var(--error-bg); border: 1px solid var(--error-border); color: var(--error-text); }
.btn-d:hover { background: var(--red); color: #FFF; border-color: var(--red); }
.btn-sm { padding: 0.3rem 0.6rem; font-size: 0.78rem; }
.btn-lg { padding: 0.75rem 1.5rem; font-size: 0.95rem; }
.btn-full { width: 100%; }

/* Cards */
.card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.125rem;
}
/* Spacing between adjacent cards is set by their parent container's gap
   (flex/grid). The old ".card + .card { margin-top: 1.25rem }" rule
   stacked on top of that gap and produced inconsistent ~36px spacing
   inside pages that already declared a column gap. */
.card-flush { padding: 0; overflow: hidden; }

/* Stat cards */
.stat-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.125rem;
}
.stat-label {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--text-muted); margin-bottom: 0.5rem;
}
.stat-val { font-size: 2rem; font-weight: 700; color: var(--text); line-height: 1; }
.stat-hint { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; }

/* Status badges — icon + label, no pill background */
.badge {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.75rem; font-weight: 500;
}
.badge-active    { color: #007a20; }
.badge-trial     { color: #007367; }
.badge-past_due  { color: #ff3100; }
.badge-canceled  { color: #ff0037; }
.badge-suspended { color: #ff0037; }
.badge-revoked   { color: #ff0037; }
.badge-pending_verification { color: #005fff; }
.badge-deactivated { color: var(--text-muted); }

/* Instance activation status — small pill (inside detail rows) */
.badge-pill {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.25rem 0.625rem; border-radius: 999px;
  font-size: 0.7rem; font-weight: 600;
  flex-shrink: 0;
}
.badge-pill-active      { background: var(--success-bg); color: var(--success-text); border: 1px solid var(--success-border); }
.badge-pill-deactivated { background: var(--bg-secondary); color: var(--text-muted); border: 1px solid var(--border); }
.badge-pill-expired     { background: var(--error-bg); color: var(--error-text); border: 1px solid var(--error-border); }
.badge-pill-inactive    { background: var(--warning-bg); color: var(--warning-text); border: 1px solid var(--warning-border); }

/* Sidebar nav count badge */
.sb-count { margin-left: auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--bg-hover); color: var(--text-secondary); font-size: 0.6875rem; font-weight: 600; display: flex; align-items: center; justify-content: center; }

/* Customer avatar initials circle */
.cust-av { width: 32px; height: 32px; border-radius: 50%; background: var(--bg-hover); color: var(--text-secondary); font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }

/* Stat card icon badge */
.stat-icon { width: 36px; height: 36px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; margin-bottom: 0.875rem; }

/* Dashboard activity feed */
.activity-list { display: flex; flex-direction: column; }
.activity-item { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.875rem 1.125rem; border-bottom: 1px solid var(--border); }
.activity-item:last-child { border-bottom: none; }
.activity-icon { width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-top: 1px; }
.activity-title { font-size: 0.8125rem; font-weight: 600; color: var(--text); }
.activity-sub { font-size: 0.75rem; color: var(--text-secondary); margin-top: 0.1rem; }
.activity-time { font-size: 0.6875rem; color: var(--text-muted); margin-top: 0.2rem; }
.activity-tag { display: inline; font-family: var(--font-mono); font-size: 0.6875rem; background: var(--bg-hover); padding: 1px 5px; border-radius: 4px; color: var(--text-secondary); }

/* Dashboard app mini-cards */
.app-card { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 1.125rem; }
.app-card-logo { width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--bg-secondary); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; font-size: 1.125rem; font-weight: 700; color: var(--text); margin-bottom: 0.75rem; }
.app-card-stats { display: flex; justify-content: space-between; margin-top: 0.875rem; padding-top: 0.75rem; border-top: 1px solid var(--border); }
.app-card-stat-label { font-size: 0.6875rem; color: var(--text-muted); margin-bottom: 0.15rem; }
.app-card-stat-val { font-size: 0.9375rem; font-weight: 700; color: var(--text); }

/* Product grid cards (Apps page) */
.prod-card {
  position: relative; cursor: pointer; text-decoration: none; color: inherit;
  display: flex; flex-direction: column; gap: .875rem;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.prod-card:hover { border-color: var(--accent); box-shadow: 0 2px 10px rgba(0,0,0,0.07); }
.prod-card-hint {
  position: absolute; bottom: 1.125rem; right: 1.125rem;
  font-size: .72rem; color: var(--text-muted);
  opacity: 0; transition: opacity 0.15s; pointer-events: none;
}
.prod-card:hover .prod-card-hint { opacity: 1; }

/* Integration cards */
.integration-card { display: flex; align-items: center; gap: 1rem; padding: 1.125rem; }
.integration-card + .integration-card { border-top: 1px solid var(--border); }
.integration-logo { width: 42px; height: 42px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 1.25rem; font-weight: 800; }

/* Alerts */
.alert { padding: 0.75rem 1rem; border-radius: var(--radius-md); border: 1px solid; font-size: 0.875rem; margin-bottom: 1rem; }
.alert-e { background: var(--error-bg); border-color: var(--error-border); color: var(--error-text); }
.alert-s { background: var(--success-bg); border-color: var(--success-border); color: var(--success-text); }
.alert-w { background: var(--warning-bg); border-color: var(--warning-border); color: var(--warning-text); }
/* Integration-mode chooser (New app modal): light-palette radio cards. Selected
   state uses an accent border + tinted bg — never a dark fill (dashboard rule). */
.im-choice-group { display: flex; flex-direction: column; gap: 0.625rem; }
.im-choice { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.75rem 0.875rem; border: 1px solid var(--border); border-radius: var(--radius-md); cursor: pointer; background: var(--bg); position: relative; transition: border-color .12s, background .12s, box-shadow .12s; }
.im-choice:hover { border-color: var(--text-muted); }
.im-choice input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.im-choice-icon { flex-shrink: 0; width: 32px; height: 32px; border-radius: var(--radius-sm); background: var(--bg-secondary); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; color: var(--text-secondary); transition: color .12s, background .12s, border-color .12s; }
.im-choice-body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.im-choice-title { font-size: 0.85rem; font-weight: 700; color: var(--text); }
.im-choice-desc { font-size: 0.75rem; color: var(--text-muted); line-height: 1.4; }
.im-choice.is-selected { border-color: var(--accent); background: var(--bg-secondary); box-shadow: 0 0 0 1px var(--accent); }
.im-choice.is-selected .im-choice-icon { background: var(--bg); border-color: var(--accent); color: var(--accent); }
.im-choice:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
.alert-i { background: var(--info-bg); border-color: var(--info-border); color: var(--info-text); }

/* Remint-chain link in the licenses list. Muted until hovered, because it is a
   secondary affordance sitting next to the status pill — but it is a real link,
   so it has to answer to the pointer. */
/* 20px box around a 12px glyph. As a bare inline icon the hover target was the
   glyph itself, which made both the link and its tooltip feel unreliable next to
   the padded triggers used elsewhere. */
.lic-chain { display: inline-flex; align-items: center; justify-content: center;
  width: 1.25rem; height: 1.25rem; flex: none; color: var(--text-muted);
  opacity: 0.7; text-decoration: none; border-radius: var(--radius-sm);
  transition: opacity 0.12s ease, color 0.12s ease, background 0.12s ease; }
.lic-chain:hover, .lic-chain:focus-visible { opacity: 1; color: var(--accent);
  background: var(--bg-hover); }
.lic-chain:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Stepper — custom −/+ number input (pill) */
.stepper { display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; background: var(--bg); flex-shrink: 0; }
.stepper button { width: 32px; height: 34px; border: none; background: none; color: var(--text-secondary); font-size: 1rem; cursor: pointer; flex-shrink: 0; transition: background 0.1s, color 0.1s; display: flex; align-items: center; justify-content: center; }
.stepper button:hover { background: var(--bg-secondary); color: var(--text); }
.stepper input[type=number] { width: 48px !important; height: 34px !important; border: none !important; border-radius: 0 !important; text-align: center !important; font-size: 0.875rem !important; padding: 0 !important; background: var(--bg) !important; color: var(--text) !important; font-family: inherit; outline: none !important; -moz-appearance: textfield !important; appearance: textfield !important; box-shadow: none !important; }
.stepper input[type=number]::-webkit-inner-spin-button,
.stepper input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none !important; display: none; }

/* Unit selector — pill dropdown, paired with stepper */
.unit-sel {
  width: auto; flex-shrink: 0;
  height: 34px; padding: 0 1.75rem 0 .75rem;
  border: 1px solid var(--border); border-radius: 999px;
  background-color: var(--bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236B7280' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .55rem center;
  color: var(--text); font-family: inherit; font-size: 0.875rem; font-weight: 500;
  cursor: pointer; outline: none;
  -webkit-appearance: none; appearance: none;
  transition: border-color .15s, box-shadow .15s;
}
.unit-sel:hover { border-color: var(--text-muted); }
.unit-sel:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(15,23,42,.08); }
/* Used as a filter: is-set marks the menu that is actually narrowing the view,
   so an applied filter is visible without reading every dropdown. */
.unit-sel.is-set { border-color: var(--accent); font-weight: 600; }

/* Unit selector nested inside a stepper — blend into the same pill */
.stepper .unit-sel {
  height: 34px;
  border: none; border-left: 1px solid var(--border); border-radius: 0;
  padding: 0 1.5rem 0 .625rem;
  background-color: transparent;
  background-position: right .4rem center;
  font-size: 0.8125rem;
  box-shadow: none !important;
}
.stepper .unit-sel:hover { background-color: var(--bg-secondary); }
.stepper .unit-sel:focus { border-color: transparent; border-left-color: var(--border); }

/* Time-window filter (Usage page header) — a segmented pill of links, sized to
   sit beside the .unit-sel app switcher. Selected segment is a white chip on
   the secondary track; no dark fill, which is reserved for marketing CTAs. */
.winseg {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: var(--radius-pill); flex-shrink: 0;
}
.winseg-opt {
  font-size: 0.75rem; font-weight: 600; line-height: 1; white-space: nowrap;
  padding: .375rem .6875rem; border-radius: var(--radius-pill);
  color: var(--text-muted); text-decoration: none;
  border: 1px solid transparent;
  transition: color .12s, background .12s, box-shadow .12s;
}
.winseg-opt:hover { color: var(--text); }
.winseg-opt.is-on {
  background: var(--bg); color: var(--text);
  border-color: var(--border); box-shadow: 0 1px 2px rgba(0,0,0,.06);
}
.winseg-opt:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(15,23,42,.08);
}
/* Sixth segment: the custom range, a <details> popover holding a GET form. The
   summary is styled as a segment, so the disclosure triangle has to go. */
.winseg-cx { position: relative; display: inline-flex; }
.winseg-cx > summary { list-style: none; cursor: pointer; }
.winseg-cx > summary::-webkit-details-marker { display: none; }
.winseg-cx[open] > summary { color: var(--text); }
.winseg-pop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 40;
  display: flex; align-items: flex-end; gap: .5rem;
  padding: .75rem; background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0,0,0,.10);
}
.winseg-pop label {
  display: flex; flex-direction: column; gap: .25rem;
  font-size: .7rem; font-weight: 600; color: var(--text-muted);
}
.winseg-pop input[type=date] { width: auto; padding: .35rem .5rem; font-size: .8125rem; }

/* Six segments no longer fit beside the app switcher once the content column
   narrows, and squashed or wrapped segments read worse than a menu. Below
   1024px the pill gives way to the canonical .unit-sel dropdown; both shapes
   are always in the markup and CSS picks one. */
.winseg-sel { display: none; }
@media (max-width: 1024px) {
  .winseg { display: none; }
  .winseg-sel { display: inline-block; }
}

/* Forms */
.field { margin-bottom: 1rem; }
.field > label {
  display: block; font-size: 0.8rem; font-weight: 600;
  color: var(--text); margin-bottom: 0.375rem;
}
input[type=text], input[type=email], input[type=password], input[type=number], input[type=url], select, textarea {
  width: 100%; padding: 0.6rem 0.75rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  color: var(--text); font-family: inherit; font-size: 0.875rem;
  outline: none; transition: border-color 0.15s, box-shadow 0.15s; -webkit-appearance: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(15, 23, 42, 0.08);
}
.hint { font-size: 0.72rem; color: var(--text-muted); margin-top: 0.3rem; }
select option { background: var(--bg); }

/* Tables */
table { width: 100%; border-collapse: collapse; }
thead th {
  text-align: left; padding: 0.55rem 1rem;
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-muted); border-bottom: 1px solid var(--border);
  background: rgba(0,0,0,0.018);
}
tbody td {
  padding: 0.5rem 1rem;
  color: var(--text-secondary); font-size: 0.8125rem;
}
tbody tr:hover td { background: var(--border-light); }
.tlink { color: var(--text); font-weight: 600; }
.tlink:hover { color: var(--accent); }

/* Sortable column header — an <a> inside a <th>. The caret is always rendered,
   dimmed on the columns you aren't sorting by, so the whole row reads as
   sortable at rest and the label never shifts when a column becomes active. */
.th-sort {
  display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap;
  color: inherit; text-decoration: none;
  margin: -0.25rem -0.45rem; padding: 0.25rem 0.45rem;
  border-radius: var(--radius-sm);
  transition: background 0.12s, color 0.12s;
}
.th-sort:hover { background: var(--bg-hover); color: var(--text); text-decoration: none; }
.th-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.th-sort.is-active { color: var(--text); }
.th-caret { font-size: 0.65rem; line-height: 1; opacity: 0.3; transition: opacity 0.12s; }
.th-sort:hover .th-caret { opacity: 0.65; }
.th-sort.is-active .th-caret { opacity: 1; }

/* Progress bars */
.prog { height: 6px; background: var(--border-light); border-radius: 999px; overflow: hidden; }
.prog-fill { height: 100%; border-radius: 999px; transition: width 0.4s; }
.prog-g { background: var(--green); }
.prog-y { background: var(--yellow); }
.prog-r { background: var(--red); }

/* Detail list */
.dl { display: grid; grid-template-columns: 130px 1fr; gap: 0.6rem 1rem; align-items: start; }
.dl dt { font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); padding-top: 0.2rem; }
.dl dd { font-size: 0.875rem; color: var(--text); }

hr { border: none; border-top: 1px solid var(--border); margin: 1.5rem 0; }

/* Usage bars */
.ub { margin-bottom: 0.875rem; }
.ub:last-child { margin-bottom: 0; }
.ub-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.35rem; }
.ub-label { font-size: 0.8rem; color: var(--text-secondary); }
.ub-val { font-size: 0.72rem; color: var(--text-muted); font-family: var(--font-mono); }

/* Usage world map (country choropleth) */
.wm { position: relative; margin-bottom: 0.875rem; }
.wm svg { display: block; width: 100%; height: auto; }
.wm svg path { transition: fill-opacity 0.12s ease, stroke 0.12s ease, stroke-width 0.12s ease; }
.wm svg path:hover { stroke: var(--text-secondary); stroke-width: 1; }
.wm path.wm-c:hover { stroke: var(--accent); stroke-width: 1.4; fill-opacity: 0.92; }
.wm-tip {
  position: absolute; top: 0; left: 0; z-index: 10; pointer-events: none;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.10), 0 2px 6px rgba(15, 23, 42, 0.06);
  padding: 0.5rem 0.65rem; min-width: 120px; white-space: nowrap;
}
.wm-tip-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.15rem; }
.wm-tip-name { font-size: 0.8rem; font-weight: 600; color: var(--text); }
.wm-tip-code { font-size: 0.65rem; color: var(--text-muted); font-family: var(--font-mono); }
.wm-tip-val {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  font-size: 0.72rem; color: var(--text-secondary); font-family: var(--font-mono);
}
.wm-tip-pct { color: var(--text-muted); }

/* Client-side table pager (Daily activity, device tables) */
.tbl-pager {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem 1rem; border-top: 1px solid var(--border);
}
.tbl-pager-info { font-size: 0.72rem; color: var(--text-muted); font-family: var(--font-mono); }
.tbl-pager .btn[disabled],
.tbl-pager .btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
.wm-legend { display: flex; align-items: center; gap: 2px; margin-top: 0.5rem; justify-content: flex-end; }
.wm-legend i { width: 14px; height: 6px; border-radius: 2px; }
.wm-legend span { font-size: 0.65rem; color: var(--text-muted); padding: 0 0.35rem; }
.wm-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.45rem; }
.wm-row:last-child { margin-bottom: 0; }
.wm-swatch { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
.wm-name { font-size: 0.8rem; color: var(--text-secondary); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── App shell v2 (sidebar + main) ── */
.shell { display: flex; height: 100vh; overflow: hidden; }

.sidebar {
  width: 260px; flex-shrink: 0;
  background: var(--bg-secondary); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; min-height: 0;
}
/* Pin sb-logo (top) and the full bottom stack (cards + footer) while only
 * the nav section scrolls. This matches the onboarding shell so short card
 * stacks sit flush above the footer instead of floating with a gap. */
.sb-scroll { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.sb-bottom-stack { flex: 0 0 auto; display: flex; flex-direction: column; }
.sb-scroll-cards { flex: 0 0 auto; }
.sb-logo, .sb-bottom-stack, .sb-footer { flex-shrink: 0; }

.sb-logo {
  padding: 1rem 0.75rem 0.75rem;
}
.sb-brand { display: block; width: auto; height: 1.5rem; }
.sb-meta { margin-top: 0.75rem; }
.sb-name { font-size: 0.875rem; font-weight: 700; color: var(--text); }
.sb-subname { font-size: 0.6875rem; color: var(--text-muted); margin-top: 0.05rem; }

.sb-section { padding: 0.125rem 0.75rem 0.75rem; }
.sb-slabel {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-muted);
  padding: 0 0.25rem; margin-bottom: 0.25rem;
}
.sb-nav { list-style: none; display: flex; flex-direction: column; gap: 0.1rem; }
.sb-nav li {
  border: 1px solid transparent; border-radius: var(--radius-sm);
  transition: background 0.12s, border-color 0.12s; position: relative;
}
.sb-nav li a, .sb-nav li button {
  display: flex; align-items: center; gap: 0.625rem; width: 100%;
  padding: 0.45rem 0.5rem 0.45rem 0.625rem;
  font-size: 0.85rem; color: var(--text-secondary);
  text-decoration: none; background: none; border: none;
  cursor: pointer; font-family: inherit;
}
.sb-nav li:not(.active):hover { background: var(--bg-hover); }
.sb-nav li.active { background: var(--bg); }
.sb-nav li.active a, .sb-nav li.active button { color: var(--text); font-weight: 600; }
.sb-nav-icon {
  width: 18px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; color: var(--text-muted);
  transition: color 0.15s;
}
.sb-nav li.active .sb-nav-icon { color: var(--sb-color, var(--text)); }

/* Get started card */
.sb-footer {
  padding: 0.75rem; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 0.5rem;
}
.sb-getstarted {
  display: flex; flex-direction: column; gap: 0.1rem;
  padding: 0.75rem 0.875rem;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-decoration: none; transition: background .12s;
}
.sb-getstarted:hover { background: var(--bg-hover); }
.sb-gs-icon { color: var(--text-secondary); margin-bottom: 0.2rem; display: flex; }
.sb-gs-title { font-size: 0.8rem; font-weight: 700; color: var(--text); line-height: 1.2; }
.sb-gs-sub { font-size: 0.7rem; color: var(--text-secondary); line-height: 1.4; margin-top: 0.1rem; }
.sb-feedback-dismiss {
  position: absolute; top: .35rem; right: .35rem;
  width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: none; border-radius: 50%;
  color: var(--text-muted); cursor: pointer; padding: 0; line-height: 0;
  opacity: 0; pointer-events: none;
  transition: opacity .12s, background .12s, color .12s;
}
#sb-feedback:hover .sb-feedback-dismiss,
#sb-feedback:focus-within .sb-feedback-dismiss {
  opacity: 1; pointer-events: auto;
}
.sb-feedback-dismiss:hover {
  background: var(--bg-secondary); color: var(--text);
}

/* Marketing-style pill button (dark, with cutout icon) */
.btn-mint {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  background: #171717; color: #fff;
  border: none; border-radius: 999px;
  font-family: inherit; font-size: 0.78rem; font-weight: 600;
  cursor: pointer; text-decoration: none;
  transition: background 0.15s, transform 0.12s;
  white-space: nowrap; line-height: 1;
}
/* When a trailing icon is present, tuck the right padding in against it. */
.btn-mint:has(svg) { padding-right: 0.375rem; }
.btn-mint:hover { background: #262626; color: #fff; }
.btn-mint:active { transform: scale(0.97); }
.btn-mint svg { width: 1.3125rem; height: 1.3125rem; flex-shrink: 0; }

.btn-mint-alt {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  background: var(--bg); color: var(--text-secondary);
  border: 1px solid var(--border); border-radius: 999px;
  font-family: inherit; font-size: 0.78rem; font-weight: 600;
  cursor: pointer; text-decoration: none;
  transition: border-color 0.15s, color 0.15s, transform 0.12s;
  white-space: nowrap; line-height: 1;
}
.btn-mint-alt:hover { border-color: var(--text-muted); color: var(--text); }
.btn-mint-alt:active { transform: scale(0.97); }
.btn-mint-alt svg { width: 1rem; height: 1rem; flex-shrink: 0; }

.sb-tenant {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.25rem 0;
}
.sb-av {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.6875rem; font-weight: 700; color: #fff;
  flex-shrink: 0; letter-spacing: 0.03em; user-select: none;
  overflow: hidden;
}
.sb-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sb-tname {
  font-size: 0.8125rem; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sb-tstatus { font-size: 0.625rem; color: var(--text-muted); margin-top: 0.05rem; }

.app-main {
  flex: 1; overflow-y: auto; display: flex; flex-direction: column; min-width: 0;
  background: var(--bg);
}
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 1.25rem; height: 44px; flex-shrink: 0;
  border-bottom: 1px solid var(--border);
}
.topbar-crumb {
  display: flex; align-items: center; gap: 0.375rem;
  font-size: 0.8125rem; color: var(--text-muted);
}
.topbar-crumb-home {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; color: var(--text-muted);
}
/* The mark is a 88×97 portrait asset — constrain by height and let the width
   follow, or the img's intrinsic size blows out the 20px crumb slot. */
.topbar-crumb-mark { height: 16px; width: auto; display: block; }
.topbar-crumb-sep { font-size: 0.75rem; color: var(--text-muted); line-height: 1; }
.topbar-crumb-page { color: var(--text-secondary); font-weight: 500; }
.topbar-search {
  display: flex; align-items: center; gap: 0.375rem;
  font-size: 0.8125rem; color: var(--text-muted);
  background: none; border: none; cursor: pointer; font-family: inherit;
  padding: 0.25rem 0.5rem; border-radius: var(--radius-sm);
  transition: color 0.12s, background 0.12s;
}
.topbar-search:hover { color: var(--text); background: var(--bg-hover); }
.topbar-search-kbd {
  font-family: var(--font-mono);
  font-size: 0.6875rem; color: var(--text-muted);
  background: var(--bg); border: 1px solid var(--border);
  padding: 0.05rem 0.35rem; border-radius: 4px;
  margin-left: 0.25rem;
}

/* Mobile nav toggle (hamburger) — hidden on desktop, revealed at ≤768px.
   Lives at the left of the topbar and slides the sidebar in as a drawer. */
.topbar-menu {
  display: none; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin-left: -0.25rem; flex-shrink: 0;
  border: none; background: none; cursor: pointer;
  color: var(--text-secondary); border-radius: var(--radius-sm);
  transition: background 0.12s, color 0.12s;
}
.topbar-menu:hover { background: var(--bg-hover); color: var(--text); }

/* Scrim behind the mobile drawer. Toggled via .shell.nav-open. */
.sb-backdrop {
  position: fixed; inset: 0; z-index: 95;
  background: rgba(15, 15, 15, 0.4); backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden; transition: opacity 0.2s ease, visibility 0.2s;
}

/* Global search overlay (Cmd+K) */
.search-overlay {
  display: none; position: fixed; inset: 0; z-index: 300;
  background: rgba(0,0,0,0.4); backdrop-filter: blur(2px);
  align-items: flex-start; justify-content: center;
  padding-top: 12vh;
}
.search-overlay.open { display: flex; }
.search-modal {
  width: 560px; max-width: 92vw;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: 0 20px 60px rgba(0,0,0,0.18);
  overflow: hidden; display: flex; flex-direction: column;
}
.search-input-wrap {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.875rem 1rem; border-bottom: 1px solid var(--border);
}
.search-input-wrap svg { color: var(--text-muted); flex-shrink: 0; }
.search-input {
  flex: 1; border: none; outline: none; background: none;
  font: inherit; font-size: 0.9375rem; color: var(--text);
}
.search-input::placeholder { color: var(--text-muted); }
.search-results { max-height: 50vh; overflow-y: auto; padding: 0.375rem; }
.search-group-label {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-muted);
  padding: 0.5rem 0.625rem 0.25rem;
}
.search-result {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.5rem 0.625rem; border-radius: var(--radius-sm);
  cursor: pointer; text-decoration: none; color: var(--text);
}
.search-result.active { background: var(--bg-hover); }
.search-result-icon { color: var(--text-muted); flex-shrink: 0; display: flex; }
.search-result-text { flex: 1; min-width: 0; }
.search-result-label { font-size: 0.8125rem; font-weight: 500; color: var(--text); }
.search-result-sub {
  font-size: 0.7rem; color: var(--text-muted); margin-top: 0.05rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.search-empty {
  padding: 1.5rem 1rem; text-align: center;
  font-size: 0.8125rem; color: var(--text-muted);
}

/* ── Generic confirm modal (replaces native confirm() for destructive ops) ── */
.kl-confirm-overlay {
  display: none; position: fixed; inset: 0; z-index: 350;
  background: rgba(15,15,15,0.45); backdrop-filter: blur(3px);
  align-items: center; justify-content: center; padding: 1.25rem;
  animation: kl-fade-in 0.12s ease-out;
}
.kl-confirm-overlay.open { display: flex; }
.kl-confirm-modal {
  width: 440px; max-width: 100%;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 24px 64px rgba(0,0,0,0.18);
  padding: 1.25rem 1.25rem 1rem;
  display: flex; flex-direction: column; gap: 0.875rem;
  animation: kl-pop-in 0.16s cubic-bezier(0.22, 1, 0.36, 1);
  /* The trigger + modal are emitted together, so the modal ends up wherever
     its button lives — often a table cell styled for tidy columns. The API
     tokens table's .tok-actions cell sets text-align:right and
     white-space:nowrap, and both were inherited straight into this dialog:
     the message refused to wrap and ran outside the modal, and the heading sat
     right-aligned. A fixed-position dialog must not inherit text layout from
     its DOM neighbourhood. */
  text-align: left;
  white-space: normal;
}
.kl-confirm-head {
  display: flex; align-items: flex-start; gap: 0.75rem;
}
.kl-confirm-icon {
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.kl-confirm-icon.danger { background: #FEF2F2; color: #B91C1C; }
.kl-confirm-icon.warn   { background: #FFFBEB; color: #B45309; }
.kl-confirm-body { flex: 1; min-width: 0; }
.kl-confirm-title {
  font-size: 1rem; font-weight: 700; color: var(--text); line-height: 1.3;
  margin: 0 0 0.25rem;
}
.kl-confirm-message {
  font-size: 0.8125rem; color: var(--text-secondary); line-height: 1.55; margin: 0;
  /* Titles interpolate user-supplied token names, which can be long and
     unbroken. */
  overflow-wrap: anywhere;
}
.kl-confirm-title { overflow-wrap: anywhere; }
.kl-confirm-actions {
  display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 0.25rem;
}
.kl-confirm-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.5rem 0.95rem;
  font-family: inherit; font-size: 0.8125rem; font-weight: 600;
  border-radius: var(--radius-pill); cursor: pointer; border: 1px solid transparent;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
  line-height: 1;
}
.kl-confirm-btn.cancel {
  background: var(--bg); color: var(--text-secondary); border-color: var(--border);
}
.kl-confirm-btn.cancel:hover { background: var(--bg-hover); color: var(--text); }
.kl-confirm-btn.confirm-danger {
  background: #B91C1C; color: #fff;
}
.kl-confirm-btn.confirm-danger:hover { background: #991B1B; }
.kl-confirm-btn.confirm {
  background: var(--accent); color: #fff;
}
.kl-confirm-btn.confirm:hover { background: var(--accent-hover); }

/* ── Toast (transient feedback) ── */
.kl-toast-stack {
  position: fixed; top: 1rem; right: 1rem; z-index: 400;
  display: flex; flex-direction: column; gap: 0.5rem;
  pointer-events: none;
}
.kl-toast {
  pointer-events: auto;
  background: var(--text); color: #fff;
  padding: 0.625rem 0.875rem;
  border-radius: var(--radius-sm);
  font-size: 0.8125rem; font-weight: 500;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  display: inline-flex; align-items: center; gap: 0.5rem;
  animation: kl-pop-in 0.18s ease-out;
}
.kl-toast.success { background: #166534; }
.kl-toast.error   { background: #991B1B; }
@keyframes kl-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes kl-pop-in {
  from { opacity: 0; transform: translateY(4px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.content { padding: 2.5rem 1.75rem 1.25rem; flex: 1; width: 100%; }

/* Page header */
.ph { margin-bottom: 1.25rem; }
.ph h1 { font-size: 1.375rem; font-weight: 700; }
.ph p { color: var(--text-secondary); font-size: 0.875rem; margin-top: 0.2rem; }
.ph-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }

/* ── Mobile responsive (≤768px) ──
   The 260px sidebar becomes an off-canvas drawer toggled by the topbar
   hamburger, so the full nav (groups, cards, user profile) stays intact
   instead of being squashed into a horizontal strip. Content patterns that
   assume desktop width (multi-column grids, side-by-side rows, fixed-column
   detail lists) collapse to a single column. */
@media (max-width: 768px) {
  /* Stop fighting mobile viewport-height quirks: let the page scroll. */
  .shell { display: block; height: auto; overflow: visible; }
  .app-main { overflow: visible; min-height: 100dvh; }

  /* Sidebar → off-canvas drawer, keeping its desktop column layout. */
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 100;
    width: 84vw; max-width: 300px; height: 100dvh;
    flex-direction: column;
    border-right: 1px solid var(--border); border-bottom: none;
    box-shadow: var(--shadow-md);
    transform: translateX(-100%);
    transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .shell.nav-open .sidebar { transform: translateX(0); }
  .shell.nav-open .sb-backdrop { opacity: 1; visibility: visible; }

  /* Topbar gains the hamburger; keep the breadcrumb from overflowing. */
  .topbar-menu { display: inline-flex; }
  .topbar { padding: 0 0.875rem; gap: 0.5rem; }
  .topbar-crumb { min-width: 0; overflow: hidden; }
  .topbar-crumb-page { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .topbar-search-kbd { display: none; }

  /* Content gutters + heading scale. */
  .content { padding: 1.5rem 1rem 1.25rem; }
  .ph h1, .ph-title { font-size: 1.25rem; }

  /* Side-by-side page headers stack. */
  .ph-row { flex-direction: column; align-items: stretch; gap: 0.75rem; }

  /* Grids collapse to a single column. The dashboard pages build their
     layouts with *inline* grid-template-columns (stat rows, 1fr 320px
     main+sidepanel splits), not the .g* utility classes — so the attribute
     selector below is what actually unbreaks the real pages. A media-query
     !important overrides the inline style. */
  [style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
  .g2, .g3, .g4 { grid-template-columns: 1fr; }

  /* Detail lists: label stacks above value. */
  .dl { grid-template-columns: 1fr; gap: 0 0; }
  .dl dt { padding-top: 0.6rem; }
  .dl dd { padding-bottom: 0.1rem; }

  /* Account rows stack label over control. */
  .acct-row { flex-direction: column; align-items: stretch; gap: 0.4rem; }
  .acct-row-label { min-width: 0; }
  .acct-row-val { max-width: none; }
  .acct-tabs { overflow-x: auto; }

  /* Integration cards: let the trailing action wrap below. */
  .integration-card { flex-wrap: wrap; }

  /* Wide tables scroll horizontally within their card. */
  table { display: block; overflow-x: auto; }

  /* Modals + toasts fit the viewport. */
  .kl-confirm-overlay { padding: 1rem; }
  .kl-toast-stack { left: 1rem; right: 1rem; top: 0.75rem; }
}

/* ── Small phones (≤480px) ── */
@media (max-width: 480px) {
  .content { padding: 1.25rem 0.875rem 1rem; }
  .stat-val { font-size: 1.75rem; }
}

/* ── Sidebar — Help link ── */
.sb-help {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.4rem 0.625rem;
  font-size: 0.85rem; color: var(--text-secondary);
  border-radius: var(--radius-sm); text-decoration: none;
  transition: background 0.12s;
}
.sb-help:hover { background: var(--bg-hover); color: var(--text); }

/* ── Sidebar — User row ── */
.sb-user-wrap { position: relative; }
.sb-user {
  display: flex; align-items: center; gap: 0.5rem;
  width: 100%; padding: 0.4rem 0.5rem;
  border-radius: var(--radius-sm); border: none; background: none;
  cursor: pointer; font-family: inherit; text-align: left;
  transition: background 0.12s;
}
.sb-user:hover { background: var(--bg-hover); }
.sb-user-info { flex: 1; min-width: 0; }
.sb-user-name { font-size: 0.8125rem; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb-bell {
  width: 24px; height: 24px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); flex-shrink: 0;
}

/* ── Sidebar — User popover ── */
.sb-popover {
  display: none; position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  padding: 0.375rem; z-index: 100; min-width: 180px;
}
.sb-popover.open { display: block; }
.sb-pop-label {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--text-muted);
  padding: 0.25rem 0.5rem 0.375rem;
}
.sb-pop-item {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.5rem; border-radius: var(--radius-sm);
  font-size: 0.85rem; color: var(--text-secondary);
  text-decoration: none; cursor: pointer; transition: background 0.1s;
  border: none; background: none; font-family: inherit; width: 100%;
}
.sb-pop-item:hover { background: var(--bg-hover); color: var(--text); }
.sb-pop-item.danger { color: var(--error-text); }
.sb-pop-item.danger:hover { background: var(--error-bg); }
.sb-pop-sep { border: none; border-top: 1px solid var(--border); margin: 0.25rem 0; }

/* ── Account page ── */
.acct-tabs { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 1.5rem; }
.acct-tab {
  padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 500;
  color: var(--text-muted); text-decoration: none; border-bottom: 2px solid transparent;
  margin-bottom: -1px; transition: color 0.15s, border-color 0.15s;
}
.acct-tab:hover { color: var(--text); }
.acct-tab.active { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
.acct-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem 0; border-bottom: 1px solid var(--border-light); gap: 1rem;
}
.acct-row:last-of-type { border-bottom: none; }
.acct-row-label { font-size: 0.875rem; color: var(--text); min-width: 140px; }
.acct-row-val { flex: 1; max-width: 320px; }
.acct-av {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 1rem; font-weight: 700; color: #fff;
  letter-spacing: 0.03em; user-select: none;
  overflow: hidden; flex-shrink: 0;
}
.acct-av img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── Account: titled section over a bordered card of rows ──────────────────
   The rows used to sit directly on the page with a hairline between them and
   the label column carrying the whole hierarchy. Grouping them inside a card
   under a heading is what makes a settings page scannable: the heading says
   what the group is for, and the card's edge says where it stops. */
.acct-sec { margin-bottom: 1.5rem; }
.acct-sec-head { padding: 0 .25rem .625rem; }
.acct-sec-title { font-size: .9375rem; font-weight: 600; color: var(--text); margin: 0; }
.acct-sec-desc { font-size: .8125rem; line-height: 1.4; color: var(--text-muted); margin: .125rem 0 0; }
.acct-card { border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg-card, #fff); }
/* Rows inside a card need their own padding; the bare .acct-row has none. */
.acct-card .acct-row { padding: .875rem 1rem; border-bottom: 1px solid var(--border-light); }
.acct-card .acct-row:last-child { border-bottom: none; }
/* A description belongs under its label, at a measure, rather than running the
   width of the row under the control — and it replaces the spacer rows that
   existed only to park a hint somewhere. */
.acct-row-head { min-width: 140px; flex: 1; }
.acct-row-title { display: block; font-size: .875rem; font-weight: 500; color: var(--text); line-height: 1.35; }
.acct-row-desc { display: block; max-width: 420px; margin-top: .125rem; font-size: .8125rem; line-height: 1.4; color: var(--text-muted); }
/* Controls sit at their own width against the right edge; only text inputs get
   the fixed measure .acct-row-val gives them. */
.acct-row-act { display: flex; align-items: center; gap: .5rem; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
.acct-val-static { font-size: .875rem; color: var(--text-muted); }

/* A row whose whole surface is the switch. The previous version was a bordered
   box carrying its hover state in two inline event handlers — the first token
   change would have left it behind. */
.acct-row-toggle { cursor: pointer; user-select: none; }
.acct-row-toggle:hover { background: var(--bg-hover, #EEEEEC); }
.acct-card .acct-row:first-child { border-top-left-radius: var(--radius-md); border-top-right-radius: var(--radius-md); }
.acct-card .acct-row:last-child { border-bottom-left-radius: var(--radius-md); border-bottom-right-radius: var(--radius-md); }

/* A row that opens. The summary IS the row, so a destructive action reads as
   one line among its neighbours until it is asked for. */
.acct-card .acct-row-open { display: block; padding: 0; }
.acct-row-sum { display: flex; align-items: center; gap: 1rem; padding: .875rem 1rem; cursor: pointer; list-style: none; }
.acct-row-sum::-webkit-details-marker { display: none; }
.acct-row-sum:hover { background: var(--bg-hover, #EEEEEC); }
.acct-row-body { padding: 0 1rem 1rem; }

/* The identity row: avatar, name over email, actions. One glance answers "whose
   account am I in", which the old label/value grid never stated at all. */
.acct-id { display: flex; align-items: center; gap: .75rem; min-width: 0; flex: 1; }
.acct-id-text { min-width: 0; }
.acct-id-name { display: block; font-size: .9375rem; font-weight: 600; color: var(--text); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-id-mail { display: block; font-size: .8125rem; color: var(--text-muted); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-id-actions { display: flex; align-items: center; gap: .5rem; flex-shrink: 0; }
.acct-av-lg { width: 56px; height: 56px; font-size: 1.125rem; }

/* The avatar IS the control. A separate "Add photo" button plus a row
   explaining accepted formats is two pieces of chrome for one action nobody
   needed told about in advance — the server already rejects a bad file and
   says so. Clicking the avatar opens the picker; the badge is the only hint
   required. */
.acct-av-edit { position: relative; display: inline-flex; cursor: pointer; border-radius: 50%; flex-shrink: 0; }
.acct-av-edit:hover .acct-av { opacity: .9; }
.acct-av-edit:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.acct-av-badge {
  position: absolute; right: -1px; bottom: -1px;
  display: flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--accent); color: #fff;
  border: 2px solid var(--bg-card, #fff);
}
/* Hidden until a photo exists, so it never offers to remove something that is
   not there — but present in the DOM, because choosing a photo has to be able
   to reveal it without a page load. */
.acct-av-item[hidden] { display: none; }

/* The photo saves the moment it is chosen, which means the save needs somewhere
   to speak. It sits under the email, in the identity row's own column, so it
   never reflows the row. */
.acct-av-status {
  display: block; margin-top: .125rem;
  font-size: .75rem; line-height: 1.35; color: var(--text-muted);
  opacity: 0; transition: opacity .15s ease;
}
.acct-av-status.show { opacity: 1; }
.acct-av-status.bad { color: var(--error-text); }
/* While the request is in flight the picture is a claim, not a fact. */
[data-av-busy] .acct-av { opacity: .55; }

/* Share-of-devices donut (version adoption). Ring + legend side by side above
   ~520px, stacked below — the legend is the readable half and must not be
   squeezed into a column beside a shrinking ring. */
.dn { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.dn svg { width: 120px; height: 120px; flex-shrink: 0; }
.dn-arc { transition: opacity .15s ease; }
.dn:hover .dn-arc { opacity: .55; }
.dn .dn-arc:hover { opacity: 1; }
.dn-total { text-anchor: middle; font-size: 24px; font-weight: 700; fill: var(--text); }
.dn-cap { text-anchor: middle; font-size: 9px; fill: var(--text-muted); }
.dn-legend { flex: 1; min-width: 180px; display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: .375rem 1.5rem; align-content: center; }
.dn-row { display: flex; align-items: center; gap: .5rem; font-size: .8125rem; }
.dn-sw { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.dn-name { flex: 1; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 520px) { .dn { justify-content: center; } }

/* Avatar menu. <details> rather than JS: it gives open/close, Escape and
   keyboard focus for free, and this page already renders without a framework. */
.acct-av-menu { position: relative; flex-shrink: 0; }
.acct-av-menu > summary { list-style: none; }
.acct-av-menu > summary::-webkit-details-marker { display: none; }
.acct-av-pop {
  position: absolute; top: calc(100% + .375rem); left: 0; z-index: 30;
  min-width: 168px; padding: .25rem;
  background: var(--bg-card, #fff); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: 0 8px 24px rgba(0,0,0,.10);
  display: flex; flex-direction: column;
}
.acct-av-item {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: .5rem .625rem; border: 0; background: none;
  font-size: .8125rem; font-family: inherit; color: var(--text);
  border-radius: var(--radius-sm);
}
.acct-av-item:hover { background: var(--bg-hover, #EEEEEC); }
.acct-av-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.email-verified { display: flex; align-items: center; gap: 0.5rem; }
.verified-badge { color: #10b981; flex-shrink: 0; }

/* ── Accessibility ── */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.skip-link { position: absolute; top: -40px; left: 8px; z-index: 1000; padding: 0.5rem 0.875rem; background: var(--accent); color: #fff; border-radius: 999px; font-size: 0.8rem; font-weight: 600; text-decoration: none; }
.skip-link:focus { top: 8px; color: #fff; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* ── Toggle switch (CSS-only, role="switch" on the input) ── */
.toggle { display: inline-flex; align-items: center; flex-shrink: 0; }
.toggle-input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.toggle-track {
  position: relative; display: inline-block;
  width: 36px; height: 20px; border-radius: 999px;
  background: #D1D5DB; transition: background .15s ease;
  flex-shrink: 0;
}
.toggle-knob {
  position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.18);
  transition: transform .15s ease;
}
.toggle-input:checked + .toggle-track { background: var(--accent); }
.toggle-input:checked + .toggle-track .toggle-knob { transform: translateX(16px); }
.toggle-input:focus-visible + .toggle-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.toggle-input:disabled + .toggle-track { opacity: 0.5; cursor: not-allowed; }

/* Develop page */
.dev-head{margin-bottom:22px}
.dev-head-top{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.dev-head h1{font-size:24px;font-weight:800;letter-spacing:-.02em}
.dev-sub{color:var(--text-muted);font-size:14px;margin-top:4px;max-width:64ch}
.dev-alert{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600;padding:5px 12px;border-radius:var(--radius-pill);background:var(--warning-bg);color:var(--warning-text);border:1px solid var(--warning-border);text-decoration:none;transition:filter .12s}
.dev-alert:hover{filter:brightness(.97)}
/* Success flash after an SDK-key rotation — a fact, not an alert. */
.dev-flash{display:flex;align-items:center;gap:8px;margin-bottom:18px;padding:9px 13px;border-radius:var(--radius-sm);background:var(--success-bg);border:1px solid var(--success-border);color:var(--success-text);font-size:13px;font-weight:500}
.dev-flash svg{flex-shrink:0}

/* Two-column workbench: heavier action cards (Keys & SDK, Test a purchase) on
   the left, lighter reference/status cards (Look up a key, Integrations) on the
   right. Each column stacks independently; collapses to one column ≤900px. */
.dev-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:16px;align-items:start}
.dev-col{display:flex;flex-direction:column;gap:16px;min-width:0}
@media(max-width:900px){.dev-grid{grid-template-columns:1fr}}

.dev-grid .card{padding:20px 22px}
.dev-cardhead{display:flex;align-items:center;gap:11px;margin-bottom:5px}
.dev-cardicon{width:30px;height:30px;border-radius:8px;background:var(--bg-hover);color:var(--text);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}
.dev-cardicon svg{width:16px;height:16px}
.dev-grid .card h2{font-size:15.5px;font-weight:700;margin:0;line-height:1.2}
.dev-cardsub{color:var(--text-muted);font-size:13px;margin:0 0 14px;max-width:62ch;line-height:1.5}
/* A note under a card's content — e.g. the support-gated SDK-key rotation line. */
.dev-cardnote{color:var(--text-muted);font-size:12px;margin:14px 0 0;line-height:1.5}
.dev-cardnote a{color:var(--accent);font-weight:600;text-decoration:none}
.dev-cardnote a:hover{text-decoration:underline}

.dev-lookup{display:flex;gap:10px}
.dev-input{flex:1;min-width:0;font-family:var(--font-mono);font-size:13px;padding:9px 13px;border:1px solid var(--border);border-radius:var(--radius-pill);background:var(--bg);color:var(--text)}
.dev-input:focus{outline:2px solid var(--accent);outline-offset:1px}
.dev-miss{margin-top:12px;font-size:12.5px;color:var(--text-muted)}

.dev-chip{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;padding:3px 10px;border-radius:var(--radius-pill)}
.dev-chip.ok{background:var(--success-bg);color:var(--success-text)}
.dev-chip.warn{background:var(--warning-bg);color:var(--warning-text)}

.dev-irow{display:flex;align-items:center;gap:14px;padding:14px 0;border-top:1px solid var(--border-light)}
.dev-irow:first-of-type{border-top:none;padding-top:2px}
.dev-ibody{flex:1;min-width:0}
.dev-iname{font-size:14px;font-weight:600;display:flex;align-items:center;gap:9px}
.dev-isub{font-size:12.5px;color:var(--text-muted);margin-top:2px}
/* Empty state for the integrations card — the product's most common unfinished
   state, so it reads as an invitation rather than a bare line. Centered, to
   match the other empty states across the dashboard. */
.dev-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px;padding:32px 16px 24px}
.dev-empty-icon{display:inline-flex;align-items:center;justify-content:center;width:46px;height:46px;border-radius:12px;background:var(--bg-secondary);border:1px solid var(--border);color:var(--text);margin-bottom:4px}
.dev-empty-icon svg{opacity:.85}
.dev-empty-title{font-size:14.5px;font-weight:600;color:var(--text);margin:0}
.dev-empty-sub{font-size:12.5px;color:var(--text-muted);line-height:1.55;margin:0;max-width:42ch}
.dev-empty .btn{margin-top:6px}

/* ── Tooltip (hover/focus hint) ── */
#ll-tip {
  position: fixed; top: 0; left: 0; z-index: 450;
  max-width: 260px; padding: 0.45rem 0.6rem;
  background: var(--text); border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  font-family: var(--font-family, var(--font-body)); text-align: left;
  pointer-events: none; opacity: 0; visibility: hidden;
  transform: translateY(2px);
  transition: opacity 0.12s ease, transform 0.12s ease, visibility 0.12s;
}
#ll-tip[data-pos="below"] { transform: translateY(-2px); }
#ll-tip.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
.ll-tip-title { color: #fff; font-size: 0.7rem; font-weight: 600; line-height: 1.35; }
.ll-tip-body {
  color: rgba(255,255,255,0.64); font-size: 0.7rem; font-weight: 400;
  line-height: 1.4; margin-top: 0.15rem;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
.ll-tip-body:empty { display: none; }

/* An SVG inside a trigger should not be a pointer target of its own. */
[data-ll-tip] > svg { pointer-events: none; }
.ll-tip-body.mono { font-family: var(--font-mono); font-size: 0.675rem; word-break: break-all; }
@media (prefers-reduced-motion: reduce) { #ll-tip { transition: none; } }

