.dashboard-page {
  min-height: 100vh;
}

.dashboard-shell {
  position: relative;
  z-index: 1;
  width: min(1220px, 100%);
  margin: 0 auto;
  padding: 118px clamp(18px, 4vw, 52px) 72px;
}

.dash-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
  gap: clamp(24px, 5vw, 68px);
  align-items: end;
  padding-bottom: 36px;
  border-bottom: 1px solid var(--line);
}

.dash-hero h1 {
  max-width: 720px;
  margin-bottom: 16px;
  font-size: clamp(54px, 8vw, 94px);
  line-height: .94;
}

.dash-lede {
  max-width: 620px;
  margin: 0;
  color: var(--muted);
  font-size: clamp(17px, 1.6vw, 21px);
}

.dash-signin-card,
.dash-section,
.dash-rail,
.account-card,
.token-card,
.dash-tier {
  border: 1px solid var(--panel-line);
  background: rgba(255, 250, 240, .78);
  box-shadow: 0 16px 44px rgba(72, 44, 20, .08);
}

.dash-signin-card {
  padding: 24px;
  border-radius: 18px;
}

.signin-title {
  margin: 0 0 6px;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 24px;
}

.dash-signin-card p:not(.signin-title) {
  margin: 0 0 18px;
  color: var(--muted);
}

.google-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 46px;
  padding: 0 16px;
  border-radius: 12px;
  background: var(--ink);
  color: #fff8ee;
  font-weight: 700;
}

.google-button span {
  display: inline-flex;
  align-items: center;
  color: inherit;
}

.mock-link {
  display: inline-block;
  margin-top: 12px;
  color: var(--terracotta-deep);
  font-size: 13px;
  font-weight: 700;
}

.dashboard-grid {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: clamp(22px, 4vw, 48px);
  margin-top: 36px;
}

.dash-rail {
  position: sticky;
  top: 92px;
  align-self: start;
  padding: 14px;
  border-radius: 16px;
}

.dash-rail a {
  display: block;
  padding: 10px 12px;
  border-radius: 10px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 700;
}

.dash-rail a:hover {
  background: rgba(193, 97, 60, .08);
  color: var(--terracotta-deep);
}

.dash-main {
  display: grid;
  gap: 18px;
  min-width: 0;
}

.dash-section {
  padding: clamp(22px, 3.5vw, 34px);
  border-radius: 18px;
}

.section-kicker {
  margin-bottom: 20px;
}

.section-kicker h2 {
  margin-bottom: 8px;
}

.section-kicker p:not(.eyebrow) {
  max-width: 680px;
  margin: 0;
  color: var(--muted);
}

.setup-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 14px;
}

.setup-list li {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--panel-line);
}

.setup-list li:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.setup-list li > span {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(150deg, var(--terracotta), var(--gold));
  color: #fff8ee;
  font-weight: 700;
  font-size: 13px;
}

.setup-list h3 {
  margin-bottom: 4px;
}

.setup-list p,
.card-note,
.empty-token,
.billing-note {
  color: var(--muted);
  margin: 0;
}

.dash-code {
  position: relative;
  margin: 10px 0 10px;
  border-radius: 12px;
  background: #2a2018;
  overflow: hidden;
  box-shadow: 0 12px 28px rgba(72, 44, 20, .12);
}

.dash-code pre {
  margin: 0;
  padding: 16px 78px 16px 16px;
  overflow-x: auto;
  color: #f3e9d8;
  font: 13px/1.7 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.dash-copy {
  position: absolute;
  top: 10px;
  right: 10px;
  height: 30px;
  min-width: 56px;
  border: 1px solid rgba(255, 250, 240, .14);
  border-radius: 8px;
  background: rgba(255, 250, 240, .1);
  color: rgba(255, 250, 240, .86);
  font: 700 11px/1 var(--font-body);
  cursor: pointer;
  transition: background .15s ease;
}

.dash-copy:hover {
  background: rgba(255, 250, 240, .2);
}

.dash-copy.is-copied {
  background: var(--gold);
  border-color: transparent;
  color: #2a2018;
}

.account-card,
.token-card {
  padding: 22px;
  border-radius: 16px;
  background: var(--panel);
}

.account-head,
.token-card-head,
.tier-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}

.account-head h3,
.token-card h3 {
  margin-bottom: 4px;
}

.account-head p,
.token-card p {
  margin: 0;
  color: var(--muted);
}

.plan-badge {
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--bg-2);
  color: var(--wood-deep);
  font-size: 12px;
  font-weight: 700;
}

.usage-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 18px;
}

