/* IndieVouch — tokens first, then components. Light (warm, editorial) is the default;
   dark is available via the theme toggle. Brand accent is a warm ember orange, used
   sparingly for links, badges and small highlights — primary buttons are solid ink,
   not brand-colored, so the accent stays a highlight rather than the loudest thing
   on every screen. */

/* Native cross-document transitions between full page loads — smooths navigation
   on browsers that support it (Chrome/Edge, Safari 18.2+), ignored elsewhere with no
   fallback needed since normal navigation is what already happens without it. */
@view-transition {
  navigation: auto;
}

:root, :root[data-theme="light"] {
  color-scheme: light;
  --plane:         #f5f1e8;
  --surface:       #fffdf9;
  --surface-2:     #efe8da;
  --ink:           #1c1712;
  --ink-2:         #5c5347;
  --ink-muted:     #766d60;
  --hairline:      rgba(28, 20, 12, 0.12);
  --gridline:      #e6ddcc;
  --baseline:      #d8cdb8;

  --brand:         #d9560c;
  --brand-strong:  #b8470a;
  --brand-wash:    #fbe8d8;
  --brand-ink:     #1c1712;

  --info:          #2a6fb0;
  --good:          #2f7d32;
  --good-text:     #2f7d32;
  --warning:       #93610a;
  --warning-text:  #93610a;
  --critical:      #b3301c;
  --good-wash:     #e7f2e3;
  --warning-wash:  #faf0da;
  --critical-wash: #fae5df;
  --info-wash:     #e7f1fa;
  --neutral-wash:  #eee6d6;

  --radius-sm:     9px;
  --radius:        14px;
  --radius-lg:     22px;
  --font: "Outfit", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Fraunces", "Outfit", Georgia, serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --dur-fast:      180ms;
  --dur-normal:    300ms;
  --dur-slow:      450ms;
  --ease:          cubic-bezier(.16, 1, .3, 1);
  --ease-sm:       cubic-bezier(0, 0, .2, 1);

  --shadow-sm: 0 1px 2px rgba(28, 20, 12, .04);
  --shadow-md: 0 1px 2px rgba(28, 20, 12, .04), 0 10px 30px -14px rgba(28, 20, 12, .18);
  --shadow-lg: 0 2px 4px rgba(28, 20, 12, .05), 0 24px 48px -20px rgba(28, 20, 12, .30);
  --shadow-primary: inset 0 1px 0 rgba(255, 255, 255, .12), 0 14px 28px -10px rgba(28, 20, 12, .5);
  --shadow-primary-hover: inset 0 1px 0 rgba(255, 255, 255, .16),
    0 22px 40px -12px rgba(217, 86, 12, .35), 0 16px 32px -10px rgba(28, 20, 12, .55);
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --plane:         #15110c;
  --surface:       #201a13;
  --surface-2:     #2a2318;
  --ink:           #f7f2e8;
  --ink-2:         #cabfab;
  --ink-muted:     #93897a;
  --hairline:      rgba(255, 246, 232, 0.10);
  --gridline:      #35301f;
  --baseline:      #463c28;

  --brand:         #ef7a2e;
  --brand-strong:  #ff9450;
  --brand-wash:    #35220f;
  --brand-ink:     #17110a;

  --info:          #5a9bdb;
  --good:          #5fbf63;
  --good-text:     #6fca72;
  --warning:       #e0a83e;
  --warning-text:  #e0a83e;
  --critical:      #e2705a;
  --good-wash:     #17291a;
  --warning-wash:  #382a10;
  --critical-wash: #3a2015;
  --info-wash:     #182838;
  --neutral-wash:  #2a2318;
}

* { box-sizing: border-box; }

/* overflow-x: clip (not hidden) on purpose -- Safari has a long-standing bug where
   giving html/body a non-visible overflow-x with no overflow-y set breaks
   `position: sticky` for every descendant on the page (the dashboard's .side and
   .topbar included), even though neither one has anything to do with the sidebar.
   Setting overflow-y: visible explicitly alongside it keeps normal page scrolling
   untouched while still guarding against stray horizontal overflow. */
html { scroll-behavior: smooth; overflow-x: clip; overflow-y: visible; }

body {
  margin: 0; font-family: var(--font); background: var(--plane); color: var(--ink);
  font-size: 15px; line-height: 1.55; -webkit-font-smoothing: antialiased;
  overflow-x: clip; overflow-y: visible; max-width: 100vw;
}
a { color: var(--brand-strong); text-decoration: none; }
a:hover { text-decoration: underline; }
/* A link inline in a paragraph needs more than color to stand out from the
   surrounding text (WCAG "use of color" / Lighthouse's link-in-text-block) --
   underline it rather than darkening the brand color further. Nav, button and
   card links aren't inside <p>, so they're unaffected. */
p a { text-decoration: underline; text-underline-offset: 2px; }
h1, h2, h3 { text-wrap: balance; }
h1 { font-size: 25px; font-weight: 650; letter-spacing: -.02em; margin: 0 0 6px; }
h2 { font-size: 17px; font-weight: 650; letter-spacing: -.01em; margin: 0 0 12px; }
h3 { font-size: 15px; font-weight: 600; margin: 0 0 8px; }
p { margin: 0 0 12px; text-wrap: pretty; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100; background: var(--brand);
  color: var(--brand-ink); padding: 10px 16px; border-radius: 0 0 var(--radius-sm) 0;
  font-size: 13px; font-weight: 650;
}
.skip-link:focus { left: 0; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.sub { font-family: var(--font-display); font-style: italic; font-weight: 400;
  color: var(--ink-2); margin: 0 0 20px; }
.muted { color: var(--ink-muted); }
.small { font-size: 13px; }
.mono { font-family: var(--mono); font-size: 13px; }
.nowrap { white-space: nowrap; }

/* ------------------------------------------------------------ app shell */

.shell { display: flex; min-height: 100vh; }
.side {
  width: 216px; flex: 0 0 216px; background: var(--surface);
  border-right: 1px solid var(--hairline); display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.logo { font-weight: 700; font-size: 19px; letter-spacing: -.03em; color: var(--ink); }
.logo:hover { text-decoration: none; }
.logo .dot { color: var(--brand); }
.side-nav { padding: 8px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; }
.side-nav a {
  display: flex; align-items: center; gap: 10px; padding: 8px 11px; border-radius: var(--radius-sm);
  color: var(--ink-2); font-size: 14px; font-weight: 500;
}
.side-nav a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.side-nav a.on { color: var(--brand-ink); background: var(--brand); font-weight: 600; }
.side-nav a.on .ic { opacity: 1; }
.side-nav .ic { width: 17px; text-align: center; opacity: .85; font-size: 14px; }
.side-nav .pill {
  margin-left: auto; font-size: 11px; font-weight: 700; background: var(--critical-wash);
  color: var(--critical); padding: 1px 7px; border-radius: 999px;
}
.side-foot { margin-top: auto; padding: 10px; border-top: 1px solid var(--hairline); }
.side-foot a { display: flex; gap: 10px; padding: 9px 11px; border-radius: var(--radius-sm);
  color: var(--ink-2); font-size: 13.5px; align-items: center; }
.side-foot a:hover { background: var(--surface-2); text-decoration: none; }
.side-foot .val { margin-left: auto; font-weight: 700; color: var(--ink); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  height: 58px; border-bottom: 1px solid var(--hairline); background: var(--surface);
  display: flex; align-items: center; padding: 0 22px; gap: 14px;
  position: sticky; top: 0; z-index: 15;
  box-shadow: var(--shadow-md);
}
.topbar .title { font-weight: 600; font-size: 15.5px; }
.topbar .who { margin-left: auto; display: flex; align-items: center; gap: 12px; font-size: 13px; }
.topbar .who .name { font-weight: 600; }
.topbar .who .mail { color: var(--ink-muted); font-size: 12px; }
.content { padding: 22px; max-width: 1240px; width: 100%; }

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 20px; }
.wrap-narrow { max-width: 560px; margin: 0 auto; padding: 0 20px; }

/* --------------------------------------------------------------- cards */

.card {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 18px;
}
.card + .card, .card + .notice, .notice + .card { margin-top: 14px; }
.card-tight { padding: 14px; }
.grid { display: grid; gap: 14px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.split { display: flex; justify-content: space-between; align-items: center; gap: 12px;
  flex-wrap: wrap; }
.stack > * + * { margin-top: 12px; }
.page-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px;
  flex-wrap: wrap; }
.page-head .grow { flex: 1; min-width: 200px; }

/* ----------------------------------------------------------- stat tiles */

.tile { background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 15px 17px; display: flex; gap: 13px;
  align-items: flex-start; }
.tile .badge-ic {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 9px; display: grid;
  place-items: center; font-size: 15px; background: var(--neutral-wash);
}
.tile .lbl { font-size: 12.5px; color: var(--ink-2); }
.tile .val { font-size: 25px; font-weight: 650; letter-spacing: -.025em; line-height: 1.2;
  font-variant-numeric: tabular-nums; }
.tile .foot { font-size: 12.5px; color: var(--ink-muted); }
.rs { font-size: .66em; font-weight: 550; color: var(--ink-2); margin-right: 1px; }

/* --------------------------------------------------------------- chart */

.chart { display: flex; align-items: flex-end; gap: 7px; height: 130px; }
.chart .col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 7px; justify-content: flex-end;
  height: 100%; position: relative; }
