/* Layout and components. Colours come from tokens.css only. */

html, body { height: 100%; }
body {
  font-family: var(--q-font);
  background: var(--bg);
  color: var(--text);
  margin: 0;
}
a { color: var(--accent); }
/* Bootstrap draws form controls, menus and modals from its own body colours; in the dark theme they are ours, not its bluish grey. */
:root[data-theme="dark"] { --bs-body-bg: var(--surface); --bs-body-color: var(--text); --bs-border-color: var(--border-strong); --bs-secondary-bg: var(--surface-2); --bs-tertiary-bg: var(--surface-2); }
.btn-accent { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn-outline-accent { color: var(--accent); border-color: var(--accent); }
.btn-outline-accent:hover, .btn-outline-accent:focus { background: var(--accent); color: var(--accent-ink); }
.btn-accent:hover, .btn-accent:focus { background: var(--accent); color: var(--accent-ink); filter: brightness(1.08); }
.text-dim { color: var(--text-dim) !important; }
.text-faint { color: var(--text-faint) !important; }
.hidden { display: none !important; }

/* ------------------------------------------------------------ app frame */

.app { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
.topbar {
  display: flex; align-items: center; gap: .75rem;
  padding: .5rem 1.4rem; border-bottom: 1px solid var(--border); background: var(--surface);
  min-height: 56px; flex: 0 0 auto;
}
.topbar .brand { font-weight: 700; font-size: 1.05rem; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The brand reads the same on every page of the editor's; a participant's bar holds the session's title instead. */
.topbar a.brand, .app.editor .topbar .brand { color: var(--accent); }
.topbar a.brand > .icon { margin-right: .35rem; vertical-align: -.12em; }
.topbar .spacer { flex: 1 1 auto; }
/* A choice of one among a few options, as buttons (util.choice). */
.toggle-group { flex-wrap: wrap; }
/* A label sits above what it labels, a row of buttons included. */
.form-label { display: block; }
/* Icons (icons.js): 1em square on the text baseline, in the text colour. An icon with a word beside it (iconText) keeps them on one line. */
.icon { width: 1em; height: 1em; vertical-align: -.125em; flex: none; }
.icon-text { display: inline-flex; align-items: center; gap: .4em; white-space: nowrap; }
/* The browser's Back and Forward, at the left of the editor's top bar. */
.history-nav { display: inline-flex; gap: .1rem; margin-left: -.5rem; margin-right: -.25rem; flex: 0 0 auto; }
.history-button { width: 1.9rem; height: 1.9rem; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--text-dim); font-size: 1.125rem; }
.history-button:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.history-button:disabled { opacity: .35; }
.topbar .who { flex: 0 1 auto; max-width: 14em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 575.98px) { .topbar .who { max-width: 6em; } }

.stage { flex: 1 1 auto; display: flex; min-height: 0; }
.pane-chat { flex: 0 0 clamp(18rem, var(--chat-w, 420px), 60%); display: flex; flex-direction: column; min-width: 0; border-right: 1px solid var(--border); background: var(--surface); }
.pane-canvas { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
/* Stacked on a phone, a pane must be allowed to be shorter than what it holds, or a long text grows past the screen instead of scrolling. */
.pane-chat, .pane-canvas { min-height: 0; }
.stage.no-board .pane-chat { flex: 1 1 auto; border-right: 0; max-width: 820px; margin: 0 auto; }
.stage.no-board .pane-canvas { display: none; }
.stage.no-chat .pane-chat { display: none; }
/* The chat's own border is the line; the divider is a grip over it that takes no width. */
.stage > .divider { flex: 0 0 10px; margin: 0 -5px; z-index: 5; }
.stage > .divider::after { background: transparent; }
.stage.no-board > .divider, .stage.no-chat > .divider { display: none; }
.chat-note { margin: 0 0 .4rem; color: var(--text-dim); font-size: .85rem; }
.mobile-tabs { display: none; }

/* What a chat step is about, above the chat. */
.topic-bar { flex: 0 0 auto; padding: .45rem .9rem; border-bottom: 1px solid var(--border); background: var(--accent-soft); font-weight: 600; }
/* Back and Next of a person's own, where each goes at their own pace (session.js renderPace). */
.pace-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; gap: .75rem; padding: .35rem .9rem; border-bottom: 1px solid var(--border); background: var(--surface); }
.pace-where { font-size: .85rem; color: var(--text-dim); white-space: nowrap; }
/* On a computer, beside a board, the same in the board's title bar, after its name. */
.canvas-title > .pace-bar { gap: .5rem; padding: 0; border: 0; background: none; font-weight: 400; }
/* In Design's frame, the agenda picks the step. */
.app.embedded .pace-bar { display: none; }
/* The run controls (overview.js): Back, and Next naming the step it will show. */
.run-steps { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; min-width: 0; flex: 0 1 auto; }
.run-steps:empty { display: none; }
.run-steps .btn { padding-left: .7rem; padding-right: .7rem; }
.run-next { display: inline-flex; align-items: center; gap: .4rem; max-width: 24rem; min-width: 0; flex-shrink: 0; }
.run-next-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.manage-page .topbar-wrap { position: sticky; top: 0; z-index: 20; }
.topbar-wrap { flex: 0 0 auto; }
/* The editor's own tab as a participant says what it is. */
.guest-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; gap: .5rem; padding: .35rem .9rem; font-size: .85rem; text-align: center; background: var(--gold-fill); color: var(--text); border-bottom: 1px solid var(--gold); }
.guest-bar .btn-close { flex: 0 0 auto; padding: .75rem; }
@media (max-width: 767.98px) { .guest-bar { font-size: .78rem; padding: .1rem .3rem .1rem .8rem; text-align: left; } }
/* The run bar: the run controls and who is here, under the projector's top bar. */
.runbar { display: flex; align-items: center; gap: .5rem; padding: .5rem 1.4rem .45rem; border-bottom: 1px solid var(--border); background: var(--bg); min-width: 0; }
.runbar:empty { display: none; }
.account-button { width: 2rem; height: 2rem; border-radius: 50%; border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text); font-weight: 600; font-size: .85rem; padding: 0; }
.account-button.dropdown-toggle::after { display: none; }

