/* Lifted shell slices from demo styles.css. Tenant tokens via CSS variables. */
/* Demo styles.css L1688: the gate legal bar is suppressed on desktop. */
.toggle-legal-bar { display: none !important; }

:root {

  --accent: #31557a;

  --accent-dark: #24415e;

  --page: #f7f8fa;

  --plate-blue: #31557b;

}

/* 1. Tokens ---------------------------------------------------- */
:root {
  --aios-blue: var(--accent);
  /* 6.B split-toggle config (reference): AiOS-half background = brand blue, white CTA. */
  --aios-half-bg: var(--aios-blue);
  --aios-toggle-cta: #ffffff;
  --aios-blue-dark: var(--accent-dark);
  --aios-blue-light: var(--accent);
  --aios-blue-bg: color-mix(in srgb, var(--aios-blue) 4%, transparent);
  --aios-blue-tint: color-mix(in srgb, var(--aios-blue) 8%, transparent);
  --aios-blue-border: color-mix(in srgb, var(--aios-blue) 18%, transparent);
  --ac: var(--accent);
  --sub: var(--muted);
  --r-chip: 999px;
  --ink: #1A1A1A;
  --ink-soft: #3F4451;
  --muted: #6B7280;
  --muted-light: #9CA3AF;
  --line: #E5E7EB;
  --line-soft: #F1F3F5;
  --bg-tint: #F8F9FB;
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 4px 14px rgba(15, 23, 42, 0.06);
  --shadow-lg: 0 18px 48px rgba(15, 23, 42, 0.12);
  --shadow-blue: 0 12px 32px color-mix(in srgb, var(--aios-blue) 18%, transparent);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;
  --ease: cubic-bezier(.2,.65,.25,1);
  --nav-height: clamp(58px, 5.2vw, 72px);
  --footer-height: 290px;
  /* P1-2: one content boundary governs everything. The answer canvas, the
     composer, and the follow-up prompt row all resolve to this single column
     width and share the same side gutter, so every layer aligns to one
     invisible column (the Claude pattern). Change it here, it moves everywhere. */
  --content-max: 1120px;
  --content-gut: clamp(16px, 3vw, 40px);
  /* The padded outer box: content is flush to --content-max on wide screens, and
     the gutter only bites once the viewport is narrower than the column. Every
     boundary wrapper (answer canvas, composer, follow-up row) uses this max-width
     with --content-gut side padding, so all three resolve to one identical column. */
  --content-box: calc(var(--content-max) + 2 * var(--content-gut));
  /* Universal UI scale — set by JS (applyGlobalScale) from the viewport so the
     whole experience scales as one proportional unit on any screen. */
  --app-zoom: 1;
}

/* One global zoom drives the entire app: navbar, chat, dock, orb, persona,
   chips, footer — everything shrinks/grows together and stays proportional.
   Viewport-height elements below divide by --app-zoom to still fill the screen. */
body { zoom: var(--app-zoom); }

/* 2. Reset + base ---------------------------------------------- */
* { box-sizing: border-box; }
html { font-size: clamp(14px, 0.55vw + 11.5px, 17px); -webkit-font-smoothing: antialiased; }
html, body { margin: 0; padding: 0; }
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  color: var(--ink);
  background: var(--bg-tint);
  font-feature-settings: 'cv11', 'ss01';
  font-size: 1rem;
  line-height: 1.5;
}
button, input, textarea, select { font-family: inherit; }
.hidden { display: none !important; }
.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; }

/* 3. Navbar (LEGACY — kept for tenant shells not yet converged) ------- */
/* The shared/reference shell retires the visible navbar (a hidden data-nav-manifest
   for plate.js) and uses .aios-topbar below. Tenant shells that still ship their
   own navbar keep these styles until they migrate. */
