/* ════════════════════════════════════════════════════════════════
   TAGSIGHT · CANONICAL LANDING + PRE-AUTH CHROME
   Ported from claude-design canonical handoff (2026-06-04).
   Scoped under .ts-canon so it does not collide with the
   brand-v4 token system still owning the rest of the marketing
   pages. The /app shell uses the same token system (app-v2-tokens
   under .ts-app-v2) so the user lands in an identical paint.

   Light = the default working surface paper (#F1F4F0).
   Dark  = neutral graphite; green lives ONLY in the accent.
   ════════════════════════════════════════════════════════════════ */

/* ───────── tokens · light (default + explicit marketing) ───────── */
.ts-canon,
[data-theme="marketing"] .ts-canon,
[data-theme="light"] .ts-canon,
[data-theme="system"] .ts-canon {
  /* Page canvas = a clean COOL light gray (B >= R), not the old warm zinc
     stone that read dull/yellowish. The ladder rises from this cool gray to
     pure white so sections + cards stay distinct planes, but the whole thing
     is cooler and brighter now (crisp, not cream). Forest inks + mint accent
     are kept, so the green brand colour pops against the cool canvas. */
  --bg:        #E8ECF3;
  --bg-alt:    #DEE4EE;
  --surface:   #F6F9FD;
  --surface-2: #ECF1F7;
  --surface-3: #DBE2EC;
  --rail:      #DDE3EA;
  --rail-2:    #CCD4DD;
  --over:      rgba(255,255,255,0.82);

  --ink-1: #0E1A14;
  --ink-2: #364039;
  --ink-3: #5E6760;
  --ink-4: #828B83;
  --ink-5: #AEB4AD;

  --line:    rgba(17,25,34,0.16);
  --line-2:  rgba(17,25,34,0.10);
  --line-3:  rgba(17,25,34,0.07);
  --line-strong: rgba(17,25,34,0.28);

  --accent:      #0C8F61;
  --accent-2:    #0A7B53;
  --accent-fill: #18C088;
  --accent-fill-h:#13B07C;
  --accent-fg:   #052A1E;
  --accent-soft: rgba(24,192,136,0.12);
  --accent-line: rgba(12,143,97,0.34);
  --accent-glow: rgba(24,192,136,0.18);

  --flag:      #B5781B;
  --flag-soft: rgba(181,120,27,0.13);
  --bad:       #C03A2B;
  --bad-soft:  rgba(192,58,43,0.12);
  --good:      #0C8F61;

  /* Dimensional elevation — inset top light-catch + layered ambient drop
     (ported from the app/spine premium recast 2026-07-07). The inset white
     top edge is what sells the 3D; the flat two-layer shadow it replaced read
     as a sticker. --shadow-ctl keeps buttons crisp and close to the plane.
     NOTE: the .intel-sec light-mode dark island (below) MUST re-darken these,
     or the bright top-catch bleeds onto its near-black cells. */
  --shadow-1:
    inset 0 1px 0 rgba(255,255,255,0.85),
    0 1px 2px rgba(20,24,31,0.07),
    0 4px 10px -3px rgba(20,24,31,0.10),
    0 12px 22px -10px rgba(20,24,31,0.10);
  --shadow-2:
    inset 0 1px 0 rgba(255,255,255,0.90),
    0 2px 4px rgba(20,24,31,0.08),
    0 10px 22px -6px rgba(20,24,31,0.14),
    0 24px 44px -16px rgba(20,24,31,0.16);
  --shadow-3:
    0 1px 2px rgba(20,24,31,0.10),
    0 14px 30px -8px rgba(20,24,31,0.20),
    0 34px 64px -22px rgba(20,24,31,0.26);
  --shadow-ctl:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 1px 2px rgba(20,24,31,0.14);

  color-scheme: light;
}

/* ───────── tokens · dark ─────────
   Three selectors needed:
     1. html data-theme="dark" — page-level dark mode
     2. html.dark            — legacy .dark class cascade
     3. .ts-canon [data-theme="dark"] — when a child block scopes itself to
        dark (canonical topbar, hero `data-theme="dark"` on the section).
        Without this third selector, the topbar inherits light tokens
        via the .ts-canon cascade even when its own attribute is set,
        and paints the wrong color in light mode. */
[data-theme="dark"] .ts-canon,
html.dark .ts-canon,
.ts-canon [data-theme="dark"] {
  /* Deeper bg + stronger step ladder so alternating sections read as
     distinct planes instead of one flat slab. Bg dropped one step to
     true near-black; surface lifted one step. */
  --bg:        #07090A;
  --bg-alt:    #0D1312;
  --surface:   #1B2220;
  /* steps widened 2026-06-22 so stacked planes (section < grid < card < band)
     read as distinct tones instead of one flat grey ("same colour"). */
  --surface-2: #28302C;
  --surface-3: #333D38;
  --rail:      #0C100F;
  --rail-2:    #262C29;
  --over:      rgba(16,20,19,0.74);

  --ink-1: #F6F8F6;
  --ink-2: #D2D7D4;
  /* The MARK's ink, not body copy. BrandMark reads --mark-ink and falls back to
     the light brand ink, so every dark scope must reverse it here. Keep it the
     LOGO LAW reversed value verbatim; never point it at --ink-1. */
  --mark-ink: #F5F8F5;
  --ink-3: #ABB1AD;
  --ink-4: #8B928D;
  --ink-5: #5A615D;

  /* Hairlines bumped 2026-06-22 (premium-craft pass) so card edges, dividers
     and table rows read as deliberate structure on the deep base, not mush. */
  --line:    rgba(236,239,237,0.22);
  --line-2:  rgba(236,239,237,0.14);
  --line-3:  rgba(236,239,237,0.09);
  --line-strong: rgba(236,239,237,0.44);

  /* Mint pushed brighter on dark — premium accent, never a big fill.
     Matches the canonical intent: "mint reads premium on dark, never
     a big light fill." */
  --accent:      #6FE9BB;
  --accent-2:    #8AEEC9;
  --accent-fill: #4EDDA8;
  --accent-fill-h:#63E3B6;
  --accent-fg:   #03130C;
  --accent-soft: rgba(78,221,168,0.18);
  --accent-line: rgba(78,221,168,0.50);
  --accent-glow: rgba(78,221,168,0.36);

  --flag:      #F0B45C;
  --flag-soft: rgba(240,180,92,0.18);
  --bad:       #F2796B;
  --bad-soft:  rgba(242,121,107,0.18);
  --good:      #4EDDA8;

  /* Deeper shadows so depth reads on graphite. A faint inset top edge +
     hairline ring stand in for the light-catch the deep base swallows. */
  --shadow-1: 0 1px 2px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.05), 0 0 0 1px rgba(236,239,237,0.035);
  --shadow-2: 0 16px 36px -16px rgba(0,0,0,0.85), inset 0 1px 0 rgba(255,255,255,0.06), 0 4px 10px -2px rgba(0,0,0,0.7);
  --shadow-3: 0 34px 78px -28px rgba(0,0,0,0.92), 0 8px 22px -8px rgba(0,0,0,0.7);
  --shadow-ctl: inset 0 1px 0 rgba(255,255,255,0.06), 0 1px 2px rgba(0,0,0,0.6);

  color-scheme: dark;
}

