/* ============================================================
   luxechain.ai — design tokens + base
   Light, warm-neutral. Every contrast pair computed and verified.
   Rule: semantic tokens only. No raw hex in components.
   ============================================================ */

:root {
  /* surfaces — warm stone, not cold grey */
  --background: #FAFAF9;
  --card:       #FFFFFF;
  --raised:     #FFFFFF;
  --muted:      #F4F4F2;
  --muted-2:    #EFEFED;

  /* text */
  --ink-900: #0C0A09;   /* 18.9:1 — headings          */
  --ink-700: #292524;   /* 14.5:1 — body              */
  --ink-500: #57534E;   /*  7.3:1 — secondary         */
  --ink-400: #78716C;   /*  4.6:1 — captions (floor)  */

  /* lines */
  --border:        #DCD8D4;  /* 1.4:1  decorative hairlines — strong enough to hold a card edge */
  --border-strong: #78716C;  /* 4.6:1  inputs, focusable controls */

  /* accent — warm yellow (design #7's signature).
     Yellow is a FILL colour. It must always carry dark ink (--accent-fg) and
     must never be used as a text colour on a light surface: yellow on white is
     1.5:1. Text and emphasis use --accent-ink, which clears 4.5:1. */
  --accent:      #FFC72C;  /* 12.66:1 against --accent-fg */
  --accent-fg:   #0C0A09;  /* ink that sits ON the yellow */
  --accent-hover:#F0B71A;
  --accent-soft: #FFF6DC;  /* tinted surface, 5.14:1 with --accent-ink */
  --accent-ink:  #8A6100;  /* 5.30:1 on --background — the TEXT accent */

  /* status */
  --danger:    #9F1239;
  --danger-fg: #FFFFFF;
  --danger-soft:#FFF1F2;
  --warn:      #B45309;
  --warn-soft: #FFFBEB;
  --ok-soft:   #DCFCE7;   /* success state stays green — it means "ok", not "brand" */

  /* type */
  --font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --font-sans: "Instrument Sans", -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* motion */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --dur-fast: 140ms;
  --dur:      200ms;
  --dur-slow: 320ms;

  /* geometry */
  --r-sm: 6px;
  --r:    10px;
  --r-lg: 14px;
  /* Wide canvas: the old 1180px cap left 130px+ of dead gutter on a 1440
     screen and much more on larger ones. 1340px uses the space while keeping
     body copy at a readable measure (long prose sections stay on .wrap-narrow). */
  --maxw: 1340px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

html, body { margin: 0; padding: 0; }

body {
  background-color: var(--background);
  /* A very faint grid texture so the page never reads as flat empty paper.
     0.028 alpha: invisible as a pattern, but it gives the wide margins body. */
  background-image:
    linear-gradient(to right, rgba(12,10,9,.028) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(12,10,9,.028) 1px, transparent 1px);
  background-size: 58px 58px;
  color: var(--ink-700);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Content sits above the fixed ambient layer (z-index 0). */
.site-header, main, .site-footer { position: relative; z-index: 1; }

h1, h2, h3, h4 {
  margin: 0;
  color: var(--ink-900);
  line-height: 1.12;
  letter-spacing: -0.015em;
  font-weight: 500;
}
h1, h2 { font-family: var(--font-display); font-weight: 400; letter-spacing: -0.005em; }

p { margin: 0; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font-family: inherit; }

code, pre, .mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* ---------- focus: always visible, never removed ---------- */
:focus-visible {
  /* Yellow is 1.55:1 on the page background, which fails WCAG 1.4.11 for a focus
     indicator. The ink accent clears 5.3:1 and reads as the same brand family. */
  outline: 2px solid var(--accent-ink);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* ---------- layout ---------- */
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 28px; }
html, body { overflow-x: hidden; }
img, svg, video, canvas { max-width: 100%; height: auto; }
/* long unbroken strings (API keys, URLs) wrap instead of overflowing */
code, pre, .mono { overflow-wrap: anywhere; }
.wrap-narrow { max-width: 760px; margin: 0 auto; padding: 0 28px; }

.muted { color: var(--ink-500); }
.small { font-size: 13.5px; }
.tiny  { font-size: 12.5px; }

/* ---------- motion (opt-in, reduced-motion safe) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(14px); }
  .reveal.in {
    opacity: 1; transform: none;
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
  }
  .reveal.d1 { transition-delay: 60ms; }
  .reveal.d2 { transition-delay: 120ms; }
  .reveal.d3 { transition-delay: 180ms; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
}

/* ============================================================ header */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(250, 250, 249, 0.88);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--border);
}
.nav {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 66px; gap: 24px;
}

/* ---------------------------------------------------------------
   LuxeChain logo — mark + wordmark lockup.
   One component, used in the header, footer, admin sidebar, admin login card
   and the checkout summary, so the brand can never drift between pages.

   Why inline SVG rather than an <img>: an <img> loads in its own document and
   cannot inherit `currentColor` or these custom properties, so it could not
   adapt to the light header and the dark footer from one file.

   The gradient stops are variables, and the mark and the wordmark read the SAME
   ones — so the two can never drift, and dark mode is one override.
   --------------------------------------------------------------- */
.lx-logo {
  display: inline-flex; align-items: center; gap: .58em;
  font-size: 26px;            /* the single sizing dial */
  line-height: 1;
  color: inherit;
  text-decoration: none;
  /* the sparkle sits above the cap and the orbit below the baseline, so the
     optical centre is a hair lower than the geometric one */
  transform: translateY(0.5px);
}
/* The mark is sized against the wordmark's CAP HEIGHT, not its line box. The
   wordmark cap is 0.68em of the 1em type size, so ~1.16em of mark reads as the
   same visual weight. At 1.42em the icon dominated the name. */
.lx-logo-mark { display: block; width: 1.16em; height: 1.16em; flex-shrink: 0; }
.lx-logo-mark > svg { display: block; width: 100%; height: 100%; }
.lx-logo-word { display: block; height: .95em; }
.lx-logo-word > svg { display: block; height: 100%; width: auto; }
.lx-word { font-family: var(--font-sans); font-weight: 700; }
.lx-logo:hover { opacity: .88; }

/* Gradient stops. Light values are the verified-contrast pair; anything with
   `data-theme="dark"` (or a dark surface) re-points them, and the mark and the
   wordmark both follow. */
.lx-logo, .lx-mark {
  --lx-g1: #3EC6FF; --lx-g2: #2E7BFF; --lx-g3: #8B5CF6;
  --lx-w1: #0B6BCB; --lx-w2: #6D28D9;
}
[data-theme="dark"] .lx-logo, [data-theme="dark"] .lx-mark,
.lx-logo--dark, .lx-mark--dark {
  --lx-g1: #67E8F9; --lx-g2: #5CC8FF; --lx-g3: #C4B5FD;
  --lx-w1: #5CC8FF; --lx-w2: #C4B5FD;
}

/* Accent band, print, or any busy background: collapse the mark to one flat
   tone so it reads as a deliberate stamp rather than a gradient pasted on. */
.lx-mark--solid path, .lx-mark--solid ellipse { fill: currentColor !important; stroke: currentColor !important; }
.lx-logo--solid .lx-word tspan { fill: currentColor !important; }

/* Below ~20px the 3.6-unit orbit stroke and the sparkle fall under one device
   pixel and smear into a blob, and a gradient renders as a mid-tone wash with
   no clean edge. So small mode drops both and flattens the blade to a solid
   tone: at that size a legible letter beats a detailed logo. */
.lx-logo[data-size="sm"] .lx-mark-ring,
.lx-logo[data-size="sm"] .lx-mark-spark,
.lx-mark--small .lx-mark-ring,
.lx-mark--small .lx-mark-spark { display: none; }
.lx-logo[data-size="sm"] .lx-mark-blade,
.lx-mark--small .lx-mark-blade { fill: currentColor; }
.nav-links { display: flex; align-items: center; gap: 26px; }
.nav-links a {
  color: var(--ink-500); font-size: 14.5px; font-weight: 500;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--ink-900); }
.nav-actions { display: flex; align-items: center; gap: 10px; }

/* mobile menu — hidden on desktop */
.nav-burger { display: none; }
.mobile-menu { display: none; }

/* ============================================================ buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 44px; padding: 0 18px;
  border-radius: var(--r-sm);
  font-size: 14.5px; font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--accent); color: var(--accent-fg); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-ghost {
  background: var(--card); color: var(--ink-900);
  border-color: var(--border-strong);
}
.btn-ghost:hover { background: var(--muted); }
.btn-quiet { background: transparent; color: var(--ink-700); }
.btn-quiet:hover { background: var(--muted); color: var(--ink-900); }
.btn-danger { background: var(--danger); color: var(--danger-fg); }
.btn-sm { min-height: 36px; padding: 0 13px; font-size: 13.5px; }
.btn-lg { min-height: 50px; padding: 0 24px; font-size: 15.5px; }
.btn-block { width: 100%; }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

/* ============================================================ hero */
.hero { padding: 80px 0 56px; }
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 56px; align-items: center;
}
/* grid/flex children default to min-width:auto, so one wide child (a <pre>,
   a table, a long unbroken string) stretches the whole page. */
.hero-grid > *, .plans > *, .grid > *, .stats > * { min-width: 0; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-mono); font-size: 12px;
  color: var(--accent-ink); letter-spacing: 0.02em;
  background: var(--accent-soft);
  border-radius: 999px; padding: 5px 12px; margin-bottom: 22px;
}
.eyebrow .pip { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }

.hero h1 {
  font-size: clamp(2.4rem, 5vw, 3.75rem);
  color: var(--ink-900);
  max-width: 15ch;
}
.hero h1 em {
  font-style: italic;
  color: var(--accent-ink);
}
.hero .sub {
  color: var(--ink-500); font-size: 1.06rem;
  max-width: 46ch; margin-top: 20px; line-height: 1.65;
}
.hero-cta { display: flex; gap: 10px; margin-top: 30px; flex-wrap: wrap; }
.hero-note {
  margin-top: 14px; font-size: 13px; color: var(--ink-400);
  font-family: var(--font-mono);
}