.editor-tabs { display: flex; gap: .2rem; flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.editor-tab { padding: .3rem .65rem; border: 0; border-radius: var(--r-sm); color: var(--text-dim); text-decoration: none; font-weight: 600; font-size: .9rem; white-space: nowrap; }
button.editor-tab { background: transparent; }
.editor-tab:hover { color: var(--text); background: var(--surface-2); }
.editor-tab.active { color: var(--text); background: var(--accent-soft); }
/* The session the tabs are about, after the brand and the All sessions tab, which opens a menu of the others,
   with the page's controls for it beside it, inside one rounded border since they belong together;
   then the Design tab, and Share and ? apart at the right. Inside it the menu and the gear lose borders of their own. */
.editor-tabs > [data-tab="session"] { display: flex; align-items: center; gap: .25rem; flex: 0 0 auto; align-self: center; margin-left: 1rem; margin-right: 1rem;
  padding: .15rem .65rem .15rem .15rem; border: 1px solid var(--border-strong); border-radius: var(--r-pill); background: var(--surface); }
.editor-tabs > [data-tab="session"]:has(> :only-child) { padding-right: .15rem; }
.editor-tabs > [data-tab="session"] .session-switch,
.editor-tabs > [data-tab="session"] .gear-button:not([aria-expanded="true"]) { border-color: transparent; }
.help-button { min-width: 2.2rem; justify-content: center; font-size: 1rem; }
/* Whether the session is a rehearsal, live or closed: the word, after a dot in its colour. */
.status-blob { display: inline-flex; align-items: center; gap: .35rem; flex: 0 0 auto; font-size: .8rem; font-weight: 600; color: var(--text); white-space: nowrap;
  background: none; border: 0; padding: .2rem .3rem; border-radius: var(--r-pill); cursor: pointer; }
.status-blob:hover { background: var(--surface-2); }
.status-blob::before { content: ''; width: .65rem; height: .65rem; border-radius: 50%; background: var(--warn); }
.status-blob.live::before { background: var(--ok); }
.status-blob.closed::before { background: var(--text-faint); }
.session-switch { border: 1px solid var(--border); background: var(--surface); min-width: 18rem; max-width: 30rem; overflow: hidden; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .3rem .75rem; border-radius: var(--r-pill); color: var(--text); font-weight: 600; font-size: .9rem; }
.session-switch > span { overflow: hidden; text-overflow: ellipsis; }
.session-switch:hover, .session-switch[aria-expanded="true"] { background: var(--surface-2); border-color: var(--border-strong); }
/* On a wide screen the tabs stand on the bar's lower edge, and the open one joins the page below. The tabs' box reaches
   the bar's border, so a tab is as tall as the bar's content plus its bottom padding, and that padding is repeated inside
   the tab, which puts its words on the bar's centre line, level with the brand and the account. The session's menu is
   centred in the same box and lifted by the same distance. */
@media (min-width: 768px) {
  .editor-tabs { align-self: stretch; align-items: stretch; margin-bottom: calc(-.5rem - 1px); }
  .editor-tabs > .dropdown { display: flex; }
  .editor-tab { display: inline-flex; align-items: center; border: 1px solid transparent; border-bottom: 0; border-radius: var(--r-sm) var(--r-sm) 0 0; padding: 0 .85rem calc(.5rem + 1px); }
  /* A tab not open still reads as a tab: a faint edge and tint, sitting a little lower than the open one, which fade
     out below its words (the mask), so the bar's own lower line shows across its foot with a gap above it, and only the
     open tab reaches the page. */
  .editor-tab:not(.active) { margin-top: .3rem; border-color: color-mix(in srgb, var(--border) 70%, transparent);
    padding-bottom: calc(.5rem + 1px); background: color-mix(in srgb, var(--surface-2) 55%, transparent);
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - .85rem), transparent calc(100% - .25rem));
    mask-image: linear-gradient(to bottom, #000 calc(100% - .85rem), transparent calc(100% - .25rem)); }
  .editor-tab:hover { background: var(--surface-2); }
  /* The open tab joins the page: taller than the others and one pixel lower, over the bar's border, with the padding to
     match so its words line up with theirs, a band of the accent along its top and its words at full strength. */
  .editor-tab.active { background: var(--bg); border-color: var(--border-strong); box-shadow: inset 0 3px 0 var(--accent); color: var(--text); position: relative; margin-bottom: -1px; padding-top: .3rem; padding-bottom: calc(.5rem + 2px); }
  .editor-tabs > [data-tab="session"] { align-self: center; margin-bottom: calc(.5rem + 1px); }
  /* All sessions comes first, then the session's menu and Design straight after it; Share and ? stand together at the right, or ? alone without a session. */
  .editor-tabs > [data-tab="sessions"] { margin-left: .75rem; }
  .editor-tabs > [data-tab="session"] { margin-left: .5rem; margin-right: .25rem; }
  .editor-tabs > [data-tab="share"], .editor-tabs > [data-tab="help"] { margin-left: auto; }
  .editor-tabs > [data-tab="share"] ~ [data-tab="help"] { margin-left: 0; }
}

/* The room screen is laid out by its own width rather than the window's, so a phone drawn inside a computer's window
   (the replay's, film.js) has the phone's Chat and Board tabs as a real one does. */
.app, .room-screen { container: room / inline-size; }
@container room (max-width: 767.98px) {
  .stage { flex-direction: column; }
  .mobile-tabs { display: flex; flex: 0 0 auto; border-bottom: 1px solid var(--border); background: var(--surface); }
  .mobile-tabs button { flex: 1; border: 0; background: none; padding: .55rem; color: var(--text-dim); font-weight: 600; }
  .mobile-tabs button.active { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); }
  .stage.no-board .mobile-tabs, .stage.no-chat .mobile-tabs { display: none; }
  .pane-chat { flex: 1 1 auto; border-right: 0; }
  .stage > .divider { display: none; }
  /* With no board the chat is the whole screen: a centred column here would be as wide as its widest line, or too narrow. */
  .stage.no-board .pane-chat { margin: 0; max-width: none; }
  .stage[data-tab="board"] .pane-chat { display: none; }
  .stage[data-tab="chat"] .pane-canvas { display: none; }
  .stage[data-tab="board"] .pane-canvas { flex: 1 1 auto; }
}
@media (max-width: 767.98px) {
  .app.editor .topbar .brand, .app.editor .topbar .who { display: none; }
  .editor-tab { padding: .3rem .45rem; font-size: .82rem; }
  .session-switch { min-width: 0; max-width: 8rem; }
  /* The editor's bar on a narrow screen is two rows: the brand, Sessions and the account, then the session's own menu
     across the whole width. Back and Forward are the browser's own, Design is in the session menu, and Share stays on the first row. */
  :is(.manage-page, .home-page) .editor-tabs > [data-tab="design"], .history-nav { display: none; }
  :is(.manage-page, .home-page) .editor-tabs { display: contents; }
  :is(.manage-page, .home-page) .topbar .brand { order: 1; }
  :is(.manage-page, .home-page) .editor-tabs > :is([data-tab="sessions"], [data-tab="help"]) { order: 2; }
  .manage-page #account, .home-page .theme-toggle { order: 3; margin-left: auto; }
  .home-page #h-account { order: 3; }
  /* min-width: 0, or the title, the gear and the status make the row, and the page, wider than the screen. */
  :is(.manage-page, .home-page) .editor-tabs > [data-tab="session"] { order: 4; flex: 1 1 100%; min-width: 0; margin: 0; }
  :is(.manage-page, .home-page) .editor-tabs > [data-tab="session"] > .dropdown { flex: 1 1 auto; min-width: 0; }
  :is(.manage-page, .home-page) .editor-tabs > [data-tab="session"] .session-switch { width: 100%; max-width: none; }
  .topbar { flex-wrap: wrap; row-gap: .35rem; padding-left: .8rem; padding-right: .8rem; }
  .runbar { padding-left: .8rem; padding-right: .8rem; }
  .run-next { max-width: 12rem; }
  /* A participant's bar is one row: the session's title takes what the buttons leave, and the name is in the room menu. */
  .app:not(.editor) .topbar { flex-wrap: nowrap; gap: .4rem; min-height: 0; padding-top: .3rem; padding-bottom: .3rem; }
  .app:not(.editor) .topbar .brand { flex: 1 1 0; min-width: 0; }
  .app:not(.editor) .topbar :is(.spacer, .who) { display: none; }
  .canvas-title { padding: .35rem .75rem; }
}
/* The item a menu is on now (the workshop in the top bar's menu, the room you are in) in the app's tint, not Bootstrap's
   blue; the doubled class outranks Bootstrap's own variables on .dropdown-menu, whichever loads last. */
.dropdown-menu.dropdown-menu { --bs-dropdown-link-active-bg: var(--accent-soft); --bs-dropdown-link-active-color: var(--text); }
.dropdown-menu .dropdown-item.active { font-weight: 600; box-shadow: inset 3px 0 0 var(--accent); }
/* Fingers need 40px. */
@media (pointer: coarse) {
  .app .topbar .btn { min-height: 40px; display: inline-flex; align-items: center; }
  .theme-toggle { min-width: 40px; justify-content: center; }
  .dropdown-menu .dropdown-item { min-height: 40px; display: flex; align-items: center; }
  .composer .form-control, .composer .btn { min-height: 40px; }
  .reply-bar .btn-close { padding: .75rem; }
  .run-bar .btn, .runbar .btn, .step-line .btn { min-height: 40px; }
  .tree-pop .btn, .tree-pop .form-control { min-height: 40px; }
  .map-tools .btn, .map-tools .form-control { min-height: 40px; }
}
/* The room screen inside Design's frame keeps only the room menu in its bar. */
.app.embedded .topbar { min-height: 0; padding: .3rem .6rem; }
.app.embedded .topbar .brand, .app.embedded .topbar .who, .app.embedded .theme-toggle { display: none; }
/* An editor's room buttons (session.js), one per room of the step. */
.room-row { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .35rem; min-width: 0; }
.app.editor .topbar { flex-wrap: wrap; }
.badge-unread { background: var(--voice-ai); color: var(--surface); border-radius: var(--r-pill); font-size: .7rem; padding: .05rem .4rem; margin-left: .3rem; }

/* ------------------------------------------------------------ join */

.center-card { max-width: 420px; margin: 12vh auto 0; padding: 1.5rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); box-shadow: var(--shadow); }
.center-card :is(h1, h2) { font-size: 1.4rem; }
/* On a short screen the card starts near the top, so what it asks you to press is not at the bottom edge. */
@media (max-width: 767.98px) { .center-card { margin-top: 1rem; } }

/* ------------------------------------------------------------ chat */