.usage-grid div {
  padding: 14px;
  border: 1px solid var(--panel-line);
  border-radius: 12px;
  background: rgba(246, 236, 218, .48);
}

.usage-grid span {
  display: block;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  margin-bottom: 4px;
}

.usage-grid strong {
  color: var(--ink);
  font-size: 14px;
}

.token-card + .token-card {
  margin-top: 12px;
}

.small-action {
  flex: 0 0 auto;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--terracotta);
  color: #fff8ee;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: background .15s ease, transform .1s ease;
}

.small-action:hover {
  background: var(--terracotta-deep);
}

.small-action:active {
  transform: translateY(1px);
}

/* Not `wait`: this is disabled both while a publish or launch is in flight and
   while the form has an error on screen. A spinner pointer on the second case
   reads as "the button is busy" when the truth is "fix the line above first".
   `not-allowed` is honest about both, and matches .signed-tier's disabled. */
.small-action:disabled {
  background: var(--dim);
  cursor: not-allowed;
  transform: none;
}

.empty-token {
  margin-top: 16px;
  padding: 18px;
  border: 1px dashed rgba(90, 62, 38, .24);
  border-radius: 12px;
  text-align: center;
}

.dash-tier-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.dash-tier {
  display: flex;
  flex-direction: column;
  padding: 20px;
  border-radius: 16px;
  background: var(--panel);
}

.dash-tier.current {
  border-color: var(--terracotta);
  box-shadow: 0 0 0 1px var(--terracotta), 0 18px 48px rgba(193, 97, 60, .12);
}

.tier-top span {
  color: var(--terracotta-deep);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
}

.tier-price {
  margin: 8px 0 12px;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 700;
}

.tier-price span {
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
}

.dash-tier ul {
  flex: 1;
  padding: 0;
  margin: 0 0 16px;
  list-style: none;
}

.dash-tier li {
  padding: 6px 0;
  border-top: 1px solid var(--panel-line);
  color: var(--muted);
  font-size: 13.5px;
}

.dash-tier a {
  display: grid;
  place-items: center;
  min-height: 42px;
  border-radius: 10px;
  background: var(--bg-2);
  color: var(--ink);
  font-weight: 700;
}

.dash-tier:not(.current) a {
  background: var(--terracotta);
  color: #fff8ee;
}

/* The note is centred under the signed-out plans grid, where it sits beneath a
   row of cards — but NOT under Change plan's cancel row, which is left-aligned
   text beside a button, where a centred line reads as misaligned. One class
   carrying both intents is how it ended up centred in both places
   both places. */
.billing-note {
  margin-top: 16px;
  font-size: 13px;
}

#plans .billing-note {
  text-align: center;
}

@media (max-width: 980px) {
  .dash-hero,
  .dashboard-grid {
    grid-template-columns: 1fr;
  }

  .dash-rail {
    position: relative;
    top: auto;
    display: flex;
    gap: 8px;
    overflow-x: auto;
  }

  .dash-rail a {
    white-space: nowrap;
  }

  .dash-tier-grid,
  .usage-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .dashboard-shell {
    padding-inline: 18px;
  }

  .dash-hero h1 {
    font-size: clamp(42px, 13vw, 58px);
  }

  .dash-tier-grid,
  .usage-grid {
    grid-template-columns: 1fr;
  }

  .account-head,
  .token-card-head {
    display: grid;
  }

  .dash-code pre {
    padding-right: 70px;
    font-size: 12.5px;
  }
}

/* ---------- signed-in content faithful mock ---------- */
.signed-shell {
  position: relative;
  z-index: 1;
  width: min(1220px, 100%);
  margin: 0 auto;
  padding: 104px clamp(18px, 4vw, 52px) 72px;
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: clamp(22px, 4vw, 48px);
}

.signed-toc {
  position: sticky;
  top: 92px;
  align-self: start;
  padding: 14px;
  border: 1px solid var(--panel-line);
  border-radius: 16px;
  background: rgba(255, 250, 240, .78);
  box-shadow: 0 14px 40px rgba(72, 44, 20, .08);
}

.toc-identity {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 2px 4px 14px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}

.toc-identity strong {
  display: block;
  font-size: 14px;
  color: var(--ink);
}

.plan-chip {
  display: inline-block;
  margin-top: 3px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bg-2);
  color: var(--wood-deep);
  font-size: 11px;
  font-weight: 700;
}

.toc-links {
  display: grid;
  gap: 2px;
}

.signed-toc a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  border-left: 2px solid transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 700;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.signed-toc a svg {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  opacity: .62;
}

.signed-toc a:hover {
  background: rgba(193, 97, 60, .08);
  color: var(--terracotta-deep);
}