.chart .stack { width: 100%; max-width: 20px; display: flex; flex-direction: column-reverse; gap: 2px; }
.chart .seg { width: 100%; border-radius: 3px; }
.chart .seg.ok { background: var(--brand); }
.chart .seg.bad { background: var(--ink); }
.chart .seg.zero { background: var(--gridline); }
.chart-legend { display: flex; gap: 16px; font-size: 11.5px; font-weight: 600; color: var(--ink-2); margin-top: 4px; }
.chart-legend span { display: flex; align-items: center; gap: 5px; }
.chart-legend i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.chart-axis { display: flex; gap: 3px; border-top: 1px solid var(--baseline);
  padding-top: 6px; font-size: 11px; color: var(--ink-muted); }
.chart-axis span { flex: 1; text-align: center; overflow: hidden; white-space: nowrap; }
.chart .col:hover .tip, .hbar:hover .tip { opacity: 1; margin-bottom: 6px; }
.tip {
  /* Horizontal position is plain left/transform so JS can override just those
     two (see bindChartTips in app.html) without fighting this rule -- the
     hover "lift" is margin-bottom instead of a transform:translateY, which
     would otherwise collide with JS setting transform for horizontal clamping. */
  position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 2px;
  background: var(--ink); color: var(--plane); font-size: 12px; padding: 5px 8px;
  border-radius: 6px; white-space: nowrap; pointer-events: none; opacity: 0;
  transition: opacity .12s, margin-bottom .12s; z-index: 5;
}
.hbars { display: flex; flex-direction: column; gap: 9px; }
.hbar { display: grid; grid-template-columns: 96px 1fr auto; gap: 11px; align-items: center;
  font-size: 13px; position: relative; }
.hbar .track { background: var(--surface-2); border-radius: 4px; height: 20px; overflow: hidden; }
.hbar .fill { background: var(--brand); height: 100%; border-radius: 4px; min-width: 3px; }
.hbar .n { color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- buttons */

.btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  gap: 7px; border: 1px solid var(--hairline); background: var(--surface); color: var(--ink);
  border-radius: 999px; padding: 9px 16px; font: inherit; font-size: 14px;
  font-weight: 550; cursor: pointer; text-decoration: none; overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
    transform var(--dur-normal) var(--ease), box-shadow var(--dur-normal) var(--ease);
}
.btn:hover { background: var(--surface-2); text-decoration: none; transform: translateY(-1px);
  box-shadow: var(--shadow-md); }
.btn:active { transform: translateY(0) scale(.98); box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-sm), box-shadow var(--dur-fast) var(--ease-sm); }
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn-primary { background: var(--ink); border-color: var(--ink); color: var(--plane);
  box-shadow: var(--shadow-primary); }
.btn-primary:hover { background: var(--ink); border-color: var(--ink);
  box-shadow: var(--shadow-primary-hover); }
.btn-primary::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 40%, rgba(255, 255, 255, .16) 50%, transparent 60%);
  transform: translateX(-120%); transition: transform var(--dur-slow) var(--ease-sm);
}
.btn-primary:hover::before { transform: translateX(120%); }
.btn-primary::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(140% 90% at 50% 0%, rgba(255, 255, 255, .18), transparent 60%);
  opacity: 0; transition: opacity var(--dur-normal) var(--ease-sm);
}
.btn-primary:hover::after { opacity: 1; }
.btn-primary .arrow { transition: transform var(--dur-normal) cubic-bezier(.34, 1.56, .64, 1); }
.btn-good { background: var(--good); border-color: var(--good); color: #fff; }
.btn-danger { color: var(--critical); }
.btn-danger:hover { background: var(--critical-wash); }
.btn-lg { padding: 14px 24px; font-size: 16px; width: 100%; }
.btn-sm { padding: 6px 12px; font-size: 12.5px; }
.btn-row { display: flex; gap: 9px; flex-wrap: wrap; }
.btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.btn:disabled:hover { transform: none; box-shadow: none; }
.btn:disabled:active { transform: none; }

.btn.is-loading { opacity: 1; color: transparent !important; pointer-events: none;
  cursor: default; box-shadow: var(--shadow-sm); transform: none; }
.btn.is-loading::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 15px; height: 15px;
  margin: -7.5px 0 0 -7.5px; border: 2px solid var(--ink); border-top-color: transparent;
  border-radius: 50%; animation: btn-spin .65s linear infinite;
}
.btn-primary.is-loading::after, .btn-good.is-loading::after {
  border-color: var(--plane); border-top-color: transparent;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

.arrow { display: inline-block; transition: transform var(--dur-normal) var(--ease); }
a:hover .arrow, .btn:hover .arrow { transform: translateX(3px); }

a:focus-visible, .nav-links a:focus-visible, .side-nav a:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 3px;
}

/* ---------------------------------------------------------------- forms */

label { display: block; font-size: 13px; font-weight: 600; margin: 0 0 5px; color: var(--ink-2); }
.field { margin-bottom: 14px; }
.req { color: var(--critical); }
.hint { font-size: 12.5px; color: var(--ink-muted); margin-top: 5px; }
input[type=text], input[type=email], input[type=password], input[type=tel], input[type=url],
input[type=number], input[type=date], input[type=search], textarea, select {
  width: 100%; padding: 9px 12px; font: inherit; font-size: 15px;
  border: 1px solid var(--baseline); border-radius: var(--radius-sm);
  background: var(--plane); color: var(--ink);
}
input:focus, textarea:focus, select:focus {
  outline: 2px solid var(--brand); outline-offset: -1px; border-color: var(--brand);
}
input:disabled, textarea:disabled, select:disabled {
  background: var(--surface-2); color: var(--ink-muted); cursor: not-allowed; opacity: .75;
}
input[type=color] { width: 44px; height: 38px; padding: 3px; border-radius: var(--radius-sm);
  border: 1px solid var(--baseline); background: var(--plane); cursor: pointer; }
textarea { min-height: 76px; resize: vertical; }
.check { display: flex; align-items: center; gap: 9px; margin-bottom: 8px; }
.check input { width: 17px; height: 17px; accent-color: var(--brand); flex: 0 0 17px; }
.check label { margin: 0; font-weight: 500; color: var(--ink); }
.prefix { position: relative; }
.prefix > span { position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  color: var(--ink-muted); pointer-events: none; }
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 40px; }
.pw-toggle { position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  background: none; border: none; padding: 0; cursor: pointer; color: var(--ink-muted);
  border-radius: var(--radius-sm); }
.pw-toggle:hover { color: var(--ink); }
.pw-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.pw-toggle .i-eye-off { display: none; }
.pw-toggle.is-visible .i-eye { display: none; }
.pw-toggle.is-visible .i-eye-off { display: block; }
.prefix input { padding-left: 26px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row > * { flex: 1; min-width: 150px; }
fieldset { border: 1px solid var(--hairline); border-radius: var(--radius); padding: 15px;
  margin: 0 0 14px; }
legend { font-size: 13px; font-weight: 650; padding: 0 6px; color: var(--ink-2); }

/* --------------------------------------------------------------- badges */

.badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  font-weight: 650; padding: 3px 9px; border-radius: 999px; white-space: nowrap;
  background: var(--neutral-wash); color: var(--ink-2); }
.badge .ic { font-size: 10px; line-height: 1; }
.b-completed { background: var(--good-wash);     color: var(--good-text); }
.b-submitted { background: var(--warning-wash);  color: var(--warning-text); }
.b-initiated { background: var(--neutral-wash);  color: var(--ink-2); }
.b-flagged   { background: var(--critical-wash); color: var(--critical); }
.b-failed    { background: var(--critical-wash); color: var(--critical); }
.b-refunded  { background: var(--neutral-wash);  color: var(--ink-2); }
.b-expired   { background: var(--neutral-wash);  color: var(--ink-muted); }
.b-active    { background: var(--good-wash);     color: var(--good-text); }
.b-paused    { background: var(--neutral-wash);  color: var(--ink-2); }
.b-linked    { background: var(--good-wash);     color: var(--good-text); }
.b-unlinked  { background: var(--neutral-wash);  color: var(--ink-2); }
.b-info      { background: var(--info-wash);     color: var(--info); }