/* ───────── shared base ───────── */
.ts-canon {
  /* fonts — IBM Plex Sans for working ink, Space Grotesk for display,
     Source Serif 4 for em italic, JetBrains Mono for numerics/codes. */
  --f-sans: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --f-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
  --f-display: 'Space Grotesk', 'IBM Plex Sans', system-ui, sans-serif;
  --f-serif:   'Source Serif 4', Georgia, serif;

  --r-sm: 6px;
  --r-md: 9px;
  --r-lg: 13px;
  --r-xl: 18px;

  --pad-xl:      clamp(104px, 11vw, 176px);
  --pad-default: clamp(76px, 8vw, 124px);
  --pad-md:      clamp(56px, 6vw, 92px);
  --pad-sm:      clamp(40px, 4.2vw, 64px);

  --mkt-w: 1280px;
  --gut:   clamp(24px, 4.4vw, 56px);

  background: var(--bg);
  color: var(--ink-1);
  font-family: var(--f-sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
.ts-canon *,
.ts-canon *::before,
.ts-canon *::after { box-sizing: border-box; }
.ts-canon a { color: inherit; text-decoration: none; }
.ts-canon button { font: inherit; color: inherit; cursor: pointer; background: none; border: none; }
.ts-canon svg { display: block; }
.ts-canon ::selection { background: var(--accent-fill); color: var(--accent-fg); }

/* ───────── interaction floor ─────────
   Ported from the post-auth app (.ts-app-v2): every control gets a keyboard
   focus ring and a physical press dip, so nothing reads as dead. Scoped to
   real controls (the SVG hotspots in Explore own a bespoke focus treatment,
   so they're excluded). Sub-pixel dip is acceptable under reduced-motion —
   it matches the app — but we still null the transform there to be safe. */
.ts-canon a:focus-visible,
.ts-canon button:focus-visible,
.ts-canon [role="button"]:focus-visible,
.ts-canon input:focus-visible,
.ts-canon select:focus-visible,
.ts-canon textarea:focus-visible,
.ts-canon [tabindex]:focus-visible {
  outline: 2px solid var(--accent-line);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
.ts-canon button:active:not(:disabled),
.ts-canon [role="button"]:active:not([aria-disabled="true"]) {
  transform: translateY(0.5px) scale(0.992);
  opacity: 0.9;
}
@media (prefers-reduced-motion: reduce) {
  .ts-canon button:active:not(:disabled),
  .ts-canon [role="button"]:active:not([aria-disabled="true"]) { transform: none; }
}

.ts-canon .mono { font-family: var(--f-mono); font-feature-settings: "tnum" 1; }
.ts-canon .tag  { font-family: var(--f-mono); font-weight: 500; letter-spacing: -0.01em; }

/* mint headline terminal — the brand's "closing period in mint" (§05).
   The single unifying accent across the display headlines; one mark per screen. */
.ts-canon .h-dot { color: var(--accent-fill); }

/* ───────── shared atoms ─────────
   Mono eyebrows/labels: 11.5px floor per the brand v4 typography
   doctrine. Below 11.5 reads as scaffolding tags, not text. */
.ts-canon .eyebrow {
  font-family: var(--f-mono);
  font-size: 11.5px; font-weight: 500;
  letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink-4);
}

.ts-canon .btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 500; letter-spacing: -0.006em;
  padding: 9px 16px; border-radius: var(--r-sm);
  border: 1px solid transparent; cursor: pointer;
  transition: background 140ms var(--ease, ease), border-color 140ms, color 140ms, transform 140ms var(--ease, ease), box-shadow 180ms;
  white-space: nowrap;
}
.ts-canon .btn svg { width: 15px; height: 15px; }
.ts-canon .btn-ghost { color: var(--ink-2); }
.ts-canon .btn-ghost:hover { background: var(--surface-3); color: var(--ink-1); }
.ts-canon .btn-line { border-color: var(--line); color: var(--ink-2); background: var(--surface); }
.ts-canon .btn-line:hover { border-color: var(--line-strong); color: var(--ink-1); }
.ts-canon .btn-icon { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; color: var(--ink-3); border-radius: var(--r-sm); flex: none; }
.ts-canon .btn-icon svg { display: block; }
.ts-canon .btn-icon:hover { background: var(--surface-3); color: var(--ink-1); }
.ts-canon .btn-lg { font-size: 15px; padding: 15px 26px; border-radius: 10px; gap: 9px; }
.ts-canon .btn-lg svg { width: 17px; height: 17px; }

/* marketing primary — dark forest pill, mint as the arrow accent only.
   Matches canonical CSS comment: "primary is a dark graphite pill, NOT
   mint. mint is reserved for thin accents (tags, class, pulse, citations)." */
.ts-canon .btn-pri {
  background: linear-gradient(180deg, #1B2A22 0%, #14201A 100%); color: #F3F7F3; font-weight: 600;
  border: 1px solid rgba(255,255,255,0.10);
  box-shadow: 0 1px 0 rgba(255,255,255,0.07) inset, 0 2px 4px rgba(8,14,10,0.28), 0 14px 30px -14px rgba(8,14,10,0.62);
}
.ts-canon .btn-pri:hover { background: linear-gradient(180deg, #21332A 0%, #182720 100%); box-shadow: 0 1px 0 rgba(255,255,255,0.09) inset, 0 3px 6px rgba(8,14,10,0.3), 0 18px 38px -14px rgba(8,14,10,0.7); transform: translateY(-1.5px); }
.ts-canon .btn-pri svg { color: var(--accent-2); }
[data-theme="dark"] .ts-canon .btn-pri,
html.dark .ts-canon .btn-pri { background: #1B2722; border-color: rgba(255,255,255,0.1); color: #ECF2EE; }
[data-theme="dark"] .ts-canon .btn-pri:hover,
html.dark .ts-canon .btn-pri:hover { background: #233029; }
.ts-canon .btn-lg:active { transform: translateY(1px); }

.ts-canon .pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 500;
  padding: 4px 9px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink-2);
  background: var(--surface);
  transition: border-color 130ms, color 130ms, background 130ms;
}
.ts-canon .pill .n { font-family: var(--f-mono); font-weight: 600; }
.ts-canon .pill.mint { color: var(--accent); border-color: var(--accent-line); background: var(--accent-soft); }

.ts-canon .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.ts-canon .dot.flag { background: var(--flag); }
.ts-canon .dot.bad { background: var(--bad); }
.ts-canon .dot.good { background: var(--good); }

/* ───────── page scaffold ───────── */
.ts-canon .page { width: 100%; min-height: 100vh; }
.ts-canon .sec { position: relative; }
.ts-canon .sec > .wrap { max-width: var(--mkt-w); margin: 0 auto; padding-left: var(--gut); padding-right: var(--gut); }
.ts-canon .pad-xl { padding-top: var(--pad-xl); padding-bottom: var(--pad-xl); }
.ts-canon .pad-default { padding-top: var(--pad-default); padding-bottom: var(--pad-default); }
.ts-canon .pad-md { padding-top: var(--pad-md); padding-bottom: var(--pad-md); }
.ts-canon .pad-sm { padding-top: var(--pad-sm); padding-bottom: var(--pad-sm); }

.ts-canon .bg-base { background: var(--bg); }
.ts-canon .bg-surface { background: var(--surface); }
/* dark — give every section a subtle top-lit depth so the page reads as a
   cohesive lit surface, never a flat slab. Barely-there per-section glow; the
   hero overrides with a stronger version. (premium-craft pass, 2026-06-22) */
[data-theme="dark"] .ts-canon .bg-base,
html.dark .ts-canon .bg-base {
  background: radial-gradient(150% 78% at 50% 0%, #0C1013 0%, #080B0C 52%, var(--bg) 100%);
}
/* alternating section tone — applied to every other section so the page has
   rhythm as you scroll instead of one continuous slab. The bg change IS the
   divider (brand §04·10). White/light cards still lift on it. 2026-06-22. */
.ts-canon .bg-alt { background: var(--bg-alt); }
[data-theme="dark"] .ts-canon .bg-alt,
html.dark .ts-canon .bg-alt {
  background: radial-gradient(150% 82% at 50% 0%, #18211E 0%, #121A17 50%, #0E1513 100%);
}
.ts-canon .ts-divider--hair { border: 0; height: 1px; background: var(--line-2); max-width: var(--mkt-w); margin: 0 auto; }

/* ───────── shared type atoms ───────── */
.ts-canon h1.h-hero, .ts-canon h2.h-sec {
  font-family: var(--f-display); font-weight: 600;
  line-height: 1.04; letter-spacing: -0.028em; margin: 0;
  text-wrap: balance; color: var(--ink-1);
}
.ts-canon h1.h-hero { font-size: clamp(34px, 4vw, 56px); font-weight: 500; line-height: 1.0; }
.ts-canon h2.h-sec  { font-size: clamp(28px, 2.9vw, 40px); font-weight: 600; }
.ts-canon .h-sec em, .ts-canon .h-hero em { font-family: var(--f-serif); font-style: italic; font-weight: 400; letter-spacing: -0.01em; }

.ts-canon .sec-head { display: flex; flex-direction: column; gap: 14px; max-width: 68ch; position: relative; border-top: 1px solid var(--line); padding-top: clamp(28px, 2.9vw, 42px); }
.ts-canon .sec-head::before { content: ""; position: absolute; top: -1px; left: 0; width: 48px; height: 2px; background: var(--accent-fill); }
.ts-canon .sec-head .lede,
.ts-canon .sec-head .sec-lede { font-size: clamp(16px, 1.35vw, 18.5px); color: var(--ink-2); margin: 0; max-width: 64ch; line-height: 1.55; }

/* ═══════════ TOP BAR SURFACE · ONE COLOUR, EVERY PRE-AUTH PAGE ═══════════
   The bar element itself is chrome-less (transparent, see .topbar below), so
   the colour a visitor actually sees above the fold is this wrapper, which
   components/landing-navbar.tsx renders as `ts-canon ts-barhost`.

   The bug this closes (founder, 2026-07-26, "the topbar colour is different on
   the landing page and different on other pre-auth pages"): the homepage
   painted its bar white via `.cine-home .ts-canon` in _home-cine.css while
   every other page fell through to `.ts-canon { background: var(--bg) }`.
   Measured on prod before the fix: / = rgb(255,255,255); /pricing /security
   /integrations /about /contact /blog /help and the 404 = rgb(232,236,243).

   White with a hairline + a soft shadow is the founder-approved homepage
   treatment, so the homepage stays put and every other page moves onto it.

   Two things are deliberate and load-bearing:
     - the hook is `.ts-barhost`, NOT `.ts-canon`. The bare `.ts-canon` selector
       also matches the FOOTER wrapper (components/footer.tsx), which is why the
       homepage rule could never be generalised without repainting the footer.
     - it lives HERE, not in the marketing-only _cine-theme.css. This file is
       imported by landing-navbar.tsx itself, so the rule reaches every surface
       that renders the bar, including app/not-found.tsx which sits outside the
       (marketing) route group and was therefore left on #E8ECF3.
   Locked by components/__tests__/topbar-surface-contract.test.ts.

   `--bar-surface` is the SINGLE source of that colour. It is declared here and
   inherits down to every part of the bar that can become opaque when the user
   PRESSES something: the bar in its mega-open and mobile-sheet-open states, the
   mega panel, the dropdown panels, and the mobile drawer. Those five used to
   read `var(--surface)` (#F6F9FD) or `var(--bg)` (#E8ECF3), so opening a nav
   group or the hamburger repainted the bar off white and put the mismatched
   band straight back above it (founder, 2026-07-26, second report). Anything
   that goes opaque on the bar reads this token. Never hardcode a surface into
   one of those rules again.
   `.ts-canon.ts-barhost` (0,2,0) rather than the bare class, so it outranks the
   `.ts-canon { background: var(--bg) }` base by SPECIFICITY and not merely by
   being further down the file. */
.ts-canon.ts-barhost {
  --bar-surface: #FFFFFF;
  background: var(--bar-surface);
  border-bottom: 1px solid rgba(9,20,15,0.07);
  box-shadow: 0 1px 2px rgba(9,20,15,0.04);
  /* THE NOTCH STRIP (founder, recurring, ~10 reports). viewport-fit=cover puts
     the status-bar / notch zone INSIDE the viewport, so something has to paint
     it. Every previous attempt used a `position: fixed` ::before pinned to the
     top of the screen and filled with a LITERAL #FFFFFF, scoped to the per-page
     `.cine` class (_cine-theme.css + _home-cine.css, both deleted 2026-07-30).
     That mechanism is why this kept coming back:
       - the bar is NOT effectively sticky (`.topbar` is position:sticky inside
         this wrapper, whose height IS the bar's, so its sticky travel is zero
         and it scrolls away, as lib/status-bar-paint.ts already documents). A
         fixed painter therefore became a WHITE BAND sitting over whatever dark
         band or the dark footer had scrolled under the notch. Measured before
         this change at 390x844 on /: #ffffff above the boundary against
         #0f1213 below it, once scrolled to the footer.
       - `.cine` is applied per PAGE, so app/not-found.tsx and every
         components/marketing-page-shell.tsx route (blog, help) never had a
         painter at all.
     Owning the inset as PADDING on the wrapper that already paints the bar
     makes the strip the bar's own surface by construction: it cannot drift from
     --bar-surface, it cannot be missing on a page that forgot a class, and when
     the page scrolls the bar leaves with it instead of leaving a band behind.
     0px on non-notched devices, so it costs nothing there.
     Locked by components/__tests__/safe-area-strip-contract.test.ts and
     measured in pixels by scripts/preauth-strip-check.mjs. */
  padding-top: env(safe-area-inset-top, 0px);
}
[data-theme="dark"] .ts-canon.ts-barhost,
html.dark .ts-canon.ts-barhost {
  --bar-surface: #0B0C0E;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  box-shadow: none;
}

/* ═══════════════ TOP BAR (sticky, theme-aware) ═══════════════ */
.ts-canon .topbar {
  position: sticky; top: 0; z-index: 60; color: var(--ink-1);
  /* Chrome-less: no bar. The logo + nav + actions sit directly on the page
     surface (transparent, no border/shadow) and inherit the PAGE theme
     (data-theme="dark" removed from the header element), instead of the old
     heavy dark bar bolted on top. Opaque only when the mobile sheet is open. */
  background: transparent;
  border-bottom: 1px solid transparent;
}
/* When a mega panel is open, the bar takes the SAME surface as the panel so the
   bar + panel read as one continuous white sheet (no colour seam). That surface
   is --bar-surface, i.e. the colour the bar ALREADY is: pressing a nav group
   must not change the bar's colour. It used to be var(--surface) #F6F9FD. */
.ts-canon .topbar.is-mega-open { background: var(--bar-surface, var(--surface)); }
/* While the mobile sheet is open the body is pinned (position:fixed, see
   top-bar.tsx) so touch can't scroll the page behind the menu. Pin the
   topbar too so it stays at the top instead of riding the pinned body
   off-screen when the menu is opened mid-scroll. */
.ts-canon .topbar.is-sheet-open {
  position: fixed; top: 0; left: 0; right: 0;
  /* Going fixed lifts the bar OUT of .ts-barhost, so it stops being covered by
     the wrapper's safe-area padding and would slide under the notch. Carry the
     inset itself while pinned, painted with the same --bar-surface below. */
  padding-top: env(safe-area-inset-top, 0px);
  /* The mobile drawer needs an opaque bar regardless of scroll position, and it
     must be the colour the bar ALREADY is. This was var(--bg) #E8ECF3, so
     tapping the hamburger repainted the bar and re-created the mismatched band
     above it against the white safe-area strip. */
  background: var(--bar-surface, var(--bg));
  border-bottom-color: var(--line);
}
.ts-canon .topbar-in {
  /* Full-bleed with a comfortable inset. Taller, roomier bar (spacious,
     legitimate) — the logo + nav + actions get air rather than being crammed. */
  max-width: none; margin: 0; padding: 14px clamp(32px, 5vw, 92px);
  display: flex; align-items: center; gap: 28px;
}
.ts-canon .tb-brand { display: flex; align-items: center; gap: 11px; }
.ts-canon .tb-word { font-family: var(--f-display); font-weight: 600; font-size: 19px; letter-spacing: -0.02em; color: var(--ink-1); }
.ts-canon .tb-nav { display: flex; align-items: center; gap: 4px; margin-left: 8px; }

/* both nav-trigger buttons and plain nav links share one look */
.ts-canon .tb-nav-link,
.ts-canon .tb-nav-trigger {
  font-size: 15px; font-weight: 500; color: var(--ink-2);
  padding: 9px 15px; border-radius: var(--r-sm);
  transition: background 130ms, color 130ms;
  display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap; cursor: pointer;
  font-family: inherit;
}
.ts-canon .tb-nav-link:hover,
.ts-canon .tb-nav-trigger:hover,
.ts-canon .tb-nav-item.is-open > .tb-nav-trigger {
  color: var(--ink-1); background: var(--surface-3);
}
.ts-canon .tb-nav-link.is-active {
  color: var(--ink-1);
  background: var(--surface-3);
  box-shadow: inset 0 -2px 0 0 var(--accent);
}
.ts-canon .tb-nav-trigger svg {
  color: var(--ink-3); transition: transform .15s ease, color .15s;
}
.ts-canon .tb-nav-item.is-open > .tb-nav-trigger svg {
  transform: rotate(-90deg);
  color: var(--accent);
}

/* ── Product 2-column dropdown · tight ── */
.ts-canon .tb-dropdown.is-wide { min-width: 540px; padding: 8px; }
.ts-canon .tb-dropdown-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
.ts-canon .tb-dropdown-col { display: flex; flex-direction: column; min-width: 0; }
.ts-canon .tb-dropdown-colhead {
  font-family: var(--f-mono); font-size: 11.5px; font-weight: 500;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-3);
  padding: 6px 11px 8px;
  margin-bottom: 2px;
}
@media (max-width: 720px) {
  .ts-canon .tb-dropdown.is-wide { min-width: 84vw; }
  .ts-canon .tb-dropdown-cols { grid-template-columns: 1fr; gap: 2px; }
}

.ts-canon .tb-nav-item { position: relative; }
/* Wide mega panels anchor to the whole nav (not the individual trigger) so a
   right-side trigger's panel can't run off the screen edge. All mega menus then
   open from a consistent left position, like a real product bar. */
.ts-canon .tb-nav-item.has-mega { position: static; }

/* ─── dropdown panel · lean industrial list ─── */
.ts-canon .tb-dropdown {
  position: absolute;
  top: calc(100% + 4px); left: 0;
  min-width: 240px;
  /* one sheet with the bar: --bar-surface, never a separate off-white. */
  background: var(--bar-surface, var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  padding: 6px;
  z-index: 80;
  animation: ts-canon-dd-in 120ms ease;
}
@keyframes ts-canon-dd-in {
  from { opacity: 0; transform: translateY(-3px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .ts-canon .tb-dropdown { animation: none; }
}
.ts-canon .tb-dropdown-grid {
  display: flex; flex-direction: column; gap: 1px;
}
.ts-canon .tb-dropdown-item {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 9px 11px;
  border-radius: 7px;
  color: var(--ink-1);
  transition: background 120ms;
}
.ts-canon .tb-dropdown-item.has-glyph { align-items: center; }
.ts-canon .tb-dropdown-item:hover { background: var(--surface-2); }
.ts-canon .tb-dd-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ts-canon .tb-dd-name { font-size: 14px; font-weight: 600; color: var(--ink-1); letter-spacing: -0.005em; white-space: nowrap; }
.ts-canon .tb-dd-meta { font-size: 11.5px; line-height: 1.35; color: var(--ink-3); }
.ts-canon .tb-dd-glyph {
  font-family: var(--f-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--ink-2); background: var(--surface-3); border: 1px solid var(--line-2);
  border-radius: 5px; padding: 5px 6px; min-width: 34px; text-align: center; line-height: 1;
  flex-shrink: 0; transition: color 120ms, border-color 120ms;
}
.ts-canon .tb-dropdown-item:hover .tb-dd-glyph { color: var(--ink-1); border-color: var(--line-strong); }

.ts-canon .tb-dropdown-foot {
  display: inline-flex; align-items: center; justify-content: flex-start;
  gap: 8px;
  margin-top: 4px;
  padding: 9px 12px;
  border-top: 1px solid var(--line-2);
  border-radius: 0 0 6px 6px;
  color: var(--accent);
  font-family: var(--f-mono); font-size: 12.5px; font-weight: 500;
  letter-spacing: 0.02em;
  transition: background 120ms;
}
.ts-canon .tb-dropdown-foot:hover { background: var(--accent-soft); }
.ts-canon .tb-dropdown-foot svg { transition: transform .15s; }
.ts-canon .tb-dropdown-foot:hover svg { transform: translateX(3px); }

/* ── Products & Solutions mega: capability columns + a solution-card rail ── */
.ts-canon .tb-dropdown.has-cards { min-width: 760px; padding: 12px; }
.ts-canon .tb-dd-body {
  display: grid; grid-template-columns: minmax(280px, 1fr) minmax(300px, 340px);
  gap: 18px; align-items: start;
}
.ts-canon .tb-dropdown-sol {
  border-left: 1px solid var(--line-2); padding-left: 16px;
}
.ts-canon .tb-sol-grid { display: flex; flex-direction: column; gap: 2px; }
.ts-canon .tb-sol-card {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 12px;
  padding: 9px 10px; border-radius: var(--r-sm);
  transition: background 120ms;
}
.ts-canon .tb-sol-card:hover { background: var(--surface-2); }
.ts-canon .tb-sol-glyph {
  font-family: var(--f-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--ink-2); background: var(--surface-3); border: 1px solid var(--line-2);
  border-radius: 5px; padding: 5px 6px; min-width: 34px; text-align: center; line-height: 1;
}
.ts-canon .tb-sol-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ts-canon .tb-sol-name { font-size: 13.5px; font-weight: 600; color: var(--ink-1); letter-spacing: -0.01em; }
.ts-canon .tb-sol-meta { font-size: 11.5px; line-height: 1.36; color: var(--ink-3); }
.ts-canon .tb-sol-card > svg { color: var(--ink-4); opacity: 0; transform: translateX(-3px); transition: opacity .15s, transform .15s, color .15s; }
.ts-canon .tb-sol-card:hover > svg { opacity: 1; transform: translateX(0); color: var(--accent); }

/* two foot links side by side (All exports · All solutions) */
.ts-canon .tb-dropdown-foots { display: flex; gap: 4px; margin-top: 8px; border-top: 1px solid var(--line-2); padding-top: 6px; }
.ts-canon .tb-dropdown-foots .tb-dropdown-foot { border-top: 0; margin-top: 0; }

@media (max-width: 840px) {
  .ts-canon .tb-dropdown.has-cards { min-width: 84vw; }
  .ts-canon .tb-dd-body { grid-template-columns: 1fr; gap: 12px; }
  .ts-canon .tb-dropdown-sol { border-left: 0; padding-left: 0; border-top: 1px solid var(--line-2); padding-top: 10px; }
  .ts-canon .tb-dropdown-foots { flex-direction: column; }
}

/* ═══ MEGA MENU — full-width panel under the bar (Cadmatic-style) ═══
   Anchored to .topbar (sticky = positioned ancestor) so it spans edge to edge
   and can never run off-screen. Content aligns to the same left gutter as the
   logo. Big section headings, name + description items, generous spacing. */
.ts-canon .tb-mega {
  position: absolute; top: 100%; left: 0; right: 0;
  /* one sheet with the bar: --bar-surface, never a separate off-white. */
  background: var(--bar-surface, var(--surface));
  border-bottom: 1px solid var(--line);
  box-shadow: 0 26px 50px -26px rgba(14,26,20,0.22);
  z-index: 80;
  animation: ts-canon-dd-in 140ms ease;
}
@media (prefers-reduced-motion: reduce) { .ts-canon .tb-mega { animation: none; } }
.ts-canon .tb-mega-in {
  max-width: 1440px; margin: 0;
  padding: clamp(44px, 4vw, 64px) clamp(28px, 3vw, 56px) clamp(36px, 3vw, 48px);
}
/* generous, airy horizontal spread (Cadmatic): sections sit far apart, using the
   width instead of clustering in the left corner. */
.ts-canon .tb-mega-cols { display: flex; flex-wrap: wrap; align-items: start; gap: clamp(40px, 4vw, 60px) clamp(64px, 8vw, 168px); }
.ts-canon .tb-mega-sec { flex: 0 1 auto; min-width: 210px; max-width: 300px; }
.ts-canon .tb-mega-sec--cards { max-width: 420px; }
.ts-canon .tb-mega-h {
  font-family: var(--f-display); font-size: 20px; font-weight: 600;
  color: var(--ink-1); letter-spacing: -0.015em;
  margin: 0 0 24px; padding-bottom: 16px; border-bottom: 1px solid var(--line-2);
}
.ts-canon .tb-mega-list { display: flex; flex-direction: column; gap: 9px; }
/* one heading over a 2-column item grid (Cadmatic Resources / By-industry) */
.ts-canon .tb-mega-sec--2 { max-width: clamp(520px, 55vw, 840px); }
.ts-canon .tb-mega-list--2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px clamp(80px, 9vw, 190px); }
.ts-canon .tb-mega-item {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 10px 11px; margin: 0 -11px; border-radius: 9px;
  transition: background 120ms;
}
.ts-canon .tb-mega-item.has-glyph { align-items: center; }
.ts-canon .tb-mega-item:hover { background: var(--surface-2); }
.ts-canon .tb-mega-glyph {
  font-family: var(--f-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--ink-2); background: var(--surface-3); border: 1px solid var(--line-2);
  border-radius: 6px; padding: 6px; min-width: 38px; text-align: center; line-height: 1;
  flex-shrink: 0; transition: color 120ms, border-color 120ms;
}
.ts-canon .tb-mega-item:hover .tb-mega-glyph { color: var(--ink-1); border-color: var(--line-strong); }
.ts-canon .tb-mega-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ts-canon .tb-mega-name { font-size: 15px; font-weight: 600; color: var(--ink-1); letter-spacing: -0.008em; }
.ts-canon .tb-mega-desc { font-size: 13px; line-height: 1.42; color: var(--ink-3); margin-top: 1px; }
/* Support: a bordered card grid (Cadmatic Support pattern) — one section that
   spans the full width, cards flow across it. */
.ts-canon .tb-mega-sec--cardgrid { flex: 1 1 100%; max-width: none; }
.ts-canon .tb-mega-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px; max-width: 1180px;
}
.ts-canon .tb-mega-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 20px 22px; border: 1px solid var(--line-2); border-radius: 12px;
  background: var(--surface);
  transition: border-color 140ms, background 140ms, box-shadow 140ms, transform 140ms;
}
.ts-canon .tb-mega-card:hover {
  border-color: var(--line-strong); background: var(--surface-2);
  box-shadow: 0 12px 30px -18px rgba(14,26,20,0.24); transform: translateY(-2px);
}
.ts-canon .tb-mega-card-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ts-canon .tb-mega-card-top svg { color: var(--ink-4); flex-shrink: 0; transition: color 140ms, transform 140ms; }
.ts-canon .tb-mega-card:hover .tb-mega-card-top svg { color: var(--accent); transform: translate(2px, -2px); }

.ts-canon .tb-mega-foot {
  display: flex; gap: 30px; margin-top: 24px; padding-top: 18px;
  border-top: 1px solid var(--line-2);
}
.ts-canon .tb-mega-footlink {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--f-mono); font-size: 13px; font-weight: 500;
  letter-spacing: 0.01em; color: var(--accent);
}
.ts-canon .tb-mega-footlink svg { transition: transform 120ms; }
.ts-canon .tb-mega-footlink:hover svg { transform: translateX(3px); }
@media (max-width: 900px) {
  .ts-canon .tb-mega-cols { flex-wrap: wrap; gap: 28px 36px; }
  .ts-canon .tb-mega-sec { max-width: none; flex: 1 1 40%; }
}

/* mobile sheet — group ledes + grouped links */
.ts-canon .tb-sheet-group { display: flex; flex-direction: column; gap: 4px; padding-top: 12px; }
.ts-canon .tb-sheet-h {
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-4);
  padding: 0 8px 4px;
}
.ts-canon .tb-sheet-link {
  font-size: 15px; color: var(--ink-1); padding: 10px 8px;
  border-bottom: 1px solid var(--line-2);
}
.ts-canon .tb-sheet-foot {
  font-family: var(--f-mono); font-size: 12.5px; color: var(--accent);
  border-bottom: 0;
}
.ts-canon .tb-spacer { flex: 1; }
.ts-canon .tb-actions { display: flex; align-items: center; gap: 10px; }
/* Topbar CTA (Dashboard / Start a workspace / Sign in). The base .btn size
   read undersized next to the 14.5px nav — "Dashboard" in particular was a
   tiny pill. Give the actions presence (full 14.5px text, generous
   horizontal padding) while keeping vertical padding tight so the whole bar
   stays compact — the CTA anchors the right without ballooning bar height.
   Scoped to the topbar actions only (not every .btn site-wide). */
.ts-canon .tb-actions .btn {
  font-size: 14.5px;
  font-weight: 600;
  padding: 13px 24px;
  border-radius: 9px;
}
/* The primary CTA gets real presence. Without a floor, a short label
   ("Dashboard") collapsed the button to ~120px and it read stubby next to the
   nav. The reference bar (Cadmatic) pins its topbar CTA at 48x180 for exactly
   this reason: the button is a fixed anchor, not a label-width chip. */
.ts-canon .tb-actions .btn-pri { min-width: 158px; justify-content: center; }
.ts-canon .tb-actions .btn-ghost { padding: 13px 16px; font-weight: 500; }
.ts-canon .tb-actions .btn-icon { width: 38px; height: 38px; }

/* ─── auth-state actions (the anti-flash contract) ───
   The topbar ships BOTH button sets — signed-in (.tb-auth--in) and signed-out
   (.tb-auth--out) — and this is the ONLY thing that decides which one paints.
   `data-auth` lands on <html> during head parse (components/auth-init-script.tsx),
   before the first frame, so a signed-in visitor's refresh paints "Dashboard"
   straight away instead of flashing "Sign in" until React hydrates.
   Default with no attribute (JS off, script threw) = signed-out: the safe view,
   and the one the CDN-cached HTML is written for. Do not turn this back into a
   React-state ternary. */
.ts-canon .tb-auth { align-items: center; gap: 10px; }
.ts-canon .tb-auth--in { display: none; }
.ts-canon .tb-auth--out { display: inline-flex; }
html[data-auth='in'] .ts-canon .tb-auth--in { display: inline-flex; }
html[data-auth='in'] .ts-canon .tb-auth--out { display: none; }
/* Mobile sheet: the branch span replaces the buttons as the flex child, so it
   has to carry the flex:1 the buttons used to (see .tb-sheet-actions .btn). */
.ts-canon .tb-sheet-actions .tb-auth { flex: 1; }
html[data-auth='in'] .ts-canon .tb-sheet-actions .tb-auth--in { display: flex; }
.ts-canon .tb-sheet-actions .tb-auth--out { display: flex; }

/* mobile drawer trigger (desktop hidden) */
.ts-canon .tb-mobile-trigger { display: none; }
@media (max-width: 920px) {
  .ts-canon .tb-nav { display: none; }
  .ts-canon .tb-mobile-trigger { display: inline-flex; }
  /* touch (2026-07-14): the hamburger + icon buttons meet a 44px tap target on
     phones (was 38px, below the comfortable thumb minimum). */
  .ts-canon .tb-mobile-trigger { min-width: 44px; min-height: 44px; align-items: center; justify-content: center; }
  .ts-canon .tb-actions .btn-icon { min-width: 44px; min-height: 44px; }
}

/* mobile sheet (open state) — full-height scroll container that sits
   directly below the 57px topbar. It MUST own the scroll (overflow-y:auto
   + overscroll-behavior:contain) so the menu scrolls instead of the page
   bleeding through behind it. Top offset matches the real topbar height
   (was 49px while the bar is 57px — that 8px mismatch read as a top gap). */
.ts-canon .tb-sheet {
  position: fixed; top: 57px; left: 0; right: 0; bottom: 0; z-index: 59;
  /* one sheet with the bar: --bar-surface, never the page ground. */
  background: var(--bar-surface, var(--bg)); border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 6px;
  padding: 18px var(--gut) 40px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
/* NAV ROWS ONLY. Never the buttons in .tb-sheet-actions.
   A bare `.tb-sheet a` (specificity 0,2,1) out-ranks `.ts-canon .btn-pri`
   (0,2,0), so it repainted the sheet's primary pill with the page ink:
   near-black #0E1A14 on the dark forest fill, measured 1.19:1, i.e. the
   label was invisible. That is what "Dashboard" (signed in) and "Start a
   workspace" (signed out) looked like on every phone. It also forced
   15.5px / 12px-8px padding and drew a hairline across the pill.
   `:not(.btn)` keeps the nav rows exactly as they were and hands the
   buttons back to the button system. Locked by
   components/landing/canonical/__tests__/mobile-sheet-buttons.test.ts. */
.ts-canon .tb-sheet a:not(.btn) {
  font-size: 15.5px; color: var(--ink-1); padding: 12px 8px;
  border-bottom: 1px solid var(--line-2);
}
.ts-canon .tb-sheet a:not(.btn):hover { color: var(--accent); }
.ts-canon .tb-sheet-actions { display: flex; gap: 10px; margin-top: 16px; }
/* Full-width rows in the sheet, so a real touch height instead of the 32px
   desktop pill they would otherwise inherit. */
.ts-canon .tb-sheet-actions .btn { flex: 1; justify-content: center; min-height: 46px; font-size: 14.5px; }

/* ═══════════════ BLOCK 1 · HERO ═══════════════
   Hero is a full-page surface per the project's hero-is-a-page rule
   (memory feedback_hero_is_a_page): min-height: calc(100vh - topbar),
   flex-centered. The canonical's smaller clamp paddings were tuned for
   a card-shaped hero — on this site every hero is a full page. */
.ts-canon .hero-sec {
  overflow: hidden;
  min-height: calc(100vh - 49px);
  display: flex;
  align-items: center;
  padding-top: clamp(56px, 7vw, 120px);
  padding-bottom: clamp(64px, 7.5vw, 128px);
  border-bottom: 1px solid var(--line);
  /* depth, not a flat slab — lit subtly from the upper area so the surface
     reads as a premium lit space (light mode: cool, barely-there). */
  background:
    radial-gradient(125% 90% at 72% -8%, #F6F9FD 0%, #EDF2F8 34%, var(--bg) 72%);
}
/* dark — neutral depth, lit toward the field side, deepening down + to the
   edges so the near-black never reads as a dead void. No colored glow. */
[data-theme="dark"] .ts-canon .hero-sec,
html.dark .ts-canon .hero-sec {
  background:
    radial-gradient(120% 95% at 70% -6%, #131A1D 0%, #0B0E10 44%, #06080A 78%);
}
.ts-canon .hero-sec > .wrap { width: 100%; }
@media (max-width: 920px) {
  .ts-canon .hero-sec {
    /* on narrow viewports let content drive height so the chat panel
       isn't squished — still feels page-sized via the upper padding */
    min-height: auto;
    align-items: flex-start;
    padding-top: clamp(40px, 8vh, 72px);
    padding-bottom: clamp(48px, 9vh, 80px);
  }
}
/* the animated engineering grid (grid-field.tsx) is the hero's single living
   background pattern — it replaces the old static grid overlay AND the field's
   dot lattice (one coherent system, no more grid+dots mix). Gently masked on
   the left so the headline stays crisp; present + alive across the rest. */
.ts-canon .hero-gridfield {
  position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0.7) 26%, #000 52%);
  mask-image: linear-gradient(90deg, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0.7) 26%, #000 52%);
}
.ts-canon .hero-sec > .wrap { position: relative; z-index: 1; }

.ts-canon .hero-grid { display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.12fr); gap: clamp(30px, 4vw, 68px); align-items: center; }
/* single-column hero (the moving-tags field was removed 2026-06-23; the living
   grid carries the motion). Copy sits left over the masked grid, constrained so
   it doesn't stretch the full marketing width. */
.ts-canon .hero-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 30px; max-width: 700px; }
.ts-canon .hero-eyebrow { display: inline-flex; align-items: center; gap: 12px; font-family: var(--f-mono); font-size: 12.5px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3); }
.ts-canon .hero-eyebrow .he-tick { width: 26px; height: 2px; background: var(--accent-fill); display: inline-block; }
.ts-canon .hero-lead { font-family: var(--f-display); font-weight: 600; font-size: clamp(44px, 5.1vw, 78px); letter-spacing: -0.034em; line-height: 1.0; color: var(--ink-1); margin: 0; }
.ts-canon .hero-desc { font-size: clamp(17px, 1.35vw, 19.5px); color: var(--ink-2); margin: 0; max-width: 44ch; line-height: 1.62; }
.ts-canon .hero-cta { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 2px; }
.ts-canon .hero-cta .btn-line { background: transparent; border-color: var(--line); color: var(--ink-1); }
.ts-canon .hero-cta .btn-line:hover { background: var(--surface-3); border-color: var(--accent); color: var(--accent-2); }
.ts-canon .hero-cta .btn-line svg { color: var(--ink-4); }
.ts-canon .hero-cta .btn-line:hover svg { color: var(--accent); }
.ts-canon .hero-spec { font-family: var(--f-mono); font-size: 13px; color: var(--ink-3); letter-spacing: 0.01em; margin: 4px 0 0; line-height: 1.7; }
.ts-canon .hero-spec .spec-tok { color: var(--accent); font-weight: 500; }
/* "Reading <file> — opening your workspace…" after a drop/upload */
.ts-canon .hero-fired { font-family: var(--f-mono); font-size: 13px; color: var(--accent-2); letter-spacing: 0.01em; margin: 4px 0 0; line-height: 1.7; }
/* drop affordance — a P&ID dragged over the hero */
.ts-canon .hero-sec.drag-over { outline: 2px dashed var(--accent); outline-offset: -12px; }

/* ─── hero field — living grid + wave-revealed instrument index (hero-field.tsx) ───
   One layer behind the copy. The grid canvas (.hero-gridfield) is full-bleed and
   masked dim on the left so the headline stays crisp; the ordered tag index sits
   on the right (over the alive, unmasked grid) and each tag is revealed by the
   grid's own light wave as its front sweeps past — driven by hero-field.tsx, no
   CSS animation (opacity is set per-frame so the reveal tracks the wave exactly). */
.ts-canon .hero-field { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.ts-canon .hf-tags-wrap { position: absolute; inset: 0; max-width: var(--mkt-w); margin: 0 auto; }
.ts-canon .hf-tags {
  position: absolute; right: var(--gut); top: 50%; transform: translateY(-50%);
  display: grid; grid-template-columns: repeat(3, minmax(0, auto));
  gap: clamp(18px, 2vw, 30px) clamp(44px, 4.4vw, 72px);
  justify-items: start;
}
.ts-canon .hf-tag {
  font-family: var(--f-mono); font-size: clamp(12px, 1.05vw, 14px); font-weight: 600;
  letter-spacing: 0.02em; color: var(--ink-1); white-space: nowrap; will-change: opacity;
}
[data-theme="dark"] .ts-canon .hf-tag,
html.dark .ts-canon .hf-tag { text-shadow: 0 1px 12px rgba(4, 6, 7, 0.6); }
/* the index would crowd the copy below the two-column threshold — hide it there;
   the living grid still carries the hero on its own. */
@media (max-width: 1080px) {
  .ts-canon .hf-tags { display: none; }
}

.ts-canon .hero-stage { display: flex; flex-direction: column; gap: 16px; }
.ts-canon .hero-try { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ts-canon .hero-try .hc-lab { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-4); }
.ts-canon .hero-try .hc-list { display: flex; gap: 9px; flex-wrap: wrap; }
.ts-canon .hero-pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 500; color: var(--ink-2);
  padding: 8px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface);
  cursor: pointer; transition: border-color .15s, color .15s, background .15s;
}
.ts-canon .hero-pill svg { color: var(--ink-4); }
.ts-canon .hero-pill:hover { border-color: var(--accent-line); color: var(--ink-1); }
.ts-canon .hero-pill.on { border-color: var(--accent); color: var(--ink-1); background: var(--accent-soft); }
.ts-canon .hero-pill.on svg { color: var(--accent); }

/* ═══════════════ BLOCK 2 · THE DELIVERABLE (2026-06-28) ═══════════════
   The drawing read into a real I/O list, shown AS the product. Theme-aware
   section (consistent in light + dark) with depth: a mint glow + dot lattice,
   and two product panels carrying the dark app skin so they FLOAT and contrast
   on the page in both modes. The signal-class colours are product semantics,
   not decoration. Synthetic tags + counts only (content-firewall). */
.ts-canon .deliverable-sec {
  --c-ai: #4FA0EE; --c-ao: #3FBE8F; --c-di: #E0A93B; --c-do: #A88BEC;
  --dl-panel: #0E120F;
  --dl-ink-1: #F4F7F4; --dl-ink-2: #C2C9C3; --dl-ink-3: #8A938C; --dl-ink-4: #69716B;
  --dl-line: rgba(236,239,237,0.10); --dl-line-2: rgba(236,239,237,0.06);
  position: relative; overflow: hidden;
  padding-top: clamp(80px, 9vw, 150px);
  padding-bottom: clamp(80px, 9vw, 150px);
  background:
    radial-gradient(78% 52% at 50% -6%, var(--accent-soft) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg-alt) 0%, var(--bg) 45%);
  border-top: 1px solid var(--line-2);
  border-bottom: 1px solid var(--line-2);
}
/* faint engineering dot lattice for depth (both themes) */
.ts-canon .deliverable-sec::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0.7;
  background-image: radial-gradient(rgba(128,140,130,0.16) 1px, transparent 1.5px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(110% 80% at 80% 14%, #000 16%, transparent 68%);
  mask-image: radial-gradient(110% 80% at 80% 14%, #000 16%, transparent 68%);
}
.ts-canon .deliverable-sec > .wrap { position: relative; z-index: 1; }

.ts-canon .dl-head { max-width: 820px; }
.ts-canon .dl-title { font-family: var(--f-display); font-weight: 600; font-size: clamp(32px, 4vw, 56px); letter-spacing: -0.034em; line-height: 1.0; color: var(--ink-1); margin: 0; }
.ts-canon .dl-title em { font-style: italic; font-family: var(--f-serif, 'Source Serif 4', Georgia, serif); letter-spacing: -0.01em; color: var(--accent-2); }
.ts-canon .dl-sub { margin: 18px 0 0; font-size: clamp(15px, 1.2vw, 17px); line-height: 1.62; color: var(--ink-3); max-width: 64ch; }

.ts-canon .dl-stage {
  margin-top: clamp(38px, 4.4vw, 64px);
  display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(16px, 1.8vw, 26px); align-items: stretch;
}

/* shared product panel — dark app skin, floats + lifts in both themes */
.ts-canon .dl-card {
  position: relative; border-radius: 16px; overflow: hidden;
  background: var(--dl-panel); border: 1px solid var(--dl-line);
  box-shadow: 0 44px 84px -40px rgba(0,0,0,0.6), 0 10px 26px -16px rgba(0,0,0,0.45);
}
/* a hair of mint at the top edge — energy + status */
.ts-canon .dl-card::after { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: linear-gradient(90deg, transparent, rgba(78,221,168,0.6), transparent); }

/* ── breakdown card (the energy: big metric + the live signal split) ── */
.ts-canon .dl-metric { display: flex; flex-direction: column; padding: clamp(20px, 2vw, 30px); gap: clamp(18px, 2vw, 24px); }
.ts-canon .dl-points { display: flex; flex-direction: column; gap: 3px; }
.ts-canon .dl-points b { font-family: var(--f-display); font-weight: 700; font-size: clamp(54px, 6.4vw, 90px); line-height: 0.9; letter-spacing: -0.045em; color: var(--dl-ink-1); }
.ts-canon .dl-points span { font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--dl-ink-3); }
.ts-canon .dl-bars { display: flex; flex-direction: column; gap: 12px; }
.ts-canon .dl-barrow { display: grid; grid-template-columns: 38px 1fr 24px; align-items: center; gap: 12px; }
.ts-canon .dl-barlab { display: inline-flex; align-items: center; gap: 7px; font-family: var(--f-mono); font-size: 11.5px; font-weight: 600; color: var(--dl-ink-2); }
.ts-canon .dl-bartrack { height: 8px; border-radius: 5px; background: rgba(236,239,237,0.07); overflow: hidden; }
.ts-canon .dl-barfill { display: block; height: 100%; border-radius: 5px; }
.ts-canon .cdot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
.ts-canon .cdot.c-ai, .ts-canon .dl-barfill.c-ai { background: var(--c-ai); box-shadow: 0 0 12px -2px var(--c-ai); }
.ts-canon .cdot.c-ao, .ts-canon .dl-barfill.c-ao { background: var(--c-ao); box-shadow: 0 0 12px -2px var(--c-ao); }
.ts-canon .cdot.c-di, .ts-canon .dl-barfill.c-di { background: var(--c-di); box-shadow: 0 0 12px -2px var(--c-di); }
.ts-canon .cdot.c-do, .ts-canon .dl-barfill.c-do { background: var(--c-do); box-shadow: 0 0 12px -2px var(--c-do); }
.ts-canon .dl-barn { font-family: var(--f-mono); font-size: 12px; font-weight: 600; color: var(--dl-ink-1); text-align: right; }
.ts-canon .dl-metrow { display: flex; align-items: baseline; gap: 10px; padding-top: 16px; border-top: 1px solid var(--dl-line-2); font-family: var(--f-mono); }
.ts-canon .dl-metk { font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--dl-ink-4); }
.ts-canon .dl-metv { font-size: 12.5px; color: var(--dl-ink-2); display: inline-flex; align-items: center; }
.ts-canon .dl-metsep { width: 3px; height: 3px; border-radius: 50%; background: var(--dl-ink-4); margin: 0 9px; display: inline-block; }
.ts-canon .dl-exports { display: flex; flex-wrap: wrap; gap: 7px; margin-top: auto; padding-top: 4px; }
.ts-canon .dl-fmt { font-family: var(--f-mono); font-size: 10.5px; color: var(--dl-ink-2); border: 1px solid var(--dl-line); border-radius: 5px; padding: 4px 9px; }
.ts-canon .dl-fmt.is-primary { color: #04130C; background: #4EDDA8; border-color: #4EDDA8; font-weight: 700; }

/* ── register card (the proof: dense, classified list) ── */
.ts-canon .iol { display: flex; flex-direction: column; }
.ts-canon .iol-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 15px 18px; border-bottom: 1px solid var(--dl-line); }
.ts-canon .iol-title { font-family: var(--f-mono); font-size: 12px; font-weight: 700; letter-spacing: 0.16em; color: var(--dl-ink-1); }
.ts-canon .iol-state { font-family: var(--f-mono); font-size: 10.5px; color: var(--dl-ink-3); letter-spacing: 0.02em; }
.ts-canon .iol-grid { display: flex; flex-direction: column; flex: 1; }
.ts-canon .iol-row { display: grid; grid-template-columns: 80px 42px 50px minmax(0,1fr) 72px 54px 78px; align-items: center; gap: 10px; padding: 0 18px; height: 41px; border-top: 1px solid var(--dl-line-2); font-size: 12.5px; }
.ts-canon .iol-colh { height: 34px; border-top: 0; font-family: var(--f-mono); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dl-ink-4); }
.ts-canon .iol-row:not(.iol-colh):hover { background: rgba(236,239,237,0.022); }
.ts-canon .iol-tag { font-family: var(--f-mono); font-weight: 600; color: var(--dl-ink-1); }
.ts-canon .iol-type { font-family: var(--f-mono); color: var(--dl-ink-3); font-size: 11.5px; }
.ts-canon .iol-clscell { display: inline-flex; align-items: center; gap: 6px; font-family: var(--f-mono); font-size: 11px; font-weight: 600; color: var(--dl-ink-2); }
.ts-canon .iol-desc { color: var(--dl-ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .iol-sig { font-family: var(--f-mono); font-size: 11px; color: var(--dl-ink-3); }
.ts-canon .iol-sys { font-family: var(--f-mono); font-size: 11px; color: var(--dl-ink-3); letter-spacing: 0.03em; }
.ts-canon .iol-status { justify-self: start; }
.ts-canon .iol-chip { font-family: var(--f-mono); font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase; padding: 3px 8px; border-radius: 4px; border: 1px solid; white-space: nowrap; }
.ts-canon .iol-chip.is-ok { color: #5FD6A6; border-color: rgba(78,221,168,0.26); background: rgba(78,221,168,0.07); }
.ts-canon .iol-chip.is-review { color: #F0B45C; border-color: rgba(240,180,92,0.3); background: rgba(240,180,92,0.09); }
.ts-canon .iol-row.is-flag { background: rgba(240,180,92,0.04); }
.ts-canon .iol-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 18px; border-top: 1px solid var(--dl-line); }
.ts-canon .iol-trace { font-size: 11.5px; color: var(--dl-ink-3); }
.ts-canon .iol-count { font-family: var(--f-mono); font-size: 11px; color: var(--dl-ink-3); }

@media (max-width: 940px) {
  .ts-canon .dl-stage { grid-template-columns: 1fr; gap: clamp(16px, 4vw, 24px); }
  .ts-canon .iol-row { grid-template-columns: 76px 48px minmax(0,1fr) 76px; }
  .ts-canon .iol-type, .ts-canon .iol-sig, .ts-canon .iol-sys,
  .ts-canon .iol-colh > :nth-child(2),
  .ts-canon .iol-colh > :nth-child(5),
  .ts-canon .iol-colh > :nth-child(6) { display: none; }
}

/* ═══════════════ BLOCK · EXPLORE A READ DRAWING (section 2) ═══════════════
   The drawing and its data as one linked, living thing: a real P&ID + a record
   that resolves for whatever instrument is in focus (hover, tab, or the ambient
   tour). Light premium ground, hero-consistent; mint only where it's earned. */
.ts-canon .exp-sec {
  position: relative; overflow: hidden;
  padding-top: var(--pad-default); padding-bottom: var(--pad-default);
  /* deeper, calm cool ground — NO grid (the hero owns the grid; grid-after-grid
     reads as slop). A clear step down from the hero + a crisp top light-edge so
     the section reads as its own surface and the white sheet + card lift off it.
     Deepened 2026-07-07 (chaptered-rhythm pass) so the step down from the hero is
     felt, not near-invisible. */
  background-color: #CFD8E4;
  background-image: radial-gradient(135% 80% at 50% -12%, rgba(12,143,97,0.045) 0%, rgba(12,143,97,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), inset 0 16px 32px -26px rgba(15,22,30,0.30);
}
[data-theme="dark"] .ts-canon .exp-sec, html.dark .ts-canon .exp-sec {
  background-color: #0E1413;
  background-image: radial-gradient(135% 80% at 50% -12%, rgba(31,106,78,0.12) 0%, rgba(31,106,78,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.ts-canon .exp-wrap { max-width: var(--mkt-w); margin: 0 auto; padding-left: var(--gut); padding-right: var(--gut); position: relative; z-index: 1; }
/* stacked header (headline, then lede directly under it, both left-aligned to the
   page) — matches the hero, so the lede is clearly anchored and readable. */
.ts-canon .exp-head { max-width: 720px; margin-bottom: clamp(30px, 4vw, 52px); }
.ts-canon .exp-title {
  margin: 0; font-family: var(--f-display); font-weight: 600;
  font-size: clamp(32px, 3.7vw, 52px); line-height: 1.0; letter-spacing: -0.038em; color: var(--ink-1); text-wrap: balance;
}
.ts-canon .exp-lede { margin: 18px 0 0; max-width: 56ch; font-size: clamp(16px, 1.15vw, 18px); line-height: 1.6; color: var(--ink-2); }

/* the stage: drawing (left) + record (right) */
.ts-canon .exp-stage { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: clamp(18px, 2.4vw, 34px); align-items: center; }

.ts-canon .exp-sheet {
  position: relative; aspect-ratio: 385 / 162; border-radius: 14px; overflow: hidden;
  background: #FBFCFE;
  box-shadow: 0 40px 90px -52px rgba(15,22,30,0.4), 0 8px 22px -16px rgba(15,22,30,0.16), 0 0 0 1px var(--line-2);
}
.ts-canon .exp-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; user-select: none; -webkit-user-drag: none; }
.ts-canon .exp-hot { position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 2; }
.ts-canon .exp-sheet-tag { position: absolute; left: 14px; bottom: 11px; z-index: 3; font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: #9aa39d; pointer-events: none; }
.ts-canon .exp-hotspot { fill: transparent; cursor: pointer; outline: none; transition: fill .15s ease; }
.ts-canon .exp-hotspot:hover { fill: rgba(12,143,97,0.07); }
.ts-canon .exp-hotspot:focus-visible { fill: rgba(12,143,97,0.12); stroke: var(--accent); stroke-width: 1.2; }
/* the active instrument's ring — breathes so the drawing↔record link reads */
.ts-canon .exp-ring { pointer-events: none; }
.ts-canon .exp-ring-core { fill: rgba(12,143,97,0.06); stroke: var(--accent); stroke-width: 1.3; }
.ts-canon .exp-ring-glow { fill: var(--accent); opacity: 0.14; }

/* the record card — clean app surface, resolves for the focused instrument */
.ts-canon .exp-rec {
  display: flex; flex-direction: column; min-height: clamp(296px, 26vw, 356px);
  border: 1px solid var(--line); border-radius: 14px;
  background: linear-gradient(180deg, #F8FBFE 0%, #EEF3F9 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 28px 60px -42px rgba(15,22,30,0.32), 0 8px 20px -16px rgba(15,22,30,0.15);
  padding: clamp(20px, 2vw, 28px);
}
[data-theme="dark"] .ts-canon .exp-rec, html.dark .ts-canon .exp-rec { background: linear-gradient(180deg, #232B30 0%, #1A2024 100%); border-color: rgba(236,239,237,0.20); box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), 0 26px 54px -32px rgba(0,0,0,0.72); }
.ts-canon .exp-rec-top { display: flex; align-items: center; gap: 12px; }
.ts-canon .exp-rec-tag { font-family: var(--f-mono); font-weight: 700; font-size: clamp(22px, 2.2vw, 30px); letter-spacing: -0.01em; color: var(--ink-1); }
.ts-canon .exp-rec-io {
  margin-left: auto; font-family: var(--f-mono); font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em;
  color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent-line);
  border-radius: 6px; padding: 4px 9px; white-space: nowrap;
}
/* not an I/O point (local gauge, mechanical relief) — neutral, not mint */
.ts-canon .exp-rec-io.is-muted { color: var(--ink-3); background: var(--surface-3); border-color: var(--line); }
.ts-canon .exp-rec-note { margin: 7px 0 0; font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.01em; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ts-canon .exp-rec-svc {
  margin: 14px 0 0; min-height: 2.7em; font-size: clamp(16px, 1.4vw, 19px); font-weight: 600; line-height: 1.35; color: var(--ink-1);
  letter-spacing: -0.015em;
}
/* the tag decoded, letter by letter — small mono glyph over its meaning */
.ts-canon .exp-decode { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 2px; }
.ts-canon .exp-glyph {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 7px 10px; border-radius: 7px;
  background: var(--surface-3); border: 1px solid var(--line-2);
}
.ts-canon .exp-glyph-l { font-family: var(--f-mono); font-size: 15px; font-weight: 700; color: var(--ink-1); line-height: 1; }
.ts-canon .exp-glyph-m { font-family: var(--f-sans); font-size: 9.5px; letter-spacing: 0.02em; color: var(--ink-3); white-space: nowrap; }
.ts-canon .exp-rec-fields { margin: clamp(16px, 1.8vw, 22px) 0 0; display: flex; flex-direction: column; }
.ts-canon .exp-rec-row { display: grid; grid-template-columns: 7.6em 1fr; gap: 14px; align-items: baseline; padding: 10px 0; border-top: 1px solid var(--line-2); }
.ts-canon .exp-rec-row:first-child { border-top: 0; }
.ts-canon .exp-rec-row dt { font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-4); }
.ts-canon .exp-rec-row dd { margin: 0; font-size: 14px; color: var(--ink-1); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ts-canon .exp-rec-foot {
  margin-top: auto; padding-top: clamp(16px, 1.8vw, 22px); display: flex; align-items: center; gap: 9px;
  font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--ink-4);
}
/* square status mark (1.5px radius) — instrument-panel precision, not a
   generic round dot; matches the app's .dcard-status .sq. */
.ts-canon .exp-rec-dot { width: 7px; height: 7px; border-radius: 1.5px; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* the tour rail — the instruments on the sheet, current one lit; click to jump */
.ts-canon .exp-track { display: flex; flex-wrap: wrap; gap: 8px; margin-top: clamp(20px, 2.4vw, 30px); }
.ts-canon .exp-pip {
  font-family: var(--f-mono); font-size: 11.5px; font-weight: 600; letter-spacing: 0.02em; color: var(--ink-4);
  background: var(--surface); border: 1px solid var(--line-2); border-radius: 7px; padding: 7px 11px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease, transform .15s ease;
}
.ts-canon .exp-pip:hover { color: var(--ink-1); border-color: var(--line); }
.ts-canon .exp-pip.is-active { color: var(--accent); border-color: var(--accent-line); background: var(--accent-soft); transform: translateY(-1px); }

@media (max-width: 900px) {
  .ts-canon .exp-head { grid-template-columns: 1fr; gap: 14px; align-items: start; margin-bottom: 28px; }
  .ts-canon .exp-lede { margin-bottom: 0; }
  .ts-canon .exp-stage { grid-template-columns: 1fr; gap: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .ts-canon .exp-sheet .hl-glow { animation: none; }
  .ts-canon .exp-rec-svc { animation: none; }
}

/* ═══════════════ BLOCK · STACK — what you get & where it goes ═══════════════
   Sits between Explore (deeper ground) and Intelligence (dark): a clean light
   ground so the deeper→light→dark steps all read. Real vendor marks in their
   brand tints on lifted cells (never bland), export targets, catalog links. */
.ts-canon .stk-sec {
  position: relative; overflow: hidden;
  padding-top: var(--pad-default); padding-bottom: var(--pad-default);
  /* deeper cool ground so the pure-white tiles clearly separate + float
     (card-vs-bg contrast pass 2026-07-08). */
  background-color: #DCE3EE;
  background-image: radial-gradient(130% 80% at 50% -12%, rgba(12,143,97,0.04) 0%, rgba(12,143,97,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), inset 0 14px 30px -26px rgba(15,22,30,0.28);
}
[data-theme="dark"] .ts-canon .stk-sec, html.dark .ts-canon .stk-sec {
  background-color: #0C100F;
  background-image: radial-gradient(130% 80% at 50% -12%, rgba(31,106,78,0.10) 0%, rgba(31,106,78,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.ts-canon .stk-wrap { max-width: var(--mkt-w); margin: 0 auto; padding-left: var(--gut); padding-right: var(--gut); }
.ts-canon .stk-head { max-width: 720px; margin-bottom: clamp(34px, 4vw, 56px); }
.ts-canon .stk-title {
  margin: 0; font-family: var(--f-display); font-weight: 600;
  font-size: clamp(32px, 3.7vw, 52px); line-height: 1.0; letter-spacing: -0.038em; color: var(--ink-1); text-wrap: balance;
}
.ts-canon .stk-lede { margin: 18px 0 0; max-width: 58ch; font-size: clamp(16px, 1.15vw, 18px); line-height: 1.6; color: var(--ink-2); }

/* two groups: reads-from CAD · exports-to control systems */
.ts-canon .stk-grid { display: grid; grid-template-columns: 1fr auto 1fr; gap: clamp(24px, 3vw, 48px); align-items: start; }
.ts-canon .stk-grp { display: flex; flex-direction: column; }
/* directional flow mark: drawings come in from CAD (left) → the register goes
   out to the control systems (right). Sits centred between the two groups. */
.ts-canon .stk-flow { align-self: center; display: flex; align-items: center; justify-content: center; color: var(--ink-4); padding-top: 26px; }
.ts-canon .stk-flow svg { width: 22px; height: 22px; }
.ts-canon .stk-flow svg path { stroke: var(--accent); }
.ts-canon .stk-k {
  font-family: var(--f-mono); font-size: 12px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: clamp(16px, 2vw, 22px);
}
.ts-canon .stk-logos { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.ts-canon .stk-logo-cell {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 13px;
  min-height: 104px; padding: 22px; border-radius: var(--r-md);
  background: linear-gradient(180deg, #FFFFFF 0%, #F3F7FC 100%);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), var(--shadow-2);
  color: var(--intg-tint, var(--ink-2));
  transition: border-color .16s ease, box-shadow .2s ease, transform .2s ease;
}
.ts-canon .stk-logo-cell:hover { border-color: var(--line-strong); box-shadow: var(--shadow-3); transform: translateY(-3px); }
[data-theme="dark"] .ts-canon .stk-logo-cell, html.dark .ts-canon .stk-logo-cell {
  background: linear-gradient(180deg, #232B30 0%, #1A2024 100%); color: var(--intg-tint-dark, var(--intg-tint, var(--ink-1)));
  border-color: rgba(236,239,237,0.22);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), 0 18px 40px -26px rgba(0,0,0,0.7);
}
.ts-canon .stk-logo { display: inline-flex; align-items: center; height: 32px; }
.ts-canon .stk-logo > svg { display: block; max-height: 32px; width: auto; max-width: 158px; }
.ts-canon .stk-logo-name { font-size: 14.5px; font-weight: 500; letter-spacing: -0.006em; color: var(--ink-1); }

/* the deliverable's export targets */
.ts-canon .stk-out { margin-top: clamp(40px, 5vw, 72px); border-top: 1px solid var(--line); padding-top: clamp(28px, 3vw, 42px); }
.ts-canon .stk-fmts { display: flex; flex-wrap: wrap; gap: 9px; margin-top: clamp(14px, 1.6vw, 20px); }
.ts-canon .stk-fmt {
  font-family: var(--f-mono); font-size: 13px; font-weight: 500; color: var(--ink-1);
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: 8px; padding: 9px 15px;
  transition: border-color .14s, color .14s;
}
.ts-canon .stk-fmt:hover { border-color: var(--accent-line); color: var(--ink-1); }

/* catalog links — clean, confident, not the old arrow-chip clutter */
.ts-canon .stk-links { margin-top: clamp(30px, 3.4vw, 46px); display: flex; flex-wrap: wrap; gap: clamp(20px, 3vw, 40px); }
.ts-canon .stk-link {
  display: inline-flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 500;
  color: var(--ink-1); text-decoration: none; transition: color .15s ease;
}
.ts-canon .stk-link svg { color: var(--ink-4); transition: color .15s ease, transform .15s ease; }
.ts-canon .stk-link:hover { color: var(--accent-2); }
.ts-canon .stk-link:hover svg { color: var(--accent); transform: translateX(3px); }

@media (max-width: 860px) {
  .ts-canon .stk-grid { grid-template-columns: 1fr; gap: clamp(28px, 7vw, 40px); }
  .ts-canon .stk-flow { display: none; }
  .ts-canon .stk-links { gap: 16px; }
}

/* ═══════════════ BLOCK · LIVE READ (section 2) ═══════════════
   A real P&ID on a dark drafting stage; a luminous reading head crosses it and
   recognises + classifies each device as it passes. One rAF clock (block-read.tsx)
   drives the head, the reveals, and the readout. Cinematic, restrained, industrial. */
.ts-canon .read-sec {
  position: relative; overflow: hidden;
  padding: clamp(84px, 11vh, 156px) 0;
  background-color: #0A0C0E;
  background-image:
    radial-gradient(120% 80% at 50% -12%, rgba(31,106,78,0.12) 0%, rgba(31,106,78,0) 56%),
    linear-gradient(rgba(255,255,255,0.026) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.026) 1px, transparent 1px);
  background-size: 100% 100%, 46px 46px, 46px 46px;
  background-position: center top, center, center;
  color: #F5F7F9;
  --r-accent: #3FD9A2;
}
.ts-canon .read-wrap { max-width: var(--mkt-w); margin: 0 auto; padding-left: var(--gut); padding-right: var(--gut); }
.ts-canon .read-copy { max-width: 720px; margin-bottom: clamp(34px, 4vw, 56px); }
.ts-canon .read-title {
  margin: 0; font-family: var(--f-display); font-weight: 600;
  font-size: clamp(28px, 3.4vw, 46px); line-height: 1.1; letter-spacing: -0.025em;
  color: #F5F7F9; text-wrap: balance;
}
.ts-canon .read-sub { margin: 16px 0 0; max-width: 58ch; font-size: clamp(14.5px, 1.05vw, 16.5px); line-height: 1.6; color: #9AA0A9; }

/* the stage: the drawing sheet (main) + a live readout rail */
.ts-canon .read-stage { display: grid; grid-template-columns: minmax(0, 1fr) 272px; gap: clamp(20px, 3vw, 44px); align-items: stretch; }
.ts-canon .read-sheet {
  position: relative; aspect-ratio: 340 / 230; border-radius: 12px; overflow: hidden;
  background: #FBFCFE;
  box-shadow: 0 60px 120px -50px rgba(0,0,0,0.72), 0 12px 34px -20px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.07);
}
.ts-canon .read-sheet > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ts-canon .read-overlay { z-index: 2; pointer-events: none; }

/* recognition: a soft halo, a crisp ring, a one-shot ping, a classification chip */
.ts-canon .rec-glow { fill: var(--r-accent); opacity: 0.18; }
.ts-canon .rec-ring { fill: rgba(63,217,162,0.10); stroke: var(--r-accent); stroke-width: 1.4; }
.ts-canon .rec-ping { fill: none; stroke: var(--r-accent); stroke-width: 1.2; opacity: 0; transform-box: fill-box; transform-origin: center; }
.ts-canon .rec.is-on .rec-ping { animation: rec-ping 0.72s cubic-bezier(0.16,1,0.3,1); }
@keyframes rec-ping { 0% { opacity: 0.65; transform: scale(1); } 100% { opacity: 0; transform: scale(2.2); } }
.ts-canon .rec-chip-bg { fill: #0C140F; stroke: var(--r-accent); stroke-width: 0.5; opacity: 0.94; }
.ts-canon .rec-chip-tx { fill: var(--r-accent); font-family: var(--f-mono); font-size: 7px; font-weight: 700; letter-spacing: 0.04em; text-anchor: middle; }

/* the reading head: a trailing band + a bright leading edge */
.ts-canon .read-edge { fill: var(--r-accent); opacity: 0.4; }
.ts-canon .read-edge-core { fill: var(--r-accent); }

/* live readout rail */
.ts-canon .read-hud {
  align-self: end; display: flex; flex-direction: column; gap: 16px;
  padding: 22px; border: 1px solid rgba(255,255,255,0.09); border-radius: 12px;
  background: rgba(255,255,255,0.022);
}
.ts-canon .read-hud-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ts-canon .read-hud-k { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.1em; color: #757B84; }
.ts-canon .read-hud-status { font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--r-accent); }
.ts-canon .read-hud-count { display: flex; align-items: baseline; gap: 9px; }
.ts-canon .read-hud-n { font-family: var(--f-mono); font-size: 44px; font-weight: 700; line-height: 1; color: #F5F7F9; font-variant-numeric: tabular-nums; }
.ts-canon .read-hud-of { font-size: 12px; line-height: 1.35; color: #9AA0A9; max-width: 14ch; }
.ts-canon .read-hud-classes { display: flex; flex-wrap: wrap; gap: 7px; }
.ts-canon .read-hud-class {
  font-family: var(--f-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.05em;
  padding: 4px 9px; border-radius: 5px; border: 1px solid rgba(255,255,255,0.12); color: #757B84;
  transition: color .25s ease, border-color .25s ease, background .25s ease;
}
.ts-canon .read-hud-class[data-on="true"] { color: var(--r-accent); border-color: rgba(63,217,162,0.5); background: rgba(63,217,162,0.10); }
.ts-canon .read-hud-foot { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 0.04em; color: #757B84; border-top: 1px solid rgba(255,255,255,0.08); padding-top: 14px; }

@media (max-width: 900px) {
  .ts-canon .read-stage { grid-template-columns: 1fr; gap: 18px; }
  .ts-canon .read-hud { align-self: stretch; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 14px 22px; }
  .ts-canon .read-hud-foot { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .ts-canon .rec.is-on .rec-ping { animation: none; }
}

/* ═══════════════ BLOCK · INTELLIGENCE (2026-06-28) ═══════════════
   A full-viewport tease of the REAL Intelligence screen, matched to its actual
   app code: THEME-AWARE (light = a soft white luminance core over the dot grid;
   dark = a forest glow from the top over white dots), the real --surface tiles,
   the datum mark, and the ask bar. Flows out of the hero's grid (same ground, no
   hard cut). Clicking an ask reveals a clearly-labeled SAMPLE answer cited to
   sheets — a tease, never a dead control. Synthetic data only (firewall). */
/* the SECTION stays on the page's light ground (flows out of the hero, left-
   aligned spine). The Intelligence screen lives in a wide WINDOW that lifts off
   it — centred content inside, the page left-aligned around it. */
.ts-canon .intel-sec {
  position: relative; overflow: hidden;
  display: flex; align-items: center;
  padding: clamp(92px, 12vh, 168px) 0;
  /* EXACT real-app Intelligence-screen tokens (app-v2-tokens.css, dark):
     NEUTRAL near-black charcoal, NO green cast anywhere. Cards lift off it.
     Green is ONLY a small accent (the datum tail, the "?" dot, the send key). */
  --bg: #0B0C0E; --bg-alt: #0F1113; --surface: #16181C; --surface-2: #1D2025; --surface-3: #262A30;
  --ink-1: #F5F7F9; --ink-2: #CCD1D8; --ink-3: #9AA0A9; --ink-4: #757B84;
  --mark-ink: #F5F8F5;   /* the MARK's reversed ink, never --ink-1 */
  --line: rgba(255,255,255,0.11); --line-2: rgba(255,255,255,0.065); --line-3: rgba(255,255,255,0.035); --line-strong: rgba(255,255,255,0.24);
  --accent: #3FD9A2; --accent-2: #5FE3B5; --accent-line: rgba(63,217,162,0.50); --accent-soft: rgba(63,217,162,0.14); --accent-glow: rgba(63,217,162,0.30);
  /* re-darken the elevation stack for this light-mode dark island — without
     this override the light --shadow-1 top light-catch (inset white) bleeds
     onto the near-black .intel-cell / .intel-bar / .intel-a. */
  --shadow-1: 0 1px 2px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.05);
  --shadow-2: 0 16px 36px -16px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.06);
  --shadow-3: 0 34px 78px -28px rgba(0,0,0,0.9), 0 8px 22px -8px rgba(0,0,0,0.7);
  color: var(--ink-1);
  /* the section IS the app screen — verbatim from the real .intel-screen (dark):
     #0B0C0E ground + ONE restrained forest glow from top-centre (rgba(31,106,78)
     = --accent-fill, the single allowed accent) + the same faint dot grid.
     Content floats directly on it; there is no separate grey box. */
  background-color: #0B0C0E;
  background-image:
    radial-gradient(95% 70% at 50% 0%, rgba(31,106,78,0.20) 0%, rgba(31,106,78,0.07) 30%, rgba(31,106,78,0) 58%),
    radial-gradient(rgba(255,255,255,0.05) 1.1px, transparent 1.4px);
  background-size: 100% 100%, 20px 20px;
  background-position: center top, 10px 10px;
  background-repeat: no-repeat, repeat;
}
.ts-canon .intel-wrap { position: relative; z-index: 1; width: 100%; display: flex; flex-direction: column; align-items: stretch; text-align: left; gap: clamp(26px, 3.4vw, 44px); }

/* left header — the marketing message, consistent with the hero */
.ts-canon .intel-lead { max-width: 760px; }

/* the app-preview window — wide, fills the width, the app's own surface tokens
   so it reads as the real screen; a border + shadow lift it off the page. */
.ts-canon .intel-window {
  /* NOT a separate surface — just the centring container for the screen content
     (mark · prompt · grid · composer) floating on the section's screen ground.
     No own background, border, or shadow: that two-surface split (grey box on a
     green field) was the exact bug. The cards (#16181C) provide the only lift. */
  position: relative; z-index: 1;
  width: 100%; max-width: 940px; margin: 0 auto;
  padding: clamp(8px, 1.5vh, 20px) 0;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: clamp(20px, 2.6vw, 30px);
}
.ts-canon .intel-mark { display: block; }
.ts-canon .intel-prompt { margin: 0; font-family: var(--f-display); font-weight: 600; font-size: clamp(19px, 2vw, 26px); letter-spacing: -0.02em; color: var(--ink-1); }
.ts-canon .intel-prompt .dot { color: var(--accent); }
.ts-canon .intel-head { font-family: var(--f-display); font-weight: 600; font-size: clamp(29px, 3.6vw, 50px); letter-spacing: -0.03em; line-height: 1.05; color: var(--ink-1); margin: 0; }
.ts-canon .intel-head em { font-style: italic; font-family: var(--f-serif, 'Source Serif 4', Georgia, serif); color: var(--ink-1); letter-spacing: -0.005em; }
.ts-canon .intel-head .intel-q-mark { color: var(--accent); }
.ts-canon .intel-sub { margin: 10px 0 0; max-width: 58ch; font-size: clamp(14.5px, 1.1vw, 16px); line-height: 1.55; color: var(--ink-3); }

/* 3x3 grid + tiles — the real .intel-screen__empty look, theme-aware */
.ts-canon .intel-grid { margin-top: clamp(4px, 0.8vw, 12px); width: 100%; max-width: 1000px; display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 12px; }
.ts-canon .intel-cell {
  min-height: 78px; display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 0 18px; border-radius: 12px;
  background: linear-gradient(180deg, #21262C 0%, #171B20 100%); border: 1px solid rgba(255,255,255,0.13); box-shadow: var(--shadow-1);
  color: var(--ink-2); text-decoration: none; cursor: pointer;
  transition: border-color .22s ease, box-shadow .28s ease, transform .3s cubic-bezier(.2,.8,.2,1);
}
.ts-canon .intel-cell:hover { border-color: var(--line); box-shadow: var(--shadow-2); transform: translateY(-3px); }
.ts-canon .intel-cell:active { transform: translateY(0); }
.ts-canon .intel-ico { flex: none; display: grid; place-items: center; color: var(--ink-3); }
.ts-canon .intel-ico svg { width: 18px; height: 18px; }
.ts-canon .intel-q { flex: 1; min-width: 0; font-size: 14px; font-weight: 500; line-height: 1.3; color: var(--ink-1); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ts-canon .intel-cell.is-action .intel-q { font-weight: 600; color: var(--ink-1); }
.ts-canon .intel-cell:not(.is-action) .intel-ico { display: none; }

/* ask bar — the real composer, theme-aware, mint send */
.ts-canon .intel-bar {
  margin-top: clamp(14px, 1.8vw, 22px); width: 100%; max-width: 680px;
  display: flex; align-items: center; gap: 12px; padding: 11px 11px 11px 18px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow-1);
  text-decoration: none; transition: border-color .16s, box-shadow .16s;
}
.ts-canon .intel-bar:hover { border-color: var(--accent-line); box-shadow: var(--shadow-1), 0 0 0 3px var(--accent-glow); }
.ts-canon .intel-clip { color: var(--ink-4); display: inline-flex; flex: none; }
.ts-canon .intel-bar-text { flex: 1; text-align: left; font-size: 14px; color: var(--ink-4); }
.ts-canon .intel-send { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; flex: none; border-radius: 9px; background: var(--accent); color: #04130C; }

@media (max-width: 860px) { .ts-canon .intel-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .ts-canon .intel-grid { grid-template-columns: 1fr; } .ts-canon .intel-cell { min-height: 0; padding: 16px 18px; } }

/* the answer view — clicking an ask reveals a SAMPLE answer, cited to sheets */
.ts-canon .intel-answer { width: 100%; max-width: 680px; display: flex; flex-direction: column; align-items: stretch; gap: 16px; text-align: left; animation: ts-canon-settle 240ms cubic-bezier(0.16,1,0.3,1) both; }
@keyframes ts-canon-settle { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ts-canon .intel-answer { animation: none; } }
.ts-canon .intel-back { align-self: center; display: inline-flex; align-items: center; gap: 6px; background: none; border: 0; cursor: pointer; font-family: var(--f-mono); font-size: 11.5px; letter-spacing: 0.04em; color: var(--ink-4); padding: 4px; transition: color .15s; }
.ts-canon .intel-back:hover { color: var(--ink-1); }
.ts-canon .intel-qline { margin: 0; align-self: center; text-align: center; font-family: var(--f-display); font-weight: 600; font-size: clamp(21px, 2.5vw, 31px); letter-spacing: -0.022em; line-height: 1.12; color: var(--ink-1); max-width: 26ch; }
.ts-canon .intel-a { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow-1); overflow: hidden; }
.ts-canon .intel-a-sum { margin: 0; padding: 16px 18px 14px; font-size: 15px; line-height: 1.5; color: var(--ink-1); border-bottom: 1px solid var(--line-2); }
.ts-canon .intel-a-rows { display: flex; flex-direction: column; }
.ts-canon .intel-a-row { display: grid; grid-template-columns: 96px minmax(0,1fr) auto; align-items: center; gap: 12px; padding: 11px 18px; border-top: 1px solid var(--line-3); }
.ts-canon .intel-a-row:first-child { border-top: 0; }
.ts-canon .intel-a-tag { font-family: var(--f-mono); font-weight: 600; font-size: 12.5px; color: var(--ink-1); }
.ts-canon .intel-a-note { font-size: 13px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .intel-a-src { font-family: var(--f-mono); font-size: 11px; color: var(--ink-4); white-space: nowrap; }
.ts-canon .intel-a-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 18px; border-top: 1px solid var(--line-2); background: var(--surface-2); }
.ts-canon .intel-a-cite { font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); }
.ts-canon .intel-a-sample { font-family: var(--f-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-4); border: 1px solid var(--line-2); border-radius: 4px; padding: 2px 7px; }
.ts-canon .intel-cta { align-self: center; margin-top: 4px; }

/* the I/O-list (cross-reference) card carries the mint accent on its icon */
.ts-canon .intel-cell[data-io] .intel-ico { color: var(--accent); }

/* ─── canonical hero-window chrome (matches lc-hero.jsx exactly) ─── */
.ts-canon .hero-window {
  position: relative; border-radius: 14px; overflow: hidden;
  border: 1px solid var(--line); background: #0E1712;
  box-shadow:
    0 50px 110px -50px rgba(0,0,0,0.78),
    0 12px 34px -16px rgba(0,0,0,0.55),
    0 0 0 1px rgba(236,239,237,0.05);
}
.ts-canon .hw-bar {
  display: flex; align-items: center; gap: 12px; height: 42px; padding: 0 18px 0 22px;
  background: #15211C; border-bottom: 1px solid rgba(236,239,237,0.08);
}
.ts-canon .hw-brand { display: inline-flex; align-items: center; gap: 9px; flex: none; }
.ts-canon .hw-word { font-size: 14px; font-weight: 600; letter-spacing: -0.02em; color: #ECF2EE; }
.ts-canon .hw-live {
  display: inline-flex; align-items: center; gap: 7px; flex: none; margin-left: auto;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent-fill);
}
.ts-canon .hw-pulse { width: 6px; height: 6px; border-radius: 50%; background: var(--accent-fill); box-shadow: 0 0 0 0 rgba(91,227,175,0.5); animation: ts-canon-pulse 2.4s infinite; }
.ts-canon .hw-stage {
  /* taller stage so the static workspace (P&ID + chat + composer) reads
     as a real workspace, not a cramped card. */
  position: relative;
  height: clamp(560px, 72vh, 820px);
  background: #0E1712;
  overflow: hidden;
}

/* when the static workspace fills the stage, drop the inner panel
   chrome so it reads as ONE dark working surface, and proportion the
   children so the drawing has room to breathe. */
.ts-canon .hw-stage > .intel {
  position: absolute; inset: 0;
  border: 0; border-radius: 0;
  box-shadow: none;
  background: transparent;
  display: flex; flex-direction: column;
}
.ts-canon .hw-stage > .intel .intel-pid { margin: 16px 16px 10px; flex: 0 0 auto; }
.ts-canon .hw-stage > .intel .cp-thread { flex: 1 1 auto; max-height: none; min-height: 0; padding: 6px 16px 8px; }
.ts-canon .hw-stage > .intel .cp-composer { padding: 12px 16px 16px; }

@media (max-width: 720px) {
  .ts-canon .hw-stage { height: clamp(540px, 85vh, 760px); }
  .ts-canon .hero-cta .btn-lg { justify-content: center; }
  /* phone-tuned chrome: tighter bar, smaller wordmark, tighter inner pads */
  .ts-canon .hw-bar { padding: 0 14px 0 16px; height: 40px; }
  .ts-canon .hw-word { font-size: 13px; }
  .ts-canon .hw-live { font-size: 9.5px; letter-spacing: 0.14em; gap: 6px; }
  .ts-canon .hw-stage > .intel .intel-pid { margin: 12px 12px 8px; }
  .ts-canon .hw-stage > .intel .cp-thread { padding: 6px 12px 8px; gap: 11px; }
  .ts-canon .hw-stage > .intel .cp-composer { padding: 10px 12px 12px; }
  /* P&ID inset header reads at phone size without truncating */
  .ts-canon .intel-pid-bar { padding: 7px 10px; font-size: 10px; gap: 7px; }
  .ts-canon .intel .cp-bubble-user,
  .ts-canon .intel .cp-say { font-size: 12.5px; }
  .ts-canon .intel .cp-line { gap: 8px; padding: 6px 10px; }
  /* reference tables (Exports + Pricing): tighter cells so 4 columns fit
     without horizontally clipping at phone widths */
  .ts-canon .xtable th, .ts-canon .xtable td,
  .ts-canon .ptable th, .ts-canon .ptable td { padding: 12px 9px; }
  .ts-canon .xtable th, .ts-canon .ptable th { font-size: 10.5px; letter-spacing: 0.08em; }
  .ts-canon .xtable td { font-size: 13.5px; }
  .ts-canon .ptable td.tier { font-size: 14.5px; }
  .ts-canon .ptable td.price { font-size: 14px; }
  .ts-canon .ptable td.col { font-size: 13px; }
  /* drawing-types reference list rhythm on phones */
  .ts-canon .ref-item .ref-name { font-size: 15.5px; }
  .ts-canon .ref-item .ref-desc { font-size: 13.5px; }
}

/* ─── hero stage : intelligence panel (graphite in both themes) ─── */
.ts-canon .intel {
  --p-bg: #0F1814; --p-surface: #18241F; --p-input: #131E19;
  --p-line: rgba(236,239,237,0.11); --p-line-2: rgba(236,239,237,0.06);
  --p-ink: #E7ECE9; --p-ink-2: #A9B2AD; --p-ink-3: #79827D; --p-mint: #5BE3AF;
  background: var(--p-bg); border: 1px solid var(--p-line);
  border-radius: var(--r-lg);
  box-shadow:
    0 50px 110px -50px rgba(0,0,0,0.78),
    0 12px 34px -16px rgba(0,0,0,0.55),
    0 0 0 1px rgba(236,239,237,0.05);
  display: flex; flex-direction: column; overflow: hidden;
}
.ts-canon .intel-head { display: flex; align-items: center; gap: 11px; padding: 13px 16px; border-bottom: 1px solid var(--p-line-2); }
.ts-canon .intel-head .ttl { font-size: 12.5px; font-weight: 600; color: var(--p-ink); letter-spacing: -0.01em; }
.ts-canon .intel-head .live { margin-left: auto; font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--p-mint); display: inline-flex; align-items: center; gap: 7px; }
.ts-canon .intel-head .live .pulse { width: 6px; height: 6px; border-radius: 50%; background: var(--p-mint); box-shadow: 0 0 0 0 rgba(91,227,175,0.5); animation: ts-canon-pulse 2.4s infinite; }
@keyframes ts-canon-pulse { 0% { box-shadow: 0 0 0 0 rgba(91,227,175,0.5); } 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }

/* white drawing inset */
.ts-canon .intel-pid { margin: 14px; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--p-line); background: #fff; }
.ts-canon .intel-pid-bar { display: flex; align-items: center; gap: 9px; padding: 8px 12px; border-bottom: 1px solid rgba(14,26,20,0.08); background: #F6F8F5; font-family: var(--f-mono); font-size: 10.5px; color: #5E6760; letter-spacing: 0.02em; }
.ts-canon .intel-pid-bar .id { color: #364039; font-weight: 600; }
.ts-canon .intel-pid-bar .sp { flex: 1; }
.ts-canon .intel-pid-bar .ct { color: #0A7B53; }
.ts-canon .intel-pid-holder { position: relative; aspect-ratio: 16 / 9.7; background: #fff; }
.ts-canon .intel-pid-holder svg { position: absolute; inset: 0; width: 100%; height: 100%; }

/* chat thread on dark intel */
.ts-canon .intel .cp-thread { padding: 4px 16px 6px; display: flex; flex-direction: column; gap: 14px; min-height: 104px; max-height: 184px; overflow-y: auto; overflow-x: hidden; }
.ts-canon .intel .cp-row { display: flex; }
.ts-canon .intel .cp-row.user { justify-content: flex-end; }
.ts-canon .intel .cp-bubble-user { background: var(--p-surface); color: var(--p-ink); border: 1px solid var(--p-line); padding: 9px 13px; border-radius: 13px 13px 4px 13px; max-width: 84%; font-size: 13px; line-height: 1.45; }
.ts-canon .intel .cp-assist { display: flex; gap: 11px; max-width: 94%; min-width: 0; }
.ts-canon .intel .cp-mk { flex: none; width: 26px; height: 26px; border-radius: 7px; background: var(--p-surface); border: 1px solid var(--p-line); display: grid; place-items: center; }
.ts-canon .intel .cp-assist-body { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ts-canon .intel .cp-say { color: var(--p-ink); font-size: 13px; line-height: 1.5; }
.ts-canon .intel .cp-say .tag, .ts-canon .intel .cp-line .tag { color: var(--p-mint); font-weight: 600; }

.ts-canon .intel .cp-result { border: 1px solid var(--p-line); border-radius: var(--r-md); overflow: hidden; background: var(--p-input); min-width: 0; }
.ts-canon .intel .cp-result-h { display: flex; align-items: center; gap: 8px; padding: 7px 11px; border-bottom: 1px solid var(--p-line-2); font-family: var(--f-mono); font-size: 10.5px; color: var(--p-ink-3); }
.ts-canon .intel .cp-result-h .nm { color: var(--p-ink-2); font-weight: 600; }
.ts-canon .intel .cp-result-h .ms { margin-left: auto; color: var(--p-ink-3); }
.ts-canon .intel .cp-rows { display: flex; flex-direction: column; }
.ts-canon .intel .cp-line { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px; padding: 7px 11px; font-size: 12px; border-top: 1px solid var(--p-line-2); }
.ts-canon .intel .cp-line:first-child { border-top: 0; }
.ts-canon .intel .cp-line .tag { font-family: var(--f-mono); font-weight: 600; font-size: 11.5px; }
.ts-canon .intel .cp-line .meta { color: var(--p-ink-3); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .intel .cp-line .st { display: inline-flex; align-items: center; gap: 6px; font-family: var(--f-mono); font-size: 10.5px; }
.ts-canon .intel .cp-line .st.flag { color: var(--flag); }
.ts-canon .intel .cp-line .st.ok { color: var(--p-ink-2); }
.ts-canon .intel .cp-result-foot { display: flex; align-items: center; gap: 8px; padding: 7px 11px; border-top: 1px solid var(--p-line-2); font-family: var(--f-mono); font-size: 10.5px; color: var(--p-ink-3); }
.ts-canon .intel .cp-result-foot a { color: var(--p-mint); cursor: pointer; margin-left: auto; }
.ts-canon .intel .cp-cite { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font-family: var(--f-mono); font-size: 10.5px; color: var(--p-mint); border: 1px solid rgba(91,227,175,0.34); background: rgba(91,227,175,0.08); border-radius: 5px; padding: 3px 8px; align-self: flex-start; }
.ts-canon .intel .cp-cite .sq { width: 9px; height: 9px; border: 1.5px solid var(--p-mint); border-radius: 2px; }

.ts-canon .intel .cp-composer { padding: 12px 14px 14px; border-top: 1px solid var(--p-line-2); }
.ts-canon .intel .cp-input-wrap { display: flex; align-items: flex-end; gap: 9px; border: 1px solid var(--p-line); border-radius: var(--r-md); background: var(--p-input); padding: 8px 8px 8px 13px; transition: border-color 140ms; }
.ts-canon .intel .cp-input-wrap:focus-within { border-color: rgba(91,227,175,0.4); }
.ts-canon .intel .cp-input { flex: 1; border: 0; background: none; resize: none; outline: none; font-size: 13.5px; line-height: 1.45; min-height: 22px; max-height: 80px; padding: 2px 0; color: var(--p-ink); font-family: inherit; }
.ts-canon .intel .cp-input::placeholder { color: var(--p-ink-3); }
.ts-canon .intel .cp-send { flex: none; width: 32px; height: 32px; border-radius: var(--r-sm); background: var(--p-mint); color: #06231A; display: grid; place-items: center; }
.ts-canon .intel .cp-send:disabled { background: var(--p-surface); color: var(--p-ink-3); cursor: default; }
.ts-canon .intel .cp-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.ts-canon .intel .cp-chip { font-size: 12px; color: var(--p-ink-2); border: 1px solid var(--p-line); background: var(--p-surface); border-radius: 999px; padding: 6px 12px; display: inline-flex; align-items: center; gap: 6px; transition: border-color 140ms, color 140ms; }
.ts-canon .intel .cp-chip:hover { border-color: rgba(91,227,175,0.4); color: var(--p-mint); }
.ts-canon .intel .cp-chip svg { color: var(--p-ink-3); }

/* ═══════════════ BLOCK 2 · DROP ZONE ═══════════════
   The whole panel IS the drop surface — no nested dashed cloud-uploader box
   (that box-in-a-box with a circle icon was the generic-SaaS tell). A plotted
   dot lattice ties it to the hero field; mint lights the full panel on drag. */
.ts-canon .drop {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr); gap: clamp(28px, 3.4vw, 60px);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--shadow-2);
  padding: clamp(28px, 3vw, 52px); align-items: center;
  overflow: hidden; cursor: pointer;
  transition: border-color 160ms, box-shadow 160ms, background 160ms;
}
/* dark — inset top-highlight + deep shadow so the card lifts cleanly off the
   base instead of melting into it (premium-craft pass). */
[data-theme="dark"] .ts-canon .drop,
html.dark .ts-canon .drop {
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), var(--shadow-2);
}
.ts-canon .drop::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(var(--line-strong) 1px, transparent 1.1px);
  background-size: 26px 26px; background-position: 0 0;
  opacity: 0.2;
  -webkit-mask-image: radial-gradient(130% 140% at 3% 50%, #000 0%, transparent 64%);
  mask-image: radial-gradient(130% 140% at 3% 50%, #000 0%, transparent 64%);
  transition: opacity 160ms;
}
.ts-canon .drop > * { position: relative; z-index: 1; }
.ts-canon .drop:hover { border-color: var(--accent-line); }
.ts-canon .drop.over { border-color: var(--accent); background: var(--accent-soft); box-shadow: var(--shadow-3); }
.ts-canon .drop.over::before { opacity: 0.5; }
/* left — the one action */
.ts-canon .drop-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.ts-canon .drop-h { font-family: var(--f-display); font-weight: 600; font-size: clamp(23px, 2.3vw, 31px); letter-spacing: -0.028em; line-height: 1.04; color: var(--ink-1); margin: 0; }
.ts-canon .drop-line { font-size: clamp(14.5px, 1.05vw, 16px); color: var(--ink-2); line-height: 1.55; margin: 0; max-width: 42ch; }
.ts-canon .drop-spec { font-family: var(--f-mono); font-size: 12.5px; color: var(--ink-3); letter-spacing: 0.05em; margin: 2px 0 0; }
.ts-canon .drop-cta { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin-top: 8px; }
.ts-canon .drop-cta .btn { cursor: pointer; }
.ts-canon .drop-or { font-size: 13px; color: var(--ink-4); }

/* right — the proof: the I/O list a drawing becomes (reuses .cp-result) */
.ts-canon .drop-proof { width: 100%; align-self: center; box-shadow: var(--shadow-2); }

.ts-canon .drop.fired { border-color: var(--accent); background: var(--accent-soft); }
.ts-canon .drop-fire { grid-column: 1 / -1; display: flex; align-items: center; justify-content: center; gap: 16px; }

/* Band variant (beem-z03): single-column "read your own drawing" strip for
   SEO spoke pages whose hero already proves the deliverable — no right-hand
   proof card, so the page never shows the same I/O-list card twice. */
.ts-canon .drop.band { grid-template-columns: 1fr; }

@media (max-width: 560px) {
  .ts-canon .drop-cta { align-items: stretch; width: 100%; }
  .ts-canon .drop-cta .btn { width: 100%; justify-content: center; }
}

/* ═══════════════ BLOCK 3 · ASK list ═══════════════ */
.ts-canon .ask-list { margin-top: clamp(26px, 3vw, 40px); }
.ts-canon .ask-row { border-top: 1px solid var(--line); position: relative; }
.ts-canon .ask-row:last-child { border-bottom: 1px solid var(--line); }
.ts-canon .ask-q {
  display: grid; grid-template-columns: 96px 1fr auto; gap: 22px; align-items: center;
  width: 100%; text-align: left; padding: 17px 2px; cursor: pointer; transition: padding-left .16s;
  position: relative;
}
.ts-canon .ask-q:hover { padding-left: 8px; }
.ts-canon .ask-q .ask-ctx { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-4); }
.ts-canon .ask-q .ask-text { font-size: clamp(15px, 1.3vw, 17px); color: var(--ink-1); font-weight: 500; letter-spacing: -0.01em; }
.ts-canon .ask-q .ask-cue { font-family: var(--f-mono); font-size: 12.5px; color: var(--ink-4); display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.ts-canon .ask-q:hover .ask-cue { color: var(--accent); }
.ts-canon .ask-q .ask-cue svg { transition: transform .2s; }
.ts-canon .ask-row.open .ask-cue svg { transform: rotate(90deg); }
.ts-canon .ask-row.open .ask-cue { color: var(--accent); }
.ts-canon .ask-row::after, .ts-canon .ask-q::after { content: ""; position: absolute; left: -10px; top: 0; bottom: 0; width: 2px; background: var(--accent-fill); border-radius: 2px; opacity: 0; transform: scaleY(0.4); transition: opacity .18s ease, transform .18s ease; }
.ts-canon .ask-row:not(.open) .ask-q:hover::after { opacity: 1; transform: scaleY(1); }

.ts-canon .ask-ans { padding: 4px 2px 24px; display: grid; grid-template-columns: 1.05fr 1fr; gap: clamp(24px, 3vw, 44px); align-items: start; }
.ts-canon .ask-ans .aa-say { font-size: clamp(15px, 1.4vw, 17.5px); line-height: 1.6; color: var(--ink-1); }
.ts-canon .ask-ans .aa-say .tag { font-family: var(--f-mono); font-weight: 600; color: var(--accent-2); font-size: 0.88em; }
.ts-canon .ask-ans .aa-cite { margin-top: 16px; }

/* shared mini-result block */
.ts-canon .cp-result { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--surface-2); }
.ts-canon .cp-result-h { display: flex; align-items: center; gap: 8px; padding: 7px 11px; border-bottom: 1px solid var(--line-2); font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-3); }
.ts-canon .cp-result-h .nm { color: var(--ink-2); font-weight: 600; }
.ts-canon .cp-result-h .ms { margin-left: auto; color: var(--ink-4); }
.ts-canon .cp-rows { display: flex; flex-direction: column; }
.ts-canon .cp-line { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px; padding: 7px 11px; font-size: 12px; border-top: 1px solid var(--line-3); }
.ts-canon .cp-line:first-child { border-top: 0; }
.ts-canon .cp-line .tag { font-family: var(--f-mono); font-weight: 600; color: var(--ink-1); font-size: 11.5px; }
.ts-canon .cp-line .meta { color: var(--ink-3); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .cp-line .st { display: inline-flex; align-items: center; gap: 6px; font-family: var(--f-mono); font-size: 10.5px; }
.ts-canon .cp-line .st.flag { color: var(--flag); }
.ts-canon .cp-line .st.ok { color: var(--good); }
.ts-canon .cp-result-foot { display: flex; align-items: center; gap: 8px; padding: 7px 11px; border-top: 1px solid var(--line-2); font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-4); background: var(--surface); }
.ts-canon .cp-result-foot a { color: var(--accent); cursor: pointer; margin-left: auto; }
.ts-canon .cp-cite { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font-family: var(--f-mono); font-size: 10.5px; color: var(--accent); border: 1px solid var(--accent-line); background: var(--accent-soft); border-radius: 5px; padding: 3px 8px; align-self: flex-start; }
.ts-canon .cp-cite .sq { width: 9px; height: 9px; border: 1.5px solid var(--accent); border-radius: 2px; }

/* ═══════════════ BLOCK 4 · USE (named jobs) ═══════════════ */
.ts-canon .jobs { margin-top: clamp(26px, 3vw, 40px); display: grid; grid-template-columns: 1fr 1fr; gap: 0 clamp(40px, 5vw, 80px); }
.ts-canon .job { padding: 18px 2px; border-top: 1px solid var(--line); display: block; transition: padding-left .16s; position: relative; }
.ts-canon .job::after { content: ""; position: absolute; left: -10px; top: 0; bottom: 0; width: 2px; background: var(--accent-fill); border-radius: 2px; opacity: 0; transform: scaleY(0.4); transition: opacity .18s ease, transform .18s ease; }
.ts-canon .job:hover { padding-left: 8px; }
.ts-canon .job:hover::after { opacity: 1; transform: scaleY(1); }
.ts-canon .job .job-name { display: flex; align-items: center; gap: 9px; font-size: 16px; font-weight: 600; color: var(--ink-1); letter-spacing: -0.01em; }
.ts-canon .job .job-name svg { color: var(--ink-5); opacity: 0; transform: translateX(-4px); transition: opacity .16s, transform .16s; }
.ts-canon .job:hover .job-name { color: var(--accent-2); }
.ts-canon .job:hover .job-name svg { opacity: 1; transform: translateX(0); color: var(--accent); }
.ts-canon .job .job-desc { font-size: 14px; color: var(--ink-3); line-height: 1.5; margin-top: 5px; max-width: 46ch; }

/* ═══════════════ BLOCK 5 · DRAWINGS (glossary) ═══════════════ */
.ts-canon .ref-list { margin-top: clamp(26px, 3vw, 40px); }
.ts-canon .ref-item {
  display: grid; grid-template-columns: minmax(190px, 1.1fr) 2fr auto; gap: 12px clamp(20px, 3vw, 40px);
  align-items: baseline; padding: 18px 2px; border-top: 1px solid var(--line); transition: padding-left .16s; position: relative;
}
.ts-canon .ref-list .ref-item:last-child { border-bottom: 1px solid var(--line); }
.ts-canon .ref-item::after { content: ""; position: absolute; left: -10px; top: 0; bottom: 0; width: 2px; background: var(--accent-fill); border-radius: 2px; opacity: 0; transform: scaleY(0.4); transition: opacity .18s ease, transform .18s ease; }
.ts-canon .ref-item:hover { padding-left: 8px; }
.ts-canon .ref-item:hover::after { opacity: 1; transform: scaleY(1); }
.ts-canon .ref-item .ref-name { font-size: 16px; font-weight: 600; color: var(--ink-1); letter-spacing: -0.01em; }
.ts-canon .ref-item .ref-code { font-family: var(--f-mono); font-size: 12px; color: var(--ink-4); margin-left: 10px; font-weight: 500; }
.ts-canon .ref-item .ref-desc { font-size: 14.5px; color: var(--ink-3); line-height: 1.5; }
.ts-canon .ref-item .ref-acts { display: inline-flex; gap: 20px; justify-self: end; align-items: baseline; }
.ts-canon .ref-item .ref-link { font-family: var(--f-mono); font-size: 12.5px; color: var(--ink-3); white-space: nowrap; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.ts-canon .ref-item .ref-link:hover { color: var(--accent); text-decoration: underline; }
.ts-canon .ref-item .ref-link svg { transition: transform .18s ease; }
.ts-canon .ref-item .ref-link:hover svg { transform: translateX(3px); }

/* ═══════════════ BLOCK 6 · EXPORTS (sober reference table) ═══════════════ */
.ts-canon .xtable-wrap, .ts-canon .ptable-wrap { margin-top: clamp(26px, 3vw, 40px); max-width: 880px; overflow-x: auto; }
.ts-canon .xtable, .ts-canon .ptable { width: 100%; border-collapse: collapse; }
.ts-canon .xtable th, .ts-canon .xtable td, .ts-canon .ptable th, .ts-canon .ptable td { text-align: left; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.ts-canon .xtable th, .ts-canon .ptable th { font-family: var(--f-mono); font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-4); font-weight: 500; border-bottom: 1px solid var(--ink-5); white-space: nowrap; }
.ts-canon .xtable td { font-size: 14.5px; }
.ts-canon .xtable td.fmt { color: var(--ink-1); font-weight: 600; }
.ts-canon .xtable td.ext { font-family: var(--f-mono); font-size: 13px; color: var(--accent-2); }
.ts-canon .xtable td.tgt { color: var(--ink-3); }
.ts-canon .xtable tr:last-child td, .ts-canon .ptable tr:last-child td { border-bottom: 0; }
.ts-canon .xtable tbody tr, .ts-canon .ptable tbody tr { transition: background .15s ease; }
.ts-canon .xtable tbody tr:hover, .ts-canon .ptable tbody tr:hover { background: var(--surface-2); }

/* ═══════════════ BLOCK 7 · API + MCP ═══════════════ */
.ts-canon .api { margin-top: clamp(26px, 3vw, 40px); max-width: 70ch; display: flex; flex-direction: column; gap: 20px; }
.ts-canon .api p { font-size: clamp(15.5px, 1.35vw, 18px); line-height: 1.62; color: var(--ink-2); margin: 0; }
.ts-canon .api code { font-family: var(--f-mono); font-size: 0.84em; color: var(--ink-1); background: var(--surface-2); border: 1px solid var(--line-2); border-radius: 4px; padding: 1px 6px; }
.ts-canon .api-more, .ts-canon .more {
  font-family: var(--f-mono); font-size: 13px; color: var(--accent);
  display: inline-flex; gap: 7px; align-items: center; width: fit-content; white-space: nowrap;
}
.ts-canon .api-more svg, .ts-canon .more svg { transition: transform .18s ease; }
.ts-canon .api-more:hover, .ts-canon .more:hover { text-decoration: underline; }
.ts-canon .api-more:hover svg, .ts-canon .more:hover svg { transform: translateX(3px); }

/* ═══════════════ BLOCK 8 · STANDARDS ═══════════════ */
.ts-canon .standards { max-width: 82ch; }
.ts-canon .standards .std-p { font-size: clamp(17px, 1.6vw, 22px); line-height: 1.6; color: var(--ink-1); margin: 0; letter-spacing: -0.01em; }
.ts-canon .standards .std-ids { display: flex; flex-wrap: wrap; gap: 8px; margin: 28px 0 0; }
.ts-canon .standards .std-ids .fam {
  font-family: var(--f-mono); font-size: 12.5px; font-weight: 500; color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 7px 12px;
  transition: border-color .14s, color .14s;
}
.ts-canon .standards .std-ids .fam:hover { border-color: var(--accent-line); color: var(--ink-1); }

/* ═══════════════ BLOCK 9 · INTEGRATIONS (logo wall) ═══════════════ */
.ts-canon .intg { margin-top: clamp(26px, 3vw, 40px); display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line-strong); border-left: 1px solid var(--line-strong); border-radius: var(--r-md); overflow: hidden; }
/* solid paneled grid — cells carry a surface so the wall reads as a precise
   panel, not big empty boxes; hover lifts each cell (premium-craft pass). */
.ts-canon .intg-cell { border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 20px 16px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 11px; min-height: 104px; background: var(--surface); transition: background .16s ease, border-color .16s ease; }
.ts-canon .intg-cell:hover { background: var(--surface-2); }
.ts-canon .intg-cell .intg-placeholder {
  width: 132px; height: 40px; border-radius: 6px;
  background: var(--surface-2); border: 1px dashed var(--line);
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 10px; color: var(--ink-5); letter-spacing: 0.08em; text-transform: uppercase;
}
/* real logo cells — each cell sets `color: <brand-tint>` inline so the
   inline-SVG `currentColor` cascade paints the mark in the vendor's
   brand color (per data.ts LC_INTEGRATIONS.tint). On dark theme an
   optional brighter shade is read from --intg-tint-dark when present
   so the mark still reads on graphite. */
.ts-canon .intg-cell {
  /* light-mode cascade — currentColor inside LogoMark resolves to this */
  color: var(--intg-tint, var(--ink-2));
}
[data-theme="dark"] .ts-canon .intg-cell,
html.dark .ts-canon .intg-cell {
  color: var(--intg-tint-dark, var(--intg-tint, var(--ink-1)));
}
.ts-canon .intg-cell .intg-logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 132px; height: 40px;
}
.ts-canon .intg-cell .intg-logo > svg { display: block; max-width: 100%; max-height: 100%; }
.ts-canon .intg-cell .intg-name { font-family: var(--f-mono); font-size: 12.5px; letter-spacing: 0.03em; color: var(--ink-3); text-align: center; }
@media (max-width: 860px) { .ts-canon .intg { grid-template-columns: repeat(2, 1fr); } }

/* ═══════════════ BLOCK 10 · PRICING (sober table) ═══════════════ */
.ts-canon .ptable td.tier { font-weight: 600; color: var(--ink-1); font-size: 15.5px; }
.ts-canon .ptable td.price { font-family: var(--f-mono); font-size: 16px; color: var(--ink-1); white-space: nowrap; }
.ts-canon .ptable td.price .per { color: var(--ink-4); font-size: 12.5px; margin-left: 2px; }
.ts-canon .ptable td.col { color: var(--ink-3); font-size: 14px; }
.ts-canon .ptable td .quote { color: var(--accent-2); font-style: italic; font-family: var(--f-serif); }
.ts-canon .ptable-foot { margin-top: 24px; display: flex; gap: 18px; align-items: center; flex-wrap: wrap; }
.ts-canon .ptable-foot .pf-note { font-size: 13.5px; color: var(--ink-4); }
.ts-canon .ptable-foot .pf-note a { color: var(--accent); font-weight: 600; }

/* ═══════════════ BLOCK 11 · FOOTER ═══════════════ */
/* ─── footer · dark forest always (light AND dark theme) ───
   The footer carries data-theme="dark" on the element itself, which
   via the .ts-canon [data-theme="dark"] cascade resolves every token
   inside to canonical dark values. So even in light page mode the
   footer surface, ink, hairlines, and accents read as dark workspace.
   Hard-coded background here is the belt for the brace. */
/* Footer colors lifted to the new contrast ladder (2026-06-22). These were
   hardcoded faint greys (#888E8B headers ~3:1, #A5AAA7 legal) that bypassed the
   token lift, so the footer read washed-out while the rest of the page sharpened.
   Subtle top-lit depth matches the page; the mint datum edge stays. */
/* ═══════════ FOOTER SURFACE · ONE COLOUR, ALL THE WAY DOWN ═══════════
   The exact counterpart of .ts-barhost above, and it exists for the same
   founder report from the other end of the page: "below the footer there is a
   strip that is off colour when it should be the same colour as the footer"
   (2026-07-30, and the 2026-07-13 mobile report before it).

   The mechanism was an asymmetry. components/landing-navbar.tsx got a
   `ts-barhost` hook that paints the bar; components/footer.tsx kept a BARE
   `.ts-canon`, which resolves to `background: var(--bg)` (light). So the dark
   ground came only from the <footer> element inside a LIGHT wrapper, and every
   sub-pixel rounding difference between the two showed the page ground as a
   seam. The previous fix was a `box-shadow: 0 2px 0 0 #0F1213` bleed on the
   footer, i.e. hiding 2px of a wrapper that was the wrong colour. That is
   deleted: the wrapper is now the right colour, so there is nothing to hide.

   Three surfaces have to agree or the strip returns, and all three read the one
   token so they cannot drift:
     1. this wrapper (what shows through any gap, and behind the footer),
     2. the <footer> itself,
     3. .footer-in's bottom padding, which carries env(safe-area-inset-bottom)
        so the footer's own ground fills the home-indicator zone at the end of
        the page instead of stopping short of it.
   The fourth way the page ground can appear below the footer is the overscroll
   rubber-band, which shows the CANVAS (white on marketing) no matter what any
   element paints. That is closed by overscroll-behavior below.
   Locked by components/__tests__/footer-surface-contract.test.ts and measured
   in pixels by scripts/preauth-strip-check.mjs. */
.ts-canon.ts-foothost {
  --foot-surface: #0F1213;
  background: var(--foot-surface);
}

/* ═══ THE FIFTH WAY, AND THE ONE THAT WAS STILL LIVE ══════════════════════
   Founder, 2026-08-02, after all four fixes above had shipped: "off colored
   part at the bottom below the footer (there should be no part below the
   footer but this oof color/part that doesnt match the footer makes it seem
   like a extra strip below the footer)".

   MEASURED on production at 360x740 / 393x727 / 320x568, scrolled to the very
   end: the footer's own box reaches the last pixel of the document
   (`footerRect.y + h` = 9217 against `scrollHeight` 9218) and paints
   `rgb(15,18,19)` correctly. And `html` paints `rgb(255,255,255)`.

   That white IS the strip. The document CANVAS is not the footer's problem to
   solve: it is the surface the browser paints everywhere the document is not,
   and on a phone with `viewport-fit=cover` that region is real and visible at
   the bottom of the page (the gesture-nav / home-indicator band). Killing the
   rubber-band above closed the overscroll route to it; it did nothing about
   the persistent inset, which is why the report came back.

   The comment above says the canvas "cannot be right at both ends" because it
   has one background-color. That is true of ONE box, and the fix is that there
   are TWO: `html` paints the canvas, `body` paints the page. Per CSS
   backgrounds, body's background only propagates to the canvas when html has
   none, so giving html its own colour keeps body's white on the body box while
   the canvas underneath goes footer-dark. Body starts at y=0 (margin is zeroed
   by preflight) so it still covers the TOP inset, and it ends where the footer
   ends, so the only thing left under it is the bottom band. Right at both ends,
   from two declarations.

   `min-height: 100dvh` is load-bearing, not tidiness: a short page (`/404` also
   renders this footer) would otherwise end its body above the fold and let the
   near-black canvas show as a band under the CONTENT. It guarantees the white
   always reaches at least the bottom of the viewport.

   Scoped by `:has(.ts-foothost)` so it touches only pages that actually render
   the dark footer. Locked by components/__tests__/footer-surface-contract.test.ts. */
html:has(.ts-foothost) { background-color: var(--foot-surface, #0F1213); }
html:has(.ts-foothost) body { background-color: #FFFFFF; min-height: 100dvh; }
/* The canvas is the one surface no element owns: at the top it is the bar's
   white (correct, that is the top of the document), at the bottom it is that
   same white behind a near-black footer. There is exactly one background-color
   for the canvas, so it cannot be right at both ends; removing the rubber-band
   is what makes the bottom right without making the top wrong. Trade-off,
   deliberate: this also disables pull-to-refresh on pre-auth pages.

   IT GOES ON `html` ONLY. The companion `... body { overscroll-behavior-y:
   none }` that used to sit here KILLED MOUSEWHEEL SCROLLING ON EVERY
   MARKETING PAGE, in production. Measured 2026-08-01 against tagsight.io
   itself: a real wheel at 1440x900 left scrollY at 0 on `/` and `/pricing`.
   Keyboard scrolling still worked once the body had focus, so the wheel is
   the whole of it.

   The mechanism: `body` computes `overflow-y: auto` by viewport propagation
   and its used height equals the full content height, so it is itself a
   scroll container with NO scrollable overflow. `overscroll-behavior-y: none`
   on that box tells the browser not to CHAIN, so the wheel is swallowed by a
   box that cannot scroll and never reaches the element that can. Bisected on
   the live page, and the split is unambiguous:
       html:none  body:auto  -> scrolls (rubber-band still suppressed)
       html:auto  body:none  -> BROKEN
   The wheel event itself arrives at the window un-prevented, so nothing is
   calling preventDefault; the browser is simply refusing to scroll.

   NEVER put overscroll-behavior on `body`. On `html` it means "no rubber-band";
   on `body` it means "swallow the scroll".
   Locked by scripts/preauth-scroll-check.mjs, which drives a REAL mouse wheel.
   A programmatic window.scrollTo() still worked throughout, which is exactly
   why every existing harness scored this page green. */
html:has(.ts-foothost) { overscroll-behavior-y: none; }

.ts-canon .footer {
  background: var(--foot-surface, #0F1213) !important;
  color: #F2F5F3 !important;
  position: relative;
}
/* a whisper-thin neutral top hairline. The old mint seam is gone. */
.ts-canon .footer::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: rgba(236,239,237,0.08);
}
/* The bottom padding carries env(safe-area-inset-bottom) so the footer's own
   dark ground fills the home-indicator strip when the page is scrolled to the
   end. Without it the footer stops above that zone and the canvas shows. 0px on
   devices without a home indicator, so it costs nothing there. */
.ts-canon .footer-in {
  max-width: var(--mkt-w); margin: 0 auto;
  padding: clamp(78px, 8vw, 128px) var(--gut) calc(46px + env(safe-area-inset-bottom, 0px));
}
.ts-canon .footer-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.55fr); gap: clamp(48px, 7vw, 128px); align-items: start; }
.ts-canon .footer-brand { display: flex; flex-direction: column; gap: 26px; max-width: 44ch; }
.ts-canon .fb-lockup { display: flex; align-items: center; gap: 14px; }
.ts-canon .footer-brand .fb-word { font-family: var(--f-display); font-weight: 700; font-size: clamp(33px, 3.1vw, 43px); color: #FCFEFC; letter-spacing: -0.026em; }
.ts-canon .footer-brand .fb-desc { margin: 0; font-size: 15px; color: #9AA29B; line-height: 1.64; max-width: 42ch; }
/* Social/link icon buttons: bordered squares, muted glyph at rest that lights
   to the brand green on hover (echoes the footer's link behaviour). */
.ts-canon .fb-social { display: flex; gap: 12px; margin-top: 4px; }
.ts-canon .fb-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 11px;
  border: 1px solid rgba(236,239,237,0.13);
  background: rgba(236,239,237,0.02);
  color: #A7AEA8;
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease, transform 150ms ease;
}
.ts-canon .fb-social a svg { width: 19px; height: 19px; fill: currentColor; }
.ts-canon .fb-social a:hover {
  color: #2FBE81;
  border-color: rgba(47,190,129,0.42);
  background: rgba(47,190,129,0.08);
  transform: translateY(-1px);
}
.ts-canon .fb-social a:focus-visible {
  outline: 2px solid #2FBE81; outline-offset: 2px; color: #2FBE81;
}
.ts-canon .footer-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(22px, 3vw, 44px); }
.ts-canon .footer-col h3, .ts-canon .footer-col h4 { font-family: var(--f-sans); font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: #7C837D; margin: 0 0 22px; }
.ts-canon .footer-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 15px; }
.ts-canon .footer-col a { font-size: 14.5px; color: #E9EDEA; transition: color 130ms; }
.ts-canon .footer-col a:hover { color: #FFFFFF; }

.ts-canon .footer-bottom {
  margin-top: clamp(62px, 7vw, 104px); padding-top: 26px;
  border-top: 1px solid rgba(236,239,237,0.1);
  display: flex; flex-wrap: wrap; gap: 16px; align-items: center;
}
.ts-canon .footer-bottom .fb-line { font-family: var(--f-sans); font-size: 13px; color: #868D87; }
.ts-canon .footer-bottom .fb-spacer { flex: 1; }
.ts-canon .footer-bottom .fb-links { display: flex; gap: 24px; }
.ts-canon .footer-bottom .fb-links a { font-family: var(--f-sans); font-size: 13px; color: #C4C9C4; transition: color 130ms; }
.ts-canon .footer-bottom .fb-links a:hover { color: #FFFFFF; }

/* touch (2026-07-14): footer links become 44px-tall tap targets on phones. The
   tight row gap is traded for real tap height (the link text is unchanged). */
@media (max-width: 640px) {
  .ts-canon .footer-col ul { gap: 2px; }
  .ts-canon .footer-col a,
  .ts-canon .footer-bottom .fb-links a { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ═══════════════ P&ID drawing primitives ═══════════════ */
.ts-canon .pid svg { font-family: var(--f-mono); }
.ts-canon .pid .frame { fill: none; stroke: rgba(14,26,20,0.14); stroke-width: 1; }
.ts-canon .pid .titleblock { fill: #F6F8F5; stroke: rgba(14,26,20,0.14); stroke-width: 1; }
.ts-canon .pid .tb-txt { fill: #828B83; font-size: 5.4px; letter-spacing: 0.04em; }
.ts-canon .pid .tb-txt.big { fill: #364039; font-size: 6.6px; font-weight: 600; }
.ts-canon .pid .proc { stroke: #364039; stroke-width: 1.7; fill: none; }
.ts-canon .pid .sig { stroke: #5E6760; stroke-width: 0.9; fill: none; stroke-dasharray: 3.2 2.2; }
.ts-canon .pid .vessel { fill: #F6F8F5; stroke: #364039; stroke-width: 1.6; }
.ts-canon .pid .valve { fill: #FFFFFF; stroke: #364039; stroke-width: 1.4; }
.ts-canon .pid .bub { fill: #FFFFFF; stroke: #364039; stroke-width: 1.3; }
.ts-canon .pid .bub-line { stroke: #364039; stroke-width: 0.9; }
.ts-canon .pid .bt { fill: #0E1A14; font-size: 5px; font-weight: 600; text-anchor: middle; letter-spacing: 0.01em; }
.ts-canon .pid .lbl { fill: #5E6760; font-size: 4.6px; }
.ts-canon .pid .hl-ring { fill: rgba(24,192,136,0.12); stroke: #0C8F61; stroke-width: 1.6; }
.ts-canon .pid .hl-glow { fill: none; stroke: rgba(24,192,136,0.4); stroke-width: 5; opacity: 0.5; }
.ts-canon .pid .hl-tag { fill: #0A7B53; font-size: 4.8px; font-weight: 700; text-anchor: middle; }

/* ═══════════════ engineering-tool focus ring ═══════════════ */
.ts-canon a:focus-visible, .ts-canon button:focus-visible, .ts-canon [tabindex]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px;
}

/* ═══════════════ responsive ═══════════════ */
@media (max-width: 1080px) {
  .ts-canon .footer-top { grid-template-columns: 1.2fr repeat(2, 1fr); }
  .ts-canon .footer-addr { grid-template-columns: 1.2fr 1fr 1fr; }
}
@media (max-width: 920px) {
  .ts-canon .hero-grid { grid-template-columns: 1fr; }
  .ts-canon .hero-copy { max-width: 100%; }
  .ts-canon .ask-ans { grid-template-columns: 1fr; gap: 18px; }
  .ts-canon .jobs { grid-template-columns: 1fr; gap: 0; }
  .ts-canon .footer-top { grid-template-columns: 1fr 1fr; }
  .ts-canon .footer-addr { grid-template-columns: 1fr; }
  .ts-canon .footer-legal { grid-column: 1 / -1; }
}
@media (max-width: 680px) {
  .ts-canon .drop { grid-template-columns: 1fr; }
  .ts-canon .footer-top { grid-template-columns: 1fr; gap: 28px; }
  /* footer link columns: collapse 4 -> 2 so they stop cramping/wrapping on phones.
     Scoped via .footer-top for higher specificity than the base .footer-cols, so it
     wins on specificity (not source order) even when the sheet is inlined into
     multiple route bundles. */
  .ts-canon .footer-top .footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 34px 24px; }
}
@media (max-width: 400px) {
  .ts-canon .footer-top .footer-cols { gap: 30px 18px; }
}
@media (max-width: 640px) {
  .ts-canon .ask-q { grid-template-columns: 1fr auto; gap: 10px; }
  .ts-canon .ask-q .ask-ctx { display: none; }
  .ts-canon .ref-item { grid-template-columns: 1fr; gap: 6px; }
  .ts-canon .ref-item .ref-link { justify-self: start; }
  /* Pricing — convert 4-col table to stacked cards on phones so no column
     clips at 375px and every row reads on one screen. Desktop layout
     untouched above this breakpoint. */
  .ts-canon .ptable,
  .ts-canon .ptable thead,
  .ts-canon .ptable tbody,
  .ts-canon .ptable tr,
  .ts-canon .ptable th,
  .ts-canon .ptable td { display: block; }
  .ts-canon .ptable thead { display: none; }
  .ts-canon .ptable tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 6px 16px;
    align-items: baseline;
    padding: 16px 12px;
    border-top: 1px solid var(--line);
    border-bottom: 0;
  }
  .ts-canon .ptable tr:last-child { border-bottom: 1px solid var(--line); }
  .ts-canon .ptable td { padding: 0; border: 0; }
  .ts-canon .ptable td.tier { font-size: 17px; }
  .ts-canon .ptable td.price { justify-self: end; font-size: 15px; }
  .ts-canon .ptable td.col { grid-column: 1 / -1; font-size: 13px; color: var(--ink-3); }
  /* Exports — same treatment so the 3-col format/file/target table reads
     cleanly on phones */
  .ts-canon .xtable,
  .ts-canon .xtable thead,
  .ts-canon .xtable tbody,
  .ts-canon .xtable tr,
  .ts-canon .xtable th,
  .ts-canon .xtable td { display: block; }
  .ts-canon .xtable thead { display: none; }
  .ts-canon .xtable tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 4px 16px;
    align-items: baseline;
    padding: 14px 12px;
    border-top: 1px solid var(--line);
    border-bottom: 0;
  }
  .ts-canon .xtable tr:last-child { border-bottom: 1px solid var(--line); }
  .ts-canon .xtable td { padding: 0; border: 0; }
  .ts-canon .xtable td.fmt { font-size: 15.5px; }
  .ts-canon .xtable td.ext { justify-self: end; }
  .ts-canon .xtable td.tgt { grid-column: 1 / -1; }
}

/* ─── mobile hardening for the topbar + sections ───
   Below 720px the desktop Sign in / Start-a-workspace buttons would
   compete with the brand + hamburger for width and overflow on small
   phones; they're already in the mobile sheet so we hide the duplicates
   here. Tightens topbar gutter + brand wordmark too. */
@media (max-width: 720px) {
  .ts-canon .topbar-in { gap: 12px; padding-left: 16px; padding-right: 16px; }
  /* Hide the whole branch span, not just its buttons — an empty inline-flex
     span still takes a 10px flex gap and would shove the hamburger left.
     The html[data-auth] copy is here to out-specify the `in`-branch rule
     above (0,4,1 beats 0,3,1), which would otherwise re-show Dashboard. */
  .ts-canon .tb-actions .tb-auth,
  html[data-auth] .ts-canon .tb-actions .tb-auth { display: none; }
  .ts-canon .tb-actions .btn-ghost,
  .ts-canon .tb-actions .btn-pri { display: none; }
  .ts-canon .tb-word { font-size: 16px; }
  .ts-canon .tb-brand svg { width: 50px; height: auto; }
  /* hero CTAs full-width-stack on mobile */
  .ts-canon .hero-cta { flex-direction: column; align-items: stretch; width: 100%; }
  .ts-canon .hero-cta .btn-lg { width: 100%; justify-content: center; }
  /* hero copy max-width should be unbounded on small */
  .ts-canon .hero-desc { max-width: 100%; }
  /* drawings ref-list rows: space them out on narrow */
  .ts-canon .ref-item { padding: 14px 2px; }
  /* footer columns get a clearer rhythm when stacked */
  .ts-canon .footer-top { gap: 28px; }
  .ts-canon .footer-bottom { flex-direction: column; align-items: flex-start; gap: 12px; }
  .ts-canon .footer-bottom .fb-spacer { display: none; }
}

/* very narrow phones — keep the hero workspace card from squishing */
@media (max-width: 420px) {
  .ts-canon .hw-stage { height: clamp(500px, 78vh, 640px); }
  .ts-canon .hw-bar { padding: 0 14px 0 16px; }
  .ts-canon .hw-word { font-size: 13px; }
}

/* ════════════════════════════════════════════════════════════════
   MOBILE EXCELLENCE PASS (≤640) — craft over coverage.
   The page already stacks without overflow; this tightens the things
   that read "unfinished" on a phone: cavernous section gaps, an empty
   integration wall, and 12px tap targets on the drawing-type actions.
   ════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  /* 1 · Section rhythm. Desktop pad (up to 124px each side) stacks to
     ~150px of dead space between sections on a phone. Halve it for a
     confident scroll without losing the air between chapters. */
  .ts-canon .pad-default { padding-top: clamp(50px, 12vw, 76px); padding-bottom: clamp(50px, 12vw, 76px); }
  .ts-canon .pad-sm { padding-top: clamp(34px, 9vw, 52px); padding-bottom: clamp(34px, 9vw, 52px); }
  .ts-canon .sec-head { padding-top: clamp(22px, 6vw, 34px); }
  .ts-canon .sec-head .sec-lede,
  .ts-canon .sec-head .lede { font-size: 15.5px; line-height: 1.55; }

  /* 2 · Integration wall. Desktop cells are 132px tall; at 2-col on a
     phone each is a cavern around a small logo. Compact them — shorter
     cells, smaller logo box, tighter gap — so the grid reads dense and
     intentional, not half-empty. */
  .ts-canon .intg-cell { min-height: 92px; padding: 18px 10px; gap: 9px; }
  .ts-canon .intg-cell .intg-logo { width: 88px; height: 28px; }
  .ts-canon .intg-cell .intg-name { font-size: 11px; line-height: 1.35; letter-spacing: 0.02em; }

  /* 3 · Drawing-type rows. Stacked name / desc / actions. Turn the two
     cramped 12px text links into real 40px-tall outlined tap targets
     sitting on their own row — thumb-friendly, clearly interactive. */
  .ts-canon .ref-item { padding: 16px 2px 18px; gap: 9px; }
  .ts-canon .ref-item .ref-name { font-size: 16.5px; }
  .ts-canon .ref-item .ref-desc { font-size: 14px; }
  .ts-canon .ref-item .ref-acts { justify-self: start; gap: 10px; margin-top: 3px; }
  .ts-canon .ref-item .ref-acts .ref-link {
    font-size: 12.5px; min-height: 40px; padding: 0 16px;
    border: 1px solid var(--line-strong); border-radius: var(--r-sm);
    color: var(--ink-2); justify-content: center; letter-spacing: 0.02em;
  }
  .ts-canon .ref-item .ref-acts .ref-link:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }

  /* 4 · Tap targets on the ask list — the whole question row should be a
     comfortable touch height, not a thin text line. */
  .ts-canon .ask-q { min-height: 52px; padding-top: 16px; padding-bottom: 16px; }
  .ts-canon .ask-q .ask-cue { font-size: 12px; }
}

/* keep scroll anchors clear of the sticky bar */
.ts-canon [id] { scroll-margin-top: 76px; }

/* ════════════════════════════════════════════════════════════════
   BODY PAINT — owned directly via the `.ts-canon-body` class set on
   <body> by the root layout + MarketingThemeApplier. No :has(),
   no !important fights with the legacy ts-v3-root cascade — that
   class is gone from <body> on marketing routes.
   ════════════════════════════════════════════════════════════════ */
body.ts-canon-body {
  /* NEUTRAL light ladder: the founder-approved homepage surface (see
     _home-cine.css .cine-home: TRUE white base, #F4F4F5 neutral-gray band,
     white cards). The old #F1F4F0 / #F6F8F5 / #F6F9FD green-paper ladder was
     the banned paper ground and made every pre-auth page a different light
     colour than the homepage. Every pre-auth surface now matches the homepage. */
  background: #FFFFFF;
  color: #0E1A14;
  min-height: 100vh;
  /* sticky canonical topbar sits at top: 0, no body padding-top */
  padding-top: 0;

  /* ─── CANONICAL TOKEN BRIDGE ───────────────────────────────────────
     Every brand-v4 component on every pre-auth page reads its surface
     and accent tokens through these CSS variables (--ts-paper, --ts-ink-N,
     --ts-mint, etc.) declared at :root in brand-v4-tokens.css. Rebinding
     them here at body level rewrites the entire pre-auth palette to
     canonical values without touching a single brand-v4 component file. */
  --ts-paper:        #FFFFFF;
  --ts-paper-2:      #F4F4F5;
  --ts-paper-3:      #ECECEE;
  --ts-paper-card:   #FFFFFF;
  --ts-paper-sunk:   #F4F4F5;

  --ts-ink-1:        #0E1A14;
  --ts-ink-2:        #364039;
  --ts-ink-3:        #5E6760;
  --ts-ink-4:        #828B83;
  --ts-ink-disabled: #AEB4AD;

  --ts-rule:         rgba(14,26,20,0.14);
  --ts-rule-soft:    rgba(14,26,20,0.06);
  --ts-rule-strong:  rgba(14,26,20,0.42);
  --ts-rule-ink:     #0E1A14;

  --ts-mint:         #0C8F61;
  --ts-mint-deep:    #0A7B53;
  --ts-mint-soft:    rgba(24,192,136,0.12);
  --ts-mint-line:    rgba(12,143,97,0.34);
}
[data-theme="dark"] body.ts-canon-body,
html.dark body.ts-canon-body {
  background: #0C0F0E;
  color: #ECEFED;

  --ts-paper:        #0C0F0E;
  --ts-paper-2:      #191E1C;
  --ts-paper-3:      #202623;
  --ts-paper-card:   #1B2220;
  --ts-paper-sunk:   #0F1413;

  --ts-ink-1:        #ECEFED;
  --ts-ink-2:        #B8BDBA;
  --ts-ink-3:        #888E8B;
  --ts-ink-4:        #656B68;
  --ts-ink-disabled: #474C49;

  --ts-rule:         rgba(236,239,237,0.13);
  --ts-rule-soft:    rgba(236,239,237,0.075);
  --ts-rule-strong:  rgba(236,239,237,0.30);
  --ts-rule-ink:     #ECEFED;

  --ts-mint:         #5BE3AF;
  --ts-mint-deep:    #76EABE;
  --ts-mint-soft:    rgba(80,222,170,0.15);
  --ts-mint-line:    rgba(80,222,170,0.44);
}

/* ── iOS notch / status-bar match on the cine LANDING (homepage) ──────────────
   The cine home paints a WHITE (light) / near-black (dark) page ground under a
   TRANSPARENT chrome-less topbar, but body.ts-canon-body painted the canonical
   paper ground (#F1F4F0) behind it. So a mismatched band showed above the bar on
   iPhone, and the measured status-bar tint (StatusBarColor samples the top edge)
   read that band, not the bar. Repaint body + html to the cine ground on the cine
   home so the notch strip, the area above the bar, and the topbar are ONE colour.
   Also zero the un-reset 8px UA <body> margin that exposed an html sliver at y=0. */
   BODY, NOT HTML. This pair used to paint `html` as well, and that is what kept
   the strip below the footer alive on the most-visited page: `html:has(.cine-home)`
   has the same specificity as `html:has(.ts-foothost)` and sits LATER in this
   file, so it silently won and repainted the canvas white behind a near-black
   footer. Measured on the built homepage at 393x727: `html` resolved to
   rgb(255,255,255) with the footer at rgb(15,18,19).

   Dropping `html` costs nothing, because the reason this rule exists is the TOP
   of the page and `body` already covers it: body starts at y=0 (its UA margin is
   zeroed on the line above) and, per the foothost rule, is floored at 100dvh. So
   the notch strip, the area above the bar and the topbar are still one colour.
   The canvas below the document belongs to `html:has(.ts-foothost)`.

   THE GENERAL RULE, and it is the same one the bare-`.ts-canon` guard encodes:
   BODY IS THE PAGE, HTML IS THE CANVAS. A page-ground rule that reaches for
   `html` is claiming a surface it does not own, and it will collide with the
   footer at the bottom every time. */
body.ts-canon-body { margin: 0; }
body.ts-canon-body:has(.cine-home) { background: #FFFFFF; }
html.dark body.ts-canon-body:has(.cine-home) { background: #0B0C0E; }

html { scroll-padding-top: 56px; }

/* ───────── What you get — the I/O list as a precise engineering document ─────────
   The deliverable shown as the real artifact: a strong header band with a mint
   datum tick, a dense hairline grid (mono tags + signal-class chips), an export
   foot. It lifts off the calm ground as the section's single artifact — no
   diptych, no logo wall, no arrow-links. */
/* chaptered ground: a cool mid-light band, a step between the dark Intelligence
   band above and the bright Stack below; its dark artifact carries the contrast
   within (chaptered-rhythm pass 2026-07-07). Specificity beats the bg-base
   utility the section also carries. */
.ts-canon .sec.wyg {
  background-color: #E4EAF2;
  background-image: radial-gradient(130% 78% at 50% -12%, rgba(12,143,97,0.04) 0%, rgba(12,143,97,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6);
}
[data-theme="dark"] .ts-canon .sec.wyg,
html.dark .ts-canon .sec.wyg {
  background-color: #0C100F;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.ts-canon .wyg-doc {
  margin-top: clamp(36px, 4vw, 60px);
  /* ALWAYS a dark product screen — the I/O list exactly as the app renders it,
     a cinematic artifact lifted off the light section like a real screenshot.
     Dark tokens scoped here so the header, rows, chips + distribution all paint
     on the app's dark surface; a restrained forest glow warms the top. */
  --bg: #0B0C0E; --surface: #16181C; --surface-2: #1D2025; --surface-3: #262A30;
  --ink-1: #F5F7F9; --ink-2: #CCD1D8; --ink-3: #9AA0A9; --ink-4: #757B84;
  --mark-ink: #F5F8F5;   /* the MARK's reversed ink, never --ink-1 */
  --line: rgba(255,255,255,0.11); --line-2: rgba(255,255,255,0.065); --line-strong: rgba(255,255,255,0.22);
  --accent: #3FD9A2; --accent-fill: #4EDDA8; --accent-line: rgba(63,217,162,0.5);
  /* re-darken the elevation stack for this light-mode dark island so the light
     --shadow-1 top light-catch can't bleed onto any child that consumes it
     (same fix pattern as .intel-sec). */
  --shadow-1: 0 1px 2px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.05);
  --shadow-2: 0 16px 36px -16px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.06);
  color: var(--ink-1);
  border: 1px solid rgba(255,255,255,0.09); border-radius: var(--r-md); overflow: hidden;
  background-color: #0B0C0E;
  background-image:
    radial-gradient(92% 60% at 50% 0%, rgba(31,106,78,0.15) 0%, rgba(31,106,78,0.045) 34%, rgba(31,106,78,0) 62%),
    radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1.3px);
  background-size: 100% 100%, 22px 22px;
  background-position: center top, 11px 11px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 54px 120px -54px rgba(10,14,20,0.6), 0 16px 38px -24px rgba(10,14,20,0.46);
}

.ts-canon .wyg-doc-h {
  position: relative; display: flex; align-items: center; gap: 12px;
  padding: 15px clamp(16px, 2vw, 24px); border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface-2) 92%, #fff 8%), var(--surface-2));
  font-family: var(--f-mono);
}
[data-theme="dark"] .ts-canon .wyg-doc-h,
html.dark .ts-canon .wyg-doc-h { background: linear-gradient(180deg, var(--surface-3), color-mix(in srgb, var(--surface-3) 88%, #000 12%)); }
.ts-canon .wyg-doc-h::before { content: ""; position: absolute; left: 0; top: -1px; width: 56px; height: 2px; background: var(--accent-fill); }
/* a small drafting dot-grid chip at the far left — an instrument-panel tell */
.ts-canon .wyg-doc-dotgrid {
  width: 15px; height: 15px; flex: none; color: var(--ink-4); opacity: 0.8;
  background-image: radial-gradient(currentColor 1px, transparent 1.3px);
  background-size: 5px 5px; background-position: 0 0;
}
.ts-canon .wyg-doc-title { font-size: 13px; font-weight: 700; letter-spacing: 0.2em; color: var(--ink-1); }
.ts-canon .wyg-doc-meta { font-size: 11.5px; letter-spacing: 0.04em; color: var(--ink-3); margin-left: auto; font-variant-numeric: tabular-nums; }
/* a live "reconciled" status with a soft mint pulse — the screen reads as
   reviewed and alive, not a static dump. */
.ts-canon .wyg-doc-live {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11px; letter-spacing: 0.05em; color: var(--accent-2);
  padding: 4px 10px 4px 8px; border-radius: 999px;
  border: 1px solid var(--accent-line); background: var(--accent-soft);
}
.ts-canon .wyg-doc-live-dot {
  width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--accent-fill);
  box-shadow: 0 0 0 0 var(--accent-glow);
  animation: wyg-live-pulse 2.6s ease-out infinite;
}
@keyframes wyg-live-pulse { 0% { box-shadow: 0 0 0 0 var(--accent-glow); } 70% { box-shadow: 0 0 0 6px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) { .ts-canon .wyg-doc-live-dot { animation: none; } }

.ts-canon .wyg-doc-scroll { overflow-x: auto; }
.ts-canon .wyg-doc-grid { min-width: 880px; }
.ts-canon .wyg-doc-row {
  position: relative;
  display: grid;
  grid-template-columns: 6em minmax(0, 1.7fr) minmax(0, 0.95fr) 6em 6.6em 3.4em 5.6em 5.2em;
  align-items: center; gap: clamp(10px, 1.2vw, 18px);
  padding: 14px clamp(16px, 2vw, 24px); border-top: 1px solid var(--line-2);
  transition: background 130ms ease;
}
/* a mint reading-edge slides in on hover — the row you're inspecting */
.ts-canon .wyg-doc-row:not(.wyg-doc-colh)::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: var(--accent-fill); transform: scaleY(0); transform-origin: center;
  transition: transform 150ms var(--ease, ease); opacity: 0.9;
}
.ts-canon .wyg-doc-row:not(.wyg-doc-colh):hover::before { transform: scaleY(1); }
/* the cleared exception — surfaced, reviewed, and let through. A standing mint
   edge + a check, so "every exception is surfaced for you to clear" is visible
   in the artifact itself, not just claimed below it. */
.ts-canon .wyg-doc-row.is-reviewed { background: linear-gradient(90deg, var(--accent-soft), transparent 62%); }
.ts-canon .wyg-doc-row.is-reviewed::before { transform: scaleY(1); }
.ts-canon .wyg-doc-row.is-reviewed .c-tag::after {
  content: "✓"; margin-left: 7px; color: var(--accent-2); font-size: 10.5px; font-weight: 700;
}
.ts-canon .c-rng { font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }
.ts-canon .c-loop { font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-3); letter-spacing: 0.01em; }
.ts-canon .wyg-doc-colh {
  border-top: 0;
  font-family: var(--f-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-4);
}
.ts-canon .wyg-doc-row:not(.wyg-doc-colh):hover { background: var(--surface-2); }
.ts-canon .c-tag { font-family: var(--f-mono); font-weight: 600; font-size: 13px; color: var(--ink-1); letter-spacing: 0.01em; }
.ts-canon .c-svc { font-size: 14px; color: var(--ink-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .c-type { font-size: 13px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .c-sig { font-family: var(--f-mono); font-size: 12px; color: var(--ink-3); }
.ts-canon .c-io { display: flex; }
.ts-canon .io-chip {
  font-family: var(--f-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: 5px; padding: 3px 0; min-width: 34px; text-align: center;
}
.ts-canon .c-sheet { font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-4); letter-spacing: 0.02em; }

.ts-canon .wyg-doc-foot {
  display: flex; align-items: center; gap: 12px 14px; flex-wrap: wrap;
  padding: 14px clamp(16px, 2vw, 24px); border-top: 1px solid var(--line); background: var(--surface-2);
}
[data-theme="dark"] .ts-canon .wyg-doc-foot,
html.dark .ts-canon .wyg-doc-foot { background: var(--surface-3); }
.ts-canon .wyg-doc-out { font-family: var(--f-mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink-3); }
.ts-canon .wyg-fmts { display: flex; flex-wrap: wrap; gap: 7px; }
.ts-canon .wyg-fmt {
  font-family: var(--f-mono); font-size: 11.5px; font-weight: 500; color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: 6px; padding: 5px 10px;
  transition: border-color .14s, color .14s;
}
.ts-canon .wyg-fmt:hover { border-color: var(--accent-line); color: var(--ink-1); }

/* ── section marker + two-tone headline (the Neon-grade section opener, in our
   monochrome engineering voice — a dot-square datum mark, a big two-tone line) ── */
.ts-canon .sec-mark {
  display: block; width: 30px; height: 30px; color: var(--ink-4);
  background-image: radial-gradient(currentColor 1.05px, transparent 1.5px);
  background-size: 6px 6px; background-position: 0 0;
  -webkit-mask-image: linear-gradient(135deg, #000 0%, #000 38%, transparent 78%);
          mask-image: linear-gradient(135deg, #000 0%, #000 38%, transparent 78%);
}
/* header — headline + lede sharing the width (no wasted space, no marker), the
   headline matched to the hero: single ink, display face, tight tracking. */
.ts-canon .wyg-head {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 72px); align-items: end;
}
.ts-canon .wyg-title {
  margin: 0; font-family: var(--f-display); font-weight: 600;
  font-size: clamp(32px, 3.7vw, 52px); line-height: 1.0; letter-spacing: -0.038em;
  color: var(--ink-1); text-wrap: balance;
}
.ts-canon .wyg-lede {
  margin: 0 0 7px; max-width: 42ch; font-size: clamp(15.5px, 1.2vw, 18px);
  line-height: 1.6; color: var(--ink-2);
}
@media (max-width: 820px) {
  .ts-canon .wyg-head { grid-template-columns: 1fr; gap: 16px; align-items: start; }
  .ts-canon .wyg-lede { margin-bottom: 0; }
}

/* ── signal-class distribution — the 52 points at a glance (a real data strip,
   monochrome ink ramp; reads as a breakdown, never decorative colour) ── */
/* channel-class allocation — a real I/O summary (how the 52 points split across
   card types). A slim legible bar on a recessed track, clear separators, with a
   crisp tally beneath. */
.ts-canon .wyg-dist { display: flex; flex-direction: column; gap: 11px; padding: 15px clamp(16px,2vw,24px) 17px; border-bottom: 1px solid var(--line); background: var(--surface); }
.ts-canon .wyg-dist-bar { display: flex; height: 8px; border-radius: 999px; overflow: hidden; background: #0C0E11; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.05); }
.ts-canon .wyg-dist-seg { height: 100%; }
.ts-canon .wyg-dist-seg + .wyg-dist-seg { box-shadow: inset 2px 0 0 #0C0E11; }
.ts-canon .wyg-dist-keys { display: flex; flex-wrap: wrap; gap: 16px; }
.ts-canon .wyg-dist-key { display: inline-flex; align-items: center; gap: 7px; font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.06em; color: var(--ink-4); }
.ts-canon .wyg-dist-key b { color: var(--ink-1); font-weight: 700; margin-left: 1px; }
.ts-canon .wyg-dist-dot { width: 8px; height: 8px; border-radius: 2px; }
/* legible light→dark steps (all clearly above the recessed track) */
.ts-canon .wyg-doc .wyg-dist-seg.seg-ai, .ts-canon .wyg-doc .wyg-dist-dot.seg-ai { background: #F2F5F8; }
.ts-canon .wyg-doc .wyg-dist-seg.seg-di, .ts-canon .wyg-doc .wyg-dist-dot.seg-di { background: #C4CBD4; }
.ts-canon .wyg-doc .wyg-dist-seg.seg-do, .ts-canon .wyg-doc .wyg-dist-dot.seg-do { background: #99A1AC; }
.ts-canon .wyg-doc .wyg-dist-seg.seg-ao, .ts-canon .wyg-doc .wyg-dist-dot.seg-ao { background: #6E7884; }

/* subtle row striping for the denser table */
.ts-canon .wyg-doc-grid .wyg-doc-row:not(.wyg-doc-colh):nth-child(even) { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.ts-canon .wyg-doc-more {
  padding: 13px clamp(16px,2vw,24px); border-top: 1px solid var(--line-2);
  font-family: var(--f-mono); font-size: 11.5px; letter-spacing: 0.04em; color: var(--ink-4);
}

/* footer now carries provenance (source sheets) + export targets, balanced */
.ts-canon .wyg-doc-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 14px 28px; flex-wrap: wrap;
  padding: 14px clamp(16px,2vw,24px); border-top: 1px solid var(--line); background: var(--surface-2);
}
.ts-canon .wyg-doc-src, .ts-canon .wyg-doc-exp { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ts-canon .wyg-src-chip {
  font-family: var(--f-mono); font-size: 11px; color: var(--ink-3);
  background: var(--surface); border: 1px solid var(--line-2); border-radius: 5px; padding: 4px 8px;
}

/* ── the substance behind the table: the data model + the reconciliation ──
   Two real content panels on the light section (contrast to the dark screen),
   each a dense list with descriptions — not three decorative cards. */
.ts-canon .wyg-detail {
  margin-top: clamp(40px, 5vw, 76px);
  display: grid; grid-template-columns: 1.15fr 1fr; gap: clamp(36px, 5vw, 80px);
  align-items: start;
}
/* shared datum mark — a short mint tick that opens each sub-part (no numbers) */
.ts-canon .wyg-tick { display: block; width: 34px; height: 2px; background: var(--accent-fill); margin-bottom: clamp(14px, 1.6vw, 18px); }
.ts-canon .wyg-panel-h {
  margin: 0; font-family: var(--f-display); font-weight: 600; font-size: clamp(19px, 1.7vw, 23px);
  letter-spacing: -0.02em; color: var(--ink-1);
}
.ts-canon .wyg-panel-sub {
  margin: 12px 0 0; max-width: 46ch; font-size: 14.5px; line-height: 1.6; color: var(--ink-3);
}

/* the data model — a two-column field list, mono field name + description */
/* the data model — a two-col field list; each row is a live hover target
   (subtle well + the field name takes the mint on hover, earned not sprinkled) */
.ts-canon .wyg-fields { margin: clamp(20px, 2.2vw, 28px) 0 0; display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }
.ts-canon .wyg-field {
  padding: 12px 12px; border-radius: 7px;
  transition: background .15s ease, box-shadow .15s ease;
  box-shadow: inset 0 1px 0 var(--line-2);
}
.ts-canon .wyg-field:hover { background: var(--surface-2); box-shadow: inset 0 1px 0 transparent; }
.ts-canon .wyg-field dt { font-family: var(--f-mono); font-size: 12px; font-weight: 600; letter-spacing: 0.02em; color: var(--ink-1); transition: color .15s ease; }
.ts-canon .wyg-field:hover dt { color: var(--accent); }
.ts-canon .wyg-field dd { margin: 5px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-3); }

/* the reconciliation — a check list; the glyph is a quiet bordered box at rest,
   the whole row lights (well + mint glyph) on hover, so it reads alive not dead */
.ts-canon .wyg-checks { list-style: none; margin: clamp(20px, 2.2vw, 28px) 0 0; padding: 0; }
.ts-canon .wyg-check {
  display: flex; gap: 13px; padding: 12px 12px; border-radius: 7px;
  box-shadow: inset 0 1px 0 var(--line-2);
  transition: background .15s ease, box-shadow .15s ease;
}
.ts-canon .wyg-check:first-child { box-shadow: none; }
.ts-canon .wyg-check:hover { background: var(--surface-2); box-shadow: inset 0 1px 0 transparent; }
.ts-canon .wyg-check-mk {
  flex: none; display: grid; place-items: center; width: 21px; height: 21px; margin-top: 1px;
  border-radius: 6px; border: 1px solid var(--line); background: var(--surface); color: var(--ink-4);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.ts-canon .wyg-check:hover .wyg-check-mk { color: var(--accent); border-color: var(--accent-line); background: var(--accent-soft); }
.ts-canon .wyg-check-b { display: flex; flex-direction: column; gap: 3px; }
.ts-canon .wyg-check-t { font-size: 15px; font-weight: 600; color: var(--ink-1); letter-spacing: -0.01em; }
.ts-canon .wyg-check-d { font-size: 13px; line-height: 1.45; color: var(--ink-3); }

/* the handover — every export target, format to system, as a real grid */
/* ── the stack — real vendor marks with room to breathe, grouped reads-from /
   exports-to, in their brand tints (the credibility band industrial buyers want) ── */
.ts-canon .wyg-stack {
  margin-top: clamp(40px, 5vw, 76px); border-top: 1px solid var(--line); padding-top: clamp(32px, 3.6vw, 50px);
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(36px, 5vw, 80px); align-items: start;
}
.ts-canon .wyg-stack-grp { display: flex; flex-direction: column; }
.ts-canon .wyg-stack-k {
  font-family: var(--f-mono); font-size: 12px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-4); margin-bottom: clamp(18px, 2vw, 24px);
}
.ts-canon .wyg-logos { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.ts-canon .wyg-logo-cell {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 13px;
  min-height: 104px; padding: 22px 22px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-2); box-shadow: var(--shadow-1);
  color: var(--intg-tint, var(--ink-2));
  transition: border-color .16s ease, box-shadow .2s ease, transform .2s ease;
}
.ts-canon .wyg-logo-cell:hover { border-color: var(--line); box-shadow: var(--shadow-2); transform: translateY(-2px); }
[data-theme="dark"] .ts-canon .wyg-logo-cell, html.dark .ts-canon .wyg-logo-cell { color: var(--intg-tint-dark, var(--intg-tint, var(--ink-1))); }
.ts-canon .wyg-logo { display: inline-flex; align-items: center; height: 32px; }
.ts-canon .wyg-logo > svg { display: block; max-height: 32px; width: auto; max-width: 158px; }
.ts-canon .wyg-logo-name { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.02em; color: var(--ink-3); }
.ts-canon .wyg-fmt-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
@media (max-width: 980px) { .ts-canon .wyg-stack { grid-template-columns: 1fr; gap: clamp(32px, 7vw, 48px); } }

@media (max-width: 860px) {
  .ts-canon .wyg-detail { grid-template-columns: 1fr; gap: clamp(32px, 8vw, 48px); }
  .ts-canon .wyg-fields { grid-template-columns: 1fr; }
  .ts-canon .wyg-field:nth-child(-n+2) { border-top: 1px solid var(--line-2); }
  .ts-canon .wyg-field:first-child { border-top: 0; }
  .ts-canon .wyg-exp-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
  .ts-canon .wyg-exp-grid { grid-template-columns: 1fr; }
}

/* ───────── Closing section (page finale) ─────────
   Bookends the hero. Deeper cool ground (steps cleanly off the dark Intelligence
   section above and the dark footer below); the register card lifts off it as a
   tinted, light-catching surface, never a flat white box. No marker. */
/* CLOSE — the settled payoff. A LIGHT band (card-vs-bg contrast pass 2026-07-08):
   a deeper cool ground so the register card floats as a bright WHITE, obviously
   elevated panel — crisp, HD, clearly separated. Dark page theme gets its own
   dark-appropriate variant. Dark buttons pop on the light ground. */
.ts-canon .lc-close {
  position: relative; overflow: hidden;
  background-color: #DCE3EE;
  background-image: radial-gradient(130% 80% at 50% -12%, rgba(12,143,97,0.045) 0%, rgba(12,143,97,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), inset 0 16px 32px -26px rgba(15,22,30,0.28);
}
[data-theme="dark"] .ts-canon .lc-close, html.dark .ts-canon .lc-close {
  background-color: #0B0F12;
  background-image: radial-gradient(130% 80% at 50% -12%, rgba(31,106,78,0.10) 0%, rgba(31,106,78,0) 56%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
/* the register card floats as a bright white panel on the cool ground */
.ts-canon .lc-close .lc-ledger {
  background: linear-gradient(180deg, #FFFFFF 0%, #F3F7FC 100%);
  border-color: var(--line);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), var(--shadow-3);
}
[data-theme="dark"] .ts-canon .lc-close .lc-ledger,
html.dark .ts-canon .lc-close .lc-ledger {
  background: linear-gradient(180deg, #262F34 0%, #1B2126 100%); border-color: rgba(236,239,237,0.24);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.10), 0 34px 70px -30px rgba(0,0,0,0.78);
}

.ts-canon .lc-close-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.78fr);
  gap: clamp(34px, 5vw, 88px);
  align-items: center;
}
.ts-canon .lc-close-copy {
  display: flex; flex-direction: column; align-items: flex-start; gap: 20px;
}
.ts-canon .lc-close-datum {
  width: 72px; height: 3px; border-radius: 999px;
  background: linear-gradient(90deg, var(--ink-3) 0 50%, var(--accent-fill) 50% 100%);
}
.ts-canon .lc-close-title {
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(32px, 3.6vw, 52px); letter-spacing: -0.035em;
  line-height: 1.02; color: var(--ink-1); margin: 0;
}
.ts-canon .lc-close-lede {
  font-size: clamp(16px, 1.4vw, 19px); color: var(--ink-2);
  line-height: 1.6; margin: 0; max-width: 48ch;
}
.ts-canon .lc-close-cta {
  display: flex; align-items: center; gap: 22px; margin-top: 6px;
  flex-wrap: wrap;
}
/* a real outline button, not a bare text link (2026-06-22). */
.ts-canon .lc-close-talk {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14.5px; font-weight: 500; color: var(--ink-1);
  padding: 13px 20px; border-radius: var(--r-md);
  border: 1px solid var(--line-strong); background: var(--surface);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.ts-canon .lc-close-talk svg { color: var(--ink-4); transition: color .15s ease, transform .15s ease; }
.ts-canon .lc-close-talk:hover { color: var(--accent-2); border-color: var(--accent); background: var(--surface-2); }
.ts-canon .lc-close-talk:hover svg { color: var(--accent); transform: translateX(2px); }

/* the settled register card — matches .cp-result, with a mint datum on the
   header to read as "reviewed" and the resolved row marked. */
.ts-canon .lc-ledger {
  border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden;
  background: linear-gradient(180deg, #F8FBFE 0%, #EEF3F9 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 28px 60px -42px rgba(15,22,30,0.32), 0 8px 20px -16px rgba(15,22,30,0.15);
}
[data-theme="dark"] .ts-canon .lc-ledger,
html.dark .ts-canon .lc-ledger { background: linear-gradient(180deg, #232B30 0%, #1A2024 100%); border-color: rgba(236,239,237,0.20); box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), 0 26px 54px -32px rgba(0,0,0,0.72); }
.ts-canon .lc-ledger-h {
  position: relative; display: flex; align-items: baseline; gap: 10px;
  padding: 13px 15px; border-bottom: 1px solid var(--line); background: var(--surface-2);
  font-family: var(--f-mono);
}
[data-theme="dark"] .ts-canon .lc-ledger-h,
html.dark .ts-canon .lc-ledger-h { background: var(--surface-3); }
.ts-canon .lc-ledger-h::before {
  content: ""; position: absolute; left: 0; top: -1px; width: 44px; height: 2px;
  background: var(--accent-fill);
}
.ts-canon .lc-ledger-h .ll-title { font-size: 11.5px; font-weight: 700; letter-spacing: 0.2em; color: var(--ink-1); }
.ts-canon .lc-ledger-h .ll-state { font-size: 11px; letter-spacing: 0.03em; color: var(--ink-3); margin-left: auto; }
.ts-canon .lc-ledger-rows { display: flex; flex-direction: column; }
.ts-canon .ll-row {
  display: grid; grid-template-columns: 5.4em 1fr 1.3em; align-items: center;
  gap: 12px; padding: 12px 15px; border-top: 1px solid var(--line-2);
}
.ts-canon .ll-row:first-child { border-top: 0; }
.ts-canon .ll-row .ll-tag { font-family: var(--f-mono); font-weight: 600; font-size: 12.5px; color: var(--ink-1); letter-spacing: 0.01em; }
.ts-canon .ll-row .ll-meta { font-size: 13px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-canon .ll-row .ll-mk { font-family: var(--f-mono); font-size: 12px; font-weight: 700; color: var(--accent); text-align: right; }

@media (max-width: 860px) {
  .ts-canon .lc-close-grid { grid-template-columns: 1fr; gap: clamp(30px, 7vw, 44px); }
}
@media (max-width: 560px) {
  .ts-canon .lc-close-cta { width: 100%; }
  .ts-canon .lc-close-cta .btn { flex: 1 1 auto; justify-content: center; }
}

