/**
 * CubeWP Console — component kit (U1).
 *
 * The shared visual language every phase builds with. Consumes tokens.css
 * exclusively — a raw hex here is a bug. Components are prefixed cw- and
 * coexist with legacy classes until each surface is rebuilt (U2–U7); the
 * legacy contrast/focus overrides at the bottom fix the audit's a11y
 * findings platform-wide without waiting for those rebuilds.
 */

/* ══ Header bar (shell) ═════════════════════════════════════════════════ */

.cw-header {
  height: var(--cw-header-h);
  display: flex; align-items: center; gap: var(--cw-s4);
  padding: 0 var(--cw-s6);
  background: var(--cw-surface);
  border-bottom: 1px solid var(--cw-border);
  position: sticky; top: 0; z-index: 800;
}
.cw-crumbs {
  display: flex; align-items: center; gap: var(--cw-s2);
  font: var(--cw-small); color: var(--cw-text-soft);
  min-width: 0; flex: 1;
}
.cw-crumbs .cw-crumb-sep { color: var(--cw-border-strong); }
.cw-crumbs .cw-crumb-current { color: var(--cw-ink); font-weight: 600; }
.cw-header-actions { display: flex; align-items: center; gap: var(--cw-s3); }

/* Bell relocated into the header (was position:fixed) */
/* The bell was originally a FLOATING control: dashboard.css still declares
   `position: fixed; top: 14px; right: 18px`. Two things follow, and both bite.

   1. It must be `relative`, not `static`. .notif-badge is absolutely
      positioned at top/right -4px; with a static parent it resolves against
      the VIEWPORT instead and pins itself to the page's top-right corner,
      which also forces a horizontal scrollbar.
   2. The inherited top/right MUST be cleared. `static` merely made them inert
      — switching to `relative` reactivates them as offsets and shunts the bell
      down 14px and left 18px. That is why "just set relative" looks broken. */
.cw-header .notif-bell {
  position: relative;
  top: auto; right: auto; bottom: auto; left: auto;
  width: 36px; height: 36px; box-shadow: none;
  border: 1px solid var(--cw-border);
}
.cw-header .notif-bell:hover { border-color: var(--cw-accent-border); }
/* The badge's ring is a hardcoded #fff in dashboard.css — a white halo on a
   dark header. Match whatever the bell is actually sitting on. */
.cw-header .notif-badge { border-color: var(--cw-surface); }

/* Account menu */
.cw-account { position: relative; }
.cw-account-btn {
  display: inline-flex; align-items: center; gap: var(--cw-s2);
  height: 36px; padding: 0 var(--cw-s3);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-full); cursor: pointer;
  font: var(--cw-small); color: var(--cw-text); font-family: inherit;
  transition: border-color var(--cw-t-micro);
}
.cw-account-btn:hover { border-color: var(--cw-border-strong); }
.cw-avatar {
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--cw-accent); color: var(--cw-accent-ink);
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 12px/1 var(--cw-font); text-transform: uppercase;
}

/* ══ Buttons ════════════════════════════════════════════════════════════ */

.cw-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--cw-s2);
  font: 600 14px/1 var(--cw-font); border-radius: var(--cw-r-md);
  height: 38px; padding: 0 var(--cw-s4); cursor: pointer; white-space: nowrap;
  border: 1px solid transparent;
  transition: background var(--cw-t-micro), border-color var(--cw-t-micro), color var(--cw-t-micro);
}
.cw-btn:disabled { opacity: .55; cursor: not-allowed; }
.cw-btn-sm { height: 32px; padding: 0 var(--cw-s3); font-size: 13px; }

.cw-btn-primary   { background: var(--cw-accent); color: var(--cw-accent-ink); }
.cw-btn-primary:hover:not(:disabled) { background: var(--cw-accent-hover); }
.cw-btn-secondary { background: var(--cw-surface); color: var(--cw-text); border-color: var(--cw-border-strong); }
.cw-btn-secondary:hover:not(:disabled) { border-color: var(--cw-text-faint); background: var(--cw-surface-2); }
.cw-btn-ghost     { background: none; color: var(--cw-text-soft); }
.cw-btn-ghost:hover:not(:disabled) { background: var(--cw-surface-2); color: var(--cw-ink); }
.cw-btn-danger    { background: var(--cw-danger); color: #fff; }
.cw-btn-danger:hover:not(:disabled) { background: #B91C1C; }
.cw-btn-icon      { width: 36px; padding: 0; }

/* ══ Status badges — the Health language (§16.5) ════════════════════════ */

.cw-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font: var(--cw-micro); font-weight: 600;
  padding: 3px 10px; border-radius: var(--cw-r-full);
  border: 1px solid var(--cw-border); background: var(--cw-surface-2); color: var(--cw-text-soft);
}
.cw-badge .cw-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.cw-badge-ok     { background: var(--cw-ok-bg);     border-color: var(--cw-ok-border);     color: var(--cw-ok); }
.cw-badge-warn   { background: var(--cw-warn-bg);   border-color: var(--cw-warn-border);   color: var(--cw-warn); }
.cw-badge-danger { background: var(--cw-danger-bg); border-color: var(--cw-danger-border); color: var(--cw-danger); }
.cw-badge-info   { background: var(--cw-info-bg);   border-color: var(--cw-info-border);   color: var(--cw-info); }
/* Breathing dot — in-progress operations ONLY. Calm, 2s, reduced-motion aware. */
.cw-badge-pulse .cw-dot { animation: cw-breathe 2s ease-in-out infinite; }
@keyframes cw-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ══ Cards ══════════════════════════════════════════════════════════════ */

.cw-card {
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); padding: var(--cw-s5);
  transition: box-shadow var(--cw-t-micro), border-color var(--cw-t-micro);
}
.cw-card-hover:hover { box-shadow: var(--cw-e1); border-color: var(--cw-border-strong); }
.cw-card-title { font: var(--cw-heading); color: var(--cw-ink); margin: 0 0 var(--cw-s3); }

.cw-stat { display: flex; flex-direction: column; gap: var(--cw-s1); }
/* The number must dominate its label — it's the reason the card exists. */
.cw-stat-value {
  font: 700 32px/38px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.cw-stat-label {
  font: 600 11px/16px var(--cw-font); color: var(--cw-text-soft);
  text-transform: uppercase; letter-spacing: .07em;
}
.cw-stat-delta { font: var(--cw-micro); }
.cw-stat-delta.up { color: var(--cw-ok); }
.cw-stat-delta.down { color: var(--cw-danger); }

/* ══ Skeletons — replace every "Loading…" string ════════════════════════ */

.cw-skel {
  position: relative; overflow: hidden;
  background: var(--cw-surface-2); border-radius: var(--cw-r-sm);
  min-height: 14px;
}
/* Shimmer animates ONLY transform — no layout, no paint of the parent, and it
   gets its own compositor layer. `will-change` is deliberately absent: these
   render in their dozens and promoting every one costs more than it saves. */
.cw-skel::after {
  content: ''; position: absolute; inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .55), transparent);
  animation: cw-shimmer 1.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes cw-shimmer { to { transform: translateX(100%); } }
/* Dark mode: a white sweep over a dark plate reads as a flash. */
[data-theme="dark"] .cw-skel::after {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .07), transparent);
}
/* tokens.css already neutralises animation globally under prefers-reduced-
   motion; this makes the fallback deliberate rather than incidental — a calm
   static plate instead of a frozen mid-sweep gradient. */
@media (prefers-reduced-motion: reduce) {
  .cw-skel::after { display: none; }
  .cw-skel { background: var(--cw-surface-2); }
}

.cw-skel-text  { height: 14px; }
.cw-skel-title { height: 22px; width: 40%; }
.cw-skel-block { height: 96px; border-radius: var(--cw-r-lg); }

/* ── Skeleton component set ─────────────────────────────────
   The vocabulary every page composes its own layout from. Sizes deliberately
   mirror the real components (see the paired rule noted on each) so swapping
   skeleton for content shifts nothing. */
.cw-skel-line   { height: 12px; border-radius: var(--cw-r-sm); }
.cw-skel-head   { height: 30px; width: 260px; border-radius: var(--cw-r-sm); }  /* --cw-display */
.cw-skel-badge  { height: 20px; width: 76px; border-radius: var(--cw-r-full); }
.cw-skel-btn    { height: 36px; width: 116px; border-radius: var(--cw-r-md); }
.cw-skel-input  { height: 38px; width: 100%; border-radius: var(--cw-r-md); }
.cw-skel-avatar { height: 34px; width: 34px; border-radius: var(--cw-r-md); flex: none; }
.cw-skel-chip   { height: 32px; width: 84px; border-radius: var(--cw-r-full); flex: none; }
.cw-skel-chart  { height: 140px; border-radius: var(--cw-r-md); }

.cw-skel-card {
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); padding: var(--cw-s5);
  display: flex; flex-direction: column; gap: var(--cw-s3);
}
.cw-skel-stack { display: flex; flex-direction: column; gap: var(--cw-s3); }
.cw-skel-row   { display: flex; align-items: center; gap: var(--cw-s3); }
.cw-skel-grid  { display: grid; gap: var(--cw-s4); }
.cw-skel-grid-3 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.cw-skel-grid-cards { grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: var(--cw-s5); }

/* Table skeleton — same 5-column rhythm as .bl-inv-table / .cw-table. */
.cw-skel-table { background: var(--cw-surface); border: 1px solid var(--cw-border); border-radius: var(--cw-r-lg); overflow: hidden; }
.cw-skel-tr {
  display: grid; grid-template-columns: 2fr 1fr 1fr 90px; gap: var(--cw-s4);
  align-items: center; padding: var(--cw-s4) var(--cw-s5);
  border-bottom: 1px solid var(--cw-border);
}
.cw-skel-tr:last-child { border-bottom: 0; }
.cw-skel-th { background: var(--cw-surface-2); }

/* First-frame placeholder for the two template grids. It sits in static markup
   so it paints before JS runs; JS then swaps in the full card-grid skeleton.
   Shaped like one row of cards rather than a bar, so the swap doesn't jump. */
.cs-demo-loading-skel {
  min-height: 210px; border-radius: var(--cw-r-lg);
  background: var(--cw-surface-2);
  position: relative; overflow: hidden;
}
.cs-demo-loading-skel::after {
  content: ''; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .55), transparent);
  animation: cw-shimmer 1.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
[data-theme="dark"] .cs-demo-loading-skel::after {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .07), transparent);
}
@media (prefers-reduced-motion: reduce) { .cs-demo-loading-skel::after { display: none; } }

/* ── Boot chrome (K2) ───────────────────────────────────────
   Show the real sidebar and header while the first request is in flight, so
   the loading state has the app's actual two-column geometry instead of one
   full-bleed skeleton. Beats `.hidden`'s !important by specificity + order. */
html.cw-booting #dash-sidebar.hidden { display: flex !important; }
html.cw-booting #cw-header.hidden    { display: flex !important; }

/* Nothing in the chrome is clickable yet — the panels behind it have no data,
   so a click would navigate to a blank tab. It reads as present, not ready. */
html.cw-booting #dash-sidenav,
html.cw-booting .cw-header-actions,
html.cw-booting .dash-sidebar-footer { pointer-events: none; }
html.cw-booting #dash-sidenav { opacity: .55; }
/* The two genuinely data-dependent bits of chrome get placeholders rather than
   showing empty. */
html.cw-booting #nav-email {
  display: block; width: 130px; height: 12px; border-radius: var(--cw-r-sm);
  background: var(--cw-surface-2); color: transparent; overflow: hidden;
}
html.cw-booting .cw-avatar { color: transparent; background: var(--cw-surface-2); }

/* Boot skeleton container — overrides .dash-loading's centred spinner box so
   the skeleton fills the content column exactly like the real page does. */
.dash-skel {
  display: block !important; text-align: left !important;
  padding: 0 !important; min-height: 0 !important;
}
.dash-skel-split {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: var(--cw-s5); margin-top: var(--cw-s5);
}
@media (max-width: 900px) { .dash-skel-split { grid-template-columns: 1fr; } }

/* ── Reveal: skeleton → content ─────────────────────────────
   opacity + transform only. Applied by CW.reveal() to whatever just replaced
   a skeleton, so content arrives instead of snapping in. */
.cw-reveal { animation: cw-reveal 220ms cubic-bezier(.2, .8, .3, 1) both; }
@keyframes cw-reveal {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cw-reveal { animation: none; }
}

/* ══ Toast queue (replaces the single #toast element for new code) ══════ */