.chat-list { flex: 1 1 auto; overflow-y: auto; padding: .75rem .75rem 0; display: flex; flex-direction: column; gap: .35rem; }
.msg { max-width: 88%; align-self: flex-start; background: var(--surface-2); border-radius: var(--r); padding: .4rem .65rem .45rem; position: relative; }
.msg.mine { align-self: flex-end; background: var(--accent-soft); }
.proposal { margin-top: .4rem; padding: .4rem .55rem; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); font-size: .9em; }
.proposal ul { margin: .15rem 0 .3rem; padding-left: 1.1rem; }
.proposal-head { font-weight: 600; }
.proposal-state { color: var(--text-dim); }
.proposal-actions { display: flex; gap: .4rem; margin-top: .35rem; }
/* A highlight Qualia or the editor put in a slide or card (<mark>). */
mark { background: var(--gold-fill); color: inherit; padding: 0 .1em; border-radius: 2px; }
.msg.qualia { background: var(--voice-ai-fill); border-left: 3px solid var(--voice-ai); }
.msg.flash { outline: 2px solid var(--accent); }
.msg-head { display: flex; gap: .5rem; align-items: baseline; font-size: .78rem; color: var(--text-dim); }
.msg-head .who { font-weight: 600; color: var(--text); }
.msg.qualia .msg-head .who { color: var(--voice-ai); }
.msg-head .tag { font-size: .68rem; border: 1px solid var(--border-strong); border-radius: var(--r-pill); padding: 0 .35rem; }
.msg-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.msg.qualia .msg-text { white-space: normal; }
.msg.qualia .msg-text p:last-child, .msg.qualia .msg-text ul:last-child { margin-bottom: 0; }
.msg-text .deleted { color: var(--text-faint); font-style: italic; }
.mention { color: var(--accent); font-weight: 600; }
.mention.me { background: var(--gold-fill); color: var(--gold); border-radius: 4px; padding: 0 .15rem; }
.quote {
  font-size: .82rem; color: var(--text-dim); border-left: 3px solid var(--border-strong);
  padding: .1rem .5rem; margin: .15rem 0 .3rem; cursor: pointer;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.quote .who { font-weight: 600; color: var(--text); }
/* A reply straight under what it answers (chat.js markFollows): no quote, and a dotted line from it up to that message,
   at its own side, or on the inner side where one is your own and the other is not (.across), so it meets both.
   With the list's gap the two are .95rem apart, enough for the line to be seen. */
.msg.follows { margin-top: .6rem; }
.msg.follows > .quote { display: none; }
.msg.follows::before { content: ''; position: absolute; left: 1.25rem; top: -.95rem; height: .95rem; border-left: 2px dotted var(--text-faint); }
.msg.mine.follows::before, .msg.follows.across::before { left: auto; right: 1.25rem; }
.msg.mine.follows.across::before { left: 1.25rem; right: auto; }
.msg-actions { display: none; position: absolute; top: -.7rem; right: .4rem; gap: .25rem; }
.msg:hover .msg-actions, .msg.show-actions .msg-actions { display: flex; }
.msg-actions button { font-size: .85rem; line-height: 1.5; border: 1px solid var(--border); background: var(--surface); color: var(--text-dim); border-radius: var(--r-pill); padding: 0 .5rem; }
.msg-actions button:hover { color: var(--text); }
/* No hover on a touch screen: a tap opens the actions, as a row under the words, with fingertip-sized buttons. */
@media (pointer: coarse) {
  .msg-actions { position: static; margin-top: .35rem; }
  .msg-actions button { min-height: 40px; min-width: 48px; font-size: 1rem; }
}
/* One thin bar for each earlier step that has messages; a press opens it (foldedList in chat.js). */
.earlier-bar { align-self: stretch; display: flex; justify-content: space-between; gap: .5rem; margin: 0 0 2px; padding: .1rem .55rem;
  border: 0; border-radius: var(--r-sm); background: var(--surface-2); color: var(--text-dim); font-size: .72rem; line-height: 1.4; text-align: left; }
.earlier-bar:hover { color: var(--text); }
.earlier-bar.open { color: var(--text); margin-top: .35rem; }
.earlier-step { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.earlier-count { flex: 0 0 auto; color: var(--text-faint); }
.step-began { align-self: stretch; text-align: center; font-size: .75rem; color: var(--text-faint); border-top: 1px solid var(--border); margin: .35rem 0; padding-top: .2rem; }
.writing { font-size: .82rem; color: var(--voice-ai); padding: .25rem .9rem; }
.writing:empty { display: none; }
.new-below { position: absolute; bottom: .5rem; left: 50%; transform: translateX(-50%); }

.composer { border-top: 1px solid var(--border); padding: .5rem; position: relative; background: var(--surface); }
.composer textarea { resize: none; max-height: 9rem; }
.reply-bar { display: flex; align-items: center; gap: .5rem; font-size: .82rem; color: var(--text-dim); padding: 0 .25rem .35rem; }
.reply-bar .snippet { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mention-menu {
  position: absolute; bottom: 100%; left: .5rem; z-index: 20; min-width: 220px; max-width: min(26rem, calc(100vw - 1rem)); max-height: 240px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-sm); box-shadow: var(--shadow);
}
.mention-menu button { display: block; width: 100%; text-align: left; border: 0; background: none; padding: .35rem .7rem; color: var(--text); }
.mention-menu button.active, .mention-menu button:hover { background: var(--accent-soft); }
.mention-menu button .detail { display: block; font-size: .78rem; color: var(--text-dim); }

/* ------------------------------------------------------------ canvas */

.canvas-title { display: flex; align-items: center; gap: .5rem; padding: .5rem .75rem; font-weight: 600; border-bottom: 1px solid var(--border); flex: 0 0 auto; }
.canvas-name { flex: 1 1 auto; min-width: 0; }
.canvas-locked { flex: 0 0 auto; font-size: .8rem; font-weight: 400; color: var(--text-dim); }
/* What a person can do on the board (util.js sayHint), in a pill beside its name. */
.canvas-hint { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .78rem; font-weight: 500;
  color: var(--accent); border: 1px solid currentColor; border-radius: var(--r-pill); padding: .05rem .55rem; }
.canvas-hint.pulse { animation: hint-pulse 1s ease-in-out 3; }
@keyframes hint-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent); } }
@media (prefers-reduced-motion: reduce) { .canvas-hint.pulse { animation: none; } }
.canvas-full { flex: 0 0 auto; border: 0; background: none; color: var(--text-dim); padding: 0 .25rem; font-size: 1.15rem; line-height: 1; }
.canvas-full:hover { color: var(--text); }
.canvas-undos { flex: 0 0 auto; display: flex; gap: .1rem; }
.canvas-undo { border: 0; background: none; color: var(--text-dim); padding: 0 .3rem; font-size: 1.15rem; line-height: 1; }
.canvas-undo:hover { color: var(--text); }
/* Full screen: the slide alone, without the chat, a map's tools or its note, its name large, and a text as the
   projector shows it (below, with .present). */
.pane-canvas:fullscreen { background: var(--surface); }
.pane-canvas:fullscreen .canvas-name { font-size: clamp(1.25rem, 2.6vw, 2.2rem); }
.pane-canvas:fullscreen .map-tools > :not(.map-crumbs, .map-zoom), .pane-canvas:fullscreen .board-note { display: none; }
.map-crumbs { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: baseline; gap: .35rem; font-size: .9rem; }
.map-crumbs .sep { color: var(--text-faint); }
.canvas-body { flex: 1 1 auto; position: relative; min-height: 0; overflow: auto; background: var(--surface); }
/* A text in the room is read on its own, so it has reading size and a measure of its own, centred in a wide pane; the
   projector's is larger again (below, with .present). */
.canvas-text { padding: 1.5rem 2rem; max-width: 68ch; margin: 0 auto; font-size: 1.1rem; line-height: 1.55; }
.canvas-text li + li { margin-top: .35em; }
.canvas-media { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: #000; }
.canvas-media video, .canvas-media img { max-width: 100%; max-height: 100%; }
.canvas-fill { position: absolute; inset: 0; }
.canvas-empty { color: var(--text-faint); padding: 2rem; text-align: center; }
.board-frame { width: 100%; height: 100%; border: 0; display: block; background: var(--surface); }
.board-note { position: absolute; left: .75rem; bottom: .5rem; font-size: .8rem; color: var(--text-dim); background: var(--surface); padding: .15rem .5rem; border-radius: var(--r-sm); }
.board-note:empty { display: none; }

.tree-pop {
  position: absolute; z-index: 30; width: 260px; max-height: 70%; overflow: auto; background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--r); box-shadow: var(--shadow); padding: .65rem;
}
.tree-pop .label { font-weight: 600; margin-bottom: .4rem; overflow-wrap: anywhere; }
/* What sits over the top of a map: the box for a free box on a network map, the slider that folds a grouped map,
   and the grouping tools. Each is its own card, and the row wraps on a narrow screen. */