/* ============================================================ code block */
.code {
  background: var(--ink-900);
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--ink-900);
}
.code-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 14px;
  border-bottom: 1px solid rgba(255,255,255,0.09);
}
.code-head .title {
  font-family: var(--font-mono); font-size: 12px;
  color: #A8A29E; letter-spacing: 0.03em;
}
.copy-btn {
  background: rgba(255,255,255,0.08); color: #E7E5E4;
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 5px; padding: 4px 10px;
  font-family: var(--font-mono); font-size: 11.5px;
  cursor: pointer; min-height: 26px;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.copy-btn:hover { background: rgba(255,255,255,0.16); color: #FFFFFF; }
.copy-btn.done { background: var(--accent); color: var(--accent-fg)FFF; border-color: var(--accent-ink); }

.code pre {
  margin: 0; padding: 16px 18px; overflow-x: auto;
  max-width: 100%;
  font-size: 12.8px; line-height: 1.85;
  color: #E7E5E4;
}
.code .k { color: #93C5FD; }   /* keys   */
.code .s { color: #86EFAC; }   /* strings*/
.code .c { color: #9A9490; }   /* comments — 6.6:1 on code bg, readable */
.code .n { color: #FDBA74; }   /* numbers*/

/* light code block variant (docs) */
.code.light { background: var(--muted); border-color: var(--border); }
.code.light .code-head { border-bottom-color: var(--border); }
.code.light .code-head .title { color: var(--ink-500); }
.code.light .copy-btn {
  background: var(--card); color: var(--ink-700); border-color: var(--border-strong);
}
.code.light .copy-btn:hover { background: var(--background); color: var(--ink-900); }
.code.light pre { color: var(--ink-700); }
.code.light .k { color: #1D4ED8; }
.code.light .s { color: var(--accent-ink); }
.code.light .c { color: var(--ink-500); }
.code.light .n { color: #B45309; }

/* ============================================================ sections */
section { padding: 68px 0; }
section.tight { padding: 44px 0; }
.sec-head { margin-bottom: 36px; max-width: 62ch; }
.sec-head { max-width: 100%; }
.sec-head h1, .sec-head h2 {
  overflow-wrap: break-word; font-size: clamp(1.7rem, 3.2vw, 2.35rem); margin-bottom: 12px; }
.sec-head p { color: var(--ink-500); font-size: 1rem; }
.sec-head.center { margin-left: auto; margin-right: auto; text-align: center; }

/* minor sections — smaller heading so major sections lead the page */
.sec-head.minor h1, .sec-head.minor h2 { font-size: clamp(1.25rem, 2.2vw, 1.5rem); }
.sec-head.minor { margin-bottom: 22px; }
.sec-head.minor p { font-size: 14.5px; }

.rule { height: 1px; background: var(--border); border: 0; margin: 0; }

/* ============================================================ stats strip */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.stat { padding: 26px 20px; border-right: 1px solid var(--border); }
.stat:last-child { border-right: 0; }
.stat .v {
  font-family: var(--font-mono); font-size: 26px; font-weight: 600;
  color: var(--ink-900); letter-spacing: -0.02em;
}
.stat .l { font-size: 12.5px; color: var(--ink-500); margin-top: 4px;
           text-transform: uppercase; letter-spacing: 0.05em; }

/* ============================================================ cards */
/* `.gN` classes are used both alone (`class="g3"`) and alongside `.grid`
   (`class="grid g3"`). They used to set only grid-template-columns, so a bare
   `g3` fell back to a block and its cards stacked full-width. Each one is now
   a complete grid container. */
.grid { display: grid; gap: 16px; }
.g2 { display: grid; gap: 16px; grid-template-columns: repeat(2, 1fr); }
.g3 { display: grid; gap: 16px; grid-template-columns: repeat(3, 1fr); }
.g4 { display: grid; gap: 16px; grid-template-columns: repeat(4, 1fr); }
.g5 { display: grid; gap: 16px; grid-template-columns: repeat(5, 1fr); }

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 24px;
}
.card h3 { font-size: 15.5px; margin-bottom: 7px; font-weight: 600; }
.card p { color: var(--ink-500); font-size: 15px; line-height: 1.6; }

/* Closing call-to-action band. The markup in about.html asked for .cta-band but
   no rule existed, so it rendered as a plain left-aligned block instead of the
   intended side-by-side band. */
.cta-band {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  background: var(--muted); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 26px 28px;
}
.card .ico {
  width: 34px; height: 34px; border-radius: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
  display: grid; place-items: center; margin-bottom: 12px;
}
.card .ico svg { width: 17px; height: 17px; }

/* ============================================================ steps */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
         border: 1px solid var(--border); border-radius: var(--r-lg);
         overflow: hidden; background: var(--card); }
.step { padding: 28px 26px; border-right: 1px solid var(--border); }
.step:last-child { border-right: 0; }
.step .n {
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  color: var(--accent-ink); margin-bottom: 14px; letter-spacing: 0.06em;
}
.step h3 { font-size: 15.5px; margin-bottom: 7px; }
.step p { color: var(--ink-500); font-size: 14px; }

/* ============================================================ pricing */
/* The column count follows the number of plans (--c-xl, set on the element and
   capped at 5) so adding or removing a plan in admin re-flows the row instead
   of squeezing the cards into a fixed 5-up and leaving an empty column. */
.plans {
  display: grid;
  grid-template-columns: repeat(var(--c-xl, 5), minmax(0, 1fr));
  gap: 12px;
}
/* One or two plans would stretch to fill the whole width — cap and centre. */
.plans[data-count="1"] { max-width: 380px; margin-inline: auto; }
.plans[data-count="2"] { max-width: 760px; margin-inline: auto; }
.plan {
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: var(--r-lg); padding: 22px 20px;
  display: flex; flex-direction: column; position: relative;
}
.plan.featured { border-color: var(--accent-ink); border-width: 2px; padding: 21px 19px; }
.plan .badge {
  position: absolute; top: -10px; left: 18px;
  background: var(--accent); color: var(--accent-fg);
  font-size: 10.5px; font-weight: 700; padding: 3px 10px;
  border-radius: 999px; letter-spacing: 0.06em; text-transform: uppercase;
}
.plan .pname {
  font-size: 12.5px; font-weight: 600; color: var(--ink-400);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.plan .price {
  font-family: var(--font-mono); font-size: 30px; font-weight: 600;
  color: var(--ink-900); letter-spacing: -0.03em; margin: 8px 0 2px;
}
.plan .price small { font-size: 13px; color: var(--ink-400); font-weight: 400; }
.plan .credits {
  font-family: var(--font-mono); font-size: 12.5px; color: var(--accent-ink);
  margin-bottom: 16px;
}
.plan .tagline {
  font-size: 13.5px; color: var(--ink-500); margin-bottom: 18px;
  min-height: 40px; line-height: 1.5;
}
.plan .btn { margin-top: auto; }

/* ============================================================ model rows */
.tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 20px; }
.tab {
  background: var(--card); border: 1px solid var(--border-strong);
  color: var(--ink-500); border-radius: 999px;
  padding: 8px 16px; font-size: 13.5px; font-weight: 600;
  cursor: pointer; min-height: 38px;
  transition: all var(--dur-fast) var(--ease-out);
}
.tab:hover { color: var(--ink-900); background: var(--muted); }
.tab[aria-selected="true"] {
  background: var(--ink-900); color: #FFFFFF; border-color: var(--ink-900);
}

.models { border: 1px solid var(--border); border-radius: var(--r-lg);
          overflow: hidden; background: var(--card); }
.mrow {
  display: grid; grid-template-columns: 1fr auto auto;
  gap: 18px; align-items: center;
  padding: 14px 20px; border-bottom: 1px solid var(--border);
}
.mrow:last-child { border-bottom: 0; }
.mrow:hover { background: var(--muted); }
.mname { font-weight: 600; font-size: 14.5px; color: var(--ink-900); }
.mmaker { color: var(--ink-400); font-size: 12px; font-family: var(--font-mono);
          margin-top: 2px; }
.mprice { font-family: var(--font-mono); font-size: 12.8px; color: var(--ink-500);
          text-align: right; white-space: nowrap; }
.mprice b { color: var(--ink-900); font-weight: 600; }
/* The price leads and the credit figure supports it. The lead is the number a
   newcomer can act on (money for the model's own unit); the credits are what
   they actually buy, so both are present but not competing. --ink-900 on --card
   is 18.9:1 and --ink-500 is 7.3:1, both clear of the 4.5:1 body floor. */
.mprice-main { font-family: var(--font-sans); font-size: 15px; font-weight: 650;
               color: var(--ink-900); letter-spacing: -.01em; line-height: 1.25; }
.mprice-main span { font-family: var(--font-sans); font-size: 11.5px;
                    font-weight: 400; color: var(--ink-400); letter-spacing: 0; }
.mprice-sub { font-size: 11.5px; color: var(--ink-400); margin-top: 2px; }
.mtag { font-size: 11px; font-family: var(--font-mono); color: var(--accent-ink);
        background: var(--accent-soft); padding: 2px 8px; border-radius: 999px;
        white-space: nowrap; }

/* ============================================================ faq */
.faq { border-top: 1px solid var(--border); max-width: 820px; }
.faq details { border-bottom: 1px solid var(--border); background: transparent; }
.faq summary {
  padding: 20px 4px; cursor: pointer; font-weight: 600; font-size: 15px;
  color: var(--ink-900); list-style: none;
  display: flex; justify-content: space-between; align-items: center; gap: 20px;
  transition: color var(--dur-fast) var(--ease-out);
}
.faq summary:hover { color: var(--accent-ink); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; color: var(--accent-ink); font-size: 19px;
  font-family: var(--font-mono); font-weight: 400; flex-shrink: 0;
}
.faq details[open] summary::after { content: "−"; }
.faq .answer {
  padding: 0 0 22px; color: var(--ink-500); font-size: 14.5px; max-width: 68ch;
}

/* ============================================================ forms */
.field { margin-bottom: 16px; }
.field label {
  display: block; font-size: 13px; font-weight: 600;
  color: var(--ink-900); margin-bottom: 6px;
}
.field .hint { font-size: 12.5px; color: var(--ink-400); margin-top: 5px; }
/* `input:not([type])` is deliberate: an <input> with no type attribute is a TEXT
   input to the browser, but it does not match `input[type=text]`, so it silently
   fell back to the browser's default width. That is exactly what made the contact
   form's name field render at half width next to its full-width siblings. */
input[type=text], input:not([type]), input[type=email], input[type=password],
input[type=number], input[type=url], select, textarea {
  width: 100%; min-height: 44px; padding: 10px 13px;
  background: var(--card); color: var(--ink-900);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  font-family: inherit; font-size: 15px;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent-ink);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
textarea { min-height: 84px; resize: vertical; font-family: var(--font-mono); font-size: 13.5px; }
input::placeholder, textarea::placeholder { color: var(--ink-400); }

/* ============================================================ alerts */
.alert {
  padding: 13px 16px; border-radius: var(--r-sm);
  font-size: 14px; border: 1px solid;
  display: flex; gap: 10px; align-items: flex-start;
}
.alert-ok    { background: var(--ok-soft);    border-color: var(--accent-ink); color: var(--accent-ink); }
.alert-warn  { background: var(--warn-soft);  border-color: var(--warn);   color: var(--warn); }
.alert-danger{ background: var(--danger-soft);border-color: var(--danger); color: var(--danger); }
.alert-info  { background: var(--muted);      border-color: var(--border-strong); color: var(--ink-700); }

/* ============================================================ footer */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 52px 0 36px; margin-top: 56px;
  background: var(--card);
}
.foot-grid {
  display: grid; grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: 36px;
}
.foot-col a { line-height: 1.5; }
.foot-brand p { color: var(--ink-500); font-size: 14px; margin-top: 12px; max-width: 30ch; }
.foot-col h4 {
  font-size: 11.5px; color: var(--ink-400); text-transform: uppercase;
  letter-spacing: 0.08em; margin-bottom: 14px; font-weight: 600;
}
.foot-col a {
  display: block; color: var(--ink-500); font-size: 14px; padding: 4px 0;
  transition: color var(--dur-fast) var(--ease-out);
}
.foot-col a:hover { color: var(--ink-900); }
.foot-bottom {
  margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--border);
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  color: var(--ink-400); font-size: 13px;
}
.status-dot {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: 12px; color: var(--ink-500);
}
.status-dot::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
}

/* ============================================================ tables */
.tbl-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
            border-radius: inherit; position: relative; }
.tbl-hint { display: none; }
@media (max-width: 820px) {
  .tbl-scroll { position: relative; }
  .tbl-scroll::after {
    content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 34px;
    background: linear-gradient(to right, transparent, var(--card));
    pointer-events: none;
  }
  .tbl-hint { display: block; font-size: 11.5px; color: var(--ink-400);
              text-align: right; padding: 6px 2px 0; font-family: var(--font-mono); }
}
.tbl-wrap .tbl { min-width: 560px; }
/* a card that hosts a scrollable table must not clip it */
.card.has-table { overflow: hidden; }
.card.has-table .tbl-wrap { overflow-x: auto; }
@media (max-width: 820px) {
  .tbl-wrap .tbl { min-width: 600px; }
  .tbl th, .tbl td { white-space: nowrap; }
  /* A full-width message row (colspan empty state) must WRAP. nowrap clipped
     sentences mid-word, e.g. "appears he". */
  .tbl td[colspan] { white-space: normal; }
  /* An empty table should not keep its desktop min-width: the message then
     clips at the viewport edge with no scroll affordance to reveal it. */
  .tbl-wrap.has-empty .tbl { min-width: 0; }
  /* signal that a wide table scrolls sideways */
  .tbl-wrap.is-wide { position: relative; }
  .tbl-wrap.is-wide::after {
    content: ""; position: sticky; right: 0; top: 0; float: right;
    width: 28px; height: 100%; margin-left: -28px; pointer-events: none;
    background: linear-gradient(to right, transparent, var(--card));
  }
}
.tbl { width: 100%; border-collapse: collapse; font-size: 14px; }
.tbl th {
  text-align: left; padding: 10px 12px; font-size: 11.5px;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-400); font-weight: 600;
  border-bottom: 1px solid var(--border);
  background: var(--muted);
}
.tbl td { padding: 11px 12px; border-bottom: 1px solid var(--border); color: var(--ink-700); }
.tbl tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--muted); }
.tbl .num { text-align: right; font-family: var(--font-mono); font-size: 13px; }