.cw-toasts {
  position: fixed; right: var(--cw-s5); bottom: var(--cw-s5); z-index: 1200;
  display: flex; flex-direction: column; gap: var(--cw-s2);
  pointer-events: none;
}
.cw-toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: var(--cw-s3);
  min-width: 260px; max-width: 380px;
  background: var(--cw-ink); color: #fff;
  border-radius: var(--cw-r-md); padding: var(--cw-s3) var(--cw-s4);
  font: var(--cw-small); box-shadow: var(--cw-e2);
  border-left: 3px solid var(--cw-accent);
  animation: cw-toast-in var(--cw-t-std) both;
}
.cw-toast-ok     { border-left-color: var(--cw-ok); }
.cw-toast-danger { border-left-color: var(--cw-danger); }
.cw-toast-warn   { border-left-color: var(--cw-warn); }
.cw-toast-action {
  margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--cw-chart-3); font: 600 13px/1 var(--cw-font);
}
.cw-toast.cw-toast-leaving { animation: cw-toast-out var(--cw-t-std) both; }
@keyframes cw-toast-in  { from { opacity: 0; transform: translateY(8px); } }
@keyframes cw-toast-out { to   { opacity: 0; transform: translateY(8px); } }

/* ══ Empty states ═══════════════════════════════════════════════════════ */

.cw-empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--cw-s3);
  padding: var(--cw-s8) var(--cw-s5); text-align: center;
}
.cw-empty svg { color: var(--cw-border-strong); }
.cw-empty-title { font: var(--cw-heading); color: var(--cw-ink); }
.cw-empty-text  { font: var(--cw-small); color: var(--cw-text-soft); max-width: 340px; }

/* ══ Table ══════════════════════════════════════════════════════════════ */

.cw-table { width: 100%; border-collapse: collapse; font: var(--cw-small); }
.cw-table th {
  text-align: left; font: var(--cw-micro); color: var(--cw-text-soft);
  text-transform: uppercase; letter-spacing: .04em;
  padding: var(--cw-s2) var(--cw-s3); border-bottom: 1px solid var(--cw-border);
}
.cw-table td { padding: var(--cw-s3); border-bottom: 1px solid var(--cw-surface-2); color: var(--cw-text); }
.cw-table tr:hover td { background: var(--cw-bg); }
.cw-table .cw-num { font-variant-numeric: tabular-nums; text-align: right; }

/* ══ Forms ══════════════════════════════════════════════════════════════ */

.cw-field { display: flex; flex-direction: column; gap: var(--cw-s1); margin-bottom: var(--cw-s4); }
.cw-label { font: 600 13px/18px var(--cw-font); color: var(--cw-text); }
.cw-help  { font: var(--cw-micro); color: var(--cw-text-soft); }
.cw-input, .cw-select, .cw-textarea {
  font: var(--cw-body); font-family: inherit; color: var(--cw-ink);
  background: var(--cw-surface); border: 1px solid var(--cw-border-strong);
  border-radius: var(--cw-r-sm); padding: 9px var(--cw-s3); width: 100%; box-sizing: border-box;
  transition: border-color var(--cw-t-micro), box-shadow var(--cw-t-micro);
}
.cw-input:focus, .cw-select:focus, .cw-textarea:focus {
  outline: none; border-color: var(--cw-accent);
  box-shadow: 0 0 0 3px var(--cw-accent-subtle);
}
.cw-field-error .cw-input { border-color: var(--cw-danger); }
.cw-error-text { font: var(--cw-micro); color: var(--cw-danger); }

.cw-copy {
  display: flex; align-items: center; gap: var(--cw-s2);
  background: var(--cw-surface-2); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-sm); padding: 8px var(--cw-s3);
  font: 500 13px/20px var(--cw-font-mono); color: var(--cw-ink);
}
.cw-copy button {
  margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--cw-accent); display: inline-flex; padding: 2px;
}

/* ══ Side panel (informational) + Dialog (destructive) — §16.1.2 ════════ */

.cw-scrim {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(22, 22, 31, .32);
  opacity: 0; transition: opacity var(--cw-t-std);
}
.cw-scrim.open { opacity: 1; }

.cw-panel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 1001;
  width: min(480px, 100vw); background: var(--cw-surface);
  box-shadow: var(--cw-e2); display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform var(--cw-t-panel);
}
.cw-panel.cw-panel-wide { width: min(640px, 100vw); }
.cw-panel.open { transform: translateX(0); }
.cw-panel-head {
  display: flex; align-items: center; gap: var(--cw-s3);
  padding: var(--cw-s4) var(--cw-s5); border-bottom: 1px solid var(--cw-border);
}
.cw-panel-title { font: var(--cw-title); color: var(--cw-ink); flex: 1; min-width: 0; }
.cw-panel-context { font: var(--cw-micro); color: var(--cw-text-soft); }
.cw-panel-body { flex: 1; overflow-y: auto; padding: var(--cw-s5); }
.cw-panel-foot { padding: var(--cw-s4) var(--cw-s5); border-top: 1px solid var(--cw-border); display: flex; gap: var(--cw-s3); justify-content: flex-end; }
.cw-panel-close {
  background: none; border: 0; cursor: pointer; color: var(--cw-text-faint);
  font-size: 20px; line-height: 1; padding: var(--cw-s1);
}
.cw-panel-close:hover { color: var(--cw-ink); }

.cw-dialog {
  position: fixed; top: 50%; left: 50%; z-index: 1001;
  transform: translate(-50%, -46%) scale(.98); opacity: 0;
  width: min(440px, calc(100vw - 32px));
  background: var(--cw-surface); border-radius: var(--cw-r-lg);
  box-shadow: var(--cw-e2); padding: var(--cw-s6);
  transition: transform var(--cw-t-std), opacity var(--cw-t-std);
}
.cw-dialog.open { transform: translate(-50%, -50%) scale(1); opacity: 1; }
.cw-dialog-danger { border-top: 3px solid var(--cw-danger); }

/* ══ Dropdown menu (keyboard-navigable — replaces kebab pattern) ════════ */

/* FIXED, not absolute. CW.menu() positions this from
   anchor.getBoundingClientRect() and clamps against window.innerHeight /
   innerWidth — both viewport coordinates. Under `absolute` those resolve
   against the DOCUMENT instead, so the menu was drawn exactly scrollY pixels
   too high: on a scrolled Sites page it floated over the middle of the screen,
   detached from the button that opened it. The JS was always written for
   fixed; the CSS disagreed. */
.cw-menu {
  position: fixed; z-index: 900; min-width: 200px;
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-md); box-shadow: var(--cw-e2); padding: var(--cw-s1);
}
.cw-menu [role="menuitem"] {
  display: flex; align-items: center; gap: var(--cw-s2); width: 100%;
  font: var(--cw-small); color: var(--cw-text); font-family: inherit;
  background: none; border: 0; border-radius: var(--cw-r-sm);
  padding: 8px var(--cw-s3); cursor: pointer; text-align: left;
}
.cw-menu [role="menuitem"]:hover,
.cw-menu [role="menuitem"]:focus-visible { background: var(--cw-surface-2); color: var(--cw-ink); }
.cw-menu [role="menuitem"].cw-menu-danger { color: var(--cw-danger); }
.cw-menu-sep { height: 1px; background: var(--cw-border); margin: var(--cw-s1) 0; }

/* ══ Tabs (primary + secondary — §16.3) ═════════════════════════════════ */

.cw-tabs { display: flex; gap: var(--cw-s1); border-bottom: 1px solid var(--cw-border); }
.cw-tab {
  font: 600 14px/20px var(--cw-font); color: var(--cw-text-soft);
  background: none; border: 0; border-bottom: 2px solid transparent;
  padding: var(--cw-s3) var(--cw-s4); cursor: pointer; font-family: inherit;
  transition: color var(--cw-t-micro);
}
.cw-tab:hover { color: var(--cw-ink); }
.cw-tab[aria-selected="true"] { color: var(--cw-accent); border-bottom-color: var(--cw-accent); }
.cw-subtabs { display: flex; gap: var(--cw-s2); flex-wrap: wrap; }
.cw-subtab {
  font: 600 13px/18px var(--cw-font); color: var(--cw-text-soft);
  background: none; border: 1px solid transparent; border-radius: var(--cw-r-full);
  padding: 6px var(--cw-s4); cursor: pointer; font-family: inherit;
}
.cw-subtab:hover { background: var(--cw-surface-2); color: var(--cw-ink); }
.cw-subtab[aria-selected="true"] { background: var(--cw-accent-subtle); border-color: var(--cw-accent-border); color: var(--cw-accent); }

/* ══ Banner ═════════════════════════════════════════════════════════════ */

.cw-banner {
  display: flex; align-items: flex-start; gap: var(--cw-s3);
  border-radius: var(--cw-r-md); padding: var(--cw-s3) var(--cw-s4);
  font: var(--cw-small); border: 1px solid var(--cw-border); background: var(--cw-surface-2);
}
.cw-banner-warn   { background: var(--cw-warn-bg);   border-color: var(--cw-warn-border); }
.cw-banner-danger { background: var(--cw-danger-bg); border-color: var(--cw-danger-border); }
.cw-banner-info   { background: var(--cw-info-bg);   border-color: var(--cw-info-border); }

/* ══ Overview — the daily screen (U2) ═══════════════════════════════════ */

.ov-head { margin-bottom: var(--cw-s5); }
/* The greeting is the strongest thing on the page — it sets the whole tone. */
.ov-greeting { font: 700 34px/40px var(--cw-font); color: var(--cw-ink); margin: 0 0 6px; letter-spacing: -.02em; }
.ov-fleetline { font: 450 15px/24px var(--cw-font); color: var(--cw-text-soft); margin: 0; }

.ov-fleet { display: flex; flex-wrap: wrap; gap: var(--cw-s2); margin-bottom: var(--cw-s6); }
.ov-pill {
  display: inline-flex; align-items: center; gap: var(--cw-s2);
  font: var(--cw-small); color: var(--cw-text);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-full); padding: 6px var(--cw-s4);
}
.ov-pill strong { color: var(--cw-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.ov-pill .cw-dot { width: 8px; height: 8px; border-radius: 50%; }
.ov-pill-ok   .cw-dot { background: var(--cw-ok); }
.ov-pill-warn .cw-dot { background: var(--cw-warn); }
.ov-pill-info .cw-dot { background: var(--cw-accent); animation: cw-breathe 2s ease-in-out infinite; }

.ov-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--cw-s4); margin-bottom: var(--cw-s7);
}

.ov-section { margin-bottom: var(--cw-s7); }
.ov-section-title {
  font: var(--cw-micro); color: var(--cw-text-soft); text-transform: uppercase;
  letter-spacing: .06em; margin: 0 0 var(--cw-s3);
}

.ov-list { display: flex; flex-direction: column; gap: var(--cw-s2); }
.ov-item {
  display: flex; align-items: center; gap: var(--cw-s3);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-left-width: 3px; border-radius: var(--cw-r-md);
  padding: var(--cw-s3) var(--cw-s4);
}
.ov-item .cw-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.ov-item-icon {
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 12px/1 var(--cw-font);
}
.ov-item-warn   { border-left-color: var(--cw-warn); }
.ov-item-warn   .cw-dot { background: var(--cw-warn); }
.ov-item-warn   .ov-item-icon { background: var(--cw-warn-bg); color: var(--cw-warn); }
.ov-item-danger { border-left-color: var(--cw-danger); }
.ov-item-danger .cw-dot { background: var(--cw-danger); }
.ov-item-danger .ov-item-icon { background: var(--cw-danger-bg); color: var(--cw-danger); }
.ov-item-info   { border-left-color: var(--cw-accent); }
.ov-item-info   .cw-dot { background: var(--cw-accent); }
.cw-dot-pulse { animation: cw-breathe 2s ease-in-out infinite; }
.ov-item-main { flex: 1; min-width: 0; }
.ov-item-title { font: 600 14px/20px var(--cw-font); color: var(--cw-ink); }
.ov-item-sub { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: 2px; }
.ov-steps {
  font: var(--cw-micro); color: var(--cw-text-soft); white-space: pre-line;
  margin: 4px 0 0; font-family: inherit;
}

.ov-cols { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--cw-s6); }
@media (max-width: 900px) { .ov-cols { grid-template-columns: 1fr; } }

.ov-activity {
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); padding: var(--cw-s2) var(--cw-s4);
}
/* Richer, taller activity rows — scannable at a glance (glyph · what · when). */
.ov-act {
  display: flex; align-items: flex-start; gap: var(--cw-s3);
  padding: 13px 0; border-bottom: 1px solid var(--cw-surface-2);
}
.ov-act:last-child { border-bottom: 0; }
.ov-act-glyph {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 11px/1 var(--cw-font);
}
.ov-glyph-ok     { background: var(--cw-ok-bg);     color: var(--cw-ok); }
.ov-glyph-warn   { background: var(--cw-warn-bg);   color: var(--cw-warn); }
.ov-glyph-danger { background: var(--cw-danger-bg); color: var(--cw-danger); }
.ov-glyph-info   { background: var(--cw-info-bg);   color: var(--cw-accent); }
.ov-act-main { flex: 1; min-width: 0; }
.ov-act-title { font: 500 13.5px/19px var(--cw-font); color: var(--cw-text); }
.ov-act-sub { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: 3px; }