.map-tools { position: absolute; z-index: 20; left: .75rem; right: .75rem; top: .5rem; display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; pointer-events: none; }
.map-tools > * {
  pointer-events: auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: .35rem;
  box-shadow: var(--shadow-sm);
}
.map-add { display: flex; gap: .35rem; width: min(380px, 100%); }
.map-fold { display: flex; align-items: center; gap: .5rem; }
.map-fold .form-range { width: 8rem; }
.map-level { font-size: .8rem; color: var(--text-dim); min-width: 4.8rem; }
.map-group { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }
.map-group .form-control { width: 9rem; }
/* Zoom, then who else is in the room, at the end of the row over the map. */
.map-tools > .map-zoom { margin-left: auto; display: flex; gap: .25rem; padding: .25rem; }
.map-tools > .map-zoom ~ .map-here { margin-left: 0; }
.map-tools > .map-here { margin-left: auto; display: flex; gap: .25rem; padding: .25rem .35rem; }
.map-here.hidden { display: none; }
.map-face {
  width: 1.7rem; height: 1.7rem; border-radius: var(--r-pill); display: inline-flex; align-items: center; justify-content: center;
  font-size: .72rem; font-weight: 700; background: var(--accent-soft); color: var(--text); border: 1px solid var(--border-strong);
}
/* Over a box somebody else in the room is dragging, saying who. */
.map-mover {
  position: absolute; z-index: 25; transform: translate(-50%, -100%); pointer-events: none; white-space: nowrap;
  font-size: .75rem; font-weight: 600; padding: .1rem .45rem; border-radius: var(--r-pill); background: var(--accent); color: var(--accent-ink);
}
/* The colours a box may be, in its panel. */
.map-swatches { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .45rem; }
.map-swatch {
  width: 1.6rem; height: 1.6rem; padding: 0; border-radius: var(--r-pill); border: 1px solid var(--border-strong); background: var(--surface-2);
}
.map-swatch[data-colour="yellow"] { background: var(--note-yellow); }
.map-swatch[data-colour="orange"] { background: var(--note-orange); }
.map-swatch[data-colour="pink"] { background: var(--note-pink); }
.map-swatch[data-colour="blue"] { background: var(--note-blue); }
.map-swatch[data-colour="green"] { background: var(--note-green); }
.map-swatch[aria-pressed="true"] { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ------------------------------------------------------------ editor */

.manage-wrap { max-width: 1100px; margin: 0 auto; padding: 1rem; }
/* Design takes the whole width. */
.manage-wrap.wide { max-width: none; }
/* The agenda, as wide as its divider was dragged; then the right-hand side: the run controls and Replay at its
   top, and under them the step picked, as its previews or, when it is the step showing, as the editor's own room.
   The previews stay in view, and the step scrolls inside them. */
.design-grid { display: grid; grid-template-columns: clamp(20rem, var(--agenda-w, 34rem), 58%) 1rem minmax(0, 1fr); gap: 1rem 0; align-items: start; }
.design-grid > .divider { align-self: stretch; }
.design-right { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.manage-wrap:not(.in-room) .design-right { position: sticky; top: calc(var(--topbar-h, 0px) + .75rem); max-height: calc(100vh - var(--topbar-h, 0px) - 1.5rem); }
.step-panel { min-height: 0; overflow-y: auto; padding: .75rem; background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); }
.panel-body { display: flex; flex-direction: column; gap: .75rem; }
@media (max-width: 991.98px) {
  .design-grid { grid-template-columns: minmax(0, 1fr); }
  .design-grid > .divider { display: none; }
  .manage-wrap:not(.in-room) .design-right { position: static; max-height: none; }
}
/* The run controls and Replay; the editor's own room, when the step picked is the one showing; and a replay in place of both. */
.run-bar { display: flex; align-items: center; gap: .5rem; }
.run-controls { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; flex: 1 1 auto; min-width: 0; }
/* What the right-hand side is: a preview of the step picked, or the editor's room while it shows. */
/* What the preview is, over it for a moment when that changes (manage.js, sayWhat); it takes no row. */
.stage-toast { position: absolute; top: .4rem; left: 50%; transform: translate(-50%, -.25rem); z-index: 6; max-width: calc(100% - 1rem);
  padding: .35rem .8rem; border-radius: var(--r-pill); background: var(--surface-2); border: 1px solid var(--border-strong);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .18); font-size: .8rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; pointer-events: none; transition: opacity .3s ease, transform .3s ease; }
.stage-toast.show { opacity: 1; transform: translate(-50%, 0); }
.stage-toast strong { color: var(--text); }
.panel-switch { display: inline-flex; min-width: 0; max-width: 16rem; }
.panel-switch .btn { overflow: hidden; text-overflow: ellipsis; }
.replaying > .step-panel { display: none; }
.room-frame { position: absolute; top: 0; left: 0; transform-origin: 0 0; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
@media (max-width: 991.98px) { .run-bar { flex-wrap: wrap; } }
/* A room the picked step shows in: a line, opened for who is in it. */
.room-tile { border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); padding: .3rem .55rem; margin-bottom: .35rem; }
.room-tile > summary { display: flex; align-items: baseline; gap: .4rem; cursor: pointer; }
.room-tile > .room-card, .room-tile > .chips { margin-top: .35rem; border: 0; padding: 0; }
/* One device, and the projector small at the top right (stepPanel). */
.preview-stage { position: relative; display: flex; align-items: flex-start; gap: 12px; margin-top: .5rem; }
.proj-thumb { position: absolute; right: .5rem; bottom: .5rem; z-index: 5; padding: .25rem .4rem .4rem; background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-sm); box-shadow: var(--shadow); }
.proj-label { display: flex; align-items: baseline; gap: .6rem; font-size: .8rem; color: var(--text-dim); }
.proj-frame { pointer-events: none; }
.present-page.embedded #present-top, .present-page.embedded > .controls { display: none !important; }
/* A divider dragged sideways to share the width between the two sides of it. */
.divider { position: relative; cursor: col-resize; touch-action: none; }
.divider::after { content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--border); }
.divider:hover::after, .divider:focus-visible::after, .dividing .divider::after { background: var(--accent); }
.divider:focus-visible { outline: 0; }
.dividing, .dividing * { cursor: col-resize !important; user-select: none; }
.dividing iframe { pointer-events: none; }
.preview-fit { position: relative; overflow: hidden; margin-top: .2rem; }
/* Drawn at the device's own size and scaled down by screens.js. */
.preview-screen {
  position: absolute; top: 0; transform-origin: 0 0; display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-sm);
}
.preview-screen > .canvas-body { flex: 1 1 auto; }
.preview-screen > .present { flex: 1 1 auto; }
/* Measured in the screen's own pixels, since the page's vw and vh are not the preview's. The QR's white ground and padding come from .present .qr-side svg. */
.preview-screen .present .qr svg { width: 300px; }
.preview-screen .present.with-board .qr svg { width: 100px; }
.preview-screen .present-kicker { font-size: 26px; }
.preview-screen .present-question { font-size: 56px; }
.preview-screen .present-detail { font-size: 28px; }
/* A step's picture, in the running order and the Add a step menu. */
.pic { display: inline-block; width: 48px; height: 36px; flex: 0 0 auto; color: var(--text-dim); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); }
.pic svg { display: block; }
:is(.pic, .help-pic) .pl { fill: var(--surface-2); stroke: currentColor; stroke-width: 1.4; }
:is(.pic, .help-pic) .ln { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
:is(.pic, .help-pic) .pa { fill: var(--accent); }
:is(.pic, .help-pic) .pg { fill: var(--gold-fill); stroke: var(--gold); stroke-width: 1.2; }
:is(.pic, .help-pic) .pq { fill: var(--voice-ai); }
:is(.pic, .help-pic) text { fill: currentColor; font-family: var(--q-font); }
:is(.pic, .help-pic) text.ta { fill: var(--accent); }
/* New session: the templates and a blank session, two to a row. */
.start-intro { margin: 0 0 .75rem; }
.start-gallery { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; align-items: stretch; }
@media (max-width: 767.98px) { .start-gallery { grid-template-columns: 1fr; } }
/* One board or a whole workshop, between the two galleries. */
.start-tabs { margin: 1rem 0 .75rem; }
.start-card { display: block; text-align: left; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); padding: .9rem 1rem; color: var(--text); }
.start-card:hover, .start-card:focus-visible { border-color: var(--accent); background: var(--surface-2); }
/* The choice a link from Home or Help asked for (openNew in manage.js). */
.start-card.start-picked { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
/* The draft card is a form, not a button, so it does not change under the pointer as one does. */
.start-card.start-draft, .start-card.start-draft:hover { border-color: var(--accent); background: var(--surface); }
.draft-working { color: var(--voice-ai); font-weight: 600; }
/* Over Design while an example fills, and after (exampleBanner in manage.js). */
/* What is happening, a line at a time: over Design while an example fills (manage.js exampleBanner), and above a shared
   replay (replay.js); in the accent once it is over. */
.status-banner { margin: 0 0 .75rem; padding: .6rem .9rem; border: 1px solid var(--voice-ai); border-radius: var(--r); background: var(--surface); color: var(--voice-ai); font-weight: 600; }
.status-banner.status-done { border-color: var(--accent); color: var(--text); font-weight: 400; }
.start-pics { display: flex; flex-wrap: wrap; gap: .3rem; margin: .6rem 0; }
.board-menu { display: grid; grid-template-columns: repeat(4, 1fr); gap: .25rem; }
@media (max-width: 1199.98px) { .board-menu { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 991.98px) { .board-menu { grid-template-columns: 1fr 1fr; } }
.board-menu .dropdown-item { height: 100%; white-space: normal; padding: .6rem .75rem; border-radius: var(--r-sm); }
.board-menu .menu-heading { grid-column: 1 / -1; padding: .6rem .75rem .1rem; font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim); }
.board-menu .menu-heading:first-child { padding-top: .2rem; }
@media (max-width: 575.98px) { .board-menu { grid-template-columns: 1fr; } }
.room-card { border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); padding: .5rem .6rem; }
.room-card.drop { outline: 2px dashed var(--accent); }
.res-row { display: flex; align-items: center; gap: .5rem; padding: .3rem 0; border-top: 1px solid var(--border); }
.res-row .title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kind { font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-dim); border: 1px solid var(--border-strong); border-radius: var(--r-pill); padding: 0 .4rem; }