/* ---------------------------------------------------------------- table */

.table-wrap {
  overflow-x: auto; border: 1px solid var(--hairline); border-radius: var(--radius);
  background-color: var(--surface);
  background-image:
    linear-gradient(to right, var(--surface) 30%, rgba(0, 0, 0, 0)),
    linear-gradient(to left, var(--surface) 30%, rgba(0, 0, 0, 0)),
    linear-gradient(to right, rgba(28, 20, 12, .14), rgba(0, 0, 0, 0) 100%),
    linear-gradient(to left, rgba(28, 20, 12, .14), rgba(0, 0, 0, 0) 100%);
  background-position: left center, right center, left center, right center;
  background-repeat: no-repeat;
  background-size: 24px 100%, 24px 100%, 10px 100%, 10px 100%;
  background-attachment: local, local, scroll, scroll;
}
table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th { text-align: left; font-size: 11.5px; font-weight: 650; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-muted); padding: 11px 14px;
  border-bottom: 1px solid var(--hairline); white-space: nowrap; }
td { padding: 11px 14px; border-bottom: 1px solid var(--hairline); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------------------------------------------------------------- misc */

.notice { border-radius: var(--radius-sm); padding: 11px 14px; margin-bottom: 16px;
  font-size: 14px; border: 1px solid var(--hairline); background: var(--info-wash); }
.notice-ok   { background: var(--good-wash); }
.notice-warn { background: var(--warning-wash); }
.notice-err  { background: var(--critical-wash); }
.notice ul { margin: 4px 0 0; padding-left: 20px; }
.notice b { display: block; }

.tabs { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 16px; }
.tabs a { font-size: 13.5px; font-weight: 550; color: var(--ink-2); padding: 6px 13px;
  border-radius: 999px; border: 1px solid transparent; }
.tabs a:hover { background: var(--surface-2); text-decoration: none; }
.tabs a.on { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
.subtabs { display: flex; gap: 20px; border-bottom: 1px solid var(--hairline);
  margin-bottom: 18px; flex-wrap: wrap; }
.subtabs a { padding: 9px 2px; font-size: 14px; font-weight: 550; color: var(--ink-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px; }
.subtabs a:hover { color: var(--ink); text-decoration: none; }
.subtabs a.on { color: var(--brand); border-bottom-color: var(--brand); }

.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-bottom: 14px; }
.filters .f { min-width: 120px; }
.filters .f.grow { flex: 1; min-width: 190px; }
.filters label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-muted); }
.filters input, .filters select { padding: 7px 10px; font-size: 13.5px; }

.copy-row { display: flex; gap: 8px; align-items: stretch; }
.copy-row input { font-family: var(--mono); font-size: 12.5px; }

.qr { display: inline-flex; padding: 13px; background: #fff; color: #0b0b0b;
  border-radius: var(--radius); }

pre { background: var(--plane); border: 1px solid var(--hairline); border-radius: var(--radius-sm);
  padding: 12px 14px; overflow-x: auto; font-size: 12.5px; line-height: 1.6; margin: 0;
  font-family: var(--mono); color: var(--ink-2); }
pre.reason { background: var(--critical-wash); border-color: transparent; color: var(--ink); }

.dl { display: grid; grid-template-columns: auto 1fr; gap: 7px 18px; font-size: 13.5px; }
.dl dt { color: var(--ink-muted); }
.dl dd { margin: 0; text-align: right; word-break: break-word; }

.empty { text-align: center; padding: 40px 20px; color: var(--ink-muted); }
.empty h3 { color: var(--ink); }
.empty .ic { font-size: 26px; opacity: .5; }

.steps { counter-reset: s; list-style: none; padding: 0; margin: 0; }
.steps li { counter-increment: s; position: relative; padding-left: 34px; margin-bottom: 13px;
  color: var(--ink-2); font-size: 14px; }
.steps li::before { content: counter(s); position: absolute; left: 0; top: 1px;
  width: 22px; height: 22px; border-radius: 50%; background: var(--brand-wash);
  color: var(--brand); font-weight: 700; font-size: 12px; display: grid; place-items: center; }
.steps b { color: var(--ink); font-weight: 600; }

.amount-big { font-size: 38px; font-weight: 650; letter-spacing: -.03em; line-height: 1.1;
  margin: 2px 0 12px; font-variant-numeric: tabular-nums; }
.strike { text-decoration: line-through; color: var(--ink-muted); font-weight: 400;
  font-size: .6em; margin-right: 7px; }

.prod { display: grid; grid-template-columns: 64px 1fr auto; gap: 14px; align-items: center;
  padding: 14px 0; border-bottom: 1px solid var(--hairline); }
.prod:last-child { border-bottom: none; }
.prod .thumb { width: 64px; height: 64px; border-radius: var(--radius-sm); object-fit: cover;
  background: var(--surface-2); display: grid; place-items: center; color: var(--ink-muted);
  font-size: 24px; }
.qty { display: flex; align-items: center; gap: 6px; }
.qty input { width: 62px; text-align: center; padding: 7px 4px; }
.optrow { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.optrow select { width: auto; min-width: 110px; padding: 5px 8px; font-size: 13px; }

.testimonials { display: flex; gap: 12px; overflow-x: auto; margin-bottom: 18px;
  padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
.testimonial-card { flex: 0 0 240px; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 14px 16px; }
.testimonial-card .stars { color: var(--brand); font-size: 13px; letter-spacing: 1px;
  margin-bottom: 6px; }
.testimonial-card .quote { font-size: 13.5px; line-height: 1.5; margin: 0 0 8px; }

.bio-links { display: flex; flex-direction: column; gap: 10px; max-width: 480px;
  margin: 0 auto; }
.bio-link { display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  text-decoration: none; color: var(--ink); transition: border-color .15s; }
.bio-link:hover { border-color: var(--brand); text-decoration: none; }
.bio-link .ic { font-size: 18px; width: 24px; text-align: center; flex-shrink: 0; }
.bio-link .name { font-weight: 600; font-size: 14.5px; }
.bio-link .meta { font-size: 12.5px; color: var(--ink-muted); }

.disclaimer { font-size: 12.5px; color: var(--ink-muted); line-height: 1.5;
  border-left: 2px solid var(--gridline); padding-left: 11px; }
.public-nav { position: relative; padding: 16px 20px 0; }
.public-nav .in {
  position: relative; max-width: 1080px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
.nav-pill {
  display: flex; align-items: center; gap: 12px;
  background: var(--surface);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--hairline); border-radius: 999px;
  box-shadow: var(--shadow-md);
  transition: box-shadow var(--dur-normal) var(--ease-sm), border-color var(--dur-normal) var(--ease-sm);
}
.nav-pill:hover { box-shadow: var(--shadow-lg); border-color: var(--baseline); }
.nav-logo-pill { padding: 8px 18px 8px 14px; }
.nav-links-pill { position: relative; padding: 6px 6px 6px 16px; flex-wrap: wrap; }
.public-nav img { height: 30px; width: 30px; border-radius: 7px; object-fit: cover; }
.logo .dot { display: inline-block; transition: transform var(--dur-normal) cubic-bezier(.34, 1.56, .64, 1); }
.logo:hover .dot { transform: rotate(-16deg) scale(1.2); }
.nav-links { display: flex; gap: 4px; flex-wrap: wrap; }
.nav-links a {
  position: relative; z-index: 0; color: var(--ink-2); display: inline-flex; align-items: center;
  padding: 7px 13px; border-radius: 999px;
  transition: color var(--dur-fast) var(--ease-sm), transform var(--dur-fast) var(--ease-sm);
}
.nav-links a::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: var(--surface-2); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-normal) var(--ease);
}
.nav-links a:hover { color: var(--ink); transform: translateY(-1px); }
.nav-links a:hover::before { transform: scaleX(1); }
.nav-links a.active { color: var(--ink); font-weight: 600; }
.nav-cta { display: flex; gap: 10px; align-items: center; margin-left: auto; }
@media (max-width: 700px) { .nav-links { display: none; } }

.nav-burger {
  display: none; position: relative; width: 34px; height: 34px; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--surface); cursor: pointer; padding: 0;
  transition: background var(--dur-fast) var(--ease-sm), transform var(--dur-fast) var(--ease-sm);
}
.nav-burger:hover { background: var(--surface-2); }
.nav-burger:active { transform: scale(.94); }
.nav-burger span {
  position: absolute; left: 9px; right: 9px; height: 1.6px; border-radius: 2px;
  background: var(--ink); transition: transform var(--dur-normal) var(--ease), opacity var(--dur-fast) var(--ease-sm);
}
.nav-burger span:nth-child(1) { top: 12px; }
.nav-burger span:nth-child(2) { top: 16.2px; }
.nav-burger span:nth-child(3) { top: 20.4px; }
.nav-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(4.2px) rotate(45deg); }
.nav-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-4.2px) rotate(-45deg); }
@media (max-width: 700px) { .nav-burger { display: block; } }