.ov-spark { width: 100%; height: 24px; display: block; margin: 2px 0 4px; }
.ov-spark rect { fill: var(--cw-chart-3); }
.sd-warn { color: var(--cw-warn); font-weight: 700; }

/* Sidebar separator introduced when Launch was demoted below the workspace items */
.dash-sidenav-sep { height: 1px; background: var(--cw-border); margin: var(--cw-s3) var(--cw-s3); }

/* ══ Notification center — filters + day grouping (U6) ══════════════════ */

.notif-filters {
  display: flex; gap: 4px; padding: var(--cw-s3) var(--cw-s4) var(--cw-s2);
  border-bottom: 1px solid var(--cw-border); flex-wrap: wrap;
  position: sticky; top: 0; background: var(--cw-surface); z-index: 1;
}
.notif-filter {
  display: inline-flex; align-items: center; gap: 5px;
  font: var(--cw-micro); font-weight: 600; color: var(--cw-text-soft);
  background: none; border: 1px solid transparent; border-radius: var(--cw-r-full);
  padding: 4px 10px; cursor: pointer; font-family: inherit;
}
.notif-filter:hover { background: var(--cw-surface-2); color: var(--cw-ink); }
.notif-filter.is-on { background: var(--cw-accent-subtle); border-color: var(--cw-accent-border); color: var(--cw-accent); }
.notif-filter span {
  background: var(--cw-surface-2); border-radius: var(--cw-r-full);
  padding: 0 5px; font-size: 10px; color: var(--cw-text-soft);
}
.notif-filter.is-on span { background: var(--cw-surface); color: var(--cw-accent); }

.notif-day {
  font: var(--cw-micro); font-weight: 700; color: var(--cw-text-soft);
  text-transform: uppercase; letter-spacing: .06em;
  padding: var(--cw-s3) var(--cw-s4) 6px; background: var(--cw-surface);
}
.notif-item-action {
  display: inline-block; margin-top: 6px;
  font: var(--cw-micro); font-weight: 600; color: var(--cw-accent); text-decoration: none;
}
.notif-item-action:hover { text-decoration: underline; }

/* ══ Billing summary (U6) ═══════════════════════════════════════════════ */

.bl-summary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--cw-s4); margin-bottom: var(--cw-s6);
}

/* ══ Support context (U6) ═══════════════════════════════════════════════ */

.sp-identity {
  display: flex; align-items: center; gap: var(--cw-s3); flex-wrap: wrap;
  background: var(--cw-surface-2); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-md); padding: var(--cw-s3) var(--cw-s4);
  font: var(--cw-small); color: var(--cw-text); margin-bottom: var(--cw-s4);
}
.sp-identity strong { color: var(--cw-ink); }
.sp-identity button {
  margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--cw-accent); font: 600 12px/1 var(--cw-font); font-family: inherit;
}
.sp-expect {
  font: var(--cw-micro); color: var(--cw-text-soft);
  margin-top: var(--cw-s2);
}

/* ══ Provisioning takeover + arrival (U5) ═══════════════════════════════ */

.pv-takeover {
  position: fixed; inset: 0; z-index: 1300;
  background: linear-gradient(180deg, var(--cw-surface) 0%, var(--cw-bg) 100%);
  display: flex; align-items: center; justify-content: center;
  padding: var(--cw-s6); overflow-y: auto;
  animation: cw-fade-in var(--cw-t-std) both;
}
@keyframes cw-fade-in { from { opacity: 0; } }
.pv-inner { width: 100%; max-width: 520px; text-align: center; }

/* Breathing orb — the only "we're working" motion; calm, not a spinner race */
.pv-orb { position: relative; width: 84px; height: 84px; margin: 0 auto var(--cw-s6); }
.pv-orb span {
  position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--cw-accent-border);
  animation: pv-ripple 2.4s ease-out infinite;
}
.pv-orb span:nth-child(2) { animation-delay: .8s; }
.pv-orb span:nth-child(3) { animation-delay: 1.6s; }
.pv-orb::after {
  content: ''; position: absolute; inset: 30%;
  background: var(--cw-accent); border-radius: 50%;
  animation: cw-breathe 2.4s ease-in-out infinite;
}
@keyframes pv-ripple {
  0%   { transform: scale(.55); opacity: .9; }
  100% { transform: scale(1);   opacity: 0; }
}

.pv-title { font: var(--cw-display); color: var(--cw-ink); margin: 0 0 var(--cw-s2); }
.pv-sub { font: var(--cw-body); color: var(--cw-text-soft); margin: 0 auto var(--cw-s6); max-width: 400px; }

.pv-steps { list-style: none; margin: 0 auto; padding: 0; max-width: 320px; text-align: left; }
.pv-step {
  display: flex; align-items: center; gap: var(--cw-s3);
  font: var(--cw-body); color: var(--cw-text-faint);
  padding: 9px 0; transition: color var(--cw-t-std);
}
.pv-mark { width: 18px; text-align: center; font-size: 14px; flex: none; }
.pv-step.is-done   { color: var(--cw-text); }
.pv-step.is-done .pv-mark { color: var(--cw-ok); font-weight: 700; }
.pv-step.is-active { color: var(--cw-ink); font-weight: 600; }
.pv-step.is-active .pv-mark { color: var(--cw-accent); animation: pv-spin 1.4s linear infinite; }
@keyframes pv-spin { to { transform: rotate(360deg); } }

.pv-error {
  margin-top: var(--cw-s5); padding: var(--cw-s4);
  background: var(--cw-danger-bg); border: 1px solid var(--cw-danger-border);
  border-radius: var(--cw-r-md); font: var(--cw-small); color: var(--cw-text); text-align: left;
}

/* Arrival */
.pv-done { position: relative; animation: pv-rise var(--cw-t-panel) both; }
@keyframes pv-rise { from { opacity: 0; transform: translateY(10px); } }
.pv-check {
  width: 72px; height: 72px; margin: 0 auto var(--cw-s5);
  border-radius: 50%; background: var(--cw-ok-bg); color: var(--cw-ok);
  display: flex; align-items: center; justify-content: center;
}
.pv-domain {
  font: 600 17px/24px var(--cw-font-mono); color: var(--cw-accent);
  margin: 0 0 var(--cw-s3); word-break: break-all;
}
.pv-actions { display: flex; flex-wrap: wrap; gap: var(--cw-s2); justify-content: center; margin-top: var(--cw-s6); }
.pv-next { font: var(--cw-small); color: var(--cw-text-soft); margin-top: var(--cw-s5); }
.pv-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--cw-accent); font: inherit; font-weight: 600; text-decoration: underline;
}

.pv-confetti { position: absolute; inset: -20px 0 auto; height: 200px; overflow: hidden; pointer-events: none; }
.pv-confetti i {
  position: absolute; top: -12px; width: 7px; height: 11px; border-radius: 1px;
  animation: pv-fall 2.2s ease-in forwards;
}
@keyframes pv-fall {
  to { transform: translateY(220px) rotate(220deg); opacity: 0; }
}

/* ══ Sites — adaptive project view (U4) ═════════════════════════════════ */

.sv-tools { display: flex; align-items: center; gap: var(--cw-s2); flex-wrap: wrap; }
/* Search leads the toolbar — highest-frequency action at any fleet size. */
.sv-search { width: 220px; height: 34px; padding: 0 var(--cw-s3); margin-right: var(--cw-s2); }
.sites-toolbar { flex-wrap: wrap; gap: var(--cw-s2); }
.sv-sort { width: auto; height: 34px; padding: 0 var(--cw-s3); }
.sv-density {
  display: inline-flex; border: 1px solid var(--cw-border-strong);
  border-radius: var(--cw-r-md); overflow: hidden;
}
.sv-density button {
  background: var(--cw-surface); border: 0; cursor: pointer;
  padding: 0 10px; height: 34px; color: var(--cw-text-soft); font-size: 14px;
}
.sv-density button.is-on { background: var(--cw-accent-subtle); color: var(--cw-accent); }

/* Grid */
.sv-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--cw-s5);
}

/* Six calm blocks with real breathing room: identity → health → evidence →
   actions. A HEALTHY card is deliberately plain — no coloured edge, nothing
   shouting — so an unhealthy one is impossible to miss. State is communicated
   through appearance, not just badges. */
.sc-card {
  display: flex; flex-direction: column;
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); padding: var(--cw-s5);
  cursor: pointer;
  transition: box-shadow var(--cw-t-micro), border-color var(--cw-t-micro);
}
.sc-card:hover { box-shadow: var(--cw-e1); border-color: var(--cw-border-strong); }
.sc-card:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }

/* Only states that need you get an accent. Healthy stays quiet. */
.sc-attention { border-left: 3px solid var(--cw-warn); padding-left: calc(var(--cw-s5) - 2px); }
.sc-down {
  border-left: 3px solid var(--cw-danger); padding-left: calc(var(--cw-s5) - 2px);
  background: linear-gradient(90deg, var(--cw-danger-bg) 0%, var(--cw-surface) 42%);
}
.sc-provisioning, .sc-recovering {
  border-left: 3px solid var(--cw-accent); padding-left: calc(var(--cw-s5) - 2px);
}
.sc-removed { opacity: .6; }

/* Loading placeholder: the SHAPE of a card, never a fake card. It holds the
   layout so nothing jumps when the real data lands, and it is unmistakably
   not content — no borrowed numbers, no hover, no pointer. */
.sv-skel {
  min-height: 188px; border-style: dashed; background: var(--cw-surface-2);
  pointer-events: none; opacity: .55;
  animation: cw-skel-pulse 1.4s ease-in-out infinite;
}
.sv-skel:hover { box-shadow: none; border-color: var(--cw-border); }
@keyframes cw-skel-pulse { 0%, 100% { opacity: .35; } 50% { opacity: .6; } }
@media (prefers-reduced-motion: reduce) { .sv-skel { animation: none; } }

/* 1 — identity */
.sc-head { display: flex; align-items: center; gap: var(--cw-s3); margin-bottom: var(--cw-s4); }
.sc-mono {
  width: 34px; height: 34px; border-radius: var(--cw-r-md); flex: none;
  display: inline-flex; align-items: center; justify-content: center; overflow: hidden;
  color: #fff; font: 700 13px/1 var(--cw-font); letter-spacing: .02em;
}
.sc-fav-img { width: 34px; height: 34px; object-fit: contain; display: block; }
.sc-id { flex: 1; min-width: 0; }
.sc-name {
  font: 600 15px/21px var(--cw-font); color: var(--cw-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sc-sub { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: 2px; }
.sc-menu { flex: none; font-size: 16px; line-height: 1; }

/* 2 — health (the only colour) + metadata */
.sc-health {
  display: flex; align-items: center; gap: var(--cw-s3); flex-wrap: wrap;
  padding-bottom: var(--cw-s4); border-bottom: 1px solid var(--cw-surface-2);
  margin-bottom: var(--cw-s4);
}
.sc-meta { font: var(--cw-micro); color: var(--cw-text-soft); }

/* 3 — evidence: labelled numbers, never decorative bars */
.sc-stats { display: flex; flex-direction: column; gap: var(--cw-s3); margin-bottom: var(--cw-s5); }
.sc-stat { display: flex; align-items: baseline; gap: var(--cw-s2); flex-wrap: wrap; }
.sc-stat-k {
  font: 600 11px/16px var(--cw-font); color: var(--cw-text-soft);
  text-transform: uppercase; letter-spacing: .06em; width: 62px; flex: none;
}
.sc-stat-v { font: 600 14px/20px var(--cw-font); color: var(--cw-ink); font-variant-numeric: tabular-nums; }
.sc-stat-v em { font-style: normal; font-weight: 450; color: var(--cw-text-faint); }
.sc-stat-s { font: var(--cw-micro); color: var(--cw-text-faint); }
.sc-of { font-weight: 450; color: var(--cw-text-soft); }

/* Provisioning: the card visibly works */
.sc-op {
  background: var(--cw-accent-subtle); border-radius: var(--cw-r-md);
  padding: var(--cw-s3) var(--cw-s4); margin-bottom: var(--cw-s5);
}
.sc-op-title { font: 600 13px/18px var(--cw-font); color: var(--cw-accent); }
.sc-op-steps {
  font: var(--cw-micro); color: var(--cw-text); white-space: pre-line;
  margin: 6px 0 8px; font-family: inherit;
}
.sc-op-bar { height: 3px; border-radius: 2px; background: var(--cw-accent-border); overflow: hidden; }
.sc-op-bar > i {
  display: block; height: 100%; width: 38%; border-radius: 2px;
  background: var(--cw-accent); animation: sc-indet 1.6s ease-in-out infinite;
}
@keyframes sc-indet {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(320%); }
}

/* 4 — actions */
.sc-foot { display: flex; align-items: center; gap: var(--cw-s2); margin-top: auto; }
.sc-foot .cw-btn { flex: 1; }

.sl-mono { width: 22px; height: 22px; border-radius: 5px; font-size: 9px; }

/* List */
/* Empty state gets the FULL width — never a grid cell. See paint(). */
.sv-empty-wrap { display: block; }
.sv-empty {
  gap: var(--cw-s3); padding: var(--cw-s8) var(--cw-s5);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg);
}
.sv-empty .cw-btn { margin-top: var(--cw-s2); }
/* "Nothing needs attention" is good news, so it reads calm-positive rather
   than like a failed search. */
