/* Canonical shared UI. Run node scripts/sync-site-design.js after edits. */
:root {
  /* ---- Palette (PTM colour scales) ---- */
  --purple-50:  #f4f1fd;
  --purple-100: #e2dafb;
  --purple-200: #c6b6f7;
  --purple-300: #a991f3;
  --purple-400: #8d6cef;
  --purple-500: #7047eb;
  --purple-600: #5423e7;
  --purple-700: #4316ca;
  --purple-900: #2b0e81;

  --yellow-100: #fff3d6;
  --yellow-200: #ffe7ad;
  --yellow-300: #ffda85;
  --yellow-400: #ffce5c;
  --yellow-500: #ffc233;
  --yellow-700: #c28800;

  --green-100: #dff8ea;
  --green-200: #b2eecc;
  --green-400: #56d990;
  --green-500: #2dca72;
  --green-600: #26a95f;
  --green-700: #1e874c;

  --pink-100:   #fdddf8;
  --pink-500:   #f75fde;
  --pink-700:   #db0bb9;
  --orange-100: #ffe8e1;
  --orange-500: #ff7d52;
  --orange-600: #ff571f;
  --orange-700: #eb3a00;
  --blue-100:   #dbf3ff;
  --blue-200:   #ade4ff;
  --blue-500:   #00acff;
  --blue-700:   #0075ad;
  --plum-500:   #cf75ff;
  /* Danger - one family for the website, portal and dashboard. */
  --red-100:    #ffe0e7;
  --red-200:    #ffc2cf;
  --red-500:    #f53d6b;
  --red-600:    #e01a4c;
  --red-700:    #b3123a;

  --ink:      #121217;
  --ink-2:    #1c1c24;
  --grey-700: #3f3f50;
  --grey-500: #6c6c89;
  --grey-300: #a9a9bc;
  --grey-200: #d1d1db;
  --grey-100: #e8e8ed;
  --smoke:    #f7f7f8;
  --white:    #ffffff;

  /* ---- Semantic (light ground = default) ---- */
  --page:       var(--white);
  --text:       var(--ink);
  --muted:      var(--grey-500);
  --muted-2:    var(--grey-300);
  --surface:    var(--white);
  --surface-2:  var(--smoke);
  --hairline:   var(--grey-100);
  --hairline-2: var(--grey-200);
  --brand:      var(--purple-600);
  --brand-soft: var(--purple-50);
  --accent:     var(--yellow-500);
  --accent-text: var(--on-amber);
  --ok-text:    var(--on-green);

  /* Foreground for small text on the matching -100 tint. The brand -700 steps
     read fine as large shapes but land at 2.8-4.4:1 as 12-15px text, so chips
     and inline accents use these instead. Measured ratios in comments. */
  --on-purple: #4316ca;   /* 7.10 on purple-100 */
  --on-orange: #c22f00;   /* 4.83 on orange-100 */
  --on-green:  #1a7844;   /* 4.92 on green-100, 5.51 on white */
  --on-pink:   #b8089b;   /* 4.76 on pink-100  */
  --on-blue:   #006391;   /* 5.72 on blue-100  */
  --on-amber:  #8a6000;   /* 5.07 on yellow-100, 5.59 on white */
  --on-red:    #b3123a;   /* 5.57 on red-100, 6.85 on white */
  --on-grey:   #5c5c75;   /* 5.30 on grey-100  */
  --grad:       linear-gradient(96deg, var(--purple-500), var(--purple-600) 60%, var(--purple-700));

  /* ---- Shape & depth ---- */
  --radius-sm: 12px;
  --radius:    20px;
  --radius-lg: 28px;
  --radius-xl: 40px;
  --pill:      999px;
  --shadow-sm:   0 1px 2px rgba(18, 18, 23, 0.04), 0 4px 12px -6px rgba(18, 18, 23, 0.08);
  --shadow:      0 2px 4px rgba(18, 18, 23, 0.04), 0 18px 40px -24px rgba(18, 18, 23, 0.22);
  --shadow-lift: 0 4px 8px rgba(18, 18, 23, 0.05), 0 32px 64px -28px rgba(18, 18, 23, 0.28);
  --shadow-float: 0 40px 90px -40px rgba(20, 6, 74, 0.55), 0 8px 24px -12px rgba(20, 6, 74, 0.35);

  /* ---- Type scale (root = 16px). Every size below display level maps here. ---- */
  --fs-2xs:  0.6875rem;   /* 11px - dense mock labels        */
  --fs-xs:   0.75rem;     /* 12px - micro labels, pills      */
  --fs-sm:   0.8125rem;   /* 13px - meta, captions, notes    */
  --fs-md:   0.875rem;    /* 14px - secondary UI text        */
  --fs-base: 0.9375rem;   /* 15px - card + list body         */
  --fs-lg:   1rem;        /* 16px - body copy                */
  --fs-xl:   1.0625rem;   /* 17px - large buttons, sub-heads */
  --fs-2xl:  1.1875rem;   /* 19px - doc intro, panel titles  */
  --fs-3xl:  1.3125rem;   /* 21px - small headings           */
  --track-label: 0.14em;  /* every uppercase micro-label     */

  --maxw: 1180px;
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-display: 'Outfit', 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* ---------- Buttons: full pills, medium weight, flat ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: var(--font-sans);
  font-weight: 500; font-size: var(--fs-lg); letter-spacing: -0.012em;
  padding: 14px 28px;
  border-radius: var(--pill);
  border: 1px solid transparent;
  transition: transform .18s cubic-bezier(.2,.8,.3,1), background .2s ease, border-color .2s ease, color .2s ease, box-shadow .2s ease;
  white-space: nowrap;
}
.btn svg { width: 18px; height: 18px; }
/* Hover/press feedback only on buttons that can be used. A disabled button
   keeps the one disabled look below and never changes colour on hover. */