.signed-toc a.is-active {
  background: rgba(193, 97, 60, .1);
  border-left-color: var(--terracotta);
  color: var(--terracotta-deep);
}

.signed-toc a.is-active svg {
  opacity: 1;
}

.signed-main {
  min-width: 0;
  display: grid;
  gap: 38px;
}

.signed-section {
  scroll-margin-top: 90px;
  /* Sections share one grid column, and a grid item's automatic minimum size
     is its min-content — so the widest section (the tokens table, when it is
     unfolded) stretched the column for ALL of them, past the viewport. The
     page then scrolled sideways, and following the #tokens link scrolled it
     there, which read as the sidebar losing its padding. */
  min-width: 0;
}

.signed-head {
  margin-bottom: 18px;
}

.signed-head h1,
.signed-head h2 {
  margin-bottom: 8px;
}

.signed-head p:not(.eyebrow) {
  max-width: 760px;
  margin: 0;
  color: var(--muted);
}

.plan-panel,
.manual-setup,
.token-panel,
.machine-panel {
  border: 1px solid var(--panel-line);
  border-radius: 18px;
  background: var(--panel);
  box-shadow: 0 16px 44px rgba(72, 44, 20, .08);
}

.plan-panel {
  padding: 24px;
}

.plan-panel-head {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: center;
  margin-bottom: 18px;
}

.plan-panel-head h2 {
  font-size: 24px;
}

.plan-meters {
  display: grid;
  gap: 18px;
}

.plan-meter-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 8px;
  font-size: 13.5px;
}

.plan-meter-head span {
  color: var(--muted);
  font-weight: 600;
}

.plan-meter-head strong {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.meter-track {
  position: relative;
  height: 10px;
  border-radius: 999px;
  background: var(--bg-2);
  box-shadow: inset 0 1px 3px rgba(72, 44, 20, .18);
  overflow: hidden;
}

.meter-track::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, transparent calc(25% - .5px), rgba(72, 44, 20, .16) calc(25% - .5px), rgba(72, 44, 20, .16) calc(25% + .5px), transparent calc(25% + .5px)),
    linear-gradient(90deg, transparent calc(50% - .5px), rgba(72, 44, 20, .16) calc(50% - .5px), rgba(72, 44, 20, .16) calc(50% + .5px), transparent calc(50% + .5px)),
    linear-gradient(90deg, transparent calc(75% - .5px), rgba(72, 44, 20, .16) calc(75% - .5px), rgba(72, 44, 20, .16) calc(75% + .5px), transparent calc(75% + .5px));
  pointer-events: none;
}

.meter-fill {
  position: relative;
  height: 100%;
  min-width: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--terracotta), var(--gold));
  transition: width .5s ease;
}

/* Boundary tick on a meter whose scale extends past the plan's included
   amount (traffic credit): marks where the monthly quota ends. The tick
   is a button (sibling of the track — its overflow would clip the bubble)
   with a generous hit area; the explainer bubble opens on hover, keyboard
   focus, or tap (Safari doesn't focus buttons on tap, so tap toggles
   .tip-open from the click handler). */
.meter-wrap {
  position: relative;
}

.meter-mark {
  position: absolute;
  top: -4px;
  height: 18px;
  width: 28px;
  margin-left: -14px;
  background: none;
  border: 0;
  padding: 0;
  cursor: help;
  -webkit-tap-highlight-color: transparent;
}

.meter-mark::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: rgba(72, 44, 20, .55);
}

.meter-mark-tip {
  position: absolute;
  bottom: calc(100% + 7px);
  width: max-content;
  max-width: min(250px, 72vw);
  padding: 8px 11px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--bg);
  font-size: 12.5px;
  line-height: 1.45;
  text-align: left;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s ease;
  z-index: 6;
  box-shadow: 0 4px 14px rgba(72, 44, 20, .3);
}

.meter-mark.tip-left .meter-mark-tip { left: 50%; margin-left: -10px; }
.meter-mark.tip-right .meter-mark-tip { right: 50%; margin-right: -10px; }

.meter-mark:hover .meter-mark-tip,
.meter-mark:focus-visible .meter-mark-tip,
.meter-mark.tip-open .meter-mark-tip {
  opacity: 1;
}

/* meter-info reuses the meter-mark bubble and its tap-to-toggle behavior,
   but sits inline next to a meter label as a small "?" ring instead of a
   tick on the track. */
.meter-mark.meter-info {
  position: relative;
  top: auto;
  width: 16px;
  height: 16px;
  margin-left: 2px;
  vertical-align: text-bottom;
}