.sv-empty-ok { border-color: var(--cw-ok-border); background: var(--cw-ok-bg); }
.sv-empty-mark {
  width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--cw-surface); color: var(--cw-ok);
  font: 700 18px/1 var(--cw-font); border: 1px solid var(--cw-ok-border);
  margin-bottom: var(--cw-s1);
}

.sv-list { display: flex; flex-direction: column; }
.sl-head, .sl-row {
  display: grid; grid-template-columns: 24px 1fr 150px 90px 90px 40px;
  align-items: center; gap: var(--cw-s3);
}
.sl-head {
  font: var(--cw-micro); color: var(--cw-text-soft); text-transform: uppercase;
  letter-spacing: .04em; padding: 0 var(--cw-s3) var(--cw-s2);
}
.sl-row {
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-md); padding: 10px var(--cw-s3); margin-bottom: 6px;
  cursor: pointer; transition: border-color var(--cw-t-micro);
}
.sl-row:hover { border-color: var(--cw-border-strong); background: var(--cw-bg); }
.sl-fav { border-radius: 4px; }
.sl-name {
  font: 600 14px/20px var(--cw-font); color: var(--cw-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sl-views { font: var(--cw-small); color: var(--cw-text-soft); text-align: right; }
@media (max-width: 720px) {
  .sl-head { display: none; }
  .sl-row { grid-template-columns: 24px 1fr auto; }
  .sl-plan, .sl-views { display: none; }
}

/* ══ Site Detail (U3) — the central object ══════════════════════════════ */

.sd-head { display: flex; align-items: center; gap: var(--cw-s4); margin-bottom: var(--cw-s5); }
/* Same monogram as the site's card, one size up — the object you clicked is
   visibly the object you're now looking at. */
.sd-mono { width: 44px; height: 44px; border-radius: var(--cw-r-md); font-size: 16px; }
.sd-mono .sc-fav-img { width: 44px; height: 44px; }
/* Delete is present but never competes with Restore/Download; it earns colour
   only on intent. */
.sd-bk-del { color: var(--cw-text-soft); padding-left: 8px; padding-right: 8px; }
.sd-bk-del:hover { color: var(--cw-danger); background: var(--cw-danger-soft, rgba(220, 38, 38, .08)); }
.sd-bk-del svg { display: block; }
.sd-id { flex: 1; min-width: 0; }
.sd-name {
  font: var(--cw-display); color: var(--cw-ink); margin: 0 0 var(--cw-s2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sd-meta { display: flex; align-items: center; gap: var(--cw-s2); flex-wrap: wrap; }
.sd-sub { font: var(--cw-micro); color: var(--cw-text-soft); }
.sd-actions { display: flex; gap: var(--cw-s2); flex: none; }

.sd-tabs { margin-bottom: var(--cw-s6); }
.sd-body { min-height: 240px; }

.sd-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: var(--cw-s5); }
@media (max-width: 980px) { .sd-grid { grid-template-columns: 1fr; } }
.sd-col { min-width: 0; }

.sd-conf { display: flex; flex-direction: column; }
.sd-conf-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--cw-s3);
  padding: 9px 0; border-bottom: 1px solid var(--cw-surface-2); font: var(--cw-small);
}
.sd-conf-row:last-child { border-bottom: 0; }
.sd-conf-row > span { color: var(--cw-text-soft); }
.sd-conf-row > strong { color: var(--cw-ink); font-weight: 600; text-align: right; }
.sd-tick { color: var(--cw-ok); font-weight: 700; }
.sd-conf-foot { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: var(--cw-s3); }

.sd-bk-actions { display: flex; gap: var(--cw-s2); }
.sd-plan-now { display: flex; align-items: center; gap: var(--cw-s3); flex-wrap: wrap; }

.sd-danger { border-color: var(--cw-danger-border); }
.sd-danger-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--cw-s4); flex-wrap: wrap;
}
.sd-danger-row strong { color: var(--cw-ink); font: var(--cw-heading); }

/* Site rows become enterable (U3 entry point; U4 replaces them with cards) */
.site-row { cursor: pointer; }
.site-row:hover { background: var(--cw-bg); }

/* ══ Command palette (U8) ═══════════════════════════════════════════════ */

.cw-palette { position: fixed; inset: 0; z-index: 1400; }
.cw-pal-scrim {
  position: absolute; inset: 0; background: rgba(22, 22, 31, .45);
  animation: cw-fade-in var(--cw-t-micro) both;
}
.cw-pal-box {
  position: relative; margin: 12vh auto 0; width: min(560px, calc(100vw - 32px));
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); box-shadow: var(--cw-e2); overflow: hidden;
  animation: cw-pal-in var(--cw-t-std) both;
}
@keyframes cw-pal-in { from { opacity: 0; transform: translateY(-8px) scale(.99); } }
.cw-pal-input {
  width: 100%; box-sizing: border-box; border: 0; outline: none;
  background: transparent; color: var(--cw-ink);
  font: 450 16px/24px var(--cw-font); padding: var(--cw-s4) var(--cw-s5);
  border-bottom: 1px solid var(--cw-border);
}
.cw-pal-input::placeholder { color: var(--cw-text-faint); }
.cw-pal-list { list-style: none; margin: 0; padding: var(--cw-s2); max-height: 46vh; overflow-y: auto; }
.cw-pal-item {
  display: flex; align-items: center; gap: var(--cw-s3);
  padding: 10px var(--cw-s3); border-radius: var(--cw-r-sm); cursor: pointer;
}
.cw-pal-item.is-on { background: var(--cw-accent-subtle); }
.cw-pal-title { flex: 1; min-width: 0; font: var(--cw-body); color: var(--cw-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cw-pal-item.is-on .cw-pal-title { color: var(--cw-accent); font-weight: 600; }
.cw-pal-hint { font: var(--cw-micro); color: var(--cw-text-soft); flex: none; }
.cw-pal-empty { padding: var(--cw-s5); text-align: center; color: var(--cw-text-soft); font: var(--cw-small); }
.cw-pal-foot {
  display: flex; gap: var(--cw-s4); padding: var(--cw-s2) var(--cw-s5);
  border-top: 1px solid var(--cw-border); background: var(--cw-surface-2);
  font: var(--cw-micro); color: var(--cw-text-soft);
}
.cw-pal-foot kbd {
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: 4px; padding: 1px 5px; margin-right: 3px;
  font: 500 11px/16px var(--cw-font-mono); color: var(--cw-text);
}
@media (max-width: 768px) { .cw-pal-box { margin-top: 6vh; } }

/* ══ Mobile shell (U7 / §12) ════════════════════════════════════════════ */

.cw-bottomnav { display: none; }

@media (max-width: 768px) {
  /* Sidebar is a desktop affordance — the bottom bar replaces it. */
  #dash-sidebar { display: none !important; }
  .dash-main-area { margin-left: 0 !important; width: 100% !important; }
  body.has-bottomnav .dash-content { padding-bottom: 88px; }

  .cw-bottomnav {
    display: flex; align-items: center; justify-content: space-around;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
    height: 64px; padding-bottom: env(safe-area-inset-bottom, 0);
    background: var(--cw-surface); border-top: 1px solid var(--cw-border);
    box-shadow: 0 -1px 12px rgba(22, 22, 31, .06);
  }
  .cw-bn-item {
    position: relative; flex: 1;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    min-height: 48px;                      /* ≥44px touch target (audit fix) */
    background: none; border: 0; cursor: pointer; font-family: inherit;
    color: var(--cw-text-soft); font: var(--cw-micro);
    transition: color var(--cw-t-micro);
  }
  .cw-bn-item.is-on { color: var(--cw-accent); }
  .cw-bn-add {
    flex: none; width: 52px; height: 52px; margin-top: -18px;
    border-radius: 50%; border: 3px solid var(--cw-surface);
    background: var(--cw-accent); color: var(--cw-accent-ink);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; box-shadow: var(--cw-e1);
  }
  .cw-bn-badge {
    position: absolute; top: 4px; right: 50%; transform: translateX(16px);
    min-width: 8px; height: 8px; border-radius: 50%; background: var(--cw-danger);
    font-size: 0;
  }

  /* Header stays, compacted. */
  .cw-header { padding: 0 var(--cw-s4); gap: var(--cw-s2); }
  .cw-crumbs { font-size: 12px; }
  #cw-new-site { display: none; }         /* the ➕ in the bar owns this on mobile */

  /* Panels become full-screen sheets; dialogs sit near the bottom. */
  .cw-panel { width: 100vw !important; border-radius: 0; }
  .cw-panel.open { transform: translateY(0); }
  .notif-panel {
    position: fixed; top: auto; left: 0; right: 0; bottom: 0;
    width: 100vw; max-height: 82vh; border-radius: var(--cw-r-lg) var(--cw-r-lg) 0 0;
  }
  .cw-toasts { left: var(--cw-s4); right: var(--cw-s4); bottom: 76px; }
  .cw-toast { max-width: none; }

  /* Content breathing room on small screens. */
  .dash-content { padding-left: var(--cw-s4) !important; padding-right: var(--cw-s4) !important; }
  .ov-greeting, .sd-name, .pv-title { font-size: 22px; line-height: 28px; }
  .sd-head { flex-wrap: wrap; }
  .sd-actions { width: 100%; }
  .sd-actions .cw-btn { flex: 1; }
  .cw-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .cw-tabs::-webkit-scrollbar { display: none; }
  .sv-tools { width: 100%; }
  .sv-search { flex: 1; width: auto; }
}

/* Touch targets everywhere (audit fix — legacy kebab items were ~32px) */
@media (pointer: coarse) {
  .cw-menu [role="menuitem"] { padding: 12px var(--cw-s3); }
  .notif-item-dismiss, .bk-del, .cw-panel-close { padding: 10px; }
}

/* ══ Global a11y (audit fixes — apply platform-wide NOW) ════════════════ */

.cw-skip {
  position: absolute; left: -9999px; top: 0; z-index: 2000;
  background: var(--cw-accent); color: var(--cw-accent-ink);
  padding: 10px var(--cw-s4); border-radius: 0 0 var(--cw-r-md) 0;
  font: 600 14px/1 var(--cw-font); text-decoration: none;
}
.cw-skip:focus { left: 0; }

:focus-visible {
  outline: 2px solid var(--cw-accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Legacy contrast overrides — retire the failing #9c9cb5 tier everywhere
   until each surface is rebuilt on tokens (U2–U7). */
.notif-item-meta, .notif-prefs-note, .notif-pref-row em, .notif-empty,
.bk-sub, .bk-kind, .bk-empty, .bk-toolbar-note, .bk-decrypt-note,
.cl-domain, .cl-checking, .cl-note, .cl-plan-row span,
.mx-kpi-l, .mx-chart-label, .mx-empty, .mx-fact > span,
.tl-meta, .tl-time,
.site-meta, .section-desc, .ns-note, .upgrade-note {
  color: var(--cw-text-soft) !important;
}

/* ══ Plan (U9) — a control panel, not a pricing page ═══════════════════════
   The customer already bought. So the plan they're ON is the hero, their real
   usage lives inside it, and the other tiers are a quiet rail underneath.
   No gradients, no glass, no oversized shadows: weight comes from scale,
   spacing and restraint. Section rhythm 32px, card padding 24px. */

/* CAREFUL: the `font:` shorthand RESETS font-variant-numeric. Any rule below
   that sets `font:` on an element also carrying .cw-num wipes this out, so
   those rules restate tabular-nums themselves. Figures that jitter as they
   update are the fastest way to make a dashboard feel cheap. */
.cw-num { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }

.pl-head { margin-bottom: var(--cw-s6); }
.pl-head-sub {
  font: var(--cw-body); color: var(--cw-text-soft);
  margin: var(--cw-s2) 0 0; max-width: 62ch;
}
.pl-section-title {
  font: var(--cw-title); color: var(--cw-ink);
  margin: var(--cw-s7) 0 var(--cw-s4);
}
.pl-section-title.is-hidden, .pl-up.is-hidden { display: none; }

/* ── Billing interval selector ──────────────────────────────
   Sits on the section heading row. `wrap` + `auto` margin so a long heading
   and the control never collide on narrow viewports — the control drops to
   its own line instead of overflowing. */
.pl-head-row {
  display: flex; align-items: center; gap: var(--cw-s4); flex-wrap: wrap;
}
.pl-head-row .pl-section-title { margin-right: auto; }
/* The title carries the row's top margin; the control aligns to its baseline
   box rather than adding a second, competing margin. */
.pl-interval {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--cw-surface-2);
  border: 1px solid var(--cw-border);
  border-radius: 10px;
  margin: var(--cw-s7) 0 var(--cw-s4);
}
.pl-interval-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border: 0; border-radius: 7px;
  background: transparent; color: var(--cw-text-soft);
  font: 600 13px/1 var(--cw-font); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.pl-interval-opt:hover { color: var(--cw-ink); }
.pl-interval-opt.is-active {
  background: var(--cw-surface); color: var(--cw-ink);
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
}
.pl-interval-save {
  font: 700 11px/1 var(--cw-font);
  padding: 3px 6px; border-radius: 5px;
  background: var(--cw-accent); color: var(--cw-accent-ink);
}
.pl-interval-save:empty { display: none; }

/* Same control inside the create-site modal: centred above the plan cards,
   no heading to sit beside. Reuses .pl-interval-opt so the two toggles are
   visually identical — they are the same control in two places. */
.cs-interval {
  display: inline-flex; gap: 2px; padding: 3px;
  margin: 0 auto var(--cw-s4);
  background: var(--cw-surface-2);
  border: 1px solid var(--cw-border);
  border-radius: 10px;
}
.cs-interval.hidden { display: none; }
/* The plan step is a column flex; this keeps the control centred in it. */
#cs-step-plan .cs-interval { align-self: center; }

/* ── "Need more resources?" on the Dedicated card ───────────
   Deliberately quiet: a secondary block inside the card, not an alert. It sits
   below the CTA and reads as part of the plan, not as an error state. */
.pl-up-more {
  margin-top: var(--cw-s4);
  padding-top: var(--cw-s4);
  border-top: 1px solid var(--cw-accent-border);
}
.pl-up-more-title { font: 600 13px/1.4 var(--cw-font); color: var(--cw-ink); }
.pl-up-more-text {
  font: var(--cw-micro); color: var(--cw-text-soft);
  margin: 4px 0 var(--cw-s3);
}
.pl-up-more-cta {
  display: inline-flex; align-items: center;
  padding: 7px 14px; border-radius: 8px; cursor: pointer;
  background: transparent; color: var(--cw-accent);
  border: 1px solid var(--cw-accent-border);
  font: 600 13px/1 var(--cw-font);
  transition: background .15s ease, border-color .15s ease;
}
.pl-up-more-cta:hover { background: var(--cw-surface); border-color: var(--cw-accent); }
.pl-up-more-cta:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }

/* ── Hero: the plan you're on ───────────────────────────── */
.pl-hero {
  background: var(--cw-surface);
  border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg);
  padding: var(--cw-s7);
  box-shadow: var(--cw-e1);
}
/* Dedicated earns a mark of distinction — one accent rule, nothing more. */
.pl-hero-dedicated {
  border-color: var(--cw-accent-border);
  box-shadow: inset 3px 0 0 var(--cw-accent), var(--cw-e1);
}

.pl-hero-main {
  display: grid; grid-template-columns: minmax(200px, 260px) 1fr;
  gap: var(--cw-s7); align-items: start;
}
.pl-eyebrow {
  font: var(--cw-micro); letter-spacing: .08em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s2);
}
.pl-hero-name {
  font: 700 34px/40px var(--cw-font); color: var(--cw-ink);
  letter-spacing: -.02em; margin-bottom: var(--cw-s2);
}
.pl-hero-price {
  font: 650 26px/32px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--cw-s3);
}
.pl-hero-per { font: var(--cw-small); color: var(--cw-text-soft); margin-left: 2px; }