.btn:hover:not(:disabled) { transform: translateY(-2px); }
.btn:active:not(:disabled) { transform: translateY(0); }

/* Primary: brand violet on light ground, plain white on dark ground */
.btn-primary { background: var(--purple-600); color: var(--white); }
.btn-primary:hover:not(:disabled) { background: var(--purple-700); }
.hero .btn-primary,
.doc-hero .btn-primary,
.band .btn-primary,
.sec-purple .btn-primary,
.sec-ink .btn-primary,
.cta .btn-primary,
.site-footer .btn-primary { background: var(--white); color: var(--ink); }
.hero .btn-primary:hover:not(:disabled),
.doc-hero .btn-primary:hover:not(:disabled),
.band .btn-primary:hover:not(:disabled),
.sec-purple .btn-primary:hover:not(:disabled),
.sec-ink .btn-primary:hover:not(:disabled),
.cta .btn-primary:hover:not(:disabled),
.site-footer .btn-primary:hover:not(:disabled) { background: var(--yellow-500); color: var(--ink); }

/* Accent is deliberately reserved for one recommended or time-sensitive
   action in a local group (for example, starting a featured trial). Keeping
   it here, alongside the other button voices, prevents product-specific
   pages from rendering an unstyled `btn-accent` link or button. */
.btn-accent {
  background: var(--yellow-500);
  color: var(--ink);
  font-weight: 600;
  box-shadow: 0 4px 14px -2px rgba(255, 194, 51, 0.35);
}
.btn-accent:hover:not(:disabled) {
  background: var(--yellow-400);
  color: var(--ink);
  box-shadow: 0 8px 20px -4px rgba(255, 194, 51, 0.5);
}

/* Ghost: hairline chip on light, translucent fill on dark */
.btn-ghost {
  background: var(--white);
  color: var(--ink);
  border-color: var(--grey-200);
}
.btn-ghost:hover:not(:disabled) { border-color: var(--purple-300); color: var(--purple-600); }
.hero .btn-ghost,
.doc-hero .btn-ghost,
.band .btn-ghost,
.sec-purple .btn-ghost,
.sec-ink .btn-ghost,
.cta .btn-ghost,
.site-footer .btn-ghost {
  background: rgba(255, 255, 255, 0.14);
  color: var(--white);
  border-color: transparent;
}
.hero .btn-ghost:hover:not(:disabled),
.doc-hero .btn-ghost:hover:not(:disabled),
.band .btn-ghost:hover:not(:disabled),
.sec-purple .btn-ghost:hover:not(:disabled),
.sec-ink .btn-ghost:hover:not(:disabled),
.cta .btn-ghost:hover:not(:disabled),
.site-footer .btn-ghost:hover:not(:disabled) { background: rgba(255, 255, 255, 0.24); color: var(--white); }

/* Disabled - ONE look for every variant: neutral grey, never a faded brand
   colour (a half-transparent violet reads as a second, paler brand shade
   rather than "not available right now"). Same tokens as the dashboard.
   A button that is only busy (aria-busy, showing a spinner while a request
   runs) keeps its normal colour so a submit doesn't flash grey. */