.acct-hero { display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 28px; align-items: center; }

/* 14-day chart */
.chart { display: flex; align-items: flex-end; gap: 4px; height: 120px;
         border-bottom: 1px solid var(--border-strong); padding-bottom: 1px;
         width: 100%; }
.chart .bar { flex: 1 1 0; min-width: 5px; border-radius: 3px 3px 0 0;
              background: var(--accent); transition: height .5s var(--ease-out); }
.chart .bar.zero { background: var(--border-strong); opacity: .45;
                   min-height: 6px; }
.chart .bar:hover { background: var(--accent-hover); }
.chart-labels { display: flex; justify-content: space-between; margin-top: 8px;
                font-size: 11.5px; color: var(--ink-500); font-family: var(--font-mono); }

/* live activity feed */
.live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
@media (prefers-reduced-motion: no-preference) {
  .live-dot { animation: livepulse 2s ease-in-out infinite; }
  @keyframes livepulse { 0%,100% { opacity:1; box-shadow:0 0 0 0 rgba(34,197,94,.45); }
                         50% { opacity:.6; box-shadow:0 0 0 6px rgba(34,197,94,0); } }
}
.feed-row { display: flex; align-items: center; gap: 13px; padding: 12px 18px;
            border-bottom: 1px solid var(--border); }
.feed-row:last-child { border-bottom: 0; }
.feed-ico { width: 30px; height: 30px; border-radius: 7px; background: var(--accent-soft);
            color: var(--accent-ink); display: grid; place-items: center; flex-shrink: 0; }
.feed-ico svg { width: 15px; height: 15px; }
.feed-main { flex: 1; min-width: 0; }
.feed-model { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-900);
              font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.feed-meta { font-size: 11.5px; color: var(--ink-400); margin-top: 1px; }
.feed-cost { font-family: var(--font-mono); font-size: 13px; font-weight: 600;
             color: var(--ink-900); white-space: nowrap; }
.feed-cost.bad { color: var(--danger); }
@media (prefers-reduced-motion: no-preference) {
  .feed-row { animation: feedin 260ms var(--ease-out) both; }
  @keyframes feedin { from { opacity:0; transform: translateY(-6px); }
                      to   { opacity:1; transform: none; } }
}
@media (max-width: 820px) { .acct-hero { grid-template-columns: 1fr; gap: 18px; } }

/* billing cycle toggle */
.cycle {
  display: inline-flex; background: var(--muted); border: 1px solid var(--border-strong);
  border-radius: 999px; padding: 3px; gap: 3px;
}
.cycle button {
  border: 0; background: transparent; color: var(--ink-500);
  font-family: inherit; font-size: 13.5px; font-weight: 600;
  padding: 7px 16px; border-radius: 999px; cursor: pointer; min-height: 34px;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.cycle button[aria-pressed="true"] { background: var(--card); color: var(--ink-900); }
.cycle .save { color: var(--accent-ink); font-size: 11.5px; font-weight: 700; }

.pill {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; font-family: var(--font-mono);
}
.pill-ok    { background: var(--accent-soft); color: var(--accent-ink); }
.pill-warn  { background: var(--warn-soft);   color: var(--warn); }
.pill-bad   { background: var(--danger-soft); color: var(--danger); }
.pill-idle  { background: var(--muted-2);     color: var(--ink-500); }

/* ============================================================ motion extras */
@media (prefers-reduced-motion: no-preference) {
  /* The old brand mark was a solid accent square and carried a green "live"
     pulse. The mark is now the LuxeChain logo, whose palette is blue/violet —
     a green halo around it would read as a rendering fault, so the pulse is
     gone. The mark's own hover opacity is the only motion it needs. */

  /* card lift on hover — the transition is declared here; the lift itself is
     gated to real pointers (below) so a tap on a phone cannot leave a card
     stuck in the hovered position. */
  .card, .plan { transition: border-color var(--dur) var(--ease-out),
                              transform var(--dur) var(--ease-out),
                              box-shadow var(--dur) var(--ease-out); }

  /* stat numbers settle in */
  .stat .v { animation: rise var(--dur-slow) var(--ease-out) both; }
  @keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

  /* buttons get a real press */
  .btn { will-change: transform; }

  /* tabs cross-fade their panels */
  [data-panel] { animation: fadein 180ms var(--ease-out) both; }
  @keyframes fadein { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

  /* live status dot */
  .status-dot::before { animation: pulse 2.4s ease-in-out infinite; }
  @keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
}

/* Card hover lift. `a.card:hover` only covered cards that were already links,
   so the plain `<div class="card">` blocks on pricing/about/contact/docs sat
   dead under the cursor while the homepage's cards moved. Gated to a real
   pointer (hover:hover + fine) so a tap on a phone or car screen cannot leave
   a card stuck lifted. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .card:hover, a.card:hover, .plan:hover {
    transform: translateY(-2px); border-color: var(--border-strong);
    box-shadow: 0 10px 26px rgba(12,10,9,.06);
  }
  .plan.featured:hover { border-color: var(--accent-ink); }
  /* A card that hosts a live form should not jump while the pointer is inside
     it — the fields would shift as the user moves toward them. `:has()` is
     ignored by older engines, which just means the lift stays on there. */
  .card:has(form):hover { transform: none; box-shadow: none; }
}

/* ============================================================ responsive */
@media (max-width: 1024px) {
  .hero-grid { grid-template-columns: 1fr; gap: 40px; }
  .plans { grid-template-columns: repeat(var(--c-lg, 3), minmax(0, 1fr)); }
  .g4, .g5 { grid-template-columns: repeat(2, 1fr); }
  .foot-grid { grid-template-columns: 1fr 1fr; gap: 32px; }
}
@media (max-width: 900px) {
  /* swap the desktop links for the burger + drawer */
  .nav-links { display: none; }
  .nav { gap: 10px; }
  .nav-actions { gap: 8px; }
  .nav-burger {
    display: inline-flex; flex-direction: column; justify-content: center; gap: 4px;
    width: 40px; height: 40px; padding: 0 9px; background: transparent;
    border: 1px solid var(--border-strong); border-radius: 8px; cursor: pointer;
  }
  .nav-burger span {
    display: block; height: 2px; width: 100%; background: var(--ink-700);
    border-radius: 2px; transition: transform var(--dur-fast) var(--ease-out),
                                opacity var(--dur-fast) var(--ease-out);
  }
  .nav-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .nav-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .nav-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  .mobile-menu {
    display: block; border-top: 1px solid var(--border);
    background: var(--card); padding: 8px 0 14px;
  }
  .mobile-menu[hidden] { display: none; }
  .mobile-menu a {
    display: block; padding: 13px 0; font-size: 16px; color: var(--ink-700);
    border-bottom: 1px solid var(--border); text-decoration: none;
  }
  .mobile-menu a:last-child { border-bottom: 0; }
  .mobile-menu a.mm-cta { color: var(--accent-ink); font-weight: 600; }

  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:nth-child(2) { border-right: 0; }
  .stat:nth-child(-n+2) { border-bottom: 1px solid var(--border); }
  .steps { grid-template-columns: 1fr; }
  .step { border-right: 0; border-bottom: 1px solid var(--border); }
  .step:last-child { border-bottom: 0; }
  .g2, .g3 { grid-template-columns: 1fr; }
  .plans { grid-template-columns: repeat(var(--c-md, 2), minmax(0, 1fr)); }
  .g5 { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .wrap, .wrap-narrow { padding: 0 16px; }
  /* the header gets crowded on phones — keep only the CTA and the burger */
  .nav-actions .btn-quiet { display: none; }
  .nav .lx-logo { font-size: 20px; }
  .hero { padding: 40px 0 30px; }
  section { padding: 42px 0; }
  .plans { grid-template-columns: 1fr; }
  .g4, .g5 { grid-template-columns: 1fr; }
  .foot-grid { grid-template-columns: 1fr; }
  .mrow { grid-template-columns: 1fr; gap: 6px; padding: 14px 16px; }
  .mprice { text-align: left; }
  .hero h1 { max-width: none; font-size: clamp(1.85rem, 8vw, 2.5rem); }
  .hero .sub { font-size: 1rem; }
  /* On phones, wrap code instead of hiding it behind a horizontal swipe —
     nothing should be reachable only by an undiscoverable gesture. */
  .code pre {
    font-size: 11px; padding: 13px 14px;
    white-space: pre-wrap; overflow-wrap: anywhere;
  }
  .code-head .title { font-size: 11px; }
  .hero-cta { gap: 8px; }
  .hero-cta .btn { flex: 1 1 100%; }
  .stats { grid-template-columns: 1fr 1fr; }
  .tbl-wrap .tbl { min-width: 520px; }
}

/* very small phones */
@media (max-width: 380px) {
  .wrap, .wrap-narrow { padding: 0 13px; }
  .stats { grid-template-columns: 1fr; }
  .stat:nth-child(2) { border-right: 0; }
}


/* ============================================================ luxechain widget */
.luxechain-bot-launch {
  position: fixed; right: 22px; bottom: 22px; z-index: 90;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 17px 12px 14px; border-radius: 999px;
  background: var(--accent); color: var(--accent-fg); border: 0; cursor: pointer;
  font-family: var(--font-sans); font-size: 14.5px; font-weight: 600;
  box-shadow: 0 6px 22px rgba(12,10,9,0.22);
  transition: transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.luxechain-bot-launch:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(12,10,9,0.28); }
.luxechain-bot-launch .mascot { width: 30px; height: 30px; }

.luxechain-bot-launch.hide { opacity: 0; pointer-events: none; transform: translateY(8px) scale(.96); }

.luxechain-bot-panel {
  position: fixed; right: 22px; bottom: 22px; z-index: 95;
  width: 384px; max-width: calc(100vw - 32px);
  height: 566px; max-height: calc(100vh - 44px);
  display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: 15px; overflow: hidden;
  box-shadow: 0 20px 56px rgba(28,25,23,0.20);
}
.luxechain-bot-panel[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .luxechain-bot-panel { animation: luxechainIn 220ms var(--ease-out) both; }
  @keyframes luxechainIn { from { opacity: 0; transform: translateY(12px) scale(.985); }
                      to   { opacity: 1; transform: none; } }
}

.luxechain-bot-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--border);
  background: var(--card); flex-shrink: 0;
}
.luxechain-bot-id { display: flex; align-items: center; gap: 10px; }
.luxechain-bot-avatar {
  width: 34px; height: 34px; display: grid; place-items: center;
}
.luxechain-bot-name { font-size: 14.5px; font-weight: 650; color: var(--ink-900); line-height: 1.2; }
.luxechain-bot-sub {
  font-size: 11.5px; color: var(--ink-500); display: flex; align-items: center; gap: 5px;
}
.luxechain-bot-live {
  width: 6px; height: 6px; border-radius: 50%; background: #16A34A; flex-shrink: 0;
}
.luxechain-bot-close {
  width: 30px; height: 30px; border-radius: 7px; border: 0; background: transparent;
  color: var(--ink-500); cursor: pointer; display: grid; place-items: center;
}
.luxechain-bot-close:hover { background: var(--muted); color: var(--ink-900); }