/* Stats rail — the usage context that makes an upgrade a decision rather than
   an advert. */
.pl-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: var(--cw-s6) var(--cw-s5);
}
.pl-stat-label {
  font: var(--cw-micro); letter-spacing: .04em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s2);
}
.pl-stat-value {
  font: 650 20px/26px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums;
}
.pl-stat-of  { font: 450 14px/20px var(--cw-font); color: var(--cw-text-soft); }
.pl-stat-sub { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: var(--cw-s2); }

.pl-meter {
  height: 5px; border-radius: var(--cw-r-full); background: var(--cw-surface-2);
  overflow: hidden; margin-bottom: var(--cw-s1);
}
.pl-meter > i { display: block; height: 100%; background: var(--cw-ok); border-radius: inherit; }
.pl-meter-warn   > i { background: var(--cw-warn); }
.pl-meter-danger > i { background: var(--cw-danger); }
.pl-meter-pct { font: var(--cw-micro); color: var(--cw-text-soft); }

/* Infrastructure strip — quiet facts that say "this is looked after". */
.pl-infra {
  display: flex; flex-wrap: wrap; gap: var(--cw-s3) var(--cw-s7);
  margin-top: var(--cw-s7); padding-top: var(--cw-s5);
  border-top: 1px solid var(--cw-border);
}
.pl-infra-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pl-infra-k { font: var(--cw-micro); color: var(--cw-text-faint); }
.pl-infra-v {
  font: 500 13px/20px var(--cw-font); color: var(--cw-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 30ch;
}

.pl-hero-actions {
  display: flex; flex-wrap: wrap; gap: var(--cw-s3);
  margin-top: var(--cw-s6);
}

/* ── Upgrade rail ───────────────────────────────────────── */
/* Capped tracks, left-aligned — NOT `1fr`. With a tier hidden (you're on it),
   1fr stretches the survivors to fill the row and you're back to the equal-
   width pricing grid this redesign exists to kill. The upgrades are secondary
   to the hero and should read that way at every fleet size. */
.pl-upgrades {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 340px));
  justify-content: start; gap: var(--cw-s5); align-items: stretch;
}
.pl-up {
  display: flex; flex-direction: column;
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); padding: var(--cw-s6);
  transition: border-color var(--cw-t-micro), box-shadow var(--cw-t-micro);
}
.pl-up:hover { border-color: var(--cw-border-strong); box-shadow: var(--cw-e1); }
.pl-up-featured { border-color: var(--cw-accent-border); background: var(--cw-accent-subtle); }
.pl-up-featured:hover { border-color: var(--cw-accent); }
.pl-up-eyebrow {
  font: var(--cw-micro); letter-spacing: .06em; text-transform: uppercase;
  color: var(--cw-accent); margin-bottom: var(--cw-s3);
}
.pl-up-top { margin-bottom: var(--cw-s4); }
.pl-up-name { font: var(--cw-heading); color: var(--cw-ink); margin-bottom: var(--cw-s1); }
.pl-up-price { display: flex; align-items: baseline; gap: 3px; }
.pl-up-amount {
  font: 700 26px/32px var(--cw-font); color: var(--cw-ink); letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.pl-up-per { font: var(--cw-small); color: var(--cw-text-soft); }

.pl-up-feat { list-style: none; margin: 0 0 var(--cw-s5); padding: 0; flex: 1; }
.pl-up-feat li {
  position: relative; padding-left: 22px; margin-bottom: var(--cw-s2);
  font: var(--cw-small); color: var(--cw-text);
}
.pl-up-feat li::before {
  content: '✓'; position: absolute; left: 0; top: 0;
  color: var(--cw-ok); font-weight: 700; font-size: 12px; line-height: 20px;
}
.pl-up-status { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: var(--cw-s3); }
.pl-up-status:empty { display: none; }

/* The purchase buttons keep their legacy ids and classes — dashboard.js owns
   their label and disabled state. Only their appearance is restated here. */
.pl-up .btn-plan-sm {
  width: 100%; border-radius: var(--cw-r-md); border: 1px solid var(--cw-border-strong);
  background: var(--cw-surface); color: var(--cw-ink);
  font: 600 14px/20px var(--cw-font); padding: 10px var(--cw-s4); cursor: pointer;
  transition: background var(--cw-t-micro), border-color var(--cw-t-micro);
}
.pl-up .btn-plan-sm:hover:not(:disabled) { background: var(--cw-surface-2); border-color: var(--cw-ink); }
.pl-up-featured .btn-plan-sm {
  background: var(--cw-accent); border-color: var(--cw-accent); color: var(--cw-accent-ink);
}
.pl-up-featured .btn-plan-sm:hover:not(:disabled) {
  background: var(--cw-accent-hover); border-color: var(--cw-accent-hover);
}
.pl-up .btn-plan-sm:disabled { opacity: .55; cursor: default; }

/* ── Comparison ─────────────────────────────────────────── */
.pl-compare-card { padding: 0; overflow: hidden; }
.pl-compare-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.pl-table { width: 100%; border-collapse: collapse; min-width: 560px; }
.pl-table th, .pl-table td {
  padding: var(--cw-s4) var(--cw-s5); text-align: left;
  border-bottom: 1px solid var(--cw-border);
}
.pl-table thead th {
  font: var(--cw-micro); letter-spacing: .04em; text-transform: uppercase;
  color: var(--cw-text-faint); white-space: nowrap; background: var(--cw-surface-2);
}
.pl-table tbody th { font: 500 13px/20px var(--cw-font); color: var(--cw-text); }
.pl-table tbody td { font: var(--cw-small); color: var(--cw-text); }
.pl-table tbody tr:last-child th, .pl-table tbody tr:last-child td { border-bottom: 0; }
.pl-table .is-current { background: var(--cw-accent-subtle); }
.pl-table thead .is-current { color: var(--cw-accent); }
.pl-th-tag {
  display: block; font: var(--cw-micro); text-transform: none; letter-spacing: 0;
  color: var(--cw-accent); opacity: .8;
}
.pl-yes { color: var(--cw-ok); font-weight: 700; }
.pl-no  { color: var(--cw-text-faint); }

/* ── Site picker: segmented chips (U9), shared with the Domain tab ─────── */
.site-picker { display: flex; flex-wrap: wrap; gap: var(--cw-s2); margin-bottom: var(--cw-s6); }
.site-picker .site-picker-pill {
  display: inline-flex; align-items: center; gap: var(--cw-s2);
  padding: 6px 12px 6px 6px; border-radius: var(--cw-r-full);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  font: 500 13px/20px var(--cw-font); color: var(--cw-text);
  cursor: pointer; max-width: 100%;
  transition: border-color var(--cw-t-micro), box-shadow var(--cw-t-micro), background var(--cw-t-micro);
}
.site-picker .site-picker-pill:hover { border-color: var(--cw-border-strong); box-shadow: var(--cw-e1); }
.site-picker .site-picker-pill.active {
  border-color: var(--cw-accent); background: var(--cw-accent-subtle); color: var(--cw-ink);
}
.site-picker .site-picker-pill:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }
.site-picker .spp-mark {
  width: 22px; height: 22px; border-radius: var(--cw-r-full); font-size: 9px; flex: none;
}
.site-picker .spp-mark .sc-fav-img { width: 22px; height: 22px; }
.spp-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spp-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--cw-text-faint); }
.spp-dot-ok     { background: var(--cw-ok); }
.spp-dot-warn   { background: var(--cw-warn); }
.spp-dot-danger { background: var(--cw-danger); }
.spp-dot-info   { background: var(--cw-info); }
.site-picker .site-picker-pill.is-removed { opacity: .6; }

/* ── Responsive ─────────────────────────────────────────── */
@media (max-width: 860px) {
  .pl-hero { padding: var(--cw-s6); }
  .pl-hero-main { grid-template-columns: 1fr; gap: var(--cw-s6); }
  .pl-hero-name { font: 700 28px/34px var(--cw-font); }
  .pl-infra { gap: var(--cw-s4); }
  .pl-hero-actions .cw-btn { flex: 1 1 auto; }
}

/* ══ Domain (U10) — connection as an infrastructure workflow ═══════════════
   Replaces a title + a sentence + one alert box. Density comes from putting
   real facts on the page, not from shrinking the spacing. */

.dv-head { margin-bottom: var(--cw-s6); }
.dv-head-sub {
  font: var(--cw-body); color: var(--cw-text-soft);
  margin: var(--cw-s2) 0 0; max-width: 66ch;
}
.dv-section-title {
  font: var(--cw-title); color: var(--cw-ink);
  margin: var(--cw-s7) 0 var(--cw-s4);
}
.dv-eyebrow {
  font: var(--cw-micro); letter-spacing: .08em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s2);
}

