/* marketing.css — the MoodOrbit/marketing home page CSS layer (.mk-* + .mo-*).
   SINGLE SOURCE OF TRUTH. Served live from Public/ in dev (edit → refresh, no rebuild) and as a
   versioned static file in prod. Extracted from MarketingPageRenderer's former mkCSS+moCSS constants
   (2026-07-07). Loads AFTER oo-tokens.css and BEFORE the inline LandingPage/SiteNav layer — cascade-safe:
   .mk-/.mo- are disjoint from .ln-/.oo-, and the lone .ln-section rule sets a different property. */

/* ============================== mk layer (nav / badges / footer / CTA) ============================== */
    html{scroll-behavior:smooth;scroll-padding-top:5rem;}   /* offset the fixed .ln-header so anchored sections land below it */
    @media(prefers-reduced-motion:reduce){html{scroll-behavior:auto;}}
    .ln-section{scroll-margin-top:84px;}
    /* vertical padding so the header (and its CTA button) isn't cramped against the bottom hairline. */
    /* min-height: the CTA pill is taller than the text row — without it the pill touches the viewport top
       (FIX-16) and any nav wrap overflows the bar instead of growing it (FIX-1). */
    .mk-header-wrap{display:flex;align-items:center;justify-content:space-between;gap:var(--oo-space-md);padding-block:var(--oo-space-sm);position:relative;min-height:52px;box-sizing:border-box;}
    .mk-brand{display:inline-flex;align-items:center;gap:.5rem;font-weight:800;letter-spacing:-.01em;text-decoration:none;color:var(--oo-text-primary);font-size:1.15rem;}
    /* One line at every width — same contract as the event header's `.ln-brand` (Didier 2026-07-27).
       fit-brand.js shrinks the span to the room actually available; the clamp is the no-JS floor. */
    .mk-brand{min-width:0;}
    /* generous vw term — fit-brand.js only shrinks, so a stingy clamp pins the name small where it fits */
    .mk-brand>span{white-space:nowrap;font-size:clamp(.82rem,4.6vw,1.15rem);display:block;}
    /* brand mark before the name — exported from the brand-logo SSOT (sync-brand-logos) */
    .mk-brand__logo{width:26px;height:26px;display:block;flex:none;}
    /* ship both themes; show the one that reads on the current surface */
    .mk-brand__logo--dark{display:none;}
    @media(prefers-color-scheme:dark){
      .mk-brand__logo--light{display:none;}
      .mk-brand__logo--dark{display:block;}
    }
    .mk-actions{display:flex;align-items:center;gap:var(--oo-space-md);min-width:0;}
    @media(max-width:480px){ .mk-header-wrap{gap:var(--oo-space-sm);} }
    /* The nav-CTA small-screen rules live further down, AFTER `.mk-actions .mk-nav-cta` — they need that
       same (0,2,0) compound and a later position to win. See the note there. */
    .mk-nav{display:flex;align-items:center;gap:var(--oo-space-md);flex-wrap:wrap;}
    /* Pure-CSS hamburger (NO JS): desktop → the details is transparent (`display:contents`) so the links sit
       inline and the burger is hidden; mobile (below) → the burger shows and the links drop as a panel. */
    .mk-navburger{display:none;}   /* desktop: no hamburger — the nav (a sibling) shows inline via .mk-nav */
    .mk-burger{display:none;flex-direction:column;justify-content:center;align-items:center;gap:5px;width:42px;height:42px;cursor:pointer;list-style:none;border-radius:var(--oo-radius-md);}
    .mk-burger::-webkit-details-marker{display:none;}
    .mk-burger:hover{background:var(--oo-surface-accent-container);}
    .mk-burger__bar{display:block;width:22px;height:2px;border-radius:2px;background:var(--oo-text-primary);transition:transform var(--oo-motion-fast) ease, opacity var(--oo-motion-fast) ease;}
    .mk-navburger[open] .mk-burger__bar:nth-child(1){transform:translateY(7px) rotate(45deg);}
    .mk-navburger[open] .mk-burger__bar:nth-child(2){opacity:0;}
    .mk-navburger[open] .mk-burger__bar:nth-child(3){transform:translateY(-7px) rotate(-45deg);}
    /* Plain nav links only. EXCLUDE any anchor carrying an `oo-surface-*` pairing (the CTA button): that
       utility owns BOTH its background AND its paired on-color, and this nav-link color (light-on-dark-header)
       would otherwise win by specificity (0,1,1 > the utility's 0,1,0) and paint the button's text the
       light-gray link color on its light accent fill — an illegible ~1:1 CTA. Guarded by verify-contrast.mjs. */
    .mk-nav>a:not([class*="oo-surface-"]){text-decoration:none;color:var(--oo-text-secondary);font-weight:600;font-size:.95rem;}
    .mk-nav>a:not([class*="oo-surface-"]):hover{color:var(--oo-text-primary);}
    .mk-nav-cta{font-size:.9rem;}
    /* compound selector (0,2,0): the base .ln-cta padding is declared LATER (inline <style> after this
       stylesheet) and a bare .mk-nav-cta ties with it — the padding silently lost the cascade (sweep-2). */
    .mk-actions .mk-nav-cta{padding:.62rem 1.1rem;min-height:44px;display:inline-flex;align-items:center;}
    /* ── Small-screen nav CTA. These MUST be (0,2,0) compounds placed after the rules above, for the
         cascade reason already documented on `.mk-actions .mk-nav-cta`: the CTA also carries `.ln-cta`,
         which is declared in the INLINE <style> that ships AFTER this stylesheet, so a bare
         `.mk-nav-cta{…}` ties on specificity and loses on order. Written the obvious way first, all
         three of these silently did nothing (2026-07-27 audit fix, caught by re-measuring). ──
       ≤480: "Request early access" needed 185px in 147px of room and rendered cut off at the edge.
       ≤360: brand + burger + CTA cannot coexist legibly, so the CTA yields — it duplicates the hero
       CTA just below it, and squeezing all three only produces unreadable, un-tappable slivers. */
    @media(max-width:480px){ .mk-actions .mk-nav-cta{padding:.55rem .8rem;font-size:.8rem;} }
    @media(max-width:360px){ .mk-actions .mk-nav-cta{display:none;} }
    .mk-menu{position:relative;}
    /* Structural props for ALL menu summaries; the COLOR/size only for plain (non-button) summaries. A summary
       carrying an oo-surface-* pairing (the CTA-as-dropdown button) keeps its OWN paired on-color — same
       cascade guard as the nav-CTA fix, so the dropdown button never goes light-on-light. */
    .mk-menu>summary{cursor:pointer;list-style:none;}
    .mk-menu>summary:not([class*="oo-surface-"]){color:var(--oo-text-secondary);font-weight:600;font-size:.95rem;}
    .mk-menu>summary::-webkit-details-marker{display:none;}
    .mk-menu>summary::after{content:" \\25BE";}
    .mk-menu[open]>summary:not([class*="oo-surface-"]){color:var(--oo-text-primary);}
    .mk-menu ul{position:absolute;top:calc(100% + var(--oo-space-xs));right:0;margin:0;padding:var(--oo-space-xs);list-style:none;background:var(--oo-surface-surface-raised);color:var(--oo-on-surface-surface-raised);border:1px solid var(--oo-border-subtle);border-radius:var(--oo-radius-md);box-shadow:0 14px 36px rgba(0,0,0,.20);min-width:230px;max-width:calc(100vw - 2*var(--oo-space-lg));z-index:60;}
    .mk-menu li a{display:block;padding:var(--oo-space-sm);border-radius:var(--oo-radius-sm);white-space:nowrap;text-decoration:none;color:inherit;font-weight:600;font-size:.92rem;}
    .mk-menu li a:hover,.mk-menu li a:focus{background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);outline:none;}
    /* CTA-as-dropdown: the summary is the accent button (its .oo-surface-accent-solid pairing supplies the
       legible fill + on-color). A future/unavailable destination (empty href) is a disabled "Soon" row. */
    .mk-cta-menu ul{min-width:210px;}
    .mk-menu-soon{display:flex;align-items:center;justify-content:space-between;gap:var(--oo-space-sm);padding:var(--oo-space-sm);color:var(--oo-text-secondary);font-weight:600;font-size:.92rem;cursor:default;}
    .mk-soon-badge{flex:none;font-size:.62rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:2px 7px;border-radius:var(--oo-radius-full);background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);}
    .mk-center{text-align:center;}
    .mk-center .ln-cta{margin-inline:auto;}
    /* Real-product screenshot strip: horizontal phone-width scroll on mobile (snap), 3-up grid on desktop.
       Layout-only — every color/radius/space value is a token. */
    .mk-shots{display:grid;grid-auto-flow:column;grid-auto-columns:min(72vw,300px);gap:var(--oo-space-lg);overflow-x:auto;padding-bottom:var(--oo-space-sm);-webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;margin-top:var(--oo-space-lg);}
    @media(min-width:760px){.mk-shots{grid-auto-flow:row;grid-auto-columns:unset;grid-template-columns:repeat(3,minmax(0,1fr));overflow-x:visible;}}
    .mk-shot{margin:0;scroll-snap-align:start;}
    .mk-shot img{width:100%;height:auto;border-radius:var(--oo-radius-lg);border:1px solid var(--oo-border-subtle);display:block;box-shadow:0 12px 32px rgba(0,0,0,.18);}
    .mk-shot figcaption{color:var(--oo-text-secondary);font-size:.9rem;line-height:1.45;margin-top:var(--oo-space-sm);max-width:36ch;}
    .mk-cta-sub{color:var(--oo-text-secondary);margin:0 auto var(--oo-space-md);max-width:52ch;}
    .mk-cta-note{color:var(--oo-text-secondary);font-size:.85rem;margin:var(--oo-space-sm) auto 0;max-width:52ch;}
    .ln-hero .mk-eyebrow{margin-bottom:var(--oo-space-sm);}
    .mk-intro{color:var(--oo-text-secondary);max-width:64ch;margin:0 0 var(--oo-space-lg);font-size:1.05rem;line-height:1.55;}
    .mk-link{color:var(--ln-accent,var(--oo-surface-accent-solid));font-weight:600;text-decoration:underline;}
    .mk-note{color:var(--oo-text-secondary);font-size:.85rem;margin-top:var(--oo-space-md);}
    .mk-badge{display:inline-block;background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);font-size:.68rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:2px 8px;border-radius:var(--oo-radius-full);margin-left:8px;vertical-align:middle;}
    .mk-platform{text-decoration:none;color:inherit;display:block;}
    .mk-platform:hover{border-color:var(--oo-border-strong);}
    .mk-eyebrow{color:var(--ln-accent,var(--oo-surface-accent-solid));font-weight:700;font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;margin:0 0 var(--oo-space-xs);}
    .mk-form{max-width:420px;margin-inline:auto;}
    /* Required marking — same contract as the event forms (2026-08-04). */
    .ln-req{color:var(--oo-surface-status-error);font-weight:700;}
    .ln-form__req-note{margin:0 0 var(--oo-space-md);font-size:.85rem;color:var(--oo-text-secondary);font-weight:600;}
    .ln-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}
    .mk-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}
    .mk-disclaimer{color:var(--oo-text-secondary);font-size:.8rem;max-width:70ch;margin:0 auto var(--oo-space-md);}
    .mk-footer-legal{margin-bottom:var(--oo-space-sm);}
    .mk-footer-legal a{color:var(--oo-text-secondary);text-decoration:none;margin-right:var(--oo-space-md);font-size:.85rem;}
    .mk-footer-legal a:hover{color:var(--oo-text-primary);}
    @media(max-width:949px){
      /* single row: brand + [hamburger, CTA]; the nav LINKS collapse behind the burger (opened on tap).
         949px (was 680): 5 links don't fit one row until ~920 (MoodOrbit) / ~950 (TrueAlign) — between
         680 and 950 the nav wrapped to a second row and bled over page content (FIX-1). */
      .mk-header-wrap{flex-wrap:nowrap;}
      .mk-navburger{display:block;}
      .mk-burger{display:flex;}
      .mk-nav{display:none;}
      .mk-navburger[open] ~ .mk-nav{display:flex;flex-direction:column;align-items:stretch;gap:2px;
        position:absolute;top:calc(100% + var(--oo-space-xs));right:var(--oo-space-lg);left:auto;min-width:230px;max-width:calc(100vw - 2*var(--oo-space-lg));z-index:60;
        background:var(--oo-surface-surface-raised);color:var(--oo-on-surface-surface-raised);
        border:1px solid var(--oo-border-subtle);border-radius:var(--oo-radius-md);box-shadow:0 14px 36px rgba(0,0,0,.22);padding:var(--oo-space-xs);font-size:.98rem;}
      .mk-navburger[open] ~ .mk-nav > a{display:block;padding:var(--oo-space-sm) var(--oo-space-md);border-radius:var(--oo-radius-sm);color:var(--oo-text-primary);font-weight:600;}
      .mk-navburger[open] ~ .mk-nav > a:hover,.mk-navburger[open] ~ .mk-nav > a:focus{background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);outline:none;}
      .ln-section{scroll-margin-top:84px;}
    }

