/* App Hub shell — implements the "TTM App Hub UX Design" handoff.
   Token names/values are final (from the UX design package token layer).
   Brand name/marks are runtime slots — nothing brand-literal lives here. */

@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap');

/* THE TOKENS LIVE IN /brand/app-shell.css AND ONLY THERE.
   This block used to redefine every `--hub-*` value here, with LIGHT values,
   and this stylesheet loads AFTER the shell — so the shell's dark redefinitions
   were overridden and the hub had no working dark mode at all: the wordmark
   stayed light and every control kept its light colour while the ground went
   dark. The aliases in app-shell.css already map `--hub-*` onto `--tsnz-*`, so
   deleting this block is what makes the hub obey its own design system.

   Anything genuinely local to the shell goes below, and must be DERIVED from a
   token — never a literal. */
:root {
  /* Shell-only, not part of the platform token set. */
  --hub-locked-surface: var(--tsnz-locked-surface);
  --hub-locked-fg: var(--tsnz-locked-fg);
  --hub-requested-surface: var(--tsnz-requested-surface);
  --hub-requested-fg: var(--tsnz-requested-fg);
  --hub-motion-fast: var(--tsnz-motion-fast);
  --hub-motion-standard: var(--tsnz-motion-standard);
  --hub-motion-ease: var(--tsnz-motion-ease);
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
/* Type comes from the shell's scale, not from a literal here — 24 Aug 2026,
   when the platform default moved 13/19 -> 14/20 with the Strata merge. The
   only thing this rule still says is that the lobby paints CANVAS rather than
   the shell's default sunken ground. */
body { font: var(--tsnz-fw-regular) var(--tsnz-fs-body)/var(--tsnz-lh-body) var(--hub-font-ui);
       color: var(--tsnz-ink);
       background: var(--tsnz-canvas); }
/* `:focus-visible { outline: none; box-shadow: var(--hub-focus-ring) }` lived
   here. The colour was right, but `outline: none` deleted the one layer that
   survives forced-colors / Windows High Contrast, where box-shadow is dropped
   — so the hub had no visible keyboard focus at all in that mode. The shell
   paints both layers; this rule only ever removed one of them. */
button, input, textarea { font: inherit; }

/* ------------------------------------------------------------- top bar */
.topbar { height: var(--hub-topbar-height); background: var(--hub-surface);
  border-bottom: 1px solid var(--hub-border); display: flex; align-items: center;
  padding: 0 20px; gap: 16px; position: sticky; top: 0; z-index: 20; }
/* The companion cone tile (.brand-mark) is gone — the wordmark already contains
   the cone as the A of LANE. See brandSlot() in app.js. */
.brand-slot { display: flex; align-items: center; text-decoration: none; }
/* Centred on each other, not flush left: the tracked endorsement sets the wider
   box (~103px vs the wordmark's ~95px), so left-aligning them read as an error. */
.brand-text { display: flex; flex-direction: column; align-items: center;
  line-height: 1.05; }
/* Wordmark 18 -> 21.6 -> 25.92 -> 31.104px (+20% three times); endorsement -20%
   (8.5 -> 6.8px) and held there. The text rule is the no-image fallback for the
   same slot, so it scales with the image. */
.brand-wordmark { font: 700 29.376px var(--hub-font-brand); color: var(--hub-navy); }
.brand-wordmark img { height: 31.104px; display: block; }
/* letter-spacing appends a trailing space after the final Z, which is inside the
   box being centred and would shove the glyphs ~1px left. Negative margin of one
   track pulls the box back to the visible text. */
.brand-endorse { font: 600 6.8px var(--hub-font-brand); letter-spacing: 0.24em;
  color: var(--hub-slate-600); text-transform: uppercase; margin-top: 2px;
  margin-right: -0.24em; text-align: center; }
.topbar .spacer { flex: 1; }

.orgbtn, .avatarbtn { border: 1px solid transparent; background: none; border-radius:
  var(--hub-radius-control); cursor: pointer; height: 40px; }
.orgbtn { display: flex; align-items: center; gap: 8px; padding: 0 12px;
  color: var(--hub-ink); font-weight: 500; }
.orgbtn:hover { background: var(--hub-surface-sunken); }
.orgbtn.static { cursor: default; }
.orgbtn.static:hover { background: none; }
.orgbtn i { font-size: 18px; color: var(--hub-slate-600); }
.avatarbtn { width: 40px; padding: 0; }
.avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--hub-navy);
  color: var(--tsnz-on-action); display: grid; place-items: center;
  font: var(--tsnz-fw-semibold) var(--tsnz-fs-body) var(--hub-font-ui); }

/* ------------------------------------------------------------- menus */
.menu { position: absolute; top: calc(var(--hub-topbar-height) + 6px); right: 20px;
  background: var(--hub-surface); border: 1px solid var(--hub-border);
  border-radius: var(--hub-radius-control); box-shadow: 0 8px 24px rgba(14,42,71,.12);
  padding: 6px; z-index: 30; }