/* ── 1. Platform domain ─────────────────────────────────── */
.dv-platform { padding: var(--cw-s6); }
.dv-platform-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--cw-s4); flex-wrap: wrap;
}
.dv-platform-id { min-width: 0; }
.dv-platform-url {
  font: 650 22px/28px var(--cw-font); color: var(--cw-ink);
  text-decoration: none; word-break: break-all;
}
.dv-platform-url:hover { color: var(--cw-accent); text-decoration: underline; }
.dv-platform-note {
  font: var(--cw-small); color: var(--cw-text-soft);
  margin-top: var(--cw-s2); max-width: 58ch;
}
.dv-facts {
  display: flex; flex-wrap: wrap; gap: var(--cw-s3) var(--cw-s7);
  margin-top: var(--cw-s5); padding-top: var(--cw-s5);
  border-top: 1px solid var(--cw-border);
}
.dv-fact { display: flex; flex-direction: column; gap: 2px; }
.dv-fact-k { font: var(--cw-micro); color: var(--cw-text-faint); }
.dv-fact-v { font: 500 13px/20px var(--cw-font); color: var(--cw-text); }
.dv-platform-actions { display: flex; flex-wrap: wrap; gap: var(--cw-s3); margin-top: var(--cw-s5); }

/* ── 2. Custom domain: upsell, connected, connect form ──── */
.dv-upsell {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--cw-s7); padding: var(--cw-s6);
  border-color: var(--cw-accent-border); background: var(--cw-accent-subtle);
}
.dv-upsell-main { min-width: 0; }
.dv-upsell-title { font: var(--cw-title); color: var(--cw-ink); margin: 0 0 var(--cw-s2); }
.dv-upsell-text { font: var(--cw-small); color: var(--cw-text-soft); margin: 0 0 var(--cw-s4); max-width: 60ch; }
.dv-benefits { list-style: none; margin: 0; padding: 0; }
.dv-benefits li {
  position: relative; padding-left: 24px; margin-bottom: var(--cw-s2);
  font: var(--cw-small); color: var(--cw-text);
}
.dv-benefits li::before {
  content: '✓'; position: absolute; left: 0; top: 0;
  color: var(--cw-accent); font-weight: 700; font-size: 12px; line-height: 20px;
}
.dv-benefits strong { color: var(--cw-ink); font-weight: 600; }
.dv-upsell-cta { flex: none; align-self: center; }

.dv-connected { padding: var(--cw-s6); }
.dv-domain-row { display: flex; align-items: center; gap: var(--cw-s4); flex-wrap: wrap; }
.dv-domain-id { flex: 1; min-width: 0; }
.dv-domain {
  font: 650 20px/26px var(--cw-font); color: var(--cw-ink);
  word-break: break-all; display: block;
}

/* The status text is set by dashboard.js (textContent + .ok/.pending/.error),
   so it stays a <span> — restated here as a badge to match every other status
   in the console. Uses console tokens, not the legacy --success/--warn pair. */
.dv-connected .domain-status {
  display: inline-flex; align-items: center; gap: var(--cw-s2);
  padding: 3px 10px; border-radius: var(--cw-r-full);
  border: 1px solid var(--cw-border); background: var(--cw-surface-2);
  font: var(--cw-micro); color: var(--cw-text-soft); white-space: nowrap;
}
.dv-connected .domain-status.ok {
  background: var(--cw-ok-bg); border-color: var(--cw-ok-border); color: var(--cw-ok);
}
.dv-connected .domain-status.pending {
  background: var(--cw-warn-bg); border-color: var(--cw-warn-border); color: var(--cw-warn);
}
.dv-connected .domain-status.error {
  background: var(--cw-danger-bg); border-color: var(--cw-danger-border); color: var(--cw-danger);
}

.dv-connect { padding: var(--cw-s6); }
.dv-label { display: block; font: var(--cw-micro); color: var(--cw-text-soft); margin-bottom: var(--cw-s2); }
.dv-form-row { display: flex; gap: var(--cw-s3); flex-wrap: wrap; }
.dv-input {
  flex: 1 1 260px; min-width: 0;
  padding: 10px var(--cw-s4); border-radius: var(--cw-r-md);
  border: 1px solid var(--cw-border-strong); background: var(--cw-surface);
  color: var(--cw-ink); font: var(--cw-body);
}
.dv-input::placeholder { color: var(--cw-text-faint); }
.dv-input:focus { outline: 2px solid var(--cw-accent); outline-offset: 1px; border-color: var(--cw-accent); }
.dv-form-hint { font: var(--cw-micro); color: var(--cw-text-soft); margin: var(--cw-s3) 0 0; }
.dv-form-hint code {
  font-family: var(--cw-font-mono); font-size: 11px;
  background: var(--cw-surface-2); padding: 1px 4px; border-radius: var(--cw-r-sm);
}

/* Nameservers: the one thing the customer must copy exactly, so it reads as
   data — monospaced, in a well, selectable. Scoped to #ns-box so the
   create-site flow's own list is untouched. */
#ns-box { margin-top: var(--cw-s5); padding: var(--cw-s6); background: var(--cw-surface); border: 1px solid var(--cw-border); border-radius: var(--cw-r-lg); }
#ns-box .ns-label { font: var(--cw-heading); color: var(--cw-ink); margin: 0 0 var(--cw-s4); }
#ns-box .ns-list { display: flex; flex-direction: column; gap: var(--cw-s2); }
#ns-box .ns-entry {
  font-family: var(--cw-font-mono); font-size: 13px; line-height: 20px;
  color: var(--cw-ink); background: var(--cw-surface-2);
  border: 1px solid var(--cw-border); border-radius: var(--cw-r-md);
  padding: 10px var(--cw-s4); user-select: all; word-break: break-all;
}
#ns-box .ns-note { font: var(--cw-small); color: var(--cw-text-soft); margin: var(--cw-s4) 0 0; }

/* ── 3. Connection workflow ─────────────────────────────── */
.dv-steps {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--cw-s4);
  counter-reset: dv;
}
.dv-step {
  position: relative; display: flex; gap: var(--cw-s3);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); padding: var(--cw-s5);
}
/* The connector is what turns four cards into one pipeline. */
.dv-step:not(:last-child)::after {
  content: ''; position: absolute; top: 50%; right: calc(var(--cw-s4) * -1);
  width: var(--cw-s4); height: 1px; background: var(--cw-border-strong);
}
.dv-step-mark {
  flex: none; width: 26px; height: 26px; border-radius: var(--cw-r-full);
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 12px/1 var(--cw-font);
  background: var(--cw-surface-2); color: var(--cw-text-soft);
  border: 1px solid var(--cw-border);
}
.dv-step-title { font: 600 13px/20px var(--cw-font); color: var(--cw-ink); }
.dv-step-text { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: 2px; }

.dv-step.is-done .dv-step-mark {
  background: var(--cw-ok-bg); color: var(--cw-ok); border-color: var(--cw-ok-border);
}
.dv-step.is-now { border-color: var(--cw-accent); box-shadow: inset 2px 0 0 var(--cw-accent); }
.dv-step.is-now .dv-step-mark {
  background: var(--cw-accent); color: var(--cw-accent-ink); border-color: var(--cw-accent);
}

/* Locked: shown, not hidden. Seeing the machinery you'd be buying argues
   better than a padlock — but it must never look interactive. */
.dv-steps.is-locked { opacity: .55; filter: grayscale(1); pointer-events: none; }
.dv-steps-note { font: var(--cw-small); color: var(--cw-text-soft); margin: var(--cw-s4) 0 0; }

/* ── Responsive ─────────────────────────────────────────── */
@media (max-width: 1000px) {
  .dv-steps { grid-template-columns: repeat(2, 1fr); }
  /* The horizontal connector is a lie on a wrapped grid. */
  .dv-step:not(:last-child)::after { display: none; }
}
@media (max-width: 860px) {
  .dv-platform, .dv-upsell, .dv-connected, .dv-connect, #ns-box { padding: var(--cw-s5); }
  .dv-upsell { flex-direction: column; gap: var(--cw-s5); }
  .dv-upsell-cta { align-self: stretch; width: 100%; }
  .dv-platform-url { font: 650 18px/24px var(--cw-font); }
  .dv-steps { grid-template-columns: 1fr; }
  .dv-platform-actions .cw-btn { flex: 1 1 auto; }
}

/* ══ Billing (U11) — adaptive: free accounts never see billing UI ══════════
   Money pages earn trust through precision, not decoration. Amounts are
   tabular and right-aligned wherever they're compared; status is a badge, not
   a coloured word; nothing is styled to look more important than the number. */

.bl-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--cw-s5); flex-wrap: wrap; margin-bottom: var(--cw-s6);
}
.bl-head-main { min-width: 0; }
.bl-head-sub {
  font: var(--cw-body); color: var(--cw-text-soft);
  margin: var(--cw-s2) 0 0; max-width: 60ch;
}
.bl-section-title {
  font: var(--cw-title); color: var(--cw-ink);
  margin: var(--cw-s7) 0 var(--cw-s4);
}
.bl-eyebrow {
  font: var(--cw-micro); letter-spacing: .08em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s2);
}
.bl-loading { font: var(--cw-small); color: var(--cw-text-soft); padding: var(--cw-s6) 0; }

.bl-error { padding: var(--cw-s6); border-color: var(--cw-danger-border); }
.bl-error-title { font: var(--cw-heading); color: var(--cw-ink); margin-bottom: var(--cw-s2); }
.bl-error-text { font: var(--cw-small); color: var(--cw-text-soft); margin: 0 0 var(--cw-s4); }

/* ── Free state ─────────────────────────────────────────── */
.bl-free { padding: var(--cw-s7); }
.bl-free-main { max-width: 62ch; }
.bl-free-title { font: var(--cw-display); color: var(--cw-ink); margin: 0 0 var(--cw-s3); }
.bl-free-text { font: var(--cw-body); color: var(--cw-text-soft); margin: 0 0 var(--cw-s5); }
.bl-free-list { list-style: none; margin: 0 0 var(--cw-s6); padding: 0; }
.bl-free-list li {
  position: relative; padding-left: 24px; margin-bottom: var(--cw-s2);
  font: var(--cw-small); color: var(--cw-text);
}
.bl-free-list li::before {
  content: '·'; position: absolute; left: 8px; top: 0;
  color: var(--cw-text-faint); font-weight: 700; line-height: 20px;
}
.bl-free-list strong { color: var(--cw-ink); font-weight: 600; }
.bl-free-note { font: var(--cw-small); color: var(--cw-text-soft); margin: var(--cw-s4) 0 0; }

/* ── Summary cards ──────────────────────────────────────── */
.bl-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--cw-s4);
}
.bl-stat { padding: var(--cw-s5); }
.bl-stat-label {
  font: var(--cw-micro); letter-spacing: .04em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s2);
}
.bl-stat-value {
  font: 650 24px/30px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums;
}
.bl-stat-sub { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: var(--cw-s2); }
.bl-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: var(--cw-micro); color: var(--cw-accent); text-decoration: underline;
}
.bl-link:hover { color: var(--cw-accent-hover); }