.mobile-nav-menu {
  position: absolute; right: 20px; top: 100%; margin-top: 10px; min-width: 220px;
  display: flex; flex-direction: column; gap: 2px; padding: 8px; z-index: 20;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); transform-origin: top right;
  opacity: 0; transform: translateY(-6px) scale(.97); pointer-events: none;
  transition: opacity var(--dur-normal) var(--ease-sm), transform var(--dur-normal) var(--ease-sm);
}
.mobile-nav-menu.open { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
.mobile-nav-menu a { padding: 10px 12px; border-radius: var(--radius-sm); color: var(--ink-2);
  font-size: 14.5px; font-weight: 500; transition: background var(--dur-fast) var(--ease-sm), color var(--dur-fast) var(--ease-sm); }
.mobile-nav-menu a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.mobile-nav-menu a.on { color: var(--brand); font-weight: 650; }
.mobile-nav-divider { border-top: 1px solid var(--hairline); margin: 6px 4px; }
@media (min-width: 701px) { .mobile-nav-menu { display: none; } }
.site-foot { border-top: 1px solid var(--hairline); margin-top: 50px; padding: 20px 0 32px;
  color: var(--ink-muted); font-size: 12.5px; }
.foot-grid { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
.foot-links { display: flex; gap: 16px; flex-wrap: wrap; }
.foot-links a { color: var(--ink-muted); }
.content-page h2 { margin-top: 0; }
.content-page .card + .card { margin-top: 14px; }
.faq-item summary { cursor: pointer; font-weight: 600; color: var(--ink); list-style: none; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::before { content: "+ "; color: var(--brand); }
.faq-item[open] summary::before { content: "\2212 "; }
.faq-item p { margin: 8px 0 0; color: var(--ink-2); }
.faq-item + .faq-item { border-top: 1px solid var(--hairline); margin-top: 12px; padding-top: 12px; }

.hero { position: relative; padding: 88px 0 48px; text-align: center; overflow: visible; }
.hero::before {
  content: ""; position: absolute; top: -60px; left: 50%; transform: translateX(-50%);
  width: 900px; height: 620px; max-width: 100vw; z-index: -1; pointer-events: none;
  background:
    radial-gradient(closest-side, var(--brand-wash), transparent 70%) 18% 20% / 46% 60% no-repeat,
    radial-gradient(closest-side, var(--surface-2), transparent 72%) 78% 12% / 40% 55% no-repeat;
  opacity: .9; filter: blur(2px);
}
.hero h1 { font-size: clamp(42px, 8vw, 76px); letter-spacing: -.045em; line-height: 1.01;
  margin-bottom: 18px; }
.hero h1 .g { font-family: var(--font-display); font-style: italic; font-weight: 500;
  color: var(--brand); }
.hero p { font-family: var(--font-display); font-style: italic; font-size: 20px;
  color: var(--ink-2); max-width: 580px; margin: 0 auto 28px; }
.hero .btn-row { justify-content: center; }
.chips { display: flex; gap: 9px; flex-wrap: wrap; justify-content: center; margin-bottom: 30px; }
.chip { border: 1px solid var(--hairline); border-radius: 999px; padding: 6px 14px;
  font-size: 13px; color: var(--ink-2); background: var(--surface); }
.chip b { color: var(--brand); }
.feature .ic { width: 34px; height: 34px; border-radius: var(--radius-sm);
  background: var(--brand-wash); display: grid; place-items: center; margin-bottom: 10px;
  color: var(--brand); font-weight: 650; }
.feature .ic svg { width: 18px; height: 18px; }
.feature p { margin: 0; color: var(--ink-2); font-size: 14px; }

/* ------------------------------------------------------------- proof cards */

.proof-stack { position: relative; max-width: 380px; margin: 44px auto 0; height: 210px; }
.proof-card {
  position: absolute; width: 260px; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius-lg); padding: 16px; box-shadow: var(--shadow-lg);
  transition: transform var(--dur-slow) var(--ease), box-shadow var(--dur-slow) var(--ease);
  will-change: transform;
}
.proof-card.p1 { left: 0; top: 0; transform: rotate(-6deg); z-index: 2; }
.proof-card.p2 { right: 0; top: 34px; transform: rotate(5deg); z-index: 1; }
.proof-card:hover {
  transform: rotate(0deg) scale(1.04) translateY(-8px); z-index: 3;
  box-shadow: 0 4px 8px rgba(28, 20, 12, .08), 0 40px 60px -18px rgba(28, 20, 12, .4);
}
@media (prefers-reduced-motion: reduce) { .proof-card { transition: none; } }
.proof-card .dots { display: flex; gap: 4px; margin-bottom: 10px; }
.proof-card .dots span { width: 7px; height: 7px; border-radius: 50%; background: var(--gridline); }
.proof-card .row { display: flex; justify-content: space-between; align-items: center;
  font-size: 12px; color: var(--ink-muted); margin-bottom: 8px; }
.proof-card .amt { font-family: var(--font-display); font-size: 26px; font-weight: 500;
  letter-spacing: -.02em; margin-bottom: 10px; }
.proof-card .bar { height: 7px; border-radius: 4px; background: var(--gridline); margin-bottom: 6px; }
.proof-card .bar.w60 { width: 60%; }
.proof-card .bar.w40 { width: 40%; }
.proof-card .tag { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  font-weight: 650; color: var(--good-text); background: var(--good-wash); padding: 3px 9px;
  border-radius: 999px; margin-top: 4px; }

/* --------------------------------------------------------------- reveal */

[data-reveal] { opacity: 0; transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease); }
[data-reveal].in-view { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

@keyframes fade-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
#main { animation: fade-up .45s ease both; }
@media (prefers-reduced-motion: reduce) {
  #main { animation: none; }
}

::view-transition-old(root), ::view-transition-new(root) {
  animation-duration: var(--dur-slow);
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) {
    animation: none !important;
  }
}

.statement { padding: 64px 0; text-align: center; }
.statement p { font-family: var(--font-display); font-size: clamp(28px, 5vw, 46px);
  line-height: 1.2; letter-spacing: -.02em; color: var(--ink); max-width: 820px;
  margin: 0 auto; }
.statement em { color: var(--brand); font-style: italic; }

.slider { width: 100%; accent-color: var(--brand); }
.shot { border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden;
  background: var(--surface-2); }
.shot img { display: block; width: 100%; }

@media (max-width: 980px) {
  .grid[style*="1.6fr"] { grid-template-columns: 1fr !important; }
}

@media (max-width: 860px) {
  .shell { flex-direction: column; }
  .side { display: none; }
  .content { padding: 16px; }
  .topbar { padding: 0 14px; gap: 10px; }
  .topbar .title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
  .topbar .who-info, .topbar .who-profile, .topbar .who-signout { display: none; }
}

/* ================================================================
   Dashboard re-skin -- a direct transplant of the Vertix-style mockup
   (claude.ai/artifact/VkgwE28T3oGjswXQsPM6Bm): same class names, same
   structure, same exact values, not a loose adaptation through the
   old component set. Scoped under .shell so the public site (landing,
   pricing, invoices, ...) keeps its own warm Fraunces/Outfit + ember
   palette untouched -- app.html's markup below now mirrors the
   mockup's DOM shape (.topbar as a sibling of a .body-row containing
   .side + .main) instead of the old nested layout.
   ================================================================ */

.shell {
  --plane:         #f4f4f4;
  --frame-bg:      #fafaf8;
  --surface:       #ffffff;
  --surface-2:     #f1f0ed;
  --surface-3:     #e7e5e0;
  --ink:           #15120d;
  --ink-2:         #726e66;
  --ink-muted:     #8f8b82;
  --hairline:      #eae8e3;

  --brand:         #f1592a;
  --brand-strong:  #ff7a45;
  --brand-wash:    #fde4da;
  --brand-ink:     #ffffff;

  --info:          #2f6fe0;
  --good:          #1c9d5c;
  --good-text:     #1c9d5c;
  --warning:       #d98a1d;
  --warning-text:  #d98a1d;
  --critical:      #e0453c;
  --good-wash:     #dff5e8;
  --warning-wash:  #f8e9ce;
  --critical-wash: #fbe2e0;
  --info-wash:     #e3ecfc;
  --neutral-wash:  #f1f0ed;

  --radius-sm: 12px;
  --radius:    20px;
  --radius-lg: 26px;
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --shadow-sm: 0 1px 2px rgba(20, 16, 10, .04);
  --shadow-md: 0 1px 2px rgba(20, 16, 10, .04), 0 10px 28px -18px rgba(20, 16, 10, .22);
  --shadow-lg: 0 1px 2px rgba(20, 16, 10, .04), 0 10px 28px -18px rgba(20, 16, 10, .22);
  --shadow-primary: inset 0 1px 0 rgba(255, 255, 255, .12), 0 14px 28px -10px rgba(20, 16, 10, .45);
  --shadow-primary-hover: inset 0 1px 0 rgba(255, 255, 255, .16),
    0 22px 40px -12px rgba(241, 89, 42, .35), 0 16px 32px -10px rgba(20, 16, 10, .5);

  font-family: var(--font);
}

html[data-theme="dark"] .shell {
  --plane:         #121110;
  --frame-bg:      #191714;
  --surface:       #201e1a;
  --surface-2:     #27241f;
  --surface-3:     #332f28;
  --ink:           #f3f1ec;
  --ink-2:         #9e988c;
  --ink-muted:     #7a756b;
  --hairline:      #332f28;

  --brand:         #ff7a45;
  --brand-strong:  #ff8f5c;
  --brand-wash:    #3b2318;
  --brand-ink:     #1a1208;

  --info:          #7fa8f2;
  --good:          #49cc8b;
  --good-text:     #5bdb9b;
  --warning:       #e7b458;
  --warning-text:  #e7b458;
  --critical:      #f2746b;
  --good-wash:     #173328;
  --warning-wash:  #3a2f17;
  --critical-wash: #3a1c1a;
  --info-wash:     #1c2a40;
  --neutral-wash:  #27241f;

  --shadow-md: 0 1px 2px rgba(0, 0, 0, .3), 0 14px 32px -18px rgba(0, 0, 0, .55);
  --shadow-lg: 0 1px 2px rgba(0, 0, 0, .3), 0 14px 32px -18px rgba(0, 0, 0, .55);
}

.shell label,
.shell input[type=text], .shell input[type=email], .shell input[type=password],
.shell input[type=tel], .shell input[type=url], .shell input[type=number],
.shell input[type=date], .shell input[type=search], .shell textarea, .shell select,
.shell .mono, .shell .copy-row input {
  font-family: var(--font);
}
.shell .sub { font-family: var(--font); font-style: normal; color: var(--ink-2); }

/* ---- framed shell: body itself is a .shell ancestor and can't read a token
   *defined on* .shell, so the outer page tone is spelled out directly here
   rather than threaded upward through the cascade. */
body:has(.shell) {
  background: #f4f4f4;
  padding: 18px max(18px, env(safe-area-inset-left, 0px)) 40px max(18px, env(safe-area-inset-right, 0px));
}
html[data-theme="dark"] body:has(.shell) { background: #121110; }

.shell {
  display: flex; flex-direction: column; min-height: 0;
  max-width: 1360px; margin: 0 auto;
  background: var(--frame-bg); border: 1px solid var(--hairline);
  border-radius: 28px; padding: 16px; box-shadow: var(--shadow-md);
}

/* ---- topbar: brand + pillnav + spacer + who, a sibling of .body-row now
   rather than nested inside .main like the old layout had it. */
.shell .topbar {
  height: auto; position: static; border-bottom: none; background: none; box-shadow: none;
  display: flex; align-items: center; gap: 18px; padding: 8px 10px 18px; flex-wrap: nowrap;
}
/* flex-wrap:nowrap above (not wrap) plus flex-shrink:0 here is deliberate: brand and
   who-wrap have no internal overflow handling of their own, so under width pressure
   they used to get squeezed by flexbox's default shrink behavior until the row ran out
   of room entirely and wrapped -- dropping who-wrap onto its own line below the topbar,
   left-aligned, nowhere near the avatar's usual spot. The pillnav is the one place
   built to absorb a width shortfall (overflow-x:auto plus the fade-edge affordance
   already in updatePillnavFade()), so min-width:0 here lets IT shrink to make room
   instead of the row as a whole running out of space. */
.shell .topbar .brand, .shell .topbar .who-wrap, .shell .topbar .spacer { flex-shrink: 0; }
.shell .topbar .pillnav { min-width: 0; }
.shell .brand {
  display: flex; align-items: center; gap: 11px; margin-right: 6px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 999px;
  padding: 6px 20px 6px 6px; box-shadow: var(--shadow-sm);
}
.shell .brand .mark { display: flex; }
.shell .brand .mark img { width: 38px; height: 38px; display: block; }
.shell .brand .name { font-weight: 800; font-size: 18px; letter-spacing: -.02em; }

.shell .pillnav {
  position: relative; display: flex; background: var(--surface-2); border-radius: 999px;
  padding: 4px; gap: 2px; overflow-x: auto; max-width: 56vw;
}
.shell .pillnav .nav-indicator {
  position: absolute; top: 4px; bottom: 4px; left: 4px; width: 0; border-radius: 999px;
  background: var(--ink); z-index: 0;
  transition: transform .32s cubic-bezier(.22, 1, .36, 1), width .32s cubic-bezier(.22, 1, .36, 1);
}
.shell .pillnav a {
  position: relative; z-index: 1; padding: 9px 16px; border-radius: 999px;
  font-size: 13px; font-weight: 600; color: var(--ink-2); white-space: nowrap;
  transition: color .2s ease;
}
.shell .pillnav a:hover { background: none; color: var(--ink); text-decoration: none; }
.shell .pillnav a.on { color: var(--frame-bg); }
.shell .pillnav.fade-end {
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
}
.shell .pillnav.fade-start {
  mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent 100%);
  -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent 100%);
}
.shell .pillnav.fade-start.fade-end {
  mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent 100%);
}

