/* landing-pages.css - the homepage's landing components, for /pages/ documents.
 *
 * WHY THIS FILE EXISTS: the marketing homepage and the generated /pages/ tree
 * were built on two different design systems - `landing-*` (app.css) and `md-*`
 * (modules.css). They shared an accent color and a similar font stack, which
 * made them look related in a diff and plainly different on screen.
 *
 * app.css cannot simply be linked from a document page: it opens with
 *   body { height: 100%; overflow: hidden; }
 * which is right for an application shell and fatal for a scrolling page. So the
 * landing COMPONENTS are extracted here and the shell is left behind.
 *
 * GENERATED by scripts/tests/extract-landing-css.js from app.css. Edit the
 * source rules in app.css, not this file, or the next extraction drops them.
 *
 * Pair with flux.css (tokens) and theme-bridge.css (aliases), and set
 * data-theme="light" on <html> - flux defaults to dark, and the landing is
 * always light.
 */

/* Document base. Replaces the app-shell body rule that was deliberately not
   carried over. */
body.landing-doc {
  margin: 0;
  min-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  background: var(--surface-0);
  color: var(--text-primary);
  font-family: var(--ff-sans, 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
/* NO blanket anchor rule here, deliberately.
   A `body.landing-doc a { color: ... }` rule carries specificity 0,0,1,2 and
   outranks every component that sets its own link color - .landing-btn-primary
   (0,0,1,0) lost its label to it, and .landing-nav-link lost the homepage's
   grey and rendered teal, which is what made the nav look different from the
   homepage despite identical markup and identical nav CSS.
   Components own their colors; prose links are colored where prose lives. */
.gap-split-copy p a, .gap-close a, .gap-boundary a, .gap-tool p a { color: var(--accent); }

.landing-wrap { display: flex; flex-direction: column; min-height: 100%; }
.landing-accent { color: var(--accent); }
/* --- Nav --- */
/* The rule under the nav is the VaultSync red, not a neutral border.
 *
 * It is the one piece of brand colour on an otherwise Microsoft-adjacent surface, and that is the
 * whole point: the blue says we belong in your stack, the red says which vendor it is. Everything
 * about it is deliberately restrained - 1px, well under half opacity - because the red is a signal
 * in this palette and never a fill. At full strength a rule this wide reads as an alert.
 *
 * --brand-red carries the channels unpacked so the alpha stays a single tunable number. It is the
 * corporate mark measured directly, #c11c33 = rgb(193 28 51). --brand-red-rule is the only knob:
 * raise it toward .6 to make the line assert itself, drop it toward .25 to make it a whisper.
 *
 * VaultSync surfaces only. The application is GDBS Pro chrome, where a red rule would compete with
 * the data rather than brand the page. */
:root {
  --brand-red: 193 28 51;
  --brand-red-rule: .45;
}
.landing-nav {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in oklch, var(--surface-0) 90%, transparent); backdrop-filter: blur(12px);
  /* Was a red hairline (--brand-red at .45). A saturated accent line pinned to
     the top of the viewport is on screen for the entire scroll, so it competed
     with the content the whole way down. The nav still needs an edge - without
     one it bleeds into a section that shares its ground - so it keeps a neutral
     border in the standard token instead. --brand-red stays defined above; it is
     simply no longer spent here. */
  border-bottom: 1px solid var(--border-subtle, #e9ecf3);
}
.landing-nav-inner {
  max-width: 1200px; margin: 0 auto; padding: 0 2rem;
  height: 60px; display: flex; align-items: center; gap: 2rem;
}
.landing-logo {
  display: flex; align-items: center; gap: 10px;
  font-size: 20px; font-weight: 300; color: var(--text-primary); white-space: nowrap;
}
.landing-logo i { color: var(--accent); font-size: 22px; }
.landing-logo span { font-size: 20px; }
.landing-nav-links { display: flex; gap: 0.25rem; flex: 1; }
.landing-nav-link {
  padding: 6px 14px; color: var(--text-secondary); font-size: 13px;
  border-radius: 4px; transition: all 0.2s; text-decoration: none;
}
.landing-nav-link:hover { color: var(--text-primary); background: color-mix(in oklch, var(--accent) 12%, transparent); text-decoration: none; }
.landing-nav-actions { display: flex; gap: 0.5rem; }
/* --- Buttons --- */
.landing-btn-primary {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 20px; background: var(--accent); color: var(--accent-text, #fff);
  border: none; border-radius: 5px; font-size: 13px; font-weight: 600;
  cursor: pointer; transition: all 0.2s; white-space: nowrap;
}
.landing-btn-primary i, .landing-btn-primary svg { color: inherit; }
.landing-btn-primary:hover { background: var(--accent-hover); }
.landing-btn-outline {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 18px; background: transparent; color: var(--text-bright);
  border: 1px solid var(--border-light); border-radius: 5px; font-size: 13px;
  cursor: pointer; transition: all 0.2s; white-space: nowrap;
}
.landing-btn-outline:hover { background: var(--bg-hover); border-color: var(--accent); color: var(--accent); }
.landing-btn-ghost {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 20px; background: transparent; color: var(--text-bright);
  border: 1px solid var(--border); border-radius: 5px; font-size: 13px;
  cursor: pointer; transition: all 0.2s; text-decoration: none; white-space: nowrap;
}
.landing-btn-ghost:hover { background: color-mix(in oklch, var(--text-primary) 7%, transparent); text-decoration: none; color: var(--text-primary); }
.landing-btn-lg { padding: 12px 28px; font-size: 15px; border-radius: 6px; }
.landing-btn-full { width: 100%; justify-content: center; padding: 12px; font-size: 15px; border-radius: 6px; }
/* --- Hero --- */
.landing-hero {
  background: radial-gradient(ellipse at 60% 40%, rgba(79,195,247,0.07) 0%, transparent 60%),
              radial-gradient(ellipse at 20% 80%, rgba(129,196,132,0.05) 0%, transparent 50%),
              var(--bg);
  padding: 100px 2rem 80px;
  border-bottom: 1px solid var(--border);
}
.landing-hero-inner { max-width: 1200px; margin: 0 auto; text-align: center; }
.landing-badge-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 14px; background: color-mix(in oklch, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in oklch, var(--accent) 32%, transparent); border-radius: 20px;
  font-size: 12px; color: var(--accent); margin-bottom: 1.5rem;
}
.landing-h1 {
  font-size: 44px; /* fallback for browsers without clamp() (older Android) */
  font-size: clamp(32px, 5vw, 58px); font-weight: 300;
  color: var(--text-bright); line-height: 1.2; margin-bottom: 1.25rem;
}
/* Kept in step with the same rule in app.css - a multi-paragraph hero lede needs
   the wider measure and the tight inter-line gap, or each sentence wraps to an
   orphan and the three read as three unrelated blocks. */
.landing-hero-sub {
  max-width: 720px; margin: 0 auto .35rem;
  font-size: 16px; color: var(--text-dim); line-height: 1.7;
  text-wrap: balance;
}
.landing-hero-sub:last-of-type { margin-bottom: 2.5rem; }
.landing-hero-ctas { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; margin-bottom: 4rem; }
.landing-hero-stats {
  display: flex; justify-content: center; gap: 3rem; flex-wrap: wrap;
  padding-top: 2.5rem; border-top: 1px solid var(--border);
}
.landing-stat { text-align: center; }
.landing-stat span { display: block; font-size: 36px; font-weight: 300; color: #4fc3f7; line-height: 1; margin-bottom: 0.5rem; }
.landing-stat small { font-size: 12px; color: var(--text-dim); line-height: 1.5; }
/* --- Sections --- */
.landing-section { padding: 80px 2rem; }
.landing-section-alt { background: var(--bg-alt); }
.landing-section-inner { max-width: 1200px; margin: 0 auto; }
.landing-section-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 2px; color: #4fc3f7; margin-bottom: 1rem;
}
.landing-h2 { font-size: 30px; font-size: clamp(24px, 3vw, 36px); font-weight: 300; color: var(--text-bright); margin-bottom: 1rem; }
.landing-section-sub { font-size: 15px; color: var(--text-dim); line-height: 1.7; max-width: 680px; margin-bottom: 3rem; }
/* --- Features grid --- */
.landing-features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; }
.landing-feature-card {
  background: var(--bg-panel); border: 1px solid var(--border);
  border-radius: 8px; padding: 1.75rem; transition: border-color 0.2s;
}
.landing-feature-card:hover { border-color: var(--border-light); }
.landing-feature-icon { font-size: 28px; margin-bottom: 1rem; }
.landing-feature-card h3 { font-size: 15px; font-weight: 600; color: var(--text-bright); margin-bottom: 0.75rem; }
.landing-feature-card p { font-size: 13px; color: var(--text-dim); line-height: 1.6; margin: 0; }
/* --- Domains grid --- */
.landing-domains-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; }
.landing-domain-card {
  background: var(--bg-panel); border: 1px solid var(--border);
  border-radius: 8px; padding: 1.5rem 1.25rem;
  display: flex; flex-direction: column; gap: 0.5rem;
  transition: all 0.2s; cursor: default;
}
.landing-domain-card:hover { border-color: var(--border-light); background: var(--bg-hover); }
.landing-domain-card i { font-size: 24px; }
.landing-domain-card span { font-size: 14px; font-weight: 600; color: var(--text-bright); }
.landing-domain-card small { font-size: 11px; color: var(--text-dim); line-height: 1.4; }
/* --- Tiers grid --- */
.landing-tiers-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; align-items: stretch; }
.landing-tier-card {
  background: var(--bg-panel); border: 1px solid var(--border);
  border-radius: 8px; padding: 1.75rem; display: flex; flex-direction: column; gap: 0.75rem;
}
.landing-tier-card-highlight {
  border-color: rgba(245,158,11,0.4);
  box-shadow: 0 0 0 1px rgba(245,158,11,0.15);
}
.landing-tier-label {
  display: inline-block; padding: 4px 10px; border-radius: 12px;
  font-size: 11px; font-weight: 700; letter-spacing: 1px; align-self: flex-start;
}
.landing-tier-price { font-size: 32px; font-weight: 300; color: var(--text-bright); }
.landing-tier-price small { font-size: 14px; color: var(--text-dim); }
.landing-tier-desc { font-size: 13px; color: var(--text-dim); line-height: 1.6; }
.landing-tier-features { list-style: none; display: flex; flex-direction: column; gap: 8px; font-size: 13px; color: var(--text); flex: 1; }
.landing-tier-features li { display: flex; align-items: center; gap: 8px; }
.landing-tier-features li i { width: 14px; font-size: 12px; }
.landing-tier-features li i.fa-check { color: #4ec964; }
.landing-tier-features li i.fa-times { color: #555; }
.landing-tier-features li.muted { color: var(--text-dim); }
.landing-tier-btn {
  margin-top: auto; padding: 10px 16px; width: 100%;
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 5px; color: var(--text); font-size: 13px; font-weight: 500;
  cursor: pointer; transition: all 0.2s;
}
.landing-tier-btn:hover { background: var(--bg-hover); border-color: var(--border-light); color: var(--text-bright); }
/* A SOLID tier button: white label AND white icon. The icon rule is not redundant -
   FontAwesome glyphs are font colour, so without inherit they keep the dark
   .landing-tier-btn colour and render near-black on a purple or blue fill. */
.landing-tier-btn-solid { color: #fff; }
.landing-tier-btn-solid i, .landing-tier-btn-solid svg { color: inherit; }
.landing-tier-btn-solid:hover { color: #fff; filter: brightness(1.08); }

/* The free tier reads as the secondary action, which is the convention: outlined
   against the paid tiers solid fills. Amber on pale amber failed contrast, so the
   text is the darker amber-700 and the border carries the colour instead. */
.landing-tier-btn-accent {
  background: rgba(245,158,11,0.12);
  border-color: rgba(245,158,11,0.55);
  color: #b45309;
  font-weight: 600;
}
.landing-tier-btn-accent:hover { background: rgba(245,158,11,0.22); color: #92400e; }
/* --- Feedback section --- */
.landing-feedback-wrap { display: grid; grid-template-columns: 1fr 1fr; gap: 4rem; align-items: start; }
@media (max-width: 768px) { .landing-feedback-wrap { grid-template-columns: 1fr; } }
.landing-contact-list { display: flex; flex-direction: column; gap: 1.25rem; margin-top: 2rem; }
.landing-contact-item {
  display: flex; align-items: flex-start; gap: 1rem;
  padding: 1rem 1.25rem; background: var(--bg-panel);
  border: 1px solid var(--border); border-radius: 6px;
}
.landing-contact-item i { color: #4fc3f7; font-size: 16px; margin-top: 2px; }
.landing-contact-item strong { display: block; color: var(--text-bright); font-size: 13px; margin-bottom: 3px; }
.landing-contact-item a { font-size: 12px; color: var(--text-dim); }
.landing-contact-item a:hover { color: #4fc3f7; }
.landing-form { display: flex; flex-direction: column; gap: 1rem; }
.landing-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 540px) { .landing-form-row { grid-template-columns: 1fr; } }
.landing-field { display: flex; flex-direction: column; gap: 5px; }
.landing-field label { font-size: 12px; color: var(--text-dim); font-weight: 500; }
.landing-field input,
.landing-field select,
.landing-field textarea {
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 5px; padding: 9px 12px; color: var(--text); font-size: 13px;
}
.landing-field input:focus,
.landing-field select:focus,
.landing-field textarea:focus { border-color: #4fc3f7; outline: none; }
.landing-field textarea { resize: vertical; min-height: 100px; }
/* --- Demo / GIF section --- */
.landing-demo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1.5rem;
  margin-top: 0.5rem;
}
.landing-demo-card {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  transition: border-color 0.2s, transform 0.2s;
}
.landing-demo-card:hover { border-color: rgba(79,195,247,0.4); transform: translateY(-2px); }
.landing-demo-card img {
  width: 100%; display: block;
  border-bottom: 1px solid var(--border);
  background: #111;
}
.landing-demo-card-body { padding: 1rem 1.25rem; }
.landing-demo-card-body h4 { font-size: 14px; font-weight: 600; color: var(--text-bright); margin-bottom: 4px; }
.landing-demo-card-body p { font-size: 12px; color: var(--text-dim); line-height: 1.5; margin: 0; }
/* --- Footer --- */
.landing-footer {
  margin-top: auto; padding: 2rem;
  border-top: 1px solid var(--border); background: var(--bg-alt);
}
.landing-footer-inner {
  max-width: 1200px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
/* Advisory credit. Sits a step above the copyright line and a step below the links,
 because it is a real credential and not boilerplate, but it is also SCOPE-LIMITED and
 must not read like a headline endorsement of the whole platform. */
.landing-footer-advisor {
  font-size: 12px;
  color: var(--text-dim);
  margin: 0 0 8px;
  letter-spacing: .01em;
}
.landing-footer-copy { font-size: 12px; color: var(--text-dim); }
.landing-footer-copy a { color: var(--text-dim); }
.landing-footer-copy a:hover { color: #4fc3f7; }
.landing-footer-citation { font-size: 11px; color: var(--text-dim); margin-top: 6px; opacity: 0.7; }
.landing-footer-citation a { color: #81c784; text-decoration: none; }
.landing-footer-citation a:hover { color: #a5d6a7; text-decoration: underline; }
.landing-footer-toggle { display: none; }
/* desktop: footer shows fully; the toggle is mobile-only */

/* FAQ Accordion */
.landing-faq-section { background: var(--bg-surface); }
/* ── GDBS Free section ── */
.landing-free-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 32px 0 28px;
}
@media (max-width: 760px) { .landing-free-grid { grid-template-columns: 1fr; } }
.landing-free-card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px; padding: 20px;
}
.landing-free-card-header {
  display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600;
  color: var(--text-bright); margin-bottom: 10px;
}
.landing-free-card-header i { font-size: 18px; }
.landing-free-card p { font-size: 13px; color: var(--text-muted); line-height: 1.65; margin: 0; }
.landing-free-actions {
  display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 32px; align-items: center;
}
.landing-free-snippet {
  background: #0d1117; border: 1px solid rgba(255,255,255,0.1); border-radius: 8px;
  overflow: hidden; max-width: 680px;
}
.landing-free-snippet-label {
  padding: 8px 16px; font-size: 11px; color: #8b949e;
  background: rgba(255,255,255,0.04); border-bottom: 1px solid rgba(255,255,255,0.07);
  font-family: var(--mono);
}
`,
   which is near-white in the flux light theme and rendered the code white-on-white. */
.landing-free-snippet pre { margin: 0; padding: 16px; overflow-x: auto; background: transparent; border: 0; border-radius: 0; }
.landing-free-snippet code { font-family: var(--mono); font-size: 13px; color: #e6edf3; background: transparent; line-height: 1.6; }
.landing-free-note { font-size: 12px; color: var(--text-dim); margin-top: 20px; }
/* ── Try Live nav button ── */
.landing-btn-ghost-sm {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 14px; background: rgba(79,195,247,0.08); color: #4fc3f7;
  border: 1px solid rgba(79,195,247,0.3); border-radius: 5px; font-size: 12px;
  cursor: pointer; transition: all 0.2s; white-space: nowrap;
}
.landing-btn-ghost-sm:hover { background: rgba(79,195,247,0.15); border-color: #4fc3f7; }
@media (max-width: 768px) {
  /* Hide connected status, Report and Print on mobile */
  .topbar-center { display: none; }
  .topbar-left { min-width: 0; }
  .topbar-right { min-width: 0; gap: 6px; }
  #btn-global-report, #btn-print-view { display: none; }

  /* ── De-cram the topbar ────────────────────────────────────────────────
     Everything (brand, product tabs, admin Share, 3D, tier badge, user chip)
     sat in one 36px row and overlapped into an unreadable blend. Product tabs
     go ICON-ONLY (the brand already names the product; the active tab keeps its
     highlight) and the nav SCROLLS instead of overflowing; the user chip drops
     its "User:" prefix and truncates the long email so nothing blends. */
  .topbar { padding: 0 8px; gap: 4px; }
  .topbar-left { flex-shrink: 0; }
  .topbar-left .brand { font-size: 13px; }
  .product-tabs { margin-left: 4px; min-width: 0; flex-shrink: 1; overflow-x: auto; scrollbar-width: none; gap: 1px; }
  .product-tabs::-webkit-scrollbar { display: none; }
  .product-tab { padding: 0 9px; }
  .product-tab span { display: none; }                 /* icon-only tabs */
  .topbar-right { flex-shrink: 0; gap: 4px; }
  .topbar-right .user-prefix { display: none; }        /* drop the "User:" label */
  #user-display { display: inline-block; max-width: 88px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
  #btn-view-3d { margin-right: 2px !important; }

  /* ── Collapsible landing footer ────────────────────────────────────────
     The subscribe form + legal link list made a tall footer on phones. Collapse
     them behind a toggle so the footer is a compact strip (logo + button); tap
     to expand. */
  .landing-footer-toggle {
    display: inline-flex; align-items: center; gap: 8px; margin: 8px auto 0;
    background: none; border: 1px solid var(--border); color: var(--text-dim);
    border-radius: 6px; padding: 8px 14px; font-size: 13px; font-family: inherit; cursor: pointer;
  }
  .landing-footer-toggle i { transition: transform 0.15s; }
  .landing-footer.footer-open .landing-footer-toggle i { transform: rotate(180deg); }
  .landing-footer-collapse { display: none; }
  .landing-footer.footer-open .landing-footer-collapse { display: block; }

  /* Charts fill the width on mobile; the vchart legend is moved below the plot (see vchart.js). */
  .chart-wrap, .chart-wrap canvas { width: 100% !important; }

  /* ── Fly-up module navigation ──────────────────────────────────────────
     The 52px bottom bar crammed all ~20 modules across every tier into one
     scroll with no way to jump between Standard / Pro / HPC Lab. Replace it
     with a bottom-sheet: a single "Modules" button flies up a sheet with the
     STD / PRO / HPC tabs on top and the active tier's modules as big rows. */
  .main-layout { flex-direction: column; }

  #mobile-nav-toggle {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    position: fixed; bottom: 0; left: 0; width: 100%; height: 52px; z-index: 60;
    background: var(--bg-alt); border: none; border-top: 1px solid var(--border);
    color: var(--accent); font-size: 14px; font-weight: 600; font-family: inherit; cursor: pointer;
  }
  #mobile-nav-toggle i { font-size: 16px; }

  #mobile-nav-backdrop { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 70; background: rgba(0,0,0,0.5); }
  #mobile-nav-backdrop.show { display: block; }

  /* the sidebar becomes the fly-up sheet */
  .sidebar {
    position: fixed; left: 0; bottom: 0; width: 100%; height: auto; max-height: 78vh;
    flex-direction: column; overflow-y: auto; z-index: 80;
    background: var(--bg-alt); border: none; border-top: 1px solid var(--border);
    border-radius: 14px 14px 0 0; box-shadow: 0 -8px 30px rgba(0,0,0,0.5);
    transform: translateY(100%); transition: transform 0.28s ease; padding-bottom: 12px;
  }
  .sidebar.flyup-open { transform: translateY(0); }
  .sidebar-nav { flex-direction: column; flex: none; overflow: visible; }

  /* STD / PRO / HPC tabs as the sticky sheet header */
  .tier-dots {
    display: flex; flex-direction: row; justify-content: center; gap: 8px;
    position: sticky; top: 0; z-index: 2; background: var(--bg-alt);
    padding: 14px 12px 10px; border-bottom: 1px solid var(--border);
  }
  .tier-dot { flex: 1; max-width: 110px; text-align: center; padding: 11px 8px; font-size: 13px; font-weight: 700; border-radius: 8px; }

  /* module rows */
  .nav-item {
    flex-direction: row; align-items: center; justify-content: flex-start; gap: 14px;
    width: 100%; padding: 14px 22px; font-size: 15px; text-align: left;
    border-left: 3px solid transparent; border-top: none;
  }
  .nav-item i { font-size: 18px; width: 24px; text-align: center; }
  .nav-item.active { border-left-color: var(--accent); border-top-color: transparent; background: var(--bg); }
  .nav-item-bottom { margin-top: 0; border-top: none; border-left: 3px solid transparent; }
  .nav-tier-section { display: none; }
  .nav-tier-section.active { display: flex; flex-direction: column; }

  /* ── Module sub-tab bars: icon-only on small screens ───────────────────
     The flat tab rows (Molecular / Cosmos / Materials / Geophysics / Fluids /
     Quantum / Anomaly / Theory) ran off the right edge in portrait. Collapse
     each tab to its icon (the label is a bare text node, so font-size:0 on the
     button hides it while the icon keeps its own size) and let the row wrap, so
     every tab is visible without left-right scroll. The full label is set as a
     title (hover / long-press) by app.js setTabTitles(). */
  .molecular-tabs, .cosmic-tabs, .materials-tabs, .geo-tabs,
  .fluids-tabs, .quantum-tabs, .tukey-tabs, .theory-tabs {
    flex-wrap: wrap; overflow-x: visible; justify-content: center;
    gap: 2px; padding: 6px 4px;
  }
  .mtab, .ctab, .mattab, .geotab, .fltab, .qtab, .tukeytab, .theory-tab {
    font-size: 0 !important; padding: 9px 12px; gap: 0; white-space: nowrap;
  }
  .mtab > i, .ctab > i, .mattab > i, .geotab > i,
  .fltab > i, .qtab > i, .tukeytab > i, .theory-tab > i {
    font-size: 17px !important; margin: 0; width: auto;
  }
  /* The ACTIVE sub-tab keeps its label so you always know which tool is running
     (icon-only tabs otherwise hide the selection on mobile - you can't tell what
     you're looking at). The active pill shows "<icon> Name"; the rest stay icons. */
  .mtab.active, .ctab.active, .mattab.active, .geotab.active,
  .fltab.active, .qtab.active, .tukeytab.active, .theory-tab.active {
    font-size: 12px !important; gap: 6px; padding: 9px 14px; font-weight: 600;
  }
  .mtab.active > i, .ctab.active > i, .mattab.active > i, .geotab.active > i,
  .fltab.active > i, .qtab.active > i, .tukeytab.active > i, .theory-tab.active > i {
    font-size: 13px !important;
  }

  /* pad content above the fixed toggle bar */
  .content-area, .plasma-panel, .module-panel,
  .pane-content, .detail-pane, .query-pane, .content, .view { padding-bottom: 60px; }

  /* Charts — ensure min size on small screens */
  .chart-wrap { min-height: 200px; height: 220px; }
  canvas { min-height: 160px; min-width: 0; }
  .md-chart-cell { min-height: 180px; }
  .theory-subpanel canvas { min-height: 160px; }

  /* Landing nav hamburger */
  .landing-hamburger {
    display: flex; align-items: center; justify-content: center;
    background: none; border: 1px solid var(--border); color: var(--text-dim);
    border-radius: 4px; padding: 6px 10px; cursor: pointer; font-size: 16px;
    margin-left: 8px;
  }
  .landing-nav-links { display: none; }
  /* Keep the primary "Get Started" (signup) visible in the mobile top bar;
     Try Live / Sign In live in the hamburger menu. */
  .landing-nav-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
  .landing-nav-actions .landing-btn-outline { display: none; }
  .landing-nav-actions .landing-btn-primary { display: inline-flex; align-items: center; }
  .landing-mobile-menu {
    display: none; flex-direction: column;
    background: var(--bg-panel); border-top: 1px solid var(--border);
    padding: 8px 16px 12px;
  }
  .landing-mobile-menu.open { display: flex; }
  .landing-mobile-menu .landing-nav-link { padding: 10px 4px; font-size: 14px; border-bottom: 1px solid var(--border-faint, rgba(255,255,255,0.05)); }
  .landing-mobile-actions { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 12px; }
}
@media (min-width: 769px) {
  .landing-hamburger { display: none; }
  .landing-mobile-menu { display: none !important; }
}


/* The dropdown primitives. These were authored in an inline <style> inside
   index.html rather than in app.css, so extracting the .landing-* rules never
   picked them up - and a page without `.ln-menu{display:none}` renders every
   dropdown's contents as loose inline text beside the logo, which is exactly
   what the industry menu did on the gap pages.

   Copied verbatim from that inline block. They belong in a stylesheet, not in
   one page's <head>. */
.ln-item{position:relative;display:inline-flex;align-items:center}
.ln-trigger{cursor:pointer}
.ln-caret{font-size:9px;margin-left:5px;opacity:0.55}
.ln-menu{position:absolute;top:100%;left:0;min-width:196px;background:var(--bg-panel,#ffffff);border:1px solid var(--border,#e2e8f0);border-radius:10px;box-shadow:0 14px 34px rgba(15,23,42,0.14);padding:8px;display:none;flex-direction:column;gap:2px;z-index:1300}
.ln-item:hover > .ln-menu,.ln-item.open > .ln-menu{display:flex}
.ln-menu a{display:block;padding:8px 12px;border-radius:7px;font-size:13.5px;color:var(--text-primary,#334155);text-decoration:none;white-space:nowrap;transition:background .12s,color .12s}
.ln-menu a:hover{background:var(--bg-alt,#f1f5f9);color:var(--accent,#0078d4)}
.ln-mgroup{font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--text-dim,#94a3b8);font-weight:700;margin:12px 0 2px;padding:0 2px}

/* The mobile menu is hidden until the hamburger opens it. Without this the
   whole mobile list renders inline under the desktop nav. */
.landing-mobile-menu{display:none;flex-direction:column;padding:12px 2rem 18px;border-top:1px solid var(--border,#e2e8f0);background:var(--surface-0,#fff)}
.landing-mobile-menu.open{display:flex}
@media (min-width: 861px){ .landing-mobile-menu{display:none !important} .landing-hamburger{display:none} }
@media (max-width: 860px){ .landing-nav-links{display:none} }

/* Solutions by Industry dropdown. Eleven entries is too many for the single
   narrow column the other menus use, so this one is wider and two-up on desktop.
   It links STRAIGHT to each industry page: a domain expert wants their own
   field, not a hub they then have to navigate down through. */
.ln-menu-wide {
  min-width: 460px;
  columns: 2;
  column-gap: 1.25rem;
}
.ln-menu-wide a { break-inside: avoid; }
.ln-menu-wide .ln-all {
  column-span: all;
  margin-top: 0.4rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
  font-weight: 600;
  color: var(--accent);
}
@media (max-width: 720px) {
  .ln-menu-wide { min-width: 0; columns: 1; }
}


/* ═══ PER-DOMAIN IDENTITY ═══════════════════════════════════════════════════
   Each industry page needs to feel like its own place while staying obviously
   the same product. flux already computes every accent shade from a single
   --accent-hue, so a domain gets its identity by setting that ONE number: the
   hue cascades through headings, stats, links, borders and the hero wash with
   no per-domain color ever hardcoded.

   It is scoped to .gap-page rather than :root on purpose. The nav and buttons
   keep the SITE accent - and the visitor's saved accent hue keeps working - so
   the chrome stays constant and only the content carries the domain color.
   Overriding :root would have thrown away the user preference the whole theme
   bootstrap exists to honour. */

/* ONE ACCENT, SITE-WIDE. 251 is Microsoft's communication blue in oklch terms (#0078d4 measures
 * 251.3), which is the adjacency the brand is built on: the blue says we belong in the stack the
 * buyer already runs, and the VaultSync red is what distinguishes us.
 *
 * This line previously read `--accent-hue: var(--domain-hue, 195)`, so each industry page took its
 * accent from its own domain hue - legal 232, finance 158, science 262, senior-care 168 - which is
 * eleven accent colours across one site, and none of them the brand's. Pages with no domain hue
 * fell through to flux's default 195 and came out cyan. It is why the industry pages did not match
 * the homepage.
 *
 * --domain-hue is still set on the body by the generator and is available for per-domain artwork.
 * It no longer drives type or controls. */
.gap-page { --accent-hue: 251; }

/* Hero wash. No image assets: two radial tints in the domain hue over a fine
   grid, which reads as designed at any width, costs no request, and recolors
   itself when the hue changes. */
.gap-hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 60% at 12% 0%,
      oklch(96% 0.05 var(--accent-hue) / 0.9), transparent 60%),
    radial-gradient(ellipse 50% 50% at 88% 20%,
      oklch(94% 0.07 var(--accent-hue) / 0.55), transparent 65%),
    var(--surface-0);
}
.gap-hero::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, oklch(60% 0.02 var(--accent-hue) / 0.07) 1px, transparent 1px),
    linear-gradient(to bottom, oklch(60% 0.02 var(--accent-hue) / 0.07) 1px, transparent 1px);
  background-size: 46px 46px;
  mask-image: radial-gradient(ellipse 80% 70% at 30% 0%, #000, transparent 75%);
  pointer-events: none;
}
.gap-hero > * { position: relative; }

/* The domain mark. Large, tinted, sitting with the label rather than floating. */
.gap-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  margin-bottom: 1rem;
  border-radius: 12px;
  font-size: 20px;
  color: var(--accent);
  background: oklch(94% 0.06 var(--accent-hue) / 0.8);
  border: 1px solid oklch(85% 0.06 var(--accent-hue) / 0.7);
}

/* Sections were 80px top and bottom with little in them, which read as empty
   rather than airy. Tightened, and the alternating band gets the domain tint
   instead of flat grey so the page has rhythm. */
.gap-page .landing-section { padding: 56px 2rem; }
.gap-page .landing-section-alt {
  background: oklch(97% 0.014 var(--accent-hue));
  border-top: 1px solid oklch(90% 0.02 var(--accent-hue) / 0.6);
  border-bottom: 1px solid oklch(90% 0.02 var(--accent-hue) / 0.6);
}

/* Each tool card carries the domain mark, so a card is identifiable at a glance
   instead of being an undifferentiated block of text. */
.gap-tool { position: relative; padding-left: 3.25rem; }
.gap-tool::before {
  content: '\f0c3';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  position: absolute;
  left: 1.4rem; top: 1.85rem;
  font-size: 15px;
  color: var(--accent);
  opacity: 0.75;
}
.gap-tool[data-icon]::before { content: attr(data-icon); }

/* The statistic block gets a left rule in the domain hue - the figures are the
   reason the page exists, so they should read as a unit. */
.gap-stat {
  padding-left: 0.9rem;
  border-left: 2px solid oklch(80% 0.09 var(--accent-hue) / 0.55);
}

.gap-cta { text-align: left; }
.gap-btns { margin-top: 1.5rem; }


/* ═══ SPLIT HERO ════════════════════════════════════════════════════════════
   The pages read as empty because everything sat in a single left-aligned
   column with the right half unused. Technical B2B pages give text and a visual
   equal weight; here the visual is the page's lead FIGURE, which is more use to
   a reader than an illustration would be and needs no image asset. */

.gap-split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.85fr);
  gap: 3.5rem;
  align-items: center;
}
.gap-split-copy .landing-section-sub { margin-bottom: 1.75rem; max-width: 34rem; }

.gap-proof {
  padding: 2rem 1.9rem;
  border-radius: 14px;
  background: var(--surface-0);
  border: 1px solid oklch(88% 0.04 var(--accent-hue) / 0.8);
  box-shadow: 0 18px 40px oklch(60% 0.05 var(--accent-hue) / 0.10);
}
.gap-proof-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 0.9rem;
}
/* Tabular figures so a percentage and a currency amount sit on the same
   baseline grid rather than drifting against each other. */
.gap-proof-n {
  font-size: clamp(38px, 5vw, 56px); font-weight: 300; line-height: 1;
  color: var(--text-bright); font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em; margin-bottom: 0.7rem;
}
.gap-proof-t { margin: 0 0 0.6rem; font-size: 14.5px; line-height: 1.6; color: var(--text-dim); }
.gap-proof-src {
  font-size: 12px; color: var(--text-muted, var(--text-dim));
  border-bottom: 1px dotted currentColor; text-decoration: none;
}
.gap-proof-src:hover { color: var(--accent); }
.gap-proof-rule { height: 1px; background: var(--border); margin: 1.4rem 0 1rem; }
.gap-proof-meta {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--text-dim);
}
.gap-proof-meta i { color: var(--accent); }

/* The closing call to action, contained rather than floating in a full-width
   band with nothing beside it. */
.gap-cta {
  padding: 2.5rem 2.25rem;
  border-radius: 14px;
  background: oklch(97% 0.02 var(--accent-hue));
  border: 1px solid oklch(90% 0.03 var(--accent-hue) / 0.8);
}
.gap-cta .landing-h2 { margin-bottom: 0.6rem; }
.gap-cta .landing-section-sub { margin-bottom: 0; max-width: 46rem; }

@media (max-width: 900px) {
  .gap-split { grid-template-columns: 1fr; gap: 2.25rem; }
  .gap-proof { order: 2; }
}


/* ═══ GEOMETRY ══════════════════════════════════════════════════════════════
   The first pass was all right angles and hard section edges, which read as a
   document rather than a product. Rounder surfaces and softer section joins,
   applied consistently so the pages still feel like one system. */

.gap-page .gap-proof,
.gap-page .gap-cta { border-radius: 18px; }
.gap-page .gap-tool { border-radius: 14px; }
.gap-mark { border-radius: 14px; }

/* Curve the tinted band instead of butting it flat against its neighbors. The
   inset + radius reads as a panel; a full-bleed rectangle reads as a rule. */
.gap-page .landing-section-alt {
  border: 1px solid oklch(90% 0.025 var(--accent-hue) / 0.7);
  border-radius: 24px;
  margin: 0 1.5rem;
  padding: 52px 2rem;
}

/* Give the hero a soft base curve so the transition into the next section is a
   shape rather than a line. */
.gap-hero {
  border-bottom-left-radius: 28px;
  border-bottom-right-radius: 28px;
}

/* Tool cards lift slightly on hover - enough to read as interactive, not enough
   to bounce. */
.gap-tool {
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}
.gap-tool:hover {
  transform: translateY(-2px);
  border-color: oklch(80% 0.07 var(--accent-hue) / 0.8);
  box-shadow: 0 12px 28px oklch(60% 0.05 var(--accent-hue) / 0.13);
}

@media (max-width: 700px) {
  .gap-page .landing-section-alt { margin: 0 0.75rem; border-radius: 18px; }
}


/* ═══ LIVE HERO DEMO ════════════════════════════════════════════════════════
   The real tool, running, in the hero. Framed as an instrument panel rather
   than a marketing card: a status dot, the tool's name, the live mount, and the
   privacy line. Nothing here claims anything the page cannot immediately
   demonstrate. */

.gap-live {
  padding: 1.5rem 1.5rem 1.25rem;
  border-radius: 18px;
  background: var(--surface-0);
  border: 1px solid oklch(86% 0.05 var(--accent-hue) / 0.85);
  box-shadow: 0 20px 46px oklch(60% 0.05 var(--accent-hue) / 0.14);
}
.gap-live-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 0.6rem;
}
/* A quiet pulse. It signals live without demanding attention, and it stops
   entirely for anyone who has asked for reduced motion. */
.gap-live-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px oklch(85% 0.09 var(--accent-hue) / 0.4);
  animation: gapPulse 2.4s ease-in-out infinite;
}
@keyframes gapPulse { 0%,100%{opacity:1} 50%{opacity:0.45} }
@media (prefers-reduced-motion: reduce) { .gap-live-dot { animation: none } }

.gap-live-name {
  font-size: 17px; font-weight: 600; color: var(--text-bright);
  margin-bottom: 0.9rem;
}
/* The mount is capped and scrolls internally: a plugin with a long form must
   not stretch the hero into a page of its own. */
.gap-live-mount {
  max-height: 430px; overflow: auto;
  border-radius: 12px;
  background: oklch(98% 0.008 var(--accent-hue));
  border: 1px solid var(--border);
  padding: 0.75rem;
}
.gap-live-foot {
  display: flex; align-items: center; gap: 8px;
  margin-top: 0.9rem; padding-top: 0.85rem;
  border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-dim);
}
.gap-live-foot i { color: var(--accent); }

@media (max-width: 900px) { .gap-live { order: 2; } }


/* ═══ SIGNATURE FIGURE ══════════════════════════════════════════════════════
   Each industry page carries a line figure drawn from its own subject - a decay
   curve for pharmacokinetics, a truss for structures, an orbit for aerospace.
   Generated inline, so there is no asset to ship, nothing to request, and it
   takes the domain hue automatically.

   It sits behind the copy at low opacity and is pinned to the right of the
   headline column, where the page previously had nothing. On narrow screens it
   is removed rather than shrunk: behind body text at phone width it would be
   noise, not texture. */

.gap-art {
  position: absolute;
  top: 50%;
  left: 46%;
  width: 300px;
  height: auto;
  transform: translateY(-50%);
  color: var(--accent);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  opacity: 0.13;
  pointer-events: none;
}
@media (max-width: 1100px) { .gap-art { display: none; } }


/* ═══ LOW-POLY HERO BACKDROP ════════════════════════════════════════════════
   Sits behind everything in the hero at half strength, masked so it fades out
   across the left where the headline and body copy sit. At full opacity it
   competes with the text; at half, with the mask, it reads as material. */

.gap-hero { position: relative; }

.gap-mesh {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.5;
  pointer-events: none;
  /* Copy space: transparent behind the headline at the left edge, ramping to
     full across the middle. The ramp reaches full BEFORE the demo panel starts,
     so the strongest faceting lands in the open band between the copy and the
     panel - the one part of the hero that was empty. */
  -webkit-mask-image: linear-gradient(100deg, transparent 3%, rgba(0,0,0,0.4) 26%, #000 52%);
  mask-image: linear-gradient(100deg, transparent 3%, rgba(0,0,0,0.4) 26%, #000 52%);
}

/* The fine grid was texture for a flat wash; against a faceted mesh it is
   clutter, so it goes. */
.gap-hero::before { display: none; }

/* The signature figure now sits ON the mesh, so it needs less presence. */
.gap-art { opacity: 0.09; }

@media (max-width: 900px) {
  .gap-mesh {
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 55%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 55%);
    opacity: 0.38;
  }
}

/* ═══ GAP HERO TYPE SCALE ═══════════════════════════════════════════════════
   SCOPED TO .gap-hero ON PURPOSE. .landing-section-label is the section kicker
   used 76 times across the site - 16 on the homepage alone - so resizing the
   bare class would enlarge every "AND THE REST OF THE PICTURE" on every page.
   Only the industry name in the hero changes here.

   The headline was the actual defect: the hero's <h1> carries class
   landing-h2, so it topped out at 36px while the homepage hero runs to 58px.
   A hero headline set smaller than the hero it leads is why the block read as
   undersized. It now takes a hero-scale ramp of its own.

   Letter-spacing is expressed in em rather than px. The kicker's 2px tracking
   is right at 11px type and enormous at 28px; em keeps the proportion as the
   size moves. */

.gap-hero .landing-section-label {
  font-size: 20px; /* fallback where clamp() is unavailable */
  font-size: clamp(18px, 2.2vw, 28px);
  letter-spacing: 0.07em;
  line-height: 1.25;
  margin-bottom: 0.85rem;
  color: var(--accent);
}

.gap-hero h1.landing-h2 {
  font-size: 40px; /* fallback */
  font-size: clamp(32px, 4.4vw, 52px);
  line-height: 1.14;
  letter-spacing: -0.015em;
  margin-bottom: 1.15rem;
}

/* The lede has to stay clearly subordinate to a headline that just grew. */
.gap-hero .landing-section-sub {
  font-size: 16px;
  font-size: clamp(15px, 1.15vw, 17px);
  max-width: 46ch;
}

/* The mobile menu's Login/Register are buttons, not anchors, so landing.js can
   bind them by id exactly as it does on the homepage. Buttons inherit none of
   the anchor styling around them, so they are matched to their neighbours
   explicitly rather than left looking like form controls in a nav. */
.ln-mauth {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  background: none;
  border: none;
  cursor: pointer;
}
.ln-mauth#landing-get-started-m { color: var(--accent); font-weight: 600; }
