:root {
  /* collaborate.css reads --text and --surface; alias them so both themes apply. */
  --text: var(--fg);
  --surface: var(--card);
  color-scheme: dark;
  /* The whole application reads the one warm palette declared further down: cream paper, terracotta
     for action, near-black ink, and colour only where it means something. These are aliases, so the
     appearance switch happens once, in --w-*, rather than being written out again per theme here.
     The signed-in product used to keep a green brand of its own while the landing wore this; that
     split is gone, which is what makes the two halves look like one product. */
  --bg: var(--w-paper);
  --card: var(--w-card);
  --fg: var(--w-ink);
  --muted: var(--w-ink-3);
  --border: var(--w-line);
  --sidebar-surface: var(--w-sidebar);
  --field-surface: var(--w-card);
  --surface-raised: var(--w-raised);
  --separator: var(--w-line-soft);
  --selection: var(--w-line-soft);
  /* Action, not approval. --ok carries "this is live / this went well", which used to share this
     token and would have turned terracotta with it. */
  --accent: var(--w-accent);
  --accent-fg: var(--w-accent-fg);
  --ok: var(--w-live);
  --accent-cyan: #38bdf8;
  --accent-purple: #a855f7;
  --accent-amber: #f59e0b;
  --accent-blue: #3b82f6;
  --glow-mint: none;
  --glow-cyan: none;
  --glow-card: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px -16px rgba(0, 0, 0, 0.25);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
}
:root[data-theme="light"] { color-scheme: light; }
@media (prefers-color-scheme: light) {
  /* Only the colour-scheme hint: the values themselves switch once, in --w-*. */
  :root:not([data-theme]), :root[data-theme="system"] { color-scheme: light; }
}
* { box-sizing: border-box; }
:focus-visible { outline: 3px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 2px; }
body {
  margin: 0;
  background-color: var(--bg);
  background-image:
    radial-gradient(circle at 82% 18%, color-mix(in srgb, var(--accent) 6%, transparent) 0%, transparent 60%),
    radial-gradient(circle at 12% 82%, rgba(59, 130, 246, 0.08) 0%, rgba(168, 85, 247, 0.05) 35%, transparent 60%),
    radial-gradient(circle at 50% 50%, rgba(11, 15, 25, 0.95) 0%, rgba(7, 9, 14, 1) 100%);
  background-attachment: fixed;
  color: var(--fg);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  min-height: 100vh;
  padding: 0;
}
button, select, input { font: inherit; }
button, select, summary, a.nav-item, a.route-action { min-height: 44px; }
/* Safari draws <select> as a native menu and replaces the stylesheet's padding and height with its own
   (computed min-height 18px, padding 0), so a room role picker rendered 23px tall beside 44px inputs.
   appearance: none returns the box to this stylesheet in every engine. The arrow is drawn from two
   currentColor gradients so it follows the theme; rules that colour a select must set background-color,
   not the background shorthand, or they erase it. */
select {
  -webkit-appearance: none; appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.05rem) 50%, calc(100% - 0.7rem) 50%;
  background-size: 0.35rem 0.35rem;
  background-repeat: no-repeat;
}
#app { width: 100%; min-height: 100vh; }
.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;
}
/* Render a stable shell immediately while the Bonsai bundle downloads and parses. It is inert and
   aria-hidden, but avoids the blank-screen interval that dominated perceived startup time. */
.app-placeholder {
  pointer-events: none;
  user-select: none;
}
.app-placeholder .shell-main {
  grid-column: 1;
  grid-row: 1;
  width: min(100%, 46rem);
  margin: 0 auto;
  padding: 2rem 1.25rem 3rem;
}
.placeholder-main { min-height: 24rem; }
.boot-placeholder { min-height: 19rem; }
.boot-line {
  display: block; height: 0.8rem; width: min(100%, 29rem); border-radius: 999px;
  background: color-mix(in srgb, var(--muted) 16%, transparent);
  animation: inetgarden-boot-pulse 1.2s ease-in-out infinite alternate;
}
.boot-line.title { width: min(55%, 15rem); height: 1.6rem; margin-bottom: 0.9rem; }
.boot-line.short { width: min(72%, 21rem); margin-top: 0.55rem; }
.boot-actions { display: flex; gap: 0.75rem; margin-top: 2.2rem; }
.boot-action { width: 7.5rem; height: 2.75rem; border-radius: 999px; }
@keyframes inetgarden-boot-pulse { to { opacity: 0.42; } }
@media (prefers-reduced-motion: reduce) { .boot-line { animation: none; } }
.skip-link {
  position: fixed; z-index: 1000; left: 0.75rem; top: 0.75rem; padding: 0.65rem 0.85rem;
  border-radius: 8px; background: var(--fg); color: var(--bg); font-weight: 700;
  transform: translateY(-200%); transition: transform 0.12s;
}
.skip-link:focus { transform: translateY(0); }

.app-shell {
  --sidebar-width: 15rem;
  width: 100%; min-height: 100vh; min-height: 100dvh; margin: 0; padding: 0;
  display: grid; grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  grid-template-rows: 0 auto 1fr auto; background-color: var(--bg);
  background-image: linear-gradient(to right, var(--sidebar-surface) var(--sidebar-width), transparent var(--sidebar-width));
}
.workspace-sidebar {
  grid-column: 1; grid-row: 1 / -1; position: sticky; top: 0; align-self: start;
  height: 100vh; height: 100dvh; min-width: 0; overflow-y: auto;
  display: flex; flex-direction: column; padding: 1.2rem 0.85rem;
  background: var(--sidebar-surface); scrollbar-width: thin;
  border-right: 1px solid var(--separator);
}
.workspace-sidebar .brand { margin: 0 0.5rem 1.4rem; flex: 0 0 auto; }
.brand {
  display: inline-flex; align-items: center; gap: 0.75rem; border: 0; background: transparent;
  color: var(--fg); padding: 0.35rem 0.25rem; font-weight: 700; font-size: 1.12rem; letter-spacing: -0.025em; cursor: pointer;
}
.brand-logo-img {
  width: 28px; height: 28px; flex: 0 0 auto;
  filter: none;
  transition: transform 0.2s ease, filter 0.2s ease;
}
.brand:hover .brand-logo-img {
  transform: scale(1.08);
  filter: none;
}
.sidebar-status-indicator {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.6rem 0.75rem;
  margin-top: 0.85rem; border-radius: 8px; font-size: 0.76rem; color: var(--muted);
  border-top: 1px solid var(--separator);
}
/* Green only for a live session. Every other state is neutral, amber or red, and there is no
   indicator at all without a session: the dot must never claim more than the session proves. */
.status-indicator-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
.status-live .status-indicator-dot {
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent);
  animation: pulse-online 2s infinite ease-in-out;
}
.status-backoff .status-indicator-dot { background: #f59e0b; }
.status-failed .status-indicator-dot { background: #ef4444; }
@media (prefers-reduced-motion: reduce) { .status-live .status-indicator-dot { animation: none; } }
@keyframes pulse-online {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.25); opacity: 0.7; }
}
.nav-caption { margin: 1rem 0.75rem 0.45rem; color: var(--muted); font-size: 0.72rem; font-weight: 600; }
.sidebar-bottom { margin-top: auto; padding-top: 2rem; }
.sidebar-help { display: flex; align-items: center; min-height: 44px; padding: 0.4rem 0.75rem; color: var(--muted); font-size: 0.84rem; text-decoration: none; border-radius: 8px; }
.sidebar-help:hover { background: var(--card); color: var(--fg); }
.desktop-notification-control { display: block; }
.desktop-notification-button { width: 100%; border: 0; background: transparent; text-align: left; font: inherit; cursor: pointer; }
.desktop-notification-button:disabled { cursor: default; opacity: 0.72; }
.desktop-notification-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sidebar-appearance { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; padding: 0.4rem 0.65rem 0.85rem; color: var(--muted); font-size: 0.78rem; }
.sidebar-sign-in { display: grid; gap: 0.4rem; padding: 0.4rem 0.65rem; font-size: 0.82rem; }
.sidebar-sign-in .identity-provider { display: flex; align-items: center; min-height: 44px; width: 100%; margin: 0; font-size: inherit; }
.workspace-context { display: flex; align-items: center; gap: 0.85rem; font-size: 0.85rem; }
.workspace-label, .workspace-divider { color: var(--muted); }
.workspace-current { color: var(--fg); font-weight: 600; }
.navigation-toggle { display: none; align-items: center; gap: 0.5rem; padding: 0.4rem 0.65rem; border: 1px solid var(--border); border-radius: 9px; background: var(--card); color: var(--fg); cursor: pointer; }
.shell-head {
  grid-column: 2; grid-row: 1; min-width: 0; display: none; align-items: center;
  gap: 1rem; padding: 0 2.5rem; border-bottom: 1px solid var(--separator);
}
.brand {
  display: inline-flex; align-items: center; gap: 0.55rem; border: 0; background: transparent;
  color: var(--fg); padding: 0.35rem 0; font-weight: 600; font-size: 1.05rem; letter-spacing: -0.025em; cursor: pointer;
}
.shell-nav { display: flex; flex-direction: column; align-items: stretch; gap: 0.25rem; }
/* Symbols scale with their labels; navigation keeps a stable optical slot. */
.portal-icon {
  width: 1.2em; height: 1.2em; flex: 0 0 auto; vertical-align: -0.2em; pointer-events: none;
  stroke-width: var(--icon-stroke, 1.75);
}
.nav-item .portal-icon, .account-menu-item .portal-icon { width: 20px; height: 20px; }
.connect, .route-action, .setting-title, .collaboration-region-title, h1, h2 { --icon-stroke: 1.9; }
.provider-icon-zoom { width: 2.5rem; }
.icon-label { display: inline-flex; align-items: center; gap: 0.45em; }
.nav-item .portal-icon { margin-inline-end: 0; }
.connect:not(.icon-label) .portal-icon, .host-setup-trigger .portal-icon { margin-inline-end: 0.4em; }
.nav-item {
  display: flex; align-items: center; gap: 0.75rem; width: 100%; text-align: left;
  border: 0; border-radius: 9px; padding: 0.6rem 0.75rem; background: transparent;
  color: var(--fg); cursor: pointer; font-size: 0.88rem; font-weight: 400;
}
.nav-item:hover { background: color-mix(in srgb, var(--selection) 60%, transparent); }
.nav-item.active { background: var(--selection); color: var(--fg); font-weight: 600; }
.shell-actions { display: flex; align-items: center; justify-content: flex-end; gap: 0.75rem; }
.theme-control select {
  border: 1px solid var(--border); border-radius: 999px; padding: 0.38rem 1.8rem 0.38rem 0.7rem;
  background-color: var(--card); color: var(--fg); font-size: 0.8rem; cursor: pointer;
}
.account-dot {
  display: grid; place-items: center; width: 2rem; height: 2rem; border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent);
  font-size: 0.78rem; font-weight: 750;
}
.account-menu, .account-chip { display: flex; align-items: center; gap: 0.45rem; }
.account-chip {
  border: 1px solid var(--border); border-radius: 999px; background: var(--card); color: var(--fg);
  padding: 0.16rem 0.55rem 0.16rem 0.16rem; cursor: pointer;
}
.account-chip:hover { border-color: var(--accent); }
.sidebar-bottom .account-menu { flex-direction: column; align-items: stretch; gap: 0.25rem; border-top: 1px solid var(--border); padding-top: 0.85rem; }
.sidebar-bottom .account-chip { width: 100%; border: 0; border-radius: 10px; padding: 0.5rem; background: transparent; text-align: left; gap: 0.65rem; }
.sidebar-bottom .account-chip:hover { background: var(--card); }
.account-caption { display: grid; min-width: 0; gap: 0.12rem; }
.account-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.78rem; }
.sidebar-bottom .account-dot { flex: 0 0 auto; }
.sidebar-bottom .account-logout { align-self: flex-start; color: var(--muted); padding: 0.35rem 0.65rem; }
.account-plan { color: var(--muted); font-size: 0.72rem; text-transform: capitalize; }
.account-logout { border: 0; background: transparent; cursor: pointer; }

/* The account menu. It rises from the chip pinned to the bottom of the sidebar, so it opens upward:
   anchored at the bottom, growing away from the edge it sits on. */
.sidebar-bottom .account-menu { position: relative; }
.account-chip.open { background: var(--card); }
.account-popover {
  position: absolute; bottom: calc(100% + 0.4rem); left: 0; right: 0; z-index: 40;
  display: grid; gap: 0.1rem; padding: 0.35rem;
  border: 1px solid var(--separator); border-radius: 12px;
  background: var(--surface-raised);
  box-shadow: 0 18px 40px rgb(0 0 0 / 28%);
}
.account-menu-identity {
  margin: 0; padding: 0.4rem 0.55rem 0.5rem; border-bottom: 1px solid var(--separator);
  color: var(--muted); font-size: 0.72rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account-menu-item {
  display: flex; align-items: center; gap: 0.55rem; width: 100%;
  padding: 0.5rem 0.55rem; border: 0; border-radius: 8px;
  background: transparent; color: var(--fg); font: inherit; font-size: 0.82rem;
  text-align: left; text-decoration: none; cursor: pointer;
}
.account-menu-item:hover, .account-menu-item:focus-visible { background: var(--card); }
.account-menu-appearance {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.4rem 0.55rem; border-top: 1px solid var(--border); margin-top: 0.15rem;
  color: var(--muted); font-size: 0.78rem;
}
.account-menu-note { margin: 0; padding: 0.5rem 0.55rem; color: var(--muted); font-size: 0.78rem; }
.sidebar-bottom .account-popover .account-logout {
  border-top: 1px solid var(--border); border-radius: 0 0 8px 8px; margin-top: 0.15rem;
  color: var(--muted); align-self: stretch;
}
.shell-main { grid-column: 2; grid-row: 3; width: min(100%, 108rem); min-width: 0; margin: 0 auto; padding: 2rem 2.5rem 3rem; }
/* Route focus announces the noninteractive landmark, not a selected panel. All interactive
   controls retain the global :focus-visible ring, including the skip link and menu button. */
.shell-main:focus { outline: none; }
.shell-main > .portal:not(.connect-screen), .shell-main > .account-route-host > .portal { padding: 0; background: transparent; border: 0; box-shadow: none; border-radius: 0; }
.shell-main .portal-head h1 { font-size: clamp(1.8rem, 3vw, 2.1rem); font-weight: 600; letter-spacing: -0.025em; }
.shell-foot { grid-column: 2; grid-row: 4; padding: 1rem 1.5rem; color: var(--muted); font-size: 0.72rem; text-align: center; }
.shell-foot a { color: inherit; margin-inline-start: 0.75rem; }
.notification-region { grid-column: 2; grid-row: 2; width: min(calc(100% - 3rem), 66rem); margin: 0.8rem auto 0; }
.notice {
  display: flex; align-items: center; justify-content: space-between; gap: 0.8rem;
  padding: 0.65rem 0.8rem; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-raised); color: var(--fg); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.07);
  font-size: 0.84rem;
}
.notice.success { border-color: color-mix(in srgb, var(--ok) 58%, var(--border)); }
.notice.error { border-color: #c0392b; }
.notice-close {
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  padding: 0.1rem 0.3rem; font-size: 1.15rem; line-height: 1;
}
.notice-close:hover { color: var(--fg); }

.portal {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.75rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px rgba(0, 0, 0, 0.06);
}
header h1 { margin: 0; font-size: 1.5rem; letter-spacing: -0.01em; }
.tagline { margin: 0.15rem 0 0; color: var(--muted); }
.portal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; }

/* Share hero: the prominent QR + short link + copy, above the data columns. */
.hero {
  display: flex; gap: 1.25rem; align-items: center;
  padding: 1rem 1.1rem; margin-bottom: 1.25rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
}
.hero-qr svg {
  display: block; width: 176px; height: 176px;
  border: 1px solid var(--border); border-radius: 10px; background: #ffffff;
}
.hero-info { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.hero-title { font-weight: 700; font-size: 1.05rem; }
.hero-hint { color: var(--muted); font-size: 0.82rem; }
.hero-info .copy { margin-top: 0.35rem; align-self: flex-start; }

/* Default path: one primary connection control beside plain-language status. */
.cols { display: grid; grid-template-columns: minmax(0, 2fr) minmax(12rem, 1fr); gap: 1rem 1.25rem; align-items: start; }
.col { display: flex; flex-direction: column; gap: 0.55rem; min-width: 0; }
.col-title {
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--border); padding-bottom: 0.3rem;
}
.col > .connect, .col > .copy { margin-top: 0.35rem; }
.connection-advanced, .tools-disclosure {
  grid-column: 1 / -1; min-width: 0; border-top: 1px solid var(--border); padding-top: 0.35rem;
}
.connection-advanced > summary, .tools-disclosure > summary {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.55rem 0;
  color: var(--muted); font-size: 0.8rem; font-weight: 700; cursor: pointer;
}
.connection-advanced > summary::before, .tools-disclosure > summary::before { content: "▸"; }
.connection-advanced[open] > summary::before, .tools-disclosure[open] > summary::before { content: "▾"; }
.advanced-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.7rem 1rem;
  padding: 0.5rem 0 0.25rem;
}
.advanced-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.advanced-actions .copy { margin-top: 0; }
.tools-disclosure { margin-top: 1rem; }
.tools-disclosure > .tools { margin-top: 0; border-top: 0; padding-top: 0.4rem; }
/* Putting the side panel away, on the wide layout. The narrow one below already hides it behind
   the Menu button, so this only applies above that breakpoint - collapsing a panel that is already
   an overlay would leave the reader with two controls doing one thing.
   Collapsed, the shell becomes a single column and the header appears to carry the way back. The
   header is normally hidden up here and its row is 0 high, so the row has to be reopened too. */
.nav-collapse {
  position: absolute; top: 1.2rem; right: 0.85rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; padding: 0; border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--muted); cursor: pointer;
}
.nav-collapse:hover { background: var(--card); color: var(--fg); border-color: var(--border); }
.nav-collapse:focus-visible { outline: 2px solid var(--ig-primary); outline-offset: 2px; }
@media (min-width: 56.0625rem) {
  .app-shell[data-nav-collapsed="true"] {
    grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto 1fr auto;
    background-image: none;
  }
  .app-shell[data-nav-collapsed="true"] .workspace-sidebar { display: none; }
  .app-shell[data-nav-collapsed="true"] .shell-head { display: flex; grid-column: 1; padding: 0.55rem 2.5rem; }
  .app-shell[data-nav-collapsed="true"] .navigation-toggle { display: inline-flex; }
  /* Everything in the shell is placed in column 2, beside the panel. With the panel gone there is
     only column 1, and an item still asking for column 2 creates an implicit track next to it:
     the header ended up in a zero-width column, shrunk to the width of its own button, while the
     page sat in a track the grid never declared. The visitor layout moves the same three. */
  .app-shell[data-nav-collapsed="true"] .shell-main,
  .app-shell[data-nav-collapsed="true"] .shell-foot,
  .app-shell[data-nav-collapsed="true"] .notification-region { grid-column: 1; }
}

@media (max-width: 56rem) {
  .nav-collapse { display: none; }
  .app-shell { grid-template-columns: minmax(0, 1fr); grid-template-rows: 4.25rem auto auto 1fr auto; background-image: none; }
  .shell-head { display: flex; grid-column: 1; grid-row: 1; gap: 1rem; padding: 0.5rem 1rem; }
  .navigation-toggle { display: inline-flex; }
  .workspace-sidebar { display: none; grid-column: 1; grid-row: 2; position: static; height: auto; border-right: 0; border-bottom: 1px solid var(--border); }
  .app-shell[data-sidebar-open="true"] .workspace-sidebar { display: flex; }
  .workspace-sidebar .brand { margin-bottom: 0; }
  .shell-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nav-caption { grid-column: 1 / -1; }
  .sidebar-bottom { padding-top: 1rem; }
  .sidebar-appearance { justify-content: flex-start; gap: 1rem; }
  .workspace-label, .workspace-divider { display: none; }
  .notification-region { grid-column: 1; grid-row: 3; }
  .shell-main { grid-column: 1; grid-row: 4; padding: 1.5rem 1.25rem 2rem; }
  .shell-foot { grid-column: 1; grid-row: 5; }
  .cols { grid-template-columns: 1fr; }
  .advanced-grid { grid-template-columns: 1fr; }
  .hero { flex-direction: column; text-align: center; }
  .hero-info { align-items: center; }
  .hero-info .copy { align-self: center; }
}