/* ============================== mo layer (orbit hero / sections / QoL) ============================== */
    .mo-wrap{max-width:1120px;margin:0 auto;padding:0 var(--oo-space-lg);}
    .mo-eyebrow{text-transform:uppercase;letter-spacing:.1em;font-size:.72rem;font-weight:700;color:var(--oo-surface-accent-solid);margin:0 0 var(--oo-space-sm);}
    .mo-h2{font-weight:800;font-size:clamp(1.6rem,3.6vw,2.3rem);line-height:1.14;letter-spacing:-.01em;color:var(--oo-text-primary);margin:0 0 var(--oo-space-md);}
    .mo-lead{font-size:1.1rem;color:var(--oo-text-secondary);margin:0 auto;}
    .mo-center{text-align:center;max-width:46ch;margin-inline:auto;}
    .mo-section{padding:var(--oo-space-xl) 0;scroll-margin-top:84px;}   /* xxl→xl: kill the dead air between pillars; scroll-margin so anchors clear the sticky header */
    .mo-section--tint{background:color-mix(in srgb,var(--oo-surface-accent-container) 40%,var(--oo-surface-surface-base));}
    /* Section delineation (Didier 2026-07-16): a hairline between adjacent sections (universal) + a subtle
       tint on the alternating media-left benefit rows, so each pillar reads as its own block. */
    .mo-section + .mo-section{border-top:1px solid var(--oo-border-subtle);}
    .mo-section:has(.mo-feature--left){background:color-mix(in srgb,var(--oo-surface-accent-container) 15%,transparent);}
    /* The 15% tint vanishes on light surfaces — light mode needs a stronger mix to keep the delineation. */
    @media(prefers-color-scheme:light){
      .mo-section:has(.mo-feature--left){background:color-mix(in srgb,var(--oo-surface-accent-container) 35%,transparent);}
    }
    /* hero */
    .mo-hero{position:relative;overflow:hidden;}
    .mo-hero::before{content:"";position:absolute;inset:0;z-index:0;opacity:.9;
      background:radial-gradient(60% 55% at 72% 30%, var(--oo-surface-accent-container), transparent 70%),
                 radial-gradient(50% 50% at 20% 85%, color-mix(in srgb,var(--oo-surface-accent-solid) 22%,transparent), transparent 70%);}
    /* horizontal padding = the page wrap gutter (was 0 → text clipped at the left edge on mobile). */
    .mo-hero__inner{position:relative;z-index:1;display:grid;grid-template-columns:1fr;gap:var(--oo-space-xl);align-items:center;padding:var(--oo-space-xxl) var(--oo-space-lg);min-height:86svh;
      padding-top:calc(var(--oo-space-xxl) + 3.5rem);}   /* clear the FIXED frosted nav — .mo-hero is not .ln-section.ln-hero, so the shared clearance never applies (FIX-2) */
    @media(min-width:700px){.mo-hero__inner{padding-inline:var(--oo-space-xl);}}
    @media(min-width:900px){.mo-hero__inner{grid-template-columns:1.05fr .95fr;gap:var(--oo-space-xxl);}}
    .mo-hero__title{font-weight:800;font-size:clamp(2.2rem,6vw,3.6rem);line-height:1.08;letter-spacing:-.02em;margin:0 0 var(--oo-space-md);max-width:15ch;color:var(--oo-text-primary);}
    .mo-hero__sub{font-size:clamp(1.05rem,2.2vw,1.22rem);color:var(--oo-text-secondary);max-width:48ch;margin:0 0 var(--oo-space-lg);}
    .mo-cta{display:inline-block;text-decoration:none;border-radius:var(--oo-radius-full);padding:.85rem 1.6rem;font-weight:700;font-size:1.02rem;
      background:var(--oo-surface-accent-solid);color:var(--oo-on-surface-accent-solid);
      box-shadow:0 10px 30px color-mix(in srgb,var(--oo-surface-accent-solid) 40%,transparent);transition:transform var(--oo-motion-fast) ease;}
    .mo-cta:hover{transform:translateY(-2px);}
    .mo-cta-note{font-size:.85rem;color:var(--oo-text-secondary);margin:var(--oo-space-sm) 0 0;}
    /* Closing CTA: a faint radial glow (same accent language as the hero) so the bookend has a climax
       instead of bare text on flat ground (adversarial 2026-07-16). Token-only; paints behind the content. */
    /* The branded 404/500 page is deliberately short: one heading, one line, one link. Measured at a
       1280x860 viewport it came to 519px of content in an 860px document, leaving 341px of dead space
       BELOW the footer — which reads as a half-rendered page on the one surface whose whole job is to
       look deliberate. `:has()` scopes the sticky-footer layout to error pages only, so no other
       marketing page's vertical rhythm moves, and it adapts to each brand's own footer height instead
       of hardcoding one (the three disclaimers differ in length). Browsers without `:has()` simply keep
       the old harmless mid-page footer. `svh` so mobile browser chrome does not overshoot.
       COLUMN axis on `main`, not row: as a row the section became a flex item that shrank to its
       content width and the whole card drifted left of centre. Column keeps the default `stretch`
       cross-axis sizing (full width, so `.mk-center` still centres the text) while
       `justify-content:center` does the vertical centring. */
    html:has(.mk-error-section) body{min-height:100svh;display:flex;flex-direction:column;}
    html:has(.mk-error-section) main{flex:1 0 auto;display:flex;flex-direction:column;justify-content:center;}
    .mk-cta-section{position:relative;overflow:hidden;}
    .mk-cta-section::before{content:"";position:absolute;inset:0;pointer-events:none;
      background:radial-gradient(60% 80% at 50% 110%,color-mix(in srgb,var(--oo-surface-accent-solid) 16%,transparent),transparent 70%);}
    .mk-cta-section>*{position:relative;}
    .mo-trust{font-size:.8rem;color:var(--oo-text-secondary);margin:var(--oo-space-md) 0 0;opacity:.85;}
    /* orbit stage: grid pile; radii scale with the stage so the composition holds at any size */
    .mo-orbit{position:relative;z-index:1;display:grid;place-items:center;--stage:min(84vw,470px);--r-inner:calc(var(--stage) * .2175);--r-mid:calc(var(--stage) * .3175);--r-outer:calc(var(--stage) * .4175);width:var(--stage);aspect-ratio:1;margin:0 auto;}
    .mo-orbit>*{grid-area:1/1;}
    /* the hero TEXT sits above the orbit, so out-of-orbit feelings drift BEHIND it (z-index behind text). */
    .mo-hero__copy{position:relative;z-index:2;}
    /* a soft translucent scrim sits BEHIND the text (over the drifting feelings) so the copy stays legible
       even when a feeling floats behind it — blurred + dimmed, edges masked so it isn't a hard box. */
    .mo-hero__copy::before{content:"";position:absolute;z-index:-1;
      inset:calc(-1 * var(--oo-space-lg)) -1.4rem;border-radius:var(--oo-radius-lg);   /* was -space-md (16px): text sat too close to the panel edge on phones */
      background:color-mix(in srgb, var(--oo-surface-surface-base) 58%, transparent);
      -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(3px);
      -webkit-mask:radial-gradient(130% 92% at 30% 46%, #000 58%, transparent 100%);
              mask:radial-gradient(130% 92% at 30% 46%, #000 58%, transparent 100%);}
    .mo-orbit.mo-dragging{z-index:5;}                            /* …except a held feeling comes to the front */
    .mo-orbit--live .mo-token{cursor:grab;touch-action:none;}   /* tap/drag a feeling in or out of orbit */
    .mo-token.mo-grabbing{cursor:grabbing;}
    .mo-orbit__glow{width:78%;height:78%;border-radius:50%;justify-self:center;align-self:center;filter:blur(6px);
      background:radial-gradient(circle at 50% 45%, color-mix(in srgb,var(--oo-surface-accent-solid) 34%,transparent), transparent 62%);}
    .mo-orbit__rings{width:100%;height:100%;}
    .mo-orbit__rings circle{fill:none;stroke:var(--oo-border-subtle);stroke-width:1.2;opacity:.55;}
    .mo-orbit__rings .dash{stroke-dasharray:none;opacity:.55;}   /* outer ring is SOLID, like the other two */
    .mo-ring{position:relative;width:100%;height:100%;}
    .mo-ring--inner{--radius:var(--r-inner);}
    .mo-ring--mid{--radius:var(--r-mid);}
    .mo-ring--outer{--radius:var(--r-outer);}
    .mo-token{position:absolute;top:50%;left:50%;--angle:calc(360deg / var(--total) * var(--i) + var(--offset,0deg));
      transform:translate(-50%,-50%) rotate(var(--angle)) translate(var(--radius)) rotate(calc(-1 * var(--angle)));}
    .mo-token__inner{display:grid;place-items:center;}
    /* each face is a pill; a swap token stacks two faces (grid pile) that cross-fade — one feeling drifting
       out of orbit as another drifts in. Valence tints the pill subtly (emoji carries the real signal). */
    .mo-token__face{grid-area:1/1;display:flex;align-items:center;gap:.42em;padding:.28em .72em;border-radius:var(--oo-radius-full);white-space:nowrap;font-size:.78rem;font-weight:600;
      color:var(--oo-text-primary);border:1px solid var(--oo-border-subtle);backdrop-filter:blur(3px);box-shadow:0 4px 14px rgba(0,0,0,.14);
      background:color-mix(in srgb,var(--oo-surface-surface-raised) 84%, transparent);}
    .mo-tv--up{background:color-mix(in srgb, #e8b866 15%, var(--oo-surface-surface-raised));}
    .mo-tv--down{background:color-mix(in srgb, #8296c4 15%, var(--oo-surface-surface-raised));}
    .mo-tv--mid{background:color-mix(in srgb, #b79bd6 15%, var(--oo-surface-surface-raised));}
    .mo-emoji{font-size:1.05em;line-height:1;}
    .mo-token__face--b{opacity:0;display:none;}
    /* "You" is a SPHERE: radial highlight up-left, body in the brand accent, shaded rim down-right. */
    .mo-you{position:relative;display:grid;place-items:center;width:19%;height:19%;border-radius:50%;color:var(--oo-on-surface-accent-solid);font-weight:800;font-size:1rem;letter-spacing:.02em;text-align:center;line-height:1.12;
      background:radial-gradient(circle at 31% 27%,
        color-mix(in srgb,#ffffff 88%,var(--oo-surface-accent-solid)) 0%,
        color-mix(in srgb,#ffffff 38%,var(--oo-surface-accent-solid)) 22%,
        var(--oo-surface-accent-solid) 58%,
        color-mix(in srgb,#000000 42%,var(--oo-surface-accent-solid)) 100%);
      box-shadow:0 12px 36px color-mix(in srgb,var(--oo-surface-accent-solid) 45%,transparent),
                 inset -10px -12px 26px rgba(0,0,0,.38),
                 inset 7px 9px 18px rgba(255,255,255,.20);}
    /* A MULTI-WORD centre label ("Your Brand" on the sponsor pages) wraps, and the inherited
   text-align:start left-aligned the lines against each other inside a box that is already
   centred — the block read as off-centre in the sphere. Centre the lines, hug them, and keep
   them off the rim of the circle. Single-word "You" is unaffected. */
    .mo-you__label{position:relative;z-index:3;text-shadow:0 1px 6px rgba(0,0,0,.35);
      max-width:84%;text-align:center;text-wrap:balance;}
    @media(prefers-reduced-motion:no-preference){
      .mo-orbit__glow{animation:moBreath 7s ease-in-out infinite;}
      /* "You" — a prominent pulse (scale + a breathing accent glow via drop-shadow, not clipped). */
      .mo-you{animation:moYouPulse 3.4s ease-in-out infinite;}
      /* static fallback: the three lanes co-rotate at Kepler-ish speeds (inner fastest, all one direction) */
      .mo-ring--inner{animation:moSpin 26s linear infinite;}
      .mo-ring--inner .mo-token__inner{animation:moSpin 26s linear infinite reverse;}
      .mo-ring--mid{animation:moSpin 42s linear infinite;}
      .mo-ring--mid .mo-token__inner{animation:moSpin 42s linear infinite reverse;}
      .mo-ring--outer{animation:moSpin 64s linear infinite;}
      .mo-ring--outer .mo-token__inner{animation:moSpin 64s linear infinite reverse;}
    }
    @keyframes moSpin{to{transform:rotate(360deg);}}
    @keyframes moBreath{0%,100%{transform:scale(1);}50%{transform:scale(1.045);}}
    /* You: a prominent scale pulse + a breathing accent glow (drop-shadow follows the sphere, not clipped). */
    @keyframes moYouPulse{
      0%,100%{transform:scale(1);    filter:drop-shadow(0 0 5px  color-mix(in srgb,var(--oo-surface-accent-solid) 45%,transparent));}
      50%    {transform:scale(1.055);filter:drop-shadow(0 0 22px color-mix(in srgb,var(--oo-surface-accent-solid) 85%,transparent));}}
    @media(max-width:899px){
      .mo-orbit{--stage:min(90vw,400px);margin-top:var(--oo-space-xl);}
      .mo-ring--outer{display:none;}
      .mo-token__face{font-size:.72rem;padding:.24em .6em;}
    }
    /* STATIC fallback (no-JS / reduced-motion) shows a THINNED set — all 22 pills at rest overlap; hiding
       alternates keeps the three lanes legible. The live sim un-hides and manages visibility itself. */
    .mo-orbit:not(.mo-orbit--live) .mo-ring--outer .mo-token:nth-child(even){display:none;}
    .mo-orbit:not(.mo-orbit--live) .mo-ring--mid .mo-token:nth-child(3n){display:none;}
    /* LIVE: /js/orbit.js (the three-lane planetary sim) controls each token's transform/opacity/z-index per
       frame. Disable the CSS static-orbit spin + positioning and hand over; JS manages which tokens show, so
       un-hide the outer ring here (the mobile display:none is a no-JS-only rule). The guide rings get the
       SAME tilted-plane squash the sim projects with (scaleY .42) → circles become the orbit ellipses. */
    .mo-orbit--live .mo-ring{animation:none !important;transform:none !important;}
    .mo-orbit--live .mo-ring--outer{display:block !important;}
    .mo-orbit--live .mo-orbit__rings{transform:scaleY(.55);}
    .mo-orbit--live .mo-orbit__rings circle{opacity:.75;stroke:color-mix(in srgb,var(--oo-surface-accent-solid) 38%,var(--oo-border-subtle));stroke-width:1.4;}
    .mo-orbit--live .mo-orbit__rings .dash{opacity:.75;}
    .mo-orbit--live .mo-token{transition:none;will-change:transform,opacity;}
    .mo-orbit--live .mo-token__inner{animation:none !important;transform:none !important;}
    .mo-orbit--live .mo-token__face{box-shadow:0 7px 20px rgba(0,0,0,.24);}
    /* ORBITING feelings are accent-tinted + accent-bordered so they clearly stand out; NON-orbiting (drifting)
       feelings are a muted neutral. JS toggles `.mo-in` / `.mo-out` as a feeling enters or leaves orbit. */
    .mo-orbit--live .mo-token.mo-in .mo-token__face{background:color-mix(in srgb, var(--oo-surface-accent-solid) 34%, var(--oo-surface-surface-raised));border-color:color-mix(in srgb, var(--oo-surface-accent-solid) 62%, var(--oo-border-subtle));}
    .mo-orbit--live .mo-token.mo-out .mo-token__face{background:color-mix(in srgb, #000000 24%, var(--oo-surface-surface-raised));border-color:var(--oo-border-subtle);}
    /* pillars (you-at-the-centre): reuse the shared `pillars` type but force a 3-up on this section */
    @media(min-width:760px){#center .ln-grid-2{grid-template-columns:repeat(3,1fr);}}
    #center .ln-card{border:0;background:transparent;text-align:center;}
    .mo-band .mo-lead{max-width:42ch;}
    /* steps */
    .mo-steps{display:grid;grid-template-columns:1fr;gap:var(--oo-space-xl);margin-top:var(--oo-space-xl);}
    @media(min-width:760px){.mo-steps{grid-template-columns:repeat(3,1fr);}}
    .mo-step{text-align:center;}
    .mo-step__marker{width:64px;height:64px;margin:0 auto var(--oo-space-md);position:relative;display:grid;place-items:center;}
    .mo-step__marker svg{position:absolute;inset:0;width:100%;height:100%;}
    .mo-step__marker span{position:relative;font-weight:800;color:var(--oo-surface-accent-solid);font-size:1.1rem;}
    .mo-step h3{margin:0 0 var(--oo-space-xs);color:var(--oo-text-primary);}
    .mo-step p{margin:0 auto;color:var(--oo-text-secondary);max-width:28ch;}
    /* zigzag benefit feature */
    .mo-feature{display:grid;grid-template-columns:1fr;gap:var(--oo-space-xl);align-items:center;padding:var(--oo-space-md) 0;}   /* xl→md: rows were floating in a void */
    /* GRID BLOWOUT GUARD: a `1fr` track is `minmax(auto,1fr)`, so its minimum is the child's
       MIN-CONTENT width. The pillar visuals carry wide intrinsic minimums (card grids, priced rows),
       which pushed the whole column past the viewport on phones and made every "available width"
       measurement read back the inflated value. `min-width:0` lets the track take its fr share, and
       the still then scales into it. */
    .mo-feature__media,.mo-feature__body{min-width:0;}
    @media(min-width:820px){.mo-feature{grid-template-columns:1fr 1fr;gap:var(--oo-space-xxl);}
      .mo-feature__media{order:2;}.mo-feature--left .mo-feature__media{order:0;}.mo-feature--left .mo-feature__body{order:1;}}
    .mo-feature__eyebrow{text-transform:uppercase;letter-spacing:.09em;font-size:.72rem;font-weight:700;color:var(--oo-surface-accent-solid);margin:0 0 var(--oo-space-xs);}
    .mo-feature h3,.mo-feature .mo-feature__h{font-weight:800;font-size:clamp(1.4rem,3vw,2rem);line-height:1.15;margin:0 0 var(--oo-space-sm);color:var(--oo-text-primary);}
    .mo-feature p{color:var(--oo-text-secondary);font-size:1.05rem;margin:0 0 var(--oo-space-sm);max-width:46ch;}
    .mo-badge{display:inline-block;font-size:.66rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:2px 8px;border-radius:var(--oo-radius-full);
      background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);margin-left:8px;vertical-align:middle;}
    .mo-feature__media img{width:100%;height:auto;border-radius:var(--oo-radius-xl);border:1px solid var(--oo-border-subtle);box-shadow:0 20px 50px rgba(0,0,0,.22);}
    /* ── Pillar UI illustrations (device-only, transparent PNG->webp, one per theme).
         These are DEVICE SHOTS, not cards: no frame, no radius, no shadow of ours — the render already
         carries the phone's own rounded body and drop shadow inside its alpha, so a border here would
         box the transparency. Capped in height and centred so a tall 9:19.5 device does not tower over
         the copy column, and matched to the theme via the OG-card mechanism (see the renderer). */
    .mo-feature__shot{display:block;width:100%;max-width:340px;margin-inline:auto;
      aspect-ratio:520/892;background-size:contain;background-position:center;background-repeat:no-repeat;}
    .mo-feature__shot-img{width:100%;height:100%;object-fit:contain;
      border:0 !important;border-radius:0 !important;box-shadow:none !important;}
    @media(prefers-color-scheme:light){
      .mo-feature__shot{background-image:var(--oo-shot-light);}
      .mo-feature__shot-img{display:none;}}
    /* ── Window UI illustrations (TrueAlign, 2026-07-29). Same theme-swap mechanism as the pillar
         shots above and the OG cards: ONE <img> carries the dark render, the light URL rides the
         wrapper as `--oo-shot-light` and is painted as a background, so exactly one asset downloads
         per theme. A second <img> toggled by display would never fetch while display:none.
         Brand-NEUTRAL name on purpose — `.mo-*` reads as MoodOrbit, and these are TrueAlign's; the
         aspect differs too (a landscape window, not a 9:19.5 device), so it cannot just reuse it.
         No frame/radius/shadow of ours: the render carries the window's own rounding and drop shadow
         inside its alpha, and a border here would draw a box around the transparency. */
    .oo-shot{display:block;width:100%;max-width:1160px;margin-inline:auto;
      aspect-ratio:var(--oo-shot-aspect,1160/629);
      background-size:contain;background-position:center;background-repeat:no-repeat;}
    .oo-shot-img{width:100%;height:100%;object-fit:contain;
      border:0 !important;border-radius:0 !important;box-shadow:none !important;}
    @media(prefers-color-scheme:light){
      .oo-shot{background-image:var(--oo-shot-light);}
      .oo-shot-img{display:none;}}
    /* ── Audience switch (TrueAlign #marketplaces, 2026-07-30) ─────────────────────────────
       Two readers, one section: a customer who wants work done and an expert who sells judgment.
       The two-sided-marketplace research is blunt that a single blended tone "bores the consumer and
       patronises the vendor", so each side gets its own headline, its own body and its own visual,
       and only ONE is on screen at a time. That is what makes serving both cost almost no length.

       CSS-ONLY, by necessity: the marketing CSP is `script-src 'none'`, so there is no JS to hang a
       tab on. Hidden radios + `:checked` sibling selectors do the whole job. The radios stay in the
       DOM (not `display:none`) so they remain focusable and operable by keyboard and screen reader;
       they are clipped instead, and the visible labels carry the hit area. Switching is instant with
       no transition, which is the honest trade for zero script. */
    .oo-aud{margin-top:22px;}
    .oo-aud__r{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
      clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;}
    .oo-aud__tabs{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:22px;}
    .oo-aud__tab{cursor:pointer;font-size:14px;font-weight:650;padding:15px 24px;min-height:52px;
      display:inline-flex;align-items:center;justify-content:center;
      border-radius:var(--oo-radius-full,9999px);border:1.5px solid var(--oo-border-subtle);
      color:var(--oo-text-secondary);background:transparent;}
    .oo-aud__panel{display:none;}
    /* :checked lights its own tab and reveals its own panel. The nth-of-type pairing keeps the two
       radios and the two panels in step; adding a third audience means one more pair. */
    .oo-aud__r:nth-of-type(1):checked ~ .oo-aud__tabs .oo-aud__tab:nth-of-type(1),
    .oo-aud__r:nth-of-type(2):checked ~ .oo-aud__tabs .oo-aud__tab:nth-of-type(2){
      background:var(--oo-surface-accent-solid);color:var(--oo-on-surface-accent-solid);
      border-color:var(--oo-surface-accent-solid);}
    .oo-aud__r:nth-of-type(1):checked ~ .oo-aud__panels .oo-aud__panel:nth-of-type(1),
    .oo-aud__r:nth-of-type(2):checked ~ .oo-aud__panels .oo-aud__panel:nth-of-type(2){display:block;}
    /* Keyboard focus must still be visible even though the input itself is clipped. */
    .oo-aud__r:focus-visible ~ .oo-aud__tabs .oo-aud__tab{outline:2px solid var(--oo-surface-accent-solid);
      outline-offset:2px;}
    .oo-aud__panel h3{font-size:clamp(22px,2.4vw,30px);font-weight:750;letter-spacing:-.015em;}
    .oo-aud__panel p{margin-top:10px;max-width:58ch;color:var(--oo-text-secondary);line-height:1.55;}

    /* A section figure: breathing room above, and the caption reads as a caption. */
    .oo-figure{margin-top:26px;}
    .oo-figure .oo-cap{margin-top:12px;text-align:center;font-size:12.5px;color:var(--oo-text-secondary);}
    /* MOBILE. These are LANDSCAPE desktop-app windows, so "fit the viewport" makes them unreadable: at
       390px the window lands ~330px wide and its 13px body text renders near 4px. So the figure becomes
       a horizontal scroller and the shot keeps a floor width that holds the type above ~11px. Panning a
       wide screenshot is a known, learnable gesture; illegible text is not a trade worth making. Applied
       only where the viewport actually forces it. (A cropped mobile variant per screen would avoid the
       pan altogether at the cost of 8 more assets.) */
    @media (max-width:1023px){
      .oo-figure{overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;}
      /* 880px was WRONG and I measured it wrong: the window is 1040 CSS wide inside an 1160 stage, so
         at an 880px image the window renders at 789 and its 13px body text lands at ~9.9px, not the
         11px I reported. The floor has to be derived from the WINDOW width:
             text = 13 * (imageWidth / stageWidth)  ->  11px needs 981px (windows), 1015px (pipeline).
         1020 clears both. It costs more panning; illegible text costs the reader entirely. */
      .oo-figure .oo-shot{min-width:1020px;}
      .oo-figure .oo-cap{position:sticky;left:0;}
    }
    /* Below ~460px the two audience labels cannot share a row without wrapping mid-group, which reads
       as a broken control rather than a choice. Stack them full width instead. */
    @media (max-width:460px){
      .oo-aud__tabs{display:grid;grid-template-columns:1fr;gap:8px;}
      .oo-aud__tab{text-align:center;}
    }
    .mo-ph{aspect-ratio:4/3;border-radius:var(--oo-radius-xl);display:grid;place-items:center;text-align:center;padding:var(--oo-space-lg);
      border:2px dashed var(--oo-border-strong);color:var(--oo-text-secondary);
      background:color-mix(in srgb,var(--oo-surface-accent-container) 45%,var(--oo-surface-surface-raised));}
    /* Per-pillar glyphs: the ◍ text node is hidden and each pillar draws its own mark via ::before, so the
       five placeholder boxes stop reading as one repeated wireframe (adversarial 2026-07-16). */
    .mo-ph__k{font-size:0;margin-bottom:var(--oo-space-xs);}
    .mo-ph__k::before{content:"◍";font-size:1.7rem;line-height:1;display:block;}
    .mo-ph--video .mo-ph__k::before{content:"▶";}
    #tracking .mo-ph__k::before{content:"◔";}
    #social .mo-ph__k::before{content:"◎";}
    #companion .mo-ph__k::before{content:"✶";}
    #marketplace .mo-ph__k::before{content:"◇";}
    #data .mo-ph__k::before{content:"◈";}
    .mo-ph__t{font-weight:700;color:var(--oo-text-primary);}
    .mo-ph__d{font-size:.85rem;margin-top:var(--oo-space-xs);}
    .mo-ph--shot{aspect-ratio:1/2;max-width:300px;margin-inline:auto;}
    .mo-cap{font-size:.85rem;color:var(--oo-text-secondary);margin-top:var(--oo-space-sm);}

    /* ── .pt — the 5 pillar toys (design proto: pt-proto.html · behavior: /js/pillar-toys.js).
       Each pillar's media slot embodies its idea interactively: tap a real feeling → its need (check-in),
       an invited circle orbiting You with the feed outside (social), insights inside a phone (companion),
       pick a need → the program forms (marketplace, dashed = being built), an off-by-default opt-in
       toggle (data). SSR = complete static diagram; JS upgrades. Token-only; motion behind reduced-motion. */
    .pt{aspect-ratio:4/3;border-radius:var(--oo-radius-xl);border:1px solid var(--oo-border-subtle);
        background:color-mix(in srgb,var(--oo-surface-accent-container) 22%,var(--oo-surface-surface-base));
        position:relative;overflow:hidden;display:flex;flex-direction:column;align-items:center;justify-content:center;
        gap:10px;padding:18px;text-align:center;}
    .pt__hint{position:absolute;top:10px;right:14px;font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;
        color:var(--oo-text-secondary);opacity:.7;}
    .pt button{font:inherit;cursor:pointer;}
    .pt__card{border-radius:var(--oo-radius-lg);border:1px solid var(--oo-border-subtle);
        background:var(--oo-surface-surface-base);padding:10px 14px;max-width:34ch;font-size:.85rem;
        color:var(--oo-text-secondary);line-height:1.35;box-shadow:0 8px 24px rgba(0,0,0,.12);}
    .pt__card b{color:var(--oo-text-primary);font-weight:700;}
    .pt__chips{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:420px;}
    .pt__chip{border-radius:var(--oo-radius-full);border:1px solid var(--oo-border-subtle);padding:6px 12px;
        background:var(--oo-surface-surface-base);color:var(--oo-text-primary);font-size:.85rem;font-weight:600;
        transition:transform .18s,border-color .18s,box-shadow .18s;}
    .pt__chip:hover{transform:translateY(-2px);}
    .pt__chip[aria-pressed="true"]{border-color:var(--oo-surface-accent-solid);
        box-shadow:0 0 0 3px color-mix(in srgb,var(--oo-surface-accent-solid) 25%,transparent);}
    .pt--checkin .pt__need{color:var(--oo-surface-accent-solid);font-weight:700;}
    .pt--circle .pt__stage{position:relative;width:min(88%,330px);aspect-ratio:1;flex:none;}
    .pt__ring{position:absolute;inset:12%;border:1px dashed color-mix(in srgb,var(--oo-surface-accent-solid) 45%,transparent);
        border-radius:50%;}
    .pt__you{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:64px;height:64px;border-radius:50%;
        display:grid;place-items:center;font-weight:800;color:var(--oo-on-surface-accent-solid);
        background:radial-gradient(circle at 32% 30%,color-mix(in srgb,var(--oo-surface-accent-solid) 88%,white),var(--oo-surface-accent-solid));
        box-shadow:0 0 34px color-mix(in srgb,var(--oo-surface-accent-solid) 45%,transparent);}
    .pt__person{position:absolute;transform:translate(-50%,-50%);border-radius:var(--oo-radius-full);
        border:1px solid var(--oo-border-subtle);background:var(--oo-surface-surface-base);
        padding:5px 10px;font-size:.78rem;font-weight:600;color:var(--oo-text-primary);white-space:nowrap;
        transition:border-color .18s,box-shadow .18s;}
    .pt__person[aria-pressed="true"]{border-color:var(--oo-surface-accent-solid);
        box-shadow:0 0 0 3px color-mix(in srgb,var(--oo-surface-accent-solid) 25%,transparent);}
    .pt__feed{position:absolute;right:-2%;top:4%;border-radius:var(--oo-radius-full);border:1px dashed var(--oo-border-subtle);
        padding:4px 9px;font-size:.68rem;color:var(--oo-text-secondary);opacity:.75;background:transparent;}
    @media (prefers-reduced-motion:no-preference){
      .pt--circle .pt__spin{position:absolute;inset:0;animation:pt-spin 46s linear infinite;}
      .pt--circle .pt__spin .pt__person{animation:pt-counter 46s linear infinite;}
      @keyframes pt-spin{to{transform:rotate(1turn);}}
      @keyframes pt-counter{to{transform:translate(-50%,-50%) rotate(-1turn);}}
    }
    .pt--device .pt__stage{position:relative;width:150px;height:220px;flex:none;border-radius:24px;
        border:2px solid var(--oo-border-subtle);background:var(--oo-surface-surface-base);
        display:grid;place-items:center;overflow:hidden;}
    .pt__notch{position:absolute;top:7px;left:50%;transform:translateX(-50%);width:44px;height:5px;border-radius:3px;
        background:var(--oo-border-subtle);}
    .pt__mind{width:56px;height:56px;border-radius:50%;
        background:radial-gradient(circle at 32% 30%,color-mix(in srgb,var(--oo-surface-accent-solid) 80%,white),var(--oo-surface-accent-solid));
        box-shadow:0 0 26px color-mix(in srgb,var(--oo-surface-accent-solid) 55%,transparent);}
    .pt__mote{position:absolute;width:7px;height:7px;border-radius:50%;background:color-mix(in srgb,var(--oo-surface-accent-solid) 70%,transparent);}
    .pt__mote--1{left:22%;top:26%;} .pt__mote--2{right:20%;top:38%;} .pt__mote--3{left:30%;bottom:22%;}
    @media (prefers-reduced-motion:no-preference){
      .pt__mind{animation:pt-breathe 4.5s ease-in-out infinite;}
      @keyframes pt-breathe{50%{transform:scale(1.09);box-shadow:0 0 40px color-mix(in srgb,var(--oo-surface-accent-solid) 65%,transparent);}}
      .pt__mote{animation:pt-drift 7s ease-in-out infinite;} .pt__mote--2{animation-delay:2.2s;} .pt__mote--3{animation-delay:4.1s;}
      @keyframes pt-drift{50%{transform:translate(8px,-9px);opacity:.5;}}
    }
    .pt--match .pt__card{border-style:dashed;border-color:color-mix(in srgb,var(--oo-surface-accent-solid) 55%,transparent);}
    .pt--optin .pt__stage{display:flex;align-items:center;gap:14px;flex:none;}
    .pt__node{border-radius:var(--oo-radius-lg);border:1px solid var(--oo-border-subtle);padding:8px 12px;
        font-size:.78rem;font-weight:600;color:var(--oo-text-primary);background:var(--oo-surface-surface-base);}
    .pt__lane{position:relative;width:120px;height:22px;}
    .pt__dot{position:absolute;left:0;top:50%;transform:translate(0,-50%);width:14px;height:14px;border-radius:50%;
        background:var(--oo-surface-accent-solid);transition:left 1.1s ease,filter 1.1s ease,opacity 1.1s;}
    .pt--optin.pt--on .pt__dot{left:calc(100% - 14px);filter:grayscale(1) blur(.6px);opacity:.65;}
    .pt__value{font-size:.72rem;color:var(--oo-surface-accent-solid);font-weight:700;opacity:0;transition:opacity .5s .9s;}
    .pt--optin.pt--on .pt__value{opacity:1;}
    .pt__toggle{border-radius:var(--oo-radius-full);border:1px solid var(--oo-border-subtle);padding:7px 14px;
        background:var(--oo-surface-surface-base);color:var(--oo-text-primary);font-size:.82rem;font-weight:700;}
    .pt--optin.pt--on .pt__toggle{border-color:var(--oo-surface-accent-solid);
        box-shadow:0 0 0 3px color-mix(in srgb,var(--oo-surface-accent-solid) 22%,transparent);}
    @media (prefers-reduced-motion:reduce){ .pt__dot,.pt__value{transition:none;} }
    /* Quality-of-life section: journey strip + the orbit toy + AI capstone */
    .mo-qol__head{margin-bottom:var(--oo-space-xl);}
    .mo-qol__journey{display:grid;grid-template-columns:1fr;gap:var(--oo-space-lg);margin-bottom:var(--oo-space-xxl);}
    @media(min-width:700px){.mo-qol__journey{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--oo-space-lg) var(--oo-space-md);}}
    .mo-jstep{display:flex;gap:var(--oo-space-md);align-items:flex-start;}
    .mo-jstep__emoji{font-size:1.5rem;line-height:1.15;flex:0 0 auto;width:2.1rem;text-align:center;}
    .mo-jstep__label{font-weight:800;color:var(--oo-text-primary);margin-bottom:2px;}
    .mo-jstep__body p{margin:0;color:var(--oo-text-secondary);font-size:var(--oo-type-body-small);}

    /* ── .mo-toy — the quality-of-life orbit toy (design proto: toy-b.html · behavior: /js/qol-toy.js).
       Needs orbit the "You" orb; tap a feeling → its satellite leans in with the specific thing it
       touched → one small action refills it and the center brightens. Satellite positions, resting
       fills, and the orb's warmth stages are PRESENTATION and live here; all copy is DSL-authored. ── */
    .mo-toy{max-width:680px;margin:0 auto;}
    /* [hidden] must WIN over the block's own display rules (an author display:flex silently beats the
       UA [hidden] rule — the round-1 no-JS lesson) */
    .mo-toy [hidden]{display:none !important;}
    .mo-toy__head{font-size:var(--oo-type-headline);margin:0 0 var(--oo-space-xs);letter-spacing:-.01em;text-align:center;}
    .mo-toy__lead{color:var(--oo-text-secondary);text-align:center;max-width:52ch;margin:0 auto var(--oo-space-md);}

    .mo-toy__stage{position:relative;height:340px;margin:0 0 var(--oo-space-sm);}
    .mo-toy__ring{position:absolute;left:50%;top:50%;width:min(88%,500px);height:62%;transform:translate(-50%,-50%);
      border:1.5px solid color-mix(in srgb,var(--oo-surface-accent-solid) 26%,transparent);border-radius:50%;}
    .mo-toy__glow{position:absolute;left:50%;top:50%;width:250px;height:250px;transform:translate(-50%,-50%);
      border-radius:50%;pointer-events:none;opacity:.7;transition:opacity .6s;
      background:radial-gradient(circle, color-mix(in srgb,var(--oo-surface-accent-solid) 16%,transparent), transparent 65%);}
    .mo-toy__you{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);text-align:center;}
    .mo-toy__orb{width:92px;height:92px;border-radius:50%;margin:0 auto 6px;display:flex;align-items:center;
      justify-content:center;color:var(--oo-on-surface-accent-solid);font-weight:800;font-size:var(--oo-type-body);
      background:radial-gradient(circle at 34% 28%, color-mix(in srgb,#ffffff 55%,var(--oo-surface-accent-solid)), var(--oo-surface-accent-solid) 72%);
      filter:saturate(.55) brightness(.96);transition:filter .6s,box-shadow .6s,transform .3s;}
    .mo-toy[data-warmth="1"] .mo-toy__orb{filter:saturate(.85);}
    .mo-toy[data-warmth="2"] .mo-toy__orb{filter:saturate(1.05);
      box-shadow:0 0 28px color-mix(in srgb,var(--oo-surface-accent-solid) 42%,transparent);}
    .mo-toy[data-warmth="3"] .mo-toy__orb{filter:saturate(1.2) brightness(1.06);
      box-shadow:0 0 44px color-mix(in srgb,var(--oo-surface-accent-solid) 58%,transparent);}
    .mo-toy__orb--pulse{transform:scale(1.09);}
    .mo-toy__orbcap{font-size:var(--oo-type-caption);color:var(--oo-text-secondary);}

    .mo-toy__sat{position:absolute;transition:transform .4s ease;}
    .mo-toy__sat--body{left:2%;top:3%;}
    .mo-toy__sat--safe{right:2%;top:3%;}
    .mo-toy__sat--belong{left:2%;bottom:3%;}
    .mo-toy__sat--grow{right:2%;bottom:3%;}
    .mo-toy__satcard{background:var(--oo-surface-surface-raised);border:1px solid var(--oo-border-subtle);
      border-radius:var(--oo-radius-lg);padding:.55rem .8rem;min-width:132px;transition:border-color .35s,box-shadow .35s;}
    .mo-toy__sat--lit .mo-toy__satcard{border-color:var(--oo-surface-accent-solid);
      box-shadow:0 0 18px color-mix(in srgb,var(--oo-surface-accent-solid) 30%,transparent);}
    /* the lit satellite leans toward the center (per-corner direction) */
    .mo-toy__sat--body.mo-toy__sat--lit{transform:translate(12px,12px);}
    .mo-toy__sat--safe.mo-toy__sat--lit{transform:translate(-12px,12px);}
    .mo-toy__sat--belong.mo-toy__sat--lit{transform:translate(12px,-12px);}
    .mo-toy__sat--grow.mo-toy__sat--lit{transform:translate(-12px,-12px);}
    .mo-toy__satname{font-size:var(--oo-type-body-small);font-weight:750;color:var(--oo-text-primary);margin:0 0 2px;}
    .mo-toy__sattag{font-size:var(--oo-type-caption);color:var(--oo-surface-accent-solid);font-weight:700;
      margin:0 0 5px;min-height:1.15em;}
    .mo-toy__meter{height:6px;border-radius:3px;background:color-mix(in srgb,var(--oo-border-subtle) 55%,transparent);overflow:hidden;}
    .mo-toy__meter-fill{height:100%;border-radius:3px;width:var(--rest,55%);transition:width .5s ease;
      background:linear-gradient(90deg,color-mix(in srgb,var(--oo-surface-accent-solid) 65%,var(--oo-surface-accent-container)),var(--oo-surface-accent-solid));}
    .mo-toy__meter-fill--plus{width:calc(var(--rest,55%) + 25%);}
    /* resting fills per satellite — part-full on purpose (never empty, never full) */
    .mo-toy__sat--body .mo-toy__meter-fill{--rest:55%;}
    .mo-toy__sat--safe .mo-toy__meter-fill{--rest:60%;}
    .mo-toy__sat--belong .mo-toy__meter-fill{--rest:55%;}
    .mo-toy__sat--grow .mo-toy__meter-fill{--rest:50%;}

    .mo-toy__chips{display:flex;flex-wrap:wrap;gap:var(--oo-space-sm);justify-content:center;margin:0 0 var(--oo-space-sm);}
    .mo-toy__chips button{min-height:48px;padding:.5rem 1.05rem;border-radius:var(--oo-radius-full);cursor:pointer;
      border:1px solid var(--oo-border-subtle);background:var(--oo-surface-surface-raised);color:var(--oo-text-primary);
      font:inherit;font-size:var(--oo-type-body-small);font-weight:650;transition:transform .12s,background .2s,border-color .2s;}
    .mo-toy__chips button:active{transform:scale(.96);}
    .mo-toy__chips button[aria-pressed="true"]{background:var(--oo-surface-accent-solid);
      color:var(--oo-on-surface-accent-solid);border-color:var(--oo-surface-accent-solid);}
    .mo-toy__actionrow{min-height:54px;text-align:center;}
    .mo-toy__action{min-height:48px;padding:.55rem 1.2rem;border-radius:var(--oo-radius-full);cursor:pointer;
      font:inherit;font-size:var(--oo-type-body-small);font-weight:700;border:1px solid var(--oo-surface-accent-solid);
      background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);}
    .mo-toy__cap{font-size:var(--oo-type-body-small);color:var(--oo-text-secondary);text-align:center;
      min-height:2.4em;margin:var(--oo-space-xs) 0 0;}
    .mo-toy__bridge{font-size:var(--oo-type-body-small);color:var(--oo-text-secondary);text-align:center;
      max-width:56ch;margin:var(--oo-space-md) auto 0;}
    .mo-toy__note{font-size:var(--oo-type-caption);color:var(--oo-text-secondary);text-align:center;
      margin:var(--oo-space-xs) 0 0;}
    @media(max-width:560px){
      .mo-toy__stage{height:400px;}
      .mo-toy__satcard{min-width:112px;padding:.45rem .65rem;}
      .mo-toy__orb{width:80px;height:80px;}
    }
    @media (prefers-reduced-motion: reduce){
      .mo-toy__sat,.mo-toy__orb,.mo-toy__satcard,.mo-toy__meter-fill,.mo-toy__glow,.mo-toy__chips button{transition:none;}
      .mo-toy__orb--pulse{transform:none;}
    }

    .mo-qol__ai{margin-top:var(--oo-space-xl);border-radius:var(--oo-radius-lg);padding:var(--oo-space-lg);display:flex;gap:var(--oo-space-md);align-items:flex-start;}
    .mo-qol__ai-emoji{font-size:1.8rem;line-height:1;flex:0 0 auto;}
    .mo-qol__ai h3{margin:0 0 var(--oo-space-xs);color:inherit;}
    .mo-qol__ai p{margin:0;color:inherit;opacity:.92;max-width:64ch;}

    /* ===== TrueAlign (work) — Approval Gate hero (commandHero). CSS-only (script-src 'none'). ===== */
    .ca-hero{--ca-line:color-mix(in srgb, var(--oo-text-primary) 12%, transparent);
      --ca-flow:color-mix(in srgb, var(--oo-surface-accent-solid) 55%, transparent); /* connectors: >=3:1 (WCAG 1.4.11) */
      --ca-card:var(--oo-surface-surface-base);--ca-success:var(--oo-surface-status-success);
      /* `--oo-space-2xl` does NOT exist (the scale ends at xxl) — this padding and the gap below were
         silently void, so TrueAlign's hero had zero vertical padding and zero column gap. Same
         undefined-var() class as the WIS mirror; `check-landing-tokens.sh` guards both now. */
      padding:var(--oo-space-xxl) 0;}
    .ln-field input::placeholder{color:var(--oo-text-secondary);opacity:1;} /* AA contrast on the sole conversion field */
    .ca-hero__inner{display:grid;grid-template-columns:1.02fr 1fr;gap:var(--oo-space-xxl);align-items:center;}
    .ca-hero__copy{min-width:0;}
    .ca-eyebrow{font-size:var(--oo-type-caption);font-weight:600;letter-spacing:.04em;text-transform:uppercase;
      color:var(--oo-text-secondary);margin:0 0 var(--oo-space-md);}
    .ca-title{letter-spacing:-.02em;}
    .ca-title .text-accent{white-space:nowrap;}
    .ca-sub{margin:var(--oo-space-lg) 0 0;font-size:clamp(17px,2.1vw,19px);color:var(--oo-text-secondary);max-width:35ch;}
    .ca-hero .ln-cta{margin-top:var(--oo-space-xl);}
    .ca-cta-note{margin:var(--oo-space-sm) 0 0;font-size:.875rem;color:var(--oo-text-secondary);}

    .ca-stage{position:relative;aspect-ratio:16/10;border-radius:var(--oo-radius-lg);min-width:0;overflow:hidden;
      background:var(--oo-surface-surface-raised);border:1px solid var(--ca-line);}
    .ca-lane{position:absolute;inset:0;}
    .ca-bus{position:absolute;left:19%;top:28%;height:44%;border-left:2px dashed var(--ca-flow);}
    .ca-track{position:absolute;left:19%;right:12%;top:50%;border-top:2px dashed var(--ca-flow);}
    .ca-agent{position:absolute;left:5%;width:96px;height:32px;border-radius:999px;white-space:nowrap;
      background:var(--oo-surface-accent-container);color:var(--oo-on-surface-accent-container);
      display:flex;align-items:center;gap:8px;padding:0 13px;font-size:12.5px;font-weight:600;
      border:1px solid var(--ca-line);transform:translateY(-50%);}
    .ca-dot{width:8px;height:8px;border-radius:50%;background:var(--oo-surface-accent-solid);
      animation:caPulse 2.4s ease-in-out infinite;}
    .ca-a1{top:34%;}.ca-a2{top:50%;}.ca-a3{top:66%;}
    .ca-a2 .ca-dot{animation-delay:.5s;}.ca-a3 .ca-dot{animation-delay:1s;}
    @keyframes caPulse{0%,100%{opacity:.45;transform:scale(1);}50%{opacity:1;transform:scale(1.35);}}
    .ca-gate{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:3;
      width:128px;padding:14px 12px 12px;border-radius:var(--oo-radius-md);text-align:center;
      background:var(--oo-surface-accent-solid);color:var(--oo-on-surface-accent-solid);
      box-shadow:0 12px 34px -14px rgba(0,0,0,.45);}
    .ca-gate__label{font-size:10.5px;font-weight:700;letter-spacing:.05em;opacity:.9;}
    .ca-you{position:relative;width:46px;height:46px;border-radius:50%;margin:10px auto 12px;
      background:rgba(255,255,255,.16);display:flex;align-items:center;justify-content:center;
      border:1.5px solid rgba(255,255,255,.55);}
    .ca-person{width:25px;height:25px;fill:var(--oo-on-surface-accent-solid);}
    .ca-badge{position:absolute;right:-4px;bottom:-4px;width:21px;height:21px;border-radius:50%;
      background:var(--ca-success);border:2.5px solid var(--oo-surface-accent-solid);
      display:flex;align-items:center;justify-content:center;animation:caApprove 4s ease-in-out infinite;}
    .ca-badge svg{width:11px;height:11px;fill:#fff;}
    @keyframes caApprove{0%,50%{transform:scale(.3);opacity:0;}60%,84%{transform:scale(1);opacity:1;}100%{transform:scale(.3);opacity:0;}}
    .ca-gate__cap{position:absolute;left:50%;bottom:-24px;transform:translateX(-50%);white-space:nowrap;
      font-size:11px;font-weight:600;color:var(--oo-text-secondary);}
    .ca-live{position:absolute;right:4%;top:50%;transform:translateY(-50%);font-size:11px;font-weight:600;
      color:var(--oo-text-secondary);text-align:center;}
    .ca-live__ring{width:15px;height:15px;border-radius:50%;border:2px solid var(--ca-success);margin:0 auto 6px;}
    .ca-card{position:absolute;top:50%;width:44px;height:30px;border-radius:7px;z-index:2;
      background:var(--ca-card);border:1px solid var(--ca-line);box-shadow:0 6px 16px -10px rgba(0,0,0,.45);
      animation:caFlow 4.2s linear infinite;}
    .ca-card::before{content:"";position:absolute;left:7px;top:8px;width:22px;height:3px;border-radius:2px;
      background:var(--oo-surface-accent-solid);opacity:.6;}
    .ca-card::after{content:"";position:absolute;left:7px;top:15px;width:13px;height:3px;border-radius:2px;
      background:var(--oo-text-secondary);opacity:.45;}
    .ca-c1{animation-delay:0s;}.ca-c2{animation-delay:1.4s;}.ca-c3{animation-delay:2.8s;}
    @keyframes caFlow{
      0%{left:22%;opacity:0;transform:translateY(-50%) scale(.9);}
      10%{opacity:1;}
      36%{left:calc(50% - 22px);opacity:1;transform:translateY(-50%) scale(1);}
      52%{left:calc(50% - 22px);opacity:1;}
      60%{transform:translateY(-50%) scale(1.07);}
      88%{left:80%;opacity:1;transform:translateY(-50%) scale(.92);}
      100%{left:84%;opacity:0;}
    }
    @media (prefers-reduced-motion:reduce){
      .ca-agent .ca-dot,.ca-badge,.ca-card{animation:none;}
      .ca-badge{transform:scale(1);opacity:1;}
      .ca-c1{left:30%;transform:translateY(-50%);opacity:1;}
      .ca-c2{left:calc(50% - 22px);transform:translateY(-50%);opacity:1;box-shadow:0 6px 16px -10px rgba(0,0,0,.45),0 0 0 2px var(--ca-success);}
      .ca-c3{left:72%;transform:translateY(-50%);opacity:.5;}
    }
    @media (max-width:820px){
      .ca-hero__inner{display:block;}
      .ca-stage{margin-top:var(--oo-space-xl);aspect-ratio:3/2;}
      .ca-sub{max-width:none;}
    }

/* ===== TrueAlign (work) landing — bespoke sections ===== */

/* Derived vars — the shell's oo-tokens.css provides all --oo-* tokens for
   data-oo-brand="truealign" (light + prefers-color-scheme dark). We only re-declare
   the prototype's DERIVED vars, scoped to the work brand. */
html[data-oo-brand="truealign"]{
  --ink:#0e131b;
  --card:#ffffff;
  --hair:var(--oo-border-subtle);
  --shadow:0 1px 2px rgba(23,36,51,.04), 0 12px 30px -18px rgba(23,36,51,.18);
  --shadow-lg:0 2px 4px rgba(23,36,51,.05), 0 30px 60px -30px rgba(23,36,51,.30);
  --accent:var(--oo-surface-accent-solid);
  --on-accent:var(--oo-on-surface-accent-solid);
  --success:var(--oo-surface-status-success);
  --maxw:1120px;
  --r-sm:8px; --r-md:12px; --r-lg:16px; --r-xl:24px; --r-full:9999px;
  --serif:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  --sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono","JetBrains Mono",Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark){
  html[data-oo-brand="truealign"]{
    --ink:#080c12;
    --card:#131b26;
    --shadow:0 1px 2px rgba(0,0,0,.3), 0 14px 34px -18px rgba(0,0,0,.6);
    --shadow-lg:0 2px 4px rgba(0,0,0,.35), 0 34px 64px -30px rgba(0,0,0,.7);
  }
}

/* base — replaces the prototype's .ta wrapper rules (sections have no .ta) */
.hero,.section,.hero *,.section *{box-sizing:border-box;}
.hero, .section{
  font-family:var(--sans); font-size:17px; line-height:1.55;
  color:var(--oo-text-primary); -webkit-font-smoothing:antialiased;
}
.hero *, .section *{margin:0;}
/* `color:inherit` on every anchor in a hero/section is (0,1,1) and therefore BEATS `.btn-primary`
   (0,1,0), so the primary button took the section's ink instead of its own on-accent colour. In
   light that is #172433 on #2d4a6b = 1.72:1, in dark #e4ebf3 on #6ea8de = 2.10:1. Both are
   unreadable and both are well under the 4.5:1 floor. Buttons are excluded so the component owns
   its own colour. Same shape as the surface-utility cascade override already recorded in Memory. */
.hero a:not(.btn):not(.ln-cta), .section a:not(.btn):not(.ln-cta){color:inherit;}
.wrap{max-width:var(--maxw); margin:0 auto; padding:0 24px;}
.eyebrow{font-family:var(--mono); font-size:12px; font-weight:600; letter-spacing:.14em;
  text-transform:uppercase; color:var(--oo-text-secondary);}
.eyebrow .dot{color:var(--accent);}
h1,h2,h3{font-family:var(--sans); font-weight:760; letter-spacing:-.022em;
  line-height:1.06; text-wrap:balance; color:var(--oo-text-primary);}
h2{font-size:clamp(26px,3.4vw,38px); letter-spacing:-.02em; line-height:1.1;}
h3{font-size:19px; letter-spacing:-.01em; line-height:1.25;}
.lede{font-size:clamp(17px,1.5vw,19px); color:var(--oo-text-secondary); max-width:60ch; text-wrap:pretty;}
p{text-wrap:pretty;}
.accent{color:var(--accent);}

/* ---- buttons ---- */
.btn{display:inline-flex; align-items:center; gap:9px; font-family:var(--sans);
  font-size:16px; font-weight:650; letter-spacing:-.01em; border-radius:var(--r-full);
  padding:13px 22px; border:1px solid transparent; cursor:pointer; text-decoration:none;
  transition:transform .14s ease, box-shadow .2s ease, background .2s ease; white-space:nowrap;}
.btn-primary{background:var(--accent); color:var(--on-accent); box-shadow:var(--shadow);}
.btn-primary:hover{transform:translateY(-1px); box-shadow:var(--shadow-lg);}
.btn-ghost{background:transparent; color:var(--oo-text-primary); border-color:var(--hair);}
.btn-ghost:hover{border-color:var(--oo-border-strong);}
.btn:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}

/* ---- hero ---- */
.hero{padding:clamp(40px,7vw,84px) 0 clamp(36px,5vw,60px);}
.hero-grid{display:grid; grid-template-columns:1.04fr 1fr; gap:clamp(28px,4vw,56px); align-items:center;}
.hero h1{font-size:clamp(34px,5.2vw,58px); margin-top:16px;}
.hero .lede{margin-top:20px; font-size:clamp(17px,1.7vw,20px);}
/* TrueAlign's hero no longer holds a form: D3 (2026-07-26) gave the waitlist five fields, which do not belong
   in a hero, so `.hero-form` is now the layout row around the ANCHOR down to the one real form at #join. The
   `.hero-form input` rules that styled the old inline email box were removed with it (no input matches them).
   The row keeps its flex layout so hero spacing is unchanged. */
.hero-form{margin-top:26px; display:flex; flex-wrap:wrap; gap:10px; max-width:440px;}
/* block, not flex: with flex-wrap the anonymous text node wrapped BELOW the tick whenever it needed
   a second line, orphaning the ✓ on its own row at 390 (FIX-7). */
.cta-note{margin-top:12px; font-size:13.5px; color:var(--oo-text-secondary); display:block;}
.cta-note .tick{color:var(--success); font-weight:800; display:inline-block; vertical-align:middle; margin-right:8px;}
.trust-line{margin-top:22px; padding-top:20px; border-top:1px solid var(--hair);
  font-size:14px; color:var(--oo-text-secondary); max-width:44ch;}
.trust-line b{color:var(--oo-text-primary); font-weight:650;}

/* ===== SIGNATURE HERO: the approval request — the AI finished, and stopped for a human (CSS-only) ===== */
.loop{position:relative; border-radius:var(--r-lg); border:1px solid var(--hair);
  background:var(--card); box-shadow:var(--shadow-lg); overflow:hidden;}
.loop-bar{display:flex; align-items:center; gap:7px; padding:11px 14px; border-bottom:1px solid var(--hair);
  background:var(--oo-surface-surface-raised);}
/* HERO CHROME MATCHES THE SECTION SCREENSHOTS (Didier 2026-07-30). The hero illustration and the
   four section shots are the same product, so they must be the same window: coloured traffic lights
   and a centred titlebar, not three grey dots and a left-aligned mono label. `.loop` is TrueAlign-only
   (verified: zero occurrences on the MoodOrbit and OOTech pages), so this restyle is contained.
   `min-width:0` is the fix for a REAL 320px defect: `.loop` is a grid item, grid items default to
   `min-width:auto`, and it therefore refused to shrink below its content and pushed 30px past the
   viewport, dragging six descendants with it. */
.loop{min-width:0;}
.loop-bar{position:relative;}
.loop-bar .lamp{width:11px; height:11px; border-radius:50%; background:var(--hair); flex:0 0 auto;}
.loop-bar .lamp:nth-of-type(1){background:#ff5f57;}
.loop-bar .lamp:nth-of-type(2){background:#febc2e;}
.loop-bar .lamp:nth-of-type(3){background:#28c840;}
.loop-bar .title{position:absolute; left:0; right:0; text-align:center; pointer-events:none;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; padding:0 56px;
  font-size:13px; font-weight:650; letter-spacing:-.01em; text-transform:none;
  color:var(--oo-text-primary);}
.loop-body{padding:15px;}
.loop-cap{padding:12px 15px 14px; border-top:1px solid var(--hair); font-size:11.5px; color:var(--oo-text-secondary); text-align:center;}
.loop-cap b{color:var(--oo-text-primary); font-weight:650;}
/* small mono pill, shared with the "learned about you" ledger */
.k{font-family:var(--mono); font-size:8.5px; text-transform:uppercase; letter-spacing:.04em; padding:2px 6px;
  border-radius:99px; background:rgba(0,0,0,.07); color:inherit; flex:0 0 auto;}
@media(prefers-color-scheme:dark){.k{background:rgba(255,255,255,.12);}}
/* the approval-request card — two real examples (personal / professional) cross-faded */
.req-wrap{position:relative; height:300px;}
.req{position:absolute; inset:0; display:flex; flex-direction:column; opacity:0; animation:reqShow 12s ease-in-out infinite;}
.req.req-pro{animation-delay:6s;}
.req.req-pro .req-status .s-pend,
.req.req-pro .req-status .s-done,
.req.req-pro .req-actions .req-approve,
.req.req-pro .req-loophint{animation-delay:6s;}
@keyframes reqShow{0%{opacity:0; transform:translateY(8px);}3%,44%{opacity:1; transform:none;}48%,100%{opacity:0; transform:translateY(-8px);}}
.req-task{display:flex; align-items:center; gap:8px; font-size:14.5px; font-weight:700; letter-spacing:-.01em; color:var(--oo-text-primary);}
.req-artifact{margin-top:12px; flex:1; border:1px solid var(--hair); border-radius:var(--r-md);
  background:var(--oo-surface-surface-raised); padding:15px 14px; position:relative;}
.req-artifact .tag{position:absolute; top:11px; right:12px; font-family:var(--mono); font-size:8px; letter-spacing:.05em;
  text-transform:uppercase; color:var(--oo-text-secondary); padding:3px 7px; border-radius:99px; border:1px solid var(--hair); background:var(--card);}
.req-artifact .a-main{font-size:13.5px; font-weight:650; color:var(--oo-text-primary); max-width:calc(100% - 98px); line-height:1.3;}   /* clear the absolute "PREPARED BY AI" tag at 390 (76% overlapped it) */
.req-artifact .a-sub{margin-top:9px; font-size:12px; color:var(--oo-text-secondary); line-height:1.4;}
.req-foot{margin-top:13px; display:flex; align-items:center; justify-content:space-between; gap:10px;}
.req-status{position:relative; min-width:158px; height:34px;}
.req-status span{position:absolute; left:0; top:0; display:inline-flex; align-items:center; gap:6px; font-size:12.5px;
  font-weight:700; padding:7px 13px; border-radius:var(--r-full); white-space:nowrap;}
.req-status .s-pend{color:var(--accent); border:1.5px solid var(--accent); animation:reqPend 12s ease-in-out infinite;}
.req-status .s-done{color:var(--on-accent); background:var(--success); border:1.5px solid var(--success); opacity:0; animation:reqDone 12s ease-in-out infinite;}
@keyframes reqPend{0%,2%{opacity:0;}5%,20%{opacity:1;}24%,100%{opacity:0;}}
@keyframes reqDone{0%,21%{opacity:0; transform:scale(.97);}25%,45%{opacity:1; transform:scale(1);}48%,100%{opacity:0;}}
.req-who{display:flex; align-items:center; gap:8px; flex:0 1 auto; min-width:0;}
.req-ava{width:30px; height:30px; border-radius:50%; display:grid; place-items:center; flex:0 0 auto;}
.req-ava.you{background:var(--oo-surface-branded); color:var(--oo-on-surface-branded);}
.req-ava.exp{background:var(--oo-surface-accent-container); color:var(--oo-on-surface-accent-container);}
.req-ava svg{width:17px; height:17px; fill:currentColor;}
.req-who__t{font-size:10.5px; line-height:1.2; color:var(--oo-text-secondary); text-align:right; min-width:0; overflow:hidden; text-overflow:ellipsis;}
.req-who__t b{display:block; color:var(--oo-text-primary); font-size:11px;}
.req-actions{margin-top:12px; display:flex; gap:8px;}
.req-approve{flex:1; text-align:center; font-size:13px; font-weight:700; padding:11px; border-radius:var(--r-full);
  border:1.5px solid var(--accent); color:var(--accent); background:transparent; animation:reqPress 12s ease-in-out infinite;}
@keyframes reqPress{0%,19%{background:transparent; color:var(--accent); transform:scale(1);}
  22%{transform:scale(.95);}24%,44%{background:var(--success); border-color:var(--success); color:var(--on-accent); transform:scale(1);}
  48%,100%{background:transparent; border-color:var(--accent); color:var(--accent);}}
.req-back{width:112px; text-align:center; font-size:13px; font-weight:640; padding:11px; border-radius:var(--r-full); border:1px solid var(--hair); color:var(--oo-text-secondary);}
.req-loophint{margin-top:11px; text-align:center; font-size:11px; color:var(--oo-text-secondary); opacity:0; animation:reqHint 12s ease-in-out infinite;}
.req-loophint b{color:var(--oo-text-primary); font-weight:640;}
@keyframes reqHint{0%,30%{opacity:0;}34%,44%{opacity:1;}48%,100%{opacity:0;}}
@media (prefers-reduced-motion:reduce){
  .req, .req *{animation:none !important;}
  .req.req-personal{opacity:0;}
  .req.req-pro{opacity:1;}
  .req.req-pro .s-pend{opacity:1;} .req.req-pro .s-done{opacity:0;}
  .req.req-pro .req-approve{background:transparent; border-color:var(--accent); color:var(--accent);}
  .req.req-pro .req-loophint{opacity:0;}
}

/* ---- generic section ---- */
.section{padding:clamp(48px,7vw,88px) 0;}
.section.raised{background:var(--oo-surface-surface-raised);}
.section-head{max-width:64ch;}
.section-head h2{margin-top:12px;}
.section-head .lede{margin-top:16px;}

/* fear band */
.fear{background:var(--oo-surface-branded); color:var(--oo-on-surface-branded);}
.fear h2,.fear .lede{color:inherit;}
.fear .lede{opacity:.9; max-width:66ch; font-size:clamp(18px,1.9vw,22px); line-height:1.5;}
.fear .resolve{margin-top:24px; display:inline-flex; align-items:center; gap:11px; font-weight:640;
  font-size:16px; padding:12px 18px; border-radius:var(--r-full); background:color-mix(in srgb,var(--success) 16%, transparent); border:1px solid color-mix(in srgb,var(--success) 40%,transparent);}
.fear .resolve .tick{color:var(--success); font-weight:900; font-size:18px;}

/* steps (a real sequence → numbered) */
.steps{display:grid; grid-template-columns:repeat(5,1fr); gap:14px; margin-top:32px;}
.step{background:var(--card); border:1px solid var(--hair); border-radius:var(--r-md); padding:18px 16px; position:relative;}
.step h3{font-size:16.5px; margin-top:10px;} .step p{font-size:14px;}
.step .num{font-family:var(--mono); font-size:11px; font-weight:700; color:var(--accent); letter-spacing:.04em;}
.loop-strip{margin-top:16px; display:flex; align-items:center; justify-content:center; gap:10px; text-align:center;
  padding:15px 20px; border-radius:var(--r-md); border:1px dashed color-mix(in srgb,var(--accent) 45%,transparent);
  background:color-mix(in srgb,var(--accent) 6%,transparent); font-size:14.5px; font-weight:600; color:var(--oo-text-primary);}
.loop-strip .ic{color:var(--accent); font-size:19px; font-weight:800; line-height:1;}
.step h3{margin-top:12px;} .step p{margin-top:8px; font-size:15px; color:var(--oo-text-secondary);}
.step.is-gate{background:var(--oo-surface-accent-container); border-color:color-mix(in srgb,var(--accent) 40%,transparent);}
.step.is-gate .num{color:var(--oo-on-surface-accent-container);}
.step.is-gate h3,.step.is-gate p{color:var(--oo-on-surface-accent-container);}

/* two journeys */
.journeys{display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-top:38px;}
.journey{border:1px solid var(--hair); border-radius:var(--r-lg); padding:26px; background:var(--card); box-shadow:var(--shadow);}
.journey .tag{font-family:var(--mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--accent); font-weight:600;}
.journey h3{margin-top:12px; font-size:22px;}
.journey .who{margin-top:8px; color:var(--oo-text-secondary); font-size:15px;}
.journey .task-list{margin-top:18px; display:flex; flex-direction:column; gap:9px;}
.journey .task{display:flex; align-items:center; gap:11px; padding:11px 13px; border-radius:var(--r-sm);
  background:var(--oo-surface-surface-raised); font-size:14.5px; border:1px solid transparent;}
.journey .task .ic{width:26px; height:26px; border-radius:7px; display:grid; place-items:center; flex:0 0 auto;
  background:var(--oo-surface-accent-container); color:var(--oo-on-surface-accent-container);}
.journey .task .ic svg{width:15px; height:15px;}
.journey .gate-note{margin-top:18px; padding-top:16px; border-top:1px solid var(--hair); font-size:14.5px; color:var(--oo-text-secondary);}
.journey .gate-note b{color:var(--oo-text-primary); font-weight:650;}

/* #aligned layout. The `.led-*` learned-rules ANIMATION that used to sit in this grid was
   REMOVED 2026-07-29 (Didier: replace the animations, keep the hero one) and replaced by a
   macOS window shot via `.oo-figure`/`.oo-shot`. 31 lines of CSS plus the ledEvent and
   ledR1-3 keyframes went with it. `.align-grid` stays: the section still uses the 2-col grid.
   The hero's own `.req-*` animation is deliberately untouched. */
.align-grid{display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px,4vw,52px); align-items:center;}

/* contrast band (what goes wrong) */
.contrast-list{margin-top:28px; display:grid; grid-template-columns:1fr 1fr; gap:14px;}
.contrast-item{display:flex; gap:13px; padding:16px 18px; border-radius:var(--r-md); background:var(--card); border:1px solid var(--hair);}
.contrast-item .x{flex:0 0 auto; width:24px; height:24px; border-radius:7px; display:grid; place-items:center;
  background:color-mix(in srgb,var(--oo-surface-status-warning) 22%,transparent); color:#8a6d00; font-weight:800; font-size:14px;}
@media (prefers-color-scheme:dark){.contrast-item .x{color:#e6cf6a;}}
.contrast-item p{font-size:14.5px; color:var(--oo-text-secondary);}
.contrast-item b{color:var(--oo-text-primary); font-weight:640;}

/* cost comparison */
.cost-compare{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:32px;}
.cost-col{border:1px solid var(--hair); border-radius:var(--r-lg); padding:24px; background:var(--card);}
.cost-col.new{border-color:color-mix(in srgb,var(--accent) 40%,transparent); background:var(--oo-surface-accent-container); color:var(--oo-on-surface-accent-container);}
.cost-tag{font-family:var(--mono); font-size:11px; letter-spacing:.08em; text-transform:uppercase; font-weight:600; color:var(--oo-text-secondary); margin-bottom:15px;}
.cost-col.new .cost-tag{color:var(--oo-on-surface-accent-container);}
.cost-col ul{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:12px;}
.cost-col li{font-size:14.5px; line-height:1.45; padding-left:24px; position:relative; color:var(--oo-text-secondary);}
.cost-col.new li{color:var(--oo-on-surface-accent-container);}
.cost-col li::before{position:absolute; left:3px; font-weight:800;}
.cost-col.old li::before{content:"\2013"; color:var(--oo-text-secondary);}
.cost-col.new li::before{content:"\2713"; left:2px; color:var(--success);}
.cost-foot{margin-top:22px; text-align:center; font-size:16.5px; font-weight:650; color:var(--oo-text-primary); letter-spacing:-.01em;}

/* marketplaces (vision) */
.vision-badge{display:inline-flex; align-items:center; gap:8px; font-family:var(--mono); font-size:11px;
  letter-spacing:.1em; text-transform:uppercase; font-weight:600; color:var(--oo-text-secondary);
  padding:6px 12px; border-radius:var(--r-full); border:1px dashed var(--oo-border-strong);}
.mkts{display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-top:34px;}
.mkt{border:1px solid var(--hair); border-radius:var(--r-lg); padding:26px; background:var(--card); position:relative; overflow:hidden;}
.mkt h3{font-size:21px;}
.mkt .sub{margin-top:10px; color:var(--oo-text-secondary); font-size:15px;}
.mkt .chips{margin-top:18px; display:flex; flex-wrap:wrap; gap:8px;}
.mkt .chip{font-size:12.5px; font-weight:600; padding:7px 12px; border-radius:var(--r-full);
  background:var(--oo-surface-surface-raised); border:1px solid var(--hair);}
.mkt .toggle{margin-top:18px; display:flex; gap:8px;}
.mkt .toggle span{flex:1; text-align:center; font-size:13px; font-weight:640; padding:10px; border-radius:var(--r-sm); border:1px solid var(--hair);}
.mkt .toggle span.on{background:var(--oo-surface-accent-container); color:var(--oo-on-surface-accent-container); border-color:color-mix(in srgb,var(--accent) 40%,transparent);}
.seller-cta{margin-top:18px; display:flex; align-items:center; justify-content:space-between; gap:18px; flex-wrap:wrap;
  padding:18px 22px; border-radius:var(--r-lg); border:1px solid var(--hair); background:var(--oo-surface-surface-raised);}
.seller-cta__t{font-size:15px; color:var(--oo-text-secondary); max-width:62ch;}
.seller-cta__t b{color:var(--oo-text-primary); font-weight:650;}
.seller-cta .btn{flex:0 0 auto;}

/* principles */
.principles{display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-top:34px;}
.principle{padding:20px; border-radius:var(--r-md); border:1px solid var(--hair); background:var(--card);}
.principle .ic{width:34px; height:34px; border-radius:9px; display:grid; place-items:center; margin-bottom:14px;
  background:var(--oo-surface-accent-container); color:var(--oo-on-surface-accent-container);}
.principle .ic svg{width:18px; height:18px;}
.principle h3{font-size:16px;} .principle p{margin-top:7px; font-size:13.5px; color:var(--oo-text-secondary);}
.pledge-handoff{margin:28px auto 0; max-width:64ch; text-align:center; font-size:15.5px; line-height:1.5;
  color:var(--oo-text-secondary);}
.pledge-handoff b{color:var(--oo-text-primary); font-weight:650;}

/* final CTA — dark closing band; var(--ink) is dark in both themes */
.finale{background:var(--ink); color:#e4ebf3; border-radius:var(--r-xl); padding:clamp(36px,6vw,64px);
  margin:0 auto; max-width:760px; text-align:center; box-shadow:var(--shadow-lg);}
.finale h2{color:#fff; font-size:clamp(28px,3.6vw,40px);}
.finale .lede{color:#aebfd4; margin:16px auto 0; max-width:54ch;}
/* `.finale-form` removed 2026-07-26: TrueAlign's closing waitlist is no longer hand-written HTML inside the
   DSL, it is a real `emailCapture` section rendered by MarketingPageRenderer, so nothing carried that class.
   The `.finale` band rules above are ALSO unmatched now for the same reason. They are kept, not deleted,
   because they describe a DESIGN (the dark closing band) that the generic emailCapture section does not have a
   channel for; restoring it needs a decision, not a renderer guess. See the stage report. */
.finale .cta-note{color:#93a6bd; justify-content:center;}

/* ── TrueAlign approval LOOP (2026-08-05) — replaced truealign-pipeline.webp ────────────────────
   Was a four-card straight line in a .webp, with "later changes come back to the gate" as a
   footnote under it. A closed RING states that structurally: work leaves the gate, goes live, and
   comes back. All copy now lives in the DSL (OOApprovalLoop) instead of inside the image.

   LAYOUT: the <ol> is the source of truth for ORDER; the ring is CSS placement on top of it. Each
   node carries `--i` (its index) and the container `--n` (the count), so the angle is computed —
   a fifth node re-spaces itself with no new CSS. Nodes are positioned with a rotate/translate pair
   and then counter-rotated so their TEXT stays upright.
   The 50%/-50% translate centres each node on its point; `--r` is the ring radius. */
/* ── THE INTAKE ───────────────────────────────────────────────────────────────────────────────
   One outcome in, sub-tasks out. It sits ABOVE the ring and feeds into it, because the ring's first
   node is at 0° (top dead centre) so the feed lands straight in, and one stacked arrangement works
   at every width. Sized to the ring so the two read as one diagram rather than two blocks.

   Timing shares the loop's `--dur`, and everything here is expressed as a FRACTION of it, so the
   intake stays in step with the ring no matter what the duration is set to. The sequence: the
   outcome lands, the AI answers, the sub-tasks appear one after another, then they travel down the
   feed. Each sub-task's `--k` staggers its own entrance. */
/* The bottom padding exists to hold the feed pipe, so it only applies where the pipe does. */
.ta-intake{position:relative; width:min(100%, 620px); margin:0 auto; text-align:center;
  padding-bottom:10px;}
@media (min-width:761px){ .ta-intake{padding-bottom:52px;} }
.ta-intake__icon{display:flex; justify-content:center; color:var(--oo-text-secondary); margin-bottom:6px;}
.ta-intake__kicker{margin:0; letter-spacing:.10em; text-transform:uppercase;
  color:var(--oo-text-secondary); font-size:.7rem;}
.ta-intake__title{margin:4px 0 0; font-weight:800; line-height:1.2;}
/* The outcome reads as something the reader SAID, so it is a quote, not an input. It must never
   look like a field this page is collecting. */
/* The outcome as SPOKEN (Instagram voice-note / Magnific command-palette pattern: wave inline with
   the transcript, one rounded container). The frame fades in fast; the wave and words own the
   "speaking" window. */
.ta-intake__outcome{margin:14px auto 0; max-width:34ch; padding:12px 18px;
  border:1px dashed var(--oo-border-strong); border-radius:var(--oo-radius-lg);
  background:var(--oo-surface-surface-raised); font-weight:700;
  display:flex; align-items:center; gap:12px; text-align:left;
  animation:ta-intake-outcome var(--dur) linear infinite;}
/* Equalizer bars. Two animations per bar: a fast bounce that never stops (each bar's own duration
   and negative delay come from `--b`, so the cluster moves organically, not in lockstep) and a gate
   on the loop's master clock that holds the bars bright while the words are being "spoken", then
   drops them to an idle shimmer, the way a voice UI rests after the command lands. */
.ta-intake__wave{display:flex; align-items:center; gap:3px; flex:none; height:22px;}
.ta-intake__wave span{width:3px; height:18px; border-radius:var(--oo-radius-full);
  background:var(--oo-surface-accent-solid);
  animation:ta-wave-bounce calc(.5s + var(--b) * .13s) ease-in-out calc(var(--b) * -.19s) infinite alternate,
            ta-wave-gate var(--dur) linear infinite both;}
.ta-intake__words{flex:1; min-width:0;}
/* Word-by-word materialization: blur-and-rise in, on a per-word delay across the speaking window.
   Split at render time; the copy is still one authored string. fill-mode both keeps a word hidden
   until its own delay has elapsed on the very first cycle. */
.ta-intake__word{display:inline-block;
  animation:ta-word var(--dur) linear infinite both;
  animation-delay:calc(var(--dur) * (.02 + .10 * var(--w) / var(--words)));}
.ta-intake__breakdown{margin:14px 0 0; color:var(--oo-text-secondary); font-size:.86rem;
  animation:ta-intake-breakdown var(--dur) linear infinite;}
.ta-intake__subtasks{list-style:none; margin:12px 0 0; padding:0;
  display:flex; flex-wrap:wrap; gap:8px; justify-content:center;}
.ta-intake__subtask{border-radius:var(--oo-radius-full); padding:5px 13px; white-space:nowrap;
  font-size:.72rem; font-weight:700; letter-spacing:.04em;
  background:var(--oo-surface-accent-solid); color:var(--oo-on-surface-accent-solid);
  animation:ta-intake-subtask var(--dur) linear infinite both;
  animation-delay:calc(var(--k) * var(--dur) / 30);}
/* The pipe into the ring. A dashed line the sub-tasks visibly run down, so "these feed the loop" is
   shown rather than asserted; the moving dot is what makes it a pipe instead of a divider.
   HIDDEN below the ring breakpoint: in the rail layout the hub sits between the intake and the first
   node, so the pipe would point at the centre HEADING rather than at Plan, which is worse than no
   pipe at all. The rail is already a downward flow, so the intake stacked above it reads without one. */
.ta-intake__feed{display:none; position:absolute; left:50%; bottom:6px; width:2px; height:40px;
  transform:translateX(-50%); background:repeating-linear-gradient(to bottom,
    var(--oo-border-strong) 0 4px, transparent 4px 9px);}
@media (min-width:761px){ .ta-intake__feed{display:block;} }
.ta-intake__feed::after{content:""; position:absolute; left:50%; top:0; width:7px; height:7px;
  border-radius:50%; background:var(--oo-surface-accent-solid);
  animation:ta-intake-feed var(--dur) linear infinite;}

/* One narrative per cycle, every number a fraction of the same clock:
     0-2%    the bubble frame lands
     2-14%   the wave is live and the words are spoken in
     15-19%  the AI answers (breakdown line)
     20-28%  the sub-task chips pop in, staggered
     30-44%  three dots run down the feed, one per sub-task, into the ring
     92-100% the whole intake dims and resets for the next outcome */
@keyframes ta-intake-outcome{
  0%       {opacity:0; transform:translateY(6px);}
  2%, 90%  {opacity:1; transform:translateY(0);}
  96%, 100%{opacity:.3; transform:translateY(0);}
}
@keyframes ta-wave-gate{
  0%       {opacity:0;}
  1%, 14%  {opacity:1;}
  17%, 92% {opacity:.28;}
  100%     {opacity:.28;}
}
@keyframes ta-word{
  0%        {opacity:0; transform:translateY(5px); filter:blur(4px);}
  1.2%, 90% {opacity:1; transform:translateY(0);   filter:blur(0);}
  96%, 100% {opacity:0; transform:translateY(0);   filter:blur(2px);}
}
@keyframes ta-intake-breakdown{
  0%, 14%  {opacity:0;}
  19%, 90% {opacity:1;}
  96%, 100%{opacity:.3;}
}
@keyframes ta-intake-subtask{
  0%, 20%  {opacity:0; transform:translateY(-6px) scale(.9);}
  23%, 90% {opacity:1; transform:translateY(0) scale(1);}
  96%, 100%{opacity:.3; transform:translateY(0) scale(1);}
}
/* One dot, three passes: each chip dispatches down the pipe right after the row settles. */
@keyframes ta-intake-feed{
  0%, 30%    {opacity:0; transform:translate(-50%, 0);}
  31%        {opacity:1; transform:translate(-50%, 2px);}
  34%        {opacity:1; transform:translate(-50%, 34px);}
  34.5%      {opacity:0; transform:translate(-50%, 38px);}
  35%        {opacity:0; transform:translate(-50%, 0);}
  36%        {opacity:1; transform:translate(-50%, 2px);}
  39%        {opacity:1; transform:translate(-50%, 34px);}
  39.5%      {opacity:0; transform:translate(-50%, 38px);}
  40%        {opacity:0; transform:translate(-50%, 0);}
  41%        {opacity:1; transform:translate(-50%, 2px);}
  44%        {opacity:1; transform:translate(-50%, 34px);}
  44.5%, 100%{opacity:0; transform:translate(-50%, 38px);}
}

/* BASE = the vertical sequence: correct everywhere, and the fallback if a browser lacks the ring's
   requirements. The ring is layered on top as an ENHANCEMENT further down, so nothing ever collapses
   into an unreadable pile. */
.ta-loop{position:relative; margin-top:40px; width:100%; padding-left:26px;}
.ta-loop__ring{display:none;}
.ta-loop__hub{margin-bottom:18px; text-align:center;}
.ta-loop__hub-label{margin:0; font-weight:800;}
.ta-loop__hub-note{margin:6px 0 0; color:var(--oo-text-secondary); font-size:.86rem;}
.ta-loop__nodes{list-style:none; margin:0; padding:0 0 0 20px; display:flex; flex-direction:column;
  gap:14px; border-left:2px dashed var(--oo-border-strong); margin-left:4px;}
.ta-loop__node{background:var(--oo-surface-surface-raised); border:1px solid var(--oo-border-subtle);
  border-radius:var(--oo-radius-lg); padding:14px 16px; text-align:left;
  box-shadow:0 6px 20px rgba(0,0,0,.10);}
/* The rail turns back on itself, so the LOOP survives the linear layout instead of reading as a
   one-way list that happens to stop. */
/* (The old rail-only `::after` "back to the gate" line is GONE: it was copy living in a CSS
   `content:` rule, invisible to the copy pipeline, and stale two node-renames later. Its job is
   done by the DSL-authored redo badge in `.ta-loop__outcomes` below.) */
.ta-loop__icon{display:flex; justify-content:flex-start; color:var(--oo-text-secondary); margin-bottom:6px;}
.ta-loop__kicker{margin:0; letter-spacing:.10em; text-transform:uppercase;
  color:var(--oo-text-secondary); font-size:.7rem;}
.ta-loop__title{margin:4px 0 0; font-weight:800; line-height:1.2;}
.ta-loop__detail{margin:4px 0 0; color:var(--oo-text-secondary); font-size:.86rem;}
.ta-loop__chips{display:flex; flex-wrap:wrap; gap:6px; justify-content:flex-start; margin-top:8px;}
.ta-loop__chip{border-radius:var(--oo-radius-full); padding:2px 10px; font-size:.72rem;
  background:var(--oo-surface-surface-base); border:1px solid var(--oo-border-subtle);}
/* THE GATE is the section's argument, so it carries the accent the way it did in the illustration. */
.ta-loop__node[data-node="humans"]{background:var(--oo-surface-accent-solid);
  color:var(--oo-on-surface-accent-solid); border-color:transparent;}
.ta-loop__node[data-node="humans"] .ta-loop__kicker,
.ta-loop__node[data-node="humans"] .ta-loop__detail,
.ta-loop__node[data-node="humans"] .ta-loop__icon{color:inherit; opacity:.86;}
.ta-loop__node[data-node="humans"] .ta-loop__chip{background:rgba(255,255,255,.22);
  border-color:transparent; color:inherit; font-weight:700;}
/* THE FORK — done exits, sent-back loops. Base (rail) layout: a row of two badges after the last
   node, aligned with the cards. The DEAD-END and the U-TURN of the diagram, in the status tokens
   those meanings already own (success / warning), so the two outcomes are told apart by colour
   before the words are even read. */
.ta-loop__return{display:none;}
.ta-loop__done-ramp{display:none;}
.ta-loop__outcomes{display:flex; flex-wrap:wrap; gap:10px; margin:14px 0 0 24px; align-items:center;}
.ta-loop__done-badge, .ta-loop__redo-badge{display:inline-flex; align-items:center; gap:7px;
  border-radius:var(--oo-radius-full); padding:6px 14px; white-space:nowrap;
  font-size:.72rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;}
.ta-loop__done-badge{background:var(--oo-surface-status-success); color:var(--oo-on-surface-status-success);
  animation:ta-done-pop var(--dur) linear infinite;}
.ta-loop__redo-badge{background:var(--oo-surface-status-warning); color:var(--oo-on-surface-status-warning);
  animation:ta-redo-glow var(--dur) linear infinite;}
/* The classic pulse ring: the shadow is born at zero spread in the badge's own colour and dies
   expanded and transparent, so it reads as a radiating ping rather than a resize. Fires at ~50%,
   which is the moment the done dot (ring layout) finishes its run down the exit ramp. */
@keyframes ta-done-pop{
  0%, 48%  {transform:scale(1);    box-shadow:0 0 0 0 transparent;}
  50%      {transform:scale(1.14); box-shadow:0 0 0 0 var(--oo-surface-status-success);}
  56%      {transform:scale(1);    box-shadow:0 0 0 12px transparent;}
  57%, 100%{transform:scale(1);    box-shadow:0 0 0 0 transparent;}
}
@keyframes ta-redo-glow{
  0%, 76%  {transform:scale(1);    filter:none;}
  81%      {transform:scale(1.10); filter:brightness(1.15);}
  86%, 92% {transform:scale(1);    filter:brightness(1.15);}
  96%, 100%{transform:scale(1);    filter:none;}
}
/* Sits AFTER the `.hero *, .section *{margin:0}` reset above, same specificity, so the margin holds.
   Generous on purpose: this line is the loop's conclusion, and crowding it against the last card read
   as a caption on that card rather than a statement about the whole cycle. */
.ta-loop__note{margin:52px auto 0; max-width:60ch; text-align:center; color:var(--oo-text-secondary);}
/* Direction markers exist only with the ring (the vertical fallback shows its own return line). */
.ta-loop__arrow{display:none;}

/* ── THE LOOP, RUNNING ────────────────────────────────────────────────────────────────────────
   One clock (`--dur`) drives everything, and every timing is derived from the node's own `--i`,
   so the animation stays in step with the geometry: node i lights at i/n of the cycle, which is
   exactly when the orbiting packet reaches it. Add a fifth node in the DSL and the choreography
   re-times itself along with the placement — no hand-tuned delays to forget to update.

   The packet rides UNDER the cards (z-index below `.ta-loop__nodes`) on purpose. It slides behind
   each card and emerges the other side, which reads as the work entering a stage and coming out of
   it — a packet skating over the top would just look like a loose dot. */
/* ONE clock for the whole section. Declared on BOTH roots because the intake is the loop's SIBLING,
   not its child — declared on .ta-loop alone, var(--dur) was invalid throughout the intake, which
   made every intake `animation` shorthand compute to NONE. Nothing errored: the chips, words and
   feed dot just sat in their static base styles, and screenshots of "the animation" were really
   screenshots of the fallback. If these two ever get a common dedicated wrapper, hoist it there. */
.ta-intake, .ta-loop{--dur:18s;}
.ta-loop__orbit{display:none;}
.ta-loop__node{position:relative;}          /* containing block for the gate's stamp, both layouts */

@keyframes ta-loop-pulse{
  0%       {border-color:var(--oo-surface-accent-solid); box-shadow:0 0 0 4px var(--oo-surface-accent-subtle);}
  10%      {border-color:var(--oo-surface-accent-solid); box-shadow:0 0 0 0 transparent;}
  26%, 100%{border-color:var(--oo-border-subtle);        box-shadow:0 0 0 0 transparent;}
}
/* The gate is exempt: its border is ALREADY the accent, so a border pulse there says nothing.
   It answers the arriving work by stamping it instead — the one node that acts, acting. */
.ta-loop__node:not([data-node="humans"]){
  animation:ta-loop-pulse var(--dur) linear infinite;
  animation-delay:calc(var(--i) * var(--dur) / var(--n));
}

/* The carrier hands off down the rail: node i shows it for its quarter of the cycle, fading out as
   the next fades in, so "the work" is always somewhere and never in two places. Same delay formula as
   the pulse, so the lit card and the label it is holding are always the same card. Sits on the rail
   at the card's top-left, which is why it reads as riding the line rather than labelling the box. */
@keyframes ta-loop-carry{
  0%       {opacity:0; transform:translateY(7px) scale(.9);}
  3%       {opacity:1; transform:translateY(0)   scale(1);}
  22%      {opacity:1; transform:translateY(0)   scale(1);}
  27%, 100%{opacity:0; transform:translateY(-7px) scale(.95);}
}
.ta-loop__carrier{position:absolute; left:-15px; top:-13px; opacity:0; z-index:2;
  border-radius:var(--oo-radius-full); padding:5px 13px; white-space:nowrap;
  font-size:.72rem; font-weight:700; letter-spacing:.04em;
  background:var(--oo-surface-accent-solid); color:var(--oo-on-surface-accent-solid);
  box-shadow:0 6px 18px rgba(0,0,0,.28);
  animation:ta-loop-carry var(--dur) linear infinite;
  animation-delay:calc(var(--i) * var(--dur) / var(--n));}

@keyframes ta-loop-stamp{
  0%       {opacity:0; transform:rotate(-9deg) scale(.6);}
  4%       {opacity:1; transform:rotate(-9deg) scale(1.06);}
  8%       {opacity:1; transform:rotate(-9deg) scale(1);}
  24%      {opacity:1; transform:rotate(-9deg) scale(1);}
  34%, 100%{opacity:0; transform:rotate(-9deg) scale(1);}
}
.ta-loop__stamp{position:absolute; top:-11px; right:-11px; opacity:0;
  border-radius:var(--oo-radius-full); padding:3px 11px; font-size:.72rem; font-weight:800;
  letter-spacing:.08em; text-transform:uppercase; white-space:nowrap;
  background:var(--oo-surface-surface-raised); color:var(--oo-text-primary);
  border:1.5px solid var(--oo-surface-accent-solid);
  animation:ta-loop-stamp var(--dur) linear infinite;
  animation-delay:calc(var(--i) * var(--dur) / var(--n));}

/* Motion here is decoration on top of a diagram that already reads statically, so reduced-motion
   drops it entirely rather than substituting a gentler version. The stamp stays VISIBLE (not
   animated) so its words are not lost — it is authored copy, not an effect. */
@media (prefers-reduced-motion: reduce){
  .ta-loop__node:not([data-node="humans"]), .ta-loop__stamp, .ta-loop__orbit, .ta-loop__packet,
  .ta-loop__carrier, .ta-intake__outcome, .ta-intake__breakdown, .ta-intake__subtask,
  .ta-intake__feed::after, .ta-intake__wave span, .ta-intake__word,
  .ta-loop__return, .ta-loop__done-ramp::after, .ta-loop__done-badge, .ta-loop__redo-badge{
    animation:none !important;}
  /* The intake's copy is CONTENT, not effect, so it stays fully legible with the motion removed
     (its keyframes fade things in, which without animation would leave them at the 0% state).
     The wave freezes as full-height bars (its base styles), the words sit at full opacity, and
     both fork badges stand still — their words are claims, not effects. Travelling dots go. */
  .ta-intake__outcome, .ta-intake__breakdown, .ta-intake__subtask{opacity:1; transform:none;}
  .ta-intake__feed::after{display:none;}
  .ta-loop__done-ramp::after{display:none;}
  .ta-loop__stamp{opacity:1; transform:rotate(-9deg);}
  /* The carrier's whole meaning is WHICH node holds the work right now. Frozen it would assert one
     stage forever, so it goes rather than parking somewhere and lying. The stamp stays because its
     word is true of the gate whether or not anything is moving. */
  .ta-loop__carrier{display:none;}
}

/* THE RING — enhancement only, and only where it can actually be read:
     • ≥761px, because four cards on a circle at phone width is a pile, not a diagram; and
     • only where CSS trig exists, since the placement is genuinely computed (see below).
   Placement uses `top`/`left`, whose percentages resolve against the CONTAINER — the reason the
   first attempt failed: a percentage inside `translate()` resolves against the NODE'S OWN box, so
   every node sat ~48px from the centre instead of ~236px. `--i` (index) and `--n` (count) mean a
   fifth node re-spaces itself with no new CSS, and the nodes stay upright with no counter-rotation. */
@supports (top: calc(1% * sin(45deg))){
  @media (min-width:761px){
    .ta-loop{aspect-ratio:1; width:min(100%, 620px); margin-inline:auto; padding-left:0; --r:38%;}
    /* The base ring is CLIPPED OUT of the last-node → first-node quadrant (top-left), and the
       revision lane below is clipped INTO exactly that quadrant: two complementary clip-paths on the
       same circle, so together they read as one ring whose final stretch is a different road. The
       cuts land at 0° and 270°, dead behind the plan and software cards, so no raw line-end shows. */
    .ta-loop__ring{display:block; position:absolute; inset:12%; border-radius:50%;
      border:1px dashed var(--oo-border-strong); opacity:.55;
      clip-path:polygon(50% 0, 100% 0, 100% 100%, 0 100%, 0 50%, 50% 50%);}
    .ta-loop__return{display:block; position:absolute; inset:12%; border-radius:50%;
      border:2px dashed var(--oo-surface-status-warning); opacity:.55;
      clip-path:polygon(0 0, 50% 0, 50% 50%, 0 50%);
      animation:ta-return-glow var(--dur) linear infinite;}
    /* The lane glows exactly while a sub-task is riding it home: pill k=0's wrapper sweeps the
       270°→360° quadrant during the last quarter of the master cycle. */
    @keyframes ta-return-glow{
      0%, 76%  {opacity:.55;}
      82%, 94% {opacity:1;}
      100%     {opacity:.55;}
    }
    /* The hub has to fit the gap the ring leaves BETWEEN the left and right nodes, or its text runs
       underneath them (it did at first: a 348px hub in a 262px gap). Derived, not eyeballed — the
       side nodes sit at ±--r and are `--node-w` wide, so the clear span is
       2·--r − --node-w − breathing room, and it re-derives itself if either value changes. */
    .ta-loop{--node-w:min(42%, 210px);}
    .ta-loop__hub{position:absolute; inset:0; display:flex; flex-direction:column;
      align-items:center; justify-content:center; padding:0; margin:0; pointer-events:none;}
    .ta-loop__hub > *{max-width:calc(2 * var(--r) - var(--node-w) - 28px); margin-inline:auto;}
    .ta-loop__nodes{position:absolute; inset:0; display:block; padding:0; margin:0;
      border-left:0;}
    /* On the ring the wrapper dissolves so the two outcomes can place themselves on the diagram. */
    .ta-loop__outcomes{display:contents;}
    /* DONE exits the ring: a ramp drops from the software node into the bottom-left corner of the
       square, which the circle leaves genuinely empty, and the badge waits at its foot. The dot
       departs at ~42% — the moment pill k=1 passes the software node — and the badge's pulse
       answers its arrival at ~50%. Same clock as everything else. */
    .ta-loop__done{position:absolute; left:8%; top:62%; transform:translateX(-50%);
      display:flex; flex-direction:column; align-items:center; gap:8px; z-index:2;}
    .ta-loop__done-ramp{display:block; position:relative; width:2px; height:84px;
      background:repeating-linear-gradient(to bottom,
        var(--oo-surface-status-success) 0 4px, transparent 4px 9px); opacity:.7;}
    .ta-loop__done-ramp::after{content:""; position:absolute; left:50%; top:0;
      width:7px; height:7px; border-radius:50%; background:var(--oo-surface-status-success);
      transform:translateX(-50%);
      animation:ta-done-dot var(--dur) linear infinite;}
    @keyframes ta-done-dot{
      0%, 42%  {opacity:0; transform:translate(-50%, 0);}
      43%      {opacity:1; transform:translate(-50%, 4px);}
      49%      {opacity:1; transform:translate(-50%, 76px);}
      50%, 100%{opacity:0; transform:translate(-50%, 80px);}
    }
    /* SENT BACK rides the lane: the tag sits at the arc's 315° point, ROTATED to the lane's tangent
       there so it reads as travelling the road it labels — and the rotation is also what clears the
       plan card: upright, the tag's width reached the card's left edge. */
    .ta-loop__redo{position:absolute; left:17%; top:21%;
      transform:translate(-50%, -50%) rotate(-45deg); z-index:2;}
    .ta-loop__node{position:absolute; width:var(--node-w); text-align:center;
      --a:calc(var(--i) * 360deg / var(--n));
      left:calc(50% + var(--r) * sin(var(--a)));
      top:calc(50% - var(--r) * cos(var(--a)));
      transform:translate(-50%, -50%);}
    .ta-loop__icon{justify-content:center;}
    .ta-loop__chips{justify-content:center;}
    /* Each arrow sits ON the ring in a node GAP, rotated to point along the circle so the eye
       follows it clockwise. A SOLID triangle (the classic zero-size border trick) rather than two
       borders forming a corner: at this size a corner reads as a crop/registration mark, not as
       direction — which is exactly how the first attempt looked. The triangle points UP at rest, so
       the tangent needs --a + 90°. No glyph, no font, and it inherits the ring's colour. */
    .ta-loop__arrow{display:block; position:absolute; width:0; height:0;
      --a:calc(var(--i) * 360deg / var(--n));
      left:calc(50% + var(--r) * sin(var(--a)));
      top:calc(50% - var(--r) * cos(var(--a)));
      border-left:6px solid transparent; border-right:6px solid transparent;
      border-bottom:10px solid var(--oo-border-strong);
      transform:translate(-50%, -50%) rotate(calc(var(--a) + 90deg));}
    /* The arrow in the revision quadrant wears the lane's colour (arrows are the only direct span
       children of .ta-loop, so nth-of-type(4) is the software→plan gap). */
    .ta-loop > .ta-loop__arrow:nth-of-type(4){border-bottom-color:var(--oo-surface-status-warning);}

    /* The orbiting packet. Two counter-rotating layers: the wrapper sweeps the full circle while the
       pill spins back at the same rate, so the label stays upright the whole way round instead of
       cartwheeling. Both share `--dur`, so they can never drift apart.
       Stacking: packet(1) under cards(3) so it passes BEHIND each one; hub(2) between, so the centre
       text is never crossed by a moving object while you are reading it. */
    /* On the ring the orbiting pill does this job properly, travelling the whole circle, so the
       per-node carriers stand down rather than double-announcing it. */
    .ta-loop__carrier{display:none;}
    /* The gate card hangs near the bottom of the square, so the conclusion needs more air here than
       it does under the rail to read as separate from that card. */
    .ta-loop__note{margin-top:64px;}
    /* One orbit per sub-task, spread around the ring by a NEGATIVE delay (which starts an animation
       partway through rather than postponing it), so all of them are in flight from the first frame
       at evenly spaced points. `--k`/`--tasks` come from the renderer, so the spacing follows the
       number of sub-tasks the DSL authors instead of being hand-tuned for three. */
    .ta-loop__orbit{display:block; position:absolute; inset:0; z-index:1; pointer-events:none;
      animation:ta-loop-orbit var(--dur) linear infinite;
      animation-delay:calc(-1 * var(--k) * var(--dur) / var(--tasks));}
    .ta-loop__hub{z-index:2;}
    .ta-loop__nodes{z-index:3;}
    .ta-loop__packet{position:absolute; left:50%; top:calc(50% - var(--r));
      display:block; border-radius:var(--oo-radius-full); padding:5px 13px; white-space:nowrap;
      background:var(--oo-surface-accent-solid); color:var(--oo-on-surface-accent-solid);
      box-shadow:0 6px 18px rgba(0,0,0,.28);
      animation:ta-loop-packet var(--dur) linear infinite;
      /* matches its own orbit's offset, or the pill would counter-rotate out of step and tilt */
      animation-delay:calc(-1 * var(--k) * var(--dur) / var(--tasks));}
    .ta-loop__packet-label{font-size:.72rem; font-weight:700; letter-spacing:.04em;}
    @keyframes ta-loop-orbit{from{transform:rotate(0deg);} to{transform:rotate(360deg);}}
    @keyframes ta-loop-packet{
      from{transform:translate(-50%, -50%) rotate(0deg);}
      to  {transform:translate(-50%, -50%) rotate(-360deg);}
    }
  }
}

/* responsive */
@media (max-width:900px){
  .hero-grid,.align-grid,.finale{grid-template-columns:1fr;}
  .journeys,.mkts,.contrast-list,.cost-compare{grid-template-columns:1fr;}
  .steps{grid-template-columns:repeat(2,1fr);}
  .principles{grid-template-columns:1fr 1fr;}
  .loop{max-width:560px; margin:8px auto 0;}
  .led{max-width:560px;}
}
@media (max-width:520px){
  .principles{grid-template-columns:1fr;}
  .steps{grid-template-columns:1fr;}
  .hero h1{font-size:clamp(30px,8.6vw,40px);}
}

/* ── Landing v2: per-pillar quiet CTA + the honest trust strip (2026-07-20) ────────────────────
   .mo-feature__cta renders under each pillar caption (Landing_Craft §5: a CTA after each major
   block — value-phrased, quiet, never competing with the demo). .mo-trust is the four-chip strip
   of ONLY-true facts between the data pillar and the closing CTA (zero-proof protocol: the
   testimonial/count omission is recorded in the DSL). Tokens only; floor ≥.72rem. */
.mo-feature__cta{display:inline-block;margin-top:10px;color:var(--oo-surface-accent-solid);font-size:.95rem;font-weight:700;
  text-decoration:none;border-bottom:1px solid transparent;}
.mo-feature__cta:hover{border-bottom-color:var(--oo-surface-accent-solid);}
.mo-trust{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;max-width:840px;margin:0 auto;   /* 900 fit exactly 3 chips → lone 4th orphan at 1440; 840 wraps 2+2 */
  padding:26px var(--oo-space-lg);}
.mo-trust span{font-size:.85rem;color:var(--oo-text-secondary);border:1px solid var(--oo-border-subtle);
  border-radius:var(--oo-radius-full);padding:7px 15px;text-wrap:balance;}   /* balanced 2-liners, no "ins" orphan (FIX-15) */
.mo-trust span b{color:var(--oo-text-primary);font-weight:650;}

/* ============================== hero background image + legibility panel (item 5) ==============================
   Opt-in via the hero's `bgImage` (DSL) → the renderer adds `.ln-hero--bg` + a `.ln-hero__bg` layer carrying an
   inline background-image. A translucent, blurred, edge-masked panel sits behind the copy so any abstract art
   keeps the H1/lede/CTA legible. Layout + token values only. Modeled on the proven `.mo-hero__copy::before`. */
    .ln-hero--bg{position:relative;overflow:hidden;isolation:isolate;display:flex;align-items:center;min-height:72svh;}
    /* The renderer supplies the two URLs as INLINE CUSTOM PROPERTIES (--oo-hero-img / --oo-hero-img-light)
       and this stylesheet owns `background-image`. That split matters: an inline property always beats a
       stylesheet rule, so if the renderer set `background-image` directly no media query could ever swap it
       (see Memory/inline-var-beats-stylesheet-state-rules). Light falls back to the dark URL when a brand
       has no light twin, so a missing asset degrades instead of rendering an empty hero. */
    .ln-hero--bg .ln-hero__bg{position:absolute;inset:0;z-index:0;background-size:cover;background-position:center;
      background-image:var(--oo-hero-img);}
    @media(prefers-color-scheme:light){
      .ln-hero--bg .ln-hero__bg{background-image:var(--oo-hero-img-light,var(--oo-hero-img));}}
    /* a soft brand-tinted veil unifies the art with the page + lifts overall contrast */
    .ln-hero--bg::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
      background:radial-gradient(130% 100% at 50% 38%, transparent 40%, color-mix(in srgb,var(--oo-surface-surface-base) 46%, transparent) 100%);}
    .ln-hero--bg > .ln-wrap{position:relative;z-index:1;width:100%;}
    /* the semi-translucent legible panel behind the hero copy (edges feathered so it isn't a hard box) */
    .ln-hero--bg > .ln-wrap::before{content:"";position:absolute;z-index:-1;
      top:calc(-1 * var(--oo-space-xl));bottom:calc(-1 * var(--oo-space-xl));
      left:50%;transform:translateX(-50%);width:min(46rem,calc(100% - 1.5rem));border-radius:var(--oo-radius-lg);   /* 0.75rem inside the screen edges (FIX-4); phones also widen the wrap padding so text keeps air to the panel edge */
      background:color-mix(in srgb,var(--oo-surface-surface-base) 72%,transparent);
      -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(6px);
      -webkit-mask:radial-gradient(125% 100% at 50% 45%,#000 60%,transparent 100%);
              mask:radial-gradient(125% 100% at 50% 45%,#000 60%,transparent 100%);}
    @media(prefers-reduced-motion:reduce){.ln-hero--bg .ln-hero__bg{background-attachment:scroll;}}
    /* phones: extra wrap padding so the hero TEXT keeps ~1.5rem of air to the panel edge */
    @media(max-width:600px){.ln-hero--bg > .ln-wrap{padding-inline:calc(var(--oo-space-lg) + 1rem);}}

/* ============================== platform cards as OG social-preview cards (item 3) ==============================
   When a platform card targets a known site, the renderer draws it as that site's shared-link preview:
   its /og/<key>.png + exported meta.title/description + the canonical domain. New classes only — no override
   of the base `.ln-card`/`.mk-platform` behavior beyond padding (so the image can go flush to the rounded edge). */
    .ln-card.mk-og{padding:0;overflow:hidden;display:flex;flex-direction:column;}   /* 0,2,0 — the later `.ln-card{padding:…}` was overriding the bare .mk-og rule (FIX-5) */
    /* height:auto is REQUIRED — the <img width=1200 height=630> attributes otherwise fix the height at
       630px, which disables aspect-ratio and makes object-fit:cover crop to a tall slice. flex:none keeps
       the image at its true 1200/630 landscape; the body flexes to absorb any grid-equal-height stretch. */
    .mk-og__img{display:block;width:100%;height:auto;aspect-ratio:1200/630;object-fit:cover;flex:none;
      background:var(--oo-surface-surface-base);border-bottom:1px solid var(--oo-border-subtle);}
    /* Light theme swaps the card via a background-image on the wrapper, NOT a second <img>. Two <img>
       elements toggled by display looked cleaner but never loaded: a loading="lazy" image that starts out
       display:none is not fetched, and revealing it later does not reliably trigger the load, so the card
       rendered blank. Here the lazy <img> being display:none in light theme is exactly what we want, since
       it means only ONE 1200x630 card is ever downloaded per theme. `<picture>` would be the native answer
       but is unavailable in this swift-html build. */
    .mk-og__media{display:block;width:100%;aspect-ratio:1200/630;flex:none;
      background-size:cover;background-position:center;
      border-bottom:1px solid var(--oo-border-subtle);}
    @media(prefers-color-scheme:light){
      .mk-og__media{background-image:var(--oo-og-light);}
      .mk-og__img{display:none;}}
    .mk-og__body{padding:var(--oo-space-lg);display:flex;flex-direction:column;gap:var(--oo-space-xs);flex:1 1 auto;}
    /* EVENT GRID (2026-08-03; cards not pills 2026-08-04): the brand's event landings at the FOOT of the
       card. The card is no longer one big <a> — a link inside a link is invalid HTML and browsers reparent
       it (the row float we already fixed once), so the OG block is the link and these are siblings under it.
       Each event is now its own /og/<slug>.png social-preview card rather than a text pill. A brand with no
       events renders nothing at all — the renderer omits the block rather than leaving an empty shell. */
    .mk-og__link{display:flex;flex-direction:column;flex:1 1 auto;text-decoration:none;color:inherit;}
    .mk-og__events{padding:0 var(--oo-space-lg) var(--oo-space-lg);display:flex;flex-direction:column;gap:var(--oo-space-xs);}
    .mk-og__events-label{font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--oo-text-secondary);
      text-decoration:none;align-self:flex-start;min-height:24px;display:inline-flex;align-items:center;}
    .mk-og__events-label:hover,.mk-og__events-label:focus-visible{color:var(--oo-surface-accent-solid);text-decoration:underline;}
    /* MAX 2 PER ROW (Didier, 2026-08-04). The 45% floor is what enforces it: three tracks would need
       135% of the row, so auto-fit can never place more than two — and because it is auto-FIT (not
       auto-fill) a lone event still stretches across the whole row instead of leaving a dead column.
       The 9rem term collapses the grid to one column inside a narrow card, where two 1200x630 cards
       side by side would be illegible. */
    .mk-og__events-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(max(45%,9rem),1fr));gap:var(--oo-space-sm);}
    .mk-og__event{display:block;border-radius:var(--oo-radius-md);overflow:hidden;
      border:1px solid var(--oo-border-subtle);background:var(--oo-surface-surface-base);
      color:inherit;text-decoration:none;}
    .mk-og__event:hover,.mk-og__event:focus-visible{border-color:var(--oo-surface-accent-solid);}
    /* Same one-image-per-theme shape as .mk-og__media/.mk-og__img above: in light theme the lazy <img> is
       display:none (so it is never fetched) and the wrapper paints the light card instead. */
    .mk-og__event-media{display:block;width:100%;aspect-ratio:1200/630;
      background-size:cover;background-position:center;}
    /* height:auto for the same reason as .mk-og__img — the width/height attributes would otherwise pin
       this at 630px and crop to a tall slice. */
    .mk-og__event-img{display:block;width:100%;height:auto;aspect-ratio:1200/630;object-fit:cover;}
    @media(prefers-color-scheme:light){
      .mk-og__event-media{background-image:var(--oo-og-light);}
      .mk-og__event-img{display:none;}}
    .mk-og__meta{display:flex;align-items:center;gap:var(--oo-space-sm);flex-wrap:wrap;}
    .mk-og__domain{font-size:.72rem;letter-spacing:.02em;color:var(--oo-text-secondary);}
    .mk-og .mk-badge{margin-left:0;}
    .mk-og__title{margin:0;}
    .mk-og__desc{margin:0;color:var(--oo-text-secondary);font-size:.95rem;line-height:1.5;}

/* ============================== per-brand hero background images ==============================
   An on-brand abstract image sits BEHIND each hero's existing content/animation, muted by a
   surface-base veil so the copy (each hero already carries its own text scrim) stays legible. Painted on
   the section's own `background` (deepest layer) so no z-index work is needed. Scoped by brand and
   guarded with :not([data-oo-event]) so it never leaks onto the event pages (which reuse .mo-hero). */
    html[data-oo-brand="moodorbit"]:not([data-oo-event]) .mo-hero{
      background:linear-gradient(color-mix(in srgb,var(--oo-surface-surface-base) 58%,transparent),
                                 color-mix(in srgb,var(--oo-surface-surface-base) 58%,transparent)),
                 var(--oo-hero-img,url('/img/moodorbit-hero-bg.webp')) center/cover;}
    @media(prefers-color-scheme:light){
      html[data-oo-brand="moodorbit"]:not([data-oo-event]) .mo-hero{
        --oo-hero-img:url('/img/moodorbit-hero-bg-light.webp');}}
    /* TrueAlign's hero is a rawSection (class "section hero"); its animated gate lives in .loop. */
    html[data-oo-brand="truealign"] .section.hero{position:relative;overflow:hidden;
      padding-top:calc(clamp(40px,7vw,84px) + 2.75rem);   /* clear the fixed frosted header */
      background:linear-gradient(color-mix(in srgb,var(--oo-surface-surface-base) 30%,transparent),
                                 color-mix(in srgb,var(--oo-surface-surface-base) 30%,transparent)),
                 var(--oo-hero-img,url('/img/truealign-hero-bg.webp')) center/cover;}
    @media(prefers-color-scheme:light){
      html[data-oo-brand="truealign"] .section.hero{
        --oo-hero-img:url('/img/truealign-hero-bg-light.webp');}}
    /* translucent legibility panel behind the hero copy (matches OOTech/MoodOrbit — see oo-hero-scrim) */
    html[data-oo-brand="truealign"] .section.hero .hero-copy{position:relative;z-index:1;padding-inline:1rem;}
    html[data-oo-brand="truealign"] .section.hero .hero-copy::before{content:"";position:absolute;z-index:-1;
      inset:-1.5rem -.75rem;border-radius:var(--oo-radius-lg);
      background:color-mix(in srgb,var(--oo-surface-surface-base) 62%,transparent);
      -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
      -webkit-mask:radial-gradient(125% 100% at 32% 45%,#000 60%,transparent 100%);
              mask:radial-gradient(125% 100% at 32% 45%,#000 60%,transparent 100%);}
    /* iPad + iPhone: the old -1.75rem panel bled 4px PAST the screen edge (measured) with text only ~28px from
       it. Base inset is now -.75rem so the panel sits ~16px inside the 24px section gutter at every width (no
       clip); tablet/phone add real inline air so text never hugs the translucent border. */
    @media(max-width:1024px){
      html[data-oo-brand="truealign"] .section.hero .hero-copy{padding-inline:clamp(1.25rem,4vw,1.75rem);}
    }

/* The last section and the waitlist stacked their padding: 88px below the marketplaces content plus
   48px above the form heading left 136px of empty page right where the reader is meant to convert.
   Halved, and the form keeps its own breathing room. */
#marketplaces{padding-bottom:44px;}
#join{padding-top:28px;}

/* ── TrueAlign flow spacing for the .oo-* components (2026-07-30) ──────────────────────────────
   marketing.css:680 is TrueAlign's base reset: `.hero *, .section *{margin:0;}`. It has the same
   specificity as a bare `.oo-aud`/`.oo-figure` class rule, so every margin those declared EARLIER
   in this file was silently discarded on TrueAlign pages — the tab row sat at 0px from the lede
   above and the headline below, panel headings touched their body text, and figures touched the
   copy above them. Didier caught it by eye twice while my probes reported the declared values.
   Spacing for anything inside `.hero`/`.section` MUST be declared after line 680; this block is
   the one home for it. Selectors are scoped under the section id for specificity headroom. */
#marketplaces .oo-aud{margin-top:36px;}
#marketplaces .oo-aud__tabs{margin-bottom:30px;}
#marketplaces .oo-aud__panel h3{margin-bottom:12px;}
#marketplaces .oo-aud__panel p{margin-top:0;margin-bottom:6px;}
.section .oo-figure{margin-top:30px;}
.section .oo-figure .oo-cap{margin-top:14px;}
.section .dg-qfoot{margin-top:16px;}