.navbar[data-nav-manifest] { display: none !important; }
.navbar {
  background: var(--aios-blue);
  color: white;
  padding: clamp(10px, 1.1vw, 16px) clamp(20px, 2.4vw, 40px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 50;
  min-height: var(--nav-height);
  letter-spacing: 0.045em;
  gap: clamp(12px, 1.5vw, 24px);
}
.navbar-logo { height: clamp(28px, 2.4vw, 36px); width: auto; cursor: pointer; display: block; flex-shrink: 0; }
.navbar-logo svg, .navbar-logo img { height: 100%; width: auto; display: block; }
.navbar-left, .navbar-right { display: flex; align-items: center; gap: clamp(14px, 1.7vw, 28px); }
.navbar-left { flex: 1; min-width: 0; }
.navbar-link {
  font-size: clamp(11px, 0.78vw, 13px); font-weight: 700; cursor: pointer;
  transition: opacity 0.15s var(--ease); text-transform: uppercase; color: white;
  white-space: nowrap; background: none; border: none; padding: 4px 2px; letter-spacing: inherit;
}
.navbar-link:hover { opacity: 0.72; }
.navbar-hamburger {
  background: none; border: none; cursor: pointer; padding: 6px; margin-left: 6px;
  line-height: 0; color: white; border-radius: var(--radius-sm); transition: background 0.15s var(--ease);
}
.navbar-hamburger:hover { background: rgba(255,255,255,0.1); }
@media (max-width: 1365px) {
  .navbar-link.secondary { display: none; }
  .navbar-hamburger.always-visible { display: inline-flex !important; }
}

/* 3b. AiOS topbar (the new standard chrome) ---------------------------- */
/* Minimal, in-flow (sticky), SAME colour as the canvas so there is no navy band
   and the canvas opens up. Logo top-left aligned to the answer column, controls
   top-right recoloured for the light ground. Shown only inside AiOS (the gateway
   is a full-screen modal above it). Keeps --nav-height so the canvas calc holds. */
.aios-topbar {
  position: sticky; top: 0; z-index: 60;
  min-height: var(--nav-height);
  background: var(--bg-tint);
  display: flex; align-items: center; justify-content: space-between;
  /* Logo pushed to the top-left corner, controls to the top-right corner — close
     to the edges but with a little breathing room (not flush to the walls). */
  padding-inline: clamp(20px, 2.2vw, 44px);
  gap: 12px;
}
body:not(.aios-active) .aios-topbar { display: none; }
/* The brand slot can be capped from script when an open record puts a breadcrumb
   across the bar (trail.js measure(), and the note there explains why the mark
   gives way rather than the trail). A cap only helps if the mark obeys it, so the
   slot clips and the mark carries a max-width at EVERY width, not just on the
   phone. The inline width fitBrandLogo writes stays the specified width and is
   merely clamped, so a wordmark whose SVG has a viewBox and no intrinsic size
   still has something definite to resolve against; object-fit keeps a clamped
   mark undistorted rather than squashed. Uncapped, this changes nothing. */
.aios-topbar-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
.aios-topbar-brand { display: flex; align-items: center; min-width: 0; overflow: hidden; }
.aios-topbar .navbar-logo { height: clamp(22px, 2.1vw, 32px); min-width: 0; max-width: 100%; }
/* !important because fitBrandLogo() writes max-width:none INLINE on the mark
   (init.js), which a plain stylesheet rule cannot outrank. Without this the slot
   caps correctly and the mark simply overflows it: measured 116.3px slot against
   a 185.6px mark on Kylemore at 1440. */
.aios-topbar .navbar-logo img,
.aios-topbar .navbar-logo svg { max-width: 100% !important; object-fit: contain; }
.aios-topbar-controls { display: flex; align-items: center; gap: 12px; }
/* Hamburger recoloured dark for the light topbar (legacy navy navbars keep white). */
.aios-topbar .navbar-hamburger {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-soft, #3F4451); margin-left: 0;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.aios-topbar .navbar-hamburger:hover { background: var(--aios-blue-bg); color: var(--aios-blue); }
.trailslot { display: flex; align-items: center; pointer-events: auto; }
.trailslot.empty { display: none; }
.trailslot .trailrow {
  display: flex;
  align-items: center;
}
.aios-trail {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  max-width: 22.5rem;
  overflow: hidden;
  pointer-events: auto;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--aios-blue);
  border: 1px solid var(--line, #E5E7EB);
  background: #fff;
  border-radius: 999px;
  padding: 5px 11px;
  white-space: nowrap;
  margin: 0;
  box-sizing: border-box;
}
.aios-trail-steps {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  min-width: 0;
}
.tnode.t-home {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  pointer-events: auto;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  color: var(--aios-blue);
}
.tnode.t-home svg { display: block; width: 11px; height: 11px; }
.aios-trail-step {
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  color: var(--aios-blue);
  font: inherit;
  letter-spacing: inherit;
  white-space: nowrap;
}
.aios-trail-step:first-child { margin-left: 8px; }
.aios-trail-chevron,
.aios-trail-ellipsis {
  display: inline-flex;
  align-items: center;
  margin: 0 6px;
  color: var(--aios-blue);
  font: inherit;
  pointer-events: none;
}

/* 4. Toggle screen --------------------------------------------- */
.toggle-screen {
  /* Vertical footprint kept tight so the whole splash (headline through the
     Privacy/Terms/Accessibility bar) fits on a laptop viewport without the legal
     line clipping at the fold. Top padding and the subhead gap are the whitespace
     levers; card geometry is untouched. */
  /* NI-3 (2026-07-14): more top breathing room below the navbar before the headline. */
  padding: clamp(44px, 4.5vw, 68px) 20px 36px;
  max-width: 1100px;
  margin: 0 auto;
  text-align: center;
}
/* P1-5: headline sits at the choice-box visual weight (not a towering hero), so
   the choice cards lead; the supporting line is one size larger than before. */
.toggle-headline {
  font-size: clamp(24px, 2.6vw, 34px);
  font-weight: 700;
  color: var(--aios-blue);
  margin: 0 0 12px;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.toggle-subhead {
  font-size: clamp(16px, 1.4vw, 20px);
  font-weight: 500;
  color: var(--ink-soft);
  margin-bottom: clamp(22px, 2.6vw, 36px);
}
.toggle-cards {
  display: flex;
  gap: clamp(20px, 2.4vw, 40px);
  justify-content: center;
  flex-wrap: wrap;
}
.toggle-card {
  background: var(--aios-blue);
  color: white;
  padding: clamp(32px, 3vw, 48px) clamp(28px, 2.6vw, 40px);
  border-radius: var(--radius-md);
  width: 380px;
  min-height: 330px;
  text-align: center;
  display: flex;
  flex-direction: column;
  position: relative;
  box-shadow: var(--shadow-blue);
}
.toggle-card-title {
  font-size: clamp(22px, 1.9vw, 26px);
  font-weight: 800;
  margin-bottom: 18px;
  letter-spacing: 0.01em;
  line-height: 1.2;
  text-transform: uppercase;
}
.toggle-card-body {
  font-size: clamp(13px, 0.95vw, 15px);
  line-height: 1.55;
  margin-bottom: 22px;
  color: rgba(255,255,255,0.92);
}
.toggle-language-picker {
  position: relative;
  margin-top: auto;       /* push the picker + Choose button to the bottom together */
  margin-bottom: 14px;
  display: flex;
  justify-content: center;
}
.toggle-language-button {
  width: auto;
  max-width: 100%;
  background: white;
  color: var(--aios-blue);
  padding: 12px 18px;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: 13px;
  border: none;
  cursor: pointer;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  transition: background 0.15s var(--ease);
  white-space: nowrap;
}
.toggle-language-button > span:first-child {
  overflow: visible;
  white-space: nowrap;
}
.toggle-language-button:hover { background: #F5F7FB; }
.toggle-language-button svg { transition: transform 0.2s var(--ease); }
.toggle-language-button.open svg { transform: rotate(180deg); }
.lang-dropdown {
  /* Amendment 9 D.6 (owner-authorized opening exemption): the menu opens
     DOWNWARD below its trigger and never clips. Fixed positioning (set per
     open in nav.js from the trigger's rect) escapes the locked toggle
     card's overflow:hidden, and the max-height is computed from the space
     below the trigger, so every item is fully visible with internal scroll
     only when the list exceeds that space. */
  position: fixed;
  min-width: 240px;
  max-width: 300px;
  background: white;
  border: 1px solid var(--line, #E5E7EB);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  max-height: 280px;
  overflow-y: auto;
  z-index: 2000;
  padding: 6px;
  text-align: left;
}
.lang-dropdown-item {
  padding: 10px 14px;
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
  border-radius: var(--radius-sm);
  font-weight: 500;
  transition: background 0.1s;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: transparent;
  border: none;
  width: 100%;
  font-family: inherit;
  text-align: left;
}
.lang-dropdown-item:hover { background: var(--aios-blue-bg); color: var(--aios-blue); }
.lang-dropdown-item.active { background: var(--aios-blue-tint); color: var(--aios-blue); font-weight: 700; }
.lang-dropdown-item.active::after { content: '✓'; color: var(--aios-blue); }
#toggleScreen #gateLanguage {
  pointer-events: none;
}
/* 2.4: no filled buttons on the toggle cards. On the dark-filled reference cards the
   button is transparent with a white outline and white text (the card's contrast). */
.toggle-card-button {
  background: transparent;
  color: #fff;
  padding: 14px 28px;
  border-radius: var(--radius-sm);
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.04em;
  border: 1.5px solid #fff;
  cursor: pointer;
  margin-top: 24px;
  transition: transform 0.1s var(--ease), background 0.15s var(--ease);
}
.toggle-card-button:hover { background: rgba(255,255,255,0.12); }
.toggle-card-button:active { transform: translateY(1px); }
.toggle-dontask {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--ink-soft);
  margin-top: 40px;
  cursor: pointer;
  user-select: none;
}
.toggle-dontask-circle {
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--muted);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.15s, background 0.15s;
}
.toggle-dontask.checked .toggle-dontask-circle {
  background: var(--aios-blue);
  border-color: var(--aios-blue);
}
.toggle-dontask.checked .toggle-dontask-circle::after {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: white;
}
.toggle-poweredby {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 28px;
  letter-spacing: 0.02em;
}

/* 5. AiOS canvas shell ----------------------------------------- */
.aios-canvas {
  display: flex;
  flex-direction: column;
  /* Viewport-locked: the AiOS experience is exactly the viewport tall. 100dvh
     tracks the small/large viewport so mobile browser bars never crop the dock;
     the 100vh line is the fallback for engines without dvh. */
  height: calc(100vh / var(--app-zoom) - var(--nav-height));
  height: calc(100dvh / var(--app-zoom) - var(--nav-height));
  background: var(--bg-tint);
}
.chat-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-behavior: smooth;
  /* The conversation feed is the ONLY scroll container in AiOS mode; contain its
     scroll so it never chains into the page or the footer sheet. */
  overscroll-behavior: contain;
}

/* The rest of the scroll model (page-scroll lock, the site-footer slide-up sheet,
   and the footer toggle) is injected at runtime by engine/app/plate.js, because
   the Gallea and Tompkins shells do NOT load this core stylesheet; plate.js runs on
   every tenant, so that is the one place the app-shell scroll model reaches all
   three. Keep it there, not here. */
.aios-dock {
  flex-shrink: 0;
  background: var(--bg-tint);
  padding: 14px 0 10px;
  border-top: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
/* P1-2: dock rows resolve to the same boundary + gutter as the answer canvas so
   the composer and follow-up prompts line up with the answer content above. */
.aios-dock .input-bar-wrap,
.aios-dock .chips-row,
.aios-dock .composer-meta,
.aios-dock .powered-by-gallea {
  width: 100%;
  max-width: var(--content-box);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--content-gut);
  padding-right: var(--content-gut);
  box-sizing: border-box;
}
.aios-dock .orb-wrapper { margin: 2px 0 0; }

/* P1-2: the answer canvas resolves to the shared content boundary (--content-max)
   with the shared side gutter (--content-gut), so answer content aligns edge for
   edge with the composer and the follow-up prompt row below it. box-sizing keeps
   the gutter inside the column, so both layers share identical outer + inner width. */
.aios-container {
  max-width: var(--content-box);
  margin: 0 auto;
  width: 100%;
  padding: 26px var(--content-gut) 8px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  min-height: 100%;
}
/* In welcome state (no messages yet) center so the starting boxes fill the screen.
   The inner #welcomeFit is scaled by JS (fitWelcomeScreen) so the whole welcome
   block always fits the available height — no clipping behind the dock on laptops. */
.aios-canvas:not(.has-messages) .chat-scroll { overflow: hidden; }
.aios-canvas:not(.has-messages) .aios-container {
  justify-content: center;
  align-items: center;
  height: 100%;
  min-height: 0;
  padding-top: clamp(16px, 2vh, 32px);
  padding-bottom: clamp(16px, 2vh, 32px);
}
/* #welcomeFit holds the headline + orb + starting cards as one block that
   JS scales down on shorter screens. align-items lets it size to content. */
#welcomeFit {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform-origin: center center;
  will-change: transform;
}
.aios-welcome {
  text-align: center;
  color: var(--aios-blue);
  /* Opening-screen headline size taken directly from the Gallea Ai demo
     (.discovery-welcome: 30px / line-height 1.28 / max-width 820px). */
  font-size: 30px;
  font-weight: 700;
  line-height: 1.28;
  max-width: 820px;
  margin: 0 auto clamp(16px, 2.2vh, 26px);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* 6. Chat messages --------------------------------------------- */
.chat-messages {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 28px;
  min-height: 60px;
}
.aios-canvas:not(.has-messages) .chat-messages { min-height: 0; margin-bottom: 0; }
.msg-user {
  align-self: flex-end;
  background: var(--aios-blue-tint);
  color: var(--ink);
  padding: 13px 18px;
  border-radius: 16px 16px 4px 16px;
  max-width: 72%;
  font-size: 15.5px;
  line-height: 1.5;
}
.msg-user-time {
  align-self: flex-end;
  font-size: 11px;
  color: var(--muted-light);
  margin-top: -8px;
  padding-right: 6px;
}
.msg-aios {
  align-self: flex-start;
  background: white;
  border: 1px solid var(--line-soft);
  color: var(--ink);
  padding: 16px 20px;
  border-radius: 16px 16px 16px 4px;
  /* Answer canvas spans the full shared content column, flush with the composer
     field (the old 76% cap read narrow and cramped). Reading size 16px. */
  max-width: 100%;
  width: 100%;
  box-sizing: border-box;
  font-size: 16px;
  line-height: 1.65;
  box-shadow: var(--shadow-sm);
}
.msg-aios p { margin: 0 0 8px; }
.msg-aios p:last-child { margin-bottom: 0; }
.msg-aios ul, .msg-aios ol { margin: 6px 0 10px; padding-left: 20px; }
.msg-aios li { margin-bottom: 5px; }
.msg-aios li::marker { color: var(--aios-blue); }
.msg-aios strong { color: var(--aios-blue); font-weight: 700; }
.msg-aios em { font-style: italic; }
.msg-aios .msg-h {
  font-size: 13px;
  font-weight: 800;
  color: var(--aios-blue);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 14px 0 6px;
}
.msg-aios > .msg-h:first-child { margin-top: 0; }
.msg-aios h5.msg-h { text-transform: none; letter-spacing: 0; font-size: 14px; }

/* Streaming caret retired with the token-streaming presentation (Amendment 9,
   Rule 2.1): answers render complete, so nothing trails the text. */

.typing-indicator {
  align-self: flex-start;
  display: flex;
  gap: 5px;
  padding: 16px 20px;
  background: white;
  border: 1px solid var(--line-soft);
  border-radius: 16px 16px 16px 4px;
  align-items: center;
  box-shadow: var(--shadow-sm);
}
.typing-indicator span {
  width: 7px;
  height: 7px;
  background: var(--aios-blue);
  border-radius: 50%;
  animation: typingBounce 1.3s ease-in-out infinite;
}
.typing-indicator span:nth-child(2) { animation-delay: 0.18s; }
.typing-indicator span:nth-child(3) { animation-delay: 0.36s; }
@keyframes typingBounce {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-5px); }
}