.form { display: grid; gap: 0.9rem; }
.field { display: grid; gap: 0.3rem; }
.field .label { font-size: 0.8rem; font-weight: 600; color: var(--muted); }
.field input, .field select {
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  color: var(--fg);
  background-color: var(--field-surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  outline: none;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.field select { padding-right: 2rem; }
.field input::placeholder { color: var(--muted); opacity: 1; }
.field input:focus, .field select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.field input.mono { font-family: var(--mono); font-size: 0.85rem; }
.field input.invalid { border-color: #c0392b; }
.field input.invalid:focus { box-shadow: 0 0 0 3px #c0392b33; }
.field-hint { font-size: 0.72rem; color: #c0392b; }

.recents { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.9rem; }
.recents-label { font-size: 0.72rem; font-weight: 600; color: var(--muted); }
.chip {
  font: inherit; font-size: 0.78rem; padding: 0.2rem 0.6rem;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--bg); color: var(--fg); cursor: pointer;
  max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: border-color 0.12s;
}
.chip:hover { border-color: var(--accent); }

/* "Open in the desktop app": a quiet secondary action beneath the primary Connect button.
   It stays subordinate to Connect and collapses to a disclosure until a local alias is known,
   so the default home screen keeps exactly one prominent action. */
.open-in-app { margin-top: 0.75rem; font-size: 0.85rem; }
.open-in-app summary {
  cursor: pointer; color: var(--muted); list-style: none;
  padding: 0.15rem 0; border-radius: 4px;
}
.open-in-app summary::-webkit-details-marker { display: none; }
.open-in-app summary:hover { color: var(--fg); }
.open-in-app summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.open-in-app .hint { color: var(--muted); margin: 0.4rem 0 0.5rem; }
.open-in-app .field { margin-bottom: 0.4rem; }
.app-link {
  color: var(--accent); text-decoration: none; font-weight: 600;
  border-bottom: 1px solid transparent;
}
.app-link:hover { border-bottom-color: var(--accent); }
.app-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.linkish {
  font: inherit; font-size: 0.85rem; background: none; border: 0; padding: 0.15rem 0;
  margin-left: 0.6rem; color: var(--muted); cursor: pointer; text-decoration: underline;
}
.linkish:hover:not(:disabled) { color: var(--fg); }
.linkish:disabled { opacity: 0.5; cursor: default; text-decoration: none; }
.linkish:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

.remember { display: flex; align-items: center; gap: 0.45rem; margin-top: 0.2rem; font-size: 0.78rem; color: var(--muted); cursor: pointer; }
.remember input { width: auto; margin: 0; }

.actions { display: flex; gap: 0.6rem; align-items: stretch; }
/* A class that sets `display` beats the user agent's [hidden] rule, so any element given both a
   component class and `hidden` stays on screen. Two rules below already patch this one element at
   a time (.availability-notice, the QR video); this is the general form, so the next component
   does not have to discover it again. */
[hidden] { display: none !important; }

.actions .connect { flex: 1; margin-top: 0; }
.actions .copy { margin-top: 0; }
.copy {
  margin-top: 0.9rem;
  padding: 0.7rem 1rem;
  font: inherit;
  font-weight: 600;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--card);
  color: var(--fg);
  cursor: pointer;
  transition: border-color 0.12s;
}
.copy:hover { border-color: var(--accent); }

.qr-link { font-family: var(--mono); font-size: 0.72rem; word-break: break-all; color: var(--muted); }

.status { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 1.25rem 0 0.5rem; }
.badge { font-size: 0.72rem; font-weight: 600; padding: 0.2rem 0.5rem; border-radius: 999px; white-space: nowrap; }
.badge.secure { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.badge.plain { background: color-mix(in srgb, var(--muted) 18%, transparent); color: var(--muted); }
.hint { color: var(--muted); font-size: 0.85rem; }

.session { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; margin: 1.25rem 0 0.25rem; }
.session .meta { color: var(--muted); font-size: 0.8rem; font-family: var(--mono); }
.connection-state { display: flex; align-items: flex-start; gap: 0.65rem; padding: 0.45rem 0; }
.connection-state > span:last-child { display: grid; gap: 0.1rem; }
.connection-state-dot { width: 0.7rem; height: 0.7rem; margin-top: 0.35rem; border-radius: 50%; background: var(--muted); }
.connection-state-hint { color: var(--muted); font-size: 0.78rem; }
.connection-state.status-resolving .connection-state-dot,
.connection-state.status-connecting .connection-state-dot,
.connection-state.status-backoff .connection-state-dot { background: #b47700; animation: wv-pulse 1.1s ease-in-out infinite; }
.connection-state.status-live .connection-state-dot { background: var(--ok); }
.connection-state.status-failed .connection-state-dot { background: #c0392b; }
.session-details { margin-top: 0.35rem; border-top: 1px solid var(--border); }
.session-details > summary { padding: 0.5rem 0; color: var(--muted); cursor: pointer; font-size: 0.76rem; font-weight: 650; }
.session-details .session { margin: 0.1rem 0 0.35rem; }
.head-actions { display: flex; align-items: center; gap: 0.65rem; }
.auth-link { color: var(--accent); font-size: 0.82rem; font-weight: 650; text-decoration: none; }
.auth-link:hover { text-decoration: underline; }
.sidebar-bottom button.auth-link {
  width: 100%; padding: 0.5rem 0.75rem; border: 0; border-radius: 9px;
  background: transparent; text-align: left; cursor: pointer;
}
.sidebar-bottom button.auth-link:hover { background: var(--card); }
.badge.status-idle, .badge.status-stopped { background: color-mix(in srgb, var(--muted) 18%, transparent); color: var(--muted); }
.badge.status-connecting, .badge.status-backoff {
  background: #b4770022; color: #b47700;
  animation: wv-pulse 1.1s ease-in-out infinite;
}
.badge.status-connecting::before, .badge.status-backoff::before {
  content: ""; display: inline-block; width: 0.5em; height: 0.5em; margin-right: 0.35em;
  border-radius: 50%; background: currentColor; vertical-align: middle;
  animation: wv-pulse 1.1s ease-in-out infinite;
}
@keyframes wv-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.badge.status-live { background: color-mix(in srgb, var(--ok) 20%, transparent); color: var(--ok); }
.badge[class*="status-error"], .badge.status-failed { background: #c0392b22; color: #c0392b; }

.log {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.7rem;
  max-height: 9rem;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 9px;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--muted);
}
.log li { padding: 0.05rem 0; }
.log li.log-resumed { color: var(--ok); font-weight: 600; }

.connect {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
  padding: 0.65rem 1.4rem;
  text-align: center;
  font: inherit;
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
  text-decoration: none;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-fg);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--w-ink) 12%, transparent);
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.connect:hover:not(:disabled) {
  filter: brightness(1.1);
  transform: translateY(-1px);
  box-shadow: 0 2px 8px -2px color-mix(in srgb, var(--accent) 45%, transparent);
}
.connect:active:not(:disabled) {
  transform: translateY(0);
}
.connect.stop { background: #c0392b; color: #ffffff; box-shadow: 0 0 16px rgba(192, 57, 43, 0.4); }
.connect.disabled, .connect:disabled {
  background: #182235;
  color: #64748b;
  border-color: rgba(255, 255, 255, 0.05);
  box-shadow: none;
  cursor: not-allowed;
  pointer-events: none;
  filter: none;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media (max-width: 22rem) {
  html, body, #app { max-width: 100%; overflow-x: hidden; }
  .portal { padding: 1rem; }
  .shell-nav { gap: 0; }
  .nav-item { padding-inline: 0.4rem; font-size: 0.78rem; }
  .shell-actions { gap: 0.25rem; }
  .theme-control select { padding-inline: 0.5rem; }
  .account-chip { padding-right: 0.25rem; }
  .account-plan { display: block; }
  .hero-qr svg { width: min(176px, 100%); height: auto; }
}

/* SSH access & tools panel, below the columns. */
.tools { margin-top: 1.5rem; border-top: 1px solid var(--border); padding-top: 1.1rem; display: flex; flex-direction: column; gap: 1rem; }
.tools-row { display: flex; flex-direction: column; gap: 0.5rem; }
.tools-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.tools-head .col-title { border: none; padding: 0; }
.feat-toggle { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; cursor: pointer; }
.feat-toggle input { width: auto; margin: 0; }
.feat-toggle.disabled { color: var(--muted); cursor: not-allowed; }
.feat-note { font-size: 0.76rem; color: var(--muted); }
.feat-lock { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); background: color-mix(in srgb, var(--muted) 16%, transparent);
  padding: 0.1rem 0.45rem; border-radius: 999px; }
.cmd { display: flex; align-items: stretch; gap: 0.5rem; }
.cmd code {
  flex: 1; min-width: 0; overflow-x: auto; white-space: pre; padding: 0.55rem 0.7rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: 9px;
  font-family: var(--mono); font-size: 0.78rem; color: var(--fg);
}
.cmd .copy { margin-top: 0; padding: 0.4rem 0.7rem; font-size: 0.78rem; white-space: nowrap; }
.cmd-hint { font-size: 0.76rem; color: var(--muted); font-family: var(--mono); }
.downloads { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.downloads a.dl {
  font-size: 0.78rem; padding: 0.3rem 0.7rem; text-decoration: none;
  border: 1px solid var(--border); border-radius: 999px; background: var(--bg); color: var(--fg);
  transition: border-color 0.12s;
}
.downloads a.dl:hover { border-color: var(--accent); }
.host-setup-check { align-self: flex-start; margin-top: 0; }
.host-setup-result:empty { display: none; }
.host-setup-result {
  display: grid; gap: 0.45rem; padding: 0.7rem 0.8rem;
  border: 1px solid var(--border); border-radius: 9px; background: var(--bg);
}
.host-setup-result strong { font-size: 0.86rem; }
.host-setup-result p, .host-setup-result ol { margin: 0; color: var(--muted); font-size: 0.76rem; }
.host-setup-result ol { padding-left: 1.25rem; }
.host-setup-result .cmd { margin-top: 0.2rem; }
.host-setup-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.host-setup-actions .copy { margin-top: 0; font-size: 0.76rem; padding: 0.45rem 0.7rem; }

/* Web terminal */
.webterm { display: flex; flex-direction: column; gap: 0.5rem; }
.webterm-form { display: flex; gap: 0.5rem; align-items: end; flex-wrap: wrap; }
.webterm-form .field { flex: 1; min-width: 8rem; gap: 0.2rem; }
.webterm-form .connect { margin-top: 0; padding: 0.55rem 0.9rem; white-space: nowrap; }
.term-host {
  height: 20rem; border: 1px solid var(--border); border-radius: 9px; overflow: hidden;
  background: #0f1216; padding: 0.4rem;
}
.term-host.hidden { display: none; }
.term-err { font-size: 0.76rem; color: #c0392b; }

:root .availability-notice { margin: 24px auto; padding: 20px; max-width: 760px; border: 1px solid currentColor; border-radius: 14px; }
.availability-notice[hidden] { display: none; }
#workspace-unavailable { position: fixed; z-index: 30; inset: auto 16px 16px; margin: 0 auto; max-height: calc(100vh - 32px); overflow: auto; background: var(--card); box-shadow: 0 12px 40px #0003; }
.availability-notice button, .availability-notice a { margin-inline-end: 16px; }

/* Connect prioritizes the invite and its action. Secondary controls share one disclosure. */
.connect-screen {
  width: min(100%, 68rem);
  margin: 1.5rem auto 3rem;
  background: rgba(14, 21, 36, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 16px 48px -8px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: 2.25rem 2.5rem;
}
.connect-screen .portal-head { margin-bottom: 0.75rem; }
.connect-screen .tagline { margin-top: .45rem; font-size: 0.95rem; color: var(--muted); }

/* Hero split layout */
/* Two columns above 62rem, as the mockup lays it out: the sentence on the left, the thing the
   sentence is about on the right. The decorative network image that used to sit there was removed
   for describing the product rather than doing anything, and that still holds -- what is there now
   is the session surface itself, in the words the running product uses. One column below the
   breakpoint, words first. */
.hero-split-layout { margin-bottom: 1.5rem; }
@media (min-width: 62rem) {
  /* Only when the preview is actually there. A grid track with nothing in it still takes its
     27rem, and that is what squeezed the signed-in join panel into a sliver on CQA: the node is
     absent for a signed-in person, the column was not. */
  .hero-split-layout:has(> .session-preview) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 31rem);
    gap: 2.5rem;
    align-items: start;
  }
  .hero-split-layout:has(> .session-preview) > .session-preview { margin-top: 2.6rem; }
}
.join-section { margin-top: 0; padding-top: 0; border-top: 0; }
.join-section .portal-head h2 { margin: 0; font-size: 1.05rem; }
.customer-head { display: block; margin-bottom: 1rem; }
.customer-head .tagline { margin-top: .4rem; max-width: 40rem; }
.hero-left-column {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  min-width: 0;
}
.connection-form { display: grid; gap: .75rem; }
.connection-primary { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .85rem; align-items: end; }
.connection-primary .field { min-width: 0; }
.connection-primary .field input {
  min-height: 48px; padding: .65rem .85rem; border-radius: 12px; font-size: 1rem;
  background: var(--field-surface); border: 1px solid var(--border);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.connection-primary .field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.connection-primary > .connect {
  margin: 0; min-height: 48px; min-width: 130px; align-self: end; border-radius: 999px;
}
.connect-screen .connection-state { padding: 0.25rem 0; gap: .5rem; font-size: .84rem; }
.connect-screen .connection-state > span:last-child { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .65rem; }
.connect-screen .connection-state strong { font-weight: 600; color: var(--fg); }
.connect-screen .connection-state-dot { width: .6rem; height: .6rem; flex-shrink: 0; margin-top: .35rem; }
.connect-screen .connection-state-hint { font-size: inherit; }
.connect-screen .connection-advanced { border-top: 0; padding-top: 0; margin-top: .5rem; }
.connect-screen .connection-advanced > summary { min-height: 44px; font-weight: 500; }
.connect-screen .advanced-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); margin: .4rem 0; }
.connect-screen .session-details > summary, .connect-screen .tools-disclosure > summary { min-height: 44px; }
.connect-screen > .hero, .connect-screen > .open-in-app { margin-top: 1.5rem; }


.connect-auth {
  margin: 0 0 0.95rem;
  padding: 1rem 1.25rem;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  background: rgba(10, 15, 26, 0.5);
  backdrop-filter: blur(14px);
  display: grid;
  gap: 0.75rem;
}
.connect-auth-note {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}
.connect-auth .identity-provider {
  min-height: 44px;
  border-radius: 999px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  color: var(--fg);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  transition: all 0.15s ease;
}
.connect-auth .identity-provider:hover {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface-raised));
  border-color: var(--accent);
  transform: translateY(-1px);
}
.invite-qr-actions button,
.invite-qr-actions label.invite-qr-file,
.invite-qr-capture-actions button,
.invite-qr-capture-actions label.invite-qr-file {
  border-radius: 999px;
  padding: 0.5rem 1.2rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  color: var(--fg);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.88rem;
  transition: all 0.15s ease;
}
.invite-qr-actions button:hover,
.invite-qr-actions label.invite-qr-file:hover,
.invite-qr-capture-actions button:hover,
.invite-qr-capture-actions label.invite-qr-file:hover {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface-raised));
  border-color: var(--accent);
  transform: translateY(-1px);
}
.route-note {
  color: var(--muted);
  font-size: 0.82rem;
}
.identity-provider-actions {
  display: grid;
  gap: 0.45rem;
}
.identity-provider-actions .identity-provider {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  width: 100%;
  margin: 0;
}
.home-provider {
  justify-content: center;
}
/* Room content fills the workspace; the invite form keeps a readable width. */
.shell-main:has(.workspace-surface) { width: 100%; }
.workspace-surface { display: flex; flex-direction: column; width: 100%; margin: 1rem auto; }

/* Signed in, the join controls and directory are the screen. A repeated Support heading consumed
   an otherwise empty row, so the working surfaces now start at the top of the canvas. */
.workspace-signed-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "join" "start";
  row-gap: .75rem;
  align-items: start;
  max-width: none;
}
.workspace-signed-in .workspace-customer-slot { display: none; }
.workspace-signed-in .workspace-collaborate-slot { grid-area: start; min-width: 0; }
.workspace-signed-in .workspace-join { grid-area: join; min-width: 0; }
/* The collaborate screen is a column here, not a page section: no rule above it, no extra top. */
.workspace-signed-in .collaborate-screen { margin-top: 0; padding-top: 0; border-top: 0; }
.workspace-signed-in .workspace-join .portal { background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 1rem 1.15rem; }
.workspace-signed-in .workspace-join h2 { font-size: 1.05rem; margin: 0 0 .15rem; }
.workspace-signed-in .workspace-join .tagline { font-size: .9rem; color: var(--muted); margin: 0 0 .6rem; }

/* A session in progress is the whole screen: the invite field and the second column would be two
   more things to read while the one thing that matters is preparing. */
.workspace-signed-in:has(.in-focus-mode) { grid-template-columns: minmax(0, 1fr); grid-template-areas: "start"; max-width: none; }
.workspace-signed-in:has(.in-focus-mode) .workspace-join { display: none; }

/* The region title and empty-state line repeat the controls directly below them. */
.workspace-signed-in #journey-root > .collaboration-region > .collaboration-region-title,
.workspace-signed-in #journey-root > .collaboration-region > .room-empty { display: none; }

@media (max-width: 62rem) {
  .workspace-signed-in { grid-template-columns: minmax(0, 1fr); grid-template-areas: "join" "start"; row-gap: .75rem; }
}
.workspace-surface .portal { width: 100%; max-width: none; margin: 0; padding: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
.workspace-surface .collaborate-screen { max-width: none; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--separator); }
.workspace-surface h1 { font-size: 2rem; letter-spacing: -.035em; }
.workspace-surface .collaboration-region-title { font-size: 1.2rem; font-weight: 600; }
.workspace-surface .placeholder-panel { border-top: 0; padding-top: 0.5rem; }
/* #journey-root is capped at 52rem for its own page, where it is a column of prose. Inside the
   workspace it holds the rooms board, and that cap is what kept the board at 832px on a 1440px
   screen while the window sat empty beside it. */