/* ── Subscription cards ─────────────────────────────────── */
.bl-subs {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--cw-s4);
}
.bl-sub { padding: var(--cw-s5); display: flex; flex-direction: column; }
.bl-sub-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--cw-s3); margin-bottom: var(--cw-s4);
}
.bl-sub-id { min-width: 0; }
.bl-sub-plan { font: var(--cw-heading); color: var(--cw-ink); }
.bl-sub-domain {
  font: var(--cw-small); color: var(--cw-text-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bl-sub-facts {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--cw-s4); flex-wrap: wrap; flex: 1;
  padding-bottom: var(--cw-s4);
}
.bl-sub-amount {
  font: 650 22px/28px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums;
}
.bl-sub-per { font: var(--cw-small); color: var(--cw-text-soft); margin-left: 2px; }
.bl-sub-when { text-align: right; }
.bl-sub-when-k { display: block; font: var(--cw-micro); color: var(--cw-text-faint); }
.bl-sub-when-v { font: 500 13px/20px var(--cw-font); color: var(--cw-text); }
.bl-sub-actions {
  display: flex; gap: var(--cw-s2); flex-wrap: wrap;
  padding-top: var(--cw-s4); border-top: 1px solid var(--cw-border);
}
.bl-cancel { color: var(--cw-text-soft); }
.bl-cancel:hover:not(:disabled) { color: var(--cw-danger); }

/* ── Invoices ───────────────────────────────────────────── */
.bl-inv-card { padding: 0; overflow: hidden; }
.bl-inv-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.bl-inv-table { width: 100%; border-collapse: collapse; min-width: 480px; }
.bl-inv-table th, .bl-inv-table td {
  padding: var(--cw-s4) var(--cw-s5); text-align: left;
  border-bottom: 1px solid var(--cw-border); vertical-align: middle;
}
.bl-inv-table thead th {
  font: var(--cw-micro); letter-spacing: .04em; text-transform: uppercase;
  color: var(--cw-text-faint); background: var(--cw-surface-2); white-space: nowrap;
}
.bl-inv-table tbody tr:last-child td { border-bottom: 0; }
.bl-inv-title { font: 500 14px/20px var(--cw-font); color: var(--cw-ink); }
.bl-inv-date { font: var(--cw-micro); color: var(--cw-text-soft); margin-top: 2px; }
/* The number people scan for: right-aligned so digits line up column-wise.
   MUST out-specify `.bl-inv-table th, .bl-inv-table td { text-align: left }`
   above — a bare `.bl-inv-amount` loses to it and the column silently goes
   back to ragged-left, which is the whole reason to use tabular figures. */
.bl-inv-table th.bl-inv-amount,
.bl-inv-table td.bl-inv-amount {
  text-align: right; white-space: nowrap;
}
.bl-inv-table td.bl-inv-amount {
  font: 600 14px/20px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums;
}
.bl-inv-table th.bl-inv-link, .bl-inv-table td.bl-inv-link { text-align: right; }
.bl-inv-status {
  display: inline-flex; align-items: center; padding: 2px 9px;
  border-radius: var(--cw-r-full); border: 1px solid var(--cw-border);
  font: var(--cw-micro); background: var(--cw-surface-2); color: var(--cw-text-soft);
  white-space: nowrap;
}
.bl-inv-ok     { background: var(--cw-ok-bg);     border-color: var(--cw-ok-border);     color: var(--cw-ok); }
.bl-inv-warn   { background: var(--cw-warn-bg);   border-color: var(--cw-warn-border);   color: var(--cw-warn); }
.bl-inv-danger { background: var(--cw-danger-bg); border-color: var(--cw-danger-border); color: var(--cw-danger); }
.bl-inv-link { white-space: nowrap; }
.bl-inv-link a { font: 500 13px/20px var(--cw-font); color: var(--cw-accent); text-decoration: none; }
.bl-inv-link a:hover { text-decoration: underline; }
.bl-inv-none { color: var(--cw-text-faint); }

@media (max-width: 860px) {
  .bl-head { flex-direction: column; align-items: stretch; }
  .bl-head .cw-btn { width: 100%; }
  .bl-free { padding: var(--cw-s5); }
  .bl-free-title { font: 700 24px/30px var(--cw-font); }
  .bl-subs { grid-template-columns: 1fr; }
  .bl-sub-actions .cw-btn { flex: 1 1 auto; }
}

/* ══ Launch experience (L1–L4) ═════════════════════════════════════════════
   Creating a site should feel like a product, not an admin form. Weight comes
   from scale and restraint — no gradients, no glass. Motion is short and
   purposeful, and every animation here is inside a transition the user
   initiated, so prefers-reduced-motion (tokens.css) neutralises all of it. */

/* ── L4: compact hero ───────────────────────────────────── */
.ls-hero {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--cw-s6); flex-wrap: wrap; margin-bottom: var(--cw-s6);
}
.ls-hero-copy { min-width: 0; }
.ls-hero-title {
  font: 700 30px/36px var(--cw-font); color: var(--cw-ink);
  letter-spacing: -.02em; margin: 0;
}
.ls-hero-sub { font: var(--cw-body); color: var(--cw-text-soft); margin: var(--cw-s2) 0 0; }
.ls-hero-actions { display: flex; gap: var(--cw-s3); flex-wrap: wrap; }

.ls-start {
  display: flex; align-items: center; gap: var(--cw-s3); text-align: left;
  min-width: 260px; padding: var(--cw-s4) var(--cw-s5);
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg); cursor: pointer;
  transition: transform var(--cw-t-micro), box-shadow var(--cw-t-micro), border-color var(--cw-t-micro);
}
.ls-start:hover { transform: translateY(-2px); box-shadow: var(--cw-e2); border-color: var(--cw-accent); }
.ls-start:active { transform: translateY(0); }
.ls-start:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }
.ls-start-icon {
  width: 36px; height: 36px; border-radius: var(--cw-r-md); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--cw-accent-subtle); color: var(--cw-accent);
  transition: background var(--cw-t-micro), color var(--cw-t-micro);
}
.ls-start:hover .ls-start-icon { background: var(--cw-accent); color: var(--cw-accent-ink); }
.ls-start-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ls-start-title { font: 600 14px/20px var(--cw-font); color: var(--cw-ink); }
.ls-start-desc { font: var(--cw-micro); color: var(--cw-text-soft); }

.ls-library-title { font: var(--cw-title); color: var(--cw-ink); margin: 0 0 var(--cw-s1); }
.ls-library-sub { font: var(--cw-small); color: var(--cw-text-soft); margin: 0 0 var(--cw-s5); }

/* Column count follows the CONTAINER, not the viewport. dashboard.css keyed
   its breakpoints off viewport width (4 columns above 1600px), but the grid
   never gets the viewport — the sidebar and page padding take ~300px first.
   A 1920px laptop therefore rendered 4 columns into ~1150px of space, giving
   cards too narrow to hold their own hover buttons (see .ls-library below).
   auto-fill + a real minimum can't drift out of sync with the layout. */
.ls-library .sites-templates-grid {
  /* min(330px, 100%) — NOT a bare 330px. A bare minimum is a floor the track
     cannot go below, so on a 375px phone the card renders 330px wide inside a
     ~327px column and pushes the whole page sideways. min() lets the track
     collapse to the container when the container is the smaller of the two. */
  grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr));
  gap: var(--cw-s5);
}

/* The hover actions overflowed both edges of a narrow card — two pill buttons
   with `white-space: nowrap` and 22px of padding each simply don't fit, and
   flex let them spill rather than shrink. That produced the "one button off
   each edge with a gap in the middle" look. Wrapping + inset padding means
   they sit side by side when there's room and stack when there isn't. */
.ls-library .cwp-templates-explore-hover-overlay {
  flex-wrap: wrap; padding: 0 var(--cw-s4); align-content: center;
}
.ls-library .cwp-templates-explore-preview-btn,
.ls-library .cwp-templates-explore-create-btn {
  padding: 0 18px; max-width: 100%; height: 40px; font-size: 14px;
}

/* ── L4: category chips ─────────────────────────────────── */
/* WRAP on anything desktop-sized. A single scrolling line hid the 11th
   category off the right edge on a laptop with no visible affordance that it
   was there — horizontal scroll is discoverable on touch, invisible on a
   trackpad. Only the mobile rule below opts into scrolling. */
.ls-chips {
  display: flex; gap: var(--cw-s2); flex-wrap: wrap;
  margin-bottom: var(--cw-s5);
  /* The :hover lift is 1px. `overflow-x: auto` forces overflow-y to compute to
     auto too, so without room above, the lifted chip's top border is sliced
     off by the scroll container. This padding IS the fix — don't remove it. */
  padding: 2px 0 var(--cw-s2);
}
.ls-chip {
  flex: none; padding: 7px 14px; border-radius: var(--cw-r-full);
  border: 1px solid var(--cw-border); background: var(--cw-surface);
  font: 500 13px/18px var(--cw-font); color: var(--cw-text); cursor: pointer;
  white-space: nowrap;
  transition: background var(--cw-t-micro), color var(--cw-t-micro),
              border-color var(--cw-t-micro), transform var(--cw-t-micro);
}
.ls-chip:hover { border-color: var(--cw-accent); color: var(--cw-accent); transform: translateY(-1px); }
.ls-chip:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }
.ls-chip.is-active {
  background: var(--cw-accent); border-color: var(--cw-accent);
  color: var(--cw-accent-ink); transform: none;
}
.ls-chip.is-active:hover { background: var(--cw-accent-hover); color: var(--cw-accent-ink); }

/* ── L1: site name + address ────────────────────────────── */
.ls-field-label {
  display: block; font: var(--cw-micro); color: var(--cw-text-soft);
  margin-bottom: var(--cw-s2);
}
.ls-addr {
  margin-top: var(--cw-s4); padding: var(--cw-s4);
  background: var(--cw-surface-2); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-md);
}
.ls-addr-label { font: var(--cw-micro); color: var(--cw-text-faint); margin-bottom: 2px; }
.ls-addr-value {
  font-family: var(--cw-font-mono); font-size: 15px; line-height: 24px;
  color: var(--cw-ink); word-break: break-all;
}
.ls-addr-value .tpl-sdpre-suffix { color: var(--cw-text-soft); }

.ls-status {
  display: flex; align-items: baseline; gap: var(--cw-s2); flex-wrap: wrap;
  margin-top: var(--cw-s3); min-height: 20px;
}
.ls-status-main { font: 600 13px/20px var(--cw-font); }
.ls-status-detail { font: var(--cw-micro); color: var(--cw-text-soft); }
.ls-status.available .ls-status-main { color: var(--cw-ok); }
.ls-status.taken     .ls-status-main { color: var(--cw-danger); }
.ls-status.checking  .ls-status-main { color: var(--cw-text-soft); }
.ls-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; font-size: 11px; font-weight: 700;
  align-self: center;
}
.ls-ic-ok { background: var(--cw-ok-bg); color: var(--cw-ok); }
.ls-ic-no { background: var(--cw-danger-bg); color: var(--cw-danger); }
.ls-spin {
  width: 14px; height: 14px; border-radius: 50%; align-self: center;
  border: 2px solid var(--cw-border-strong); border-top-color: var(--cw-accent);
  animation: ls-spin .7s linear infinite;
}
@keyframes ls-spin { to { transform: rotate(360deg); } }
.ls-continue:disabled { opacity: .5; cursor: not-allowed; }

/* ── L2: plan cards ─────────────────────────────────────── */
/* Two columns inside a 560px modal, not four cramped ones. Four cards at
   ~120px each were unreadable AND made the step so tall that the Continue
   button fell below the modal's scroll line.
   With three tiers the last one would orphan into a half-empty row, so it
   spans instead — the leftover gap read as a missing fourth plan. */
.ls-plans {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--cw-s3); align-items: stretch;
}
.ls-plans > .ls-plan:last-child:nth-child(odd) { grid-column: 1 / -1; }
/* Spanning gives the row real width, so its features read across rather than
   stacking into a narrow column. */