/* Thinking indicator — branded orb + rotating short status label. */
.aios-thinking {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 18px;
  background: white;
  border: 1px solid var(--line-soft);
  border-radius: 16px 16px 16px 4px;
  box-shadow: var(--shadow-sm);
}
.thinking-orb {
  flex: 0 0 auto;
  display: inline-flex;
}
.thinking-orb .orb {
  width: 30px;
  height: 30px;
  animation-duration: 9s;       /* spin a touch livelier than the resting orb */
}
.thinking-orb .orb circle {
  animation-duration: 1.5s;     /* gentle pulse while thinking */
}
.thinking-label {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-soft, #5b6470);
  white-space: nowrap;
  transition: opacity 0.18s ease;
}
.thinking-label.fading { opacity: 0; }
body.a11y-reduce-motion .thinking-orb .orb,
body.a11y-reduce-motion .thinking-orb .orb circle { animation: none !important; }
body.a11y-reduce-motion .thinking-label { transition: none; }


/* 11. Orb ------------------------------------------------------ */
.orb-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;
}
.orb-wrapper-large { margin: 0 0 24px; }
/* The compact dock orb is retired (matching the Gallea Ai demo): voice feedback
   now lives in the mic button (the red recording orb), so this orb only added
   empty space above the chips. Kept out of the layout entirely. */
.orb-wrapper-compact { margin: 0; display: none !important; }
.aios-canvas.has-messages .orb-wrapper-large { display: none; }
/* Welcome screen: smaller orb so the starting-path boxes are the focus. */
.aios-canvas:not(.has-messages) .orb-wrapper-large { margin: 0 0 18px; }
.aios-canvas:not(.has-messages) .orb-wrapper-large .orb {
  width: clamp(112px, 15vh, 150px);
  height: clamp(112px, 15vh, 150px);
}

/* WELCOME ACTIONS — big starting-path cards on the opening screen. They
   replace the bottom pills until the first message; hidden once chatting. */
.welcome-actions {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  width: 100%;
  max-width: 1000px;
  margin: 6px auto 0;
}
.aios-canvas.has-messages .welcome-actions { display: none; }
.welcome-action {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: 10px;
  background: white;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg, 16px);
  padding: 22px 22px 20px;
  cursor: pointer;
  font-family: inherit;
  transition: transform 0.16s var(--ease), box-shadow 0.16s var(--ease),
              border-color 0.16s var(--ease);
}
.welcome-action:hover {
  transform: translateY(-3px);
  border-color: var(--aios-blue-border);
  box-shadow: 0 12px 28px color-mix(in srgb, var(--aios-blue) 13%, transparent);
}
.welcome-action-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: none;
  color: var(--aios-blue);
}
.welcome-action-icon:has(img) {
  background: none !important;
}
.welcome-action-icon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.welcome-action-title {
  font-size: 17px;
  font-weight: 800;
  color: var(--aios-blue);
  letter-spacing: -0.01em;
  width: 100%;
  line-height: 1.2;
}
.welcome-action-sub {
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
  font-weight: 500;
  text-wrap: pretty;
}
/* On the opening screen the big boxes ARE the prompts, so hide the dock pills. */
.aios-canvas:not(.has-messages) .chips-row,
.aios-canvas:not(.has-messages) .chips-label { display: none; }
.aios-canvas.has-messages .aios-dock .chips-row,
.aios-canvas.has-messages .aios-dock .chips-label { display: none; }
@media (max-width: 860px) {
  .welcome-actions { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .welcome-actions { grid-template-columns: 1fr; }
}
.orb {
  position: relative;
  animation: orbSpin 28s linear infinite;
}
/* WF8: enlarge the desktop opening orb to reclaim the whitespace freed by removing
   the under-orb "Tap to speak" label (WF7). Mobile overrides the size below. */
.orb-wrapper-large .orb { width: clamp(240px, 32vh, 380px); height: clamp(240px, 32vh, 380px); }
.orb-wrapper-compact .orb { width: 64px; height: 64px; animation-duration: 32s; }
@keyframes orbSpin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.orb svg { width: 100%; height: 100%; overflow: visible; }
.orb circle {
  fill: var(--aios-blue);
  animation: orbDot 2.6s ease-in-out infinite;
  transform-origin: center;
  transform-box: fill-box;
}
@keyframes orbDot {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}
/* Voice orb colour code (fleet default): RED while it is the visitor's turn to
   speak (listening), GREY while AiOS is speaking/thinking. reference (data-visual v2)
   overrides these to bright GREEN / bright BLUE below (owner spec 2026-07-23);
   other fleet tenants keep this default. */
.orb-listening .orb { animation-duration: 6s; }
.orb-listening .orb circle { fill: #D9534F; animation-duration: 0.9s; }
.orb-speaking .orb { animation-duration: 12s; }
.orb-speaking .orb circle { fill: #99A1AB; animation-duration: 1.4s; }
#micButton.listening .mic-orb .orb circle { fill: #D9534F; }
#micButton.speaking .mic-orb .orb circle { fill: #99A1AB; }
/* reference v2: BRIGHT GREEN listening, BRIGHT BLUE speaking (welcome + composer orb). */
[data-visual="v2"] .orb-listening .orb circle { fill: #22C55E; }
[data-visual="v2"] .orb-speaking .orb circle { fill: #2E90FA; }
[data-visual="v2"] #micButton.listening .mic-orb .orb circle { fill: #22C55E; }
[data-visual="v2"] #micButton.speaking .mic-orb .orb circle { fill: #2E90FA; }

/* 12. Chips ---------------------------------------------------- */
.chips-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 340px));
  gap: 16px;
  justify-content: center;
  margin: 4px 0 10px;
  max-width: 1080px;
  width: 100%;
}
.chips-row.left-aligned { justify-content: center; margin-top: 4px; }
.chips-label {
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  text-align: center;
  margin: 2px 0 6px;
}
.chip {
  background: white;
  border: 1.5px solid var(--aios-blue);
  color: var(--aios-blue);
  padding: 14px 20px;
  border-radius: var(--radius-pill);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease), box-shadow 0.2s var(--ease), transform 0.18s var(--ease);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: inherit;
  min-height: 52px;
  width: 100%;
  min-width: 0;
  text-align: center;
  line-height: 1.3;
  /* FIX-6: chips are equal-height cards, never truncating pills. Text wraps in
     full (no ellipsis, no clip); the grid row (align-items: stretch) equalises
     all three to the tallest, so the row is always uniform. */
  white-space: normal;
  overflow-wrap: anywhere;
  /* Subtle blue glow so chips feel inviting rather than secondary. */
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--aios-blue) 4%, transparent),
    0 4px 14px color-mix(in srgb, var(--aios-blue) 10%, transparent),
    0 0 0 4px color-mix(in srgb, var(--aios-blue) 4%, transparent);
}
.chip > span:last-child {
  white-space: normal;
  overflow-wrap: anywhere;
  min-width: 0;
}
.chip:hover {
  background: var(--aios-blue);
  color: white;
  border-color: var(--aios-blue);
  transform: translateY(-1px);
  box-shadow:
    0 2px 0 color-mix(in srgb, var(--aios-blue) 4%, transparent),
    0 10px 24px color-mix(in srgb, var(--aios-blue) 22%, transparent),
    0 0 0 6px color-mix(in srgb, var(--aios-blue) 8%, transparent);
}
.chip:hover .chip-sparkle { color: white; }
/* P1-4: the follow-up star is locked to one em-based ratio (1.2x the chip text)
   so it pops and holds the exact same proportion at every screen size and on
   every tenant. Never a fixed px size (that drifts against the text). */