.meter-mark.meter-info::before {
  content: "?";
  position: static;
  display: block;
  width: 16px;
  height: 16px;
  margin: 0;
  border-radius: 50%;
  background: rgba(72, 44, 20, .12);
  color: var(--wood-deep);
  font: 700 10.5px/16px var(--font-body);
  text-align: center;
}

.plan-limit-note {
  margin: 20px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--panel-line);
  color: var(--muted);
  font-size: 13.5px;
}

/* A meter's own breakdown, tucked under its bar. Deliberately without
   .plan-limit-note's border-top: that divider detached the RAM split from the
   RAM bar and made it read as the VOLUME pool's breakdown. */
.meter-breakdown {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 13px;
}

.plan-limit-note strong {
  color: var(--ink);
}

.signed-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  width: min(760px, 100%);
}

.signed-steps li {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 18px;
  padding: 18px 0;
  border-top: 1px solid var(--line);
}

.signed-steps li > span {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--bg-2);
  color: var(--terracotta-deep);
  font-weight: 700;
}

.signed-steps li.done > span {
  position: relative;
  background: var(--sage-wash);
  color: var(--sage-deep);
  font-size: 0;
}

.signed-steps li.done > span::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 6px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  /* Center the glyph's visual mass, not its bounding box: the stroke of a
     rotated L sits low-left, so true center needs this up-right bias. */
  transform: translate(-44%, -72%) rotate(-45deg);
}

.signed-steps h3 {
  margin-bottom: 4px;
}

.signed-steps p,
.manual-setup p,
.machine-panel p,
.secure-note {
  margin: 0;
  color: var(--muted);
}

.signed-steps p + p {
  margin-top: 8px;
}

.signed-steps a,
.manual-setup a {
  color: var(--terracotta-deep);
  font-weight: 700;
}

.ghost-action.inline {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  margin-top: 10px;
  padding: 0 12px;
}

.manual-setup {
  margin-top: 22px;
  overflow: hidden;
}

.manual-setup summary {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  padding: 16px 20px;
  color: var(--wood-deep);
  font-weight: 700;
  list-style: none;
  transition: background .15s ease;
}

.manual-setup summary::-webkit-details-marker {
  display: none;
}

/* Direct child, not descendant: the no-browser guide is a details INSIDE
   the tokens details, and a descendant selector let the outer one's [open]
   state rotate the inner chevron — which then never moved on its own
   toggle, because it was never following its own state. */
.manual-setup > summary::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .2s ease;
}

.manual-setup[open] > summary::before {
  transform: rotate(45deg);
}

.manual-setup summary:hover {
  background: rgba(193, 97, 60, .06);
}

.manual-setup > div {
  padding: 0 20px 20px;
  display: grid;
  gap: 14px;
}

.manual-setup h3,
.machine-panel h3 {
  font-size: 18px;
}

/* The no-browser guide sits inside the tokens panel, so it is quieter than
   the section around it: smaller summary, no drop shadow competing with the
   card it lives in. It is a footnote people can open, not a second heading. */
.browser-help {
  box-shadow: none;
  background: transparent;
}

.browser-help > summary {
  font-size: 15px;
  padding: 12px 14px;
}

.browser-help > div {
  padding: 0 14px 14px;
}

/* The four steps for signing in a machine with no browser. Numbers stay
   visible on purpose: this is the one flow a non-technical person follows
   on an unfamiliar machine, so "which step am I on" has to be obvious. */
.token-steps {
  margin: 0;
  padding-left: 22px;
  display: grid;
  gap: 12px;
  color: var(--muted);
}

.token-steps li::marker {
  color: var(--wood-deep);
  font-weight: 700;
}

.token-steps .dash-code {
  margin-top: 8px;
}

/* Anything following the steps sits in the same text column they do, so a
   code block below the list lines up with the one inside it. Flush left
   against the panel, the wider block reads as having broken out of the
   list. 22px matches .token-steps padding-left. */
.token-steps-note {
  padding-left: 22px;
  display: grid;
  gap: 12px;
}

.token-panel,
.machine-panel {
  padding: 22px;
}

.token-panel + .machine-panel {
  margin-top: 16px;
}

.token-panel-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 16px;
}

.token-panel-head > span {
  color: var(--muted);
  font-weight: 700;
}

.token-list-table {
  overflow: hidden;
  border: 1px solid var(--panel-line);
  border-radius: 14px;
  background: rgba(246, 236, 218, .36);
}

.token-head,
.token-row {
  display: grid;
  grid-template-columns: minmax(160px, 1fr) 108px 108px 108px auto;
  gap: 14px;
  align-items: center;
  padding: 13px 14px;
}

.token-head {
  color: var(--muted);
  background: rgba(239, 224, 199, .58);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
}