.luxechain-bot-body {
  flex: 1; overflow-y: auto; padding: 16px 14px 8px;
  display: flex; flex-direction: column; gap: 11px;
  background: var(--bg);
  scroll-padding-top: 10px;
  scrollbar-width: thin;
}
/* fade the top edge so a scrolled message never looks chopped off */
.luxechain-bot-body {
  mask-image: linear-gradient(to bottom, transparent 0, #000 14px,
                              #000 calc(100% - 4px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 14px,
                              #000 calc(100% - 4px), transparent 100%);
}
.luxechain-bot-msg {
  max-width: 88%; padding: 10px 13px; border-radius: 13px;
  font-size: 14px; line-height: 1.6; color: var(--ink-800);
  overflow-wrap: anywhere;
}
.luxechain-bot-msg p { margin: 0 0 7px; }
.luxechain-bot-msg p:last-child { margin-bottom: 0; }
.luxechain-bot-from-bot {
  align-self: flex-start; background: var(--card);
  border: 1px solid var(--border); border-bottom-left-radius: 4px;
}
.luxechain-bot-me {
  align-self: flex-end; background: var(--accent); color: var(--accent-fg);
  border-bottom-right-radius: 4px;
}
.luxechain-bot-err { align-self: center; font-size: 12.5px; color: var(--danger); text-align: center; }
@media (prefers-reduced-motion: no-preference) {
  .luxechain-bot-msg { animation: luxechainMsg 200ms var(--ease-out) both; }
  @keyframes luxechainMsg { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
}

.luxechain-bot-typing { display: inline-flex; gap: 4px; align-items: center; padding: 3px 0; }
.luxechain-bot-typing span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink-400);
  animation: luxechainBlink 1.3s ease-in-out infinite;
}
.luxechain-bot-typing span:nth-child(2) { animation-delay: .18s; }
.luxechain-bot-typing span:nth-child(3) { animation-delay: .36s; }
@keyframes luxechainBlink { 0%,60%,100% { opacity: .3; } 30% { opacity: 1; } }