.room-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: .5rem; }
.chips { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; margin-top: .35rem; }
.chip {
  display: inline-flex; align-items: center; gap: .3rem; border: 1px solid var(--border-strong); background: var(--surface-2);
  border-radius: var(--r-pill); padding: .1rem .55rem; font-size: .85rem; cursor: grab; user-select: none;
}
.chip.selected { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.chip .dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--text-faint); }
.chip .dot.on { background: var(--ok); }
.select-bar { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; padding: .4rem .6rem; margin-top: .35rem; border-radius: var(--r); background: var(--accent-soft); }

/* ------------------------------------------------------------ replay */

/* The replay, in Design in place of the step picked (film.js), and its controls: play, speed, the device, the slider with a mark at each change of step, and the clock. */
.film-speed { display: inline-flex; align-items: center; gap: .4rem; margin: 0; font-size: .85rem; color: var(--text-dim); }
.film-speed .form-range { width: 6.5rem; margin: 0; }
.film { display: flex; flex-direction: column; min-height: 26rem; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); overflow: hidden; }
/* The respondent's screen sits on a darker desk, in a bezel, under a line saying whose it is; the controls above are ours. */
.film-desk { flex: 1 1 auto; padding: .6rem .9rem .9rem; background: var(--bg); border-top: 1px solid var(--border-strong); }
.film-desk > .preview-stage { margin: 0; }
.film-caption { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .2rem 1rem; margin-bottom: .7rem; font-size: .8rem; color: var(--text-dim); }
.film-caption-who { font-weight: 600; color: var(--text); }
.film-desk .device-fit { margin: 6px 0 0 6px; border-radius: 10px; box-shadow: 0 0 0 6px var(--text-faint), 0 12px 32px rgba(0, 0, 0, .35); }
.film > .runbar { flex-wrap: wrap; }
.film-track { flex: 1 1 auto; min-width: 8rem; display: flex; flex-direction: column; }
.film-slider { margin: 0; display: block; }
/* The marks sit on the slider's track, across its height, inset by half the thumb so each lines up with where the thumb stands at that moment. */
.film-scrub { position: relative; }
.film-ticks { position: absolute; left: 8px; right: 8px; top: 50%; height: .5rem; transform: translateY(-50%); pointer-events: none; }
.film-tick { position: absolute; top: 0; width: 3px; height: 100%; margin-left: -1px; padding: 0; border: 0; border-radius: 1px; background: var(--accent); opacity: .45; pointer-events: auto; }
.film-tick:hover { opacity: 1; }
.film-note { font-size: .75rem; color: var(--text-faint); }
.film-clock { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text-dim); font-size: .9rem; }
/* A replay shared by link (replay.html): the session's title in the top bar, and the film across the page. */
.replay-title { margin: 0; font-size: 1rem; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.replay-wrap { max-width: 1400px; margin: 0 auto; padding: .75rem; }
.replay-page .topbar { flex-wrap: nowrap; }
/* What a shared replay is, over the page until it is closed (replay.js). */
.replay-intro { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 1rem;
  background: color-mix(in srgb, var(--bg) 70%, transparent); backdrop-filter: blur(3px); opacity: 0; transition: opacity .3s ease; }
.replay-intro.open { opacity: 1; }
.replay-intro-card { max-width: 34rem; padding: 1.5rem 1.75rem; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); box-shadow: 0 10px 40px rgba(0, 0, 0, .25); }
.replay-intro-card ul { padding-left: 1.2rem; }
.replay-intro-card li { margin-bottom: .35rem; }
.replay-intro-actions { display: flex; align-items: center; gap: 1.25rem; margin-top: 1rem; }
/* A copy link's offer: Make my own copy in the top bar, and the steps where there is no replay to watch. */
.copy-take { flex: none; }
.copy-offer { max-width: 40rem; margin: 1.5rem auto; }
.copy-steps { margin: .75rem 0 0; padding-left: 1.4rem; }
.replay-page .topbar .brand { flex: 0 0 auto; }
@media (max-width: 575.98px) { .replay-page .topbar { padding-left: .8rem; padding-right: .8rem; gap: .5rem; } .replay-wrap { padding: .4rem; } }
.rooms-bar { display: flex; flex-wrap: wrap; gap: .35rem; padding: .45rem 1.4rem; border-bottom: 1px solid var(--border); background: var(--bg); }
.rooms-bar:empty { display: none; }
.room-count { margin-left: .4rem; font-size: .75rem; color: var(--text-dim); }
.room-pick.active .room-count { color: inherit; }
@media (max-width: 767.98px) {
  .rooms-bar { padding-left: .8rem; padding-right: .8rem; }
}

/* ------------------------------------------------------------ present */