.shell .topbar .spacer { flex: 1; }
.shell .iconbtn {
  width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--hairline);
  background: var(--surface); display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0; color: var(--ink-2);
}
.shell .iconbtn svg { width: 16px; height: 16px; }
.shell .who-wrap { position: relative; }
.shell .who {
  display: flex; align-items: center; gap: 10px; padding: 5px 12px 5px 5px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 999px;
  box-shadow: var(--shadow-sm); font: inherit; color: inherit; cursor: pointer;
}
.shell .who:hover { background: var(--surface-2); }
.shell .who-info { text-align: right; line-height: 1.25; }
.shell .who-info .name { font-size: 13.5px; font-weight: 700; }
.shell .who-info .mail { font-size: 11.5px; color: var(--ink-2); }
.shell .who-chev {
  width: 16px; height: 16px; color: var(--ink-muted); flex: 0 0 auto;
  transition: transform .2s ease;
}
.shell .who[aria-expanded="true"] .who-chev { transform: rotate(180deg); }

.shell .who-menu {
  position: absolute; top: calc(100% + 8px); right: 0; width: 240px; z-index: 70;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 18px;
  padding: 8px; box-shadow: var(--shadow-lg);
}
.shell .who-menu[hidden] { display: none; }
.shell .who-menu-head { display: flex; align-items: center; gap: 12px; padding: 8px 8px 12px; }
.shell .who-menu-head .who-info { text-align: left; }
.shell .who-menu hr { border: none; border-top: 1px solid var(--hairline); margin: 6px 0; }
.shell .who-menu .item {
  display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 10px;
  border-radius: 11px; font-size: 14px; font-weight: 600; color: var(--ink-2);
}
.shell .who-menu .item:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.shell .who-menu .item svg { width: 17px; height: 17px; flex: 0 0 auto; }
.shell .who-menu .item.danger { color: var(--critical); }
.shell .who-menu .item.danger:hover { background: var(--critical-wash); color: var(--critical); }

/* ---- body row: icon-only rail + main content. position:sticky here (unlike
   the mockup's own rail, which has no set height and just scrolls away) so
   Profile/Sign out/Credits/Link-a-device -- now living at its bottom -- stay
   reachable while scrolling a long dashboard page, instead of requiring a
   scroll back up first.

   Deliberately NOT height:calc(100vh - 28px) -- a sticky element's *height*
   is fixed the moment it's set, but its position before you've scrolled far
   enough to actually stick is wherever normal flow puts it (here, below the
   topbar). A 100vh-tall box starting there overflows past the viewport
   bottom by roughly the topbar's own height, until you scroll past that --
   which is exactly what made Credits/Link-a-device/Profile/Sign out
   intermittently unreachable without scrolling first. Leaving height auto
   (sized to its own content) and letting .side-nav scroll internally if
   that content ever *does* run taller than the viewport avoids the bug
   entirely, in every window size, not just the one this was tested at. */