.chip-sparkle { color: var(--aios-blue); font-size: 1.2em; line-height: 1; transition: color 0.15s var(--ease); display: inline-flex; align-items: center; }
.chip-sparkle svg { display: block; width: 1em; height: 1em; }

/* Visual-v2: answer-owned NEXT is the only chip lane. Dock chips occupy zero space. */
[data-visual="v2"] .aios-dock {
  border-top: 1px solid var(--mk-hairline, rgba(102, 102, 102, 0.22));
  background: linear-gradient(to bottom, var(--mk-surface, #fff), var(--mk-bg, #f4f4f4));
}
[data-visual="v2"] .aios-dock .chips-row,
[data-visual="v2"] .aios-dock .chips-label {
  display: none !important;
  height: 0 !important;
  min-height: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  overflow: hidden !important;
  border: 0 !important;
}
[data-visual="v2"] .aios-answer-next {
  max-width: var(--content-box, 760px);
  width: 100%;
}
[data-visual="v2"] .aios-answer-next .chip:focus,
[data-visual="v2"] .aios-answer-next .chip:active,
[data-visual="v2"] .aios-answer-next .chip.selected,
[data-visual="v2"] .aios-answer-next .chip.on,
[data-visual="v2"] .aios-answer-next .chip.is-on {
  outline: none;
  background: #fff;
  color: var(--aios-blue);
}

/* 14. Input bar ------------------------------------------------ */
.input-bar-wrap {
  display: flex;
  align-items: center;
  gap: 18px;
  max-width: 1180px;
  margin: 0 auto;
  width: 100%;
}
.input-persona { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.input-avatar {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--aios-blue);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14.5px;
  font-weight: 700;
  flex-shrink: 0;
}
.input-name { font-size: 15px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.input-bar {
  flex: 1;
  background: white;
  border: 1.5px solid var(--aios-blue);
  border-radius: var(--radius-pill);
  display: flex;
  align-items: center;
  padding: 6px 10px 6px 24px;
  box-shadow: 0 4px 16px color-mix(in srgb, var(--aios-blue) 12%, transparent);
  transition: opacity 0.2s var(--ease), border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
  min-width: 0;
}
.input-bar:focus-within {
  border-color: var(--aios-blue-dark);
  box-shadow: 0 6px 22px color-mix(in srgb, var(--aios-blue) 22%, transparent);
}
.input-bar.disabled { opacity: 0.6; cursor: not-allowed; }
.input-plus {
  color: var(--aios-blue);
  font-size: 26px;
  margin-right: 14px;
  cursor: pointer;
  font-weight: 300;
  line-height: 1;
  user-select: none;
}
.input-text {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-size: 16px;
  padding: 16px 0;
  color: var(--ink);
}
.input-text::placeholder { color: var(--muted-light); }
.input-text:disabled { cursor: not-allowed; }
.input-mic, .input-send {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: none;
  flex-shrink: 0;
  margin-left: 8px;
  transition: background 0.15s var(--ease), transform 0.1s var(--ease);
}
.input-mic svg { width: 19px; height: 19px; }
.input-send svg { width: 17px; height: 17px; }
.input-mic { background: transparent; color: var(--aios-blue); }
.input-mic:hover:not(:disabled) { background: var(--aios-blue-bg); }
/* Recording visual (from the Gallea Ai demo): while listening, voice.js swaps
   the mic icon for a small red recording orb in the mic's own spot. Neutralise
   the button chrome (no red fill / pulse) so the orb reads cleanly; the mic icon
   is restored by updateMicButton() when recording stops. */
.input-mic.listening { background: transparent; color: inherit; animation: none; box-shadow: none; }
/* WF17: "Tap to speak" microcopy above the mic icon, all tenants, web + mobile. The
   affordance wraps only the mic and inherits its horizontal spacing; the label floats
   above the icon (absolute), so composer-rail alignment is untouched. */
.mic-affordance { position: relative; display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; flex-shrink: 0; }
.mic-affordance .input-mic { margin-left: 0; }
.mic-microcopy {
  position: absolute; bottom: calc(100% + 2px); left: 50%; transform: translateX(-50%);
  font-size: 9px; line-height: 1; letter-spacing: 0.03em; white-space: nowrap;
  color: var(--muted, #6B7280); pointer-events: none;
}
/* AMENDMENT 19 TASK 6 (owner ruling): with the microphone selected the orb must
   read at the send button's circumference, colour hue excepted. The send button
   is a border-radius:50% disc at the same 44px as the mic button at every
   viewport, so the orb fills its button and the two discs are equal. The orb
   PAINTS at this size rather than merely sitting in a box of it, because
   fitOrbViewBox() refits the viewBox to the ink; at 26px it painted 18.5px.
   The 8px rail gap between the two controls is untouched, so they cannot
   overlap, and the probe asserts that on the ink at 1440 and 390. */
#micButton .mic-orb { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; }
#micButton .mic-orb .orb { width: 44px; height: 44px; animation: orbSpin 6s linear infinite; }
#micButton .mic-orb .orb svg { width: 100%; height: 100%; overflow: visible; }
#micButton .mic-orb .orb circle {
  fill: #D9534F; transform-origin: center; transform-box: fill-box;
  animation: orbDot 0.9s ease-in-out infinite;
}
/* reference v2: idle composer orb is brand navy, not red. */
[data-visual="v2"] #micButton .mic-orb .orb circle { fill: var(--aios-blue); }
.input-mic.is-stop { background: var(--aios-blue); color: white; }
.input-mic.is-stop:hover { background: var(--aios-blue-dark); }
@keyframes pulseRed {
  0%, 100% { box-shadow: 0 0 0 0 rgba(217, 83, 79, 0.5); }
  50% { box-shadow: 0 0 0 8px rgba(217, 83, 79, 0); }
}
.input-send { background: var(--aios-blue); color: white; }
.input-send:hover:not(:disabled) { background: var(--aios-blue-dark); }
.input-send:disabled, .input-mic:disabled { background: var(--muted-light); color: white; cursor: not-allowed; }
.input-mic:disabled { background: transparent; color: var(--muted-light); }
/* P1-3: the traditional-website link no longer sits inside the composer row (it
   was pushing the input off centre). It lives on its own meta row below the
   composer, right-aligned to the content boundary, so the composer stays centred
   at every width. */
.composer-meta {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  margin-top: 6px;
}
.classic-mode-link {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: underline;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: color 0.15s var(--ease);
}
.classic-mode-link:hover { color: var(--aios-blue); }

.powered-by-gallea {
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  padding: 6px 0 14px;
  letter-spacing: 0.02em;
}

/* P2-6: the locked attribution line is a full sentence naming the IBM stack, so
   it must wrap cleanly and stay centred and readable on every attribution
   surface (toggle screen + chat footer). Rendered from one core token. */
.aios-attribution {
  max-width: 660px;
  margin-left: auto;
  margin-right: auto;
  line-height: 1.5;
  letter-spacing: 0.01em;
}
/* Two stacked lines: primary on top, the IBM stack line beneath it, one size
   down and softened so it reads as supporting detail (owner override P2-6). */
.aios-attribution-primary { font-weight: 600; }
.aios-attribution-ibm { margin-top: 3px; font-size: 0.85em; opacity: 0.8; }

/* P2-7: version tag shown in the chat interface in the manner of a model tag. */
.aios-version-tag { text-align: center; margin: 0 0 4px; }
.aios-version {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 2px 9px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 999px;
}


/* 17. Side panel + overlays ------------------------------------ */
.side-panel-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.35);
  z-index: 90;
  display: none;
}
.side-panel-backdrop.open { display: block; }
.side-panel-backdrop.behind-overlay { pointer-events: none; background: transparent; }

.side-panel {
  position: fixed;
  top: 0;
  left: 0;
  height: calc(100vh / var(--app-zoom));
  height: calc(100dvh / var(--app-zoom));
  width: 280px;
  background: white;
  z-index: 95;
  transform: translateX(-100%);
  transition: transform 0.28s var(--ease);
  display: flex;
  flex-direction: column;
  box-shadow: 4px 0 16px rgba(0,0,0,0.10);
}
.side-panel.open { transform: translateX(0); }
.side-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 18px 8px;
}
.side-panel-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--aios-blue);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.05em;
}
.side-panel-brand svg { height: 18px; }
.side-panel-close {
  cursor: pointer;
  background: none;
  border: none;
  color: var(--aios-blue);
  padding: 6px;
  border-radius: var(--radius-sm);
  transition: background 0.15s;
  display: flex;
}
.side-panel-close:hover { background: var(--aios-blue-bg); }
.side-panel-nav { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.side-panel-nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: var(--radius-md);
  cursor: pointer;
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  font-family: inherit;
}
.side-panel-nav-item svg { flex-shrink: 0; }
.side-panel-nav-item:hover { background: var(--aios-blue-bg); color: var(--aios-blue); }
.side-panel-nav-item.active { background: var(--aios-blue-bg); color: var(--aios-blue); }
.side-panel-lang {
  padding: 8px 14px 12px;
  border-top: 1px solid var(--line-soft, #eee);
}
.side-panel-lang-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted, #6B7280);
  margin-bottom: 6px;
}
.side-panel-language {
  width: 100%;
  max-width: 100%;
  min-height: 40px;
  box-sizing: border-box;
  padding: 8px 10px;
  border: 1px solid var(--line, #e5e7eb);
  border-radius: 8px;
  background: #fff;
  color: var(--ink, #14181f);
  font: inherit;
  font-size: 14px;
}
.side-panel-user {
  margin-top: auto;
  padding: 18px;
  border-top: 1px solid var(--line-soft);
  display: flex;
  align-items: center;
  gap: 12px;
}
.side-panel-user-meta { flex: 1; min-width: 0; }
.side-panel-user-meta div:nth-child(1) { font-weight: 700; font-size: 13px; }
.side-panel-user-meta div:nth-child(2) { font-size: 11.5px; color: var(--muted); }
.side-panel-user-meta button {
  font-size: 11px;
  color: var(--muted);
  cursor: pointer;
  margin-top: 4px;
  text-decoration: underline;
  background: none;
  border: none;
  padding: 0;
}

/* content overlay (history/settings) takes full main area (side panel closes) */
.content-overlay {
  position: fixed;
  top: var(--nav-height);
  left: 0;
  right: 0;
  bottom: 0;
  background: white;
  z-index: 92;
  display: none;
  overflow-y: auto;
}
.content-overlay.open { display: block; }
.content-overlay-inner {
  max-width: 920px;
  margin: 0 auto;
  padding: clamp(24px, 3vw, 48px) clamp(24px, 3vw, 48px) 48px;
}
.content-overlay-close {
  position: absolute;
  top: 18px;
  right: 22px;
  background: white;
  border: 1px solid var(--line);
  width: 38px;
  height: 38px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  z-index: 2;
  transition: background 0.15s var(--ease), transform 0.1s var(--ease);
}
.content-overlay-close:hover { background: var(--line-soft); transform: rotate(90deg); }
.content-overlay h2 {
  font-size: 24px;
  color: var(--aios-blue);
  margin: 0 0 22px;
  letter-spacing: -0.01em;
  font-weight: 700;
}

/* History */
.history-search-wrap { position: relative; max-width: 640px; margin-bottom: 18px; }
.history-search-wrap svg {
  position: absolute;
  left: 18px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--aios-blue);
  pointer-events: none;
}
.history-search {
  width: 100%;
  border: 1px solid var(--aios-blue-border);
  background: var(--aios-blue-bg);
  padding: 12px 22px 12px 46px;
  border-radius: var(--radius-pill);
  font-size: 14px;
  color: var(--ink);
  outline: none;
}
.history-search:focus { border-color: var(--aios-blue); background: white; }
.history-filter {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 16px;
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.history-filter-label { font-weight: 600; }
.history-filter button {
  font-size: 12.5px;
  color: var(--muted);
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  transition: all 0.15s;
  font-family: inherit;
}
.history-filter button:hover { color: var(--aios-blue); }
.history-filter button.active {
  color: var(--aios-blue);
  background: var(--aios-blue-bg);
  border-color: var(--aios-blue-border);
  font-weight: 700;
}
.history-list { max-width: 760px; }
.history-empty { padding: 24px 16px; color: var(--muted); font-size: 13.5px; }
button.history-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  font: inherit;
}
.history-item {
  padding: 18px 16px;
  border-bottom: 1px solid var(--line-soft);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background 0.15s, padding 0.15s;
}
.history-item:hover { background: var(--aios-blue-bg); padding-left: 22px; }
.history-item-title { color: var(--aios-blue); font-weight: 700; font-size: 14px; margin-bottom: 5px; }
.history-item-preview { color: var(--ink-soft); font-size: 13px; margin-bottom: 6px; line-height: 1.5; }
.history-item-time { color: var(--muted-light); font-size: 11px; font-weight: 500; }

/* 18. Settings ------------------------------------------------- */
.settings-panel { padding: 4px 0; max-width: 820px; }
.settings-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--line);
  margin-bottom: 28px;
}
.settings-tab {
  padding: 13px 22px;
  cursor: pointer;
  font-weight: 600;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  font-size: 13.5px;
  transition: color 0.15s, border-color 0.15s;
  background: none;
  border-top: none;
  border-left: none;
  border-right: none;
  font-family: inherit;
  margin-bottom: -1px;
}
.settings-tab:hover { color: var(--aios-blue); }
.settings-tab.active { color: var(--aios-blue); border-bottom-color: var(--aios-blue); }