.token-row {
  border-top: 1px solid var(--panel-line);
}

.token-row code {
  color: var(--muted);
}

.token-row button {
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid rgba(193, 97, 60, .26);
  border-radius: 9px;
  background: transparent;
  color: var(--terracotta-deep);
  font-weight: 700;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}

.token-row button:hover {
  background: rgba(193, 97, 60, .08);
  border-color: rgba(193, 97, 60, .4);
}

.token-row button:disabled {
  color: var(--dim);
  border-color: var(--panel-line);
  background: transparent;
  cursor: wait;
}

.secure-note {
  margin-top: 14px;
  font-size: 13px;
}

.machine-panel {
  display: grid;
  gap: 12px;
}

.signed-tier-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

.signed-tier {
  display: flex;
  flex-direction: column;
  padding: 22px;
  border: 1px solid var(--panel-line);
  border-radius: 16px;
  background: var(--panel);
  box-shadow: 0 16px 44px rgba(72, 44, 20, .08);
}

.signed-tier.current {
  border-color: var(--terracotta);
  box-shadow: 0 0 0 1px var(--terracotta), 0 18px 48px rgba(193, 97, 60, .12);
}

.signed-tier ul {
  flex: 1;
  padding: 0;
  margin: 0 0 18px;
  list-style: none;
}

.signed-tier li {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 0;
  border-top: 1px solid var(--panel-line);
  color: var(--muted);
  font-size: 14px;
}

.signed-tier li:before {
  content: "";
  flex: 0 0 auto;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--sage-deep);
  border-bottom: 2px solid var(--sage-deep);
  transform: rotate(-45deg) translate(1px, -1px);
}

.signed-tier button {
  min-height: 44px;
  border: 0;
  border-radius: 10px;
  background: var(--terracotta);
  color: #fff8ee;
  font-weight: 700;
  cursor: pointer;
  transition: background .15s ease, transform .1s ease;
}

.signed-tier button:hover:not(:disabled) {
  background: var(--terracotta-deep);
}

.signed-tier button:active:not(:disabled) {
  transform: translateY(1px);
}

.signed-tier button:disabled {
  background: var(--bg-2);
  color: var(--dim);
  cursor: not-allowed;
}

.app-user-actions {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--muted);
  font-size: 14px;
}

.logout-action {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: 0 14px;
  border: 1px solid var(--panel-line);
  border-radius: 10px;
  background: rgba(255, 250, 240, .56);
  color: var(--wood-deep);
  font-weight: 700;
  transition: background .15s ease;
}

.logout-action:hover {
  background: rgba(255, 250, 240, .9);
}

@media (max-width: 980px) {
  .signed-shell {
    display: block;
  }

  .signed-toc {
    position: relative;
    top: auto;
    display: flex;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    margin-bottom: 22px;
  }

  .toc-identity {
    flex: 0 0 auto;
    padding: 2px 12px 2px 2px;
    margin-bottom: 0;
    border-bottom: 0;
    border-right: 1px solid var(--line);
  }

  .toc-links {
    flex: 1 1 auto;
    display: flex;
    gap: 4px;
  }

  .signed-toc a {
    white-space: nowrap;
    border-left: 0;
    border-bottom: 2px solid transparent;
  }

  .signed-toc a.is-active {
    border-left-color: transparent;
    border-bottom-color: var(--terracotta);
  }

  .signed-tier-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .app-user-actions span {
    display: none;
  }
}

@media (max-width: 640px) {
  .signed-shell {
    padding-inline: 18px;
  }

  .toc-identity strong,
  .toc-identity .plan-chip {
    display: none;
  }

  .token-panel-head {
    display: grid;
  }

  .token-head {
    display: none;
  }

  .token-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .signed-tier-grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- shared identity + modal + toast ---------- */
.avatar {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: linear-gradient(150deg, var(--terracotta), var(--gold));
  color: #fff8ee;
  font-family: var(--font-display);
  font-weight: 700;
}

.ghost-action {
  min-height: 38px;
  padding: 0 13px;
  border: 1px solid var(--panel-line);
  border-radius: 10px;
  background: rgba(255, 250, 240, .56);
  color: var(--wood-deep);
  font-weight: 700;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}

.ghost-action:hover {
  background: rgba(255, 250, 240, .95);
  border-color: rgba(193, 97, 60, .3);
  color: var(--terracotta-deep);
}

dialog.mock-modal {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  border: 0;
  color: inherit;
}
dialog.mock-modal:not([open]) { display: none; }
dialog.mock-modal::backdrop { background: transparent; }

.mock-modal {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: none;
  place-items: center;
  padding: 20px;
  background: rgba(54, 35, 20, .38);
  backdrop-filter: blur(8px);
}

.mock-modal.is-open {
  display: grid;
}

.mock-modal-card {
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
  overscroll-behavior: contain;
  position: relative;
  width: min(420px, 100%);
  padding: 24px;
  border: 1px solid var(--panel-line);
  border-radius: 18px;
  background: var(--panel);
  box-shadow: var(--shadow);
}

.modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  /* Flex-centre the glyph: as a plain block button the × inherited the UA
     button padding (1px 6px) and sat high and left of the circle's centre,
     which is the lopsided cross an owner reported. */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--panel-line);
  border-radius: 50%;
  background: var(--bg);
  color: var(--wood-deep);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.modal-close:hover {
  border-color: rgba(193, 97, 60, 0.4);
  color: var(--terracotta-deep);
}