.ls-plans > .ls-plan:last-child:nth-child(odd) .ls-plan-feats {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px var(--cw-s4);
}
.ls-plan {
  position: relative; display: flex; flex-direction: column; gap: var(--cw-s2);
  text-align: left; padding: var(--cw-s4); cursor: pointer;
  background: var(--cw-surface); border: 1px solid var(--cw-border);
  border-radius: var(--cw-r-lg);
  transition: transform var(--cw-t-micro), box-shadow var(--cw-t-micro), border-color var(--cw-t-micro);
}
.ls-plan:hover:not(:disabled) { transform: translateY(-2px); box-shadow: var(--cw-e1); border-color: var(--cw-border-strong); }
.ls-plan:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }
.ls-plan.selected {
  border-color: var(--cw-accent); box-shadow: 0 0 0 1px var(--cw-accent) inset;
  background: var(--cw-accent-subtle);
}
.ls-plan.cs-plan-row-disabled, .ls-plan:disabled {
  opacity: .5; cursor: not-allowed; transform: none; box-shadow: none;
}
.ls-plan-rec { border-color: var(--cw-accent-border); }
.ls-plan-badge {
  position: absolute; top: -9px; left: var(--cw-s4);
  padding: 2px 9px; border-radius: var(--cw-r-full);
  background: var(--cw-accent); color: var(--cw-accent-ink);
  font: var(--cw-micro); letter-spacing: .02em;
}
.ls-plan-head { display: flex; flex-direction: column; gap: 2px; }
.ls-plan-name { font: 600 13px/18px var(--cw-font); color: var(--cw-ink); }
.ls-plan-price {
  font: 700 20px/26px var(--cw-font); color: var(--cw-ink);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.ls-plan-per { font: var(--cw-micro); color: var(--cw-text-soft); margin-left: 3px; font-weight: 500; }
.ls-plan-feats { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.ls-plan-feat {
  position: relative; padding-left: 16px;
  font: 400 11.5px/17px var(--cw-font); color: var(--cw-text);
}
.ls-plan-feat::before {
  content: '✓'; position: absolute; left: 0; top: 0;
  color: var(--cw-ok); font-weight: 700;
}
.ls-plan-feat-no { color: var(--cw-text-faint); }
.ls-plan-feat-no::before { content: '–'; color: var(--cw-text-faint); }
.ls-plan-note {
  font: 400 11px/15px var(--cw-font); color: var(--cw-text-soft);
  padding-top: var(--cw-s2); border-top: 1px solid var(--cw-border);
}

/* The only way forward must never be the thing you have to hunt for. The modal
   body scrolls (max-height: 85vh), so the plan step's actions stick to its
   bottom instead of sliding off the end of the card grid.
   bottom MUST be 0, not a negative value: a sticky offset is the THRESHOLD at
   which the element pins, not a margin. `bottom: -32px` pinned the button 32px
   BELOW the container's bottom edge — permanently out of sight, which is
   exactly how the Continue action went missing. */
#cs-step-plan .btn-primary,
#cs-step-plan .cs-pay-methods {
  position: sticky; bottom: 0; z-index: 2;
  padding-bottom: var(--cw-s2);
}
/* NO background on the button. `#cs-step-plan .btn-primary` is (1,1,0) and
   beats `.btn-primary` (0,1,0), so a backdrop declared here repaints the CTA
   itself — the purple button rendered in the surface colour, i.e. a white bar
   on a white modal that looked like no button at all. The button is already
   opaque; it needs no backdrop of its own.
   .cs-pay-methods IS a bare container, so it keeps one to stop cards showing
   through the gaps between its buttons. */
#cs-step-plan .cs-pay-methods { background: var(--cw-surface); }
#cs-step-plan .btn-primary { margin-top: var(--cw-s4); }

/* ── L3: arrival ────────────────────────────────────────── */
.ls-done-top { text-align: center; }
.ls-done-mark {
  font-size: 46px; line-height: 1; margin-bottom: var(--cw-s3);
  animation: ls-pop .5s cubic-bezier(.34, 1.56, .64, 1) both;
}
@keyframes ls-pop {
  0%   { transform: scale(.4) rotate(-12deg); opacity: 0; }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}
.ls-done-title { font: var(--cw-display); color: var(--cw-ink); margin: 0 0 var(--cw-s2); }
.ls-done-sub { font: var(--cw-small); color: var(--cw-text-soft); margin: 0 0 var(--cw-s5); }

.ls-done-addr {
  display: flex; align-items: center; justify-content: space-between; gap: var(--cw-s3);
  padding: var(--cw-s4); background: var(--cw-surface-2);
  border: 1px solid var(--cw-border); border-radius: var(--cw-r-md);
  margin-bottom: var(--cw-s4);
}
.ls-done-url {
  font-family: var(--cw-font-mono); font-size: 14px; color: var(--cw-ink);
  text-decoration: none; word-break: break-all; min-width: 0;
}
.ls-done-url:hover { color: var(--cw-accent); text-decoration: underline; }
.ls-copy {
  flex: none; background: none; border: 1px solid var(--cw-border-strong);
  border-radius: var(--cw-r-sm); padding: 5px 10px; cursor: pointer;
  font: var(--cw-micro); color: var(--cw-text);
  transition: border-color var(--cw-t-micro), color var(--cw-t-micro);
}
.ls-copy:hover { border-color: var(--cw-accent); color: var(--cw-accent); }

.ls-done-actions { display: flex; flex-wrap: wrap; gap: var(--cw-s2); margin-bottom: var(--cw-s6); }
.ls-btn-primary, .ls-btn-secondary {
  flex: 1 1 auto; text-align: center; text-decoration: none;
  padding: 10px var(--cw-s4); border-radius: var(--cw-r-md);
  font: 600 13px/20px var(--cw-font); cursor: pointer;
  transition: background var(--cw-t-micro), border-color var(--cw-t-micro), transform var(--cw-t-micro);
}
.ls-btn-primary { background: var(--cw-accent); color: var(--cw-accent-ink); border: 1px solid var(--cw-accent); }
.ls-btn-primary:hover { background: var(--cw-accent-hover); transform: translateY(-1px); }
.ls-btn-secondary { background: var(--cw-surface); color: var(--cw-ink); border: 1px solid var(--cw-border-strong); }
.ls-btn-secondary:hover { border-color: var(--cw-ink); transform: translateY(-1px); }

.ls-next { border-top: 1px solid var(--cw-border); padding-top: var(--cw-s5); }
.ls-next-title {
  font: var(--cw-micro); letter-spacing: .08em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s3);
}
.ls-next-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--cw-s1); }
.ls-next-item a {
  display: block; padding: var(--cw-s3); border-radius: var(--cw-r-md);
  text-decoration: none; transition: background var(--cw-t-micro);
}
.ls-next-item a:hover { background: var(--cw-surface-2); }
.ls-next-item a:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: -2px; }
.ls-next-item-title { display: block; font: 600 13px/20px var(--cw-font); color: var(--cw-ink); }
.ls-next-item-text { display: block; font: var(--cw-micro); color: var(--cw-text-soft); }

.ls-done-foot { display: flex; gap: var(--cw-s2); margin-top: var(--cw-s5); }

@media (max-width: 720px) {
  /* Mobile keeps the single scrolling strip — swiping a chip row is natural on
     touch, and wrapping 12 chips would eat half the screen. */
  .ls-chips {
    flex-wrap: nowrap; overflow-x: auto;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .ls-chips::-webkit-scrollbar { display: none; }

  .ls-hero { flex-direction: column; align-items: stretch; }
  .ls-hero-title { font: 700 24px/30px var(--cw-font); }
  .ls-hero-actions { flex-direction: column; }
  .ls-start { min-width: 0; width: 100%; }
  .ls-plans { grid-template-columns: 1fr; }
  .ls-done-actions, .ls-done-foot { flex-direction: column; }
}

/* ══ Dark mode: legacy hardcoded surfaces (K3) ═════════════════════════════
   tokens.css remaps every VARIABLE for dark, but dashboard.css also contains
   ~80 literal hex values that no variable can reach. Those are what produced
   a dark app with white template cards, a white notification panel and white
   pagination. Overridden here because console.css loads last.

   Scope is deliberate: only surfaces and text. Brand accents, status tints and
   the traffic-light dots keep their literals — they read correctly on dark and
   are meant to be constant. */

html[data-theme="dark"] {
  /* Template library */
  --cwp-dk-surface: #17171F;
  --cwp-dk-raise:   #1E1E29;
  --cwp-dk-border:  #262632;
  --cwp-dk-ink:     #F4F4F9;
}

html[data-theme="dark"] #sites-templates-showcase .cwp-templates-explore-card-header { background: var(--cwp-dk-raise); }
html[data-theme="dark"] #sites-templates-showcase .cwp-templates-explore-card { background: var(--cwp-dk-surface); border-color: var(--cwp-dk-border); }
html[data-theme="dark"] #sites-templates-showcase .cwp-card-tag-category { background: var(--cwp-dk-surface); color: var(--cwp-dk-ink); }
html[data-theme="dark"] #sites-templates-showcase .cwp-card-title,
html[data-theme="dark"] #sites-templates-showcase .cwp-card-demo { color: var(--cwp-dk-ink); }
html[data-theme="dark"] #sites-templates-showcase .cwp-templates-explore-create-btn { background: var(--cwp-dk-surface); color: #9B8DF9; }
html[data-theme="dark"] #sites-templates-showcase .cwp-templates-explore-create-btn:hover { background: var(--cwp-dk-raise); }
html[data-theme="dark"] #sites-templates-showcase .cwp-templates-explore-search-box input {
  background: var(--cwp-dk-raise); border-color: var(--cwp-dk-border); color: var(--cwp-dk-ink);
}
html[data-theme="dark"] #sites-templates-showcase .cwp-page-arrow,
html[data-theme="dark"] #sites-templates-showcase .cwp-page-number {
  background: var(--cwp-dk-surface); border-color: var(--cwp-dk-border); color: var(--cwp-dk-ink);
}
html[data-theme="dark"] #sites-templates-showcase .cwp-page-number.active {
  background: #7C6BF7; border-color: #7C6BF7; color: #fff;
}

/* Notification bell + slide-over panel */
html[data-theme="dark"] .notif-bell { background: var(--cwp-dk-surface); border-color: var(--cwp-dk-border); color: var(--cwp-dk-ink); }
html[data-theme="dark"] .notif-panel { background: var(--cwp-dk-surface); border-color: var(--cwp-dk-border); color: var(--cwp-dk-ink); }
html[data-theme="dark"] .notif-item.unread { background: #1E1B3A; }
html[data-theme="dark"] .notif-banner { background: var(--cwp-dk-raise); border-color: var(--cwp-dk-border); color: var(--cwp-dk-ink); }
html[data-theme="dark"] .notif-banner[data-sev="warn"]   { background: #2A2213; border-color: #4A3A1A; }
html[data-theme="dark"] .notif-banner[data-sev="danger"] { background: #2B1618; border-color: #4A2226; }
html[data-theme="dark"] .notif-banner[data-sev="info"]   { background: #1E1B3A; border-color: #332E63; }

/* Status pills that pair a light tint with dark text — unreadable inverted. */
html[data-theme="dark"] .bk-badge.ok      { background: #10281E; color: #34D399; }
html[data-theme="dark"] .bk-badge.pending { background: #1E1B3A; color: #9B8DF9; }

/* Support form controls (signup.css literals). */
html[data-theme="dark"] .support-radio { background: var(--cwp-dk-surface); }

/* Intro-pricing line on a plan card. The customer must never have to work out
   when the price changes — the transition is stated on the card itself. */
.pl-up-intro {
  font: var(--cw-micro); color: var(--cw-text-soft);
  margin-top: var(--cw-s2); line-height: 16px;
}
.pl-up-intro strong { color: var(--cw-ink); font-weight: 600; }

/* ── First run: an account with no sites (K4) ─────────────────
   Not a dashboard with the numbers missing — a starting point. */
.ov-first { max-width: 720px; }
.ov-first-sub {
  font: var(--cw-body); color: var(--cw-text-soft);
  margin: var(--cw-s3) 0 var(--cw-s6); max-width: 60ch;
}
.ov-first-actions { display: flex; gap: var(--cw-s3); flex-wrap: wrap; margin-bottom: var(--cw-s7); }
.ov-first-card { padding: var(--cw-s6); }
.ov-first-card-title {
  font: var(--cw-micro); letter-spacing: .08em; text-transform: uppercase;
  color: var(--cw-text-faint); margin-bottom: var(--cw-s4);
}
.ov-first-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--cw-s3); }
.ov-first-list li {
  position: relative; padding-left: 22px;
  font: var(--cw-small); color: var(--cw-text-soft);
}
.ov-first-list li::before {
  content: '✓'; position: absolute; left: 0; top: 0;
  color: var(--cw-ok); font-weight: 700; font-size: 12px; line-height: 20px;
}
.ov-first-list strong { color: var(--cw-ink); font-weight: 600; }
.ov-first-foot {
  font: var(--cw-micro); color: var(--cw-text-faint);
  margin-top: var(--cw-s5); padding-top: var(--cw-s4);
  border-top: 1px solid var(--cw-border);
}
@media (max-width: 720px) { .ov-first-actions .cw-btn { flex: 1 1 auto; } }

/* Storage: measurement pending. A spinner beside the label, never a meter —
   we draw no bar for a number we do not have. */
.pl-measuring { display: inline-flex; align-items: center; gap: var(--cw-s2); }
.pl-measuring .ls-spin { width: 11px; height: 11px; border-width: 2px; }

/* Introductory terms under the plan price. Secondary weight: it explains the
   headline rate, it does not compete with it. */
.pl-hero-intro {
  font: var(--cw-small); color: var(--cw-text-soft);
  margin: calc(var(--cw-s2) * -1) 0 var(--cw-s3);
}

/* Next-step banner in the plan hero. Accent-tinted so it reads as guidance,
   not as an error — the customer has done nothing wrong, there is simply one
   more step. Sits between the infrastructure facts and the actions. */
.pl-next {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--cw-s5); flex-wrap: wrap;
  margin-top: var(--cw-s5); padding: var(--cw-s4) var(--cw-s5);
  background: var(--cw-accent-subtle);
  border: 1px solid var(--cw-accent-border);
  border-radius: var(--cw-r-md);
}
.pl-next-body { min-width: 0; flex: 1 1 320px; }
.pl-next-title { font: 600 14px/20px var(--cw-font); color: var(--cw-ink); }
.pl-next-text {
  font: var(--cw-small); color: var(--cw-text-soft);
  margin-top: 2px; max-width: 62ch;
}
.pl-next .cw-btn { flex: none; }
@media (max-width: 720px) {
  .pl-next { flex-direction: column; align-items: stretch; }
  .pl-next .cw-btn { width: 100%; }
}