.settings-section-title { font-size: 15px; font-weight: 700; margin: 0 0 18px; color: var(--ink); }
.settings-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; max-width: 560px; }
.settings-field label {
  font-size: 10.5px;
  color: var(--muted);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  display: block;
  margin-bottom: 4px;
}
.settings-field input {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 13.5px;
  background: white;
  color: var(--ink);
}
.settings-field input:focus { outline: none; border-color: var(--aios-blue); }

.lang-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  max-width: 760px;
}
.lang-pill {
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 12px 16px;
  text-align: center;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.15s var(--ease);
  color: var(--ink);
  background: white;
}
.lang-pill:hover { border-color: var(--aios-blue); color: var(--aios-blue); background: var(--aios-blue-bg); }
.lang-pill.active { border-color: var(--aios-blue); color: white; background: var(--aios-blue); font-weight: 700; }

.voice-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; max-width: 600px; }
.voice-card {
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  padding: 18px;
  cursor: pointer;
  transition: all 0.15s var(--ease);
  background: white;
  position: relative;
}
.voice-card:hover { border-color: var(--aios-blue-light); }
.voice-card.active { border-color: var(--aios-blue); background: var(--aios-blue-bg); }
.voice-card.active::after {
  content: '✓';
  position: absolute;
  top: 12px;
  right: 12px;
  width: 22px;
  height: 22px;
  background: var(--aios-blue);
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
}
.voice-card-name { font-weight: 700; color: var(--aios-blue); margin-bottom: 4px; font-size: 16px; letter-spacing: -0.01em; }
.voice-card-desc { font-size: 12px; color: var(--muted); margin-bottom: 14px; }
.voice-preview-btn {
  background: var(--aios-blue);
  color: white;
  border: none;
  padding: 7px 14px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  cursor: pointer;
  font-weight: 700;
  letter-spacing: 0.06em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  text-transform: uppercase;
}
.voice-preview-btn:hover:not(:disabled) { background: var(--aios-blue-dark); }
.voice-preview-btn:disabled { background: var(--muted-light); cursor: wait; }
.voice-preview-btn .playing-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #FF6B6B;
  animation: dotPulse 0.8s ease-in-out infinite;
}
@keyframes dotPulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }

.access-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: white;
  cursor: pointer;
  max-width: 560px;
  margin-bottom: 10px;
  transition: border-color 0.15s;
}
.access-toggle:hover { border-color: var(--aios-blue-border); }
.access-toggle-label { font-size: 14px; font-weight: 600; color: var(--ink); }
.access-toggle-switch {
  width: 36px;
  height: 20px;
  background: var(--line);
  border-radius: 999px;
  position: relative;
  transition: background 0.18s;
  flex-shrink: 0;
}
.access-toggle-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: white;
  border-radius: 50%;
  transition: transform 0.2s var(--ease);
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.access-toggle.on .access-toggle-switch { background: var(--aios-blue); }
.access-toggle.on .access-toggle-switch::after { transform: translateX(16px); }

/* 19. Misc / RTL ----------------------------------------------- */
/* Layout stays LTR (the user asked: "leave the structure but the text in the
   text boxes etc should be written right-to-left"). We flip direction only on
   text-containing elements so paragraphs, inputs, labels read R→L, while the
   navbar, grids, side panel, and overall page chrome stay in the same physical
   position as English. */