.btn:disabled:not([aria-busy="true"]) {
  background: var(--grey-100);
  color: var(--grey-500);
  border-color: var(--grey-100);
  box-shadow: none;
  cursor: not-allowed;
}
.hero .btn:disabled:not([aria-busy="true"]),
.doc-hero .btn:disabled:not([aria-busy="true"]),
.band .btn:disabled:not([aria-busy="true"]),
.sec-purple .btn:disabled:not([aria-busy="true"]),
.sec-ink .btn:disabled:not([aria-busy="true"]),
.cta .btn:disabled:not([aria-busy="true"]),
.site-footer .btn:disabled:not([aria-busy="true"]) {
  background: rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.5);
  border-color: transparent;
}
.btn[aria-busy="true"] { cursor: progress; }

.btn-lg { font-size: var(--fs-xl); padding: 17px 34px; }
.btn-block { display: flex; width: 100%; }

/* Shared navigation: identical on the website and customer portal. */
.site-header { position: fixed; inset: 0 0 auto; z-index: 60; background: var(--white); color: var(--ink); border-bottom: 1px solid var(--hairline); }
.site-header.scrolled { box-shadow: var(--shadow-sm); }
.site-header .nav { display: flex; align-items: center; justify-content: space-between; gap: 20px; height: 76px; }
.brand { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-display); font-size: 19px; letter-spacing: -.03em; white-space: nowrap; }
.brand b { font-weight: 500; }
.site-header .brand img { width: 32px; height: 32px; filter: brightness(.78) saturate(1.35); }
.nav-links { display: flex; align-items: center; gap: 20px; }
.nav-links a { font-size: 14px; font-weight: 500; color: var(--grey-700); }
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--brand); }
.nav-cta { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.nav-cta .btn { padding: 10px 18px; font-size: 14px; white-space: nowrap; }

.nav-toggle { display: none; position: relative; padding: 10px; border-radius: 10px; }
.nav-toggle svg { width: 24px; height: 24px; }
.nav-toggle .icon-menu { transition: opacity .18s ease, transform .18s ease; }
.nav-toggle .icon-close {
  position: absolute; top: 50%; left: 50%;
  width: 24px; height: 24px;
  transform: translate(-50%, -50%) rotate(-45deg) scale(.5);
  opacity: 0;
  transition: opacity .18s ease, transform .18s ease;
}
.site-header.menu-open .nav-toggle .icon-menu { opacity: 0; transform: rotate(45deg) scale(.5); }
.site-header.menu-open .nav-toggle .icon-close { opacity: 1; transform: translate(-50%, -50%) rotate(0) scale(1); }

/* Fixed height so every small pill button is identical across the website nav
   and the portal header, regardless of each context's inherited line-height
   (which otherwise rendered the same button 44px in one place and 40px in
   another). Horizontal padding only; the flex box centres the label. */
.btn-sm { font-size: 14px; height: 44px; padding: 0 18px; }
.btn-ic { width: 16px; height: 16px; flex-shrink: 0; }
@media (max-width: 1120px) {
  .site-header .nav-links { display: none; }
  .site-header .nav-toggle { display: flex; }
  /* Fixed, not absolute, so the panel always spans the full remaining
     viewport regardless of scroll position - a short dropdown left the
     page visible and scrollable underneath it. main.js locks body scroll
     to match; overflow-y here only kicks in if the link list is ever
     taller than the screen (a small phone in landscape). */
  .site-header.menu-open .nav-links {
    display: flex; position: fixed; top: 76px; left: 0; right: 0; bottom: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 4px 24px 24px;
    background: var(--white);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    animation: navPanelIn .2s ease both;
  }
  .site-header.menu-open .nav-links a { padding: 14px 0; font-size: 16px; color: var(--grey-700); border-bottom: 1px solid var(--hairline); }
}
@keyframes navPanelIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (max-width: 480px) {
  .site-header .nav { height: 64px; gap: 8px; padding-inline: 16px; }
  .site-header .brand { font-size: 17px; gap: 7px; }
  .site-header .brand img { width: 28px; height: 28px; }
  .site-header .nav-cta .btn { padding: 9px 12px; font-size: 12px; }
  .site-header .nav-cta .btn-ghost { display: none; }
  .site-header.menu-open .nav-links { top: 64px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

.site-header .mobile-auth-link { display: none; }
@media (max-width: 480px) {
  .site-header.menu-open .mobile-auth-link { display: block; }
}

/* ---------- Signed-in header control ----------
   Once a customer is signed in, the Sign in / Start trial buttons are replaced
   by this single avatar - the first letter of their name - which opens their
   dashboard. It is the only signed-in control in the header; Sign out lives in
   the dashboard itself. The identity card (name, email, action) is a styled
   tooltip rather than the browser's native one, so it looks the same
   everywhere. Single source of truth for both the website and the portal
   (injected by main.js on the website, toggled by app.js on the portal);
   neither may redefine it. */
.user-profile-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex-shrink: 0;
  border-radius: 50%;
  background: var(--brand); color: var(--white);
  font-size: 17px; font-weight: 600; line-height: 1;
  transition: background .18s ease, box-shadow .18s ease;
}
.user-profile-initial { text-transform: uppercase; }
.user-profile-btn:hover { background: var(--purple-700); box-shadow: 0 0 0 4px rgba(84, 35, 231, 0.16); }
.user-profile-btn:focus-visible { outline: 2px solid var(--purple-600); outline-offset: 3px; }

.user-profile-tip {
  position: absolute; top: calc(100% + 12px); right: 0; z-index: 70;
  display: grid; gap: 2px;
  /* max-content, not the default shrink-to-fit: inside a 44px button the
     default collapses the card to its minimum width and wraps the email
     mid-word. It now grows to its longest line, up to the cap, then wraps. */
  width: max-content; min-width: 200px; max-width: min(300px, calc(100vw - 76px));
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--ink); color: var(--white);
  box-shadow: var(--shadow-lift);
  text-align: left; font-size: 13px; font-weight: 400; line-height: 1.4;
  cursor: pointer;
  /* Hidden = visibility: hidden, which also stops it catching clicks. While
     shown it is part of the link: the pointer can move onto it and a click
     anywhere on the card opens the dashboard. Closing waits a moment, so a
     pointer that drifts off the avatar or the card edge does not lose it. */
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .15s ease .2s, transform .15s ease .2s, visibility 0s linear .35s;
}
/* Invisible bridge over the gap between avatar and card, so the pointer never
   leaves the link on its way down. */
.user-profile-tip::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 14px;
}
/* Arrow, centred under the 44px avatar (22px from its right edge). */
.user-profile-tip::before {
  content: ""; position: absolute; top: -5px; right: 17px;
  width: 10px; height: 10px; background: var(--ink);
  transform: rotate(45deg); border-radius: 2px;
}
/* Explicit colour: page-level rules (e.g. the portal's own strong) would
   otherwise make the name dark-on-dark. */