/* The heading shares the card's top padding row with the close button, so it
   must not run under it: reserve the button's lane. */
.mock-modal-card > h2:first-of-type,
.mock-modal-card > h3:first-of-type {
  margin-top: 0;
  padding-right: 40px;
}

.mock-modal-card p,
.mock-modal-card label {
  color: var(--muted);
}

.mock-modal-card label,
.mock-modal-card input {
  display: block;
  width: 100%;
}

.mock-modal-card input {
  height: 44px;
  margin: 8px 0 16px;
  padding: 0 12px;
  border: 1px solid var(--panel-line);
  border-radius: 10px;
  background: #fffaf0;
  color: var(--ink);
  font: inherit;
}

/* One-time reveal password modal */
.pw-modal-card { width: min(460px, 100%); }
.pw-modal-title { margin: 0 0 6px; font-size: 18px; }
.pw-modal-lead { color: var(--muted); margin: 0 0 16px; line-height: 1.45; }
.pw-modal-row { display: flex; gap: 8px; align-items: stretch; margin: 0 0 16px; }
.mock-modal-card input.pw-modal-value {
  display: block; flex: 1 1 auto; width: auto; min-width: 0; margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px; letter-spacing: .04em;
}
.pw-reveal-btn, .pw-modal-eye, .pw-modal-copy, .pw-modal-done {
  cursor: pointer; font: inherit; border-radius: 10px; white-space: nowrap;
  border: 1px solid var(--panel-line); background: var(--bg); color: var(--ink);
  padding: 9px 14px;
}
.pw-modal-eye, .pw-modal-copy { height: 44px; }
.pw-reveal-btn, .pw-modal-done { background: var(--wood-deep); color: #fff; border-color: var(--wood-deep); }
.pw-modal-done { padding: 10px 22px; }
.pw-modal-done:disabled { opacity: .45; cursor: not-allowed; }
.pw-modal-check { display: flex; align-items: center; gap: 9px; color: var(--ink); margin: 0 0 18px; cursor: pointer; }
.mock-modal-card input.pw-modal-saved {
  display: inline-block; width: 18px; height: 18px; flex: none; margin: 0; padding: 0;
}
.pw-modal-actions { display: flex; justify-content: flex-end; }


.toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 90;
  transform: translateY(20px);
  opacity: 0;
  padding: 12px 15px;
  border-radius: 12px;
  background: var(--ink);
  color: #fff8ee;
  font-weight: 700;
  transition: opacity .18s ease, transform .18s ease;
}

.toast.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* --- Live-dashboard states (wired against the API in dashboard/app.js) --- */

/* Elements toggled with the `hidden` attribute must stay hidden even when a
   layout rule below gives them a display value. */
[hidden] {
  display: none !important;
}

.over-pool-banner {
  border: 1px solid var(--terracotta);
  background: rgba(193, 97, 60, .1);
  color: var(--terracotta-deep);
  border-radius: 14px;
  padding: 14px 18px;
  margin-bottom: 18px;
  font-size: 14px;
  line-height: 1.5;
}

.new-token-display {
  border: 1px solid var(--sage);
  background: var(--sage-wash);
  border-radius: 14px;
  padding: 14px 16px;
  margin-bottom: 16px;
}

.new-token-display p {
  color: var(--sage-deep);
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 10px;
}

.new-token-display pre {
  word-break: break-all;
  white-space: pre-wrap;
}

.token-empty {
  color: var(--dim);
  font-size: 14px;
}

/* The landing page's `.pricing-note` under its own card grid, in dashboard
   dress. Same job on the same kind of grid, so it reads the same way. */
.tier-grid-note {
  margin: 22px auto 0;
  max-width: 640px;
  text-align: center;
  color: var(--dim);
  font-size: 13.5px;
  line-height: 1.5;
}