.menu.orgs { width: 280px; right: 72px; }
.menu.account { width: 260px; }
.menu .helper { font-size: 11px; color: var(--hub-slate-600); padding: 8px 10px 6px; }
.menu .row { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px;
  padding: 0 10px; border: 0; background: none; border-radius: 6px; cursor: pointer;
  text-align: left; color: var(--hub-ink); }
.menu .row:hover { background: var(--hub-surface-sunken); }
.menu .row.active { background: var(--hub-requested-surface); color: var(--hub-navy);
  font-weight: 600; }
.menu .row i { font-size: 18px; color: var(--hub-slate-600); }
.menu .who { padding: 10px 10px 8px; }
.menu .who .nm { font-weight: 600; }
.menu .who .em { font: 400 12px var(--hub-font-mono); color: var(--hub-slate-600); }
.menu .who .rl { font-size: 11px; color: var(--hub-slate-300); margin-top: 2px; }
.menu hr { border: 0; border-top: 1px solid var(--hub-border); margin: 6px 0; }

/* ------------------------------------------------------------- layout */
/* ONE measure, from the platform. This was `.shellwrap` 1120 wrapping
   `.content` 1040 — two max-widths where the inner is exactly the outer minus
   its padding, i.e. a no-op that reads as a decision. */
.shellwrap { max-width: var(--tsnz-measure-wide); margin: 0 auto; padding: 28px 40px 60px; }
.content { width: 100%; margin: 0 auto; }
/* h1 and .subline are the platform's `.tsnz-page-head` / `.tsnz-page-meta`
   now; these two rules said the same thing in local numbers. */
h1 { margin: 0 0 4px; }
.subline { color: var(--hub-slate-600); margin: 0 0 24px; }

/* ------------------------------------------------------------- banners */
.banner { display: flex; gap: 10px; align-items: flex-start; border-radius:
  var(--hub-radius-control); padding: 12px 14px; margin-bottom: 16px; font-size: 13px; }
.banner.info { background: var(--hub-requested-surface); color: var(--hub-navy); }
.banner.quiet { background: var(--hub-surface-sunken); color: var(--hub-slate-600); }
.banner i { font-size: 18px; flex: 0 0 auto; margin-top: 1px; }
.returnpill { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px;
  background: var(--hub-surface); border: 1px solid var(--hub-border); border-radius: 999px;
  padding: 4px 12px; font-weight: 500; color: var(--hub-navy); font-size: 12px; }

/* ------------------------------------------------------------- auth card */
.authwrap { min-height: calc(100vh - var(--hub-topbar-height)); display: flex;
  flex-direction: column; align-items: center; padding: 48px 20px; }
.authcard { width: 400px; max-width: 100%; background: var(--hub-surface);
  border: 1px solid var(--hub-border); border-radius: var(--hub-radius-control);
  padding: 28px; }
.authcard h1 { margin-bottom: 20px; }
.field { margin-bottom: 16px; }
.field label { display: block; font-weight: 500; margin-bottom: 6px; }
.field input { width: 100%; height: 48px; padding: 0 14px; border: 1px solid
  var(--hub-border-strong); border-radius: var(--hub-radius-control); font-size: 14px; }
/* No `outline: none` here either — the sign-in field is the first control a
   customer ever focuses, and forced-colors mode drops the shadow. */
.field input:focus-visible { box-shadow: var(--hub-focus-ring); }
.field input[readonly] { background: var(--hub-surface-sunken);
  font-family: var(--hub-font-mono); font-size: 13px; }
.field .err { color: var(--hub-danger); font-size: 12px; margin-top: 6px;
  display: flex; gap: 6px; align-items: center; }
.rule { display: flex; align-items: center; gap: 8px; font-size: 12px;
  color: var(--hub-slate-600); margin: -6px 0 14px; }
.rule.ok { color: var(--hub-navy); font-weight: 500; }
.rule i { font-size: 16px; }
.forgot { display: inline-block; margin-top: 14px; color: var(--hub-navy); font-size: 12px; }
.endorse-footer { margin-top: 28px; font: 600 9px var(--hub-font-brand);
  letter-spacing: 0.24em; color: var(--hub-slate-300); text-transform: uppercase; }
.disable-why { font-size: 12px; color: var(--hub-slate-600); margin-top: 8px; }

/* ------------------------------------------------------------- buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 40px; padding: 0 16px; border-radius: var(--hub-radius-control);
  border: 1px solid transparent; cursor: pointer; font-weight: 500;
  transition: background var(--hub-motion-fast) var(--hub-motion-ease); }
/* .btn.primary is defined ONCE, in /brand/app-shell.css, using the
   --tsnz-action / --tsnz-on-action pair. It was restated here with
   --hub-navy, which is a TEXT colour in dark mode — and because this sheet
   loads after the shell it won the cascade and painted white text on a
   near-white fill. Same "two definitions of one value" defect as the token
   block that was removed above. */
.btn.primary:disabled { background: var(--hub-slate-300); cursor: default; }
.btn.secondary { background: var(--hub-surface); border-color: var(--hub-border-strong);
  color: var(--hub-navy); }