.luxechain-bot-chips {
  display: flex; flex-wrap: wrap; gap: 7px; padding: 2px 0 8px;
}
.luxechain-bot-chips button {
  font-family: var(--font-sans); font-size: 12.5px; padding: 7px 12px;
  border-radius: 999px; border: 1px solid var(--border-strong);
  background: var(--card); color: var(--ink-700); cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.luxechain-bot-chips button:hover { border-color: var(--accent-ink); color: var(--accent-ink); }

.luxechain-bot-form {
  display: flex; gap: 8px; padding: 11px 12px; border-top: 1px solid var(--border);
  background: var(--card); flex-shrink: 0;
}
.luxechain-bot-form input {
  flex: 1; min-height: 42px; padding: 9px 13px; font-size: 14.5px;
  border: 1px solid var(--border-strong); border-radius: 10px;
  background: var(--bg); color: var(--ink-900); font-family: var(--font-sans);
}
.luxechain-bot-form input:focus { outline: none; border-color: var(--accent-ink); box-shadow: 0 0 0 3px var(--accent-soft); }
.luxechain-bot-form button {
  width: 42px; height: 42px; flex-shrink: 0; border-radius: 10px; border: 0;
  background: var(--accent); color: var(--accent-fg); cursor: pointer;
  display: grid; place-items: center;
}
.luxechain-bot-form button:disabled { opacity: .5; cursor: not-allowed; }
.luxechain-bot-foot {
  font-size: 11px; color: var(--ink-400); text-align: center;
  padding: 0 14px 10px; background: var(--card); margin: 0; flex-shrink: 0;
}

@media (max-width: 620px) {
  .luxechain-bot-launch { right: 14px; bottom: 14px; padding: 12px 15px 12px 13px; }
  .luxechain-bot-launch-label { display: none; }
  .luxechain-bot-launch { padding: 14px; }
  .luxechain-bot-panel {
    right: 0; bottom: 0; width: 100vw; max-width: 100vw;
    height: 100dvh; max-height: 100dvh; border-radius: 0; border: 0;
  }
  .luxechain-bot-msg { max-width: 92%; font-size: 14.5px; }
}


/* ---------------------------------------------------- mascot (living face) */
.luxechain-bot-avatar {
  position: relative; width: 38px; height: 38px; flex-shrink: 0;
  display: grid; place-items: center;
}
.luxechain-bot-avatar.small { width: 26px; height: 26px; }
.mascot { width: 100%; height: 100%; display: block; overflow: visible; }

.m-face  { fill: #F5D9B8; }
.m-hair  { fill: #6D28D9; }
.m-eye   { fill: #1C1917; transform-origin: center; }
.m-mouth { fill: none; stroke: #8A5A3B; stroke-width: 1.6; stroke-linecap: round; }
.m-blush { fill: #F0A98B; opacity: .55; }

/* status dot on the avatar */
.mascot-status {
  position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px;
  border-radius: 50%; background: #22C55E; border: 2px solid var(--card);
}
.luxechain-bot-avatar.small .mascot-status { width: 8px; height: 8px; }

@media (prefers-reduced-motion: no-preference) {
  /* breathing: the whole head lifts very slightly */
  .mascot { animation: luxechainBreathe 3.6s ease-in-out infinite; transform-origin: 50% 80%; }
  @keyframes luxechainBreathe {
    0%,100% { transform: translateY(0) scale(1); }
    50%     { transform: translateY(-1.1px) scale(1.018); }
  }
  /* a natural blink every few seconds */
  .m-eye { animation: luxechainBlink 4.4s ease-in-out infinite; }
  .m-eye:nth-of-type(2) { animation-delay: .04s; }
  @keyframes luxechainBlink {
    0%, 92%, 100% { transform: scaleY(1); }
    95%           { transform: scaleY(0.08); }
  }
  /* the smile breathes a little with the head */
  .m-mouth { animation: luxechainSmile 3.6s ease-in-out infinite; transform-origin: 20px 27px; }
  @keyframes luxechainSmile {
    0%,100% { transform: scaleX(1); }
    50%     { transform: scaleX(1.06); }
  }
  /* blush gently pulses so it feels alive, not printed */
  .m-blush { animation: luxechainBlush 4.6s ease-in-out infinite; }
  @keyframes luxechainBlush { 0%,100% { opacity: .45; } 50% { opacity: .7; } }

  /* while the bot is thinking, the eyes look around and the status dot pulses */
  .luxechain-bot-avatar.thinking .mascot { animation-duration: 1.5s; }
  .luxechain-bot-avatar.thinking .m-eye {
    animation: luxechainLook 1.35s ease-in-out infinite;
  }
  @keyframes luxechainLook {
    0%,100% { transform: translateX(0); }
    25%     { transform: translateX(-1.6px); }
    70%     { transform: translateX(1.6px); }
  }
  .luxechain-bot-avatar.thinking .mascot-status { animation: luxechainPulse 1s ease-in-out infinite; }
  @keyframes luxechainPulse { 0%,100% { opacity: 1; transform: scale(1); }
                          50%     { opacity: .45; transform: scale(.8); } }
}

/* the launcher gets a friendlier hover wiggle */
@media (prefers-reduced-motion: no-preference) {
  .luxechain-bot-launch:hover .mascot { animation: luxechainPeek .5s ease-out; }
  @keyframes luxechainPeek {
    0%   { transform: rotate(0); }
    35%  { transform: rotate(-7deg); }
    70%  { transform: rotate(5deg); }
    100% { transform: rotate(0); }
  }
}


/* ------------------------------------------------- typing-in text reveal */
.luxechain-bot-msg .tw {
  display: inline; opacity: 0;
  animation: luxechainWord .26s var(--ease-out) forwards;
}
@keyframes luxechainWord { from { opacity: 0; } to { opacity: 1; } }

/* the caret that follows the text while it types */
.luxechain-bot-caret {
  display: inline-block; width: 2px; height: 1em; margin-left: 1px;
  background: var(--accent); vertical-align: text-bottom;
  animation: luxechainCaret .8s steps(1) infinite;
}
@keyframes luxechainCaret { 0%,49% { opacity: 1; } 50%,100% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .luxechain-bot-msg .tw { opacity: 1; animation: none; }
  .luxechain-bot-caret { display: none; }
}

/* richer thinking dots, shown while the request is in flight */
.luxechain-bot-typing { display: inline-flex; gap: 5px; align-items: center; padding: 4px 1px; }
.luxechain-bot-typing span {
  width: 7px; height: 7px; border-radius: 50%; background: var(--ink-400);
  animation: luxechainBounce 1.25s ease-in-out infinite;
}
.luxechain-bot-typing span:nth-child(2) { animation-delay: .16s; }
.luxechain-bot-typing span:nth-child(3) { animation-delay: .32s; }
@keyframes luxechainBounce {
  0%, 60%, 100% { transform: translateY(0); opacity: .4; }
  30%           { transform: translateY(-4px); opacity: 1; }
}


/* ------------------------------------------------- currency picker */
.ccy-pick { position: relative; }
.ccy-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 11px; border-radius: 8px;
  border: 1px solid var(--border-strong); background: transparent;
  color: var(--ink-700); font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer; letter-spacing: .02em;
  transition: border-color .15s, color .15s;
}
.ccy-btn:hover { border-color: var(--ink-400); color: var(--ink-900); }
.ccy-btn svg { opacity: .55; transition: transform .18s var(--ease-out); }
.ccy-pick.open .ccy-btn svg { transform: rotate(180deg); }

.ccy-menu {
  position: absolute; top: calc(100% + 7px); right: 0; z-index: 60;
  min-width: 216px; padding: 6px;
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: 12px; box-shadow: 0 12px 34px rgba(28,25,23,.14);
}
.ccy-menu[hidden] { display: none; }
.ccy-menu button {
  display: grid; grid-template-columns: 30px 44px 1fr; align-items: center;
  gap: 8px; width: 100%; padding: 9px 10px;
  border: 0; background: transparent; border-radius: 8px;
  font: inherit; font-size: 13.5px; color: var(--ink-700);
  cursor: pointer; text-align: left;
  transition: background .13s, color .13s;
}
.ccy-menu button:hover { background: var(--ink-50, #F5F5F4); color: var(--ink-900); }
.ccy-menu button[aria-selected="true"] { color: var(--accent-ink); font-weight: 600; }
.ccy-sym { font-weight: 700; font-size: 14px; }
.ccy-code { font-family: var(--mono); font-size: 12px; opacity: .75; }
.ccy-name { font-size: 12.5px; opacity: .6; }

.ccy-mobile { padding: 12px 0 4px; border-top: 1px solid var(--border); margin-top: 8px; }
.ccy-mobile .lbl {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-400); margin-bottom: 9px;
}
.ccy-row { display: flex; flex-wrap: wrap; gap: 7px; }
.ccy-row button {
  padding: 8px 13px; border-radius: 999px; font: inherit; font-size: 12.5px;
  font-weight: 600; cursor: pointer;
  border: 1px solid var(--border-strong); background: transparent; color: var(--ink-700);
}
.ccy-row button.on { background: var(--accent); border-color: var(--accent-ink); color: var(--accent-fg); }

@media (max-width: 900px) { .ccy-pick { display: none; } }


/* ------------------------------------------------- models page */
.brand-strip {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px;
}
.brand-chip {
  padding: 7px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  border: 1px solid var(--border-strong); color: var(--ink-600);
  background: var(--card);
}
.maker-filter {
  display: flex; flex-wrap: wrap; gap: 7px; margin: 4px 0 20px;
}
.maker-filter button {
  padding: 7px 13px; border-radius: 999px; font: inherit; font-size: 12.5px;
  font-weight: 600; cursor: pointer;
  border: 1px solid var(--border); background: transparent; color: var(--ink-500);
  transition: border-color .15s, color .15s, background .15s;
}
.maker-filter button:hover { border-color: var(--ink-400); color: var(--ink-800); }
.maker-filter button.on {
  background: var(--accent); border-color: var(--accent-ink); color: var(--accent-fg);
}
.mlead { display: flex; align-items: center; gap: 13px; min-width: 0; }
.mrank {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  color: var(--ink-400); min-width: 20px;
}


/* ---------------------------------------------------------------- checkout */
.order-line {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 11px 0; border-bottom: 1px solid var(--border);
}
.order-line:last-child { border-bottom: 0; }
.order-k { color: var(--ink-500); font-size: 13.5px; }
.order-v { font-weight: 600; color: var(--ink-900); text-align: right; }
.order-total { border-top: 2px solid var(--ink-900); margin-top: 6px; padding-top: 14px; }
.order-total .order-k { color: var(--ink-900); font-weight: 600; font-size: 14.5px; }
.order-total .order-v { font-size: 21px; letter-spacing: -.02em; }

/* ------------------------------------------------- subscription on account */
.sub-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px;
}
.sub-cell { min-width: 0; }
.sub-cell .tiny {
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink-400);
  font-size: 10.5px; font-weight: 600;
}
.sub-v { font-size: 16px; font-weight: 600; color: var(--ink-900); margin-top: 3px; }
@media (max-width: 720px) {
  .sub-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .sub-v { font-size: 15px; }
}

/* checkout: the recurring note carries the payment disclosure, so it must not be
   the faintest text on the page. */
.recurring-note {
  margin-top: 14px; padding: 12px 14px; border-radius: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
  font-size: 13px; line-height: 1.5;
}
.order-line + .order-line { border-top: 0; }
.order-total + .order-line { border-top: 0; padding-top: 4px; }
.order-total + .order-line .order-k,
.order-total + .order-line .order-v { color: var(--ink-500); font-size: 13.5px; font-weight: 600; }

/* ---------------------------------------------------- quantity stepper
   Used on checkout. The buttons are sized for a THUMB, not a mouse: 46x46 with
   the glyph centred. Note the `input[type=number].qty-in` selector — a bare
   `.qty-in` loses to the global `input[type=number]` rule on specificity, so the
   field silently kept `width:100%; padding:10px 13px` and pushed the buttons
   down to 29px. Always qualify a number input with its type. */
.qty-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--border);
}
.qty-ctl {
  display: inline-flex; align-items: stretch; flex: 0 0 auto;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  overflow: hidden; background: var(--card);
}
.qty-btn {
  flex: 0 0 46px; width: 46px; height: 46px; min-height: 46px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 0; background: var(--muted); color: var(--ink-900);
  font-size: 24px; font-weight: 700; line-height: 1; cursor: pointer;
}
.qty-btn:hover { background: var(--muted-2); }
.qty-btn:active { background: var(--border); }
.qty-btn:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: -2px; }
input[type=number].qty-in {
  flex: 0 0 auto; width: 62px; min-height: 46px; height: 46px; padding: 0;
  border: 0; border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  border-radius: 0; text-align: center; font-size: 16px; font-weight: 700;
  color: var(--ink-900); background: var(--card);
  -moz-appearance: textfield; appearance: textfield;
}
input[type=number].qty-in:focus { box-shadow: none; }
input[type=number].qty-in::-webkit-outer-spin-button,
input[type=number].qty-in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---------------------------------------------------- voucher codes
   Shown on the payment-success page. The code must be big, monospaced and
   easy to read off a phone; the copy button is a real 44px target because
   that is the whole point of the screen. */
.code-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--border);
}
.code-row:last-child { border-bottom: 0; }
.code-val {
  font-family: var(--font-mono); font-size: 19px; font-weight: 700;
  letter-spacing: .08em; color: var(--ink-900); word-break: break-all;
}
.code-copy {
  flex: 0 0 auto; min-height: 44px; padding: 0 18px; border-radius: var(--r-sm);
  border: 1px solid var(--border-strong); background: var(--card);
  color: var(--ink-900); font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.code-copy:hover { background: var(--muted); }
.code-copy:active { background: var(--muted-2); }

/* .alert is a flex row; when the content is a paragraph it must be ONE child or
   the text renders as a second column and gets clipped at the card edge. */
.alert-stack { display: block; }
.alert-stack p { margin: 6px 0 0; }
.alert-stack strong { font-size: 14.5px; }


/* ============================================================ legal pages */
/* Long-form policy pages: terms, privacy, refunds. Narrow measure, generous
   leading, and a left rule on h2 so a 13-section document stays scannable. */
.legal { padding-bottom: 24px; }
.legal .legal-lede {
  font-size: 1.0625rem; line-height: 1.75; color: var(--ink-700);
  padding: 18px 20px; background: var(--accent-soft);
  border-left: 3px solid var(--accent); border-radius: 0 var(--r-sm) var(--r-sm) 0;
  margin: 0 0 34px;
}
.legal h2 {
  font-family: var(--font-sans); font-size: 1.0625rem; font-weight: 600;
  color: var(--ink-900); letter-spacing: -0.01em;
  margin: 38px 0 12px; padding-top: 18px; border-top: 1px solid var(--border);
}
.legal h2:first-of-type { border-top: 0; padding-top: 0; margin-top: 8px; }
.legal p { font-size: .9375rem; line-height: 1.78; color: var(--ink-700); margin: 0 0 14px; }
.legal ul { margin: 0 0 16px; padding-left: 22px; }
.legal li { font-size: .9375rem; line-height: 1.78; color: var(--ink-700); margin-bottom: 7px; }
.legal li::marker { color: var(--accent-ink); }
.legal a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.legal a:hover { color: var(--ink-900); }
.legal strong { color: var(--ink-900); font-weight: 600; }
.legal code {
  font-family: var(--font-mono); font-size: .875em;
  background: var(--muted); border: 1px solid var(--border);
  border-radius: 4px; padding: 1px 5px; color: var(--ink-900);
}
@media (max-width: 640px) {
  .legal .legal-lede { padding: 15px 16px; font-size: 1rem; }
  .legal p, .legal li { font-size: .9375rem; }
}

.foot-legal { display: flex; gap: 16px; flex-wrap: wrap; }
.foot-legal a { color: var(--ink-500); font-size: 13px; }
.foot-legal a:hover { color: var(--accent-ink); }
@media (max-width: 640px) { .foot-legal { gap: 12px; } .foot-legal a { font-size: 12.5px; } }

/* ============================================================
   Design #7 language — alternating bands, illustration panels,
   logo strip, testimonial cards.

   The reference template is illustration-driven. Rather than paste in
   character art that would look borrowed, the same STRUCTURE is kept —
   banded sections, big coloured panels, generous rhythm — and the
   illustration slot is filled with geometric SVG scenes in the brand
   palette. That reads as a deliberate house style rather than a
   template someone else already owns.
   ============================================================ */

/* ---- full-bleed colour band -------------------------------------- */
.band { padding: 62px 0; }
.band-accent { background: var(--accent); color: var(--accent-fg); }
.band-accent h2, .band-accent h3, .band-accent strong { color: var(--accent-fg); }
.band-accent p, .band-accent .muted { color: rgba(12,10,9,.76); }
.band-soft { background: var(--accent-soft); }
.band-ink { background: var(--ink-900); color: #EDEDEF; }
.band-ink h2, .band-ink h3 { color: #FFFFFF; }
.band-ink p { color: rgba(237,237,239,.74); }
.band-split {
  display: grid; grid-template-columns: 1.05fr .95fr; gap: 44px; align-items: center;
}
@media (max-width: 860px) { .band-split { grid-template-columns: 1fr; gap: 26px; } }

/* ---- illustration panel ------------------------------------------ */
/* Fixed aspect so the art never reflows or squashes at any width. */
.illo {
  position: relative; border-radius: var(--r-lg); overflow: hidden;
  background: var(--card); border: 1px solid var(--border);
  aspect-ratio: 16 / 11;
}
.illo svg { display: block; width: 100%; height: 100%; }
.illo-flat { border: 0; }
.illo-pad { padding: 22px; }

/* ---- 4-up feature cards with a coloured art panel on top ---------- */
.fgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
@media (max-width: 1000px) { .fgrid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .fgrid { grid-template-columns: 1fr; } }
.fcard {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); overflow: hidden; display: flex; flex-direction: column;
}
.fcard .art { aspect-ratio: 4 / 3; display: block; }
.fcard .art svg { display: block; width: 100%; height: 100%; }
.fcard .body { padding: 18px 18px 20px; }
.fcard h3 { font-size: 1.0625rem; margin-bottom: 7px; }
.fcard p { font-size: .875rem; line-height: 1.65; color: var(--ink-500); margin: 0; }

/* ---- client / trust logo strip ----------------------------------- */
.logostrip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px 20px; }
@media (max-width: 760px) { .logostrip { grid-template-columns: repeat(2, 1fr); } }
.logostrip .lg {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 16px 10px; border-radius: var(--r-sm);
  color: var(--ink-400); font-weight: 600; font-size: 14.5px;
  letter-spacing: -0.01em; opacity: .82;
  transition: opacity var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.logostrip .lg:hover { opacity: 1; color: var(--ink-900); }
.logostrip .lg svg { width: 19px; height: 19px; flex-shrink: 0; }

/* ---- testimonial cards ------------------------------------------- */
.tgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 900px) { .tgrid { grid-template-columns: 1fr; } }
.tcard {
  background: var(--card); border: 1px solid var(--border);
  border-top: 3px solid var(--accent); border-radius: var(--r-lg);
  padding: 24px 22px; display: flex; flex-direction: column;
}
.tcard .quote { font-size: .9375rem; line-height: 1.72; color: var(--ink-700); margin: 0 0 18px; }
.tcard .who { margin-top: auto; display: flex; align-items: center; gap: 11px; }
.tcard .av {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center; font-weight: 700; font-size: 14px;
  background: var(--accent-soft); color: var(--accent-ink);
}
.tcard .who .n { font-weight: 600; font-size: 14px; color: var(--ink-900); line-height: 1.3; }
.tcard .who .r { font-size: 12.5px; color: var(--ink-400); }

/* ---- big closing CTA -------------------------------------------- */
.cta-final {
  border-radius: var(--r-lg); padding: 52px 32px; text-align: center;
  background: var(--ink-900); color: #EDEDEF;
}
.cta-final h2 { color: #FFFFFF; font-size: clamp(1.5rem, 3vw, 2.05rem); margin-bottom: 12px; }
.cta-final p { color: rgba(237,237,239,.76); max-width: 52ch; margin: 0 auto 26px; }

/* ---- yellow footer band (design #7 signature) -------------------- */
.band-foot { background: var(--accent); color: var(--accent-fg); padding: 54px 0 30px; }
.band-foot .foot-col h4 { color: rgba(12,10,9,.72); }
.band-foot .foot-col a, .band-foot p { color: rgba(12,10,9,.80); }
.band-foot .foot-col a:hover { color: var(--accent-fg); }
.band-foot .foot-brand p { color: rgba(12,10,9,.72); }
.band-foot .foot-bottom { border-top-color: rgba(12,10,9,.16); }
.band-foot .foot-bottom, .band-foot .foot-legal a { color: rgba(12,10,9,.70); }
.band-foot .foot-legal a:hover { color: var(--accent-fg); }
.band-foot .status-dot { color: rgba(12,10,9,.80); }


/* ============================================================ mobile fixes */
@media (max-width: 860px) {
  /* The chat launcher was a wide pill sitting on top of the code card and the
     illustration panel. On a phone it also competes with the primary CTA, so
     it collapses to a compact round button and tucks into the corner. */
  .luxechain-bot-launch {
    right: 12px; bottom: 12px;
    width: 52px; height: 52px; padding: 0;
    border-radius: 50%; justify-content: center;
  }
  .luxechain-bot-launch-label { display: none; }
  .luxechain-bot-launch .mascot { width: 28px; height: 28px; }

  /* Room at the foot of the page so the launcher never covers the last block */
  body { padding-bottom: 4px; }
  .cta-final { margin-bottom: 62px; }

  /* Code cards: let long lines scroll instead of overflowing the card */
  .code pre { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* The illustration is decorative on a phone; give it less height so the
     section does not dominate the scroll. */
  .illo { aspect-ratio: 4 / 3; }
}

@media (max-width: 560px) {
  .band { padding: 46px 0; }
  .band-foot { padding: 42px 0 26px; }
  .cta-final { padding: 38px 22px; }
  .stats { grid-template-columns: repeat(2, 1fr); }
}


/* ================================================= password show / hide */
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 46px; }
.pw-toggle {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  width: 36px; height: 36px; display: grid; place-items: center;
  background: transparent; border: 0; border-radius: var(--r-sm);
  color: var(--ink-400); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.pw-toggle:hover { color: var(--ink-700); background: var(--surface-2); }
.pw-toggle[aria-pressed="true"] { color: var(--accent-ink); }


/* =========================================================== onboarding tour
   One-time walkthrough shown after a customer's first purchase. It highlights
   real elements on the page rather than drawing a static illustration, so what
   the customer sees is exactly where the control actually is.

   Layering:
     .tour-scrim   z 9998  dims the page, blocks clicks outside the target
     .tour-spot    z 9999  the cut-out hole over the highlighted element
     .tour-card    z 10000 the explanation card (always above the spotlight)

   The hole is made with a huge box-shadow rather than an SVG mask: one element,
   no mask support questions, and it works at any viewport size.
   ============================================================ */
.tour-scrim {
  position: fixed; inset: 0; z-index: 9998;
  background: rgba(12, 10, 9, .58);
  opacity: 0; transition: opacity .22s var(--ease-out);
}
.tour-scrim.in { opacity: 1; }

/* The spotlight is a transparent box whose enormous outer shadow darkens
   everything EXCEPT the target. Position and size are set from JS. */
.tour-spot {
  position: fixed; z-index: 9999; pointer-events: none;
  border-radius: 12px;
  /* Layer order: the huge shadow dims the page, then a dark ring, then the
     brand ring outside it. Yellow alone on a white card is ~1.5:1 and reads as
     an ordinary border; the dark ring is what makes the target pop. */
  box-shadow:
    0 0 0 9999px rgba(12, 10, 9, .72),
    0 0 0 2px #0C0A09,
    0 0 0 5px var(--accent);
  transition: all .28s cubic-bezier(0.23, 1, 0.32, 1);
}
.tour-scrim { background: transparent; }   /* the spotlight's shadow does the dimming */

.tour-card {
  position: fixed; z-index: 10000;
  width: min(360px, calc(100vw - 32px));
  background: var(--card); color: var(--ink-900);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: 0 18px 50px rgba(12, 10, 9, .30);
  padding: 20px 20px 16px;
  opacity: 0; transform: translateY(6px);
  transition: opacity .22s var(--ease-out), transform .22s var(--ease-out);
}
.tour-card.in { opacity: 1; transform: none; }
.tour-card .tour-step {
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent-ink); margin-bottom: 7px;
}
.tour-card h4 { margin: 0 0 8px; font-size: 1.0625rem; line-height: 1.3; }
.tour-card p { margin: 0 0 16px; font-size: 14px; line-height: 1.65; color: var(--ink-500); }
.tour-card .tour-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  border-top: 1px solid var(--border); padding-top: 13px;
}
.tour-card .tour-dots { display: flex; gap: 6px; }
.tour-card .tour-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted-2); transition: background var(--dur-fast) var(--ease-out);
}
.tour-card .tour-dot.on { background: var(--accent-ink); }
.tour-card .tour-btns { display: flex; align-items: center; gap: 8px; }
.tour-skip {
  background: transparent; border: 0; color: var(--ink-400);
  font: inherit; font-size: 13.5px; cursor: pointer; padding: 6px 8px;
  border-radius: var(--r-sm);
}
.tour-skip:hover { color: var(--ink-700); background: var(--surface-2); }