.shell .body-row { display: flex; gap: 18px; align-items: flex-start; }
.shell .side {
  /* height:auto explicitly overrides the base (pre-redesign) .side{height:100vh}
     above -- CSS cascades per property, so simply not mentioning height here
     would leave that old rule's 100vh winning for this element even though
     every other property this block sets correctly wins on specificity. That
     was the actual cause of Credits/Link-a-device/Profile/Sign out being
     unreachable: an 100vh-tall box starting below the topbar overflows the
     viewport bottom by the topbar's own height, every time, regardless of
     this element's own content. */
  position: sticky; top: 14px; height: auto; width: 58px; flex: 0 0 58px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 12px 0; display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.shell .side .theme {
  display: flex; flex-direction: column; padding-bottom: 8px; margin-bottom: 2px;
  border-bottom: 1px solid var(--hairline); width: 100%; align-items: center;
}
.shell .side .theme button {
  width: 36px; height: 36px; border-radius: var(--radius-sm); border: none; background: var(--brand-wash);
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--brand); padding: 0;
}
.shell .side .theme button svg { width: 18px; height: 18px; }
/* One button, two icons -- which one shows follows <html data-theme> directly
   (sun = click to go dark, i.e. light mode is active; moon = click to go
   light) rather than a class JS has to toggle, since the view transition in
   theme.js already sets that attribute as part of the switch. */
.shell .side .theme button .ic-moon { display: none; }
html[data-theme="dark"] .shell .side .theme button .ic-sun { display: none; }
html[data-theme="dark"] .shell .side .theme button .ic-moon { display: block; }