.workspace-surface #journey-root,
.workspace-surface .placeholder-panel,
.workspace-surface .collaboration-region { max-width: none; }
.workspace-surface .room-empty { border: 0; padding: 0; margin: .75rem 0; border-radius: 0; }
.workspace-surface .meeting-accounts > summary { grid-column: 1 / -1; cursor: pointer; min-height: 44px; padding: .65rem 0; color: var(--muted); font-weight: 500; }
.workspace-surface .meeting-accounts > summary::before { content: "▸"; margin-right: .5rem; }
.workspace-surface .meeting-accounts[open] > summary::before { content: "▾"; }
.workspace-surface .meeting-accounts:not([open]) > :not(summary) { display: none; }
.workspace-surface .meeting-accounts { padding: .25rem 0; }
.workspace-surface .collaboration-more > summary, .workspace-surface .existing-room > summary { font-weight: 500; color: var(--muted); }
.invite-qr-actions { display: flex; gap: .5rem; flex-wrap: wrap; align-items: start; }
.invite-qr-actions .copy { margin: 0; color: var(--fg); background: transparent; min-height: 44px; padding: .5rem .65rem; font-size: .85rem; }
.room-consent { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .75rem; margin: .1rem 0 .5rem; }
.room-consent .remember { margin-top: 0; }
.room-consent .copy { margin: 0; color: var(--fg); background: transparent; min-height: 44px; padding: .5rem .65rem; font-size: .85rem; }
.room-consent .term-err { flex-basis: 100%; margin: 0; }
inetgarden-qr-capture { display: block; flex: 1 1 22rem; min-width: 0; border-radius: 9px; }
.invite-qr-capture-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.invite-qr-drop-hint { color: var(--muted); font-size: .78rem; }
inetgarden-qr-capture.drag-over { outline: 2px solid var(--accent); outline-offset: 4px; background: var(--selected-surface, var(--field-surface)); }
.invite-qr-status { margin: .4rem 0 0; font-size: .82rem; color: var(--muted); }
.invite-qr-status:empty { display: none; }
inetgarden-qr-capture video { display: block; width: min(100%, 24rem); max-height: 16rem; object-fit: contain; margin-top: .65rem; border-radius: 9px; background: #000; }
inetgarden-qr-capture video[hidden] { display: none; }
.invite-qr-header .copy { margin-top: 0; }
.invite-qr-dialog, .room-terminal-confirmation { width: min(28rem, calc(100% - 2rem)); max-height: calc(100dvh - 2rem); overflow: auto; padding: 1.5rem; border: 1px solid var(--separator); border-radius: 18px; background: var(--surface-raised); color: var(--fg); box-shadow: 0 16px 60px #0004; }
.invite-qr-dialog::backdrop, .room-terminal-confirmation::backdrop { background: #0008; }
.invite-qr-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.invite-qr-header h2 { margin: 0; font-size: 1.25rem; }
.invite-qr-dialog p, .room-terminal-confirmation p { font-size: .9rem; line-height: 1.5; }
.invite-qr-code { display: block; width: min(100%, 260px); height: auto; margin: 1.25rem auto; }
.invite-qr-link { overflow-wrap: anywhere; user-select: all; }
.invite-qr-file { position: relative; display: inline-flex; align-items: center; max-width: 14rem; min-width: 0; cursor: pointer; }
.invite-qr-file span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.invite-qr-file input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.invite-qr-file:focus-within { outline: 3px solid var(--accent); outline-offset: 2px; }
@media (max-width: 40rem) {
  .connection-primary { grid-template-columns: minmax(0, 1fr); }
  .connection-primary > .connect { width: 100%; margin-top: 0; }
  .connect-screen .advanced-grid { grid-template-columns: minmax(0, 1fr); }
}

/* The signed-out hero. Built from Jorge's mockup: a small coloured eyebrow, one large headline, a
   calm subhead, then the three things the product promises. It uses the theme tokens rather than the
   mockup's fixed light palette, so the same markup is the white page in light mode and stays legible
   when the person has chosen dark. */
.landing-hero { max-width: 52rem; }

.landing-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.75rem;
  font-size: 0.8125rem;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.landing-eyebrow::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.landing-headline {
  margin: 0 0 1rem;
  font-size: clamp(2rem, 5.5vw, 3.25rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  font-weight: 700;
  text-wrap: balance;
}

.landing-subhead {
  margin: 0 0 1.5rem;
  font-size: clamp(1rem, 1.6vw, 1.125rem);
  line-height: 1.55;
  color: var(--muted);
  max-width: 32rem;
}

/* The assurances read as one sentence of guarantees, wrapping to a column on a phone rather than
   collapsing into an unreadable run of separators. */
.landing-assurances {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  color: var(--muted);
}
.landing-assurances li { display: flex; align-items: center; gap: 0.75rem; }
/* The separator trails its item rather than leading the next one. When the line wraps -- and at this
   column width it does -- a trailing dot ends a line, where a leading one would start the next line
   with a stray mark. The mockup places them the same way. */
.landing-assurances li:not(:last-child)::after {
  content: "";
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.55;
  flex: none;
}
.landing-assurances li:first-child { color: var(--ok); font-weight: 600; }

@media (max-width: 40rem) {
  .landing-assurances { flex-direction: column; gap: 0.375rem; }
  .landing-assurances li:not(:last-child)::after { display: none; }
}


/* The session preview. The mockup's panel chrome -- a dark rounded card with a quiet title bar, a
   row of people, and a footer of what is shared -- carrying Inetgarden's own surface. It is dark in
   both themes on purpose: a terminal is dark, and the panel is a picture of one. */
.session-preview {
  border-radius: 1rem;
  overflow: hidden;
  border: 1px solid #1e293b;
  background: #020617;
  color: #e2e8f0;
  box-shadow: 0 24px 48px -24px rgb(2 6 23 / 55%);
  font-size: 0.8125rem;
  user-select: none;
}

.session-preview-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.625rem 0.875rem;
  background: #0b1120;
  border-bottom: 1px solid #1e293b;
  flex-wrap: wrap;
}
.session-preview-seal {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  color: #38bdf8;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}
.session-preview-seal::before { content: "\1f512"; font-size: 0.6875rem; color: #34d399; }
.session-preview-sep { color: #334155; font-size: 0.75rem; }
.session-preview-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.75rem;
  color: #f8fafc;
  font-weight: 600;
}
.session-preview-room {
  color: #94a3b8;
  font-size: 0.75rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.session-preview-toggle {
  display: inline-flex;
  background: #020617;
  padding: 2px;
  border-radius: 6px;
  border: 1px solid #1e293b;
  margin-left: auto;
}
.session-preview-tab {
  background: transparent;
  border: none;
  color: #94a3b8;
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  font-size: 0.725rem;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.15s ease;
}
.session-preview-tab.active {
  background: #2563eb;
  color: #ffffff;
}
.session-preview-latency {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.7rem;
  color: var(--ok, #34d399);
  background: rgba(52, 211, 153, 0.1);
  border: 1px solid rgba(52, 211, 153, 0.25);
  padding: 0.2rem 0.45rem;
  border-radius: 6px;
  white-space: nowrap;
}

.session-preview-people {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.6rem 0.875rem;
  background: #080d1a;
  border-bottom: 1px solid #1e293b;
}
.session-preview-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0.5rem;
  border-radius: 6px;
  border: 1px solid #1e293b;
  background: #0f172a;
  color: #e2e8f0;
  font-size: 0.75rem;
}
.session-preview-chip.is-host { border-color: #065f46; color: #a7f3d0; }
.session-preview-chip.is-you.active { border-color: #15803d; }
.session-preview-avatar {
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6rem;
  font-weight: 700;
}
.session-preview-avatar.host { background: #065f46; color: #a7f3d0; }
.session-preview-avatar.guest { background: #1e3a8a; color: #bfdbfe; }
.session-preview-avatar.you { background: #15803d; color: #86efac; }
.session-preview-role-tag {
  font-size: 0.6875rem;
  padding: 1px 4px;
  border-radius: 3px;
  background: #1e293b;
  color: #94a3b8;
}
.session-preview-role-tag.owner { background: #7c2d12; color: #fed7aa; }
.session-preview-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
}
.session-preview-dot.online { background: #34d399; }
.session-preview-dot.idle { background: #94a3b8; }
.session-preview-epoch-group {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.session-preview-epoch-label {
  font-size: 0.725rem;
  color: #86efac;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.session-preview-control-btn {
  background: rgba(37, 99, 235, 0.2);
  border: 1px solid #2563eb;
  color: #60a5fa;
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  font-size: 0.725rem;
  cursor: pointer;
  transition: background 0.15s ease;
}
.session-preview-control-btn:hover { background: rgba(37, 99, 235, 0.35); }

.session-preview-terminal-body {
  padding: 0.875rem 1rem;
  background: #020617;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  line-height: 1.5;
}
.session-preview-provenance {
  color: #64748b;
  border-left: 2px solid #334155;
  padding-left: 0.65rem;
  margin-bottom: 0.75rem;
  font-size: 0.725rem;
  white-space: pre-line;
}
.session-preview-cmd-line {
  color: #f8fafc;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.session-preview-prompt { color: #34d399; font-weight: 600; }
.session-preview-cmd-text { color: #f8fafc; }
.session-preview-author { color: #60a5fa; font-size: 0.725rem; }

.session-preview-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.4rem 0 0.75rem;
  font-size: 0.74rem;
  color: #cbd5e1;
}
.session-preview-table th {
  text-align: left;
  color: #64748b;
  font-weight: 600;
  padding: 0.2rem 0.4rem;
  border-bottom: 1px solid #1e293b;
}
.session-preview-table td { padding: 0.25rem 0.4rem; }
.session-preview-table .status-running { color: #34d399; }
.session-preview-table .status-crash { color: #f87171; font-weight: 500; }
.session-preview-table .row-crash td { background: rgba(248, 113, 113, 0.04); }

.session-preview-pre {
  margin: 0.4rem 0 0.75rem;
  padding: 0.5rem 0.65rem;
  background: #090e1a;
  border: 1px solid #1e293b;
  border-radius: 6px;
  color: #94a3b8;
  font-size: 0.725rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-all;
}

.session-preview-diag {
  margin: 0.6rem 0;
  padding: 0.6rem 0.75rem;
  border-radius: 8px;
  background: rgba(88, 28, 135, 0.2);
  border: 1px solid rgba(168, 85, 247, 0.35);
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  color: #f3e8ff;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 0.75rem;
  line-height: 1.4;
}
.session-preview-diag-icon { font-size: 1rem; flex-shrink: 0; }
.session-preview-diag-content { flex: 1; }
.session-preview-diag-content strong { color: #e9d5ff; }
.session-preview-diag-content p { margin: 0.2rem 0; color: #d8b4fe; }
.session-preview-diag-btn {
  margin-top: 0.25rem;
  background: #7e22ce;
  color: #ffffff;
  border: none;
  border-radius: 4px;
  padding: 0.25rem 0.5rem;
  font-size: 0.7rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  cursor: pointer;
  transition: background 0.15s ease;
}
.session-preview-diag-btn:hover { background: #9333ea; }

.session-preview-qc {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid #1e293b;
  flex-wrap: wrap;
}
.session-preview-qc-label {
  color: #64748b;
  font-size: 0.7rem;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.session-preview-qc-pill {
  background: #1e293b;
  border: 1px solid #334155;
  color: #cbd5e1;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.7rem;
  padding: 0.15rem 0.45rem;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s ease;
}
.session-preview-qc-pill:hover {
  background: #334155;
  color: #ffffff;
  border-color: #60a5fa;
}

.session-preview-steps {
  margin: 0;
  padding: 1rem 0.875rem;
  list-style: none;
  display: grid;
  gap: 0.625rem;
}
.session-preview-steps li { display: flex; align-items: center; gap: 0.5rem; color: #94a3b8; }
.session-preview-steps li::before {
  content: "";
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  border: 1px solid #334155;
  flex: none;
}
.session-preview-steps li.is-done { color: #e2e8f0; }
.session-preview-steps li.is-done::before {
  content: "\2713";
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.625rem;
  color: #022c22;
  background: var(--ok, #34d399);
  border-color: var(--ok, #34d399);
}
.session-preview-steps li.is-live { color: #f1f5f9; }
.session-preview-steps li.is-live::before { border-color: #38bdf8; box-shadow: inset 0 0 0 3px #38bdf8; }

.session-preview-foot {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 0.875rem;
  border-top: 1px solid #1e293b;
  background: #0f172a;
}
.session-preview-tag {
  padding: 0.1875rem 0.5rem;
  border-radius: 0.375rem;
  background: #1e293b;
  color: #cbd5e1;
  font-size: 0.75rem;
}
.session-preview-stop { margin-left: auto; color: #fca5a5; font-size: 0.75rem; }


/* ---- The visitor landing, signed out ---- */

/* The sign-in block was a translucent dark card holding translucent white pills: a dark-theme
   drawing that on the light page became a grey slab with three grey buttons. The mockup puts no
   box around its call to action, so neither does this. */
.landing-visitor .connect-auth {
  margin: 0.25rem 0 0;
  padding: 0;
  border: 0;
  background: transparent;
  backdrop-filter: none;
  box-shadow: none;
  gap: 0.625rem;
}
.connect-auth-lead { margin: 0; font-weight: 650; font-size: 1rem; color: var(--fg); }
.landing-visitor .connect-auth-note { font-size: 0.8125rem; }
/* Sign-in is a short decision over the landing page, so keep the page and its actions in place.
   The fixed layer also gives the chooser a clear modal boundary for keyboard and screen-reader use. */
.sign-in-modal-layer {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: max(1rem, env(safe-area-inset-top)) max(1rem, env(safe-area-inset-right))
    max(1rem, env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
  background: rgb(15 23 42 / 38%);
  backdrop-filter: blur(8px);
}
.sign-in-modal-card {
  width: min(100%, 25rem);
  max-height: min(90dvh, 40rem);
  overflow: auto;
  display: grid;
  gap: 0.875rem;
  padding: 1.25rem;
  border: 1px solid var(--border);
  border-radius: 1rem;
  background: var(--surface-raised);
  color: var(--fg);
  box-shadow: 0 24px 70px rgb(15 23 42 / 28%);
}
.sign-in-modal-head { display: flex; align-items: center; gap: 1rem; }
.sign-in-modal-head .connect-auth-lead { font-size: 1.125rem; letter-spacing: -0.015em; }
.sign-in-modal-close {
  width: 44px;
  height: 44px;
  margin-left: auto;
  padding: 0;
  flex: none;
  display: inline-grid;
  place-items: center;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.sign-in-modal-close:hover { background: var(--card); color: var(--fg); }
.sign-in-modal-close:focus-visible { outline: 2px solid var(--ig-primary, #b4551f); outline-offset: 2px; }
.sign-in-modal-close .portal-icon { width: 18px; height: 18px; }
.sign-in-modal-card .identity-provider-actions { width: 100%; }
/* The sign-in widget. One full-width row per provider, each wearing its own mark, stacked rather
   than wrapped: a row of pills made the choice look like tags, and a visitor scanning for the one
   identity they have reads a column faster than a wrapped row.
   Each provider keeps its own colours because that is how a person finds theirs. The marks are the
   official shapes in a single colour, which is how zoom, teams and slack are already carried in
   this sprite. */
.sign-in-modal-card .identity-provider-actions {
  display: grid;
  gap: 0.5rem;
  width: min(100%, 22rem);
}
.sign-in-modal-card .identity-provider-actions .identity-provider {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.7rem;
  width: 100%;
  min-height: 46px;
  padding: 0.6rem 1rem;
  border-radius: 0.7rem;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--fg);
  font-weight: 600;
  font-size: 0.9375rem;
  text-decoration: none;
  transform: none;
}
.sign-in-modal-card .identity-provider-actions .identity-provider .portal-icon { flex: 0 0 auto; width: 20px; height: 20px; }
.sign-in-modal-card .identity-provider-actions .identity-provider:hover { filter: brightness(0.98); transform: none; }
.sign-in-modal-card .identity-provider-actions .identity-provider:focus-visible { outline: 2px solid var(--ig-primary, #b4551f); outline-offset: 2px; }
/* Google's sheet puts its mark on white with a grey edge; GitHub's puts its on near-black. */
.sign-in-modal-card .identity-provider-actions .is-google { background: #fff; color: #1f1f1f; border-color: #dadce0; }
/* GitHub's near-black sits on the warm paper as a solid button. On the dark page it would vanish
   into the background, so there it keeps the same fill and gains an edge. */
.sign-in-modal-card .identity-provider-actions .is-github { background: #24292f; color: #fff; border-color: #57606a; }
:root[data-theme="light"] .sign-in-modal-card .identity-provider-actions .is-github { border-color: #24292f; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .sign-in-modal-card .identity-provider-actions .is-github,
  :root[data-theme="system"] .sign-in-modal-card .identity-provider-actions .is-github { border-color: #24292f; }
}
.sign-in-modal-card .identity-provider-actions .is-email .portal-icon { color: var(--muted); }

/* The join path is the second path: the same controls, quieter. */
.landing-join-lead { margin: 0.5rem 0 -0.5rem; font-size: 0.9375rem; color: var(--muted); }
.landing-join-lead strong { color: var(--fg); font-weight: 650; }
.landing-visitor .connection-primary .field input { min-height: 44px; font-size: 0.95rem; box-shadow: none; }
.landing-visitor .connection-primary > .connect { min-height: 44px; min-width: 0; padding-inline: 1.1rem; font-size: 0.9rem; }
.landing-visitor .invite-qr-actions button,
.landing-visitor .invite-qr-actions label.invite-qr-file {
  background: transparent; border: 0; backdrop-filter: none; padding: 0.35rem 0.25rem;
  font-size: 0.85rem; color: var(--muted); text-decoration: underline; text-underline-offset: 0.2em;
}
.landing-visitor .invite-qr-actions button:hover,
.landing-visitor .invite-qr-actions label.invite-qr-file:hover { transform: none; color: var(--fg); background: transparent; }
.landing-visitor .connection-state { font-size: 0.8125rem; }

/* The sidebar repeated the same three sign-in links a few centimetres from the call to action.
   On the landing they are the call to action; twice on one screen weakens both. */
.app-shell:has(.landing-visitor) .sidebar-sign-in { display: none; }

/* A disabled action was a near-black pill on the light page. Tokens, so it is quiet in both themes. */
.connect.disabled, .connect:disabled {
  background: color-mix(in srgb, var(--muted) 16%, transparent);
  color: var(--muted);
  border-color: transparent;
}

/* ---- Visitor landing v1, from ui-mock-landing.md ---- */

/* A visitor on the landing gets a top bar, not the application sidebar. The grid loses its first
   column and the sidebar tint; the main column takes the page. */
.app-shell[data-visitor="true"] { grid-template-columns: minmax(0, 1fr); background-image: none; }
/* Every child moves to the single column. A child left in column 2 makes the browser create an
   implicit second track, which silently narrowed the whole page to 1137px of 1440. */
.app-shell[data-visitor="true"] .shell-main { grid-column: 1; width: min(100%, 76rem); padding-top: 1.5rem; }
.app-shell[data-visitor="true"] .shell-foot,
.app-shell[data-visitor="true"] .notification-region { grid-column: 1; }
.visitor-bar {
  grid-column: 1; grid-row: 2; position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 1.5rem; padding: 0.75rem 3rem; min-height: 4rem;
  background: color-mix(in srgb, var(--bg) 92%, transparent); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--separator);
}
.visitor-bar .brand { padding: 0.25rem 0; }
.visitor-nav { display: flex; gap: 1.5rem; font-size: 0.9rem; font-weight: 600; }
.visitor-nav a { color: var(--fg); text-decoration: none; opacity: 0.85; }
.visitor-nav a:hover { opacity: 1; color: var(--accent); }
.visitor-actions { margin-left: auto; display: flex; align-items: center; gap: 1rem; font-size: 0.9rem; font-weight: 600; }
.visitor-actions a { color: var(--fg); text-decoration: none; white-space: nowrap; }
.visitor-actions .visitor-start { margin: 0; min-height: 40px; padding: 0.5rem 1.1rem; font-size: 0.9rem; }
@media (max-width: 64rem) {
  .visitor-bar { padding: 0.6rem 1rem; gap: 1rem; }
  /* Join a room goes too: the hero's own button is immediately below it, and with the theme
     control added the row no longer fits a phone. */
  .visitor-nav, .visitor-signin, .visitor-join { display: none; }
  .visitor-bar .theme-control select { padding: 0.35rem 1.6rem 0.35rem 0.6rem; font-size: 0.8125rem; }
}

/* The brief's proportions: words at 45%, the room at 55%, top-aligned. */
@media (min-width: 62rem) {
  .hero-split-layout:has(> .session-preview) { grid-template-columns: minmax(0, 45fr) minmax(0, 55fr); gap: 3rem; }
  .hero-split-layout:has(> .session-preview) > .session-preview { margin-top: 2.25rem; }
}
.landing-start { margin: 0; min-height: 48px; padding: 0.75rem 1.6rem; font-size: 1rem; }
/* The rules that used to sit here turned the providers back into quiet underlined text, which is
   what the widget above replaces: a person signing in is looking for the identity they own, and a
   mark finds it faster than a sentence. Removed rather than overridden, so there is one place that
   decides how a provider row looks. */

/* The room panel: a title, the people, three surfaces, and a footer that names the call's provider. */
.session-preview-bar > div { display: grid; gap: 0.125rem; }
.session-preview-title { font-weight: 650; color: #f1f5f9; font-size: 0.9375rem; }
.session-preview-sub { color: #94a3b8; font-size: 0.75rem; }
.session-preview-chip strong { color: #f1f5f9; font-weight: 650; }
.session-preview-tabs { display: flex; gap: 0.25rem; padding: 0.5rem 0.875rem 0; border-bottom: 1px solid #1e293b; }
.session-preview-tab {
  min-height: 36px; padding: 0.4rem 0.8rem; border: 0; border-bottom: 2px solid transparent; border-radius: 0;
  background: transparent; color: #94a3b8; font: inherit; font-size: 0.8125rem; font-weight: 600; cursor: pointer;
}
.session-preview-tab.is-active { color: #f1f5f9; border-bottom-color: #34d399; }
.session-preview-body { display: grid; gap: 0.75rem; padding: 0.875rem; }
.session-preview-control {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.625rem 0.75rem; border: 1px solid #1e293b; border-radius: 0.625rem; background: #0f172a;
}
.session-preview-control > div { display: grid; gap: 0.125rem; }
.session-preview-control strong { color: #f1f5f9; font-size: 0.875rem; }
.session-preview-control-hint { color: #94a3b8; font-size: 0.75rem; }
.session-preview-control-btn {
  min-height: 36px; padding: 0.4rem 0.8rem; border-radius: 999px; border: 1px solid #334155;
  background: transparent; color: #e2e8f0; font: inherit; font-size: 0.8125rem; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.session-preview-control-btn:hover { border-color: #64748b; }
.session-preview-source {
  display: inline-block; margin-bottom: 0.375rem; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: #64748b;
}
.session-preview-remote { padding: 0.625rem 0.75rem; border: 1px solid #1e293b; border-radius: 0.625rem; background: #020617; }
.session-preview-pre {
  margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.75rem; line-height: 1.5;
  color: #cbd5e1; white-space: pre; overflow-x: auto;
}
.session-preview-files { padding: 0.875rem; }
.session-preview-files ul { margin: 0 0 0.5rem; padding: 0; list-style: none; display: grid; gap: 0.25rem; }
.session-preview-files li {
  display: flex; justify-content: space-between; gap: 1rem; padding: 0.5rem 0.625rem; border-radius: 0.5rem;
  background: #0f172a; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.75rem; color: #e2e8f0;
}
.session-preview-files li span { color: #94a3b8; }
.session-preview-files p, .session-preview-note { margin: 0; color: #94a3b8; font-size: 0.75rem; }
.session-preview-external { color: #cbd5e1; font-size: 0.75rem; }
.session-preview-stop {
  margin-left: auto; padding: 0; border: 0; background: transparent; color: #fca5a5; font: inherit; font-size: 0.75rem; font-weight: 600; cursor: pointer;
}
.session-preview { position: relative; }
.session-preview-dialog {
  position: absolute; inset: auto 0.875rem 0.875rem; padding: 0.875rem; display: grid; gap: 0.5rem;
  border: 1px solid #334155; border-radius: 0.75rem; background: #0f172a; box-shadow: 0 16px 40px -12px rgb(2 6 23 / 80%);
}
.session-preview-dialog strong { color: #f1f5f9; }
.session-preview-dialog p { margin: 0; color: #cbd5e1; font-size: 0.8125rem; }
.session-preview-dialog > div { display: flex; gap: 0.5rem; justify-content: flex-end; }
.session-preview-dialog .copy { min-height: 36px; padding: 0.4rem 0.9rem; font-size: 0.8125rem; }
.session-preview-stop.is-confirm { margin: 0; min-height: 36px; padding: 0.4rem 0.9rem; border-radius: 999px; background: #c0392b; color: #fff; }

/* The sections after the hero. Anchors sit below the sticky bar. */
.landing-sections { display: grid; gap: 3.5rem; margin: 3.5rem 0 2rem; }
.landing-section { scroll-margin-top: 5rem; max-width: 52rem; }
.landing-section h2 { margin: 0 0 1rem; font-size: clamp(1.375rem, 2.4vw, 1.75rem); letter-spacing: -0.02em; }
.landing-section p { color: var(--muted); max-width: 40rem; }
.landing-final { padding: 2rem 0 0; border-top: 1px solid var(--separator); }
.landing-final > div { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
.landing-final .connect { margin: 0; }
#join { scroll-margin-top: 5rem; }

/* A grid item's default min-width is its content's width, so the preformatted remote output was
   pushing the whole card past its column and the card's own overflow:hidden then clipped the
   button and the table's last column. Every box between the column and the <pre> may shrink; the
   <pre> alone scrolls. */
.hero-split-layout > * { min-width: 0; }
.session-preview, .session-preview-body, .session-preview-remote, .session-preview-control, .session-preview-control > div { min-width: 0; }
.session-preview-control-hint { white-space: normal; }
.session-preview-remote { overflow-x: auto; }
/* One button, its own width, as the brief draws it. The sign-in block is a grid, which stretches
   its items unless told otherwise. */
.landing-visitor .connect-auth { justify-items: start; }
.landing-start { width: max-content; max-width: 100%; }

/* On a phone the one action takes the width, as the brief draws the narrow layout. */
@media (max-width: 40rem) { .landing-start { width: 100%; } }

/* Plus Jakarta Sans, served from this origin. The mockup loads it and Cabinet Grotesk from Google
   Fonts; the landing test forbids any cross-origin request, and Cabinet Grotesk is not an open font
   in any case. This is one variable file covering 400-800, so the display weight costs no second
   download. Provenance, licence and hashes: third_party/web-fonts.VENDORED.md. */
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

/* ======================================================================
   The mockup's visual system, on the visitor landing
   ======================================================================
   Taken from mockmock-main: slate neutrals, a blue-600 primary, emerald kept
   for status only, and a dark slate-950 product surface on a bright page. The
   brief asks for exactly that split ("blue primary actions, restrained green
   status accents"), so green stops being the action colour here and becomes the
   colour of a promise being kept.

   Scoped to [data-visitor="true"]. The signed-in product keeps Inetgarden's
   green brand: this is a landing-page brief, and restyling every button behind
   the sign-in would be a different decision than the one asked for.

   Tailwind's palette, written out because there is no Tailwind here:
     slate  200 #e2e8f0  300 #cbd5e1  400 #94a3b8  500 #64748b  600 #475569
            700 #334155  800 #1e293b  900 #0f172a  950 #020617
     blue   400 #60a5fa  500 #3b82f6  600 #2563eb  700 #1d4ed8
     emerald 400 #34d399  600 #059669

   No webfonts: the landing test asserts zero cross-origin requests, and nothing
   is self-hosted. Plus Jakarta Sans and Cabinet Grotesk are therefore taken as a
   treatment -- heavier display weights, tighter tracking, balanced wrapping --
   rather than as files. */

/* ---- The warm palette, declared once ---------------------------------------------------------
   Cream paper, terracotta for action, near-black ink, and colour used only where it means
   something. Both surfaces that wear it -- the rooms board and the signed-out landing -- read
   these tokens rather than carrying their own copies, because two copies of a palette are two
   palettes as soon as one of them is edited.

   Dark is the default here, matching the rest of the visitor styles; the two light blocks below
   are the pair this file already uses everywhere for an appearance switch. */
:root {
  --w-paper: #14161a;
  --w-sidebar: #101216;
  --w-sidebar-line: #232831;
  --w-card: #1b1f26;
  --w-raised: #232831;
  --w-line: #2b313b;
  --w-line-soft: #232831;
  --w-line-strong: #3a4250;
  --w-ink: #f2ede4;
  --w-ink-2: #c3bcb0;
  --w-ink-3: #9a9285;
  --w-ink-4: #7d7669;
  --w-accent: #d9865a;
  --w-accent-hover: #e89a70;
  --w-accent-fg: #1b1005;
  --w-accent-soft: #2a1f19;
  --w-deep: #e9e3d8;
  --w-deep-fg: #14161a;
  --w-live: #5cc47e;
  --w-live-soft: #16241b;
  --w-wait: #d9a441;
  --w-wait-soft: #251d10;
}
:root[data-theme="light"] {
  --w-paper: #f6f1e7;
  --w-sidebar: #efe8da;
  --w-sidebar-line: #e0d6c3;
  --w-card: #ffffff;
  --w-raised: #faf6ee;
  --w-line: #e6ddcc;
  --w-line-soft: #efe8db;
  --w-line-strong: #d6cab3;
  --w-ink: #17212e;
  --w-ink-2: #34404f;
  --w-ink-3: #6f6759;
  --w-ink-4: #8b8375;
  --w-accent: #a85426;
  --w-accent-hover: #8d431c;
  --w-accent-fg: #ffffff;
  --w-accent-soft: #f7ede6;
  --w-deep: #1e2b3a;
  --w-deep-fg: #f6f1e7;
  --w-live: #3f8f5f;
  --w-live-soft: #e7f3eb;
  --w-wait: #b8761f;
  --w-wait-soft: #fbf1e0;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme]), :root[data-theme="system"] {
    --w-paper: #f6f1e7;
    --w-sidebar: #efe8da;
    --w-sidebar-line: #e0d6c3;
    --w-card: #ffffff;
    --w-raised: #faf6ee;
    --w-line: #e6ddcc;
    --w-line-soft: #efe8db;
    --w-line-strong: #d6cab3;
    --w-ink: #17212e;
    --w-ink-2: #34404f;
    --w-ink-3: #6f6759;
    --w-ink-4: #8b8375;
    --w-accent: #a85426;
    --w-accent-hover: #8d431c;
    --w-accent-fg: #ffffff;
    --w-accent-soft: #f7ede6;
    --w-deep: #1e2b3a;
    --w-deep-fg: #f6f1e7;
    --w-live: #3f8f5f;
    --w-live-soft: #e7f3eb;
    --w-wait: #b8761f;
    --w-wait-soft: #fbf1e0;
  }
}

.app-shell[data-visitor="true"] {
  font-family: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* The landing wears the same palette as the rooms board. It used to carry its own blue-on-slate
     set, declared three times over for the three appearances; all of that is now one declaration
     above, and this block only says which of its names each surface token takes. */
  --ig-primary: var(--w-accent);
  --ig-primary-hover: var(--w-accent-hover);
  --ig-primary-fg: var(--w-accent-fg);
  --ig-status: var(--w-live);
  --ig-panel: var(--w-paper);
  --ig-panel-raised: var(--w-card);
  --ig-panel-line: var(--w-line);
  --bg: var(--w-paper);
  --card: var(--w-card);
  --fg: var(--w-ink);
  --muted: var(--w-ink-3);
  --border: var(--w-line);
  --separator: var(--w-line);
  --field-surface: var(--w-card);
  /* Landing surfaces and inks. Every panel below the hero is written against these rather than
     against a hex, so the one set of rules serves both appearances. */
  --ld-surface: var(--w-card);
  --ld-surface-2: var(--w-raised);
  --ld-surface-3: var(--w-line-soft);
  --ld-line: var(--w-line);
  --ld-line-soft: var(--w-line-soft);
  --ld-line-strong: var(--w-line-strong);
  --ld-ink: var(--w-ink);
  --ld-ink-2: var(--w-ink-2);
  --ld-ink-3: var(--w-ink-3);
  --ld-ink-4: var(--w-ink-4);
}

/* The hero's faint blue wash, then white. The mockup's from-blue-50/50 via-white. */
.app-shell[data-visitor="true"] {
  background-color: var(--bg);
  background-image: linear-gradient(to bottom, color-mix(in srgb, var(--ig-primary) 7%, transparent) 0%, transparent 34rem);
}

/* Type. The display face is carried by weight and tracking rather than a font file. */
.app-shell[data-visitor="true"] .landing-headline {
  font-weight: 800;
  letter-spacing: -0.028em;
  line-height: 1.06;
  font-size: clamp(2.125rem, 4.4vw, 3rem);
}
.app-shell[data-visitor="true"] .landing-section h2 {
  font-weight: 800;
  letter-spacing: -0.03em;
}
.app-shell[data-visitor="true"] .landing-subhead {
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  line-height: 1.6;
}
/* The kicker: blue words, an emerald dot. Status is the only thing that is green. */
.app-shell[data-visitor="true"] .landing-eyebrow { color: var(--ig-primary); letter-spacing: 0.09em; }
.app-shell[data-visitor="true"] .landing-eyebrow::before { background: var(--ig-status); }

/* One primary action, in the mockup's blue, with its softer corner and lifted shadow. */
.app-shell[data-visitor="true"] .connect {
  background: var(--ig-primary);
  color: var(--ig-primary-fg);
  border: 0;
  border-radius: 0.625rem;
  box-shadow: 0 4px 14px -2px color-mix(in srgb, var(--ig-primary) 45%, transparent);
  letter-spacing: -0.01em;
}
.app-shell[data-visitor="true"] .connect:hover:not(:disabled) {
  background: var(--ig-primary-hover);
  filter: none;
  box-shadow: 0 6px 20px -2px color-mix(in srgb, var(--ig-primary) 55%, transparent);
}
.app-shell[data-visitor="true"] .connect:disabled,
.app-shell[data-visitor="true"] .connect.disabled {
  background: color-mix(in srgb, var(--muted) 18%, transparent);
  color: var(--muted);
  box-shadow: none;
}
.app-shell[data-visitor="true"] .visitor-nav a:hover,
.app-shell[data-visitor="true"] .landing-section a.copy { color: var(--ig-primary); }

/* Green survives as the colour of the promise, not of the button. */
.app-shell[data-visitor="true"] .landing-assurances li:first-child { color: var(--ig-status); }

/* Cards: slate-200 hairlines and a shadow you notice only by its absence. */
.app-shell[data-visitor="true"] .visitor-bar {
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border-bottom-color: var(--border);
}
.app-shell[data-visitor="true"] .connection-primary .field input {
  border-radius: 0.625rem;
  border-color: var(--border);
  box-shadow: none;
}
.app-shell[data-visitor="true"] .connection-primary .field input:focus {
  border-color: var(--ig-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ig-primary) 22%, transparent);
}

/* The product surface keeps its own dark palette in both appearances, as the mockup does:
   a dark panel is what makes a bright marketing page read as a product page. Its active
   surface tab moves to blue so the panel agrees with the page about which colour means
   "this is the thing selected". */
.app-shell[data-visitor="true"] .session-preview-tab.is-active { border-bottom-color: var(--ig-primary); }
.app-shell[data-visitor="true"] .session-preview-control-btn:hover { border-color: var(--ig-primary); color: #ffffff; }
.app-shell[data-visitor="true"] .session-preview {
  box-shadow: 0 28px 56px -28px rgb(2 6 23 / 55%), 0 0 0 1px rgb(255 255 255 / 10%);
}
:root[data-theme="light"] .app-shell[data-visitor="true"] .session-preview,
:root:not([data-theme]) .app-shell[data-visitor="true"] .session-preview {
  box-shadow: 0 28px 56px -28px rgb(2 6 23 / 40%), 0 0 0 1px rgb(2 6 23 / 8%);
}

/* ---- The sections the mockup carries, in Inetgarden's terms ---- */

/* Some sections want the page's width rather than a reading measure. */
.landing-section-wide { max-width: none; }


/* What changes. A table, because it is one: two named alternatives per row. */
.landing-shift { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.landing-shift th, .landing-shift td { padding: 0.8rem 1rem; text-align: left; vertical-align: top; }
.landing-shift thead th { font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.landing-shift tbody tr { border-top: 1px solid var(--separator); }
.landing-shift tbody th { font-weight: 650; width: 11rem; }
.landing-shift td { color: var(--muted); }
.landing-shift td.is-ours { color: var(--fg); font-weight: 550; }
@media (max-width: 48rem) {
  .landing-shift, .landing-shift tbody, .landing-shift tr, .landing-shift th, .landing-shift td { display: block; width: auto; }
  .landing-shift thead { display: none; }
  .landing-shift tbody tr { padding: 0.75rem 0; }
  .landing-shift tbody th { padding: 0 0 0.2rem; }
  .landing-shift td { padding: 0.1rem 0; }
  .landing-shift td.is-ours::before { content: "\2192\00a0"; color: var(--accent); }
}

/* Plan cards: the mockup's composition, the catalog's numbers. */
.landing-plans {
  margin: 1.75rem 0 0; padding: 0; list-style: none;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem;
  align-items: stretch;
}
.landing-plan {
  position: relative; display: grid; align-content: start; gap: 0;
  padding: 1.75rem 1.5rem; border-radius: 1rem;
  border: 1px solid var(--ld-line); background: var(--ld-surface);
}
/* The one card that is lifted, the way a pricing table lifts one. */
.landing-plan.is-featured {
  border-color: var(--ig-primary); border-width: 2px; padding: 1.7rem 1.45rem;
  box-shadow: 0 18px 40px -28px color-mix(in srgb, var(--ig-primary) 55%, transparent);
}
.landing-plan-badge {
  position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%);
  padding: 0.3rem 0.85rem; border-radius: 999px; white-space: nowrap;
  background: var(--ig-primary); color: var(--ig-primary-fg);
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.landing-plan h3 {
  margin: 0; font-size: 0.8125rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ld-ink-3); font-weight: 700;
}
.landing-plan.is-featured h3 { color: var(--ig-primary); }
/* The amount carries the weight; the interval sits on its baseline, small. */
.landing-plan-price {
  margin: 0.6rem 0 0 !important; display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap;
}
.landing-plan-price strong {
  font-size: 2.25rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1; color: var(--ld-ink);
}
.landing-plan-price span { font-size: 0.875rem; color: var(--ld-ink-3); }
.landing-plan-audience {
  margin: 0.75rem 0 0 !important; font-size: 0.875rem; color: var(--ld-ink-3); line-height: 1.5;
}
.landing-plan-features {
  margin: 1.25rem 0 0; padding: 1.25rem 0 0; list-style: none; display: grid; gap: 0.6rem;
  font-size: 0.875rem; color: var(--ld-ink-2); border-top: 1px solid var(--ld-line);
}
.landing-plan-features li { display: flex; gap: 0.6rem; line-height: 1.4; }
.landing-plan-features li::before { content: "\2713"; color: var(--ig-status); flex: none; font-weight: 700; }
/* The button sits on the floor of the card, so three cards of different lengths still line up. */
.landing-plan { grid-template-rows: auto auto auto 1fr auto; }
.landing-plan-cta {
  margin-top: 1.5rem; justify-content: center; width: 100%; min-height: 48px; text-decoration: none;
}
.landing-plan-cta:hover { text-decoration: none; }
@media (max-width: 60rem) {
  .landing-plans { grid-template-columns: minmax(0, 1fr); }
  .landing-plan.is-featured { margin-top: 0.75rem; }
}
.landing-plans-fallback { font-size: 0.9375rem; }

/* In the mockup's system the cards sit on hairlines with a shadow you notice by its absence. */
.app-shell[data-visitor="true"] .landing-plan { box-shadow: 0 1px 2px rgb(15 23 42 / 6%); }
.app-shell[data-visitor="true"] .landing-plan-features li::before,
.app-shell[data-visitor="true"] .landing-shift td.is-ours::before { color: var(--ig-status); }


/* ---- The brand's own surface treatment ----
   Inetgarden App UI Assets, page 3 "Backgrounds": a soft radial wash, a quarter-circle arc and a
   dotted field. Drawn in CSS rather than shipped as the PNG, so it costs nothing and follows the
   theme. The mockup contributed the palette; this is the part that was Inetgarden's already. */
.app-shell[data-visitor="true"] {
  background-image:
    radial-gradient(60rem 32rem at 82% -8%, color-mix(in srgb, var(--ig-primary) 13%, transparent), transparent 70%),
    radial-gradient(44rem 26rem at 6% 4%, color-mix(in srgb, var(--ig-status) 9%, transparent), transparent 68%),
    linear-gradient(to bottom, color-mix(in srgb, var(--ig-primary) 6%, transparent) 0%, transparent 36rem);
  background-repeat: no-repeat;
}
/* The dotted field, top left, as the sheet places it. */
.app-shell[data-visitor="true"] .shell-main { position: relative; }
.app-shell[data-visitor="true"] .shell-main::before {
  content: ""; position: absolute; top: 1.5rem; left: 1.5rem; width: 7rem; height: 4.5rem;
  background-image: radial-gradient(currentColor 1px, transparent 1px);
  background-size: 14px 14px; color: var(--muted); opacity: 0.28; pointer-events: none;
}
@media (max-width: 62rem) { .app-shell[data-visitor="true"] .shell-main::before { display: none; } }

/* ---- The session, stage by stage ---- */
.landing-walk-section { position: relative; }
.landing-walk-section > .landing-eyebrow { margin-bottom: 0.5rem; }
.landing-walk {
  margin-top: 1.5rem; padding: 1.25rem; border: 1px solid var(--border); border-radius: 1.25rem;
  background:
    radial-gradient(38rem 20rem at 100% 0%, color-mix(in srgb, var(--ig-primary) 10%, transparent), transparent 70%),
    var(--card);
}
.landing-walk-steps { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.25rem; }
.landing-walk-step {
  display: inline-flex; align-items: center; gap: 0.5rem; min-height: 40px;
  padding: 0.4rem 0.85rem; border: 1px solid var(--border); border-radius: 0.625rem;
  background: transparent; color: var(--muted); font: inherit; font-size: 0.875rem; font-weight: 600; cursor: pointer;
}
.landing-walk-step:hover { color: var(--fg); }
.landing-walk-num {
  width: 1.4rem; height: 1.4rem; border-radius: 50%; display: grid; place-items: center; flex: none;
  background: color-mix(in srgb, var(--muted) 18%, transparent); font-size: 0.75rem; font-weight: 700;
}
.landing-walk-step.is-done { color: var(--fg); }
.landing-walk-step.is-done .landing-walk-num { background: color-mix(in srgb, var(--ig-status) 22%, transparent); color: var(--ig-status); }
.landing-walk-step.is-active { color: var(--ig-primary-fg); background: var(--ig-primary); border-color: transparent; }
.landing-walk-step.is-active .landing-walk-num { background: rgb(255 255 255 / 25%); color: inherit; }

.landing-walk-screens { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); }
.landing-screen {
  display: flex; flex-direction: column; min-height: 17rem; min-width: 0;
  border: 1px solid var(--border); border-radius: 0.875rem; background: var(--bg); overflow: hidden;
}
.landing-screen-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.55rem 0.8rem; border-bottom: 1px solid var(--separator);
  background: color-mix(in srgb, var(--muted) 7%, transparent); font-size: 0.75rem;
}
.landing-screen-who { font-weight: 650; color: var(--fg); }
.landing-screen-url { font-family: var(--mono); color: var(--muted); }
.landing-screen-body {
  flex: 1; display: grid; gap: 0.5rem; justify-items: start; align-content: center;
  padding: 1.25rem; text-align: left;
}
/* A stage that carries a screenshot gives the frame over to it: no padding, no centring, and the
   image fills the width so the browser chrome above it reads as the window it belongs to. */
/* Every stage reserves the same space, whatever the shape of its screenshot. The shots differ in
   height - the ready-to-share panel is short, the joined room is tall - and letting each set the
   frame made the whole section jump as the reader stepped through it. The box is the tallest
   shot's ratio and the image sits centred inside it. */
.landing-screen-body.is-shot { padding: 0; display: grid; place-items: center; aspect-ratio: 960 / 531; }
.landing-screen-shot { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; }
.landing-screen-body strong { font-size: 1.0625rem; }
.landing-screen-body p { margin: 0; color: var(--muted); font-size: 0.875rem; line-height: 1.5; }
.landing-glyph { width: 2.25rem; height: 2.25rem; color: var(--ig-primary); }
.landing-screen-btn {
  display: inline-flex; align-items: center; min-height: 38px; padding: 0.45rem 1rem;
  border-radius: 0.625rem; background: var(--ig-primary); color: var(--ig-primary-fg);
  font-size: 0.875rem; font-weight: 700;
}
.landing-screen-btn.is-small { min-height: 32px; padding: 0.3rem 0.7rem; font-size: 0.8125rem; }
.landing-screen-note { font-size: 0.8125rem !important; }
.landing-screen-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.35rem; font-size: 0.875rem; }
.landing-screen-list li { display: flex; align-items: center; gap: 0.5rem; color: var(--muted); }
.landing-screen-list li::before {
  content: ""; width: 0.95rem; height: 0.95rem; border-radius: 50%; border: 1px solid var(--border); flex: none;
}
.landing-screen-list li.is-done { color: var(--fg); }
.landing-screen-list li.is-done::before {
  content: "\2713"; display: grid; place-items: center; font-size: 0.6rem;
  background: var(--ig-status); border-color: var(--ig-status); color: var(--bg);
}
.landing-screen-list li.is-live::before { border-color: var(--ig-primary); box-shadow: inset 0 0 0 3px var(--ig-primary); }
.landing-screen-link {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; width: 100%;
  padding: 0.4rem 0.4rem 0.4rem 0.7rem; border: 1px solid var(--border); border-radius: 0.625rem;
  background: var(--field-surface);
}
.landing-screen-linktext { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); overflow-wrap: anywhere; min-width: 0; }
.landing-screen-pre {
  margin: 0; width: 100%; padding: 0.6rem 0.7rem; border-radius: 0.5rem;
  background: color-mix(in srgb, var(--w-ink) 92%, #000);
  color: #cbd5e1; font-family: var(--mono); font-size: 0.72rem; line-height: 1.5; white-space: pre; overflow-x: auto;
}

/* Each screen closes with a status line, as a real one does: what is being shared on the left, and
   on the right the thing the reader is most likely to be wondering. */
.landing-screen-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.5rem 0.8rem; border-top: 1px solid var(--separator);
  background: color-mix(in srgb, var(--muted) 5%, transparent);
  font-family: var(--mono); font-size: 0.6875rem; color: var(--muted);
}
.landing-screen-btn.is-stop { background: transparent; border: 1px solid var(--border); color: #c0392b; font-weight: 600; }
.landing-walk-section .landing-section-lead { max-width: 46rem; }

/* The use-case panel. A dark slab on the bright page, copy left and the stats right, as sent.
   It stays dark in both appearances for the same reason the session panel does: it is the part of
   the page that is about the product rather than about the page. */
/* The small illustration inside the use-case copy. It complements the argument rather than leading
   it, so it is capped well below the column width and sits between the heading and the prose.
   The artwork is drawn on its own near-white ground, a cooler grey than this page's warm paper, so
   it cannot be blended invisibly into it: multiply and an edge fade both leave a seam along the
   straight sides. It is framed instead, with the border and radius the topology boxes and the
   stage screens use, so it reads as one more panel rather than a picture dropped on the page. */
.landing-chained { margin: 0 0 1.1rem; }
.landing-chained img {
  display: block; width: 100%; height: auto; max-width: 30rem;
  border: 1px solid var(--ld-line, var(--w-line)); border-radius: 0.75rem; background: #fff;
}

.landing-usecase {
  display: grid; gap: 2rem; padding: 2.25rem; border-radius: 1.25rem;
  background:
    radial-gradient(40rem 22rem at 100% 0%, color-mix(in srgb, var(--ig-primary) 16%, transparent), transparent 70%),
    var(--ld-surface);
  color: var(--ld-ink-2); border: 1px solid var(--ld-line);
}
@media (min-width: 62rem) {
  .landing-usecase { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 3rem; align-items: center; }
}
.landing-usecase-copy > .landing-eyebrow { color: var(--ig-primary); margin-bottom: 0.75rem; }
.landing-usecase-copy > .landing-eyebrow::before { background: var(--ok, #34d399); }
.landing-usecase h2 { margin: 0 0 0.9rem; color: var(--ld-ink); font-size: clamp(1.5rem, 2.8vw, 2.125rem); font-weight: 800; letter-spacing: -0.028em; line-height: 1.12; }
.landing-usecase p { margin: 0; color: var(--ld-ink-3); line-height: 1.6; }
/* Two paragraphs make the turn from the problem to the answer; without space between them the
   turn is invisible and they read as one block. */
.landing-usecase-copy p + p { margin-top: 0.9rem; }
.landing-usecase-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-top: 1.5rem; }
.landing-usecase-actions .connect { margin: 0; }
.landing-usecase-note { color: var(--ld-ink-4); font-size: 0.875rem; }
.landing-usecase-stats { display: grid; gap: 0.75rem; align-content: start; }
.landing-usecase-statlabel {
  margin: 0 !important; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ld-ink-4) !important;
}
.landing-stat { padding: 1.1rem 1.25rem; border-radius: 0.875rem; background: var(--ld-surface-2); border: 1px solid var(--ld-line); }
.landing-stat-figure { display: block; font-size: 2.5rem; font-weight: 800; letter-spacing: -0.03em; color: var(--ig-status); line-height: 1.05; }
.landing-stat p { margin-top: 0.35rem !important; font-size: 0.875rem; }
.landing-stat.is-list strong { color: var(--ld-ink); font-size: 0.9375rem; }
.landing-stat.is-list ul { margin: 0.5rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.3rem; font-size: 0.875rem; color: var(--ld-ink-3); }
.landing-stat.is-list li { display: flex; gap: 0.5rem; }
.landing-stat.is-list li::before { content: "\2713"; color: var(--ig-status); flex: none; }

/* ---- How it works, in the mockup's own treatment ----
   The reference screens are dark in both appearances, because the panes are a picture of software
   rather than part of the page. Step pills are monospace and numbered, the active one solid blue,
   a finished one marked with a green check. Pane bodies are centred under a tinted icon tile. */
.landing-walk {
  padding: 1.5rem;
  border: 1px solid var(--ld-line);
  background:
    radial-gradient(42rem 22rem at 100% 0%, color-mix(in srgb, var(--ig-primary) 12%, transparent), transparent 70%),
    var(--ld-surface);
}
.landing-walk-steps { gap: 0.625rem; margin-bottom: 1.5rem; }
.landing-walk-step {
  font-family: var(--mono); font-size: 0.8125rem; font-weight: 500; letter-spacing: -0.01em;
  min-height: 44px; padding: 0.5rem 1rem; border-radius: 0.5rem;
  border-color: var(--ld-line); background: var(--ld-surface-3); color: var(--ld-ink-3);
}
.landing-walk-step:hover { color: var(--ld-ink-2); border-color: var(--ld-line-strong); }
.landing-walk-step .landing-walk-num {
  display: inline; background: none; width: auto; height: auto; border-radius: 0;
  font-family: inherit; font-weight: 500; color: inherit;
}
.landing-walk-step .landing-walk-num::after { content: "."; }
.landing-walk-step.is-done {
  color: var(--ig-status);
  border-color: color-mix(in srgb, var(--ok, #34d399) 34%, var(--ld-line));
  background: color-mix(in srgb, var(--ok, #34d399) 11%, var(--ld-surface));
}
.landing-walk-step.is-done::after { content: "\2713"; margin-left: 0.35rem; color: var(--ok, #34d399); }
.landing-walk-step.is-active {
  background: var(--ig-primary); border-color: var(--ig-primary); color: var(--ig-primary-fg); font-weight: 600;
  box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--ig-primary) 60%, transparent);
}

.landing-screen {
  border-color: var(--ld-line); background: var(--ld-surface-2); color: var(--ld-ink-2);
  box-shadow: 0 10px 30px -18px rgb(2 6 23 / 80%);
}
.landing-screen-bar { background: transparent; border-bottom-color: var(--ld-line-soft); padding: 0.7rem 1rem; }
.landing-screen-who { color: var(--ld-ink); }
.landing-screen-url { color: var(--ld-ink-4); }
/* Centred, as the reference draws it: the pane is a screenshot, not a column of prose. */
.landing-screen-body { justify-items: center; text-align: center; gap: 0.6rem; padding: 1.75rem 1.25rem; }
.landing-screen-body strong { color: var(--ld-ink); }
.landing-screen-body p { color: var(--ld-ink-3); }
.landing-screen-list { justify-self: center; text-align: left; }
.landing-screen-list li { color: var(--ld-ink-3); }
.landing-screen-list li.is-done { color: var(--ld-ink-2); }
.landing-screen-list li::before { border-color: #334155; }
.landing-screen-list li.is-done::before { background: var(--ok, #34d399); border-color: var(--ok, #34d399); color: #04170f; }
.landing-screen-foot {
  background: transparent; border-top-color: var(--ld-line-soft); color: var(--ld-ink-4); padding: 0.65rem 1rem;
}
.landing-screen-link { background: var(--ld-surface-2); border-color: var(--ld-line); width: auto; max-width: 100%; }
.landing-screen-linktext { color: var(--ld-ink-3); }
.landing-screen-btn { box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--ig-primary) 55%, transparent); }
.landing-screen-btn.is-stop { border-color: #3f1d21; background: #1b1113; color: #fca5a5; box-shadow: none; }

/* The icon tile: a rounded square, tinted to the thing it stands for, holding the brand glyph. */
.landing-tile {
  display: grid; place-items: center; width: 3.25rem; height: 3.25rem; border-radius: 0.875rem;
  background: color-mix(in srgb, var(--ig-primary) 16%, transparent); color: var(--ig-primary);
}
.landing-tile.is-gear { background: rgb(245 158 11 / 16%); color: #fbbf24; }
.landing-tile.is-avatar { background: rgb(148 163 184 / 14%); color: var(--ld-ink-3); }
.landing-tile .landing-glyph { width: 1.75rem; height: 1.75rem; color: inherit; }

/* ---- The walkthrough holds still ----
   The stages were a wrapping flex row, so the moment a stage finished and grew a checkmark the
   pills reflowed onto two lines and the panes below changed height. A fixed five-column track and
   a reserved slot for the mark mean pressing a stage changes the contents and nothing else. */
.landing-walk-steps {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); align-items: stretch;
}
.landing-walk-step { justify-content: center; text-align: center; }
/* Always present, so the label does not shift sideways when the stage is marked done. */
.landing-walk-step::after {
  content: "\2713"; margin-left: 0.35rem; color: var(--ok, #34d399); visibility: hidden; flex: none;
}
.landing-walk-step.is-done::after { visibility: visible; }
/* The floor is the tallest stage (22.1rem at every width down to the breakpoint below), with a
   little headroom, so the panes keep one height instead of settling to whatever the stage holds. */
.landing-walk-screens { align-items: stretch; min-height: 23rem; }
.landing-walk .landing-screen { min-height: 0; }
@media (max-width: 52rem) {
  .landing-walk-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .landing-walk-screens { min-height: 0; }
}

/* ---- Two ways in, and they are not equal ----
   Someone who needs help creates the room; the expert they invited joins one. So the page offers
   one filled button and one quiet link, rather than a text field competing with the button. */
.landing-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
.landing-join-action {
  min-height: 48px; padding: 0.75rem 1.25rem; font-size: 0.9375rem; text-decoration: none;
}
.landing-join-action:hover { text-decoration: none; }

/* ---- Connection topology ----
   Four parties on one line: the expert outside, Inetgarden between, the person being helped, and
   the organisation they are already inside. The colours carry the meaning - violet for outside,
   blue for the carrier, green for the computer the session lands on, amber for the boundary the
   expert never crosses. */
.landing-topo {
  display: grid;
  /* The two cards holding a person need room for a list and a figure side by side; the arrows and
     the Inetgarden pill need only their own words. Rebalanced when the figures went in, because at
     the old widths every bullet broke into two lines against the drawing. */
  grid-template-columns:
    minmax(0, 1.2fr) 3.4rem minmax(0, 0.68fr) 3.4rem minmax(0, 1.3fr) 3.9rem minmax(0, 1.5fr);
  align-items: stretch; gap: 0.4rem; margin-top: 1.75rem;
}
.landing-topo-node,
.landing-topo-cloud,
.landing-topo-org {
  display: grid; align-content: start; gap: 0.2rem; min-width: 0;
  padding: 1rem 1.1rem; border-radius: 0.875rem;
  border: 1px solid var(--border); background: var(--ld-surface-2);
}
.landing-topo-node strong,
.landing-topo-cloud strong { font-size: 1rem; letter-spacing: -0.01em; color: var(--ld-ink); }
.landing-topo-sub { font-size: 0.6875rem; font-family: var(--mono); color: var(--ld-ink-4); line-height: 1.35; }
.landing-topo-node ul {
  margin: 0.7rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.35rem;
  font-size: 0.8125rem; color: var(--ld-ink-3);
}
.landing-topo-node li { display: flex; gap: 0.45rem; line-height: 1.35; }
.landing-topo-node li::before { content: "\2022"; flex: none; }
.landing-topo-glyph {
  width: 2rem; height: 2rem; border-radius: 0.5rem; margin-bottom: 0.35rem;
  display: grid; place-items: center;
}
/* A laptop, drawn rather than fetched: a lid and a base. */
.landing-topo-glyph::before {
  content: ""; width: 1.05rem; height: 0.7rem;
  border: 1.5px solid currentColor; border-radius: 0.15rem; border-bottom-width: 3px;
}
.landing-topo-node.is-expert {
  border-color: color-mix(in srgb, #a78bfa 34%, var(--ld-line));
  background: color-mix(in srgb, #a78bfa 10%, var(--ld-surface));
}
.landing-topo-node.is-expert .landing-topo-glyph { background: rgb(167 139 250 / 16%); color: #a78bfa; }
.landing-topo-node.is-expert li::before { color: #a78bfa; }
.landing-topo-node.is-user {
  border-color: color-mix(in srgb, var(--ok, #34d399) 34%, var(--ld-line));
  background: color-mix(in srgb, var(--ok, #34d399) 10%, var(--ld-surface));
}
.landing-topo-node.is-user .landing-topo-glyph { background: rgb(52 211 153 / 16%); color: var(--ok, #34d399); }
.landing-topo-node.is-user li::before { color: var(--ok, #34d399); }

.landing-topo-cloud {
  align-content: center; justify-items: center; text-align: center;
  border-color: var(--ig-primary); border-radius: 2.5rem;
  background:
    radial-gradient(12rem 8rem at 50% 0%, color-mix(in srgb, var(--ig-primary) 22%, transparent), transparent 70%),
    color-mix(in srgb, var(--ig-primary) 12%, var(--ld-surface));
}
.landing-topo-cloud { align-self: center; padding: 1.4rem 1.1rem; }
.landing-topo-cloud strong { color: var(--ld-ink); }
.landing-topo-cloud .landing-topo-sub { color: color-mix(in srgb, var(--ig-primary) 62%, var(--ld-ink-3)); }

/* The connectors. Two-way to Inetgarden, one-way into the organisation. */
.landing-topo-arrow {
  display: grid; align-content: center; justify-items: center; gap: 0.3rem; min-width: 0;
}
.landing-topo-arrow::before {
  content: "\2194"; font-size: 1.125rem; line-height: 1; color: var(--ig-primary);
}
.landing-topo-arrow.is-one-way::before { content: "\2192"; color: var(--ok, #34d399); }
.landing-topo-arrow span {
  font-size: 0.625rem; font-family: var(--mono); color: var(--ld-ink-4); text-align: center; line-height: 1.25;
}

/* The boundary the expert never crosses, dashed the way the drawing has it. */
.landing-topo-org {
  border: 1px dashed color-mix(in srgb, #f59e0b 55%, var(--ld-line));
  background: color-mix(in srgb, #f59e0b 8%, var(--ld-surface));
}
.landing-topo-orgname { margin: 0 !important; font-size: 1rem; font-weight: 700; color: color-mix(in srgb, #f59e0b 72%, var(--ld-ink)); }
.landing-topo-org > .landing-topo-sub { color: color-mix(in srgb, #f59e0b 55%, var(--ld-ink-4)); }
.landing-topo-orgbody {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0.6rem;
  margin-top: 0.8rem;
}
.landing-topo-bastion {
  display: grid; justify-items: center; text-align: center; gap: 0.1rem;
  padding: 0.7rem 0.6rem; border-radius: 0.625rem;
  border: 1px solid color-mix(in srgb, #a78bfa 40%, var(--ld-line));
  background: color-mix(in srgb, #a78bfa 13%, var(--ld-surface)); color: #7c3aed;
}
.landing-topo-bastion strong { font-size: 0.8125rem; color: color-mix(in srgb, #a78bfa 60%, var(--ld-ink)); }
.landing-topo-bastion span { font-size: 0.625rem; font-family: var(--mono); color: color-mix(in srgb, #a78bfa 45%, var(--ld-ink-4)); }
.landing-topo-resources {
  margin: 0; padding: 0 0 0 0.9rem; list-style: none; display: grid; gap: 0.35rem; min-width: 0;
  position: relative;
}
.landing-topo-resources::before {
  content: ""; position: absolute; left: 0; top: 1.1rem; bottom: 1.1rem; border-left: 1px solid #4c1d95;
}
.landing-topo-resources li::before {
  content: ""; position: absolute; left: -0.9rem; top: 50%; width: 0.9rem; border-top: 1px solid #4c1d95;
}
.landing-topo-resources li {
  position: relative; display: grid; gap: 0.05rem; padding: 0.4rem 0.6rem; border-radius: 0.5rem;
  border: 1px solid var(--border); background: var(--ld-surface-2); border-left-width: 3px;
}
.landing-topo-resources strong { font-size: 0.8125rem; color: var(--ld-ink-2); }
.landing-topo-resources span { font-size: 0.625rem; font-family: var(--mono); color: var(--ld-ink-4); }
.landing-topo-resources span:empty { display: none; }
.landing-topo-resources li.is-app { border-left-color: #f59e0b; }
.landing-topo-resources li.is-data { border-left-color: #3b82f6; }
.landing-topo-resources li.is-svc { border-left-color: var(--ok, #10b981); }

p.landing-topo-deny {
  max-width: none; margin: 0.9rem 0 0 !important; padding: 0.7rem 1rem;
  border-radius: 0.625rem; font-size: 0.875rem; text-align: center;
  border: 1px solid color-mix(in srgb, var(--ok, #34d399) 34%, var(--ld-line));
  background: color-mix(in srgb, var(--ok, #34d399) 11%, var(--ld-surface)); color: var(--ig-status);
}

@media (max-width: 64rem) {
  .landing-topo { grid-template-columns: minmax(0, 1fr); }
  /* Stacked, the arrow and its label sit together rather than at opposite edges. */
  .landing-topo-arrow { min-height: 2.75rem; grid-auto-flow: column; justify-content: center; gap: 0.5rem; }
  .landing-topo-arrow::before { content: "\2195"; }
  .landing-topo-arrow.is-one-way::before { content: "\2193"; }
  .landing-topo-cloud { border-radius: 0.875rem; }
}
@media (max-width: 30rem) {
  .landing-topo-orgbody { grid-template-columns: minmax(0, 1fr); }
}

/* The invite field waits until it is asked for.
   Creating a room is what the person who needs help does, so that is the one filled button. The
   person joining already has a link, so their path is a quiet second button that reveals the field
   rather than a text input sitting open beside the first. `:not(:target)` rather than a `display`
   on the shown state, so the form keeps whatever display its own rule gives it. Only visitors:
   signed in, this same form is the join panel and stays open. */
/* The lead sits inside a .hero-slot now, so it is no longer the form's sibling and `~` no longer
   reaches it. The slot is what the sibling combinator can see, and :has() asks it about its own
   child. Without this the invite field stopped being hidden for visitors at all. */
.app-shell[data-visitor="true"] .hero-slot:has(> .landing-join-lead:not(:target)) > .landing-join-lead,
.app-shell[data-visitor="true"] .hero-slot:has(> .landing-join-lead:not(:target)) ~ .connection-form { display: none; }
.landing-join-action::after { content: " \2192"; }

/* The theme control sits in the visitor bar as well as the account menu, so a visitor with no
   account can still choose an appearance. It is quieter here than in the menu. */
.visitor-bar .theme-control { margin: 0; }
.visitor-bar .theme-control select {
  min-height: 40px; font-size: 0.875rem; font-weight: 600;
  border-radius: 999px; border: 1px solid var(--border); background: var(--card); color: var(--fg);
}

/* ---------------------------------------------------------------------------------------------
   Moved here from collaborate.css on 2026-09-28. Nothing links or imports that file: app.html
   loads workspace.css only, and a check in the browser confirmed neither its rules nor mine were
   in any loaded stylesheet. Rules added there are dead, which is how the participant rows shipped
   restyled in markup and unstyled on screen.
   --------------------------------------------------------------------------------------------- */

/* Identity, room role, capabilities and who holds the keyboard are four facts, so the row gives
   each one its own place instead of a single pill that answered none of them. */
.room-member-who { flex: 1 1 16rem; min-width: 0; display: grid; gap: 0.15rem; }
.room-member-who .room-member-email { flex: none; font-weight: 600; }
.room-member-standing { font-size: 0.8125rem; font-weight: 600; color: var(--fg); }
.room-member-caps { font-size: 0.8125rem; color: var(--muted); }
/* Control moves during a session while the role does not, so it reads as a live state. */
.room-member-control {
  flex: none; align-self: center; padding: 0.2rem 0.6rem; border-radius: 999px;
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  border: 1px solid color-mix(in srgb, var(--ok) 40%, transparent);
  background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok);
}

/* ---- Shared collection workbench -------------------------------------------------------------
   Rooms, computers, team members and groups use one geometry and one scrolling contract. Product
   classes still own their columns and actions; these classes own the predictable table shell. */
.collection-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; min-width: 0; }
.collection-surface { display: grid; width: 100%; min-width: 0; }
.collection-workbench {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(17rem, 22rem);
  gap: 0.8rem; align-items: start; min-width: 0;
}
.collection-list-pane { min-width: 0; }
.collection-scroll {
  height: clamp(16rem, 48dvh, 34rem); min-height: 12rem; max-height: 70dvh;
  overflow-y: scroll; resize: vertical; scrollbar-gutter: stable;
  scrollbar-color: var(--muted, var(--w-ink-3)) transparent; scrollbar-width: thin;
  overscroll-behavior: contain; border: 1px solid var(--border, var(--w-line)); border-radius: 8px;
}
.collection-scroll::-webkit-scrollbar { width: 11px; }
.collection-scroll::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--muted, var(--w-ink-3)) 65%, transparent);
  border: 3px solid transparent; border-radius: 999px; background-clip: padding-box;
}
.collection-table-heading { position: sticky; z-index: 2; top: 0; }
.collection-inspector {
  position: sticky; top: 0.75rem; display: grid; min-width: 0;
  border: 1px solid var(--border, var(--w-line)); border-radius: 10px;
  background: var(--card, var(--w-card));
}
.collection-pages { display: flex; align-items: center; justify-content: flex-end; gap: 0.45rem; }
@media (max-width: 56rem) {
  .collection-workbench { grid-template-columns: minmax(0, 1fr); }
  .collection-inspector { position: static; }
  .collection-toolbar { align-items: stretch; }
}

/* ---- The rooms board ------------------------------------------------------------------------
   A warm paper palette, kept in its own token set so it can be judged on one surface before it is
   taken anywhere else. Terracotta is the action colour, ink is near-black on cream, and the state
   colours are the only other hues: green for a room someone is working in, amber for one that is
   waiting, slate for setup, grey for ended. */
.rooms-board {
  container-type: inline-size;
  container-name: rooms-board;
  --rb-paper: var(--w-paper);
  --rb-card: var(--w-card);
  --rb-line: var(--w-line);
  --rb-line-soft: var(--w-line-soft);
  --rb-ink: var(--w-ink);
  --rb-ink-2: var(--w-ink-2);
  --rb-ink-3: var(--w-ink-3);
  --rb-accent: var(--w-accent);
  --rb-accent-ink: var(--w-accent-fg);
  --rb-accent-soft: var(--w-accent-soft);
  --rb-deep: var(--w-deep);
  --rb-live: var(--w-live);
  --rb-live-soft: var(--w-live-soft);
  --rb-wait: var(--w-wait);
  --rb-wait-soft: var(--w-wait-soft);
  --rb-mono: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  display: grid; gap: 0.65rem;
  padding: 0.75rem 1rem 0.65rem; border-radius: 0 0 0.75rem 0.75rem;
  background: var(--rb-card); color: var(--rb-ink);
  border: 1px solid var(--rb-line);
}
.rooms-board-live[data-live="no"] { background: var(--rb-line-soft); color: var(--rb-ink-3); border-color: var(--rb-line); }

.rooms-board-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.85rem; }
.rooms-board-stat {
  display: grid; gap: 0.15rem; padding: 0.9rem 1rem; border-radius: 0.75rem;
  background: var(--rb-card); border: 1px solid var(--rb-line);
}
.rooms-board-statlabel { font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--rb-ink-3); }
.rooms-board-statvalue { font-size: 1.75rem; font-weight: 800; line-height: 1.1; color: var(--rb-ink); }
.rooms-board-stat[data-stat="active"] .rooms-board-statvalue { color: var(--rb-live); }
.rooms-board-stat[data-stat="waiting"] .rooms-board-statvalue { color: var(--rb-wait); }
.rooms-board-statnote { font-size: 0.75rem; color: var(--rb-ink-3); line-height: 1.35; }

.rooms-board-bar { display: grid; gap: 0.45rem; padding: 0; background: transparent; border: 0; }
.rooms-board-queryrow {
  display: flex; align-items: stretch; gap: 0; min-width: 0; overflow-x: auto;
  border: 1px solid var(--rb-line); border-radius: 0.625rem; background: var(--rb-card);
  scrollbar-width: thin;
}
.rooms-board-queryrow:focus-within { border-color: var(--rb-accent); box-shadow: 0 0 0 1px var(--rb-accent); }
.rooms-board-search {
  flex: 1 1 18rem; min-width: 12rem; min-height: 42px; padding: 0.5rem 0.8rem;
  border: 0; border-radius: 0; outline: 0;
  background: transparent; color: var(--rb-ink); font: inherit; font-family: var(--rb-mono); font-size: 0.875rem;
}
.rooms-board-presets { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.rooms-board-presetlabel { font-size: 0.75rem; font-weight: 700; color: var(--rb-ink-3); letter-spacing: 0.04em; text-transform: uppercase; }
.rooms-board-preset {
  min-height: 36px; padding: 0.35rem 0.75rem; border-radius: 0.5rem; cursor: pointer;
  border: 1px solid var(--rb-line); background: var(--rb-paper); color: var(--rb-ink-2);
  font-size: 0.8125rem; font-weight: 600;
}
.rooms-board-preset:hover { color: var(--rb-ink); border-color: var(--rb-ink-3); }
.rooms-board-preset[data-current="yes"] { background: var(--rb-accent); border-color: var(--rb-accent); color: var(--rb-accent-ink); }

.rooms-board-tokens { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.rooms-board-tokenlabel { font-size: 0.75rem; font-weight: 700; color: var(--rb-ink-3); }
.rooms-board-token {
  min-height: 32px; padding: 0.25rem 0.6rem; border-radius: 0.5rem; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--rb-accent) 32%, transparent);
  background: var(--rb-accent-soft); color: var(--rb-accent);
  font-family: var(--rb-mono); font-size: 0.75rem; font-weight: 600;
}
.rooms-board-token::after { content: " \00d7"; }
.rooms-board-clear { border: 0; background: none; color: var(--rb-accent); font-size: 0.75rem; font-weight: 700; cursor: pointer; padding: 0.25rem 0.4rem; }

.rooms-board-controls { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; justify-content: space-between; }
.rooms-board-builder-toggle {
  min-height: 40px; padding: 0.35rem 0.65rem; border-radius: 0.5rem; cursor: pointer;
  border: 1px solid var(--rb-line); background: var(--rb-paper); color: var(--rb-ink-2); font-size: 0.8125rem; font-weight: 600;
}
.rooms-board-builder-toggle[data-open="yes"] { background: var(--rb-deep); border-color: var(--rb-deep); color: var(--rb-paper); }
.rooms-board-tabs { display: flex; flex-wrap: wrap; gap: 0.2rem; padding: 0.2rem; border-radius: 0.625rem; background: var(--rb-paper); border: 1px solid var(--rb-line); }
.rooms-board-tab {
  min-height: 34px; padding: 0.3rem 0.75rem; border-radius: 0.45rem; cursor: pointer;
  border: 0; background: none; color: var(--rb-ink-2); font-size: 0.8125rem; font-weight: 600;
}
.rooms-board-tab[data-current="yes"] { background: var(--rb-card); color: var(--rb-ink); box-shadow: 0 1px 2px rgb(0 0 0 / 8%); }
.rooms-board-layout { display: flex; gap: 0.2rem; padding: 0.2rem; border-radius: 0.625rem; background: var(--rb-paper); border: 1px solid var(--rb-line); }
.rooms-board-layoutbtn { min-height: 34px; min-width: 38px; display: grid; place-items: center; border: 0; border-radius: 0.45rem; background: none; color: var(--rb-ink-3); cursor: pointer; }
.rooms-board-layoutbtn[data-current="yes"] { background: var(--rb-card); color: var(--rb-ink); box-shadow: 0 1px 2px rgb(0 0 0 / 8%); }
.rooms-board-export, .rooms-board-bulk button {
  min-height: 40px; padding: 0.35rem 0.7rem; border-radius: 0.5rem;
  border: 1px solid var(--rb-line); background: var(--rb-card); color: var(--rb-ink-2);
  font: inherit; font-size: 0.8125rem; font-weight: 600; cursor: pointer;
}
.rooms-board-export { display: inline-grid; place-items: center; width: 2.65rem; padding: 0; }
.rooms-board-bulk {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem;
  padding-top: 0.65rem; border-top: 1px solid var(--rb-line-soft);
}
.rooms-board-bulk button:disabled { opacity: 0.45; cursor: default; }
.rooms-bulk-count { margin-right: auto; color: var(--rb-ink-3); font-size: 0.8125rem; font-weight: 600; }
.rooms-board-bulk .rooms-bulk-clear { border-color: transparent; background: transparent; }

.rooms-board-builder { padding: 0.9rem; border-radius: 0.625rem; background: var(--rb-paper); border: 1px dashed var(--rb-line); }
.rooms-board-builderrow { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.rooms-board-where, .rooms-board-is { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--rb-ink-3); }
.rooms-board-select {
  min-height: 40px; padding: 0.4rem 2rem 0.4rem 0.6rem; border-radius: 0.5rem;
  border: 1px solid var(--rb-line); background: var(--rb-card); color: var(--rb-ink); font: inherit; font-size: 0.875rem;
}
.rooms-board-apply { margin: 0; min-height: 40px; background: var(--rb-deep); border-color: var(--rb-deep); color: var(--rb-paper); }

/* One AWS/ServiceNow-style command bar: search, filter and export are the only global operations.
   Sorting belongs to the column being sorted, instead of consuming another toolbar widget. */
.rooms-board-queryrow > :is(.rooms-board-builder-toggle, .rooms-board-create, .rooms-board-export) {
  flex: 0 0 auto; min-height: 42px; margin: 0; border: 0; border-left: 1px solid var(--rb-line);
  border-radius: 0; background-color: transparent;
}
.rooms-board-queryrow > :is(.rooms-board-builder-toggle, .rooms-board-create, .rooms-board-export):hover { background: var(--rb-line-soft); color: var(--rb-ink); }
.rooms-board-queryrow > .rooms-board-builder-toggle[data-open="yes"] { background: var(--rb-deep); color: var(--rb-paper); }
.rooms-board-queryrow > .rooms-board-create { padding: 0.35rem 0.7rem; color: var(--rb-accent); font: inherit; font-size: 0.8125rem; font-weight: 700; cursor: pointer; }
.rooms-board-queryrow > .rooms-board-export { width: 2.65rem; }

/* The directory follows the same workbench contract as Teams: a bounded, scrollable collection
   owns the left pane and the one current item's facts stay visible in the right inspector. */
.rooms-board-body[data-inspector="no"] { grid-template-columns: minmax(0, 1fr); }
.rooms-board-results { display: grid; gap: 0; align-content: start; }
.rooms-board-count { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--rb-ink-3); }
.rooms-board-columns {
  display: grid; align-items: center; gap: 0.75rem; min-height: 2.35rem; padding: 0.35rem 0.8rem;
  border: 1px solid var(--rb-line); border-bottom: 0; border-radius: 0.65rem 0.65rem 0 0;
  background: color-mix(in srgb, var(--rb-accent-soft) 28%, transparent); color: var(--rb-ink-3); font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.03em; text-transform: uppercase;
}
.rooms-board[data-listing="room"] {
  --rooms-directory-columns: minmax(8rem, 2fr) 5.25rem 3.75rem 5.5rem minmax(7rem, 1.5fr) 3.5rem;
}
.rooms-board[data-listing="room"] .rooms-board-columns {
  grid-template-columns: var(--rooms-directory-columns);
}
.rooms-board[data-listing="computer"] .rooms-board-columns {
  grid-template-columns: minmax(0, 2fr) auto minmax(0, 0.7fr) auto;
}
.rooms-board-column-sort {
  display: inline-flex; align-items: center; justify-content: flex-start; gap: 0.3rem; min-width: 0;
  padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer;
  font: inherit; font-weight: inherit; letter-spacing: inherit; text-transform: inherit;
}
.rooms-board-column-sort:hover { color: var(--rb-ink); }
.rooms-board-column-sort::after { content: "↕"; color: var(--rb-ink-3); font-size: 0.75rem; }
.rooms-board-column-sort[data-direction="asc"]::after { content: "↑"; color: var(--rb-accent); }
.rooms-board-column-sort[data-direction="desc"]::after { content: "↓"; color: var(--rb-accent); }
.rooms-board-list { display: grid; gap: 0; border-color: var(--rb-line); border-radius: 0 0 0.65rem 0.65rem; }
.rooms-board-list::-webkit-scrollbar-track { background: var(--rb-line-soft); }
.rooms-board-list .rooms-row { border-width: 0 0 1px; border-radius: 0; }
.rooms-board-list .rooms-row:last-child { border-bottom: 0; }
.rooms-board-pages { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; min-height: 2.5rem; padding-top: 0.4rem; }
.rooms-board-page {
  display: grid; place-items: center; min-width: 2.25rem; min-height: 2.25rem; padding: 0.2rem;
  border: 1px solid var(--rb-line); border-radius: 0.5rem; background: var(--rb-card); color: var(--rb-ink);
  font: inherit; font-size: 1.15rem; line-height: 1; cursor: pointer;
}
.rooms-board-page:disabled { opacity: 0.42; cursor: default; }
.rooms-board-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.75rem; }

.rooms-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.65rem; align-items: center; text-align: left;
  min-height: 3rem; padding: 0.2rem 0.35rem; border-radius: 0.75rem;
  background: var(--rb-card); border: 1px solid var(--rb-line); color: var(--rb-ink); font: inherit;
}
.rooms-board[data-listing="room"][data-selection-mode="single"] .rooms-row {
  grid-template-columns: var(--rooms-directory-columns); cursor: pointer;
}
.rooms-row:hover { border-color: var(--rb-ink-3); }
.rooms-row[data-selected="yes"] { border-color: var(--rb-line); background: var(--rb-accent-soft); box-shadow: inset 3px 0 var(--rb-accent); }
button.rooms-row {
  grid-template-columns: minmax(0, 2fr) auto minmax(0, 0.7fr) auto;
  gap: 0.65rem; padding: 0.45rem 0.65rem; cursor: pointer;
}
.rooms-row-select {
  display: grid; grid-template-columns: subgrid; grid-column: 1 / 6;
  gap: 0.65rem; align-items: center; min-width: 0; padding: 0.35rem 0.25rem;
  color: inherit; text-decoration: none; border-radius: 0.5rem;
}
.rooms-row > .rooms-item-open { grid-column: 6; }
.directory-item:focus-visible { position: relative; z-index: 1; outline: 2px solid var(--rb-accent); outline-offset: -2px; }
.directory-item-check { width: 1rem; height: 1rem; margin: 0.45rem; accent-color: var(--rb-accent); }
.rooms-item-open {
  display: inline-flex; align-items: center; justify-content: center; min-height: 32px;
  padding: 0.25rem 0.6rem; border-radius: 0.45rem; border: 1px solid var(--rb-line);
  background: var(--rb-accent); border-color: var(--rb-accent); color: var(--rb-accent-ink); font-size: 0.8125rem; font-weight: 700;
  text-decoration: none;
}
.rooms-item-open:hover { background: color-mix(in srgb, var(--rb-accent) 84%, #000); color: var(--rb-accent-ink); }
.rooms-row-name { display: grid; gap: 0.15rem; min-width: 0; }
.rooms-row-name strong { font-size: 0.82rem; overflow-wrap: anywhere; }
.rooms-row-target, .rooms-tile-target { font-family: var(--rb-mono); font-size: 0.75rem; color: var(--rb-ink-3); overflow-wrap: anywhere; }
.rooms-row-people, .rooms-tile-people, .rooms-row-expiry { font-size: 0.8125rem; color: var(--rb-ink-2); }
.rooms-row-expiry { font-family: var(--rb-mono); font-size: 0.75rem; color: var(--rb-ink-3); }

/* State is the only place the board uses colour to mean something. */
.rooms-row-state {
  flex: none; padding: 0.2rem 0.6rem; border-radius: 999px; white-space: nowrap;
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.03em;
  background: var(--rb-line-soft); color: var(--rb-ink-2); border: 1px solid var(--rb-line);
}
.rooms-row-state.is-active { background: var(--rb-live-soft); color: var(--rb-live); border-color: color-mix(in srgb, var(--rb-live) 28%, transparent); }
.rooms-row-state.is-waiting { background: var(--rb-wait-soft); color: var(--rb-wait); border-color: color-mix(in srgb, var(--rb-wait) 28%, transparent); }
/* The computers list reuses the same chip. A running computer is the live colour for the same
   reason an occupied room is; the other three states are the plain chip, because none of them is
   a fault worth colouring. */
.rooms-row-state.is-ready { background: var(--rb-live-soft); color: var(--rb-live); border-color: color-mix(in srgb, var(--rb-live) 28%, transparent); }
.rooms-row-computer { font-size: 0.75rem; font-weight: 600; color: var(--rb-ink-3); white-space: nowrap; }
.rooms-row-computer.is-linked { color: var(--rb-live); }

/* Rooms or computers: one control, and this says which. It sits above the board, so it is the
   first thing read on the screen the board is on. */
.board-listing-switch {
  display: flex; gap: 0.15rem; width: 100%; max-width: 100%; box-sizing: border-box;
  margin: 0; padding: 0.3rem 0.65rem; overflow-x: auto;
  background: color-mix(in srgb, var(--rb-accent-soft) 24%, transparent);
  border: 1px solid var(--rb-line); border-bottom: 0; border-radius: 0.75rem 0.75rem 0 0;
}
.board-listing-btn {
  display: inline-flex; align-items: center; gap: 0.4rem; min-height: 2rem;
  padding: 0.3rem 0.6rem; border: 0; border-radius: 7px; cursor: pointer;
  background: transparent; color: var(--rb-ink-2); font: inherit; font-size: 0.76rem; font-weight: 700;
}
.board-listing-btn .portal-icon { width: 1rem; height: 1rem; }
.board-listing-btn[data-listing="rooms"] .portal-icon { color: var(--rb-accent); }
.board-listing-btn[data-listing="computers"] .portal-icon { color: var(--rb-live); }
.board-listing-btn[data-current="yes"] {
  background: var(--rb-card); color: var(--rb-ink); box-shadow: 0 1px 2px rgb(0 0 0 / 8%);
}
.computers-detail-actions { display: flex; flex-direction: column; gap: 0.4rem; }
.computers-detail-attach { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin-top: 0.5rem; }
.computers-detail-attach select { flex: 1 1 10rem; min-width: 0; }
.computers-detail-revoke { margin-top: 0.5rem; }

.rooms-tile {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 0.35rem; align-items: start;
  text-align: left; padding: 0.55rem; border-radius: 0.875rem; min-height: 9rem;
  background: var(--rb-card); border: 1px solid var(--rb-line); color: var(--rb-ink); font: inherit;
}
.rooms-board[data-selection-mode="single"] .rooms-tile { grid-template-columns: minmax(0, 1fr) auto; cursor: pointer; }
.rooms-tile:hover { border-color: var(--rb-ink-3); }
.rooms-tile[data-selected="yes"] { border-color: var(--rb-accent); background: var(--rb-accent-soft); }
button.rooms-tile { display: grid; grid-template-columns: 1fr; gap: 0.4rem; padding: 1rem; cursor: pointer; }
.rooms-tile-select {
  display: grid; gap: 0.4rem; align-content: start; min-width: 0; min-height: 100%;
  padding: 0.45rem; color: inherit; text-decoration: none; border-radius: 0.5rem;
}
.rooms-tile > .rooms-item-open { align-self: start; }
.rooms-tile-top { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.rooms-tile-name { font-size: 0.9375rem; overflow-wrap: anywhere; }
.rooms-tile-foot { margin-top: auto; padding-top: 0.5rem; border-top: 1px solid var(--rb-line-soft); }

.rooms-board-empty {
  display: grid; gap: 0.4rem; justify-items: center; text-align: center;
  padding: 3rem 1.5rem; border-radius: 0.875rem;
  background: var(--rb-card); border: 1px dashed var(--rb-line);
}
.rooms-board-empty strong { font-size: 1rem; }
.rooms-board-empty p { margin: 0; font-size: 0.875rem; color: var(--rb-ink-2); max-width: 26rem; }
.rooms-board-reset { margin-top: 0.5rem; }

.rooms-board-detail { gap: 0.7rem; align-content: start; margin: 0; padding: 0.8rem; }
.rooms-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.6rem; }
.rooms-detail-titles { display: grid; gap: 0.35rem; min-width: 0; justify-items: start; }
.rooms-detail-name { font-size: 1.0625rem; overflow-wrap: anywhere; }
.rooms-detail-close { border: 0; background: none; color: var(--rb-ink-3); cursor: pointer; min-height: 32px; min-width: 32px; display: grid; place-items: center; border-radius: 0.4rem; }
.rooms-detail-close:hover { background: var(--rb-line-soft); color: var(--rb-ink); }
.rooms-detail-facts { margin: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.4rem 0.9rem; font-size: 0.8125rem; }
.rooms-detail-facts dt { color: var(--rb-ink-3); font-weight: 600; }
.rooms-detail-facts dd { margin: 0; color: var(--rb-ink); overflow-wrap: anywhere; }
.rooms-detail-shared { display: grid; gap: 0.35rem; padding-top: 0.75rem; border-top: 1px solid var(--rb-line-soft); }
.rooms-detail-sharedlabel { font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--rb-ink-3); }
.rooms-detail-sharedlist { margin: 0; padding-left: 1.1rem; display: grid; gap: 0.2rem; font-size: 0.8125rem; color: var(--rb-ink-2); }

/* Everything below asks the board how wide IT is, not the window. */
/* The directory needs enough room for its six compact columns plus the 17rem inspector.
   Collapse before the row can overflow underneath the inspector and steal pointer events. */
@container rooms-board (max-width: 56rem) {
  .rooms-board-body { grid-template-columns: minmax(0, 1fr); }
  .rooms-board-detail { margin-top: 0; }
  .rooms-board-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rooms-board-columns { display: none; }
  .rooms-board-list { border-radius: 0.65rem; }
  .rooms-board[data-listing="room"][data-selection-mode="single"] .rooms-row { grid-template-columns: minmax(0, 1fr) auto; }
  .rooms-row-select { grid-column: 1; grid-template-columns: minmax(0, 1fr) auto; row-gap: 0.4rem; }
  .rooms-row > .rooms-item-open { grid-column: 2; }
  .rooms-row-people, .rooms-row-expiry { display: none; }
}
@container rooms-board (max-width: 34rem) {
  .rooms-board-stats { grid-template-columns: minmax(0, 1fr); }
  .rooms-row { grid-template-columns: auto minmax(0, 1fr); }
  .rooms-board[data-selection-mode="single"] .rooms-row { grid-template-columns: minmax(0, 1fr); }
  .rooms-row-select { grid-template-columns: minmax(0, 1fr); }
  .rooms-row > .rooms-item-open { grid-column: 2; justify-self: start; }
  .rooms-board[data-selection-mode="single"] .rooms-row > .rooms-item-open { grid-column: 1; }
  .rooms-row-state { justify-self: start; }
  .rooms-board-grid { grid-template-columns: minmax(0, 1fr); }
  .rooms-board-tabs, .rooms-board-layout { justify-content: center; }
}
@media (max-width: 56rem) { .rooms-board { padding: 1rem; } }

/* ---- Room labels ----------------------------------------------------------------------------
   One badge for every label, whatever produced it. The mockup states the rule and it is the whole
   point: a label the system derived and a label a person typed are drawn identically, so no label
   looks more official than another. Colour comes from the name, never from the kind.

   The palette is Apple's system colours, light and dark pairs, as appleLabelTheme.ts defines them. */
.room-label {
  display: inline-flex; align-items: center; gap: 0.35rem; max-width: 100%;
  padding: 0.1rem 0.45rem; border-radius: 0.375rem;
  font-size: 0.6875rem; font-weight: 500; letter-spacing: -0.01em; line-height: 1.5;
  border: 1px solid transparent; overflow-wrap: anywhere;
  background: color-mix(in srgb, var(--label-dot) 9%, transparent);
  color: var(--label-ink);
  border-color: color-mix(in srgb, var(--label-dot) 26%, transparent);
}
.room-label[data-size="sm"] { font-size: 0.625rem; padding: 0.05rem 0.35rem; gap: 0.3rem; }
.room-label::before {
  content: ""; flex: none; width: 0.375rem; height: 0.375rem; border-radius: 50%;
  background: var(--label-dot);
}
button.room-label { cursor: pointer; }
button.room-label:hover { background: color-mix(in srgb, var(--label-dot) 16%, transparent); }
button.room-label[data-active="yes"] {
  font-weight: 650;
  background: color-mix(in srgb, var(--label-dot) 18%, transparent);
  border-color: var(--label-dot);
  box-shadow: 0 0 0 1px var(--label-dot);
}

.room-label[data-label-colour="blue"] { --label-dot: #007AFF; --label-ink: #0062cc; }
.room-label[data-label-colour="purple"] { --label-dot: #AF52DE; --label-ink: #8929b8; }
.room-label[data-label-colour="indigo"] { --label-dot: #5856D6; --label-ink: #4341b5; }
.room-label[data-label-colour="green"] { --label-dot: #34C759; --label-ink: #207d39; }
.room-label[data-label-colour="orange"] { --label-dot: #FF9500; --label-ink: #b86200; }
.room-label[data-label-colour="red"] { --label-dot: #FF3B30; --label-ink: #c92117; }
.room-label[data-label-colour="teal"] { --label-dot: #5AC8FA; --label-ink: #02779e; }
.room-label[data-label-colour="pink"] { --label-dot: #FF2D55; --label-ink: #c2183b; }
.room-label[data-label-colour="yellow"] { --label-dot: #FFCC00; --label-ink: #946c00; }
.room-label[data-label-colour="gray"] { --label-dot: #8E8E93; --label-ink: #545459; }

:root[data-theme="dark"] .room-label, :root:not([data-theme="light"]) .room-label { --label-ink: var(--label-ink-dark); }
:root[data-theme="dark"] .room-label[data-label-colour="blue"],
:root:not([data-theme="light"]) .room-label[data-label-colour="blue"] { --label-dot: #0A84FF; --label-ink: #6cb4ff; }
:root[data-theme="dark"] .room-label[data-label-colour="purple"],
:root:not([data-theme="light"]) .room-label[data-label-colour="purple"] { --label-dot: #BF5AF2; --label-ink: #d388f7; }
:root[data-theme="dark"] .room-label[data-label-colour="indigo"],
:root:not([data-theme="light"]) .room-label[data-label-colour="indigo"] { --label-dot: #5E5CE6; --label-ink: #8b89f0; }
:root[data-theme="dark"] .room-label[data-label-colour="green"],
:root:not([data-theme="light"]) .room-label[data-label-colour="green"] { --label-dot: #30D158; --label-ink: #55e079; }
:root[data-theme="dark"] .room-label[data-label-colour="orange"],
:root:not([data-theme="light"]) .room-label[data-label-colour="orange"] { --label-dot: #FF9F0A; --label-ink: #ffb74d; }
:root[data-theme="dark"] .room-label[data-label-colour="red"],
:root:not([data-theme="light"]) .room-label[data-label-colour="red"] { --label-dot: #FF453A; --label-ink: #ff7870; }
:root[data-theme="dark"] .room-label[data-label-colour="teal"],
:root:not([data-theme="light"]) .room-label[data-label-colour="teal"] { --label-dot: #64D2FF; --label-ink: #78dcff; }
:root[data-theme="dark"] .room-label[data-label-colour="pink"],
:root:not([data-theme="light"]) .room-label[data-label-colour="pink"] { --label-dot: #FF375F; --label-ink: #ff6e8a; }
:root[data-theme="dark"] .room-label[data-label-colour="yellow"],
:root:not([data-theme="light"]) .room-label[data-label-colour="yellow"] { --label-dot: #FFD60A; --label-ink: #ffe043; }
:root[data-theme="dark"] .room-label[data-label-colour="gray"],
:root:not([data-theme="light"]) .room-label[data-label-colour="gray"] { --label-dot: #8E8E93; --label-ink: #aeafb4; }

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .room-label, :root[data-theme="system"] .room-label { --label-ink: var(--label-ink-light); }
  :root:not([data-theme]) .room-label[data-label-colour="blue"],
  :root[data-theme="system"] .room-label[data-label-colour="blue"] { --label-dot: #007AFF; --label-ink: #0062cc; }
  :root:not([data-theme]) .room-label[data-label-colour="purple"],
  :root[data-theme="system"] .room-label[data-label-colour="purple"] { --label-dot: #AF52DE; --label-ink: #8929b8; }
  :root:not([data-theme]) .room-label[data-label-colour="indigo"],
  :root[data-theme="system"] .room-label[data-label-colour="indigo"] { --label-dot: #5856D6; --label-ink: #4341b5; }
  :root:not([data-theme]) .room-label[data-label-colour="green"],
  :root[data-theme="system"] .room-label[data-label-colour="green"] { --label-dot: #34C759; --label-ink: #207d39; }
  :root:not([data-theme]) .room-label[data-label-colour="orange"],
  :root[data-theme="system"] .room-label[data-label-colour="orange"] { --label-dot: #FF9500; --label-ink: #b86200; }
  :root:not([data-theme]) .room-label[data-label-colour="red"],
  :root[data-theme="system"] .room-label[data-label-colour="red"] { --label-dot: #FF3B30; --label-ink: #c92117; }
  :root:not([data-theme]) .room-label[data-label-colour="teal"],
  :root[data-theme="system"] .room-label[data-label-colour="teal"] { --label-dot: #5AC8FA; --label-ink: #02779e; }
  :root:not([data-theme]) .room-label[data-label-colour="pink"],
  :root[data-theme="system"] .room-label[data-label-colour="pink"] { --label-dot: #FF2D55; --label-ink: #c2183b; }
  :root:not([data-theme]) .room-label[data-label-colour="yellow"],
  :root[data-theme="system"] .room-label[data-label-colour="yellow"] { --label-dot: #FFCC00; --label-ink: #946c00; }
  :root:not([data-theme]) .room-label[data-label-colour="gray"],
  :root[data-theme="system"] .room-label[data-label-colour="gray"] { --label-dot: #8E8E93; --label-ink: #545459; }
}

.rooms-board-labels { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.rooms-board-alllabels {
  min-height: 26px; padding: 0.1rem 0.55rem; border-radius: 0.375rem; cursor: pointer;
  border: 1px solid var(--rb-line); background: var(--rb-paper); color: var(--rb-ink-2);
  font-size: 0.6875rem; font-weight: 600;
}
.rooms-board-alllabels[data-active="yes"] { background: var(--rb-deep); border-color: var(--rb-deep); color: var(--rb-paper); }
.rooms-row-labels { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.3rem; }
.rooms-row-labelmore { font-size: 0.625rem; font-weight: 600; color: var(--rb-ink-3); align-self: center; }
.rooms-board-detail .rooms-row-labels { margin-top: 0; }

/* Holds a child position in the hero column whether or not it has anything in it. A block that
   disappears takes its slot with it, every later sibling shifts up, and the diff replaces nodes it
   would otherwise have patched -- which is how an invite someone was typing lost its focus when
   their account resolved. */
/* display:contents keeps the element in the DOM - which is all the diff needs to hold a child
   position - without giving it a box. The earlier `:empty { display: block }` gave each empty slot
   a box after all, and with it a share of the column's row-gap: two of them left a 70px void under
   the heading on the workspace. */
.hero-slot { display: contents; }

/* ---- The workspace header is an action bar, not a column ---------------------------------------
   Joining is one field and one button. As a tall card it set the height of the header row, and the
   heading beside it sat above 400px of nothing on a 1440px screen. The mockup's header is a title
   with its actions on the right and the work full width beneath, so this is that: the panel keeps
   everything it had, with the parts that are not the action folded away. */
@media (min-width: 70rem) {
  .workspace-signed-in .workspace-join .portal { padding: 0.85rem 1rem; }
  .workspace-signed-in .workspace-join h2 { font-size: 0.95rem; }
  .workspace-signed-in .workspace-join .tagline { display: none; }
  /* Field and button on one line. */
  .workspace-signed-in .workspace-join .connection-primary { display: flex; align-items: flex-end; gap: 0.5rem; }
  .workspace-signed-in .workspace-join .connection-primary .field { flex: 1 1 auto; min-width: 0; }
  .workspace-signed-in .workspace-join .connect { margin: 0; white-space: nowrap; }
  /* Everything that is not the action: still present, not taking the header's height. */
  /* The QR paths, the ambient status line and the four advanced fields are all still one click
     away in Connection options; none of them is the action, and together they were most of the
     panel's height. */
  /* Nothing is hidden here. Two attempts tried that and both were caught: "landing QR controls stay
     direct and compact" wants Scan QR code on screen, and "both first-screen actions are visible
     together" wants the connection status. The panel is made short by laying it out, not by
     removing what it offers. */
  .workspace-signed-in .workspace-join .invite-qr-actions {
    margin-top: 0.5rem; font-size: 0.8125rem;
  }
  .workspace-signed-in .workspace-join .invite-qr-capture-actions { gap: 0.5rem; }
  /* The panel inherits the landing hero's spacing, which is built for a column that fills a
     screen. In a header card it is most of the height. One rhythm, set once, on whatever the
     children happen to be. */
  .workspace-signed-in .workspace-join .hero-left-column > * { margin-block: 0; }
  .workspace-signed-in .workspace-join .hero-left-column > * + * { margin-top: 0.5rem; }
  .workspace-signed-in .workspace-join .portal-head { margin: 0; }
  .workspace-signed-in .workspace-join .portal > * + * { margin-top: 0.5rem; }
  .workspace-signed-in .workspace-join .connection-advanced { margin-top: 0.35rem; }
  /* The connection status stays: "signed in, both first-screen actions are visible together"
     checks for it, and it is the one line in the panel that reports something rather than offering
     something. It reads as one compact line instead of a two-line block. */
  .workspace-signed-in .workspace-join .ambient-connection-status {
    display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap;
    margin: 0.5rem 0 0; font-size: 0.78rem; line-height: 1.35;
  }
  .workspace-signed-in .workspace-join .connection-advanced > summary { font-size: 0.8125rem; padding: 0.35rem 0; }
  .workspace-signed-in .workspace-join .hero-split-layout,
  .workspace-signed-in .workspace-join .hero-left-column { display: block; }
}

/* ---- The wide shape: one action row, the board across the page -------------------------------
   The mockup's screen is a title, a row of actions, then the work using the whole width. Two things
   had to change for that to be possible here.
   The hero and the board sit seven wrappers deep inside the collaborate slot, so the grid could only
   ever place the whole slot as one item, beside the join panel - which is what squeezed the board
   into half the page and left a dead column down the right of it. The wrappers carry no layout of
   their own at this width, so they become display:contents and the hero and the board become grid
   items in their own right: hero beside the panel, board across both columns.
   And the panel, stacked, was 387px tall against a 119px hero, which left the hole under it. It is
   laid out as a row here instead - field, button and the QR controls on one line, the status on the
   next - so the two halves of the action row are the same sort of height. */
@media (min-width: 70rem) {
  .workspace-signed-in .workspace-collaborate-slot,
  .workspace-signed-in .workspace-collaborate-slot > .account-route-host,
  .workspace-signed-in .workspace-collaborate-slot .route-view,
  /* #journey-root carries an id, so a class selector cannot flatten it. */
  .workspace-signed-in .workspace-collaborate-slot #collaborate-workspace,
  .workspace-signed-in .workspace-collaborate-slot #journey-root,
  .workspace-signed-in .workspace-collaborate-slot .placeholder-panel,
  .workspace-signed-in .workspace-collaborate-slot .collaboration-region,
  .workspace-signed-in .workspace-collaborate-slot .room-management { display: contents; }

  .workspace-signed-in { grid-template-areas: "head head" "start join"; align-content: start; }
  /* Both at their natural height. Stretching the hero to the panel made a tall card holding one
     button, which is the opposite of filling a screen: space is filled by content, not by padding. */
  .workspace-signed-in .support-intent-hero { grid-area: start; align-self: start; }
  .workspace-signed-in .workspace-join { align-self: start; }
  /* Everything the slot held after the hero runs the full width, under the action row. */
  /* Not `.workspace-collaborate-slot ~ *`: the join section is a later sibling, so that spanned the
     panel across both columns too. Named, so it only reaches what it means. */
  .workspace-signed-in .rooms-board,
  .workspace-signed-in .existing-room,
  .workspace-signed-in .collaboration-more,
  .workspace-signed-in .meeting-accounts,
  .workspace-signed-in .restore-dismissed-row { grid-column: 1 / -1; }

  /* The join panel as a row. Nothing is hidden: the invite field, Join room, both QR controls, the
     readiness line and Connection options are all still here, on fewer lines. */
  /* The QR controls are two buttons and a hint, about as wide as the field itself, so beside it the
     field collapsed to nothing. They keep their own line; the saving comes from the rows below. */
  .workspace-signed-in .workspace-join .invite-qr-actions { margin: 0.5rem 0 0; }
  /* A quiet check line, the same shape as the promises in the card beside it. As a filled green box
     it was the heaviest thing in an action row whose job is to be read past, and it stood a third
     taller than the line it holds. */
  .workspace-signed-in .workspace-join .ambient-connection-status {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.6rem;
    grid-column: 1; margin: 0; padding: 0;
    background: none; border: 0; font-size: 0.8125rem;
  }
  /* The readiness line and Connection options share a row. Closed, the disclosure is a word; on its
     own line under a two-line notice it was a third of the card's height for that word. */
  .workspace-signed-in .workspace-join .portal {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 0.75rem;
  }
  .workspace-signed-in .workspace-join .hero-split-layout { grid-column: 1 / -1; margin-bottom: 0; }
  .workspace-signed-in .workspace-join .connection-advanced { grid-column: 2; margin: 0; }
  /* Opened it is a form, not a word, so it takes the width back. */
  .workspace-signed-in .workspace-join .connection-advanced[open] { grid-column: 1 / -1; }
}

/* ---- One spacing rhythm, the mockup's ---------------------------------------------------------
   The old layout was a narrow column, so everything in it was padded outward to fill the width and
   the options that did not fit were condensed away. With the full width there is room for the
   content itself, and the spacing can be the mockup's: a consistent step between blocks, cards
   sized by what they hold, and nothing inflated to fill a gap. */
.workspace-signed-in { row-gap: 1.25rem; }
.workspace-signed-in .support-intent-hero {
  padding: 1.25rem; border-radius: 0.875rem;
  background: var(--card); border: 1px solid var(--border);
}
/* The board sets its own rhythm inside; it does not need a second card around it. */
.workspace-signed-in .rooms-board { padding: 1.25rem; }

/* The primary action at the width of its own label. As a bar across the card it read as a banner
   rather than a button, and it was the widest thing on the page for a two-word action. */
/* .journey-create is a full-width grid whose first column is 1fr, which is right for a form with a
   field in it and wrong for a form that is one button: it made a two-word action the widest thing
   on the page. Here the form is a row and the button is its own size. */
.workspace-signed-in .support-intent-hero .support-intent-form {
  display: flex; width: auto; margin-top: 0;
}
.workspace-signed-in .support-intent-hero .support-start-btn { flex: 0 1 auto; width: auto; margin-right: auto; }

/* The two halves of the action row look like a pair: same card, same title size, same inner rhythm. */
.workspace-signed-in .support-intent-title {
  font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 0.75rem;
}
.workspace-signed-in .support-intent-reassurance {
  list-style: none; margin: 0.85rem 0 0; padding: 0;
  display: grid; gap: 0.3rem; font-size: 0.8125rem; color: var(--muted);
}
/* A check, not a bullet: each line is something the product does, not an item in a list. */
.workspace-signed-in .support-intent-reassurance > li { padding-left: 1.1rem; position: relative; }
.workspace-signed-in .support-intent-reassurance > li::before {
  content: "\2713"; position: absolute; left: 0; color: var(--ok); font-weight: 700;
}

/* The check is a glyph and the sentence is a paragraph. Left to wrap as equals the glyph took a
   line of its own above the text it belongs to. */
.workspace-signed-in .workspace-join .ambient-status-check { flex: 0 0 auto; }
.workspace-signed-in .workspace-join .ambient-connection-status > span + span { flex: 1 1 0; min-width: 0; }

/* ---- Under two columns, the order is start, join, rooms --------------------------------------
   Stacked, the panel was last on the page. That was invisible while the rooms were folded away and
   wrong as soon as they were not: on a laptop the invite field ended up two thousand pixels down,
   under the board and every disclosure below it, so someone who came with a link had to scroll past
   the whole product to use it.
   Flattened here as well, the three things a person arrives to do are the first three blocks, in
   the order the strategy puts them: start a session, join one, then the rooms. Focus mode is left
   alone - it renders neither the hero nor the panel, and its surface is the whole screen. */
@media (max-width: 70rem) {
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot > .account-route-host,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot .route-view,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot #collaborate-workspace,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot #journey-root,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot .placeholder-panel,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot .collaboration-region,
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-collaborate-slot .room-management { display: contents; }

  /* Named areas place an item outright, and an explicitly placed item ignores `order`. One column
     and auto placement, so the order below is the one that counts. */
  .workspace-signed-in:not(:has(.in-focus-mode)) {
    grid-template-columns: minmax(0, 1fr); grid-template-areas: none;
  }
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-customer-slot { grid-area: auto; order: 0; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .support-intent-hero { order: 1; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .workspace-join { grid-area: auto; order: 2; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .rooms-board { order: 3; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .existing-room { order: 4; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .collaboration-more { order: 5; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .meeting-accounts { order: 6; }
  .workspace-signed-in:not(:has(.in-focus-mode)) .restore-dismissed-row { order: 7; }
}

/* The board names itself again. It used to sit under a disclosure whose summary counted the rooms,
   which made three headings for one thing; with no disclosure over it, its own title is the only
   one it has. */

/* ---- The action row speaks the board's vocabulary ---------------------------------------------
   The two cards were built before the board and kept the old shapes: 999px pills for the buttons,
   a 9px field, a 0.95rem bold label. The board underneath them uses 0.625rem on anything the size
   of a field, 0.5rem on a chip, 36px for a chip and 44px for a field, and 0.8125rem semibold text.
   Same controls, same measurements, so the screen reads as one design rather than two. */
.workspace-signed-in .support-intent-hero .support-start-btn,
.workspace-signed-in .workspace-join .connect {
  min-height: 44px; padding: 0.55rem 1rem; border-radius: 0.625rem;
  font-size: 0.875rem; font-weight: 600; letter-spacing: 0;
  border: 1px solid transparent; box-shadow: none;
}
/* Terracotta is the action, as it is for the preset the board is currently filtering by. */
.workspace-signed-in .support-intent-hero .support-start-btn {
  background: var(--w-accent); border-color: var(--w-accent); color: var(--w-accent-fg);
}
.workspace-signed-in .support-intent-hero .support-start-btn:hover:not(:disabled) {
  background: var(--w-accent-hover); border-color: var(--w-accent-hover);
}
/* Joining is the other card's action, so it is filled too - in the board's second emphasis, the
   one "Build a condition" wears when it is open. Two terracotta buttons side by side said the two
   were the same thing, and the strategy is that starting is the one being asked for. */
.workspace-signed-in .workspace-join .connect:not(:disabled):not(.disabled) {
  background: var(--w-deep); border-color: var(--w-deep); color: var(--w-deep-fg);
}
.workspace-signed-in .workspace-join .connection-primary input {
  min-height: 44px; padding: 0.55rem 0.8rem; border-radius: 0.625rem;
  border: 1px solid var(--w-line); background: var(--w-paper);
  color: var(--w-ink); font: inherit; font-size: 0.875rem;
}
/* The board names a group of controls in small uppercase - SHOW ME, LABELS, AN EXPERT IS IN - so
   the field above the invite does the same. text-transform is paint only: the accessible name is
   still "Invite link", which is what the checks and a screen reader read. */
.workspace-signed-in .workspace-join .connection-primary .field > span {
  display: block; margin-bottom: 0.35rem;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--w-ink-3);
}
/* The QR controls take the board chip's shape, fill and type, and keep 44px rather than the chip's
   36px: they are the things a person taps on a phone to join, and "landing QR controls stay direct
   and compact" holds them to that height. A filter chip on a wide board is not the same control. */
.workspace-signed-in .invite-qr-actions button,
.workspace-signed-in .invite-qr-actions label.invite-qr-file,
.workspace-signed-in .invite-qr-capture-actions button,
.workspace-signed-in .invite-qr-capture-actions label.invite-qr-file {
  min-height: 44px; padding: 0.5rem 0.85rem; border-radius: 0.5rem;
  border: 1px solid var(--w-line); background: var(--w-paper);
  color: var(--w-ink-2); font-size: 0.8125rem; font-weight: 600;
}
/* The cards match the board's card, not a rounder one of their own. */
.workspace-signed-in .support-intent-hero,
.workspace-signed-in .workspace-join .portal { border-radius: 0.875rem; padding: 1.25rem; }
.workspace-signed-in .workspace-join h2,
.workspace-signed-in .support-intent-title {
  font-size: 1rem; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 0.75rem;
}

/* ---- The two actions are one control bar -----------------------------------------------------
   They were two cards with a gutter between them, which read as two places to look before doing
   anything. They are one bar across the top of the screen now: starting on the left, joining on the
   right, a seam between them rather than a gap. Each half names itself in the board's small
   uppercase, the way SHOW ME and LABELS name a group of controls down there.
   The halves are two elements seven wrappers apart in the DOM, so the bar is made by removing the
   column gap and joining their edges: left radius on one, right radius on the other, no border in
   between. Both stretch, so the seam runs the full height whichever half is taller. */
@media (min-width: 70rem) {
  .workspace-signed-in {
    /* Enough for the button and its three promises on the left; the rest goes to the right, where
       the field, Join room and both QR controls then fit on one line. */
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    column-gap: 0;
  }
  /* The invite row is one row: field, Join room, Scan QR code, Choose QR image. The field keeps a
     floor of 18rem so it cannot be squeezed to nothing by the controls beside it, which is what
     happened the first time this was tried in a 480px panel. */
  .workspace-signed-in .workspace-join .connection-form {
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem;
  }
  .workspace-signed-in .workspace-join .connection-primary { flex: 1 1 26rem; min-width: 0; }
  /* The floor belongs to the field, not to the row around it. With min-width:0 the field could be
     squeezed to nothing while the input inside it kept its width, and an input wider than the box
     holding it runs under the button beside it - the check reads that as Join room starting before
     the field ends, which is exactly what it is. 16rem also keeps the field over the 240px that
     "the join panel keeps its width" requires, and over what a pasted invite needs to be readable. */
  .workspace-signed-in .workspace-join .connection-primary .field { min-width: 16rem; }
  .workspace-signed-in .workspace-join .connection-primary > .connect { flex: 0 0 auto; }
  .workspace-signed-in .workspace-join .invite-qr-actions { margin: 0; flex: 0 1 auto; }
  .workspace-signed-in .workspace-join .connection-status { flex: 1 1 100%; }
  /* min-height, not align-self: stretch. The hero reaches the grid through six ancestors that are
     display:contents, and in that arrangement Chromium leaves the item at its content height and
     the stretch does nothing - which left the shorter half's background stopping twenty pixels
     early and a notch in the seam. A percentage minimum resolves against the grid area and works.
     Whichever half is taller sets the height; the other one meets it. */
  .workspace-signed-in .support-intent-hero,
  .workspace-signed-in .workspace-join,
  .workspace-signed-in .workspace-join .portal { min-height: 100%; }
  .workspace-signed-in .support-intent-hero {
    border-radius: 0.875rem 0 0 0.875rem;
    border-right: 0;
  }
  .workspace-signed-in .workspace-join .portal { border-radius: 0 0.875rem 0.875rem 0; }
  /* Inside the bar the group label is the heading, so the field's own label would be a second
     uppercase line saying the same thing. Hidden to the eye, not to the accessible name: the
     placeholder carries it visually and `getByLabel("Invite link")` still finds the input. */
  .workspace-signed-in .workspace-join .connection-primary .field > span {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
  }
}

/* Each half names itself the way the board names a group of controls. At the size of a heading
   these were two titles competing with the page's own; at the size of a label they are what they
   are, which is the name of the thing under them. */
.workspace-signed-in .support-intent-title,
.workspace-signed-in .workspace-join h2 {
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--w-ink-3); margin: 0 0 0.65rem;
}
/* One line of fine print under the action, not a stacked list: in a bar the promises are a
   reassurance to read past, and three rows of them made the bar as tall as a card again. */
.workspace-signed-in .support-intent-reassurance {
  display: flex; flex-wrap: wrap; gap: 0.15rem 0.85rem; margin-top: 0.75rem;
}

/* ---- The two people in the topology ----------------------------------------------------------
   Drawn figures in the Expert and You cards, where the diagram previously had only a laptop glyph
   and a list. They are decoration: the card already says "Expert" and "You" in text, so the alt is
   empty and a screen reader is not told there is a picture of nothing.
   Absolute, so the list beside them keeps its own line breaks; the text gets a right inset instead
   of wrapping around a floated image, which at these column widths would leave two-word lines. */
.landing-topo-node { position: relative; overflow: hidden; container-type: inline-size; }
.landing-topo-figure {
  display: none;
  position: absolute; right: 0.25rem; bottom: 0.4rem;
  width: auto; height: 68%; max-height: 8.5rem;
  object-fit: contain; object-position: bottom right; pointer-events: none;
}
/* Asked of the card, not of the window. The diagram is seven columns on a wide screen and one
   column below that, so the same viewport width means a 208px card in the first case and an 820px
   card in the second - a media query gets one of the two wrong whichever way it is written. Below
   this the card cannot hold a drawing and a readable list at once, and the list is the part that
   says something.
   12rem is the card's content box, which is what a container query measures: the 238px card at
   1440px leaves 200px inside its padding, and the 208px one at 1100px leaves 171px. */
@container (min-width: 12rem) {
  .landing-topo-figure { display: block; }
  .landing-topo-node strong,
  .landing-topo-node .landing-topo-sub,
  .landing-topo-node ul { padding-right: 3.1rem; }
}

/* ---- Starting a session is the first thing in the panel ---------------------------------------
   The product's one action, at the top of the sidebar with the same plus it wears on Home, in the
   accent that means "action" everywhere else. It is a button and not a nav item because it reads as
   the thing to do, not as one destination among five - but it does lead to a screen, so it takes
   the same measurements as the controls it sits above. */
.sidebar-start {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  margin: 0 0.75rem 0.75rem; min-height: 40px; padding: 0.5rem 0.9rem;
  border: 1px solid var(--w-accent); border-radius: 0.625rem;
  background: var(--w-accent); color: var(--w-accent-fg);
  font: inherit; font-size: 0.875rem; font-weight: 600; cursor: pointer;
}
.sidebar-start:hover { background: var(--w-accent-hover); border-color: var(--w-accent-hover); }
.sidebar-start .portal-icon { width: 1rem; height: 1rem; }

/* Profile and Plans and billing are a group of their own, below the control plane and above the
   appearance row, so the panel reads account-ward as it goes down. */
.shell-nav-account { margin-top: auto; }

/* ---- The Start screen ------------------------------------------------------------------------
   One column, because there is one thing on it. Once a room is focused the session surface renders
   in the same place, which is what makes this a screen rather than a button with a redirect. */
.start-surface { display: grid; gap: 1.25rem; max-width: none; }
.start-surface .support-intent-hero {
  padding: 1.25rem; border-radius: 0.875rem;
  background: var(--card); border: 1px solid var(--border);
  max-width: 34rem;
}
/* The sentence describes what to do, so it goes once it has been done. The heading stays: a screen
   with no h1 is a screen a reader cannot place, and "Support session" is true before and after.
   Nothing interactive is hidden here - it is one line of description. */
.start-surface:has(.in-focus-mode) > .customer-head { margin-bottom: 0; padding-bottom: 0; }
.start-surface:has(.in-focus-mode) > .customer-head .tagline { display: none; }
.collaboration-region:has(.in-focus-mode) > .collaboration-region-title { display: none; }

/* ---- The mockup's vertical rhythm -------------------------------------------------------------
   mockmock-v1.5.0 sets its page header at pt-5 pb-3, the title and its actions on one row, and a
   12px subtitle 4px under the title. Everything is py-2 and gap-3. What we had instead was a band
   of empty page between each block, which is the space that later forces options to be crammed
   together: the room is spent on nothing before the content needs it. */
.workspace-signed-in { row-gap: 0.9rem; }
.workspace-signed-in .support-intent-hero,
.workspace-signed-in .workspace-join .portal { padding: 1rem 1.1rem; }
.workspace-signed-in .support-intent-title,
.workspace-signed-in .workspace-join h2 { margin-bottom: 0.5rem; }
.workspace-signed-in .support-intent-reassurance { margin-top: 0.6rem; }

/* The board starts with its command bar; the selected tab already names the directory. Keep the
   same compact inset as the Teams surfaces so switching sections does not change density. */
.workspace-signed-in .rooms-board { padding: 0.75rem 1rem 0.65rem; gap: 0.65rem; }

/* A number and what it counts. Two lines, so the four of them stop being the tallest thing on the
   screen; the value leads because the value is what is being read. */
.rooms-board-stat { gap: 0.1rem; padding: 0.65rem 0.8rem; }
.rooms-board-statvalue { font-size: 1.5rem; }
.rooms-board-stats { gap: 0.6rem; }

/* The panel's own dead space: the account group was pushed to the bottom by margin-top:auto, which
   made a void as tall as the window had room for. It sits under the control plane with a gap that
   separates it, and no more. */
.shell-nav-account { margin-top: 1.25rem; }

/* Appearance is two icons now, not a menu, so it takes a row and not a form control's height. */
.theme-control {
  display: inline-flex; gap: 0.15rem; padding: 0.15rem;
  border: 1px solid var(--w-line); border-radius: 0.625rem; background: var(--w-paper);
}
.theme-choice {
  display: inline-flex; align-items: center; gap: 0.3rem;
  min-height: 30px; padding: 0.25rem 0.5rem; border: 0; border-radius: 0.5rem;
  background: none; color: var(--w-ink-3); font: inherit; font-size: 0.75rem; font-weight: 600;
  cursor: pointer;
}
.theme-choice .portal-icon { width: 0.875rem; height: 0.875rem; }
.theme-choice:hover { color: var(--w-ink); }
.theme-choice.is-selected {
  background: var(--w-card); color: var(--w-ink);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--w-ink) 14%, transparent);
}
.theme-choice.is-selected .portal-icon { color: var(--w-accent); }
.sidebar-appearance { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }

/* The panel's utilities followed margin-top:auto, so on a tall window the space between the last
   destination and them grew to whatever the window had spare - the clearest case of room spent on
   nothing. They sit under the destinations now, and only the account chip stays at the foot, which
   is the one thing that belongs there. */
.sidebar-bottom { margin-top: 1.5rem; padding-top: 0; }
.sidebar-bottom .account-menu { margin-top: auto; }
.sidebar-appearance { padding: 0.4rem 0.65rem; }

/* pt-5 pb-3 on the page header, as the mockup has it, rather than a band above the first thing on
   the screen and another below it. */
.shell-main { padding: 1.35rem 2.5rem 2.5rem; }

/* With the start card gone from Home there is nothing in the left column, so the join panel stops
   pretending to be half of a pair and takes the row. The seam and the split only make sense when
   there are two halves; on /start, where the start card is the only one, the same rule applies to
   it. */
@media (min-width: 70rem) {
  .workspace-signed-in:not(:has(.support-intent-hero)) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "join" "start";
  }
  .workspace-signed-in:not(:has(.support-intent-hero)) .workspace-join .portal {
    border-radius: 0.875rem;
  }
}
/* Icons only where the bar is tight, as the mockup does it (`hidden sm:inline` on the labels): two
   words each is what pushed the visitor bar past the viewport at 390px. The button keeps its title
   and its accessible name, so nothing is lost but the printed word. */
@media (max-width: 30rem) {
  .theme-choice-label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
}