.plan-action-msg {
  margin-top: 16px;
  font-size: 14px;
  line-height: 1.5;
}

.plan-action-msg.is-error {
  color: var(--terracotta-deep);
}

.plan-action-msg.is-success {
  color: var(--sage-deep);
}

.modal-error {
  color: var(--terracotta-deep);
  font-size: 13px;
  margin-top: 8px;
}

/* Button and its one line of consequence, side by side. The grid that used to
   live here existed only to align a second sentence — the egress note — which
   now sits in the plan card with the traffic meter it describes, so the simple
   row is back. Below 640px the button takes its own full-width row: a 155px
   button beside 13px copy on a phone leaves the text too narrow to read. */
.cancel-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--panel-line);
}

@media (max-width: 640px) {
  .cancel-row {
    align-items: stretch;
  }

  .cancel-row > #cancel-plan {
    width: 100%;
  }
}

.cancel-row span {
  color: var(--muted);
  font-size: 13px;
}

/* Expiry picker in the create-token modal. The bottom margin matches the
   name input's: without it the submit button sits flush against the
   dropdown and reads as part of the Expires field rather than the action
   that closes the form. */
.mock-modal-card select {
  width: 100%;
  margin: 6px 0 16px;
  padding: 10px 12px;
  border: 1px solid var(--panel-line);
  border-radius: 10px;
  background: var(--panel);
  color: var(--ink);
  font: inherit;
}

.token-expiry-soon {
  color: var(--terracotta-deep);
  font-weight: 700;
}

.token-expiry-never {
  color: var(--terracotta-deep);
}

/* ------------------------------------------------------------- agents */