body.rtl .msg-aios,
body.rtl .msg-user,
body.rtl .property-card-body,
body.rtl .property-card-links,
body.rtl .modal-body,
body.rtl .comparison-row,
body.rtl .calendar-card-name,
body.rtl .calendar-card-month,
body.rtl .calendar-times-label,
body.rtl .calendar-times-empty,
body.rtl .booking-card,
body.rtl .history-item,
body.rtl .history-filter,
body.rtl .settings-field,
body.rtl .settings-field label,
body.rtl .input-text,
body.rtl .toggle-card-body,
body.rtl .toggle-card-title,
body.rtl .aios-welcome,
body.rtl .modal-form input,
body.rtl .modal-form textarea,
body.rtl .lang-dropdown-item,
body.rtl .access-toggle-label,
body.rtl .footer-col-item,
body.rtl .footer-feed-title,
body.rtl .side-panel-nav-item,
body.rtl .side-panel-user-meta,
body.rtl .calendar-confirm-strip,
body.rtl .calendar-confirm-summary,
body.rtl .voice-card,
body.rtl .voice-card-name,
body.rtl .voice-card-desc,
body.rtl .modal-title,
body.rtl .modal-subtitle,
body.rtl .modal-section,
body.rtl .modal-list li,
body.rtl .amenity-title,
body.rtl .toggle-headline,
body.rtl .toggle-subhead,
body.rtl .comparison-title,
body.rtl .comparison-subtitle { direction: rtl; }
body.rtl .input-text { text-align: right; }
body.rtl .input-text::placeholder { text-align: right; }
body.rtl .history-search { padding: 12px 46px 12px 22px; text-align: right; direction: rtl; }
body.rtl .history-search-wrap svg { left: auto; right: 18px; }
body.rtl .modal-list li { padding-left: 0; padding-right: 14px; }
body.rtl .modal-list li::before { left: auto; right: 0; }
body.rtl .footer-col-item { text-align: right; }
body.rtl .settings-field label { text-align: right; }
body.rtl .access-toggle-label { text-align: right; }
body.rtl .calendar-card-name,
body.rtl .calendar-card-month,
body.rtl .calendar-times-label { text-align: right; }



/* ===== Accessibility modes — actually applied ===== */

/* 1. Larger text size — scale text-only properties globally. */
body.a11y-large-text {
  font-size: 18px;
}
body.a11y-large-text .input-text,
body.a11y-large-text .chip,
body.a11y-large-text .msg-user,
body.a11y-large-text .msg-aios { font-size: 17px; }
body.a11y-large-text .property-card-name { font-size: 19px; }
body.a11y-large-text .property-card-sub  { font-size: 15px; }
body.a11y-large-text .property-stat-value { font-size: 15.5px; }
body.a11y-large-text .property-stat-label { font-size: 11px; }
body.a11y-large-text .aios-welcome { font-size: clamp(32px, 4vw, 50px); }
body.a11y-large-text .info-panel-title { font-size: 26px; }
body.a11y-large-text .info-panel-subtitle { font-size: 15.5px; }
body.a11y-large-text .modal-title { font-size: 28px; }