.shell .side-nav {
  /* overflow-y:visible overrides the legacy (pre-redesign, unscoped) .side-nav
     rule's overflow-y:auto -- that rule is otherwise dead code now, but since
     nothing here redeclared the property it would still win for it. Icons are
     always full-size (flex-shrink:0, below) and never scroll now; on a window
     too short to fit all of them, .side (position:sticky) just scrolls with
     the page past its own top:14px anchor rather than clipping internally. */
  position: relative; width: 100%; align-items: center; gap: 4px; overflow-y: visible;
}
.shell .side-nav .nav-indicator {
  position: absolute; left: 9px; right: 9px; top: 0; height: 0; border-radius: var(--radius-sm);
  background: var(--ink); z-index: 0;
  transition: transform .32s cubic-bezier(.22, 1, .36, 1), height .32s cubic-bezier(.22, 1, .36, 1);
}
.shell .side-nav a {
  /* flex-shrink:0 is load-bearing: without it, when .side-nav's max-height (set
     by sizeSidebarNav() in app.html) is tighter than 9 icons' natural height,
     flexbox's default shrink behavior squashes every icon short instead of
     overflowing cleanly into the scrollbar overflow-y:auto already provides --
     icons rendered at a fraction of their real height, badly distorted. */
  position: relative; z-index: 1; flex-shrink: 0; justify-content: center; width: 40px; height: 40px;
  border-radius: var(--radius-sm); padding: 0; color: var(--ink-2); transition: color .2s ease;
}
.shell .side-nav a .ic { font-size: 17px; opacity: 1; display: flex; }
.shell .side-nav a .ic svg { width: 18px; height: 18px; }
.shell .side-nav a .lbl {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.shell .side-nav a.on { background: transparent; color: var(--frame-bg); }
.shell .side-foot {
  width: 100%; margin-top: auto; padding: 0; border-top: none;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.shell .side-foot a {
  border-radius: var(--radius-sm); width: 40px; height: 40px; padding: 0;
  justify-content: center; position: relative; color: var(--ink-2);
}
.shell .side-foot a .ic { font-size: 16px; display: flex; }
.shell .side-foot a .ic svg { width: 17px; height: 17px; }
.shell .side-foot a .lbl {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* bindSideTooltips() (app.html) toggles this on pointerenter/focus and sets
   left/top itself -- position:fixed here only overrides the .lbl sr-only
   rules' position:absolute, the actual coordinates are computed in JS. Scoped
   to desktop widths since the mobile dock already shows .lbl inline, and
   bindSideTooltips() itself skips adding this class there. */
@media (min-width: 641px) {
  .shell .side-nav a .lbl.tip-show, .shell .side-foot a .lbl.tip-show {
    position: fixed; width: auto; height: auto; padding: 6px 10px; margin: 0;
    overflow: visible; clip: auto;
    background: var(--ink); color: var(--plane); font-size: 12px; font-weight: 600;
    border-radius: 6px; box-shadow: var(--shadow-md); z-index: 60; pointer-events: none;
  }
}
.shell .side-foot a .val {
  position: absolute; bottom: -3px; right: -3px; background: var(--brand); color: var(--brand-ink);
  font-size: 9px; font-weight: 800; line-height: 1; padding: 2px 4px; border-radius: 999px;
  min-width: 14px; text-align: center;
}
.shell .side-divider { width: 60%; height: 1px; background: var(--hairline); margin: 4px 0; flex: 0 0 auto; }

.shell .main { flex: 1; min-width: 0; display: block; }
.shell .content { padding: 0; max-width: none; width: auto; }

@media (prefers-reduced-motion: reduce) {
  .shell .side-nav .nav-indicator, .shell .pillnav .nav-indicator { transition: none; }
}

/* ---- mobile: the pillnav drops (the dock below already covers nav), and
   the rail itself becomes a floating, thumb-reach bottom dock -- the same
   switch the reference makes at phone width, instead of just shrinking the
   desktop sidebar in place. */
@media (max-width: 640px) {
  body:has(.shell) { padding: 10px; }
  .shell { border-radius: 20px; padding: 10px; }
  .shell .body-row { flex-direction: column; align-items: stretch; }
  .shell .main { padding-bottom: 76px; }
  /* The trigger pill itself stays avatar+chevron only at this width -- there's
     no room next to the brand pill for the full name too, and showing it did
     exactly that (pushed the pill wide enough to run off the right edge of
     the screen). A pre-redesign, unscoped .topbar .who-info rule (display:none
     at this same breakpoint, further up the file) already hides it here, which
     is fine; the dropdown's own header is spacious and gets the override
     instead, since the same unscoped rule was blanking its name and email too. */
  .shell .who-menu-head .who-info { display: block; }
  .shell .who-menu-head .who-info .mail { display: block; }
  .shell .pillnav { display: none; }

  .shell .side {
    /* align-self:flex-start opts this out of .body-row's align-items:stretch
       (set below, needed so .main fills the width once flex-direction flips
       to column) -- without it, "height:auto" was still resolving against
       the stretched cross-size instead of shrinking to content, turning the
       floating dock into a giant translucent oval covering the page. */
    /* top:auto overrides the desktop rule's position:sticky;top:14px -- left in
       effect otherwise, since this block never re-declares top itself. .side is
       display:flex, so height:auto here resolves to fit-content rather than the
       usual "solve height from top+bottom" block formula, which over-constrains
       the box once both top and bottom are non-auto -- top wins and bottom is
       dropped, pinning the dock to the top of the screen instead of the bottom. */
    position: fixed; top: auto; left: 50%; bottom: max(14px, env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%); flex-direction: row; align-self: flex-start;
    width: auto; height: auto; max-width: calc(100% - 24px);
    flex: none; padding: 6px; border-radius: 999px; overflow-x: auto; z-index: 50;
    box-shadow: 0 18px 40px -16px rgba(20, 16, 10, .35), 0 2px 8px rgba(20, 16, 10, .12);
  }
  /* width:auto overrides the desktop rule's width:100% (sized for the vertical
     column layout) -- left in effect otherwise, which collapsed this to a
     fraction of its content's real width and let the icons overflow into
     .side-foot's space instead of pushing it along in the row. */
  .shell .side-nav { flex-direction: row; gap: 2px; flex: none; width: auto; overflow: visible; }
  .shell .side-nav a {
    flex-direction: column; gap: 3px; width: auto; height: auto; padding: 7px 11px;
    border-radius: 16px; font-size: 9.5px; font-weight: 650; white-space: nowrap; text-align: center;
  }
  .shell .side-nav a .ic { font-size: 17px; }
  .shell .side-nav a .lbl {
    position: static; width: auto; height: auto; padding: 0; margin: 0;
    overflow: visible; clip: auto; white-space: nowrap;
  }
  .shell .side-nav .nav-indicator {
    left: 0; right: auto; top: 4px; height: calc(100% - 8px); border-radius: 16px;
  }
  .shell .side-foot {
    width: auto; margin-top: 0; flex-direction: row; gap: 2px; padding-left: 4px;
  }
  .shell .side-foot a {
    flex-direction: column; gap: 3px; width: auto; height: auto; padding: 7px 9px;
    border-radius: 16px; font-size: 9.5px; font-weight: 650;
  }
  .shell .side-foot a .lbl {
    position: static; width: auto; height: auto; padding: 0; margin: 0;
    overflow: visible; clip: auto; white-space: nowrap;
  }
  .shell .side-foot a .val {
    position: static; background: none; color: var(--ink-muted); font-size: 9px;
    font-weight: 650; padding: 0; margin-left: 2px;
  }
  .shell .side-divider { width: 1px; height: 24px; margin: 0 2px; }
  /* The desktop .theme styling (border-bottom + padding-bottom + margin-bottom)
     is a divider under it for the vertical column layout -- in the row-direction
     mobile dock that extra space sits below the button instead of beside it,
     throwing off align-items:center's vertical centering against its row
     siblings enough that the button visibly hung outside the dock's own rounded
     corner. A right-hand divider is the row equivalent. */
  .shell .side .theme {
    /* margin-left gives the first item in the pill a bit more clearance from
       the dock's own border-radius:999px corner than the dock's own 6px
       padding alone provides -- at this pill height the corner's curve radius
       is close to 40px, so a 36px square-ish button sitting right at that 6px
       inset was only a couple of px inside the curve, close enough to read as
       clipped by it. */
    flex-direction: row; border-bottom: none; padding-bottom: 0; margin-bottom: 0;
    margin-left: 3px; padding-right: 6px; margin-right: 4px; border-right: 1px solid var(--hairline);
  }
}

/* ---- dashboard home: the mockup's 3-column overview row (Collected+nodes /
   stat tiles / chart) plus the credits + linked-devices row underneath. */
.shell .grid3 { display: grid; grid-template-columns: 1.05fr .85fr 1.1fr; gap: 14px; margin-top: 4px; align-items: stretch; }
.shell .col1 { display: flex; flex-direction: column; }
.shell .card-row-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.shell .period-tag {
  font-size: 11px; font-weight: 700; color: var(--ink-2); background: var(--surface-2);
  padding: 4px 10px; border-radius: 999px; white-space: nowrap;
}
.shell .headline-val { font-size: 32px; font-weight: 800; letter-spacing: -.02em; margin-top: 10px; }
.shell .headline-delta { font-size: 12px; font-weight: 700; margin-top: 4px; }
.shell .col1 .btn-row { margin-top: 16px; }
.shell .nodeshead { margin: 18px 0 10px; }
.shell .nodes { display: flex; flex-direction: column; gap: 8px; }
.shell .node { background: var(--surface-2); border-radius: var(--radius-sm); padding: 11px 12px; }
.shell .node .row1 { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.shell .node .vpa { font-family: var(--font-mono); font-size: 12px; font-weight: 600; }
.shell .node .bankic {
  width: 20px; height: 20px; border-radius: 6px; background: var(--surface-3);
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
}
.shell .node .bankic svg { width: 11px; height: 11px; }
.shell .node .row2 { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; }

.shell .status-dot { font-size: 11px; font-weight: 700; display: flex; align-items: center; gap: 5px; }
.shell .status-dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; }
.shell .status-dot.active { color: var(--good); }
.shell .status-dot.active::before { background: var(--good); }
.shell .status-dot.paused { color: var(--critical); }
.shell .status-dot.paused::before { background: var(--critical); }

.shell .headline-delta { display: flex; align-items: center; gap: 4px; }
.shell .headline-delta svg { flex: 0 0 auto; }
.shell .btn-row .btn svg { width: 14px; height: 14px; }

.shell .credit-bar { height: 9px; border-radius: 999px; background: var(--surface-2); overflow: hidden; margin-top: 14px; }
.shell .credit-fill { height: 100%; border-radius: 999px; background: var(--brand); }
.shell .credit-foot { display: flex; justify-content: space-between; font-size: 12px; color: var(--ink-2); margin-top: 8px; }
.shell .credit-foot b { color: var(--ink); font-variant-numeric: tabular-nums; }

.shell .col2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.shell .col2 .tile {
  /* align-items:stretch overrides the base (unscoped) .tile's align-items:flex-start
     -- that rule is an older, row-direction stat-tile component that happens to
     share the "tile" class name, and since nothing here redeclared align-items,
     flex-start kept winning for that property even after flex-direction flipped
     to column. That shrank .top (the "COMPLETED" + checkmark row) down to its own
     content width instead of the tile's full width, leaving justify-content:
     space-between with no room to push the checkmark away from the label. */
  border-radius: var(--radius); padding: 15px; display: flex; flex-direction: column; gap: 10px;
  align-items: stretch;
  background: var(--surface); border: 1px solid var(--hairline); box-shadow: var(--shadow-md);
}
.shell .tile .top { display: flex; align-items: center; justify-content: space-between; }
.shell .tile .top .badge-ic {
  width: 26px; height: 26px; border-radius: 8px; font-size: 13px; flex: 0 0 26px;
  display: flex; align-items: center; justify-content: center; background: var(--neutral-wash); color: var(--ink-2);
}
.shell .tile .lbl { font-size: 11.5px; font-weight: 700; opacity: .85; text-transform: none; }
.shell .tile .val { font-size: 24px; font-weight: 800; letter-spacing: -.01em; }
.shell .tile .foot { font-size: 11px; font-weight: 700; opacity: .9; color: var(--good-text); }
.shell .tile.hero {
  background: linear-gradient(145deg, var(--brand), var(--brand-strong)); border: none; color: #fff;
  grid-column: 1 / -1; position: relative; overflow: hidden;
  /* text-align:left overrides the marketing .hero class's text-align:center --
     an inherited property, so it isn't blocked by position/overflow above being
     redeclared here. Without it, .val/.foot (which never set their own
     text-align) inherit center alignment instead of sitting left like every
     other tile. */
  text-align: left;
}
/* The marketing landing page's .hero::before (a big blurred radial-gradient
   backdrop sized for a full-width hero section) is an unscoped selector, and
   this tile's own "hero" class -- meaning "the featured stat tile", unrelated
   to the landing page -- collides with it by name. Without this, that giant
   900x620px decoration leaks onto this small tile as a stray pale blob. */
.shell .tile.hero::before { content: none; }
.shell .tile.hero .lbl { opacity: .9; }
.shell .tile.hero .foot { color: rgba(255, 255, 255, .9) !important; opacity: 1; }
.shell .tile.hero .top .badge-ic { background: rgba(255, 255, 255, .22); color: #fff; }

.shell .chart { display: flex; align-items: flex-end; gap: 7px; height: 150px; margin-top: 18px; padding: 0 2px; }
.shell .chart .col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 7px; height: 100%; position: relative; justify-content: flex-end; }
.shell .chart .stack { width: 100%; max-width: 20px; display: flex; flex-direction: column-reverse; gap: 2px; }
.shell .chart .seg { width: 100%; border-radius: 3px; }
.shell .chart .seg.ok { background: var(--brand); }
.shell .chart .seg.bad { background: var(--ink); }
.shell .chart .seg.zero { background: var(--surface-3); }
.shell .chart-legend { display: flex; gap: 16px; font-size: 11.5px; font-weight: 600; color: var(--ink-2); margin-top: 4px; }
.shell .chart-legend span { display: flex; align-items: center; gap: 5px; }
.shell .chart-legend i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.shell .chart-axis { display: flex; gap: 3px; border-top: 1px solid var(--hairline); padding-top: 6px; font-size: 11px; color: var(--ink-muted); margin-top: 8px; }
.shell .chart-axis span { flex: 1; text-align: center; overflow: hidden; white-space: nowrap; }

.shell .devicewrap { display: flex; gap: 10px; margin-top: 4px; flex-wrap: wrap; }
.shell .devcard {
  flex: 1; min-width: 150px; border-radius: 16px; padding: 14px; color: #fff; position: relative;
  overflow: hidden; min-height: 72px; display: flex; flex-direction: column; justify-content: space-between;
}
.shell .devcard.a { background: linear-gradient(135deg, #2b2824, #15130f); }
.shell .devcard.b { background: linear-gradient(135deg, var(--brand), var(--brand-strong)); }
.shell .devcard .badge-pill {
  align-self: flex-start; background: rgba(255, 255, 255, .2); font-size: 10px;
  font-weight: 700; padding: 3px 9px; border-radius: 999px;
}
.shell .devcard .name { font-size: 13px; font-weight: 700; margin-top: 8px; display: flex; align-items: center; gap: 7px; }
.shell .devcard .name svg { width: 14px; height: 14px; flex: 0 0 auto; }
.shell .tile .badge-ic svg { width: 13px; height: 13px; }

.shell .section-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin: 28px 4px 14px; flex-wrap: wrap;
}
.shell .section-head h2 { font-size: 18px; }
.shell .section-head .sub { font-size: 12.5px; margin-top: 2px; }

.shell .greet h1 { font-size: clamp(24px, 2.6vw, 30px); letter-spacing: -.02em; }
.shell .greet p { margin: 4px 0 0; color: var(--ink-2); font-size: 13.5px; }
.shell .page-head { margin-top: 18px; }

.shell .avatar {
  width: 36px; height: 36px; border-radius: 50%; background: var(--surface-3);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12.5px;
  flex: 0 0 auto; overflow: hidden;
}
.shell .avatar img { width: 100%; height: 100%; object-fit: cover; }

.shell .status-tabs { display: flex; gap: 4px; flex-wrap: wrap; padding: 0 4px 14px; }
.shell .status-tabs a {
  border: 1px solid var(--hairline); background: var(--surface); color: var(--ink-2);
  padding: 7px 13px; border-radius: 999px; font-size: 12px; font-weight: 700;
}
.shell .status-tabs a:hover { text-decoration: none; background: var(--surface-2); }
.shell .status-tabs a.on { background: var(--ink); color: var(--frame-bg); border-color: var(--ink); }

.shell .table-card .actrow { display: flex; align-items: center; gap: 10px; }
.shell .table-card .acticon {
  width: 28px; height: 28px; border-radius: 8px; display: flex; align-items: center;
  justify-content: center; flex: 0 0 auto;
}
.shell .table-card .acticon svg { width: 13px; height: 13px; }
.shell .table-card .ref { font-family: var(--font-mono); font-weight: 700; font-size: 12px; display: block; }
.shell .table-card .cust { font-weight: 600; color: var(--ink); font-size: 12.5px; }
.shell .table-card .amt { font-variant-numeric: tabular-nums; font-weight: 700; }
.shell .table-card .when { color: var(--ink-2); white-space: nowrap; font-size: 12px; }

.shell .table-card { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  box-shadow: var(--shadow-md); overflow: hidden; }
.shell .table-card .table-wrap { overflow-x: auto; border: none; border-radius: 0; background: none; }
.shell .table-card table { min-width: 0; }

@media (max-width: 980px) {
  .shell .grid3 { grid-template-columns: 1fr; }
}

/* ---- entrance choreography + restrained interaction, transplanted from the
   mockup (shell fade, logo pop, nav pop + indicator pop, rail curtain, card
   shells landing before their contents rise inside them). Short enough that
   htmx-boosted nav re-triggering it on every click stays pleasant, not slow. */
@media (prefers-reduced-motion: no-preference) {
  .shell .card, .shell .tile, .shell .node, .shell .devcard {
    transition: background-color .2s ease, color .2s ease, border-color .2s ease,
      box-shadow .2s ease, transform .18s ease;
  }
  .shell .card:hover { transform: translateY(-2px); box-shadow: 0 1px 2px rgba(20, 16, 10, .05), 0 16px 32px -16px rgba(20, 16, 10, .3); }
  .shell .tile:not(.hero):hover, .shell .node:hover, .shell .devcard:hover { transform: translateY(-2px); }
  .shell .side-nav a:hover:not(.on) { color: var(--ink); }

  .shell .topbar { animation: dashShellIn .5s cubic-bezier(.22, 1, .36, 1) both; }
  @keyframes dashShellIn { from { opacity: 0; transform: scale(.985); } }

  .shell .brand .mark { animation: dashLogoPop .6s cubic-bezier(.34, 1.56, .64, 1) .08s both; }
  @keyframes dashLogoPop { from { opacity: 0; transform: rotate(-120deg) scale(.3); } to { opacity: 1; transform: rotate(0) scale(1); } }
  .shell .brand .name { animation: dashNameWipe .55s cubic-bezier(.22, 1, .36, 1) .22s both; }
  @keyframes dashNameWipe { from { clip-path: inset(0 100% 0 0); transform: translateX(-8px); } to { clip-path: inset(0 0 0 0); transform: translateX(0); } }

  .shell .pillnav { animation: dashNavPop .5s cubic-bezier(.34, 1.56, .64, 1) .3s both; }
  @keyframes dashNavPop { from { opacity: 0; transform: translateY(-10px) scale(.93); } to { opacity: 1; transform: translateY(0) scale(1); } }
  .shell .pillnav .nav-indicator { animation: dashIndPop .45s cubic-bezier(.34, 1.56, .64, 1) .62s both; }
  @keyframes dashIndPop { from { opacity: 0; scale: .4 .8; } to { opacity: 1; scale: 1 1; } }

  .shell .who { animation: dashFadeSlide .45s cubic-bezier(.22, 1, .36, 1) .5s both; }
  @keyframes dashFadeSlide { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: translateX(0); } }

  .shell .side { animation: dashRailCurtain .6s cubic-bezier(.22, 1, .36, 1) .15s both; }
  @keyframes dashRailCurtain { from { opacity: 0; clip-path: inset(0 0 100% 0 round 20px); } to { opacity: 1; clip-path: inset(0 0 0% 0 round 20px); } }

  @keyframes dashCardIn { from { opacity: 0; transform: translateY(20px) scale(.975); } to { opacity: 1; transform: translateY(0) scale(1); } }
  .shell .grid3 > *, .shell .grid-2 > *, .shell .table-card { animation: dashCardIn .6s cubic-bezier(.22, 1, .36, 1) both; }
  .shell .grid3 > *:nth-child(1) { animation-delay: .1s; }
  .shell .grid3 > *:nth-child(2) { animation-delay: .16s; }
  .shell .grid3 > *:nth-child(3) { animation-delay: .22s; }
  .shell .grid-2 > *:nth-child(1) { animation-delay: .26s; }
  .shell .grid-2 > *:nth-child(2) { animation-delay: .3s; }
  .shell .table-card { animation-delay: .34s; }

  @keyframes dashRise { from { opacity: 0; transform: translateY(12px); filter: blur(4px); } to { opacity: 1; transform: translateY(0); filter: blur(0); } }
  .shell .node { animation: dashRise .45s cubic-bezier(.22, 1, .36, 1) both; }
  .shell .nodes .node:nth-child(1) { animation-delay: .4s; }
  .shell .nodes .node:nth-child(2) { animation-delay: .46s; }
  .shell .nodes .node:nth-child(3) { animation-delay: .52s; }

  .shell .col2 .tile { animation: dashTilePop .5s cubic-bezier(.22, 1, .36, 1) both; }
  .shell .tile.hero { animation-delay: .4s; }
  .shell .col2 .tile:nth-child(2) { animation-delay: .46s; }
  .shell .col2 .tile:nth-child(3) { animation-delay: .52s; }
  .shell .col2 .tile:nth-child(4) { animation-delay: .58s; }
  @keyframes dashTilePop { from { opacity: 0; transform: translateY(14px) scale(.95); } to { opacity: 1; transform: translateY(0) scale(1); } }

  .shell .devcard { animation: dashRise .45s cubic-bezier(.22, 1, .36, 1) both; }
  .shell .devicewrap .devcard:nth-child(1) { animation-delay: .48s; }
  .shell .devicewrap .devcard:nth-child(2) { animation-delay: .54s; }

  .shell .status-dot.active::before { animation: dashLivePulse 1.8s infinite 1.1s; }
  @keyframes dashLivePulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--good) 55%, transparent); } 80%, 100% { box-shadow: 0 0 0 7px transparent; } }

  .shell .table-card tbody tr { animation: dashRowRise .45s cubic-bezier(.22, 1, .36, 1) both; }
  .shell .table-card tbody tr:nth-child(1) { animation-delay: .5s; }
  .shell .table-card tbody tr:nth-child(2) { animation-delay: .53s; }
  .shell .table-card tbody tr:nth-child(3) { animation-delay: .56s; }
  .shell .table-card tbody tr:nth-child(4) { animation-delay: .59s; }
  .shell .table-card tbody tr:nth-child(5) { animation-delay: .62s; }
  .shell .table-card tbody tr:nth-child(6) { animation-delay: .65s; }
  @keyframes dashRowRise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

  @keyframes dashGrowBar { from { transform: scaleY(0); } to { transform: scaleY(1); } }
  .shell .chart .stack { transform-origin: bottom; animation: dashGrowBar .55s cubic-bezier(.22, 1, .36, 1) both; }
  .shell .chart .col:nth-child(1) .stack { animation-delay: .42s; } .shell .chart .col:nth-child(2) .stack { animation-delay: .44s; }
  .shell .chart .col:nth-child(3) .stack { animation-delay: .46s; } .shell .chart .col:nth-child(4) .stack { animation-delay: .48s; }
  .shell .chart .col:nth-child(5) .stack { animation-delay: .5s; } .shell .chart .col:nth-child(6) .stack { animation-delay: .52s; }
  .shell .chart .col:nth-child(n+7) .stack { animation-delay: .54s; }
}