/* On a phone the card sits at the foot of the screen as a sheet. The JS scrolls
   the target into the TOP of the viewport first, so the sheet never covers the
   element it is describing. */
@media (max-width: 620px) {
  .tour-card {
    left: 16px !important; right: 16px !important; width: auto;
    bottom: 16px !important; top: auto !important; transform: translateY(10px);
  }
  .tour-card.in { transform: none; }
}

/* A long token figure must not break mid-number (it wrapped as
   "500,000,000,00" / "0"). Scale it down on narrow screens instead. */
.acct-hero .mono { white-space: nowrap; }
@media (max-width: 620px) {
  .acct-hero .mono { font-size: clamp(1.35rem, 7.2vw, 2.375rem) !important; }
}

/* ============================================================
   v2 — wide canvas, ambient background, purposeful motion
   Desktop-first. Every animation is opt-in behind
   `prefers-reduced-motion: no-preference`; the reduced-motion
   path renders the final state.
   ============================================================ */

/* ---- ambient layer (full-bleed) ---------------------------------- */
/* Two large, very light tint blobs sit in the SIDE gutters, so on a wide
   screen the margins read as intentional space rather than dead paper.
   Tints only (.17/.11) — ink text keeps its contrast over them. */
.bg-ambient { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.bg-ambient::before,
.bg-ambient::after { content: ""; position: absolute; border-radius: 50%; }
.bg-ambient::before {
  width: 48vw; height: 48vw; min-width: 420px; min-height: 420px;
  left: -14vw; top: -10vw;
  background: radial-gradient(circle, rgba(255,199,44,.17), rgba(255,199,44,0) 68%);
}
.bg-ambient::after {
  width: 46vw; height: 46vw; min-width: 400px; min-height: 400px;
  right: -14vw; top: 30vh;
  background: radial-gradient(circle, rgba(46,123,255,.11), rgba(46,123,255,0) 68%);
}
@media (prefers-reduced-motion: no-preference) {
  .bg-ambient::before { animation: blobA 44s ease-in-out infinite alternate; }
  .bg-ambient::after  { animation: blobB 54s ease-in-out infinite alternate; }
  @keyframes blobA { from { transform: translate3d(0,0,0) scale(1); }
                     to   { transform: translate3d(6vw,4vh,0) scale(1.14); } }
  @keyframes blobB { from { transform: translate3d(0,0,0) scale(1); }
                     to   { transform: translate3d(-5vw,-6vh,0) scale(1.1); } }
}

/* ---- scroll progress -------------------------------------------- */
.scroll-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 100%;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--accent), var(--accent-hover));
  z-index: 200; pointer-events: none;
}