.agent-card { margin-bottom: 1.1rem; }
.agent-card-head { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.agent-card-icon { width: 28px; height: 28px; border-radius: 7px; }
.agent-card-head h3 { margin: 0; font-family: var(--font-display); font-size: 1.3rem; }
.agent-card-summary { margin: 0.4rem 0 1.1rem; color: var(--muted); max-width: 46rem; }
.agent-name-hint { margin: 0.55rem 0 1rem; color: var(--dim); font-size: 0.85rem; max-width: 46rem; }
.agent-chip.is-ok { background: var(--sage-wash); border-color: transparent; color: var(--sage-deep); }
.agent-chip.is-bad { background: rgba(193, 97, 60, 0.12); border-color: transparent; color: var(--terracotta-deep); }
/* Running, but the checks left a finding: amber, between the green of a
   clean run and the red of a failed one, and the note under the row says
   what the finding is. */
.agent-chip.is-warn { background: rgba(217, 164, 65, 0.22); border-color: transparent; color: #7a5613; }
.agent-warn-note { border-left: 3px solid var(--gold); padding-left: 0.5rem; }
/* The address is the row's payoff — clip it rather than let it break mid
   token across two lines, which reads as a rendering bug. */
.agent-url { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Remove is the one destructive action in a list about keeping agents
   alive; it must not be the most eye-catching thing in the row. */
#agent-rows .project-actions button.is-danger { color: var(--muted); }
#agent-rows .project-actions button.is-danger:hover { color: var(--terracotta-deep, #b3402a); border-color: currentColor; }

/* Traffic top-up row under the bandwidth meter: quiet disclosure + presets. */
.topup-traffic { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; font-size: 0.82rem; color: var(--muted, #8a8577); }
.topup-traffic .small-action { padding: 3px 10px; font-size: 0.8rem; }
.topup-traffic-note { color: #b0543d; }
.topup-traffic-copy { margin: 4px 0 0; font-size: 0.78rem; color: var(--muted, #8a8577); }
.topup-traffic-team { margin: 2px 0 0; font-size: 0.78rem; color: var(--muted, #8a8577); font-style: italic; }
.topup-traffic-set { display: contents; }
.topup-traffic-set[hidden] { display: none; }
.meter-fill.meter-warn { background: #b0543d; }

/* Buttons that sit inside a sentence and act like links. The class was in
   use with no rule behind it, so every one of them rendered as a raw
   platform button mid-paragraph — including the one that lets a second
   browser into an agent's control panel. */
.linklike {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--link, #2f6f4f);
  text-decoration: underline;
  cursor: pointer;
}
.linklike:disabled { color: var(--muted, #8a8577); cursor: default; text-decoration: none; }

/* What a button just did, kept beside it. Written into the button's own label
   it vanished with the label, which read as nothing having happened. */
.action-note { font-size: 0.85em; color: var(--muted, #8a8577); }


/* ---------------------------------------------------------------- domains
   The custom-domain dialog. Wider than the token dialog: a DNS record has
   three fields and each must be readable and copyable on its own line. */
.domain-card { width: min(560px, 100%); }
.domain-card .eyebrow { margin-bottom: 4px; }
.domain-card #domain-body { margin: 12px 0; }
.domain-hint { font-size: 0.88rem; line-height: 1.5; color: var(--muted); margin: 8px 0 0; }
.domain-hint code, .domain-record code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86rem;
  word-break: break-all;
}
.domain-record {
  display: grid;
  gap: 8px;
  padding: 12px 14px;
  margin: 10px 0;
  border: 1px solid var(--panel-line);
  border-radius: 12px;
  background: var(--bg);
}
.domain-field {
  display: grid;
  grid-template-columns: 4.2em 1fr auto;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.domain-field-label { font-size: 0.8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.domain-record-note { font-size: 0.82rem; color: var(--muted); }
/* Its own look: .dash-copy is drawn for a dark code block and disappears
   on the cream record card. */
.domain-copy {
  position: static;
  transform: none;
  padding: 4px 10px;
  font-size: 0.8rem;
  border: 1px solid var(--panel-line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--wood-deep);
  cursor: pointer;
}
.domain-copy:hover { border-color: var(--wood-deep); }
.domain-copy.is-copied { background: var(--sage-wash); color: var(--sage-deep); border-color: transparent; }
.domain-hint code { white-space: nowrap; }
.domain-status {
  margin: 8px 0 0;
  font-size: 0.9rem;
  color: var(--muted);
  padding-left: 18px;
  position: relative;
}
.domain-status::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.45em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--sage);
}
.domain-status.is-busy::before { animation: domain-pulse 1s ease-in-out infinite; }
@keyframes domain-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
.domain-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.domain-foot { font-size: 0.82rem; color: var(--muted); margin: 12px 0 0; }

/* Domain lines under an app row: name, plain-words state, two small actions. */
.project-domains { flex-basis: 100%; display: grid; gap: 6px; }
.project-domains:empty { display: none; }
.domain-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: 0.9rem; }
.domain-name { font-weight: 600; word-break: break-all; }
.domain-chip {
  font-size: 0.78rem;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--panel-line);
  color: var(--muted);
}
.domain-chip.is-live { background: var(--sage-wash); color: var(--sage-deep); border-color: transparent; }
.domain-chip.is-todo { border-style: dashed; }
.domain-mini {
  font-size: 0.8rem;
  padding: 3px 9px;
  border: 1px solid var(--panel-line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--wood-deep);
  cursor: pointer;
}
.domain-mini.is-danger { color: var(--muted); }
.domain-mini.is-danger:hover { color: var(--terracotta-deep, #b3402a); border-color: currentColor; }
@media (max-width: 720px) {
  .domain-field { grid-template-columns: 1fr; }
  .domain-field .domain-copy { justify-self: start; }
}
/* The panel link must read as a link, not as more hint text. */
.domain-provider a {
  color: var(--terracotta-deep, #a34c2b);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.domain-provider a:hover { color: var(--wood-deep); }


/* Project type at a glance: a small pill before the name. App and Site get
   distinct tones from the warm palette so the two read apart instantly. */
.type-badge {
  flex-shrink: 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid transparent;
}
.type-badge.type-app { background: rgba(90, 62, 38, 0.10); color: var(--wood-deep); }
.type-badge.type-site { background: var(--sage-wash); color: var(--sage-deep); }

/* Domain Connect one-click: a prominent call-to-action above the manual
   records. Only rendered when the provider supports it. */
.domain-connect-cta { display: inline-block; margin-bottom: 8px; }

/* Billing history under the plan cards. Deliberately plain: it is a record to
   scan, not something to interact with. */
.payments-block { margin-top: 1.5rem; }
.payments-block h3 { margin: 0 0 .5rem; font-size: 1rem; }
.payments-list { list-style: none; margin: 0; padding: 0; }
.payments-list li {
  display: flex; gap: 1rem; flex-wrap: wrap;
  padding: .45rem 0; border-top: 1px solid var(--line, rgba(0,0,0,.08));
  font-size: .95rem;
}
.payments-list li .pay-amount { font-variant-numeric: tabular-nums; font-weight: 600; }
.payments-list li .pay-what { color: var(--muted, #8a8577); }

.app-settings-card { width: min(620px, 100%); }
.app-settings-card h3 { margin-top: 24px; }
.app-settings-card form { display: grid; gap: 10px; margin: 12px 0; }
.app-settings-card label { display: grid; gap: 4px; }
.app-settings-list { padding-left: 20px; overflow-wrap: anywhere; }
.app-settings-list li { margin-bottom: 12px; }