.btn.secondary:hover { background: var(--hub-surface-sunken); }
.btn.ghost { background: none; color: var(--hub-navy); }
.btn.ghost:hover { background: var(--hub-surface-sunken); }
.btn.full { width: 100%; height: 44px; }
.btn .spin { width: 16px; height: 16px; border: 2px solid rgba(255,255,255,.4);
  border-top-color: var(--tsnz-on-action); border-radius: 50%; animation: spin 700ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------- lobby cards */
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.card { background: var(--hub-surface); border: 1px solid var(--hub-border);
  border-radius: var(--hub-radius-control); padding: 20px; }
.card .head { display: flex; gap: 12px; align-items: flex-start; }
.apptile { width: 36px; height: 36px; border-radius: 8px; background:
  var(--hub-surface-sunken); display: grid; place-items: center; flex: 0 0 auto; }
.apptile i { font-size: 20px; color: var(--hub-navy); }
.card .name { font: 600 16px/22px var(--hub-font-ui); color: var(--hub-navy); }
.card .purpose { color: var(--hub-slate-600); margin-top: 1px; }
.chips { margin: 12px 0 14px; display: flex; flex-wrap: wrap; gap: 6px; }
.chip { display: inline-flex; align-items: center; gap: 5px; background:
  var(--hub-surface-sunken); border-radius: 999px; padding: 3px 10px; font-size: 12px;
  color: var(--hub-ink); }
.chip i { font-size: 13px; color: var(--hub-slate-600); }
.entries { display: flex; flex-wrap: wrap; gap: 8px; }

.card.locked { background: var(--hub-locked-surface); }
.card.locked .name { color: var(--tsnz-locked-fg); }
.card.locked .apptile i { color: var(--hub-slate-300); }
.lockrow { display: flex; align-items: center; gap: 6px; margin: 12px 0 6px;
  font: 600 12px var(--hub-font-ui); color: var(--hub-locked-fg); }
.lockrow i { font-size: 15px; }
.price { font: 600 15px var(--hub-font-ui); color: var(--hub-ink); }
.price small { font: 400 12px var(--hub-font-ui); color: var(--hub-slate-600);
  margin-left: 6px; }
.reqpill { display: inline-flex; align-items: center; gap: 6px; background:
  var(--hub-requested-surface); color: var(--hub-requested-fg); border-radius: 999px;
  padding: 5px 12px; font-weight: 500; font-size: 12px; }
.reqpill i { font-size: 14px; }
.lapse { display: flex; gap: 8px; align-items: center; background:
  var(--hub-requested-surface); color: var(--hub-navy); border-radius: 6px;
  padding: 8px 10px; font-size: 12px; margin-top: 10px; }
.card .actions { margin-top: 14px; display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap; }
.admin-ctx { font-size: 12px; color: var(--hub-slate-600); margin-top: 8px; }

/* skeletons */
.skel .card { pointer-events: none; }
.sk { background: var(--hub-surface-sunken); border-radius: 6px;
  animation: pulse 1.4s var(--hub-motion-ease) infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }

/* empty / error */
.statecard { border: 1.5px dashed var(--hub-border-strong); border-radius:
  var(--hub-radius-control); padding: 48px 24px; text-align: center;
  color: var(--hub-slate-600); }
.statecard i { font-size: 32px; color: var(--hub-slate-300); }
.statecard .t { font: 600 16px var(--hub-font-ui); color: var(--hub-ink); margin: 10px 0 4px; }
.statecard .btn { margin-top: 16px; }

/* ------------------------------------------------------------- modal */
.overlay { position: fixed; inset: 0; background: rgba(14,42,71,.35); z-index: 40;
  display: grid; place-items: center; padding: 20px; }
.modal { width: 460px; max-width: 100%; background: var(--hub-surface);
  border-radius: var(--hub-radius-modal); padding: 24px; }
.modal h2 { font: 600 18px/24px var(--hub-font-ui); color: var(--hub-navy); margin: 0 0 10px; }
.modal p { margin: 0 0 12px; color: var(--hub-ink); }
.modal .muted { color: var(--hub-slate-600); font-size: 12px; }
.modal textarea { width: 100%; min-height: 72px; border: 1px solid var(--hub-border-strong);
  border-radius: var(--hub-radius-control); padding: 10px 12px; resize: vertical; }
.modal .field input { height: 44px; }
.modal .total { font-weight: 600; margin: 12px 0 4px; }
.modal .foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

/* ------------------------------------------------------------- toast */
.toastwrap { position: fixed; left: 0; right: 0; bottom: 24px; display: flex;
  justify-content: center; z-index: 50; pointer-events: none; }
.toast { display: flex; align-items: center; gap: 8px; background: var(--hub-navy);
  color: var(--tsnz-on-action); border-radius: var(--tsnz-radius-round);
  padding: 10px 18px; font-size: var(--tsnz-fs-body-small);
  box-shadow: 0 8px 24px rgba(8,29,51,.3); }
.toast i { font-size: 16px; }

/* ------------------------------------------------------------- tablet */
@media (max-width: 768px) {
  .grid { grid-template-columns: 1fr; }
  .shellwrap { padding: 20px 16px 48px; }
  .btn { height: 44px; }
  .menu.orgs { right: 60px; }
}
