/* side-panel footer */
  .side-panel-footer { margin-top: auto; padding: 14px 16px 18px; border-top: 1px solid rgba(0,0,0,0.08); display: flex; flex-direction: column; gap: 8px; }
  /* WF15: small, understated Gallea + IBM lockup in the drawer, below the hairline. */
  .side-panel-brand-lockup { display: flex; align-items: center; gap: 12px; padding: 2px 2px 6px; }
  .side-panel-brand-lockup .attr-mark-gallea { height: 15px; width: auto; display: block; }
  .side-panel-brand-lockup .attr-mark-ibm { height: 22px; width: auto; display: block; }
  .side-panel-plate-link { display: flex; align-items: center; gap: 8px; background: none; border: none; font-family: inherit; font-size: 13px; color: var(--muted, #6B7280); cursor: pointer; padding: 4px 2px; text-align: left; width: 100%; }
  .side-panel-plate-link:hover { color: inherit; }
  .side-panel-legal { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 11.5px; color: var(--muted, #6B7280); }
  .side-panel-legal button { background: none; border: none; font-family: inherit; font-size: 11.5px; color: var(--muted, #6B7280); cursor: pointer; padding: 2px 0; }
  .side-panel-legal button:hover { text-decoration: underline; }
  .side-panel { display: flex; flex-direction: column; }

  /* C4 / F-A exclusive view: the opening (welcome) and the conversation never
     co-render. The welcome is hidden once the canvas has messages (hideWelcome);
     conversely the conversation container is hidden while the welcome is shown, so
     returning to the opening (logo) never leaves the prior thread overlapping the
     starter cards / greeting. The session stays in state + DOM and resumes on the
     next turn (or via the gateway card). All tenants, all widths. */
  .aios-canvas:not(.has-messages) #chatMessages,
  .aios-canvas:not(.has-messages) .chat-messages,
  #aiosCanvas:not(.has-messages) #chatMessages,
  #aiosCanvas:not(.has-messages) .chat-messages { display: none !important; }

  /* toggle-screen legal bar */
  .toggle-legal-bar { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; font-size: 11.5px; color: var(--muted, #6B7280); }
  .toggle-legal-bar button { background: none; border: none; font-family: inherit; font-size: 11.5px; color: var(--muted, #6B7280); cursor: pointer; }
  .toggle-legal-bar button:hover { text-decoration: underline; }

  /* chrome overlays (plate + legal), full-screen sheet like settings/history */
  .chrome-overlay { position: fixed; inset: 0; z-index: 1200; background: #f4f5f7; display: none; flex-direction: column; }
  .chrome-overlay.open { display: flex; }
  .chrome-overlay-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid rgba(0,0,0,0.08); background: #fff; }
  .chrome-overlay-title { font-weight: 600; font-size: 15px; }
  .chrome-overlay-close { width: 44px; height: 44px; border: none; background: none; font-size: 26px; line-height: 1; cursor: pointer; color: #333; border-radius: 8px; }
  .chrome-overlay-close:hover { background: rgba(0,0,0,0.06); }
  .chrome-overlay-body { flex: 1; overflow-y: auto; padding: 24px 20px 60px; -webkit-overflow-scrolling: touch; }
  /* Exact-source plate: the owner-approved nameplate document renders full-bleed in
     an iframe; drop the body padding and match the document ground so it looks
     exactly like the delivered file. */
  #plateOverlay .chrome-overlay-body { padding: 0; background: #f2f5f9; }
  .vplate-frame { width: 100%; border: 0; display: block; background: #f2f5f9; min-height: 70vh; }

  /* manufacturer's plate: literal industrial nameplate, stamped mono identifiers */
  .plate { max-width: 720px; margin: 0 auto; background: linear-gradient(160deg,#20262b,#161a1e); color: #e7ebee; border: 1px solid #3a444c; border-radius: 10px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 8px 24px rgba(0,0,0,0.25); padding: 22px 24px 26px; font-family: 'Inter', system-ui, sans-serif; }
  .plate-header { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding-bottom: 12px; border-bottom: 1px dashed #46525b; }
  .plate-header-title { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.18em; font-size: 12.5px; color: #aab6bf; }
  .plate-header-serial { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; color: #7f8c95; }
  .plate-owner { margin: 16px 0 6px; }
  .plate-owner-label { font-family: ui-monospace, monospace; font-size: 10.5px; letter-spacing: 0.16em; color: #8a97a0; }
  .plate-owner-name { font-size: 26px; font-weight: 700; letter-spacing: 0.01em; margin-top: 2px; }
  .plate-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: #3a444c; border: 1px solid #3a444c; border-radius: 6px; overflow: hidden; margin: 16px 0; }
  .plate-field { background: #1b2024; padding: 10px 12px; display: flex; flex-direction: column; gap: 3px; }
  .plate-k { font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: 0.14em; color: #7f8c95; }
  .plate-v { font-family: ui-monospace, monospace; font-size: 13px; color: #eef2f4; word-break: break-word; }
  .plate-ibm { margin: 16px 0; padding: 14px 16px; background: rgba(255,255,255,0.03); border-left: 3px solid #4589ff; border-radius: 4px; }
  .plate-ibm-phrase { font-size: 13.5px; font-style: italic; color: #cfd7dd; }
  .plate-ibm-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 18px; }
  .plate-ibm-list li { font-size: 12.5px; color: #e7ebee; position: relative; padding-left: 14px; }
  .plate-ibm-list li::before { content: ''; position: absolute; left: 0; top: 6px; width: 6px; height: 6px; background: #4589ff; border-radius: 50%; }
  .plate-section-label { font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: 0.16em; color: #8a97a0; margin-bottom: 6px; }
  .plate-about p { font-size: 13px; line-height: 1.55; color: #cfd7dd; margin: 0; }
  .plate-about { margin: 18px 0; }
  .plate-contact { margin: 18px 0; }
  .plate-contact-row { display: flex; gap: 10px; padding: 4px 0; font-size: 12.5px; border-bottom: 1px solid rgba(255,255,255,0.05); }
  .plate-contact-label { flex: 0 0 92px; color: #8a97a0; font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: 0.06em; }
  .plate-contact-val { color: #e7ebee; word-break: break-word; }
  .plate-contact-val.plate-todo { color: #e0a458; font-family: ui-monospace, monospace; font-size: 11px; }
  .plate-support-line { margin-top: 10px; font-size: 12.5px; color: #9fd0a8; }
  .plate-logos { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; margin-top: 22px; padding-top: 18px; border-top: 1px dashed #46525b; }
  .plate-logo { height: 26px; display: inline-flex; align-items: center; }
  .plate-logo-gallea img, .plate-tenant-logo-img { height: 24px; }
  .plate-logo-gallea { filter: brightness(0) invert(1); opacity: 0.92; }
  .plate-logo-ibm { height: 30px; }
  .plate-tenant-logo-img { max-height: 26px; width: auto; }
  .plate-tenant-logo-text { font-weight: 700; font-size: 15px; color: #e7ebee; }
  .plate-footnote { margin-top: 18px; font-family: ui-monospace, monospace; font-size: 10.5px; color: #7f8c95; }

  /* legal docs */
  .legal-doc { max-width: 760px; margin: 0 auto; color: #1f2429; font-size: 15px; line-height: 1.6; }
  .legal-doc-brand { display: flex; justify-content: flex-start; margin: 4px 0 26px; }
  .legal-doc-brand img { height: 34px; width: auto; }
  .legal-doc-brand-text { font-size: 18px; font-weight: 800; color: var(--aios-blue, var(--accent)); }
  .legal-doc-lockup { display: flex; justify-content: flex-start; margin: 0 0 12px; }
  .legal-doc-lockup img { height: 26px; width: auto; }
  .legal-doc-meta { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: 12.5px; letter-spacing: .02em; color: #6B7280; text-transform: uppercase; margin-top: 6px; }
  .legal-doc h1.legal-doc-title { margin: 0; }
  .legal-section h3 { font-size: 15.5px; font-weight: 700; letter-spacing: .01em; margin: 26px 0 8px; padding-top: 18px; border-top: 1px solid #E5E8EE; color: #111827; }
  .legal-section p, .legal-list li { color: #374151; }
  .legal-lead { font-size: 16.5px; color: #111827; margin: 18px 0 8px; }
  .legal-doc-head { display: flex; align-items: center; gap: 12px; }
  .legal-doc-title { font-size: 30px; font-weight: 800; letter-spacing: -0.01em; color: var(--aios-blue, var(--accent)); }
  .legal-doc-meta { margin-bottom: 22px; }
  .legal-section { margin-bottom: 18px; }
  .legal-section h3 { font-size: 15px; font-weight: 650; margin: 0 0 5px; }
  .legal-section p { font-size: 13.5px; line-height: 1.6; color: #374151; margin: 0; }
  .legal-section p + p { margin-top: 10px; }
  .legal-list { margin: 8px 0 0; padding-left: 20px; }
  .legal-list li { font-size: 13.5px; line-height: 1.55; color: #374151; padding: 2px 0; }
  .legal-list + p { margin-top: 10px; }
  /* 4.2R vF2 jurisdiction/privacy-law tables + governance sidecards, in-overlay */
  .legal-table { width: 100%; border-collapse: collapse; font-size: 12.5px; margin: 12px 0; }
  .legal-table th { background: var(--aios-blue, var(--accent)); color: #fff; text-align: left; font-weight: 600; padding: 8px 12px; }
  .legal-table td { padding: 8px 12px; border: 1px solid #E5E7EB; vertical-align: top; color: #374151; line-height: 1.5; }
  .legal-table tbody tr:nth-child(even) td { background: #F3F4F6; }
  .legal-table + p { margin-top: 10px; }
  .legal-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 12px 0; }
  .legal-card { border: 1px solid #E5E7EB; border-radius: 6px; padding: 14px; background: #fff; }
  .legal-card-title { font-weight: 650; font-size: 13.5px; color: #1f2429; margin-bottom: 5px; }
  .legal-card-body { font-size: 12.5px; line-height: 1.5; color: #374151; }
  .legal-cards + p { margin-top: 10px; }
  @media (max-width: 767px) { .legal-cards { grid-template-columns: 1fr; } }
  .legal-attribution { font-size: 12.5px; line-height: 1.6; color: #374151; margin: 22px 0 0; }
  .legal-caption { font-size: 11px; font-style: italic; line-height: 1.45; color: #6B7280; margin: 10px 0 0; }
  .legal-doc-foot { margin-top: 32px; padding-top: 18px; border-top: 1px solid rgba(0,0,0,0.08); font-size: 11px; color: #6B7280; }

  /* settings general controls */
  .settings-clear-btn { margin-top: 14px; padding: 9px 16px; border: 1px solid rgba(0,0,0,0.15); background: #fff; border-radius: 8px; font-family: inherit; font-size: 13px; cursor: pointer; color: #b91c1c; }
  .settings-clear-btn:hover { background: #fef2f2; border-color: #fca5a5; }
  .settings-clear-note { margin-top: 6px; font-size: 11.5px; color: var(--muted, #6B7280); }

  /* P4-1 IBM variant emphasis (placeholder skin, pending owner input) */
  .plate-variant-banner { margin: -4px 0 14px; padding: 8px 12px; background: rgba(69,137,255,0.16); border: 1px solid #4589ff; border-radius: 5px; font-size: 12px; color: #cfe0ff; }
  .plate-ibm-variant .plate-logo-ibm { height: 40px; }
  body.aios-variant-ibm .footer-aios-ibm { height: 32px; }

  /* P2-9 Gallea partnership-tagged answer mark */
  .answer-ibm-mark { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line, #E5E7EB); }
  .answer-ibm-mark img { height: 34px; width: auto; display: block; }

  /* N15 carousel arrows: faint circular prev/next controls over a swipeable card
     carousel. Conditional visibility is set in JS (no left arrow at the start, no
     right arrow at the end). Faint by default, clearer on hover. */
  .aios-carousel-wrap { position: relative; }
  .aios-carousel-arrow {
    position: absolute; top: 46%; transform: translateY(-50%); z-index: 4;
    width: 34px; height: 34px; border-radius: 50%;
    background: rgba(255,255,255,0.85); border: 1px solid var(--line, #e5e7eb);
    box-shadow: 0 2px 8px rgba(15,23,42,0.14);
    display: flex; align-items: center; justify-content: center;
    color: var(--ink, #1A1A1A); cursor: pointer; opacity: 0.72;
    transition: opacity 0.15s ease;
  }
  .aios-carousel-arrow:hover { opacity: 1; }
  .aios-carousel-prev { left: 4px; }
  .aios-carousel-next { right: 4px; }

  /* site-footer AiOS strip */
  .footer-aios-strip { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding-top: 12px; }
  .footer-aios-label { font-size: 11px; color: var(--muted, #6B7280); letter-spacing: 0.04em; }
  .footer-aios-logo { height: 16px; }
  .footer-aios-ibm { height: 26px; }

  /* ===== COMPOSER (core, all tenants): two rows inside one rounded border ===== */
  .aios-dock .composer {
    width: 100%; box-sizing: border-box;
    display: flex; flex-direction: column;
    background: #fff;
    border: 1.5px solid var(--aios-blue, var(--accent));
    border-radius: 22px;
    box-shadow: 0 4px 16px rgba(15,23,42,0.08);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
    overflow: hidden;
  }
  .aios-dock .composer:focus-within {
    border-color: var(--aios-blue, var(--accent));
    box-shadow: 0 6px 22px color-mix(in srgb, var(--aios-blue, var(--accent)) 22%, transparent);
  }
  .aios-dock .composer .composer-input-row { padding: 6px 20px 0; display: flex; }
  /* reference' input carries .input-text; Tompkins/Gallea use #messageInput only.
     Target both so the field fills the row on every tenant. The row is now a flex
     container, so the field's flex:1 finally resolves (a bare text input in a plain
     block falls back to the browser default ~169px, which clipped the placeholder
     mid-string on Tompkins and Gallea). */
  .aios-dock .composer .input-text,
  .aios-dock .composer #messageInput {
    width: 100%; flex: 1 1 auto; min-width: 0; box-sizing: border-box; border: none; outline: none;
    background: transparent; font-family: inherit; font-size: 16px; padding: 12px 0 6px; color: var(--ink, #1A1A1A);
  }
  .aios-dock .composer .composer-rail {
    display: flex; align-items: center; justify-content: flex-end; gap: 12px;
    padding: 4px 10px 8px 20px;
  }
  .aios-dock .composer .composer-version {
    font-size: 12px; font-weight: 500; letter-spacing: 0.02em; color: var(--muted, #6B7280);
    white-space: nowrap; margin-right: 2px;
  }
  .aios-dock .composer .input-mic, .aios-dock .composer .input-send { margin-left: 0; }

  /* CD-5 (2026-07-14): one shared, subtle "Tap to speak" microcopy spec across every
     tenant. reference carried a 9px muted rule; Tompkins and Gallea had none, so the label
     rendered ~16px near-black and, being static, sat in flow beside the mic and knocked
     it off-centre from the send button. Positioning it absolutely above the mic removes
     it from flow, so the mic stays vertically centred with the send button on all
     tenants, and the size/colour match. */
  .mic-affordance { position: relative; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 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; }

  /* CD-4 (2026-07-14): "Traditional website" belongs only on the AiOS chat navbar, never
     on the toggle/gateway navbar (Gallea removes it entirely per WF27). The shell marks
     the link [data-aios-traditional]; hide it whenever the page is NOT in AiOS mode (the
     toggle/gateway view). LOGIN stays on the toggle navbar per P-1. */
  html:not(.aios-active) [data-aios-traditional] { display: none !important; }

  /* Chrome discipline (pristine): an AiOS screen carries ONLY the logo (left) and
     the hamburger (right). Every site tab disappears the moment we enter AiOS, so
     no navbar link navigates away from the demo. The bar stays full-width and the
     logo keeps its size/position, so the navbar and logo do not move by a single
     pixel between the toggle and AiOS states. The full tabbed navbar returns on the
     toggle screen (not aios-active), where tabs open the tenant's real live site. */
  body.aios-active .navbar .navbar-link,
  body.aios-active .navbar .nav-link { display: none !important; }

  /* ===== SUGGESTION CHIPS: three equal columns spanning the composer width =====
     The chips-row and the composer's .input-bar-wrap are both dock rows that
     resolve to the same content-box max-width + gutter, so the first chip's left
     border sits flush with the composer's left border and the third chip's right
     border with its right. Only the grid changes here (3 equal cols, 10px gaps);
     the width constraint is left to the dock rows so alignment holds. */
  .aios-dock .chips-row {
    display: grid !important;
    grid-template-columns: repeat(3, 1fr) !important;
    gap: 10px !important;
    justify-content: stretch !important;
    margin: 4px 0 10px !important;
  }
  /* Suggestion chips appear only AFTER answers, never on the opening (pre-conversation)
     screen; the starter cards carry the opening screen. Overrides the grid !important
     above until the canvas has messages. Targets both .aios-canvas (reference) and
     #aiosCanvas (Gallea/Tompkins). */
  .aios-canvas:not(.has-messages) .aios-dock .chips-row,
  .aios-canvas:not(.has-messages) .aios-dock .chips-label,
  #aiosCanvas:not(.has-messages) .aios-dock .chips-row,
  #aiosCanvas:not(.has-messages) .aios-dock .chips-label { display: none !important; }
  .aios-dock .chips-label {
    font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--muted, #6B7280); text-align: center; margin: 2px 0 6px;
  }
  /* AMENDMENT 19 TASK 11: HOLD THE FOLLOW-UP LABEL'S LINE THROUGH COMPOSING.
     The label renders only for real contextual follow-ups, which arrive when the
     answer settles, so renderChips flipped it from hidden to shown in the middle
     of a turn and the dock grew a second time under the visitor. It is now
     RESERVED rather than removed once the conversation has messages: the line
     keeps its space and only its ink appears, so the follow-up region reaches
     its final height once, when chat begins, and never moves again while an
     answer streams. Outside chat the rule above still removes it entirely, so
     the welcome screen is unchanged. */
  .aios-canvas.has-messages .aios-dock .chips-label[hidden],
  #aiosCanvas.has-messages .aios-dock .chips-label[hidden] {
    display: block; visibility: hidden;
  }

  /* "Tap to speak" caption (item 3 / 2.9): identical muted sentence-case caption
     with a consistent fixed gap directly beneath the orb, uniform on every tenant
     (overrides the Tompkins discovery-mic-label red/uppercase treatment). */
  .orb-caption {
    font-size: 13px !important; font-weight: 500 !important; color: var(--muted, #6B7280) !important;
    text-align: center; text-transform: none !important; letter-spacing: 0.01em !important;
    margin: 10px 0 0 !important;
  }
  .aios-canvas.has-messages .orb-caption, #aiosCanvas.has-messages .orb-caption { display: none; }

  /* 2.3 no-orphan: balanced line breaking on greetings + toggle headings. */
  .aios-welcome, .discovery-welcome, .toggle-headline, .toggle-subhead { text-wrap: balance; }

  /* 3.1 (corrected): the persona line is a subheader INSIDE the AiOS choice card,
     directly beneath the card title. It inherits the card's own text colour so it
     reads correctly on both a filled card (light text) and an outline card (dark). */
  .toggle-card-persona { font-size: 13.5px; font-weight: 700; margin: -6px 0 14px; letter-spacing: 0.01em; color: inherit; opacity: 0.96; text-wrap: balance; }

  /* 2.7 navbar prominence (revised per override): scale the whole bar system up
     ~20% honestly, type + icons + logos + inter-item gaps + horizontal padding +
     bar height together, so density matches the pre-scale look but larger. The
     earlier zoom:1.2 scaled the elements but compressed the bar's coordinate space,
     so items grew while the room between them shrank and the bar read condensed.
     Shared classes, so one core block reaches all three tenants. */
  .navbar {
    min-height: 82px;
    padding-top: 14px; padding-bottom: 14px;
    padding-left: clamp(24px, 2.4vw, 40px); padding-right: clamp(24px, 2.4vw, 40px);
    gap: 20px;
    letter-spacing: 0.02em;
  }
  .navbar-left, .navbar-right { gap: 20px; }
  .navbar-logo, .navbar-ibm { height: 38px; }
  .navbar-link, .navbar-login { font-size: 14px; }
  /* NEW LAW: never drop nav items to satisfy no-overflow. reference carries the most
     items (10 links + logo), so the 20% type scale is fitted at 1440 by tightening
     gaps (20px) and tracking (0.02em), not by hiding links. Measured clear at 1440
     with all items present, no overflow, no collision. Fewer-item tenants have room
     to spare at these same values. Standing logo rule: clear space >= half the mark
     height (38 -> >=19px): bar 82px leaves ~22px above/below, left padding >=24px,
     and this margin holds the first nav item off the logo on the right. */
  .navbar-logo { margin-right: 22px; }
  .utility-strip { font-size: 13px; }

  /* 2.5 submenu dropdown (real sub-items only; opens on click). */
  .navbar-link[data-submenu] { cursor: pointer; }
  .nav-submenu {
    display: none; position: absolute; top: calc(100% + 12px); left: 0; z-index: 60;
    min-width: 240px; background: #fff; border: 1px solid var(--line, #e5e7eb); border-radius: 10px;
    box-shadow: 0 18px 48px rgba(15,23,42,0.16); padding: 6px; text-align: left;
  }
  .nav-submenu.open { display: block; }
  /* WF49: remove the dropdown carets and reveal the subtab panel on hover, below the
     item (desktop only; nav-links are hidden at phone width, and the mobile drawer has
     no classic links per N14). Click still toggles .open for touch/keyboard. */
  .nav-chev { display: none !important; }
  .navbar-link[data-submenu]:hover > .nav-submenu { display: block; }
  .nav-submenu-item {
    display: block; width: 100%; text-align: left; background: none; border: none; cursor: pointer;
    font-family: inherit; font-size: 13.5px; font-weight: 500; color: var(--ink, #1a2330);
    letter-spacing: normal; text-transform: none; padding: 9px 12px; border-radius: 6px; white-space: nowrap;
  }
  .nav-submenu-item:hover { background: var(--aios-blue-bg, rgba(0,0,0,0.05)); color: var(--aios-blue, var(--accent)); }

  /* Answer canvas width (override): the assistant answer spans the full shared
     content column so its edges align flush with the composer field. The answer
     bubble was capped at ~76%, rendering narrower than the composer and cramping
     the text. .aios-container already resolves to --content-box with the same
     gutter as the composer, so width:100% here makes the two edges coincide.
     Standard body typography is kept; nothing in an answer renders below it.
     User utterances stay as right-aligned bubbles. All tenants, one core rule.
     width:100% + border-box makes the block span the column deterministically for
     short and long answers alike (align-self:stretch alone left short answers
     hugging their content); border-box keeps padding + border inside the column.
     .chat-messages must be full width too: on reference the flex column shrink-wrapped
     to its widest child, so a short answer's containing block collapsed and 100%
     resolved against a few pixels. width:100% on the column pins it to the canvas. */
  .chat-messages { width: 100%; box-sizing: border-box; }
  .msg-aios { max-width: 100%; width: 100%; box-sizing: border-box; align-self: stretch; font-size: 16px; line-height: 1.65; }
  /* Nothing in an answer's reading copy renders below the reading size. */
  .msg-aios p, .msg-aios li { font-size: inherit; }
  .msg-aios h5.msg-h { font-size: 16px; }

  /* 2.14 seeded history threads carry a small muted "Sample" tag and are
     non-interactive (illustrative). */
  .history-sample-tag { display: inline-block; margin-left: 8px; font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted, #6B7280); background: var(--line-soft, #f1f3f5); border-radius: 4px; padding: 1px 6px; vertical-align: middle; }
  .history-item-sample { cursor: default; }
  .history-item-sample:hover { background: transparent; padding-left: 16px; }

  /* 2.10 opening-screen density: tighten the greeting -> orb -> starter-card rhythm
     so the starter grid rises and takes visual priority. Welcome (pre-chat) only. */
  .aios-canvas:not(.has-messages) .aios-welcome,
  #aiosCanvas:not(.has-messages) .discovery-welcome { margin-bottom: clamp(8px, 1.4vh, 16px) !important; }
  .aios-canvas:not(.has-messages) .orb-wrapper-large,
  #aiosCanvas:not(.has-messages) .orb-wrapper { margin: 0 0 8px !important; }
  .aios-canvas:not(.has-messages) .orb-wrapper-large .orb,
  #aiosCanvas:not(.has-messages) .orb-wrapper .orb { width: clamp(100px, 13vh, 132px); height: clamp(100px, 13vh, 132px); }
  .orb-caption { margin-bottom: 14px !important; }
  .aios-canvas:not(.has-messages) .welcome-actions,
  #aiosCanvas:not(.has-messages) .welcome-actions { margin-top: 4px !important; }

  /* ===== TOGGLE HEADING BLOCK (item 4): spans exactly the two-card width, clamp-
     scaled, uniform across tenants, stacks at 390. Card width 384 + 32 gap = 800,
     so the heading block max-width 800 matches the two cards. Targets both toggle
     container classes (reference .toggle-cards, Tompkins .toggle-cards-row). */
  .toggle-cards, .toggle-cards-row { gap: 32px !important; justify-content: center; flex-wrap: wrap; }
  .toggle-cards > .toggle-card, .toggle-cards-row > .toggle-card { width: 384px !important; }
  .toggle-headline, .toggle-subhead {
    width: 100%; max-width: 800px; margin-left: auto !important; margin-right: auto !important;
    box-sizing: border-box;
  }
  .toggle-headline { font-size: clamp(24px, 3.6vw, 36px) !important; }
  .toggle-subhead { font-size: clamp(15px, 1.7vw, 20px) !important; }
  @media (max-width: 767px) {
    .toggle-cards, .toggle-cards-row { flex-direction: column; align-items: center; }
    .toggle-cards > .toggle-card, .toggle-cards-row > .toggle-card { width: 100% !important; max-width: 384px; }
    .toggle-headline, .toggle-subhead { max-width: 384px; }
  }

  /* ===== ATTRIBUTION TEXT LINE (chat, text-only; also beneath the toggle marks) =====
     One centred line, muted. At 1200px and up it sits on a single line (10.5px,
     widened to the composer width); below 1200px it wraps naturally, centred, and
     never bleeds its container. */
  .aios-dock .aios-attribution { max-width: none; }
  .aios-attribution-line {
    font-size: 11px; line-height: 1.45; color: var(--muted, #6B7280);
    text-align: center; margin: 0 auto; max-width: var(--content-box, 1200px);
    letter-spacing: 0.01em; padding: 0 var(--content-gut, 20px);
    box-sizing: border-box; overflow-wrap: break-word;
  }
  @media (min-width: 1200px) {
    .aios-attribution-line { font-size: 10.5px; white-space: nowrap; max-width: 100%; }
  }
  .aios-attribution-marks + .aios-attribution-line { margin-top: 8px; white-space: normal; }
  /* Gallea wordmark rendered inline in the chat attribution line, at text height,
     baseline-aligned (1.1). Inverts to white on a dark surface. */
  .aios-attribution-line .attr-gallea-inline {
    height: 1em; width: auto; display: inline-block; vertical-align: baseline;
    position: relative; top: 0.14em; margin: 0 1px;
  }
  .aios-attribution-line.on-dark .attr-gallea-inline { filter: brightness(0) invert(1); }

  /* ===== ATTRIBUTION LOCKUP (toggle screen + footer panel only): Gallea + IBM mark ===== */
  .aios-attribution-marks {
    display: flex; align-items: center; justify-content: center;
    gap: 18px; padding: 4px 0 2px;
  }
  .aios-attribution-marks .attr-mark { display: block; width: auto; height: auto; }
  .aios-attribution-marks .attr-mark-gallea { height: 22px; }
  .aios-attribution-marks .attr-mark-ibm { height: 26px; }   /* 20-28px range */
  .aios-attribution-marks.on-dark .attr-mark-gallea { filter: brightness(0) invert(1); }
  @media (max-width: 767px) {
    .aios-attribution-marks { flex-direction: column; gap: 8px; }
  }

  /* ===== AMENITIES (NI-7): a photo row (when the KB has images) + a checkmark
     checklist of every amenity. No per-amenity icons (reverses WF23). ===== */
  .amenity-summary { font-size: 14px; line-height: 1.55; color: var(--ink-soft, #3F4451); margin: 0 0 10px; }
  .amenity-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 6px; }
  .amenity-tile { margin: 0; border-radius: 12px; overflow: hidden; }
  .amenity-tile-photo { background: #fff; border: 1px solid var(--line-soft, #f1f3f5); box-shadow: var(--shadow-sm, 0 1px 2px rgba(15,23,42,0.04)); }
  .amenity-tile-photo img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; cursor: zoom-in; }
  .amenity-tile-photo figcaption { padding: 8px 10px; font-size: 12.5px; font-weight: 600; color: var(--ink-soft, #3F4451); }
  /* Amendment 13 WS-U2: the placeholder amenity tile is REMOVED, not restyled.
     It rendered a hatched empty box for every amenity the source named
     but held no photograph of, so a building with twelve amenities and two
     photos showed ten fake cards. Placeholder cards are banned: a named amenity
     with no photo belongs in the bulleted checklist, which is where it now
     renders. The rule is here as well as in cards.js so a future edit cannot
     revive the tile by finding its styles still waiting. */
  .amenity-photo-row { margin-bottom: 12px; }
  .amenity-checklist { list-style: none; margin: 4px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 4px 20px; }
  .amenity-checklist li { display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; font-weight: 600; color: var(--ink-soft, #3F4451); line-height: 1.45; padding: 4px 0; }
  .amenity-check { color: var(--aios-blue, var(--accent)); font-weight: 800; flex-shrink: 0; }
  @media (max-width: 767px) { .amenity-tiles { grid-template-columns: repeat(2, 1fr); } .amenity-checklist { grid-template-columns: 1fr; } }

  /* 2.15 footer bottom row: one LEFT-aligned row -> Powered-by lockup, faint 1px
     vertical divider spanning the row height, then the IBM trademark text. Stacks
     at 390 with the divider omitted. */
  /* CD-1/CD-3/NI-5: the footer lockup stacks LEFT-aligned to the footer text margin:
     a row of [marks + full token], then Privacy/Terms/Accessibility beneath. Bottom
     padding keeps it clear of the viewport bottom. */
  .aios-footer-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin-top: 16px; padding-top: 14px; padding-bottom: 26px; border-top: 1px solid var(--line-soft, #f1f3f5); }
  .aios-footer-lockup { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
  .aios-footer-lockup .aios-attribution-marks { justify-content: flex-start; flex-direction: row; flex: 0 0 auto; margin: 0; padding: 0; }
  .aios-footer-lockup .aios-attribution-line { text-align: left; max-width: 640px; margin: 0; }
  .aios-footer-legal { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 11.5px; color: var(--muted, #6B7280); }
  .aios-footer-legal button { background: none; border: none; font-family: inherit; font-size: 11.5px; color: var(--muted, #6B7280); cursor: pointer; padding: 0; }
  .aios-footer-legal button:hover { text-decoration: underline; }
  .aios-footer-divider { width: 1px; align-self: stretch; min-height: 28px; background: var(--line, #e5e7eb); flex: 0 0 auto; }
  @media (max-width: 767px) {
    .aios-footer-lockup { flex-direction: column; align-items: flex-start; gap: 10px; }
    .aios-footer-divider { display: none; }
  }
  /* 2.16 newsletter: real form on the toggle screen, prompt button in AiOS chat. */
  .aios-newsletter-chat { display: none; }
  /* N9 / F10 / Rule 15: on AiOS conversation surfaces the classic footer's account +
     login surfaces are removed (Buyer Login, Create Account); they remain only on the
     opening-page classic footer (body:not(.aios-active)). The newsletter form becomes
     the in-chat prompt button below. */
  body.aios-active [data-aios-site-footer] .footer-account-link { display: none !important; }
  body.aios-active [data-aios-site-footer] .footer-news-row { display: none !important; }
  body.aios-active [data-aios-site-footer] .aios-newsletter-chat {
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--aios-blue, var(--accent)); color: #fff; border: none; border-radius: 8px;
    padding: 10px 16px; font-family: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
    margin-top: 8px; max-width: 260px;
  }
  body.aios-active [data-aios-site-footer] .aios-newsletter-chat:hover { background: var(--aios-blue-dark, var(--accent-dark)); }

  /* 2-M / 2-T / N11: on mobile the footer panel carries ONE unified collapsed
     attribution unit, separated from the site footer content by a hairline. The
     P2-9 raster "Powered by" strip and any duplicate attribution are hidden so
     exactly one attribution block renders. */
  @media (max-width: 767px) {
    .footer-aios-strip { display: none !important; }
    .aios-footer-brand-mobile {
      display: flex !important; flex-direction: column; align-items: center;
      margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line, #e5e7eb);
    }
    .aios-footer-brand-mobile .aios-footer-divider { display: none; }
    /* D2 (decisions.md): clear space around the tenant wordmark in the footer sheet,
       at least half the wordmark height on all sides. The source site crowds it; this
       build deliberately does not replicate that crowding. */
    body.aios-active [data-aios-site-footer] #footerLogo,
    body.aios-active [data-aios-site-footer] .footer-logo-small,
    body.aios-active [data-aios-site-footer] .footer-brand-logo { margin: 14px 0 !important; display: inline-block; }
  }

  /* WP10 / 2-M / D2 (CARRIES-TO-MOBILE): the same wordmark clear space holds on
     desktop (>=768px), so the black footer text never crowds the reference wordmark at
     any width. */
  body.aios-active [data-aios-site-footer] #footerLogo,
  body.aios-active [data-aios-site-footer] .footer-logo-small,
  body.aios-active [data-aios-site-footer] .footer-brand-logo { margin: 16px 0; display: inline-block; }

  /* WF40: give Privacy / Terms / Accessibility a little more breathing room above,
     on every legal-link row (gateway foot, footer sheet, drawer, tenant footers). */
  .m-gw-legal, .side-panel-legal, .aios-footer-legal, .footer-legal-links { margin-top: 14px; }

  /* IBM trademark legal line inside the footer panel */
  .aios-ibm-trademark {
    font-size: 10.5px; line-height: 1.5; color: var(--muted, #6B7280);
    max-width: 640px; margin: 0; padding: 0; text-align: left;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }

  /* mobile: overlays already full-screen; keep plate readable */
  @media (max-width: 767px) {
    .plate { padding: 18px 16px 22px; }
    .plate-grid { grid-template-columns: 1fr; }
    .plate-owner-name { font-size: 22px; }
    .chrome-overlay-body { padding: 18px 14px 48px; }
  }

  /* ===== APP-SHELL SCROLL MODEL (core, all tenants) =====
     Injected here (not in styles.css) because the Gallea and Tompkins shells do
     not load the core stylesheet. In AiOS mode the page never scrolls, the app is
     exactly the viewport tall, the conversation feed is the only scroll container,
     and the site footer lives behind the footer toggle as a slide-up sheet. The
     !important rules sit on top of each shell's own layout so the model is uniform. */
  html.aios-active, body.aios-active { overflow: hidden !important; }
  /* Budget the height with flexbox rather than a fixed calc, so the chat column is
     exactly 100dvh minus the real navbar/chrome minus the full composer + attribution
     dock, whatever their measured heights. The dock never clips and the attribution's
     bottom edge is the viewport bottom. Uniform across tenants (reference uses
     .aios-canvas, Gallea/Tompkins use #aiosCanvas). */
  body.aios-active {
    height: calc(100vh / var(--app-zoom, 1));
    height: calc(100dvh / var(--app-zoom, 1));
    display: flex; flex-direction: column;
  }
  body.aios-active .navbar, body.aios-active .utility-strip { flex: 0 0 auto; }
  body.aios-active #aiosCanvas, body.aios-active .aios-canvas {
    flex: 1 1 auto; min-height: 0; height: auto !important;
    display: flex; flex-direction: column;
  }
  body.aios-active .chat-scroll, body.aios-active #chatScroll { flex: 1 1 0; min-height: 0; }
  body.aios-active .aios-dock { flex: 0 0 auto; }
  .chat-scroll, #chatScroll { overscroll-behavior: contain; }
  .aios-dock { position: relative; }

  /* Site footer -> slide-up sheet, AiOS mode only (toggle screen + traditional mode
     keep their normal footers). Scrolls within itself; scroll never bleeds. */
  body.aios-active [data-aios-site-footer] {
    position: fixed !important;
    left: 0; right: 0; bottom: 0; top: auto !important;
    z-index: 96;
    max-height: 82dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    transform: translateY(100%);
    transition: transform 0.32s var(--ease, cubic-bezier(.2,.65,.25,1));
    box-shadow: 0 -14px 44px rgba(15, 23, 42, 0.20);
  }
  body.aios-active [data-aios-site-footer]:empty {
    min-height: 48px;
    background: #fff;
    pointer-events: none;
  }
  body.aios-active.footer-sheet-open [data-aios-site-footer] { transform: translateY(0) !important; }
  .aios-footer-sheet-backdrop { position: fixed; inset: 0; z-index: 95; background: rgba(0,0,0,0.35); display: none; }
  body.aios-active.footer-sheet-open .aios-footer-sheet-backdrop { display: block; }
  .aios-footer-sheet-close {
    position: sticky; top: 0; z-index: 2; display: none;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 6px 18px 10px; background: var(--card, #fff); border-bottom: 1px solid var(--line-soft, #eee);
    font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted, #6B7280);
  }
  body.aios-active [data-aios-site-footer] .aios-footer-sheet-close { display: flex; }
  /* 6.F: grab handle + header row + rounded top corners on the sheet. */
  .aios-footer-sheet-handle {
    width: 40px; height: 5px; border-radius: 999px; background: var(--line, #d5d9df);
    margin: 6px auto 4px; flex: 0 0 auto; cursor: pointer;
  }
  .aios-footer-sheet-headrow { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  body.aios-active [data-aios-site-footer] {
    border-top-left-radius: 16px; border-top-right-radius: 16px; overflow-x: hidden;
    /* MB-R3 #2: the classic footer carries a large top padding (reference: 48px). Inside
       the slide-up sheet that padding sat ABOVE the sticky "Site Plan" header, so on
       scroll the footer content showed through that gap and the sticky title appeared to
       float over content. Zero the sheet's top padding so the sticky header sits flush
       at the sheet top and all footer content scrolls cleanly beneath it. */
    padding-top: 0 !important;
  }
  .aios-footer-sheet-close button {
    background: none; border: none; cursor: pointer; color: var(--ink, #1A1A1A);
    width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    font-size: 18px; line-height: 1;
  }
  .aios-footer-sheet-close button:hover { background: var(--line-soft, #f1f3f5); }

  /* Footer toggle: slim control at the dock's bottom edge, beside the attribution
     (so the attribution keeps the screen's bottom edge). AiOS mode only. */
  .aios-footer-toggle { display: none; }
  /* T4 (2026-07-14): the Site Plan control is present the moment the AiOS chat
     surface loads (body.aios-active), before any user message, and persists
     unchanged through the conversation. It stays absent on the gateway/toggle
     screen, which never carries body.aios-active. Supersedes the earlier G3 rule
     that gated it behind .has-messages. */
  /* AMENDMENT 19 TASK 9: the Site Plan control moves to the BOTTOM LEFT so it
     and Task 8's "Traditional Website" link hold opposite corners
     without overlap. Only the horizontal anchor changed; every other property
     here is the one it already had. */
  body.aios-active .aios-footer-toggle {
    display: inline-flex; align-items: center; gap: 6px;
    position: absolute; left: 14px; bottom: 9px; z-index: 3;
    background: none; border: none; cursor: pointer; font-family: inherit;
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--muted, #6B7280); padding: 4px 10px; border-radius: 999px;
    transition: color 0.15s ease, background 0.15s ease;
  }
  body.aios-active .aios-footer-toggle:hover { color: var(--aios-blue, var(--accent)); background: var(--aios-blue-bg, rgba(0,0,0,0.04)); }

  /* AMENDMENT 19 TASK 8: "Traditional Website", bottom right, in the
     SAME font, colour and size as the Site Plan control, and underlined. Every
     type property below is copied from the toggle rule above deliberately, so
     the two corners read as one pair; the only differences are the corner it
     anchors to and the underline the owner asked for. */
  .aios-traditional-link { display: none; }
  body.aios-active .aios-traditional-link {
    display: inline-flex; align-items: center;
    position: absolute; right: 14px; bottom: 9px; z-index: 3;
    background: none; border: none; cursor: pointer; font-family: inherit;
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--muted, #6B7280); padding: 4px 10px; border-radius: 999px;
    text-decoration: underline; text-underline-offset: 2px;
    transition: color 0.15s ease, background 0.15s ease;
  }
  body.aios-active .aios-traditional-link:hover { color: var(--aios-blue, var(--accent)); background: var(--aios-blue-bg, rgba(0,0,0,0.04)); }
  .aios-footer-toggle svg { transition: transform 0.2s ease; }
  body.footer-sheet-open .aios-footer-toggle svg { transform: rotate(180deg); }
  @media (max-width: 767px) {
    /* MC5: the "[Tenant] Site Plan" control and the collapsed attribution line share
       ONE row at the foot of the conversation dock, in smaller type, to reclaim
       canvas. The composer takes the full width above them; the two controls wrap
       onto a single centred row beneath. The version stays in the composer bar (MC8),
       so the attribution line carries no version prefix. */
    body.aios-active .aios-dock {
      display: flex; flex-direction: row; flex-wrap: wrap;
      align-items: center; justify-content: center; column-gap: 10px; row-gap: 0;
    }
    body.aios-active .aios-dock > .input-bar-wrap,
    body.aios-active .aios-dock > .orb-wrapper-compact,
    body.aios-active .aios-dock > .chips-label,
    body.aios-active .aios-dock > .chips-row { flex: 0 0 100%; width: 100%; }
    /* AMENDMENT 19 TASKS 8 AND 9: on a narrow viewport there are no corners to
       hold, so the two controls share ONE row in a readable order: the Site
       Plan control, then the Return link, then the attribution (order 6). Both
       carry order 5 and flex falls back to DOM order between them, which is the
       order they are appended in, so the attribution rule below is untouched.
       The left anchor is released alongside the right one, because Task 9 moved
       the toggle's desktop anchor to the left. */
    body.aios-active .aios-footer-toggle,
    body.aios-active .aios-traditional-link {
      position: static !important; left: auto !important; right: auto !important; bottom: auto !important;
      order: 5; margin: 4px 0 0 !important;
      font-size: 9px !important; padding: 3px 6px !important;
    }
    body.aios-active .aios-dock .aios-attribution { order: 6; margin: 0; flex: 0 0 auto; width: auto; }
    /* MB-R3 #3: reference' styles.css gives .powered-by-gallea a 6px/14px vertical pad,
       which inflated the dock attribution block to ~41px (vs ~25px on the Gallea/
       Tompkins shells that lack it), so it towered over the ~18px Site Plan control on
       the shared MC5 row (misaligned) and left dead space beneath. Zero that vertical
       padding on the mobile dock so the attribution collapses to its single line and
       centres on the same row as the Site Plan control, uniform across all three. */
    body.aios-active .aios-dock .powered-by-gallea { padding-top: 0 !important; padding-bottom: 0 !important; }
    body.aios-active .aios-dock .attr-unit { gap: 2px; margin: 0; }
    body.aios-active .aios-dock .attr-collapsed-label { font-size: 9px !important; }
  }

  /* 2.12: settings as one stacked page. Tabs hidden, every panel shown stacked
     (the !important beats the inline display:none showSettingsTab sets on open),
     each under a 13px muted uppercase section heading. Uniform on all tenants. */
  #settingsOverlay .settings-panel { max-width: 760px; }
  #settingsOverlay .settings-tabs { display: none !important; }
  #settingsOverlay #settings-language,
  #settingsOverlay #settings-accessibility,
  #settingsOverlay #settings-general { display: block !important; }
  #settingsOverlay .settings-section-head {
    font-size: 13px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--muted, #6B7280); margin: 26px 0 14px;
  }
  #settingsOverlay .settings-section-head:first-of-type { margin-top: 6px; }

  /* 4.2: manufacturer's nameplate, ported pixel-faithful from the owner-approved vF
     source. Two stacked navy plates with white line-work + condensed lettering, then
     the document blocks. Oswald with a condensed fallback (no external @import, to
     keep the standalone file offline-safe). */
  /* Plate ground + accent default to the tenant's primary brand colour token
     (--aios-blue, set per tenant), never a fixed blue. A tenant that ships an
     explicit plate palette (window.AIOS_PLATE.navy/blue, injected inline by
     renderPlateBody) still overrides these, so a configured tenant is unchanged
     and an unconfigured one inherits its own brand colour, not another tenant's. */
  .aios-vplate { --vp-navy: var(--aios-blue, var(--accent)); --vp-blue: var(--aios-blue, var(--accent)); --vp-fill: #F0F0F0; --vp-border: #E0E0E0; --vp-ink: #fff;
    max-width: 680px; margin: 0 auto; color: #333; font-size: 13px; line-height: 1.35; }
  .aios-vplate .vplate-set { width: 100%; margin: 6px 0 20px; }
  /* Amendment 9 D.5 (layout only): the plate renders in a neutral wide
     grotesque on every tenant. The previous 'Oswald','Arial Narrow' stack
     resolved to condensed Arial Narrow wherever no shell font overrode it
     (reference), which read as a squished plate next to the Choice render. */
  .aios-vplate .vplate { background: var(--vp-navy); border-radius: 12px; padding: 12px;
    color: var(--vp-ink); font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Roboto, Arial, sans-serif; box-sizing: border-box; }
  .aios-vplate .vplate + .vplate { margin-top: 14px; }
  .aios-vplate .vplate__outer { border: 2.5px solid var(--vp-ink); border-radius: 8px; padding: 4px; }
  .aios-vplate .vplate__frame { border: 1px solid var(--vp-ink); border-radius: 5px; padding: 22px 28px 0; }
  .aios-vplate .vplate__frame--secondary { padding: 0 28px 0; }
  .aios-vplate .vplate__wordmark { font-weight: 700; font-size: 34px; line-height: 1; text-align: center; letter-spacing: .01em; }
  .aios-vplate .tm { font-size: 38%; vertical-align: 30%; font-weight: 600; }
  .aios-vplate .vplate__mfr { font-weight: 600; font-size: 12px; letter-spacing: .34em; text-transform: uppercase; text-align: center; margin-top: 10px; }
  .aios-vplate .vplate__entity { font-weight: 500; font-size: 13px; letter-spacing: .22em; text-transform: uppercase; text-align: center; margin: 3px 0 18px; }
  .aios-vplate .vplate__row { display: flex; align-items: center; margin: 8px 0; gap: 14px; }
  .aios-vplate .vplate__key { flex: 0 0 24%; font-weight: 600; font-size: 13px; letter-spacing: .10em; text-transform: uppercase; }
  .aios-vplate .vplate__box { flex: 1; border: 1.2px solid var(--vp-ink); padding: 5px 14px; text-align: center; font-weight: 600; font-size: 15px; letter-spacing: .10em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .aios-vplate .vplate__box--tall { font-size: 17px; letter-spacing: .14em; padding: 7px 14px; }
  .aios-vplate .vplate__row--sn .vplate__key { flex: 0 0 10%; }
  .aios-vplate .vplate__statement { margin: 16px 2px 14px; font-weight: 600; font-size: 13px; letter-spacing: .06em; text-transform: uppercase; line-height: 1.5; }
  .aios-vplate .vplate__strip { border-top: 1px solid var(--vp-ink); margin: 16px -28px 0; padding: 10px 28px 15px; display: flex; justify-content: space-between; align-items: center; font-weight: 600; font-size: 14px; letter-spacing: .22em; text-transform: uppercase; }
  .aios-vplate .vplate__strip-box { border: 1.2px solid var(--vp-ink); padding: 2px 14px; font-size: 12px; letter-spacing: .10em; }
  .aios-vplate .vplate__header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--vp-ink); margin: 0 -28px; padding: 13px 28px; }
  .aios-vplate .vplate__header-mark { font-weight: 700; font-size: 20px; letter-spacing: .01em; }
  .aios-vplate .vplate__header-box { border: 1.2px solid var(--vp-ink); padding: 2px 14px; font-weight: 600; font-size: 12px; letter-spacing: .10em; text-transform: uppercase; }
  .aios-vplate .vplate__intro { font-weight: 600; font-size: 13px; letter-spacing: .06em; text-transform: uppercase; line-height: 1.5; margin: 16px 2px 6px; }
  .aios-vplate .vplate__components { margin: 8px 0 16px; }
  .aios-vplate .vplate__component { display: flex; align-items: baseline; gap: 16px; padding: 8px 2px; }
  .aios-vplate .vplate__component + .vplate__component { border-top: 1px solid rgba(255,255,255,.55); }
  .aios-vplate .vplate__component-name { flex: 0 0 40%; font-weight: 600; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; }
  .aios-vplate .vplate__component-version { font-weight: 400; font-size: 10px; letter-spacing: .10em; text-transform: uppercase; color: var(--vp-fill); margin-top: 3px; }
  .aios-vplate .vplate__component-fn { flex: 1; font-weight: 400; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--vp-fill); line-height: 1.45; }
  /* vF6 secondary-plate sections (Built by / Direct contact / legal), rendered
     inside the dark plate exactly like the source, full-bleed hairline rules. */
  .aios-vplate .vplate__section { border-top: 1px solid var(--vp-ink); margin: 0 -28px; padding: 12px 28px 0; }
  .aios-vplate .vplate__section-label { font-weight: 600; font-size: 13px; letter-spacing: .18em; text-transform: uppercase; color: var(--vp-ink); margin-bottom: 6px; }
  .aios-vplate .vplate__prose { font-family: 'Inter', system-ui, sans-serif; font-weight: 400; font-size: 12px; line-height: 1.55; color: var(--vp-fill); margin: 0 2px 14px; text-transform: none; letter-spacing: 0; }
  .aios-vplate .vplate__contacts { margin: 2px 0 14px; }
  .aios-vplate .vplate__contact { display: flex; align-items: baseline; gap: 16px; padding: 6px 2px; }
  .aios-vplate .vplate__contact + .vplate__contact { border-top: 1px solid rgba(255,255,255,.55); }
  .aios-vplate .vplate__contact-key { flex: 0 0 24%; font-weight: 600; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--vp-ink); }
  .aios-vplate .vplate__contact-val { font-family: 'Inter', system-ui, sans-serif; flex: 1; font-weight: 400; font-size: 12px; letter-spacing: .04em; color: var(--vp-fill); }
  .aios-vplate .vplate__contact-val a { color: var(--vp-ink); text-decoration: underline; }
  .aios-vplate .vplate__legal { font-family: 'Inter', system-ui, sans-serif; font-weight: 400; font-size: 10px; line-height: 1.5; color: var(--vp-fill); opacity: .85; margin: 0 2px 14px; text-transform: none; letter-spacing: 0; }
  .aios-vplate .vplate__endline { border-top: 1px solid var(--vp-ink); margin: 0 -28px; padding: 10px 28px 15px; font-weight: 600; font-size: 12px; letter-spacing: .18em; text-transform: uppercase; text-align: center; }

  /* 4.2 legal: lead paragraph + acceptable-use list ported from the vF User Notice. */
  .legal-doc .legal-lead { margin: 0 0 18px; color: var(--ink-soft, #3a4250); line-height: 1.6; font-size: 14px; }
  .legal-doc .legal-list { margin: 8px 0 6px; padding-left: 20px; }
  .legal-doc .legal-list li { margin-bottom: 6px; line-height: 1.55; color: var(--ink-soft, #3a4250); }

  /* ============================================================
     PHASE 6 MOBILE (<=767px): opening-screen hierarchy, one core
     block for all three tenants (shared selectors, so the Gallea
     and Tompkins bespoke shells inherit it too). 6.P: the composer
     is the dominant control. 6.C: starter cards become full-width
     list rows, icon-left, title-only. 6.D: suggestion chips stack
     full-width. Starter rows and chips read visually SECONDARY to
     the composer (one step down in type, muted, hairline, no accent
     fills). Mobile only; desktop hierarchy is untouched.
     ============================================================ */
  @media (max-width: 767px) {
    /* 6.C greeting: clamp to 16-18px over balanced lines. */
    #welcomeHeader.aios-welcome, #welcomeHeader.discovery-welcome,
    .discovery-welcome, .aios-welcome {
      font-size: clamp(16px, 4.4vw, 18px) !important;
      line-height: 1.4 !important; text-wrap: balance;
    }
    /* 6.C + G5 orb: enlarged now the "Tap to speak" caption is retired, so the orb
       reads as the primary voice affordance on the opening screen. */
    #aiosCanvas:not(.has-messages) .orb-wrapper .orb,
    .aios-canvas:not(.has-messages) .orb-wrapper-large .orb {
      width: 88px !important; height: 88px !important;
    }

    /* 6.P COMPOSER PRIMACY: dominant control, one visual step above
       everything else. Input row at least a starter row tall (52px),
       placeholder at full body size, mic and send scaled to match. */
    .aios-dock .composer {
      border-width: 2px !important;
      border-radius: 20px !important;
      box-shadow: 0 6px 20px rgba(15,23,42,0.16) !important;
    }
    .aios-dock .composer .composer-input-row { padding: 10px 18px 0 !important; }
    .aios-dock .composer .input-text,
    .aios-dock .composer #messageInput {
      font-size: 16px !important; min-height: 28px;
      padding: 14px 0 10px !important;
    }
    .aios-dock .composer .input-mic,
    .aios-dock .composer .input-send {
      width: 44px !important; height: 44px !important; flex: 0 0 auto !important;
    }
    /* MC8: the version ("[Tenant] AiOS 2.4") stays INSIDE the composer bar on mobile,
       as small non-overpowering text on the composer rail (the model-tier pill
       placement on the Claude composer), freeing the attribution row (MC5). Overrides
       the earlier 6.E rule that hid it and moved it to a micro-line beneath. */
    .aios-dock .composer .composer-version {
      display: inline !important; font-size: 10px !important; font-weight: 500 !important;
      letter-spacing: 0.02em !important; color: var(--muted, #9aa0aa) !important;
      margin-right: auto !important; white-space: nowrap !important;
    }
    .aios-dock .aios-attribution-line { font-size: 8px !important; line-height: 1.5 !important; }

    /* MC14: the opening starters become a 2-col x 3-row grid of compact square-ish
       tiles so all 6 are visible without scrolling. Each tile is TITLE FIRST (top),
       icon BELOW, one-line title. Secondary + muted (hairline border, no accent fill)
       so they sit below the composer in the hierarchy. Overrides the earlier full-width
       list-row treatment and each shell's own card fill on mobile. */
    .welcome-actions {
      display: grid !important; grid-template-columns: 1fr 1fr !important; gap: 8px !important;
    }
    /* ...but never during a conversation. The display:grid !important above would
       otherwise beat the core has-messages hide (which carries no !important), so
       restate the in-chat hide with !important. reference' welcome-actions is a sibling
       of #welcomeHeader (not hidden by hideWelcome), so this is the rule that hides
       the starter rows once the answer canvas has messages. */
    .aios-canvas.has-messages .welcome-actions,
    #aiosCanvas.has-messages .welcome-actions { display: none !important; }
    .welcome-action {
      display: flex !important; flex-direction: column !important;
      align-items: stretch !important; justify-content: flex-start !important;
      gap: 7px !important; text-align: left !important;
      height: auto !important; max-height: none !important;
      min-height: 74px !important; padding: 12px 8px !important;
      background: #fff !important; border: 1px solid var(--line, #e5e7eb) !important;
      box-shadow: none !important; border-radius: 14px !important;
    }
    .welcome-action:hover { background: var(--aios-blue-bg, rgba(0,0,0,0.03)) !important; }
    /* N6/N8: neutralize the hover tint on touch; press feedback via :active only. */
    @media (hover: none) {
      .welcome-action:hover { background: #fff !important; }
      .welcome-action:active { background: var(--aios-blue-bg, rgba(0,0,0,0.05)) !important; }
      .chip:hover, .mobile-followups .chip:hover, .side-panel-nav-item:hover,
      .m-gw-legal button:hover, .attr-collapsed:hover, .m-gw-card:hover { background: transparent !important; }
    }
    /* Title on top (order 0), icon below (order 1); DOM order is icon-then-title. */
    .welcome-action-icon {
      order: 1 !important;
      margin: 0 !important; flex: 0 0 auto !important;
      align-self: flex-start !important;
      width: 30px !important; height: 30px !important; min-width: 30px !important;
      color: var(--aios-blue, var(--accent)) !important; background: none !important;
      display: flex !important; align-items: center !important; justify-content: center !important;
    }
    .welcome-action-icon:has(img) { background: none !important; }
    .welcome-action-icon svg { width: 24px !important; height: 24px !important; }
    .welcome-action-icon img { width: 100% !important; height: 100% !important; object-fit: contain; display: block; }
    .welcome-action-title {
      order: 0 !important;
      font-size: 11.5px !important; font-weight: 600 !important; letter-spacing: -0.01em !important;
      width: 100% !important; text-align: left !important;
      min-height: 2.4em !important; line-height: 1.2 !important;
      white-space: normal !important; overflow: visible !important; text-overflow: clip !important;
      color: var(--ink-soft, #3F4451) !important; margin: 0 !important;
    }
    .welcome-action-sub { display: none !important; }

    /* N6 / N8: touch has no hover, so the :hover tint otherwise sticks after a tap
       (reading as a stuck highlight, or a "double tap to activate"). On coarse
       pointers the rows/buttons render uniform at rest and only tint while actively
       pressed; a single tap activates. */
    .welcome-action, .chip, .m-gw-card, .side-panel-nav-item,
    .m-gw-pill, .attr-collapsed, button { -webkit-tap-highlight-color: transparent; }

    /* 6.D SUGGESTED NEXT STEPS: on mobile the follow-ups render in the
       conversation flow (.mobile-followups), not the dock. Stack them
       full-width, one per line, centred label with the sparkle, kicker
       (chips-label) above. Secondary, muted, no accent fill. Also cover
       the dock grid for safety. */
    /* In-chat, the dock chip strip is replaced by the .mobile-followups block
       inside the conversation, so hide the dock row/label once there are
       messages (belt-and-braces over the shells' own rule) to avoid a
       duplicated strip. Canvas class differs per shell. */
    .aios-canvas.has-messages .aios-dock .chips-row,
    .aios-canvas.has-messages .aios-dock .chips-label,
    #aiosCanvas.has-messages .aios-dock .chips-row,
    #aiosCanvas.has-messages .aios-dock .chips-label { display: none !important; }
    .aios-dock .chips-row { grid-template-columns: 1fr !important; gap: 8px !important; }
    .aios-dock .chips-row .chip { width: 100% !important; justify-content: center !important; text-align: center !important; }
    /* N19 follow-up chip redesign: stacked full-width, LEFT-aligned label, sparkle
       + kicker kept, but understated and smaller (secondary to the composer) and
       ALWAYS equal height (grid-auto-rows:1fr gives two-line parity: if one chip
       wraps, all three match its height). No accent fill/glow. */
    .mobile-followups { margin: 12px 0 4px; }
    .mobile-followups .chips-label { text-align: left; margin: 2px 2px 8px; font-size: 10.5px; font-weight: 800; letter-spacing: 0.06em; color: var(--muted, #6B7280); }
    .mobile-followups .chips-row,
    .mobile-followups .chips-row.in-chat {
      display: grid !important; grid-template-columns: 1fr !important;
      grid-auto-rows: 1fr !important; gap: 8px !important; align-items: stretch !important;
    }
    .mobile-followups .chip {
      width: 100% !important; height: 100% !important;
      justify-content: flex-start !important; text-align: left !important; gap: 10px !important;
      min-height: 44px !important; padding: 10px 16px !important;
      font-size: 13px !important; font-weight: 600 !important;
      color: var(--ink-soft, #3F4451) !important;
      background: #fff !important; border: 1px solid var(--line, #e5e7eb) !important;
      box-shadow: none !important; transform: none !important;
    }
    /* MC7: restore the follow-up chip star in the tenant accent (Gallea blue, reference
       blue, Tompkins red via --aios-blue) at +25% size; the chip layout is otherwise
       unchanged (equal height, left-aligned). */
    .mobile-followups .chip .chip-sparkle { color: var(--aios-blue, var(--accent)) !important; font-size: 1.25em !important; flex: 0 0 auto; }
    .mobile-followups .chip > span:last-child { text-align: left !important; }

    /* 6.K navbar collapses to a hamburger + logo: hide the links, login CTA, utility
       strip and any open submenu; the topline items live in the drawer instead. The
       hamburger is a 44px target. */
    .navbar .navbar-link, .navbar .navbar-login,
    .utility-strip, .nav-submenu { display: none !important; }
    .navbar-hamburger {
      display: inline-flex !important; align-items: center; justify-content: center;
      min-width: 44px; height: 44px;
    }
    /* drawer topline items (6.K): the navbar items injected into the side panel. */
    .side-panel-nav-browse {
      margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line-soft, #f1f3f5);
      display: flex; flex-direction: column;
    }
    .side-panel-nav-topline { font-size: 14px; }
    .side-panel-nav-dot {
      width: 6px; height: 6px; border-radius: 50%; background: var(--aios-blue, var(--accent));
      display: inline-block; margin: 0 9px; flex: 0 0 auto;
    }

    /* MC6 / MC10 / MC11: cross-tenant mobile rules that must reach ALL THREE shells.
       Only reference links engine/app/styles.css; Tompkins and Gallea use their own shell
       CSS, so these live here in the injected chrome (which reaches every tenant) and,
       loading last, authoritatively govern. */
    /* MC10: shorter AiOS mobile navbar (a plate.js desktop rule forced 82px). */
    .navbar { min-height: 46px !important; height: 46px !important; padding-top: 0 !important; padding-bottom: 0 !important; }
    .navbar-logo, .navbar-ibm { height: 24px !important; }
    /* MC6: breathing room around the docked composer (Claude iOS reference).
       MB4: a little MORE room between the last answer and the composer (padding-top up
       a notch, not excessive). MB3: bottom-align the Site Plan + attribution row tight
       to the screen bottom (padding-bottom trimmed to a hairline over the safe-area, so
       the row sits flush at the bottom edge with only a minimal gap beneath). Both are
       GLOBAL-MOBILE (all three tenants). */
    .aios-dock { padding-top: 22px !important; padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px)) !important; }
    .aios-container { padding-bottom: 16px !important; }
    /* MB-R3 #2: the side-panel drawer (New Chat / History / Settings / Traditional +
       the injected brand-lockup + legal footer) is taller than a short mobile viewport,
       and the Gallea/Tompkins shells sized it with 100vh (the LARGE viewport), so its
       bottom (the legal links) was cut off on all three tenants. Lock it to 100dvh, let
       it scroll INTERNALLY when the content is taller, and pad the foot past the home
       indicator so nothing is clipped. Global, all three shells. */
    .side-panel {
      height: 100dvh !important; max-height: 100dvh !important;
      overflow-y: auto !important; overscroll-behavior: contain;
      padding-bottom: env(safe-area-inset-bottom, 0px) !important;
    }
    /* MB-R3 #form-zoom: iOS zooms into ANY input/select/textarea whose font-size is
       below 16px on focus, and does not zoom back out, leaving the page stuck zoomed.
       The reg/contact form fields (styles.css .reg-field = 14px) and settings fields
       (13.5px) triggered it. Force every text-entry control to 16px on mobile so focus
       never zooms. Checkboxes/radios ignore font-size, so this only affects text entry. */
    input, select, textarea { font-size: 16px !important; }
    /* MC11: ~40% narrower answer-canvas cards across the shared carousel classes. */
    .property-cards-row > *, .amenity-cards > *, .gallery-grid > *,
    .property-card-wrap, .amenity-card, .gallery-thumb, .fp-card,
    .product-grid > *, .property-grid > *, .floorplan-grid > * {
      flex: 0 0 52vw !important; max-width: 52vw !important;
    }
  }

  /* ===== C2/G2/N11 unified collapsed attribution unit (mobile) =====
     One component on every mobile surface: Gallea logo + IBM Silver Partner CLEAN
     TEXT lockup (never the raster, N1), then a collapsed line with a chevron that
     expands the verbatim IBM sentence. Default collapsed. Desktop unaffected. */
  .attr-unit { display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; max-width: 100%; }
  .attr-marks { display: flex; align-items: center; justify-content: center; gap: 14px; }
  .attr-marks .attr-mark-gallea { height: 16px; width: auto; display: block; }
  .attr-unit.on-dark .attr-marks .attr-mark-gallea { filter: brightness(0) invert(1); }
  /* WF-IBM: official IBM lockup (2-line artwork) sized to optically match the Gallea
     wordmark beside it; colour comes from the src swap, never a CSS filter. */
  .attr-marks .attr-mark-ibm { height: 24px; width: auto; display: block; }
  .attr-ibm-lockup { display: inline-flex; flex-direction: column; align-items: flex-start; line-height: 1; color: var(--ink, #1A1A1A); }
  .attr-unit.on-dark .attr-ibm-lockup { color: #fff; }
  .attr-ibm-name { font-weight: 800; font-size: 15px; letter-spacing: 0.04em; font-family: 'Inter', system-ui, sans-serif; }
  .attr-ibm-tier { font-size: 8px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; margin-top: 2px; opacity: 0.82; }
  .attr-collapsed { display: inline-flex; align-items: center; gap: 5px; background: none; border: none; cursor: pointer; font-family: inherit; padding: 2px 4px; color: var(--muted, #6B7280); max-width: 100%; }
  .attr-unit.on-dark .attr-collapsed { color: rgba(255,255,255,0.82); }
  .attr-collapsed-label { font-size: 10.5px; line-height: 1.4; letter-spacing: 0.01em; }
  .attr-chevron { display: inline-flex; flex: 0 0 auto; }
  .attr-chevron svg { transition: transform 0.2s ease; }
  .attr-unit.attr-open .attr-chevron svg { transform: rotate(180deg); }
  .attr-expanded { display: none; font-size: 10px; line-height: 1.55; color: var(--muted, #6B7280); max-width: 330px; margin: 1px auto 0; padding: 0 4px; }
  .attr-unit.on-dark .attr-expanded { color: rgba(255,255,255,0.74); }
  .attr-unit.attr-open .attr-expanded { display: block; }

  /* ============================================================
     C1 MOBILE GATEWAY (mobile, tenants that mount the toggle). Built only
     <=767px (ensureMobileGateway); the desktop card layout is hidden at that
     width. Masthead + eyebrow + headline + two EQUAL choice cards + don't-ask +
     collapsed attribution foot, all in one dynamic viewport, zero page scroll.
     Card 1 brand field = --aios-half-bg (reference blue, Tompkins black); card-1 pill
     keyline + eyebrow + classic keyline = tenant tokens; everything else is core.
     ============================================================ */
  @media (max-width: 767px) {
    /* MOBILE V2 NOTE. Every "display: none" in this block exists to clear space
       for the bespoke .m-gateway that ensureMobileGateway() builds. The two are
       a matched pair and must be switched on and off together: hiding the
       authored gate without building the replacement leaves no way into AiOS at
       phone width (this happened once during Adam's build). Mobile V2 builds the
       authored gate instead, so each hide below is scoped away from it with
       body:not(.aios-variant-m2). The selectors already carry !important and
       already lead with #toggleScreen, so the added prefix changes only which
       variant they apply to, never which rule wins in a default build. */
    /* The gateway is full-bleed and carries its own masthead, so the shared top
       navbar is hidden on the toggle screen. It returns in AiOS mode. */
    body:not(.aios-active):not(.aios-variant-m2) .navbar { display: none !important; }
    /* R6 (fix for the resizing gateway cards, WITHOUT killing footer scroll): the cards
       flex to the gateway height. If the gateway height is a viewport unit (svh/dvh/vh),
       a phone scroll that retracts the URL bar changes that height and squishes/expands
       the cards. Fix: the gateway height is FROZEN to a fixed pixel value by JS
       (freezeGatewayHeight, set on load + orientation change only, never on scroll), so
       the URL bar moving does not resize the cards. The value below is only the
       first-paint fallback before the JS runs. The page still scrolls to the classic
       footer below the gateway. */
    #toggleScreen .m-gateway.gw-frozen { height: var(--gw-frozen-h) !important; min-height: var(--gw-frozen-h) !important; }
    body:not(.aios-variant-m2) #toggleScreen .toggle-headline,
    body:not(.aios-variant-m2) #toggleScreen .toggle-subhead,
    body:not(.aios-variant-m2) #toggleScreen .toggle-cards,
    body:not(.aios-variant-m2) #toggleScreen .toggle-cards-row { display: none !important; }
    body:not(.aios-variant-m2) #toggleScreen { padding: 0 !important; }
    /* C1: the gateway is exactly one dynamic viewport (the whole gateway is visible
       without scrolling); the classic site footer sits below as the intended
       opening-page scroll (N9/C6). The shell's original toggle attribution + legal
       nodes are superseded by the gateway foot, so hide them on mobile (they carry
       no .m-gateway ancestor and are not the collapsed .attr-unit the foot builds). */
    body:not(.aios-variant-m2) #toggleScreen .aios-attribution,
    body:not(.aios-variant-m2) #toggleScreen .aios-attribution-marks,
    body:not(.aios-variant-m2) #toggleScreen .toggle-poweredby,
    body:not(.aios-variant-m2) #toggleScreen #toggleLegalBar,
    body:not(.aios-variant-m2) #toggleScreen .toggle-legal-bar,
    /* MB2: the original toggle-shell "Don't ask again" row + its settings note are
       superseded by the gateway's own upper checkbox (built by ensureMobileGateway).
       They otherwise re-appear as a grey-fill duplicate beneath the gateway after a
       slight scroll (reference + Tompkins carry them; Gallea's toggle has neither node),
       so hide the shell nodes and their surrounding space on mobile. */
    body:not(.aios-variant-m2) #toggleScreen .toggle-dontask,
    body:not(.aios-variant-m2) #toggleScreen .toggle-settings-note,
    body:not(.aios-variant-m2) #toggleScreen [data-i18n="toggle_change_anytime"] { display: none !important; }

    /* MB-R3 #4: the gateway is sized with 100svh (the SMALL, URL-bar-visible viewport),
       not 100dvh. svh is a CONSTANT: it does not grow when a scroll retracts the mobile
       URL bar, so the two flex cards no longer STRETCH as you begin to scroll (Tompkins
       was the visible case). dvh is kept as the fallback for engines without svh. The
       gateway already fits the small viewport (MB1), so svh renders correct on first
       paint and stays put. Below it the classic footer is the intended scroll (N9). */
    #toggleScreen .m-gateway {
      display: flex; flex-direction: column; box-sizing: border-box;
      height: 100dvh; min-height: 100dvh;
      height: 100svh; min-height: 100svh; overflow: hidden;
      padding: calc(12px + env(safe-area-inset-top,0px)) 18px calc(10px + env(safe-area-inset-bottom,0px));
      background: #fff; color: var(--ink, #14181f);
    }
    /* MB-R3 #1: the original .toggle-screen (headline/cards/dont-ask/attribution) is
       fully superseded by the gateway built above; every child was already hidden, but
       the empty container itself still reserved vertical space, leaving a large BLANK
       band between the gateway and the classic footer on scroll (reference + Tompkins).
       Collapse the container so the footer follows the gateway with no dead space. The
       gateway read its logo + language picker + browse button from it at build time, so
       hiding it now is safe (the browse button still receives .click()). */
    body:not(.aios-variant-m2) #toggleScreen .toggle-screen,
    body:not(.aios-variant-m2) #toggleScreen .toggle-stage { display: none !important; }
    /* MC19: the gateway masthead is the tenant brand field (reference blue, Tompkins
       black via --aios-half-bg) with the white knockout logo, full-bleed to the top
       and side edges (negative margins cancel the gateway's own padding). */
    .m-gw-masthead {
      flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px;
      background: var(--aios-half-bg, var(--accent)); color: #fff; border-bottom: none;
      margin: calc(-1 * (12px + env(safe-area-inset-top,0px))) -18px 11px;
      padding: calc(12px + env(safe-area-inset-top,0px)) 18px 12px;
    }
    .m-gw-logo { height: 26px; width: auto; display: block; color: #fff; }
    .m-gw-logo img, .m-gw-logo svg { height: 26px !important; width: auto !important; display: block; }
    /* MB6: snug gap between the (one-line) language pill and the hamburger so both fit
       beside the wide Tompkins wordmark at 390. min-width:0 lets the group stay within
       the masthead's padded content box rather than overflowing the right edge. */
    .m-gw-mast-right { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
    .m-gw-burger { background: none; border: none; color: #fff; cursor: pointer; padding: 4px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
    /* MC18: the classic card title renders in ink (black) on the white card. */
    .m-gw-card.is-classic .m-gw-card-title { color: var(--ink, #14181f); }
    /* MC22: classic-site nav panel (gateway hamburger). A right-anchored sheet listing
       the tenant's ACTUAL classic navbar tabs (+ Tompkins expandable subtabs), separate
       from the AiOS conversation drawer (N14). Links sourced from the live navbar. */
    .m-gw-navpanel { position: fixed; inset: 0; z-index: 60; background: rgba(10,14,20,0.45); display: none; }
    .m-gw-navpanel.open { display: block; }
    .m-gw-navsheet { position: absolute; top: 0; right: 0; height: 100%; width: min(86vw, 360px); background: #fff; box-shadow: -8px 0 24px rgba(0,0,0,0.18); display: flex; flex-direction: column; padding: calc(8px + env(safe-area-inset-top,0px)) 0 calc(10px + env(safe-area-inset-bottom,0px)); overflow-y: auto; }
    .m-gw-navpanel-head { display: flex; justify-content: flex-end; padding: 4px 14px 6px; }
    .m-gw-navpanel-close { background: none; border: none; color: var(--ink, #14181f); cursor: pointer; padding: 6px; }
    .m-gw-navpanel-list { display: flex; flex-direction: column; }
    .m-gw-navrow { border-top: 1px solid var(--line, #eee); }
    .m-gw-navtab { width: 100%; text-align: left; background: none; border: none; font-family: inherit; font-size: 16px; font-weight: 600; color: var(--ink, #14181f); padding: 15px 20px; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
    .m-gw-navchev { transition: transform 0.2s ease; flex: 0 0 auto; }
    .m-gw-navrow.open .m-gw-navchev { transform: rotate(180deg); }
    .m-gw-navsub { display: none; flex-direction: column; padding: 0 0 8px; background: var(--aios-blue-bg, rgba(0,0,0,0.02)); }
    .m-gw-navrow.open .m-gw-navsub { display: flex; }
    .m-gw-navsubtab { width: 100%; text-align: left; background: none; border: none; font-family: inherit; font-size: 14px; color: var(--ink-soft, #3F4451); padding: 11px 20px 11px 34px; cursor: pointer; }
    /* MC15: line 1 (larger, tenant accent) "Choose Your <Tenant> Experience."; line 2
       (smaller, grey) "How would you like to experience our website?". */
    /* MB1: eyebrow/headline/card margins trimmed a notch (vs the MC15 originals 14/4,
       15, 16px) so the two flex cards get enough height for card 1's content to sit
       fully inside its border even at the SHORT cold-load viewport (URL bar visible).
       Card CONTENT sizing (orb, type) is unchanged at every height, so a slight scroll
       that retracts the bar and grows 100dvh produces no visible pop, only more padding
       around the same content. */
    .m-gw-eyebrow { flex: 0 0 auto; text-align: center; margin: 10px 0 3px; font-size: clamp(21px, 6vw, 27px); font-weight: 800; line-height: 1.14; letter-spacing: -0.01em; text-transform: none; color: var(--aios-blue, var(--accent)); text-wrap: balance; }
    .m-gw-headline { flex: 0 0 auto; text-align: center; margin: 0 0 11px; font-size: 14px; font-weight: 500; line-height: 1.35; letter-spacing: 0; color: var(--muted, #6B7280); text-wrap: balance; }
    .m-gw-cards { flex: 1 1 auto; display: flex; flex-direction: column; gap: 12px; min-height: 0; }
    .m-gw-card {
      flex: 1 1 0; min-height: 0; box-sizing: border-box;
      display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
      text-align: center; border-radius: 18px; padding: 13px 18px; cursor: pointer;
      /* MB1: subpixel insurance so card content can never spill PAST the rounded border
         on a short first-paint viewport; the max-height compaction block below keeps
         real content comfortably inside, so this clips nothing in practice. */
      overflow: hidden;
    }
    .m-gw-card.is-aios { background: var(--aios-half-bg, var(--accent)); color: #fff; }
    .m-gw-card.is-classic { background: #fff; border: 1.5px solid var(--aios-blue, var(--accent)); }
    .m-gw-card-orb { line-height: 0; }
    /* MB-R3 #3: at the short cold-load viewport the AiOS card content filled the whole
       card and jammed the "Start the conversation" pill against the bottom border (~2px).
       Trim the orb so the content sits comfortably inside its padded box with real
       breathing room above and below the pill (no longer edge-to-edge). */
    .m-gw-card-orb .orb { width: 44px; height: 44px; }
    .m-gw-card.is-aios .m-gw-card-orb .orb circle { fill: #fff; }
    .m-gw-glyph { color: var(--aios-blue, var(--accent)); display: inline-flex; line-height: 0; }
    .m-gw-card-title { font-size: 19px; font-weight: 800; letter-spacing: 0.01em; line-height: 1.15; }
    .m-gw-card-sub { font-size: 13px; font-weight: 500; line-height: 1.35; }
    .m-gw-card.is-aios .m-gw-card-sub { opacity: 0.9; }
    .m-gw-card.is-classic .m-gw-card-sub { color: var(--muted, #6B7280); }
    .m-gw-pill { margin-top: 5px; display: inline-flex; align-items: center; justify-content: center; border-radius: 999px; padding: 9px 22px; font-weight: 700; font-size: 14px; }
    .m-gw-card.is-aios .m-gw-pill { border: 1.5px solid var(--aios-toggle-cta, #fff); color: #fff; background: transparent; }
    /* MB7 (NI-6): the classic card pill keeps the tenant-accent border, but its TEXT
       colour is tenant-overridable via --aios-gw-classic-pill-text. reference + Gallea
       leave it unset -> falls back to the accent (blue). Tompkins' shell sets it to
       ink so "Continue to site" reads black on the red keyline, per NI-6. */
    .m-gw-card.is-classic .m-gw-pill { border: 1.5px solid var(--aios-blue, var(--accent)); color: var(--aios-gw-classic-pill-text, var(--aios-blue, var(--accent))); background: transparent; }
    .m-gw-dontask { flex: 0 0 auto; text-align: center; margin: 8px 0 5px; }
    .m-gw-dontask-row { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink-soft, #3F4451); }
    .m-gw-dontask-box { width: 16px; height: 16px; border: 1.5px solid var(--line, #c9ccd2); border-radius: 4px; flex: 0 0 auto; position: relative; }
    .m-gw-dontask.checked .m-gw-dontask-box { background: var(--aios-blue, var(--accent)); border-color: var(--aios-blue, var(--accent)); }
    .m-gw-dontask.checked .m-gw-dontask-box::after { content: ''; position: absolute; left: 5px; top: 1.5px; width: 4px; height: 8px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
    .m-gw-dontask-sub { font-size: 11px; color: var(--muted, #6B7280); margin-top: 3px; }
    .m-gw-foot { flex: 0 0 auto; border-top: 1px solid var(--line, #e6e6ea); padding-top: 8px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
    .m-gw-legal { display: flex; align-items: center; gap: 10px; }
    .m-gw-legal button { background: none; border: none; font-family: inherit; font-size: 11.5px; color: var(--muted, #6B7280); cursor: pointer; padding: 2px; }
    .m-gw-legal span { color: var(--line, #c9ccd2); }


    /* N5: on the gateway the language menu drops DOWN (the shared control opens
       upward, which runs off the top of the masthead) and anchors to the button's
       right edge; it stays fully functional (renderLanguageDropdown wires setLanguage).
       Scoped to .m-gw-lang so the desktop toggle picker is untouched (Section 7). */
    .m-gw-lang { position: relative; }
    .m-gw-lang .toggle-lang-wrap, .m-gw-lang .toggle-language-picker { margin: 0 !important; position: relative; }
    .m-gw-lang .lang-dropdown {
      /* Amendment 9 D.6: the shared .lang-dropdown is now position:fixed and
         JS-placed; inside the gateway masthead it stays anchored to the pill
         absolutely (the gateway section is a full-screen fixed layer, so
         nothing clips it), still opening downward. */
      position: absolute !important;
      top: calc(100% + 6px) !important; bottom: auto !important;
      left: auto !important; right: 0 !important; transform: none !important;
    }
    /* MC20: the gateway language button is a white control on the tenant brand field.
       reference = blue text + blue keyline; Tompkins = black text + red keyline. The
       per-tenant text colour comes from --aios-gw-lang-text (default = the tenant
       accent, so reference is blue; Tompkins' shell overrides it to ink/black); the
       keyline is always the tenant accent (--aios-blue = blue on reference, red on
       Tompkins). It drops DOWN (set above) and is the only control besides the
       hamburger in the masthead right group. */
    .m-gw-lang .toggle-language-button,
    .m-gw-lang .toggle-lang-select {
      background: #fff !important; color: var(--aios-gw-lang-text, var(--aios-blue, var(--accent))) !important;
      border: 1.5px solid var(--aios-blue, var(--accent)) !important; border-radius: 999px !important;
      /* MB6: keep "English (Canada)" on ONE line. Tompkins uses .toggle-lang-select,
         whose shell rule carries no white-space (so it wrapped); reference' shell already
         nowraps. Force nowrap here for both, and let the label carry it too. The pill is
         kept compact (padding/font/gap) so that ONE-line pill + the hamburger still fit
         beside the wide Tompkins wordmark at 390 without pushing the burger off-screen. */
      padding: 7px 11px !important; font-size: 11.5px !important; gap: 6px !important; width: auto !important;
      white-space: nowrap !important; flex: 0 0 auto !important;
    }
    .m-gw-lang .toggle-language-button #toggleLanguageLabel,
    .m-gw-lang .toggle-lang-select #toggleLanguageLabel { white-space: nowrap !important; }
    .m-gw-lang .toggle-language-button svg,
    .m-gw-lang .toggle-lang-select svg { stroke: var(--aios-gw-lang-text, var(--aios-blue, var(--accent))); color: var(--aios-gw-lang-text, var(--aios-blue, var(--accent))); }
  }

  /* ============================================================
     6.I MOBILE LISTENING STATE. On orb tap the welcome orb enlarges
     and pulses, the caption becomes "Listening..." with "Tap to stop"
     beneath, and a waveform animates. Driven by body.aios-listening
     (voice.js). Phone width only.
     ============================================================ */
  .orb-listening-ui { display: none; }
  /* 6.O(2): the mobile column-major comparison view is desktop-hidden; the
     row-major .comparison-grid is the desktop view. Swaps at <=767px below. */
  .comparison-cols { display: none; }
  @keyframes aiosOrbPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.07); } }
  @keyframes aiosWave { 0%, 100% { height: 6px; } 50% { height: 18px; } }
  @media (max-width: 767px) {
    body.aios-listening #aiosCanvas:not(.has-messages) .orb-wrapper .orb,
    body.aios-listening .aios-canvas:not(.has-messages) .orb-wrapper-large .orb {
      width: 96px !important; height: 96px !important;
      animation: aiosOrbPulse 1.1s ease-in-out infinite; transform-origin: center;
    }
    body.aios-listening .orb-caption { display: none !important; }
    body.aios-listening .orb-listening-ui {
      display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 12px;
    }
    .orb-listening-title { font-size: 14px; font-weight: 700; color: var(--aios-blue, var(--accent)); letter-spacing: 0.01em; }
    .orb-listening-stop { font-size: 12px; color: var(--muted, #6B7280); }
    .orb-waveform { display: flex; align-items: center; gap: 4px; height: 20px; }
    .orb-waveform span {
      width: 3px; height: 6px; border-radius: 2px; background: var(--aios-blue, var(--accent));
      animation: aiosWave 0.9s ease-in-out infinite;
    }
    .orb-waveform span:nth-child(2) { animation-delay: 0.12s; }
    .orb-waveform span:nth-child(3) { animation-delay: 0.24s; }
    .orb-waveform span:nth-child(4) { animation-delay: 0.36s; }
    .orb-waveform span:nth-child(5) { animation-delay: 0.48s; }

    /* 6.O(2) COMPARISON on mobile: swap the row-major grid for column-major
       cards. Two options sit as a two-column pair; three or more overflow into
       a horizontal scroll where the next column peeks (scroll-snap). Attribute
       labels repeat inside every column; values never fall below 12px. */
    .comparison-grid { display: none !important; }
    .comparison-cols {
      display: flex !important; flex-direction: row; gap: 12px;
      overflow-x: auto; -webkit-overflow-scrolling: touch;
      scroll-snap-type: x mandatory; margin: 4px -2px 0; padding: 2px;
    }
    .comparison-col {
      flex: 0 0 auto; scroll-snap-align: start;
      border: 1px solid var(--line, #e5e7eb); border-radius: 12px;
      padding: 12px 14px; background: #fff;
    }
    /* Two columns fill the width as a pair; three or more are ~78vw so the next
       column peeks past the edge and reads as swipeable. */
    .comparison-cols[data-cols="2"] .comparison-col { width: calc(50% - 6px); }
    .comparison-cols[data-cols="3"] .comparison-col,
    .comparison-cols:not([data-cols="2"]) .comparison-col { width: 78vw; max-width: 300px; }
    .ccol-head {
      font-size: 14px; font-weight: 700; color: var(--ink, #1A1A1A);
      padding-bottom: 8px; margin-bottom: 8px; border-bottom: 1px solid var(--line, #e5e7eb);
      line-height: 1.25;
    }
    .ccol-pair { padding: 6px 0; border-bottom: 1px solid var(--line-soft, #f1f3f5); }
    .ccol-pair:last-child { border-bottom: none; }
    .ccol-label {
      font-size: 12px; font-weight: 600; color: var(--muted, #6B7280);
      text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 2px;
    }
    .ccol-val { font-size: 13.5px; font-weight: 600; color: var(--aios-blue, var(--accent)); line-height: 1.3; }
    .ccol-val-plain { font-size: 13px; color: var(--ink, #1A1A1A); line-height: 1.35; }

    /* 6.O(4) AREA CARDS on mobile: full-width stacked selection cards (the
       desktop auto-fill grid packs two per row). The Rent/Purchase intent
       pills stay a full-width pair above them. Submit is full-width. */
    .area-grid, .discovery-grid { grid-template-columns: 1fr !important; }
    .discovery-intent { display: flex !important; }
    .discovery-intent .intent-pill { flex: 1 1 0 !important; }
    .discovery-submit { width: 100% !important; }
  }

  /* C1 superseded. Authored Toggle cards stay visible. This block is injected
     last, so it must also pin the stacked column. A later display:flex without
     nowrap re-wraps the Traditional Website card into a second column at 320. */
  @media (max-width: 767px) {
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen:not(.hidden) {
      display: flex !important;
      align-items: stretch !important;
      justify-content: flex-start !important;
      overflow: auto !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-screen,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-stage {
      display: flex !important;
      flex-direction: column !important;
      align-items: center !important;
      width: 100% !important;
      height: auto !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-headline,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-subhead,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-logo,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-poweredby,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .aios-attribution {
      display: revert !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-cards,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-cards-row {
      display: flex !important;
      flex-direction: column !important;
      flex-wrap: nowrap !important;
      width: 100% !important;
      max-width: none !important;
      align-items: stretch !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-card {
      width: 100% !important;
      max-width: none !important;
      flex: 1 1 auto !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .aios-attribution,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .toggle-poweredby,
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .aios-attribution-marks {
      display: flex !important;
      flex-direction: row !important;
      flex-wrap: nowrap !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 14px !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen .m-gateway {
      display: none !important;
    }
    html[data-stacked-mobile-gate="true"] body:not(.aios-variant-m2) #toggleScreen.hidden {
      display: none !important;
    }
  }

.settings-language-row { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 10px; }
.settings-lang-pill { border: 1px solid var(--aios-blue); background: #fff; color: var(--aios-blue); border-radius: 999px; padding: 9px 16px; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; }
.settings-lang-pill.on { background: var(--aios-blue); color: #fff; }