.present-page { height: 100dvh; display: flex; flex-direction: column; margin: 0; }
.present { flex: 1 1 auto; min-height: 0; display: flex; background: var(--surface); }
:fullscreen #present-top { display: none; }
/* Out of full screen the top bar's run controls do this; in it, these are the only controls. */
:root:not(:fullscreen) #step-back, :root:not(:fullscreen) #step-next { display: none; }
.present .qr-side { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 2rem; gap: 1rem; text-align: center; }
.present .qr-side svg { width: min(50vh, 80vw); height: auto; background: #fff; padding: 12px; border-radius: var(--r); }
.present .how { font-size: clamp(1rem, 2.2vw, 1.6rem); }
.present .code { font-size: clamp(2rem, 6vw, 4.5rem); font-weight: 700; letter-spacing: .12em; }
/* With a board showing, the way in shrinks to one strip above it, so the board has the screen. */
.present.with-board { flex-direction: column; }
.present.with-board .qr-side { flex: 0 0 auto; flex-direction: row; justify-content: flex-start; padding: .4rem 1rem; gap: .9rem; text-align: left; border-bottom: 1px solid var(--border); }
.present.with-board .qr-side h1 { flex: 1 1 auto; min-width: 0; font-size: 1.3rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.present.with-board .qr-side svg { width: 14vh; padding: 6px; border-radius: var(--r-sm); }
.present.with-board .how { font-size: 1.15rem; }
.present.with-board .code { font-size: 2.2rem; }
.present .board-side { flex: 1 1 auto; position: relative; display: flex; flex-direction: column; min-height: 0; }
/* Past the first step the joining code is hidden until the editor shows it (projector.js). */
.present.no-code > .qr-side { display: none; }
.present .board-side .canvas-body { flex: 1; }
/* A chat step's question, over the board before it that it keeps up (projector.js). */
.present-topic { font-size: clamp(1.1rem, 2.4vw, 2rem); font-weight: 700; line-height: 1.25; }
.preview-screen .present-topic { font-size: 30px; }
/* A text on the projector, or on a device in full screen, is read from the back of the room. */
:is(.present, .pane-canvas:fullscreen) .canvas-text { max-width: 46ch; margin: 0 auto; font-size: clamp(1.1rem, 2.1vw, 1.75rem); }
:is(.present, .pane-canvas:fullscreen) .canvas-text h2 { font-size: 1.6em; }
.preview-screen .present .canvas-text { font-size: 26px; }
/* A text too long for the screen runs in columns across it (canvas.js, fitText). */
:is(.present, .pane-canvas:fullscreen) .canvas-text.in-columns { max-width: none; column-width: 30ch; column-gap: 2.5em; }
:is(.present, .pane-canvas:fullscreen) .canvas-text.in-columns > h2 { column-span: all; }
:is(.present, .pane-canvas:fullscreen) .canvas-text.in-columns :is(li, p) { break-inside: avoid-column; }
:is(.present, .pane-canvas:fullscreen) .canvas-text.in-columns :is(h1, h2, h3, h4, strong:only-child) { break-after: avoid-column; }
/* A question, a step in rooms or a chat step, large, for the room to read. */
.present-big { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.25rem; padding: 2rem 3rem; text-align: center; }
.present-kicker { font-size: clamp(1rem, 2.2vw, 1.6rem); font-weight: 600; color: var(--text-dim); }
.present-question { font-size: clamp(1.6rem, 4.4vw, 3.6rem); font-weight: 700; line-height: 1.2; max-width: 28ch; }
.present-detail { font-size: clamp(1rem, 2.3vw, 1.8rem); color: var(--text-dim); max-width: 44ch; }
.present-page > .controls { position: fixed; left: .75rem; bottom: .75rem; opacity: .35; }
.present-page > .controls:hover { opacity: 1; }

.theme-toggle { font-size: 1.1rem; line-height: 1; text-decoration: none; color: var(--text-dim); }
/* What joining means, above the name box on the join screen (consent.js). */
.consent-points { text-align: left; font-size: .875rem; color: var(--text-dim); padding-left: 1.1rem; margin: .75rem 0 1rem; }
.consent-points li + li { margin-top: .35rem; }
.gear-button { display: inline-flex; align-items: center; gap: .3rem; padding: .3rem .6rem; border-radius: var(--r-pill); }
/* Every button that opens something in place names it in aria-controls, and
   while it is open the button is filled with the accent and its chevron turned
   over: the gear, the line under a step, Replay. Keyed on the attributes, so a
   new one needs no rule of its own, and Bootstrap's dropdowns, which carry no
   aria-controls, are left alone. */
button[aria-controls][aria-expanded="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
button[aria-controls] > .chev { display: inline-block; transition: transform .3s ease-in-out; }
button[aria-controls][aria-expanded="true"] > .chev { transform: rotate(180deg); }
/* Behind the gear in the top bar, above the running order: the title and what the session is for on the
   left, and on the right who is there, going live, simulated people, face to face, open or closed and the editors. */
/* They slide down from under the top bar over the page, which stays where it is, and scroll on their own when taller than the window. */
.settings-fold { position: fixed; top: calc(var(--topbar-h, 0px) + .5rem); left: 1rem; right: 1rem; z-index: 19;
  max-height: calc(100dvh - var(--topbar-h, 0px) - 1rem); overflow-y: auto; border-radius: var(--r);
  box-shadow: 0 12px 36px rgba(0, 0, 0, .22), 0 2px 8px rgba(0, 0, 0, .1);
  opacity: 0; visibility: hidden; transform: translateY(-1.5rem);
  transition: transform .3s ease-out, opacity .3s ease-out, visibility 0s linear .3s; }
.settings-fold.open { opacity: 1; visibility: visible; transform: none; transition: transform .3s ease-out, opacity .3s ease-out; }
@media (max-width: 767.98px) { .settings-fold { left: .5rem; right: .5rem; } }
/* The page dims behind it, under the top bar, so the gear that closes it stays in reach. */
.settings-backdrop { position: fixed; inset: 0; z-index: 18; background: rgba(0, 0, 0, .35);
  opacity: 0; visibility: hidden; transition: opacity .3s ease-out, visibility 0s linear .3s; }
.settings-backdrop.open { opacity: 1; visibility: visible; transition: opacity .3s ease-out; }
@media (prefers-reduced-motion: reduce) { .settings-fold, .settings-backdrop { transition: none; } }
/* The workshops list: a line opens its settings under it (listPage), the same body, set in the table without the panel's own frame. */
.session-line { cursor: pointer; }
.session-line:hover > td, .session-line.open > td { background: var(--surface-2); }
.session-line.open > td { border-bottom-color: transparent; }
/* The workshop the top bar is for (currentSessionId): tinted, with the accent down its left edge. */
.session-line.current > td { background: var(--accent-soft); }
.session-line.current:hover > td { background: color-mix(in srgb, var(--accent-soft) 60%, var(--surface-2)); }
.session-line.current > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.session-chevron { color: var(--text-dim); vertical-align: -.1em; }
.session-more > td { background: var(--surface-2); padding: 0 .75rem 1rem; }
.session-more .settings-more { background: var(--surface); grid-template-columns: minmax(0, 1fr); }
.session-more .settings-words { max-width: 44rem; }
.session-more .settings-switches { padding-top: 0; justify-content: start; }
.session-agenda { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; padding: .25rem 0 .6rem; }
.settings-head { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding-bottom: .5rem; border-bottom: 1px solid var(--border); }
.settings-more { display: grid; grid-template-columns: minmax(0, 44rem) auto; justify-content: start; align-items: start; gap: .75rem 2.5rem;
  padding: .75rem .85rem; background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r); }
.settings-words { display: flex; flex-direction: column; gap: .2rem; }
.settings-words label:not(:first-child) { margin-top: .4rem; }
.settings-words .session-about { resize: vertical; }
/* A hairline between the rows, each row its label, its control and what it does, in three columns, so each setting
   reads as its own; the words are centred on the control beside them. */
.settings-switches { display: grid; grid-template-columns: auto auto minmax(14rem, 24rem); padding-top: 1.1rem; }
.settings-label, .settings-value, .settings-note { padding: .5rem 0; border-top: 1px solid var(--border); }
.settings-label { display: flex; align-items: center; padding-right: .75rem; }
.settings-value, .settings-note { display: flex; flex-direction: column; justify-content: center; }
.settings-value { align-items: flex-start; padding-right: 1.25rem; }
.settings-switches > :nth-child(-n+3) { border-top: 0; padding-top: 0; }
.settings-switches .settings-note { font-size: .75rem; }
/* A label and its control, hidden together. */
.settings-pair { display: contents; }
.settings-editors { display: flex; flex-direction: column; gap: .35rem; width: 24rem; max-width: 100%; }
/* A switch and what it hands out with Copy (the replay's link, the password). */
.settings-stack { display: flex; flex-direction: column; align-items: flex-start; gap: .35rem; }
.settings-stack .copy-field { width: 24rem; max-width: 100%; margin: 0; }
@media (max-width: 991.98px) { .settings-more { grid-template-columns: minmax(0, 1fr); } .settings-switches { padding-top: 0; justify-content: start; } }
/* On a phone the words go under the control, in its column. */
@media (max-width: 767.98px) {
  .settings-switches { grid-template-columns: auto minmax(0, 1fr); }
  .settings-value { padding-right: 0; }
  .settings-note { grid-column: 2; border-top: 0; padding-top: 0; }
  .settings-note:empty, .settings-value:empty { display: none; }
}
.run-head { position: sticky; top: var(--topbar-h, 0px); z-index: 10; background: var(--bg); padding: .4rem 0; }
.step-list { border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
.step-row { padding: .4rem .6rem; border-top: 1px solid var(--border); cursor: pointer; }
.step-row:first-child { border-top: 0; }
.step-row .step-sheet { cursor: auto; }
.step-row:not(.now):not(.selected):not(.replayed):hover { background: var(--surface-2); }
.step-row.now { background: var(--accent-soft); }
.step-row.selected { box-shadow: inset 4px 0 0 var(--accent); }
.step-row.selected:not(.now) { background: var(--surface-2); }
.step-meta { display: block; font-size: .8rem; color: var(--text-dim); }
.step-row.drop-above { box-shadow: inset 0 3px 0 var(--accent); }
.step-row.drop-below { box-shadow: inset 0 -3px 0 var(--accent); }
.step-grip { cursor: grab; color: var(--text-faint); user-select: none; font-size: 1.1rem; line-height: 1; margin-right: -.2rem; }
.step-grip:hover { color: var(--text); }
/* On a narrow screen the step's picture gives its width to the title, which is written in place when the step is picked. */
@media (max-width: 575.98px) { .step-line .pic { display: none; } }
/* The same when the running order's column is dragged narrow: first the line under the title goes (it is the title's
   tooltip, and the step's settings say it all when picked), then the picture. */
.running-order { container-type: inline-size; }
@container (max-width: 30rem) { .step-line .step-meta { display: none; } }
@container (max-width: 24rem) { .step-line .pic { display: none; } }
@media (pointer: coarse) { .step-grip { display: none; } }
.step-line { display: flex; align-items: center; gap: .5rem; }
.step-title-cell { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; }
.step-name { font-weight: 600; text-align: left; vertical-align: baseline; max-width: 100%; min-width: 0; }
/* The pill at the right of a step's line (manage.js): Showing filled in the accent on the step in front of everyone,
   Show outlined in it on the rest, both the same size so the column keeps its place. */
.step-pill { flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: 5.2rem; min-height: 0; padding: .2rem .8rem;
  border: 1.5px solid var(--accent); border-radius: 50rem; font-size: .8rem; font-weight: 600; line-height: 1.2; white-space: nowrap; }
.step-show.step-pill { color: var(--accent); background: transparent; }
.step-show.step-pill:hover, .step-show.step-pill:focus-visible { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.step-show.step-pill:disabled { border-color: var(--border-strong); color: var(--text-dim); }
.step-showing { color: var(--accent-ink); background: var(--accent); }
.step-showing::before { content: ''; width: .45rem; height: .45rem; margin-right: .4rem; border-radius: 50%; background: currentColor; }
.step-name.btn-link { color: var(--text); text-decoration: none; }
.step-name.btn-link:hover { color: var(--accent); text-decoration: underline; }
.now-badge { white-space: nowrap; margin-left: .5rem; font-size: .75rem; font-weight: 600; color: var(--accent); }
.step-more { line-height: 1; padding: .2rem .5rem; }
.step-num { width: 1.6rem; height: 1.6rem; border-radius: 50%; display: inline-grid; place-items: center; font-weight: 700; font-size: .8rem; background: var(--surface-2); color: var(--text-dim); flex: 0 0 auto; }
.step-row.now .step-num { background: var(--accent); color: var(--accent-ink); }
/* The step a replay is on, apart from the step showing live. */
.replay-badge { color: var(--gold); }
.step-row.replayed { background: var(--gold-fill); box-shadow: inset 4px 0 0 var(--gold); }
.step-row.replayed .step-num { background: var(--gold); color: var(--surface); }
/* The picked step: its title written in place, and under it, lined up with the title, a panel of all its settings. The step showing has a button above that, which opens its rooms. */
.step-title-input { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); padding: .05rem .35rem; margin-left: -.36rem; }
.step-title-input:focus { border-color: var(--accent); outline: 0; }
/* Under the line of the step showing: where it shows, and the rooms opened under it. */
.step-place { margin: .2rem 0 .1rem 6.75rem; display: flex; flex-wrap: wrap; align-items: flex-end; column-gap: .5rem; }
.step-place > .step-sheet { flex: 1 1 100%; }
.step-place-toggle { display: inline-flex; align-items: baseline; gap: .4rem; border: 1px solid var(--border-strong); border-radius: var(--r-sm); background: var(--surface);
  padding: .1rem .6rem; font-size: .8rem; color: var(--text); text-align: left; }
.step-place-toggle:not([aria-expanded="true"]):hover { background: var(--surface-2); }
/* Open, the button is the tab of its panel: the panel's ground, and no line between them. */
.step-place button.step-place-toggle[aria-expanded="true"] { background: var(--surface); color: var(--text); border-color: var(--border-strong); border-bottom-color: var(--surface);
  border-radius: var(--r-sm) var(--r-sm) 0 0; position: relative; z-index: 1; margin-bottom: -1px; padding-bottom: .3rem; }
.step-sheet { border: 1px solid var(--border-strong); border-radius: var(--r-sm); background: var(--surface); padding: .5rem .7rem .6rem; }
.step-place-toggle ~ .step-sheet { border-top-left-radius: 0; }
.step-section + .step-section { border-top: 1px solid var(--border); margin-top: .65rem; padding-top: .5rem; }
.step-section-title { font-size: .7rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-faint); margin: 0 0 .35rem; }
/* The menu beside Send that fills a rehearsal's step with simulated people. */
.fill-menu { min-width: 15rem; }
.fill-note { font-size: .75rem; color: var(--text-dim); white-space: normal; }
.step-opts { display: grid; grid-template-columns: max-content minmax(0, 1fr); align-items: center; gap: .3rem .6rem; }
/* The chat's row, taken from the step's own form, laid out as one of these. */
.step-opts > .setting { display: contents; }
.step-opts > .setting > .form-label { margin: 0; font-size: .8rem; color: var(--text-dim); }
.step-opts > .setting > .btn-group { justify-self: start; }
.step-opt { display: contents; }
.step-opt-label { font-size: .8rem; color: var(--text-dim); }
.step-opt-ctl { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; min-width: 0; }
.step-opts .btn-group-sm > .btn { padding: .1rem .5rem; font-size: .8rem; }
.step-opts .form-select-sm { width: auto; max-width: 100%; padding-top: .1rem; padding-bottom: .1rem; font-size: .8rem; }
@media (pointer: coarse) { .step-place { margin-left: 5.55rem; } }
/* The one form for a step's settings (settings-form.js); compact under a step's line. */
.settings-form .setting + .setting { margin-top: 1rem; }
.settings-form.compact .setting + .setting { margin-top: .55rem; }
.settings-form.compact .form-label, .settings-form.compact .form-check-label { font-size: .8rem; color: var(--text-dim); margin-bottom: .15rem; }
.settings-form.compact .form-control, .settings-form.compact .form-select { font-size: .875rem; }
.settings-form.compact .form-text { font-size: .75rem; margin-top: .15rem; }
.settings-form .setting-number { width: 6rem; }
.steps-picker .steps-chips { margin: 0 0 .35rem; }
.steps-picker .chip { cursor: default; }
.inline-name { border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--text); padding: 0 .3rem; min-width: 0; width: 10rem; }
.inline-name:hover { border-color: var(--border); }
.inline-name:focus { border-color: var(--accent); outline: 0; background: var(--surface); }
.min-w-0 { min-width: 0; }

/* Every group's results side by side. */
.compare-grid { position: absolute; inset: 0; overflow: auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); grid-auto-rows: minmax(300px, 1fr); gap: .6rem; padding: .6rem; }
.compare-cell { display: flex; flex-direction: column; min-height: 0; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; background: var(--surface); }
.compare-head { padding: .35rem .6rem; font-weight: 600; font-size: .9rem; border-bottom: 1px solid var(--border); background: var(--surface-2); }
.compare-body { position: relative; flex: 1 1 auto; min-height: 0; }