/* ---- section-head accent rule (centred heads) -------------------- */
.sec-head.center h2 { position: relative; padding-bottom: 15px; }
.sec-head.center h2::after {
  content: ""; position: absolute; left: 50%; bottom: 0;
  width: 48px; height: 3px; border-radius: 3px;
  transform: translateX(-50%);
  background: linear-gradient(90deg, var(--accent), var(--accent-ink));
}

/* ---- hero illustration: living "one key opens every door" -------- */
.illo-hero .orbit { animation: orbitRun 9s linear infinite; }
@keyframes orbitRun { to { stroke-dashoffset: -110; } }
.illo-hero .key-halo { animation: keyHalo 3.8s ease-in-out infinite; }
@keyframes keyHalo { 0%,100% { opacity: .12; } 50% { opacity: .42; } }
.illo-hero .tile { transform-box: fill-box; transform-origin: center; }
.illo-hero.in .tile { animation: tileIn .55s var(--ease-out) both; }
.illo-hero.in .tile:nth-child(1) { animation-delay: .04s; }
.illo-hero.in .tile:nth-child(2) { animation-delay: .13s; }
.illo-hero.in .tile:nth-child(3) { animation-delay: .22s; }
.illo-hero.in .tile:nth-child(4) { animation-delay: .31s; }
.illo-hero.in .tile:nth-child(5) { animation-delay: .40s; }
@keyframes tileIn { from { opacity: 0; transform: translateY(6px) scale(.94); }
                    to   { opacity: 1; transform: none; } }

/* ---- hero code: a live caret at the end of the snippet ----------- */
.code pre .caret {
  display: inline-block; width: 8px; height: 1.02em; margin-left: 3px;
  background: var(--accent); vertical-align: text-bottom; border-radius: 1px;
  animation: caretBlink 1.1s steps(1) infinite;
}
@keyframes caretBlink { 0%,49% { opacity: 1; } 50%,100% { opacity: 0; } }

/* ---- modality cards: art sheen, icon lift, glow dot -------------- */
.fcard { transition: transform var(--dur) var(--ease-out),
                     border-color var(--dur) var(--ease-out),
                     box-shadow var(--dur) var(--ease-out); }
.fcard:hover { transform: translateY(-3px); border-color: var(--border-strong);
               box-shadow: 0 12px 32px rgba(12,10,9,.08); }
.fcard .art { position: relative; overflow: hidden; }
.fcard .art::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 32%, rgba(255,255,255,.6) 50%, transparent 68%);
  transform: translateX(-130%);
}
.fcard:hover .art::after { transform: translateX(130%); transition: transform .75s var(--ease-out); }
.fcard .art svg { transition: transform var(--dur) var(--ease-out); }
.fcard:hover .art svg { transform: scale(1.07); }
.fcard .glowdot { animation: glowdot 5.2s ease-in-out infinite; }
@keyframes glowdot { 0%,100% { opacity: .10; } 50% { opacity: .24; } }

/* ---- testimonial + plan cards: a little lift and glow ------------ */
.tcard { transition: transform var(--dur) var(--ease-out),
                     box-shadow var(--dur) var(--ease-out),
                     border-color var(--dur) var(--ease-out); }
.tcard:hover { transform: translateY(-3px); box-shadow: 0 12px 32px rgba(12,10,9,.08); }
.plan:hover { box-shadow: 0 12px 32px rgba(12,10,9,.10); }

/* ---- closing CTA: a slow light sheen across the dark panel ------- */
.cta-final { position: relative; overflow: hidden; }
.cta-final::after {
  content: ""; position: absolute; top: -60%; left: -30%;
  width: 34%; height: 220%; transform: rotate(9deg);
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.11), transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .cta-final::after { animation: sheen 7.5s ease-in-out infinite; }
  @keyframes sheen { 0%, 62%, 100% { left: -40%; } 30% { left: 120%; } }
}