.user-profile-tip strong { color: var(--white); font-size: 14px; font-weight: 600; overflow-wrap: anywhere; }
.user-profile-tip .user-profile-email { color: rgba(255, 255, 255, 0.68); overflow-wrap: anywhere; }
.user-profile-tip .user-profile-action {
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--yellow-500); font-style: normal; font-weight: 500;
}
.user-profile-btn:hover .user-profile-tip,
.user-profile-btn:focus-visible .user-profile-tip {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity .15s ease, transform .15s ease, visibility 0s;
}
.user-profile-tip:hover .user-profile-action { text-decoration: underline; text-underline-offset: 3px; }
/* Touch screens have no hover: a tap goes straight to the dashboard. */
@media (hover: none) { .user-profile-tip { display: none; } }
@media (max-width: 480px) {
  .user-profile-btn { width: 40px; height: 40px; font-size: 16px; }
  .user-profile-tip::before { right: 15px; }
}

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); padding: 80px 0 36px; }
.footer-grid {
  display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
  gap: 44px; padding-bottom: 48px;
}
.footer-brand .brand { color: var(--white); margin-bottom: 16px; }
.footer-brand p { font-size: var(--fs-base); line-height: 1.65; max-width: 34ch; color: rgba(255, 255, 255, 0.6); }
.footer-col { display: grid; gap: 12px; align-content: start; }
.footer-col h3 {
  font-family: var(--font-sans); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: rgba(255, 255, 255, 0.58); margin-bottom: 4px;
}
.footer-col a { font-size: var(--fs-base); color: rgba(255, 255, 255, 0.72); transition: color .18s ease; }
.footer-col a:hover { color: var(--yellow-500); }
.footer-bottom {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: var(--fs-md); color: rgba(255, 255, 255, 0.5);
}
.footer-bottom-compact { padding-top: 0; border-top: none; }
.footer-home-link { color: rgba(255, 255, 255, 0.72); }
.footer-home-link:hover { color: var(--yellow-500); }


.site-footer .brand img { width: 32px; height: 32px; }
.site-footer .brand b { color: var(--yellow-500); }
@media (max-width: 980px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; } }
@media (max-width: 720px) { .footer-grid { grid-template-columns: minmax(0, 1fr); gap: 28px; } .footer-bottom { flex-direction: column; text-align: center; } }

@media (max-width: 360px) {
  .site-header .brand { font-size: 15px; gap: 6px; }
  .site-header .brand img { width: 24px; height: 24px; }
  .site-header .nav { gap: 4px; }
  .site-header .nav-cta { gap: 4px; }
  .site-header .nav-toggle { padding: 8px; }
}