/* ------------------------------------------------------------ help (help.js) */
.help-page { max-width: 62rem; margin: 0 auto; padding-bottom: 3rem; }
.help-lead { font-size: 1.05rem; max-width: 46rem; }
.help-section { margin: 2rem 0 0; }
.help-section > h2 { margin-bottom: .75rem; }
.help-note { color: var(--text-dim); font-size: .9rem; margin: .75rem 0 0; max-width: 46rem; }
.help-list { margin: 0; padding-left: 1.2rem; max-width: 46rem; }
.help-list li { margin-bottom: .35rem; }
.help-pic { display: block; color: var(--text-dim); }
.help-pic svg { display: block; }
.help-pic .room { fill: none; stroke: var(--border-strong); stroke-width: 1.4; stroke-dasharray: 3 2; }
.help-pic .faint { opacity: .45; }
/* The kinds of step, as the Add a step menu draws them. */
.help-kinds { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: .5rem; }
.help-kind { display: flex; gap: .6rem; align-items: flex-start; padding: .5rem .6rem; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); }
/* Two ways of doing a thing, side by side, each with its picture. */
.help-pair { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
@media (max-width: 575.98px) { .help-pair { grid-template-columns: 1fr; } }
.help-panel { display: flex; gap: .8rem; align-items: flex-start; margin: 0; padding: .8rem; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
.help-panel .help-pic { flex: 0 0 auto; width: 120px; height: 72px; }
.help-says { margin-top: .35rem; font-size: .85rem; color: var(--text-dim); }
/* How a session is made and run, top to bottom: the ways to make steps, joined into the session they make, then
   what hosts, participants and Qualia each do while it runs. On a narrow screen each row is one column, and the
   line joining the ways is left out. */
.help-flow { display: grid; }
.help-flow-head { font-weight: 600; margin-bottom: .45rem; }
.help-flow-ways { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .5rem; }
.help-flow-way { display: flex; gap: .6rem; align-items: center; padding: .55rem .65rem; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); line-height: 1.3; }
.help-flow-join { display: block; height: 16px; }
.help-flow-join svg { display: block; }
.help-flow-arrow { display: block; justify-self: center; width: 24px; height: 24px; margin-bottom: .2rem; transform: rotate(90deg); }
:is(.help-flow-join, .help-flow-arrow) .ln { stroke: var(--accent); stroke-width: 2; }
.help-flow-box { padding: .75rem .85rem; border: 1px solid var(--border-strong); border-radius: var(--r); background: var(--surface); }
.help-flow-label { font-size: .8rem; font-weight: 600; color: var(--text-dim); margin-bottom: .3rem; }
.help-flow-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .4rem; }
.help-flow-step { display: flex; flex-direction: column; gap: .3rem; padding: .45rem .5rem; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface-2); line-height: 1.25; }
.help-flow-step-top { display: flex; align-items: center; gap: .4rem; }
.help-flow-step .pic { width: 40px; height: 30px; }
.help-flow-n { font-size: .8rem; color: var(--text-dim); }
.help-flow-people { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
.help-flow-people .help-list { font-size: .9rem; }
.help-flow-people .help-list li { margin-bottom: .1rem; }
.help-flow-who { display: block; margin-top: .4rem; font-size: .78rem; font-weight: 600; color: var(--voice-ai); }
/* What a word means, under the thing it names. */
.help-term { margin: 0 0 .45rem; font-size: .85rem; color: var(--text-dim); }
/* Where a self-paced session differs. */
.help-paced { margin: .5rem 0 0; padding-left: .55rem; border-left: 3px solid var(--gold); font-size: .85rem; color: var(--text-dim); max-width: 46rem; }
/* The choices that shape a session, each its two answers side by side. */
.help-choice + .help-choice { margin-top: 1rem; }
.help-choice > h4 { margin-bottom: .45rem; }
.help-choice-where { display: block; margin-top: .1rem; font-size: .8rem; font-weight: 400; color: var(--text-dim); }
/* A heading inside a section of Help, above the choices or a list. */
.help-sub { font-size: 1rem; font-weight: 700; margin: 1.75rem 0 .5rem; }
/* The detail, folded under its heading. */
.help-more { border-top: 1px solid var(--border); padding: .5rem 0; }
.help-more:last-child { border-bottom: 1px solid var(--border); }
.help-more > summary { cursor: pointer; font-weight: 600; }
.help-more[open] > summary { margin-bottom: .45rem; }
/* The reference: each part of a screen by its name, and what it does. */
.help-ref { margin: .75rem 0 0; max-width: 46rem; }
.help-ref dt { font-weight: 600; font-size: .9rem; }
.help-ref dd { margin: 0 0 .6rem; font-size: .9rem; }
.help-more > .help-note:first-of-type { margin-top: 0; }
@media (max-width: 991.98px) { .help-flow-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 767.98px) {
  .help-flow-ways { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .help-flow-join { display: none; }
  .help-flow-people, .help-flow-steps { grid-template-columns: minmax(0, 1fr); }
  .help-flow-step { flex-direction: row; align-items: center; }
}
@media (max-width: 575.98px) { .help-flow-ways { grid-template-columns: minmax(0, 1fr); } }

/* ------------------------------------------------------------ the tour (tour.js) */
.tour-offer { position: fixed; right: 1rem; bottom: 1rem; z-index: 1060; max-width: 20rem; padding: .75rem .9rem; border: 1px solid var(--border-strong);
  border-radius: var(--r); background: var(--surface); color: var(--text); box-shadow: var(--shadow); }
.tour-offer-row { display: flex; align-items: center; gap: .25rem; margin-top: .5rem; }
.driver-popover.qs-tour { background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); border-radius: var(--r); font-family: inherit; max-width: 22rem; }
.driver-popover.qs-tour .driver-popover-title { font-family: inherit; font-size: 1rem; }
.driver-popover.qs-tour .driver-popover-description { color: var(--text); }
.driver-popover.qs-tour .driver-popover-progress-text { color: var(--text-dim); }
.driver-popover.qs-tour .driver-popover-arrow-side-left { border-left-color: var(--surface); }
.driver-popover.qs-tour .driver-popover-arrow-side-right { border-right-color: var(--surface); }
.driver-popover.qs-tour .driver-popover-arrow-side-top { border-top-color: var(--surface); }
.driver-popover.qs-tour .driver-popover-arrow-side-bottom { border-bottom-color: var(--surface); }
.driver-popover.qs-tour .driver-popover-footer button { text-shadow: none; font: inherit; font-size: .85rem; border-radius: var(--r-sm); padding: .25rem .6rem;
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border-strong); }
.driver-popover.qs-tour .driver-popover-footer .driver-popover-next-btn { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.driver-popover.qs-tour .driver-popover-close-btn { color: var(--text-dim); }

/* ------------------------------------------------------------ share menu */
/* The QR carries its own white ground and quiet zone (qr.js), which a scanner needs in either theme. */
.share-menu { width: 20rem; max-width: calc(100vw - 1rem); padding: 1rem; text-align: center; }
.share-qr { min-height: 240px; }
.share-qr svg { display: block; width: 240px; max-width: 100%; height: auto; margin: 0 auto; border-radius: var(--r-sm); }
.share-code { margin-top: .6rem; font-size: 2.4rem; font-weight: 700; line-height: 1.1; letter-spacing: .12em; color: var(--text); }
.share-how { margin-bottom: .6rem; }
.share-link { display: flex; align-items: center; gap: .5rem; margin-bottom: .6rem; text-align: left; }
.share-url { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; color: var(--text-dim); }
.share-section { margin-top: .75rem; text-align: left; }
.share-section .dropdown-divider { margin: 0 0 .6rem; }
.share-section-head { margin: 0 0 .25rem; font-size: .8rem; color: var(--text-dim); }
.share-section-link { margin-bottom: .4rem; }
/* Share stays on the first row of the narrow two-row bar, beside Sessions and ?. */
@media (max-width: 767.98px) {
  :is(.manage-page, .home-page) .editor-tabs > [data-tab="share"] { order: 2; }
}

/* The footer of Home and Help (footer.js). */
.site-foot { margin-top: 3rem; padding: 1.25rem 0 2.5rem; border-top: 1px solid var(--border); font-size: .85rem; color: var(--text-dim); }
.site-foot p { margin: .4rem 0 0; }
.site-foot a { color: inherit; text-underline-offset: 2px; }
.site-foot a:hover { color: var(--text); }
.site-foot-links { display: flex; flex-wrap: wrap; gap: .3rem 1.25rem; font-weight: 600; }
.site-foot-legal { font-size: .78rem; }

/* Help's quick start, one line above everything. */
.help-quick { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem 1rem; margin: 0 0 1.25rem; padding: .6rem 1rem;
  border-radius: var(--r); border-left: 4px solid var(--accent); background: var(--accent-soft); color: var(--text); }
.help-quick a { font-weight: 600; }
.help-quick-steps { display: flex; flex-wrap: wrap; gap: .35rem 1.1rem; margin: 0; padding: 0; list-style: none; counter-reset: quick; font-size: .95rem; }
.help-quick-steps li { counter-increment: quick; }
.help-quick-steps li::before { content: counter(quick); display: inline-grid; place-items: center; width: 1.25rem; height: 1.25rem; margin-right: .35rem;
  border-radius: 50%; background: var(--accent); color: var(--surface); font-size: .75rem; font-weight: 700; }
.help-quick-steps svg { vertical-align: -.12em; }

/* The waiter (waiter.js): shown only once a screen or a tour has taken longer than a moment, so a quick switch does
   not flicker; the screen being left dims with it. */
.route-waiter { display: none; position: fixed; top: calc(var(--topbar-h, 3.5rem) + .75rem); left: 50%; transform: translateX(-50%);
  z-index: 1090; align-items: center; gap: .5rem; padding: .35rem .9rem; border-radius: var(--r-pill);
  background: var(--surface); border: 1px solid var(--border-strong); box-shadow: var(--shadow); font-size: .875rem; }
body.waiting .route-waiter { display: flex; animation: waiter-in .15s ease .25s both; }
@keyframes waiter-in { from { opacity: 0; } to { opacity: 1; } }
#root { transition: opacity .15s; }
body.waiting #root { opacity: .5; transition-delay: .25s; }
