:root{--colden-purple:#7c5cff;--colden-blue:#2f7bff;--colden-bg:#08090c;--colden-panel:#0e1218;--colden-line:rgba(255,255,255,.09);--colden-text:#eceef1;--colden-muted:#9aa0a8}
x-dc{display:none!important}

/* ── Bundle countdown bar (announce.js) ─────────────────────────────────────────────
   Shared by all four pages. The bar is fixed above the primary nav; the nav's own
   top:0 is INLINE on three of the pages, so pushing it down needs !important. Content
   below is shifted by padding on <body> rather than by touching each page's hero, which
   all have different paddings and their own !important media overrides. Every offset
   reads one variable, so the bar can change height at a breakpoint and the rest follows.
   The .has-announce class is only present while the offer is genuinely running - once
   announce.js passes its deadline it removes the class and the page reverts exactly. */
html.has-announce{--announce-h:38px}
html.has-announce body{padding-top:var(--announce-h)}
html.has-announce .nav-bar{top:var(--announce-h)!important}
html.has-announce #catalog{scroll-margin-top:calc(76px + var(--announce-h))}
.announce-bar{position:fixed;top:0;left:0;right:0;z-index:120;
  display:flex;align-items:center;justify-content:center;gap:9px;
  height:var(--announce-h,38px);padding:0 16px;
  /* Near-black with only a green cast. The buy button is the loud green on this page;
     a fully green bar competed with it and the page read as three greens shouting. */
  background:linear-gradient(90deg,#0c1013,#101a15 48%,#0c1013);
  border-bottom:1px solid rgba(31,164,99,.30);
  color:#b9c2cb;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;
  font-size:13.5px;font-weight:600;letter-spacing:.005em;line-height:1;
  text-decoration:none;white-space:nowrap;overflow:hidden}
a.announce-bar:hover{color:#fff;border-bottom-color:rgba(31,164,99,.55)}
.announce-bar b{color:#e8eef4;font-weight:800}
/* No status dot. A pulsing "live" pip in front of the copy is generic SaaS decoration and
   the bar reads cleaner without it. */
/* Signals the bar is a link. Nudges on hover so the affordance is felt, not just seen. */
.announce-go{color:#6ee7a8;font-weight:700;transition:transform .2s ease;display:inline-block}
a.announce-bar:hover .announce-go{transform:translateX(3px)}
.announce-sep{color:rgba(185,194,203,.4)}
.announce-time{font-variant-numeric:tabular-nums}
.announce-time b{font-weight:800;color:#6ee7a8}
@media (max-width:620px){
  html.has-announce{--announce-h:34px}
  .announce-bar{font-size:12px;gap:7px}
  .announce-long{display:none}
}

/* Important content is never gated behind JavaScript or an intersection observer. */
[data-reveal]{opacity:1!important;transform:none!important;filter:none!important}

/* Shared product-page controls. */
.sticky-buy-shell{background:rgba(10,11,16,.9);border-top:1px solid rgba(255,255,255,.1);box-shadow:0 -18px 48px rgba(0,0,0,.42);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}
.sticky-buy-inner{width:min(100%,560px);margin:0 auto;box-sizing:border-box;padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px))}
.sticky-buy-shell .sticky-card{padding:0!important;border:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;backdrop-filter:none!important;-webkit-backdrop-filter:none!important}
.sticky-product-lockup{display:flex;align-items:center;gap:14px;min-width:0}
.sticky-product-logo{width:52px;height:52px;flex:none;border-radius:13px;object-fit:cover}
.tm-card{border-radius:16px!important;background:rgba(255,255,255,.03)!important;border:1px solid rgba(255,255,255,.07)!important;overflow:hidden;contain:paint}
.tm-language-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}
.tm-language-grid .tm-stage{height:180px;display:flex;align-items:center;justify-content:center;padding:14px;font-size:42px;font-weight:700;overflow:hidden;text-align:center}
.motion-pill{width:auto!important;min-width:0!important;min-height:34px!important;flex:1 1 0;padding:5px clamp(3px,1vw,11px)!important;border-radius:8px!important;font-size:clamp(8px,2.2vw,12px)!important}
.tm-motion-list{display:flex;flex-wrap:nowrap!important;gap:clamp(2px,.65vw,8px);align-items:center;justify-content:center;padding:0 clamp(8px,1.4vw,16px) 16px;white-space:nowrap}
.tm-motion-list b{color:#5a5a6e;font-size:clamp(9px,1.5vw,14px);flex:none}
.tm-motion-list--four{flex-wrap:nowrap;gap:5px}
.tm-motion-list--four .motion-pill{min-width:0!important;flex:1 1 0;padding-left:5px!important;padding-right:5px!important}
.tm-motion-list--four b{flex:none;font-size:12px}
.tm-proof-section{max-width:1120px!important;padding-top:58px!important;padding-bottom:58px!important}
.tm-proof-section .tm-proof-platforms,.tm-proof-section .tm-proof-stats{gap:12px!important}
.tm-proof-section .tm-proof-platforms .tm-card{padding:16px 20px!important}
.tm-proof-section .tm-proof-stats .tm-card{padding:18px!important}
.tm-proof-section .tm-proof-stats .tm-stat-value{font-size:38px!important}
/* Shared version caption for the fused mobile platforms card; each row carries
   its own copy of this line at widths where the rows are separate cards. */
.tm-platform-note{display:none}
.tm-compare-section{max-width:1000px!important;padding-top:28px!important;padding-bottom:28px!important}
.tm-compare-section>div[data-reveal]:first-child{margin-bottom:18px!important}
.tm-compare-section h2{font-size:50px!important}
.tm-compare-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.tm-compare-card{padding:25px 27px!important}
.tm-compare-card h3{margin:0 0 17px;color:#c9c9d4;font-size:18.5px;letter-spacing:.08em}
.tm-compare-card-win{background:linear-gradient(145deg,rgba(124,92,255,.09),rgba(255,255,255,.025))!important}
.tm-compare-card-win h3{color:#b9a7ff}
.tm-compare-list{display:grid;gap:11px;color:#d4d4df;font-size:15px;line-height:1.35}
.tm-compare-list span{display:flex;align-items:flex-start;gap:11px;min-width:0}
.tm-compare-list-old{color:#9696a4}
.tm-compare-icon{display:inline-flex;align-items:center;justify-content:center;flex:none;width:17px;height:20px;font:800 22px/1 Inter,system-ui,sans-serif;font-style:normal}
.tm-compare-icon-yes{color:#55a9ff}
.tm-compare-icon-no{color:#ff8d96}
/* The only mention of the free build on this page. It exists for the person who
   was going to leave anyway, so it stays a whisper: no border, no fill, no
   brand purple - a plain line of text that only resolves if you look for it. */
.tm-hero-basic-note{align-self:center;color:rgba(237,237,242,.42);font-size:12.5px;font-weight:400;line-height:1.4;text-decoration:none;transition:color .2s ease}
.tm-hero-basic-note:hover{color:rgba(237,237,242,.72)}

/* Cross-sell card at the foot of a product page ("More from Colden"). Shared by both
   product pages - each one points at the other product, so nothing here is TypeMotion
   or MotionEase specific. Built on .tm-card so it inherits the page's card surface. */
.cs-more{max-width:1000px;margin:0 auto;padding:4px 32px 64px}
/* Smaller than a section heading: this is a lead-in label for the card below it,
   not a statement competing with the buy CTA above. */
.cs-more h2{margin:0;font-family:'Instrument Serif',serif;font-weight:400;font-size:34px;line-height:1.1;letter-spacing:-.01em;color:#EDEDF2}
/* Accent follows the PAGE, not the product being promoted: TypeMotion is purple,
   MotionEase is blue. Each page sets --cs-accent; purple is the default. */
.cs-more h2 span{font-style:italic;color:var(--cs-accent,#C7B7FF)}
.cs-more-card{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:22px;padding:20px 24px!important;text-decoration:none;
  transition:transform .25s cubic-bezier(.2,.8,.2,1),border-color .25s ease,box-shadow .25s ease}
.cs-more-card:hover{transform:translateY(-3px);border-color:var(--cs-accent-border,rgba(124,92,255,.34))!important;box-shadow:0 26px 60px rgba(0,0,0,.45)}
.cs-more-logo{width:76px;height:76px;border-radius:18px;flex:none}
.cs-more-copy{min-width:0}
.cs-more-name{margin:0 0 5px;font-family:'Instrument Serif',serif;font-weight:400;font-size:30px;line-height:1;color:#fff}
.cs-more-tagline{margin:0;color:#8A8A99;font-size:14px;line-height:1.45}
.cs-more-buy{display:flex;flex-direction:column;align-items:flex-end;gap:9px;flex:none}
.cs-more-price{display:flex;align-items:baseline;gap:8px;font-size:22px;font-weight:800;color:#eceef1;letter-spacing:-.02em}
.cs-more-price s{font-size:14px;font-weight:600;color:#6b727c;text-decoration-color:rgba(240,119,107,.7)}
.cs-more-cta{display:inline-flex;align-items:center;justify-content:center;padding:9px 16px;border-radius:10px;border:1px solid rgba(255,255,255,.14);
  background:rgba(255,255,255,.05);color:#eceef1;font-size:13.5px;font-weight:700;white-space:nowrap;transition:border-color .2s ease,background .2s ease}
.cs-more-card:hover .cs-more-cta{border-color:rgba(255,255,255,.3);background:rgba(255,255,255,.09)}

/* MotionEase screen recordings. Already cropped to their content at encode time, so the
   job here is only to stop them reading as raw rectangular screenshots: rounded frame,
   hairline border, and a background that matches the panel so the corners blend rather
   than showing a hard edge. Radius is kept modest - the recordings are UI, and a large
   radius starts clipping the panel chrome inside them. */
/* Background matches the colour baked into the clips (#1A1A1B), so the rounded corners
   blend into the frame instead of showing a black wedge behind the video. */
/* Inert by design: these are illustrations, not media the visitor operates. Selection,
   dragging and the iOS long-press "save video" callout all make them feel like loose
   assets rather than part of the page. pointer-events:none covers the right-click and
   long-press menus that user-select alone leaves open. */
.me-shot{display:block;width:100%;height:auto;box-sizing:border-box;
  border:10px solid #1c1c1c;border-radius:20px;background:#1c1c1c;
  box-shadow:0 0 0 1px rgba(255,255,255,.08),0 24px 60px rgba(0,0,0,.45);
  transition:box-shadow .35s ease;
  user-select:none;-webkit-user-select:none;-webkit-user-drag:none;-webkit-touch-callout:none;pointer-events:none}
/* Deliberately faint: a caveat that should be findable but not part of the pitch. */
.me-fineprint{margin:10px 0 0;color:rgba(237,237,242,.26);font-size:11px;line-height:1.4;text-align:center}

/* Hero panel: the recording, with an opt-in control to load the interactive version.
   The button sits above the clip because the clip itself is pointer-events:none. */
/* Visibility runs off classes, never the `hidden` attribute: the DC runtime re-creates
   these nodes and drops valueless booleans, so `hidden` silently vanished and both the
   recording and the interactive panel rendered at once. */
/* The panel recording is a tall portrait capture (924x1348). Left to fill its column it
   towers over the hero copy beside it, so it is capped by width and the aspect ratio does
   the rest - the cap is what keeps the whole panel on screen without scrolling. */
.me-panel{max-width:100%;margin-left:auto;margin-right:auto}
/* The workflow shot zooms and pans, so the colour at its edge changes frame to frame (0 to
   49 across the clip) - no stroke colour can match it, and a fixed one reads as a ring. It
   carries its own margins anyway, so rounding it directly clips nothing. */
.me-panel-vid{border:1px solid rgba(255,255,255,.08);border-radius:16px;background:#000}

/* ---- MotionEase, phones ---- */
@media (max-width:760px){
  /* The feature titles were sized off viewport width (3vw), so they collapsed to their
     24px floor exactly where they had the most room to be the loudest thing on screen.
     Size them off the phone's width instead and let them wrap to two lines. */
  .feat-row h3{font-size:clamp(36px,10vw,46px)!important;line-height:1.06!important;letter-spacing:-.03em!important}
  /* Centred: the row is a single stacked column here, so left-aligned copy under a
     centred section heading reads as a mistake. */
  .feat-row>div{text-align:center}
  .feat-row>div>div:first-child{justify-content:center}
  .feat-row p{margin-left:auto!important;margin-right:auto!important}

  /* An auto-scrolling marquee is something you wait for, not something you read. On a
     phone, hand it over: stop the animation and let people swipe at their own pace. */
  .rev-marquee{overflow-x:auto!important;-webkit-overflow-scrolling:touch;padding:6px 0!important;scrollbar-width:none}
  .rev-marquee::-webkit-scrollbar{display:none}
  .rev-marquee:active .rev-track,.rev-marquee:hover .rev-track{animation-play-state:paused}

  /* The run after "Why not just keyframe it?" stacked 80px gaps on a screen that has
     none to spare. */
  #main-content>section#reviews{padding-top:26px!important;padding-bottom:8px!important}
  #main-content>section#faq{padding-top:26px!important;padding-bottom:12px!important}
  .me-divider{margin-top:14px!important}
}
.tm-style-stage{height:180px;display:flex;align-items:center;justify-content:center;overflow:hidden;font-size:40px;font-weight:800}
.tm-style-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:22px!important}
.tm-style-grid>.tm-card:last-child{grid-column:1/-1}
.tm-card .tm-stage{max-width:100%;min-width:0;padding-left:18px!important;padding-right:18px!important}
#main-content .tm-card>.tm-stage{font-size:54px!important;font-weight:700!important;line-height:1.05!important;text-align:center!important}
#main-content .tm-card>.tm-stage-lines{font-size:60px!important;line-height:1.02!important}
.tm-style-stage{font-size:clamp(25px,3vw,38px)!important}
.tm-language-grid .tm-stage{font-size:clamp(36px,3.6vw,44px)!important}
#features .ctrl-grid .tm-stage{font-size:clamp(46px,4.7vw,60px)!important}
#showcase .tm-stage{font-size:clamp(25px,2.8vw,34px)!important}
.tm-style-stage>span{display:inline-block}
.tm-style-sweep{animation:tm-sweep-clean 1.65s linear infinite}
.tm-style-sweep>span{line-height:1.2;padding-block:.08em;margin-block:-.08em;background-color:#7656f4;background-image:linear-gradient(90deg,transparent 0%,rgba(185,169,255,.5) 30%,#fff 50%,rgba(185,169,255,.5) 70%,transparent 100%);background-repeat:no-repeat;background-size:64px 100%;background-position:calc(var(--tm-sweep-x,0px) + var(--tm-unit-neg-x,0px)) 50%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
.tm-style-glow>span{color:#ede9ff;text-shadow:0 0 8px rgba(124,92,255,.8),0 0 22px rgba(124,92,255,.85)}
.tm-style-gradient>span{transform-origin:50% 50%;background-image:linear-gradient(105deg,#ff4fc8 0%,#b675ff 50%,#4aa8ff 100%);background-repeat:no-repeat;background-size:var(--tm-block-w,180px) 100%;background-position:var(--tm-unit-neg-x,0px) 50%;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
@property --tm-sweep-x{syntax:'<length>';inherits:true;initial-value:0px}
@keyframes tm-sweep-clean{0%,12%{--tm-sweep-x:var(--tm-sweep-start,-60px)}88%,100%{--tm-sweep-x:var(--tm-sweep-end,220px)}}
.tm-purchase-notes{display:grid;gap:4px;margin-top:22px;color:#8f8f9f;font-size:11px;line-height:1.35;letter-spacing:.01em}
#main-content>section:not(#buy)>div[data-reveal]:first-child{margin-bottom:30px!important}
#main-content>section.tm-compare-section:not(#buy)>div[data-reveal]:first-child{margin-bottom:18px!important}
#main-content .tm-card>.tm-stage{min-height:180px}
/* Entrance travel is derived from the stage's spare vertical space, and a lines
   stage spends most of its box on a second line - at the shared height it barely
   moves and its bounce cannot read. Give it the room to travel like its siblings. */
#main-content .tm-card>.tm-stage-lines{min-height:230px}
#main-content .tm-card>[data-style]{min-height:180px}
#main-content .ctrl-grid{gap:22px!important}
#main-content>section.tm-style-section{padding-bottom:42px!important}

@media(min-width:761px){
  #main-content>section{padding-top:64px!important;padding-bottom:64px!important}
  #main-content>section:first-of-type{padding-top:84px!important}
  #main-content>section.tm-proof-section{padding-top:58px!important;padding-bottom:58px!important}
  #main-content>section.tm-compare-section{padding-top:28px!important;padding-bottom:28px!important}
  #main-content>section#buy{padding-top:110px!important;padding-bottom:110px!important}
}

.tm-panel-viewport,.panel-frame-wrap{position:relative}



@media(max-width:760px){
  .nav-bar .nav-inline{display:none!important}
  .hero{min-height:auto!important}
  .hero-headline{white-space:normal!important;font-size:clamp(48px,14vw,64px)!important}
  section{scroll-margin-top:70px}
  .sticky-buy-inner{padding:10px 16px calc(10px + env(safe-area-inset-bottom,0px))}
  .sticky-product-logo{width:46px;height:46px;border-radius:12px}
  .tm-language-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
  .tm-language-grid .tm-stage{height:160px;font-size:38px!important}
  #showcase .tm-stage{font-size:30px!important}
  #features .ctrl-grid .tm-stage{font-size:clamp(42px,12vw,60px)!important}
  .tm-style-stage{font-size:31px!important}
  #main-content .tm-card>.tm-stage{font-size:48px!important;font-weight:700!important;line-height:1.05!important;text-align:center!important}
  /* A lines stage is two real lines by design, so it cannot shrink to one line like
     the other labels. Ease the type down to buy back the vertical room its entrance
     travel is measured from. */
  #main-content .tm-card>.tm-stage-lines{font-size:46px!important;line-height:1.02!important}
  #main-content>section{padding-top:44px!important;padding-bottom:44px!important}
  #main-content>section:not(#buy)>div[data-reveal]:first-child{margin-bottom:22px!important}
  #main-content .tm-card>.tm-stage{min-height:160px}
  #main-content .tm-card>.tm-stage-lines{min-height:200px}
  #main-content .tm-card>[data-style]{min-height:160px}
  #main-content>section.tm-proof-section{padding-top:48px!important;padding-bottom:48px!important}
  #main-content>section.tm-style-section{padding-bottom:36px!important}
  #main-content>section.tm-compare-section{padding-top:24px!important;padding-bottom:24px!important}
  /* Matches the shared mobile heading scale; a fixed size here read larger than
     its neighbours on small phones and smaller on large ones. */
  .tm-compare-section h2{font-size:clamp(36px,11.5vw,52px)!important}
  .tm-compare-grid{grid-template-columns:1fr;gap:12px}
  .tm-compare-card{padding:21px 20px!important}
  .tm-compare-card h3{font-size:17.5px;margin-bottom:13px}
  .tm-compare-list{font-size:15.5px;gap:10px}
  .tm-hero-basic-note{font-size:12px}
  /* Stack the cross-sell on phones; the three-up row has nowhere to go at 375px. */
  .cs-more{padding:4px 18px 48px}
  .cs-more h2{font-size:clamp(25px,7vw,32px)!important}
  .cs-more-card{grid-template-columns:1fr;justify-items:center;text-align:center;gap:14px;padding:22px 20px!important}
  .cs-more-buy{align-items:center}
}

@media(max-width:460px){.tm-language-grid{grid-template-columns:1fr}}

@media(max-width:620px){
  .tm-style-grid{grid-template-columns:1fr!important;gap:16px!important}
  .tm-style-grid>.tm-card:last-child{grid-column:auto}

  /* On a phone the proof block sits between the hero and the first real content,
     pushing the pitch down for two lines of spec. Reorder it to just above the FAQ,
     where "which app, which version" is the question people actually have by then.
     Grid only for the ordering. The track is minmax(0,1fr), not auto/1fr: these
     sections contain content that will not shrink (the panel, nowrap headings), and
     an auto-min track lets that content force the whole column wider than the phone
     - which is exactly what a plain flex/grid column here does.
     Scoped to .tm-page (the TypeMotion page's main) - NOT #main-content, which the
     landing, legal and MotionEase share. Unscoped, `#faq{order:2}` silently dragged
     MotionEase's FAQ below its final CTA, because ordering applies to every child of
     a grid container whether or not it was the one being reordered. */
  .tm-page{display:grid;grid-template-columns:minmax(0,1fr)}
  /* Anything with an explicit order below must stay in step: unordered children
     default to 0 and would jump ahead of these. The cross-sell stays last. */
  .tm-page .cs-more{order:4}
  /* Restore block-layout sizing for the items. As grid items these sections change
     behaviour twice over: min-width defaults to auto (min-content, so they refuse to
     shrink), and their `margin:0 auto` turns width:auto from "fill the container"
     into shrink-to-fit - which collapses them to their padding while their content is
     skipped by content-visibility. width:100% pins that back; max-width still caps
     them and the auto margins still centre them. */
  .tm-page>*{min-width:0;width:100%}
  .tm-page .tm-proof-section{order:1}
  .tm-page #faq{order:2}
  .tm-page #buy{order:3}

  /* Five stacked cards spend ~1000px of scroll to say two things: where it runs,
     and that it is fast. Fuse each group into one card - the platforms as two
     rows under a shared caption, the stats as a single three-up row - by making
     the grid itself the card and flattening the children into its cells. */
  .tm-proof-section{padding-top:34px!important;padding-bottom:34px!important}
  .tm-proof-section .tm-proof-platforms,.tm-proof-section .tm-proof-stats{
    gap:0!important;border:1px solid rgba(255,255,255,.07);border-radius:16px;
    background:rgba(255,255,255,.03);overflow:hidden}
  .tm-proof-section .tm-proof-platforms>.tm-card,.tm-proof-section .tm-proof-stats>.tm-card{
    border:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important}

  .tm-proof-section .tm-proof-platforms{display:block!important;margin-bottom:12px!important}
  /* Centred to match the caption beneath them; left-aligned rows under a centred
     caption read as two different cards stacked, which is what this fuses away. */
  .tm-proof-section .tm-proof-platforms>.tm-card{padding:11px 15px!important;gap:12px!important;justify-content:center!important}
  .tm-proof-section .tm-proof-platforms>.tm-card+.tm-card{border-top:1px solid rgba(255,255,255,.06)!important}
  .tm-proof-section .tm-proof-platforms>.tm-card>div:first-child{width:32px!important;height:32px!important;font-size:13px!important;border-radius:8px!important}
  .tm-proof-section .tm-proof-platforms>.tm-card>div:last-child>div:first-child{font-size:14.5px!important}
  /* The version line is identical on both rows; show it once as a caption. */
  .tm-proof-section .tm-proof-platforms>.tm-card>div:last-child>div:last-child{display:none!important}
  .tm-platform-note{display:block;padding:8px 15px 10px;border-top:1px solid rgba(255,255,255,.06);
    color:#8A8A99;font-size:11.5px;text-align:center}

  .tm-proof-section .tm-proof-stats{grid-template-columns:repeat(2,1fr)!important}
  /* Beats the row-balancer's inline span: in a three-up row nothing is orphaned. */
  .tm-proof-section .tm-proof-stats>.tm-card{padding:13px 5px!important;grid-column:auto!important}
  .tm-proof-section .tm-proof-stats>.tm-card+.tm-card{border-left:1px solid rgba(255,255,255,.06)!important}
  .tm-proof-section .tm-proof-stats .tm-stat-value{font-size:26px!important}
  .tm-proof-section .tm-proof-stats>.tm-card>div:last-child{font-size:10.5px!important;margin-top:4px!important;line-height:1.25}
}

@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}

/* Last-resort fallback. Hidden unless scripts are off (.nojs-static, inside <noscript>)
   or the watchdog decides nothing ever rendered (.is-on). Deliberately plain: no fonts,
   no images beyond the logo, nothing that can itself fail. */
.nojs-fallback{display:none;max-width:640px;margin:0 auto;padding:64px 24px;
  font-family:system-ui,-apple-system,'Segoe UI',sans-serif;color:#eceef1;text-align:center}
.nojs-static{display:block}
.nojs-fallback.is-on{display:block}
.nojs-lead{margin:0 0 28px;font-size:15px;letter-spacing:.14em;text-transform:uppercase;color:#7c8592}
.nojs-card{display:flex;align-items:center;gap:16px;margin:0 0 14px;padding:18px 20px;text-align:left;
  border:1px solid rgba(255,255,255,.12);border-radius:14px;background:rgba(255,255,255,.04);text-decoration:none;color:inherit}
.nojs-logo{width:64px;height:64px;border-radius:14px;flex:none}
.nojs-copy{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}
.nojs-copy b{font-size:19px;font-weight:700}
.nojs-copy span{font-size:13.5px;color:#8a929c;line-height:1.4}
.nojs-price{font-size:19px;font-weight:800;white-space:nowrap}
.nojs-price s{font-size:13px;font-weight:600;color:#6b727c}
.nojs-note{margin:26px 0 0;font-size:13px;line-height:1.6;color:#7c8592}
.nojs-note a{color:#7aa7ff}
@media (max-width:600px){
  .nojs-fallback{padding:40px 18px}
  .nojs-card{flex-wrap:wrap;gap:12px}
  .nojs-price{width:100%}
}


/* Hero interactivity. The page's existing hover language is a 3px lift plus a deeper
   shadow on .cs-more-card, so the hero borrows it rather than inventing a second one. */
.hero-logo,.hero-brand-logo{transition:transform .4s cubic-bezier(.2,.8,.2,1),box-shadow .4s ease}
.hero-logo:hover,.hero-brand-logo:hover{transform:translateY(-5px) scale(1.03)}
.hero-buy{transition:transform .25s cubic-bezier(.2,.8,.2,1),box-shadow .25s ease,filter .25s ease}
.hero-buy:hover{transform:translateY(-3px);filter:brightness(1.07)}
.hero-buy:active{transform:translateY(-1px)}
.me-panel{transition:transform .4s cubic-bezier(.2,.8,.2,1)}
.me-panel:hover{transform:translateY(-5px)}
/* .me-shot is pointer-events:none, so the hover has to be read off the wrapper. */
.me-panel:hover .me-shot{box-shadow:0 0 0 1px rgba(47,123,255,.4),0 34px 84px rgba(0,0,0,.6)}
.feat-row .me-shot:hover,.feat-row div:hover>.me-shot{box-shadow:0 0 0 1px rgba(47,123,255,.28),0 30px 72px rgba(0,0,0,.55)}
.hero-buy:hover{box-shadow:0 20px 46px rgba(47,123,255,.55)}
.tm-page .hero-buy:hover{box-shadow:0 20px 50px rgba(124,92,255,.6)}
@media (prefers-reduced-motion:reduce){
  .hero-logo,.hero-brand-logo,.hero-buy,.me-panel{transition:none}
  .hero-logo:hover,.hero-brand-logo:hover,.hero-buy:hover,.hero-buy:active,.me-panel:hover{transform:none}
}

/* TypeMotion hero, spaced after rystal.shop's: headline sits well clear of the nav, a big
   centred demo, the spec line tucked under it, then a COMPACT price+Buy pill. Scoped to
   .hero.tm-hero-v2 - .hero exists on both product pages, and the page's own rules are hoisted
   into <head> after this file, so equal specificity loses the tie. Hence (0,3,0) throughout. */
.hero.tm-hero-v2{display:flex!important;flex-direction:column!important;align-items:center!important;
  justify-content:center!important;gap:0!important;padding-top:78px!important;
  /* Keep the viewport reservation: I had zeroed this, which let the next section (the
     Premiere / After Effects cards) creep into the hero. svh, not vh, so mobile browser
     chrome does not overshoot. flex-start keeps the content top-aligned inside it. */
  min-height:100svh!important;padding-bottom:34px!important}
.hero.tm-hero-v2>.hero-copy,.hero.tm-hero-v2 .tm-panel-shell,
.hero.tm-hero-v2 .tm-interactive-section{display:contents!important}
/* The live-panel chrome and the big brand logo went with the iframe they belonged to. */
.hero.tm-hero-v2>.hero-brand,.hero.tm-hero-v2 .hero-brand,
.hero.tm-hero-v2 .tm-interactive-intro,.hero.tm-hero-v2 .tm-panel-bar,
.hero.tm-hero-v2 .tm-mobile-simple-demo{display:none!important}

/* One line where it can be read at a real size, two where it cannot. 36 characters need
   roughly width/18 to hold one line: below ~900px that means sub-20px type, which is smaller
   than body text and worse than wrapping. So nowrap only from 900px up. */
.hero.tm-hero-v2 .hero-headline{order:2!important;text-align:center;
  margin:0 0 20px!important;white-space:normal!important;
  font-size:min(11.5vw,58px)!important;line-height:1.05!important}
/* "One plugin." must not split across lines, and the sparkle is already nbsp'd to it, so the
   only break opportunities are between the words of "Every text animation." */
.hero.tm-hero-v2 .hero-headline span{white-space:nowrap}
/* Two lines maximum, so the break is placed rather than left to chance: natural wrapping
   would split "Every text animation." into three segments once the type gets large. */
.tm-hero-br{display:inline}
/* Under 900 the headline wraps - but left to itself it broke as
   "Every text animation. One plugin." / "✨", orphaning the sparkle on its own line. So the
   break is placed explicitly, and the sparkle is welded to "One plugin." with an nbsp. */
.tm-hero-br{display:inline}
@media (min-width:900px){
  /* One line here: 36 characters against a 1136px hero at ~0.44em each tops out near 66px. */
  .hero.tm-hero-v2 .hero-headline{white-space:nowrap!important;font-size:min(6vw,84px)!important}
  .tm-hero-br{display:none}
}

.hero.tm-hero-v2 .tm-panel-viewport{order:3!important;display:block!important;width:100%;
  max-width:min(980px,calc((100svh - 330px) * 1.778))!important;margin:0 auto!important;height:auto!important;max-height:none!important;
  border:0!important;background:transparent!important;overflow:visible!important;padding:0!important}
/* 16:9 window. The source is 1.548, so cover crops rather than squashes; centring the crop
   keeps the panel and the program monitor and sheds the outer chrome first.
   No stroke: .me-shot paints a 10px #1c1c1c border, which existed only to stop the old
   portrait panel clipping its own Apply button in the corners. This clip is cropped to a
   clean rectangle, so the border is just padding around the demo. The hairline ring and the
   drop shadow stay - they are what separate it from the page. */
.tm-demo-vid{width:100%;height:auto;display:block;aspect-ratio:16/9;object-fit:cover;
  object-position:center center;border:0!important;background:transparent!important;
  border-radius:14px}
/* Phones get a 1:1 window, and a dedicated 1:1 encode to fill it - the mobile file is cropped
   square at source (from the left, so the panel survives and the right-hand side goes). That
   is why it looks sharper rather than just bigger: the same 1080px now covers 2228 source px
   instead of 3450, so the plugin panel renders at ~436px instead of ~282. No cover-cropping
   happens in the browser at all; the file already is the crop. */
@media (max-width:760px){
  .tm-demo-vid,.hero-grid .me-panel-vid{aspect-ratio:1/1!important;object-fit:cover!important}
}

.hero.tm-hero-v2 .hero-purchase{order:4!important;margin:16px 0 0!important}
/* The button was width:100%/max-width:380px - a slab. rystal's is a pill that hugs its label,
   and it reads as one confident action rather than a form field. */
.hero.tm-hero-v2 .hero-purchase>a.hero-buy{width:auto!important;max-width:none!important;
  flex:0 0 auto!important;padding:15px 34px!important;margin:0!important}
@media (min-width:761px){
  /* price and Buy share a row; an explicit width stops the shrink-to-fit container from
     collapsing to its widest child and wrapping every item onto its own line. */
  .hero.tm-hero-v2 .hero-purchase{display:grid!important;grid-auto-flow:row;
    grid-template-columns:auto auto;justify-content:center!important;align-items:center!important;
    gap:0 22px!important;width:auto!important;max-width:none!important}
  /* was: $14.99 and $29.99 on one baseline, ~270px wide. Stacked it is ~150px, and the old
     price reads as an annotation on the new one instead of a second headline number. */
  /* Struck original to the LEFT of the sale price, one line (row-reverse: the markup is
     span-then-s, so reversing puts the struck first). Single-line keeps it level with the
     button, and inline keeps it clear of the spec line above. */
  .hero.tm-hero-v2 .hero-purchase>div:first-child{flex-direction:row-reverse!important;
    align-items:baseline!important;justify-content:center!important;gap:11px!important}
  .hero.tm-hero-v2 .hero-purchase>div:first-child>span{font-size:46px!important;line-height:1!important}
  .hero.tm-hero-v2 .hero-purchase>div:first-child>s{position:static!important;font-size:15px!important;opacity:.75;white-space:nowrap}
  /* Spans both columns so it gets its own line, but justify-self keeps the box - and the
     hover target - the width of the words. flex-basis:100% made it the full row. */
  .hero.tm-hero-v2 .hero-purchase>.tm-hero-basic-note{grid-column:1/-1;justify-self:center;
    width:max-content;margin:10px auto 0!important}
}
/* Spec line holds one line at every width: a fact strip that wraps becomes a paragraph. */
.tm-spec-line,.hero-panel-col>p{white-space:nowrap!important;text-align:center;
  font-size:clamp(10.5px,2.9vw,12.5px)!important;color:#6b727c;letter-spacing:0!important}
.tm-spec-line{margin:12px 0 0!important}

/* Hero hover states. Same language as the rest of the site: a small lift on the shared easing
   curve, never a colour change. The Buy button had a style-hover attribute that never fired. */
.hero.tm-hero-v2 .hero-buy{transition:transform .25s cubic-bezier(.2,.8,.2,1),box-shadow .25s ease,filter .25s ease}
.hero.tm-hero-v2 .hero-buy:hover{transform:translateY(-3px);filter:brightness(1.06);
  box-shadow:0 20px 50px rgba(124,92,255,.62)!important}
.hero.tm-hero-v2 .hero-buy:active{transform:translateY(-1px)}
.hero.tm-hero-v2 .tm-panel-viewport{transition:transform .4s cubic-bezier(.2,.8,.2,1)}
.hero.tm-hero-v2 .tm-panel-viewport:hover{transform:translateY(-4px)}
.hero.tm-hero-v2 .tm-demo-vid{transition:box-shadow .4s ease}
.hero.tm-hero-v2 .tm-panel-viewport:hover .tm-demo-vid{box-shadow:0 30px 80px rgba(0,0,0,.6),0 0 90px rgba(124,92,255,.2)}
.tm-hero-basic-note{transition:color .2s ease}
@media (prefers-reduced-motion:reduce){
  .hero.tm-hero-v2 .hero-buy,.hero.tm-hero-v2 .tm-panel-viewport{transition:none}
  .hero.tm-hero-v2 .hero-buy:hover,.hero.tm-hero-v2 .hero-buy:active,
  .hero.tm-hero-v2 .tm-panel-viewport:hover{transform:none}
}

/* ---- Phone hero, matched to rystal.shop/typeflow's actual measurements ----------------
   Measured at 390x844 on their live page: headline 23.4px over 2 lines starting at y=118,
   a 1:1 video 356px tall at y=191, and the CTA 292x57 ending at y=652 with 192px to spare.
   Nav height 0 - they retract it too.

   The lesson in those numbers: the headline is SMALL on purpose. That is what pays for the
   demo and puts the CTA on screen. Ours was 44.85px and pushed Buy to y~716 - past the fold
   on a real iPhone, where Safari's chrome leaves ~714px of the 844, not the full height.
   So: small headline, wide CTA, tight gaps. */
@media (max-width: 760px) {
  /* Top-aligned on a phone: centring inside 100svh pushed the block down and cost Buy the
     fold. MotionEase's phone rule does the same. */
  .hero.tm-hero-v2 { padding-top: 74px !important; padding-bottom: 24px !important;
    justify-content: flex-start !important; }

  /* Title stays big on the phone. The room comes out of the DEMO, not the headline - that is
     the instruction, and it is the right call anyway: the headline is what sells, the demo is
     the evidence. rystal shrinks its headline to 23px; we are not copying that part. */
  .hero.tm-hero-v2 .hero-headline {
    font-size: 44px !important;
    line-height: 1.1 !important;
    margin: 0 0 16px !important;
  }
  /* The demo gives up the pixels instead, so Buy still clears a real iPhone's ~714px. */
  .hero.tm-hero-v2 .tm-panel-viewport { max-width: 300px !important; }

  /* CTA is a wide bar here, not the desktop pill - it is the only action on the screen. */
  .hero.tm-hero-v2 .hero-purchase > a.hero-buy,
  .hero .hero-grid a.hero-buy {
    width: min(292px, 78vw) !important;
    padding: 17px 24px !important;
    justify-content: center !important;
  }

  .hero.tm-hero-v2 .hero-purchase { margin-top: 16px !important; }
  .hero.tm-hero-v2 .hero-purchase > div:first-child > span { font-size: 34px !important; }
  .hero.tm-hero-v2 .hero-purchase > div:first-child { flex-direction: row-reverse !important; align-items: baseline !important; justify-content: center !important; gap: 9px !important; }
  .hero.tm-hero-v2 .hero-purchase > div:first-child > s { position: static !important; font-size: 14px !important; opacity: .75; white-space: nowrap; }
  .hero.tm-hero-v2 .tm-panel-viewport { margin: 0 auto !important; }
  /* Fits inside the 300px demo: 55 characters need ~9.6px here (341px at 11.31px scales to
     ~290px). Once it fits, text-align:center actually centres it - the 21px offset was the
     line overflowing a narrower box, not a centring bug. Capped to the demo width so it can
     never be wider than the video again. */
  .tm-spec-line, .hero-panel-col > p {
    margin: 10px auto 0 !important;
    font-size: 9.6px !important;
    max-width: 300px !important;
  }
}



/* Phone: the hero hugs its content instead of reserving a full screen. min-height:100svh left
   a slab of dead air under the CTA on tall phones (content ~660px in an 852px viewport), and
   the next section starts right after this, which is where it should be. */
@media (max-width: 760px) {
  .hero.tm-hero-v2,
  header.hero {
    min-height: 0 !important;
    padding-bottom: 28px !important;
  }
}