/* ---- tools marquee (replaces the static logo grid on home) ------- */
.marquee {
  position: relative; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee-track { display: flex; width: max-content; }
.marquee-group { display: flex; gap: 12px; padding-right: 12px; }
.marquee .lg {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 18px; border-radius: 999px;
  background: var(--card); border: 1px solid var(--border);
  color: var(--ink-500); font-weight: 600; font-size: 14.5px;
  letter-spacing: -0.01em; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.marquee .lg:hover { color: var(--ink-900); border-color: var(--border-strong); }
.marquee .lg svg { width: 18px; height: 18px; flex-shrink: 0; }
@media (prefers-reduced-motion: no-preference) {
  .marquee-track { animation: marquee 44s linear infinite; }
  .marquee:hover .marquee-track { animation-play-state: paused; }
  @keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
}
@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee-track { flex-wrap: wrap; width: auto; justify-content: center; }
  .marquee-group { flex-wrap: wrap; justify-content: center; }
  .marquee-group[aria-hidden="true"] { display: none; }
}

/* On phones the ambient blobs are heavier than the benefit — drop them. */
@media (max-width: 620px) { .bg-ambient { display: none; } }

/* ============================================================ hero console */
/* The hero visual: one key driving every modality off one balance. Shown live
   rather than as a static code listing. */
.console {
  background: #0C0A09; border: 1px solid #0C0A09; border-radius: var(--r-lg);
  overflow: hidden; box-shadow: 0 24px 60px rgba(12,10,9,.22);
}
.console-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid rgba(255,255,255,.08);
}
.c-dot { width: 8px; height: 8px; border-radius: 50%; background: #22C55E; flex-shrink: 0; }
@media (prefers-reduced-motion: no-preference) {
  .c-dot { animation: pulse 2.4s ease-in-out infinite; }
}
.console-bar .c-key { font-size: 12px; color: #A8A29E; letter-spacing: .02em; }
.console-bar .c-bal { margin-left: auto; font-size: 12px; color: #A8A29E; }
.console-bar .c-bal #c-bal { color: var(--accent); font-weight: 600; }
.console-screen { padding: 18px 18px 16px; min-height: 248px; }
.c-req { display: flex; align-items: center; gap: 8px; font-size: 12.5px; min-height: 18px; }
.c-tag {
  font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--accent-fg); background: var(--accent);
  padding: 2px 8px; border-radius: 999px;
}
.c-method { color: #86EFAC; font-weight: 600; }
.c-path { color: #E7E5E4; }
/* The prompt line: what the customer actually SENDS. Distinct from the endpoint
   line above it — the endpoint is technical framing, the prompt is the product.
   --accent on #0C0A09 is 12.7:1 and #E7E5E4 is ~15:1, both well clear of AA. */
.c-prompt {
  display: flex; align-items: baseline; gap: 7px;
  margin-top: 10px; font-size: 12.5px; line-height: 1.6;
  color: #E7E5E4; min-height: 20px;
}
.c-prompt .c-arrow { color: var(--accent); font-weight: 700; flex: 0 0 auto; }
.c-prompt #c-prompt { overflow-wrap: anywhere; }
.c-cursor {
  display: inline-block; width: 8px; height: 15px; background: var(--accent);
  border-radius: 1px; animation: caretBlink 1.05s steps(1) infinite;
  flex: 0 0 auto; align-self: center;
}
.c-out {
  margin: 14px 0 0; font-size: 12.8px; line-height: 1.72; color: #E7E5E4;
  white-space: pre-wrap; overflow-wrap: anywhere; min-height: 96px;
}
.c-out .ok { color: #86EFAC; }
.c-out .dim { color: #9A9490; }
.c-meta {
  display: flex; justify-content: space-between; gap: 12px; margin-top: 14px;
  padding-top: 12px; border-top: 1px solid rgba(255,255,255,.07);
  font-size: 11.5px; color: #9A9490; min-height: 16px;
}
.c-meta #c-spend { color: var(--accent); }
.console-chips {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 12px 16px; border-top: 1px solid rgba(255,255,255,.08);
}
.c-chip {
  font-family: var(--font-sans); font-size: 12.5px; font-weight: 600;
  padding: 6px 12px; border-radius: 999px; cursor: pointer;
  background: rgba(255,255,255,.06); color: #D6D3D1; border: 1px solid transparent;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.c-chip:hover { background: rgba(255,255,255,.13); color: #FFFFFF; }
.c-chip.on { background: var(--accent); color: var(--accent-fg); }
.c-hint { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: #78716C; }
@media (max-width: 620px) {
  .c-hint { display: none; }
  .console-screen { min-height: 210px; padding: 15px 15px 13px; }
  .c-out { font-size: 12px; }
}

/* ============================================================ cart */
.cart-btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 8px; color: var(--ink-700);
  border: 1px solid var(--border-strong); background: var(--card);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.cart-btn:hover { background: var(--muted); color: var(--ink-900); }
.cart-badge {
  position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 999px; background: var(--accent); color: var(--accent-fg);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
  border: 2px solid var(--background);
}
.cart-badge[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .cart-btn.bump { animation: cartBump .35s var(--ease-out); }
  @keyframes cartBump { 0% { transform: scale(1); } 40% { transform: scale(1.18); } 100% { transform: scale(1); } }
}
.cart-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 12px);
  background: var(--ink-900); color: #EDEDEF; padding: 11px 18px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; z-index: 300; pointer-events: none;
  opacity: 0; transition: opacity .25s var(--ease-out), transform .25s var(--ease-out);
}
.cart-toast.in { opacity: 1; transform: translate(-50%, 0); }

/* ---------------------------------------------- featured-on badge (footer) */
.site-badge { display: inline-block; margin-top: 16px; }
.site-badge img { display: block; height: 54px; width: auto; border-radius: 10px; }

/* ---------------------------------------------- Google sign-in (GIS) */
/* The button is rendered by Google's script into .g_id_signin; we only centre
   it and draw the "or" divider above it. */
.oauth { margin-top: 22px; }
.oauth .g_id_signin { display: flex; justify-content: center; }
.oauth-or {
  display: flex; align-items: center; gap: 12px;
  color: var(--ink-400); font-size: 12px; margin-bottom: 18px;
}
.oauth-or::before, .oauth-or::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}
.oauth-err {
  margin: 12px 0 0; font-size: 13px; color: var(--danger); text-align: center;
}

/* "Create an account" affordance under the sign-in card. */
.auth-alt { margin-top: 24px; }
.auth-alt-or {
  display: flex; align-items: center; gap: 12px;
  color: var(--ink-400); font-size: 12px; margin-bottom: 14px;
}
.auth-alt-or::before, .auth-alt-or::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}

/* Sign-up consent row. A checkbox must NOT inherit the 44px control sizing. */
.field label.agree {
  display: flex; align-items: flex-start; gap: 10px;
  font-weight: 400; font-size: 13.5px; line-height: 1.5;
  color: var(--ink-500); cursor: pointer; margin-bottom: 0;
}
.field label.agree input[type="checkbox"] {
  width: 18px; height: 18px; min-height: 0; flex: 0 0 auto;
  margin: 2px 0 0; padding: 0; accent-color: var(--accent); cursor: pointer;
}
.field label.agree a { color: var(--accent-ink); text-decoration: underline; }
.oauth-note {
  margin: 12px 0 0; font-size: 12px; color: var(--ink-400); text-align: center;
}
.oauth-note a { color: var(--accent-ink); text-decoration: underline; }

/* ============================================================
   INDIA BAND — the passport, made visual
   The Kotler repositioning: our asset is not the catalogue, it is
   that an Indian developer whose card the labs decline can pay in
   rupees with UPI. This band exists to make that unmissable in one
   glance, above the fold of the middle of the page.

   Colour rule (professional-ui §3): every fill carries its On- pair.
   The band is --ink-900 with #FFFFFF headings (21:1) and rgba(237,
   237,239,.80) body (≈14:1). The UPI/rupee chips are --accent-soft
   (warm tint) with --accent-ink text (5.14:1) — never yellow text on
   a light fill, which would be 1.5:1.
   ============================================================ */
.india { padding: 66px 0; background: var(--ink-900); color: #EDEDEF; }
.india .wrap { display: grid; grid-template-columns: 1.02fr .98fr; gap: 52px;
               align-items: center; }
.india h2 { color: #FFFFFF; font-size: clamp(1.6rem, 3.2vw, 2.3rem);
            line-height: 1.2; letter-spacing: -.02em; margin: 10px 0 16px; }
/* Body copy lifted from .80 to .88 alpha. The vision pass called .80 "soft/
   hazy" — it cleared AA but read as a step dimmer than the headline wanted.
   .88 on --ink-900 is ~15:1, comfortably AAA, and still subordinate to #FFF. */
.india p  { color: rgba(237,237,239,.88); line-height: 1.78; margin: 0 0 14px; }
.india .eyebrow { color: rgba(237,237,239,.72); }
.india .eyebrow .pip { background: var(--accent); }
/* The eyebrow is a pill on the DARK band, so it needs its own fill. Inheriting
   the light-page .eyebrow style left amber text on a pale amber capsule —
   effectively invisible (the vision check flagged it as an unreadable smear).
   Yellow is a fill colour: it must carry dark ink, never be the text. */
.india .eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
  border: 1px solid rgba(255,199,44,.34);
  padding: 7px 14px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; letter-spacing: 0;
}
.india .eyebrow .pip { background: var(--accent-ink); }

/* the chips: what we take, stated as facts not adjectives */
.payrow { display: flex; flex-wrap: wrap; gap: 9px; margin: 22px 0 0; }
.paychip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
  border: 1px solid rgba(255,199,44,.34);
  padding: 9px 14px; border-radius: 999px;
  font-size: 13px; font-weight: 600; letter-spacing: -.01em;
}
.paychip svg { width: 15px; height: 15px; flex: 0 0 auto; }

/* the "declined card" motif — the pain, drawn. Muted, struck through,
   next to the working alternative. */
/* The panel needs a firmer edge: at #141210 on a #0C0A09 band the surface and
   border were too close, so it floated rather than sat. Lifted the surface and
   strengthened the border to #3A342E — enough separation to read as a distinct
   object without becoming a bright box on a dark band. */
.india-art { background: #1C1917; border: 1px solid #4A423B;
             border-radius: var(--r-lg); padding: 26px;
             align-self: stretch; display: flex; flex-direction: column;
             justify-content: center; }
.cardrow { display: flex; align-items: center; gap: 14px; }
.cardrow + .cardrow { margin-top: 14px; }
.cardface {
  flex: 0 0 auto; width: 62px; height: 40px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  letter-spacing: .06em;
}
/* Was a dashed #4A443E on #2A2622 — ~2.5:1, below the 3:1 floor for a
   meaningful boundary, and the vision pass flagged it as the weakest element.
   Now a solid edge at 4.0:1 so the "declined" state reads clearly. */
.cardface.bad  { background: #2E2924; color: #A8A29C;
                 border: 1px solid #57504A; }
.cardface.good { background: var(--accent); color: var(--accent-fg);
                 border: 1px solid var(--accent); }
.cardtext { min-width: 0; }
.cardtext .t { font-size: 13.5px; font-weight: 600; color: #EDEDEF; }
/* Small print lifted from .76 to .84 alpha and 12.5 -> 13px. The vision pass
   called it "legible but lean" at ~5-6:1; .84 on #1C1917 is ~9.5:1, which is
   comfortable rather than merely passing. */
.cardtext .s { font-size: 13px; color: rgba(237,237,239,.84); margin-top: 3px;
               line-height: 1.5; }
/* The struck row was the least legible thing on the page (dim + strike + small).
   The strike carries the meaning, so the TEXT no longer needs to be dimmed to
   .65 — raised to .78 so it is readable while the strike does the work. */
.cardrow.bad .cardtext .t { color: rgba(237,237,239,.78); }
.cardrow.bad .cardtext .t s { text-decoration-color: #A8A29C; }
.carddivider { height: 1px; background: #4A423B; margin: 20px 0; }
.india-note { font-size: 13px; color: rgba(237,237,239,.84); margin: 18px 0 0; }

@media (max-width: 900px) {
  .india { padding: 46px 0; }
  .india .wrap { grid-template-columns: 1fr; gap: 30px; }
}

/* ============================================================
   TRUST STRIP
   Kotler: absence of proof reads as risk, and this brand is asking
   a stranger for money. So the strip carries only checkable facts,
   each linking somewhere real. Deliberately plain — it is meant to
   read as a record, not as marketing.

   Contrast: --ink-900 on --card = 18.9:1 for the key; --ink-500 on
   --card = 7.3:1 for the value. Both clear the 4.5:1 body floor.
   ============================================================ */
.truststrip { padding: 8px 0 46px; }
.tsrow {
  display: grid; grid-template-columns: repeat(5, 1fr);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--card); overflow: hidden;
}
.tsitem {
  display: flex; flex-direction: column; gap: 3px;
  padding: 16px 15px; border-right: 1px solid var(--border);
  text-decoration: none; position: relative;
  transition: background var(--dur-fast) var(--ease-out);
}
.tsitem:last-child { border-right: 0; }
a.tsitem:hover { background: var(--muted); }
.tsk {
  font-size: 13px; font-weight: 650; color: var(--ink-900);
  letter-spacing: -.01em; display: flex; align-items: center; gap: 7px;
  white-space: nowrap;
}
.tsv { font-size: 11.5px; color: var(--ink-500); line-height: 1.4; }
/* live dot — same visual language as the status page, so the link reads as
   "this is real" rather than "this is a claim" */
.tsdot {
  width: 7px; height: 7px; border-radius: 50%; background: #16A34A;
  box-shadow: 0 0 0 3px rgba(22,163,74,.16); flex: 0 0 auto;
  margin-right: 7px;   /* explicit: never rely on the parent flex gap for spacing
                          inside a text run — that collapsed "Live" + "status page" */
  animation: tsPulse 2.6s ease-in-out infinite;
}
@keyframes tsPulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .tsdot { animation: none; } }

@media (max-width: 1040px) {
  .tsrow { grid-template-columns: repeat(3, 1fr); }
  .tsitem:nth-child(3n) { border-right: 0; }
  .tsitem:nth-child(-n+3) { border-bottom: 1px solid var(--border); }
}
@media (max-width: 620px) {
  .tsrow { grid-template-columns: repeat(2, 1fr); }
  .tsitem { border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); }
  .tsitem:nth-child(2n) { border-right: 0; }
  .tsitem:nth-last-child(-n+2) { border-bottom: 0; }
}

/* Closing block inside the India panel. Fills the lower-right pocket and
   answers the immediate next question. Separated by a rule so it reads as a
   footnote to the comparison rather than a third row of it. */
.india-foot {
  margin: 20px 0 0; padding: 16px 0 0;
  border-top: 1px solid #4A423B;
  display: flex; flex-direction: column; gap: 4px;
}
.india-foot .ifk {
  font-size: 13px; font-weight: 650; color: #FFFFFF; letter-spacing: -.01em;
}
.india-foot .ifv { font-size: 13px; color: rgba(237,237,239,.84); line-height: 1.5; }

/* The "Live" prefix is emphasised in green, but word spacing must NOT come from
   the parent's flex gap — that collapsed "Live" + "status page" into
   "Livestatus page" in review. Explicit margin-right instead. */
.tsdot-lbl { color: #16A34A; margin-right: 1px; }