/* 2. High contrast — push to pure black + white + AAA blue, remove tints. */
body.a11y-high-contrast {
  --aios-blue: color-mix(in srgb, var(--accent) 82%, #000);
  --aios-blue-dark: color-mix(in srgb, var(--accent) 55%, #000);
  --ink: #000000;
  --ink-soft: #1a1a1a;
  --muted: #2a2a2a;
  --muted-light: #4a4a4a;
  --line: #000000;
  --line-soft: #555555;
  --bg-tint: #ffffff;
  --aios-blue-tint: color-mix(in srgb, var(--accent) 12%, #fff);
  --aios-blue-bg: color-mix(in srgb, var(--accent) 12%, #fff);
}
body.a11y-high-contrast .property-card,
body.a11y-high-contrast .calendar-card,
body.a11y-high-contrast .info-panel,
body.a11y-high-contrast .floorplan-card,
body.a11y-high-contrast .modal-meta-cell,
body.a11y-high-contrast .contact-bucket,
body.a11y-high-contrast .input-bar,
body.a11y-high-contrast .chip { border-width: 2px; }
body.a11y-high-contrast .chip {
  border-color: var(--aios-blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--aios-blue) 15%, transparent);
}
body.a11y-high-contrast a,
body.a11y-high-contrast .info-link { text-decoration: underline; }

/* 3. Reduce motion — kill animations / transitions / smooth scroll. */
body.a11y-reduce-motion *, body.a11y-reduce-motion *::before, body.a11y-reduce-motion *::after {
  animation-duration: 0.001ms !important;
  animation-delay: 0ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  transition-delay: 0ms !important;
  scroll-behavior: auto !important;
}
body.a11y-reduce-motion .orb { animation: none !important; }
body.a11y-reduce-motion .typing-indicator span { animation: none !important; opacity: 0.8; }

/* 4. Screen reader optimisations — bigger hit targets, visible focus rings,
   tighten typography, and ensure offscreen labels stay perceivable. */
body.a11y-screen-reader *:focus-visible {
  outline: 3px solid var(--accent) !important;
  outline-offset: 3px !important;
}
body.a11y-screen-reader button,
body.a11y-screen-reader .chip,
body.a11y-screen-reader .lang-pill,
body.a11y-screen-reader .calendar-time-pill {
  min-height: 48px;
}
body.a11y-screen-reader .nav-btn { min-height: 44px; }
body.a11y-screen-reader .property-card-links button { min-height: 40px; font-size: 13px; }


/* ============================================================
   FIX-5 — TRUE MOBILE LAYOUT (<= 767px)
   The desktop `zoom` scaler is switched off below 768px (init.js), so these
   rules lay the app out natively at phone width: legible >= 16px text, a
   bottom-docked composer with safe-area inset, full-width stacked cards and
   chips, full-screen modals, a collapsed navbar, and no horizontal scroll.
   Desktop breakpoints above are untouched.
   ============================================================ */
@media (max-width: 767px) {
  html { font-size: 16px; }
  body { zoom: 1; }
  /* Safety net against a stray wide child forcing sideways scroll. */
  html, body { max-width: 100%; overflow-x: hidden; }

  /* MC10: reduce the AiOS mobile navbar height to reclaim answer canvas (was a firm
     56px). A tighter 46px bar with a matching smaller logo. */
  :root { --nav-height: 46px; }
  .navbar { padding: 0 14px; gap: 10px; min-height: 46px; height: 46px; }
  .navbar-logo, .navbar-logo img, .navbar-logo svg { height: 26px !important; width: auto; }
  .navbar-link { display: none !important; }
  .navbar .navbar-hamburger { display: inline-flex !important; }

  /* TASK 7 (owner): at 390 the top bar ran the tenant wordmark under the version
     chip. Measured before the fix, per tenant, in reports/f1-task7/: 77.5px of
     the mark covered on one tenant, 17.3px and 17px on two more, and 0 on the
     two whose marks are narrow enough to clear on their own.

     The cause is two rules that were each right on their own. fitBrandLogo()
     (init.js) normalizes optical AREA and writes the result as an inline width
     AND an inline height, both sized for the 42px desktop slot. The rule above
     then forces a 26px height on the phone and leaves that inline width alone,
     so a wide wordmark keeps its desktop WIDTH at a phone HEIGHT: the widest
     of the five measured 195.6x26 and reached 215.6px across a bar whose
     controls start at 138.1px.

     So on the phone the mark is sized by the SPACE THE BAR HAS, not by the
     inline constant: the width is released to the image's own ratio, capped to
     the space left over, and the brand slot may shrink while the controls may
     not. A mark that cannot fit is scaled down until it does rather than being
     drawn over the chip.

     The HEIGHT stays definite at 26px and only the WIDTH is released. Releasing
     both, and sizing from caps alone, collapsed one tenant's mark to 0x0: its
     wordmark is an SVG carrying a viewBox and no width/height attributes, so as
     an <img> it has an intrinsic RATIO but no intrinsic size, and an auto width
     against a percentage max-width inside a shrink-to-fit slot has nothing to
     resolve against. A definite height gives the ratio something to multiply.
     object-fit keeps a mark that still has to be clamped undistorted rather
     than stretched, which is what the inline width was doing to it before.
     Desktop is untouched. */
  .aios-topbar { gap: 10px; }
  .aios-topbar-brand { flex: 0 1 auto; min-width: 0; overflow: hidden; }
  .aios-topbar-controls { flex: 0 0 auto; }
  .aios-topbar .navbar-logo { min-width: 0; max-width: 100%; overflow: hidden; }
  .aios-topbar .navbar-logo img,
  .aios-topbar .navbar-logo svg {
    height: 26px !important;
    width: auto !important;
    max-width: 100% !important;
    object-fit: contain;
  }

  /* Canvas + column: full width, small gutters, native height (zoom = 1). P1-2:
     answer canvas and composer share the same 16px side gutter so they align. */
  .aios-canvas { height: calc(100vh - var(--nav-height)); height: calc(100dvh - var(--nav-height)); }
  /* MC6: comfortable breathing room so the last message is not jammed against the
     docked composer (Claude iOS reference). */
  .aios-container { padding: 16px 16px 14px; }
  .aios-canvas:not(.has-messages) .chat-scroll { overflow-y: auto; }
  .aios-canvas:not(.has-messages) .aios-container {
    justify-content: flex-start;
    height: auto;
    min-height: 100%;
    padding-top: 20px;
  }

  /* Messages: >= 16px, near full-width bubbles, comfortable line height. */
  .msg-aios { max-width: 100%; font-size: 16px; line-height: 1.6; padding: 14px 16px; }
  .msg-user { max-width: 85%; font-size: 16px; }

  /* P1-1 home: persona greeting + 2x3 image-thumbnail grid, short labels, no
     sub-text. Two columns give the 2x3 shape; the icon becomes the thumbnail. */
  .aios-welcome { font-size: 24px; }
  .welcome-actions { grid-template-columns: 1fr 1fr; gap: 12px; }
  .welcome-action { padding: 14px 12px; text-align: left; align-items: stretch; gap: 8px; }
  .welcome-action-sub { display: none; }
  .welcome-action-title { font-size: 15px; line-height: 1.2; width: 100%; text-align: left; min-height: 2.4em; }
  .welcome-action-icon { width: 40px; height: 40px; }
  .welcome-action-icon svg { width: 30px; height: 30px; }
  .welcome-action-icon img { width: 100%; height: 100%; object-fit: contain; display: block; }
  .aios-canvas:not(.has-messages) .orb-wrapper-large .orb { width: 92px; height: 92px; }

  /* Composer docked at the bottom with the iOS safe-area inset. The dock's own
     horizontal padding is 0; the shared child gutter (16px on mobile) handles the
     inset so the composer aligns to the answer canvas above it (P1-2). MC6: generous
     padding above (from the last message) and a comfortable margin below the bar. */
  .aios-dock { padding: 16px 0 calc(16px + env(safe-area-inset-bottom, 0px)); gap: 10px; }
  .input-bar-wrap { flex-wrap: wrap; gap: 8px 12px; }
  .input-bar { flex: 1 1 100%; padding: 4px 6px 4px 18px; }
  .input-text { font-size: 16px; padding: 12px 0; }   /* 16px keeps iOS from auto-zooming */
  .input-mic, .input-send { width: 44px; height: 44px; }   /* comfortable tap targets */
  .classic-mode-link { font-size: 13px; }

  /* Chips stack full width. */
  .chips-row, .chips-row.left-aligned { grid-template-columns: 1fr; max-width: 100%; gap: 10px; }
  /* P1-4: in chat, the follow-up prompts move into the message flow; the fixed
     dock strip is hidden so there is no duplicate. Welcome-screen chips stay. */
  .aios-canvas.has-messages .aios-dock .chips-row,
  .aios-canvas.has-messages .aios-dock .chips-label { display: none; }
  .mobile-followups { margin-top: 4px; }
  .mobile-followups .chips-label { display: block; margin-bottom: 8px; }
  .mobile-followups .chips-row.in-chat { display: grid; grid-template-columns: 1fr; gap: 10px; max-width: 100%; }

  /* P1-1: multi-item card and gallery rows become 85vw horizontal snap
     carousels (one card peeks the next); the carousel scrolls, never the page. */
  .property-cards-row, .amenity-cards, .amenity-grid, .gallery-grid {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 12px;
    padding-bottom: 4px;
  }
  /* MC11: reduce mobile answer-canvas card size (~40% narrower than the old 85vw) so
     property/amenity/gallery cards read well on a phone; image + text stay legible. */
  .property-card-wrap, .amenity-card, .gallery-thumb, .fp-card {
    flex: 0 0 52vw; max-width: 52vw; scroll-snap-align: start;
  }
  .property-card, .property-card.content-first { width: 100%; }
  .journey-grid { grid-template-columns: 1fr; }
  .pdetail-suites { grid-template-columns: 1fr; }
  .journey-trail, .comparison-card, .pdetail, .reg-block, .info-panel { max-width: 100%; }

  /* Modals become full-screen sheets with a 44px close target (P1-1). */
  .modal-overlay { padding: 0; align-items: stretch; }
  .modal-content { width: 100%; max-width: 100%; min-height: 100vh; border-radius: 0; }
  .modal-close { width: 44px; height: 44px; }
  .modal-header-img { height: 220px; }
  .modal-body { padding: 22px 18px 32px; }
  .modal-list { grid-template-columns: 1fr; }
  .modal-form-row { grid-template-columns: 1fr; }

  /* Content overlays (history / settings) full width. */
  .content-overlay-inner { padding: 20px 16px 40px; }
  .settings-grid-2, .voice-grid { grid-template-columns: 1fr; }
  .lang-grid { grid-template-columns: 1fr 1fr; }

  /* Toggle entry screen: the two path cards stack. */
  .toggle-cards { flex-direction: column; align-items: center; }
  .toggle-card { width: 100%; max-width: 420px; min-height: 0; }

  /* Footer stacks to one column. */
  .footer-grid { grid-template-columns: 1fr; }
  .footer-feed-grid { grid-template-columns: repeat(6, 1fr); }
}

/* Privacy / Terms / Accessibility render in the side panel and overlays.
   The mid-page toggle legal bar is a second instance, so it is suppressed. */
.toggle-legal-bar { display: none !important; }

.nextrow, .aios-answer-next { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; max-width: var(--content-box, 760px); }
.nextlab, .aios-next-lab { font-size: 9px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--sub, var(--muted)); margin-right: 2px; flex: 0 0 auto; }
.aios-next-btn { display: inline-flex; align-items: center; gap: 8px; width: auto; max-width: 100%; min-height: 40px; background: #fff; border: 2px solid color-mix(in srgb, var(--ac, var(--accent)) 60%, #fff); border-radius: var(--r-chip, 999px); padding: 9px 16px; font: inherit; font-size: 14px; font-weight: 700; color: var(--ink); white-space: nowrap; cursor: pointer; line-height: 1.2; box-sizing: border-box; }
.aios-next-spark, .aios-next-btn .chip-sparkle { display: inline-flex; color: var(--ac, var(--accent)); flex: 0 0 auto; width: 17px; height: 17px; }
.aios-next-spark svg, .aios-next-btn .chip-sparkle svg { width: 17px; height: 17px; display: block; }
.aios-answer-accuracy { display: block; max-width: var(--content-box, 760px); width: 100%; margin: 10px 0 0; padding: 0; text-align: left; font: inherit; font-size: 12px; font-weight: 400; line-height: 1.45; color: color-mix(in srgb, var(--sub, var(--muted)) 85%, #9aa3ad); letter-spacing: 0; }
[data-visual="v2"] .aios-hardbreak {
  height: 0;
  border-top: 1px solid var(--mk-hairline-strong, #666);
  opacity: 0.5;
  margin: var(--mk-block-gap, 16px) 0 4px;
  max-width: none;
}

/* =============================================================
   VISUAL V2 — the hybrid answer canvas (reference, reference-v2).
   ADDITIVE ONLY, scoped strictly under [data-visual="v2"], so every tenant
   without the flag renders byte-identically. Tokens come from
   tenants/client/kit/tokens.css (--mk-*). No em dashes.
   ============================================================= */

/* The whole AiOS answer group: marker, unbubbled text, canvas, hard break. */
[data-visual="v2"] .aios-answer {
  max-width: var(--mk-answer-max, 860px);
  margin: 4px 0 8px;
}

/* Non-interactive Max marker (v3): the persistent Max orb glyph + "MAX" in
   letterspaced caps. A div group, never a button. The orb mirrors the composer
   voice orb via the shared OrbState (is-idle | is-thinking | is-answering |
   is-speaking | is-listening set by orb.js). */
[data-visual="v2"] .aios-answer-marker {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 8px;
  user-select: none;
}
[data-visual="v2"] .aios-marker-orb {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
[data-visual="v2"] .aios-marker-orb .orb {
  width: 18px;
  height: 18px;
  animation: orbSpin 28s linear infinite;
}
[data-visual="v2"] .aios-marker-orb .orb svg { width: 100%; height: 100%; overflow: visible; }
/* idle: still, brand blue at rest. The dots do not pulse or spin when idle. */
[data-visual="v2"] .aios-marker-orb .orb circle {
  fill: var(--mk-accent, var(--plate-blue));
  transform-origin: center;
  transform-box: fill-box;
  animation: none;
}
[data-visual="v2"] .aios-marker-orb.is-idle .orb { animation-play-state: paused; }
/* Owner review (2026-07-23): BRIGHT GREEN when on/listening; BRIGHT BLUE when
   thinking, answering and speaking. */
/* thinking: bright blue, gentle dot pulse, no spin. */
[data-visual="v2"] .aios-marker-orb.is-thinking .orb { animation-play-state: paused; }
[data-visual="v2"] .aios-marker-orb.is-thinking .orb circle { fill: #2E90FA; animation: orbDot 2.0s ease-in-out infinite; }
/* answering: bright blue, dot pulse, no spin. */
[data-visual="v2"] .aios-marker-orb.is-answering .orb { animation-play-state: paused; }
[data-visual="v2"] .aios-marker-orb.is-answering .orb circle { fill: #2E90FA; animation: orbDot 1.8s ease-in-out infinite; }
/* speaking: SPIN (TTS playback), bright blue, more prominent. */
[data-visual="v2"] .aios-marker-orb.is-speaking .orb { animation-play-state: running; animation-duration: 12s; }
[data-visual="v2"] .aios-marker-orb.is-speaking .orb circle { fill: #2E90FA; animation: orbDot 1.3s ease-in-out infinite; }
/* listening / active: BRIGHT GREEN (mic open). */
[data-visual="v2"] .aios-marker-orb.is-listening .orb { animation-play-state: paused; }
[data-visual="v2"] .aios-marker-orb.is-listening .orb circle { fill: #22C55E; animation: orbDot 0.9s ease-in-out infinite; }
[data-visual="v2"] .aios-marker-label {
  font-family: var(--mk-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mk-muted, #666);
}
body.a11y-reduce-motion [data-visual="v2"] .aios-marker-orb .orb,
body.a11y-reduce-motion [data-visual="v2"] .aios-marker-orb .orb circle { animation: none !important; }

/* Composer orb (v3): the dock mic orb follows the identical OrbState. Owner
   review (2026-07-23): listening BRIGHT GREEN; thinking/answering/speaking
   BRIGHT BLUE. These override voice.js's in-place listening/speaking colours. */
[data-visual="v2"] #micButton.is-thinking .mic-orb .orb circle,
[data-visual="v2"] #micButton.is-answering .mic-orb .orb circle,
[data-visual="v2"] #micButton.is-speaking .mic-orb .orb circle,
[data-visual="v2"] #micButton.speaking .mic-orb .orb circle { fill: #2E90FA; }
[data-visual="v2"] #micButton.is-listening .mic-orb .orb circle,
[data-visual="v2"] #micButton.listening .mic-orb .orb circle { fill: #22C55E; }
[data-visual="v2"] #micButton.is-speaking .mic-orb .orb { animation-play-state: running; }

/* Composer auto-grow (v3, Phase 3f): the field is a wrapping textarea that grows
   the box upward, bounded to about eight lines then scrolls internally. Owner
   review: the placeholder was clipping, so the field carries generous symmetric
   padding and a min-height that fully clears one line. Scoped to v2. */
[data-visual="v2"] .aios-dock .composer textarea.input-text {
  resize: none;
  overflow-y: hidden;      /* JS switches to auto once the cap is reached */
  overflow-x: hidden;
  line-height: 1.5;
  padding: 14px 0 14px;
  min-height: 52px;        /* one line fully visible, no clipping */
  max-height: 200px;       /* backstop; JS caps to ~8 lines precisely */
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
  display: block;
  vertical-align: middle;
}
[data-visual="v2"] .aios-dock .composer .composer-input-row { align-items: stretch; padding: 2px 20px 0; }
/* Once it wraps past one line, ease the pill to a taller, intentional shape. */
[data-visual="v2"] .aios-dock .composer.is-multiline { border-radius: 24px; }

/* =============================================================
   CHROME (owner review) — gateway modal, version mark, tap-to-speak. v2 only.
   ============================================================= */

/* Gateway: a centred, non-scrolling modal — logo centred above the heading,
   nothing below the attribution. Engine-owned geometry so the toggle is pixel-
   consistent across tenants; only colour/font/logo/copy vary. Scoped to v2 (the
   standard); tenants adopt it with the fleet rollout. */
[data-visual="v2"] #toggleScreen:not(.hidden) {
  position: fixed; inset: 0; z-index: 500;
  background: var(--bg-tint, #F8F9FB);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
[data-visual="v2"] #toggleScreen:not(.hidden) .toggle-screen {
  max-height: 100%;
  display: flex; flex-direction: column; align-items: center;
  overflow: visible;
}
[data-visual="v2"] .toggle-logo { display: block; height: 42px; margin: 0 auto 22px; }
[data-visual="v2"] .toggle-logo img, [data-visual="v2"] .toggle-logo svg { height: 100%; width: auto; display: block; margin: 0 auto; }

/* Professional version mark, top right, to the left of the hamburger. Light on
   the navy navbar, a quiet outlined pill. */
/* Version mark: a quiet outlined pill in the top-right, on the LIGHT canvas
   ground (was white-on-navy). Global — every tenant's topbar carries it. */
.aios-version-mark {
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em;
  color: var(--muted, #6b7280);
  border: 1px solid var(--line, #E5E7EB);
  background: #fff;
  border-radius: 999px; padding: 5px 11px; white-space: nowrap;
  text-transform: none;
}

/* Tap to speak: inline to the LEFT of the mic in the rail, larger and legible
   (not the tiny caption above the icon). Scoped to v2 — tenants get it when they
   adopt the standard (the whole fleet does in the rollout). */
[data-visual="v2"] .composer .mic-affordance { flex-direction: row; align-items: center; gap: 9px; }
[data-visual="v2"] .composer .mic-microcopy {
  position: static; transform: none; left: auto; bottom: auto;
  order: -1; font-size: 13px; font-weight: 500; color: var(--muted, #666);
  white-space: nowrap;
}

/* =============================================================
   V3 SCENE OVERHAUL (Phase 3a/3b/3c/3d/3e). All additive, all scoped to the v2
   visual, all skinned by the --mk-* tokens. No new decorative vocabulary: one
   accent, hairline dividers, the harvested display face for titles, an 8px
   rhythm, a 2px hover lift, and a staggered entrance for canvas blocks.
   ============================================================= */

/* 3e. Staggered entrance for canvas blocks (60ms cascade, 8px rise, 240ms ease-out). */
@keyframes mkRise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
[data-visual="v2"] .aios-canvas-v2 > * { animation: mkRise 240ms ease-out both; }
[data-visual="v2"] .aios-canvas-v2 > *:nth-child(1) { animation-delay: 0ms; }
[data-visual="v2"] .aios-canvas-v2 > *:nth-child(2) { animation-delay: 60ms; }
[data-visual="v2"] .aios-canvas-v2 > *:nth-child(3) { animation-delay: 120ms; }
[data-visual="v2"] .aios-canvas-v2 > *:nth-child(4) { animation-delay: 180ms; }
[data-visual="v2"] .aios-canvas-v2 > *:nth-child(n+5) { animation-delay: 240ms; }
[data-visual="v2"] .mk-brochure > * { animation: mkRise 240ms ease-out both; }
[data-visual="v2"] .mk-brochure > *:nth-child(2) { animation-delay: 60ms; }
[data-visual="v2"] .mk-brochure > *:nth-child(3) { animation-delay: 120ms; }
[data-visual="v2"] .mk-brochure > *:nth-child(4) { animation-delay: 180ms; }
[data-visual="v2"] .mk-brochure > *:nth-child(n+5) { animation-delay: 240ms; }
body.a11y-reduce-motion [data-visual="v2"] .aios-canvas-v2 > *,
body.a11y-reduce-motion [data-visual="v2"] .mk-brochure > * { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  [data-visual="v2"] .aios-canvas-v2 > *,
  [data-visual="v2"] .mk-brochure > * { animation: none !important; }
}

/* Shared: display-face block titles 24-32px, hairline fact bands, 8px rhythm. */
[data-visual="v2"] .mk-block-title,
[data-visual="v2"] .mk-bro-section-head,
[data-visual="v2"] .mk-explore-head,
[data-visual="v2"] .mk-avail-kicker {
  font-family: var(--mk-display);
  font-weight: var(--mk-display-weight);
  letter-spacing: var(--mk-display-ls);
  text-transform: var(--mk-display-transform);
  color: var(--mk-ink);
}

/* Fact band: hairline-divided stats, never stacked small text. */
[data-visual="v2"] .mk-fact-band {
  display: flex; flex-wrap: wrap; gap: 0;
  border: 1px solid var(--mk-hairline);
  border-radius: var(--mk-radius-card);
  overflow: hidden;
  margin: 8px 0;
}
[data-visual="v2"] .mk-fact {
  flex: 1 1 0; min-width: 96px;
  padding: 12px 16px;
  border-left: 1px solid var(--mk-hairline);
  display: flex; flex-direction: column; gap: 3px;
}
[data-visual="v2"] .mk-fact:first-child { border-left: 0; }
[data-visual="v2"] .mk-fact-n { font-size: 17px; font-weight: 700; color: var(--mk-ink); line-height: 1.2; }
[data-visual="v2"] .mk-fact-l { font-size: 10px; letter-spacing: var(--mk-label-ls); text-transform: uppercase; color: var(--mk-muted); }
