/* ============================================================
   SOURCE ELEMENTS — MARKETING SURFACE
   Tokens: css/tokens.css — linked BEFORE this file (order is load-bearing).
   Typography voice rationing (when --font-mono is allowed): see tokens.css.
   Surface rules: marketing (12-col, 1080px, spacious, expressive)
   ============================================================ */

*{box-sizing:border-box;margin:0;padding:0}
/* The reset above also zeroes a <dialog>'s margin, and the browser centres a
   modal dialog WITH that margin (auto) — without it the home page's Start-for-
   free pop-up opened pinned to the top-left corner. The browser also paints a
   dialog's text CanvasText, i.e. black, so its heading read black on the dark
   panel. Both are handed back here, for every dialog at once. */
dialog{margin:auto;color:var(--se-text)}
html{scroll-behavior:smooth}
body{
  background:var(--se-bg);
  color:var(--se-text);
  font-family:var(--font-primary);
  font-size:16px;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
body::before{ /* ambient vignette + top glow, fixed, behind everything */
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    /* ALWAYS LIME — brand, not page accent. Routing this to --accent-rgb would tint
       whole pages on /source-nexus + /source-live. Keep --se-primary-rgb. */
    radial-gradient(1200px 600px at 50% -6%,rgba(var(--se-primary-rgb),.05),transparent 60%),
    radial-gradient(100% 100% at 50% 50%,transparent 62%,rgba(10,10,10,.35));
}
body::after{ /* fine grain for filmic depth */
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.028'/%3E%3C/svg%3E");
}
.site-header,main,.footer-cta,.site-footer{position:relative;z-index:1}
img,svg,canvas{display:block;max-width:100%}
/* [hidden] MUST WIN. The UA sheet's `[hidden]{display:none}` is a single
   attribute selector, so ANY class rule that sets display beats it — and the
   Support finders hide rows by setting the hidden attribute. This shipped
   broken on #/error-codes: `.ec-list li{display:grid}` out-specified it, so
   searching "307" reported "1 of 291" while eleven rows stayed on screen. The
   filter tests passed because they counted the ATTRIBUTE, not what rendered.
   One global rule fixes every current and future case. */
[hidden]{display:none !important}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent-hover)}
:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px;border-radius:3px}
a:focus-visible,.btn:focus-visible,.chip:focus-visible,summary:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px}
::selection{background:rgba(var(--accent-rgb),.28);color:var(--se-text-white)}

.skip{position:absolute;left:-999px;top:0;background:var(--se-primary);color:var(--se-deep);padding:10px 18px;z-index:100;border-radius:0 0 8px 0;font-weight:700}
.skip:focus{left:0}

.wrap{max-width:1080px;margin:0 auto;padding:0 24px}
.section{padding:clamp(72px,9vw,116px) 0;position:relative}
.section-tight{padding:clamp(44px,6vw,64px) 0}

/* ---------- Type roles ---------- */
.eyebrow{
  font-family:var(--font-secondary);font-size:12px;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--accent);
  display:flex;align-items:center;gap:10px;margin-bottom:20px;
}
.eyebrow::before{content:"";width:22px;height:2px;background:var(--accent);border-radius:1px;flex:none}
.section-label{
  font-family:var(--font-secondary);font-weight:500;font-size:13px;
  letter-spacing:1.6px;text-transform:uppercase;color:var(--se-a11y-muted);
  margin-bottom:14px;
}
h1.display{
  font-family:var(--font-primary);font-weight:800;
  font-size:clamp(38px,5.6vw,66px);line-height:1.04;letter-spacing:-.025em;
  color:var(--se-text-white);text-wrap:balance;
}
h1.display em{font-style:normal;color:var(--accent);position:relative;white-space:nowrap}
/* Hero accent phrases wrap, and hero display type sets a step down from the 66px scale.
   The nowrap default keeps an accent phrase intact in body-scale headings, but in a hero it
   inflates the grid track's min-content and crushes the panel column.
   EXTENDED to Source-Connect and Source-Live 2026-07-19 — they were the two that still had
   it, and the damage was measurable: the three product heroes, which are siblings and should
   align, were splitting their columns 588/361 (SC), 508/460 (NX, already overridden) and
   546/401 (SL). Same nominal `1.05fr .95fr`; the only difference was how much each accent
   phrase inflated min-content. With the phrase allowed to wrap, all three settle on the
   nominal split, and the H1s stop breaking into three lines with a short orphan middle line
   ("Welcome to the new" / "era of" / "remote recording.").
   EXTENDED to Apps 2026-08-28 (task T8) — its new hero h1 ("Specialized applications
   built for *every creative workflow*.") carries the same em phrase over a
   two-column hero grid and hit the identical 390px horizontal-overflow defect
   this rule already fixes for the other four hero pages. */
#page-home .hero h1.display em,
#page-source-connect .hero h1.display em,
#page-source-nexus .hero h1.display em,
#page-source-live .hero h1.display em,
#page-apps .hero h1.display em{white-space:normal}
#page-home .hero h1.display,
#page-source-connect .hero h1.display,
#page-source-nexus .hero h1.display,
#page-source-live .hero h1.display,
#page-apps .hero h1.display{font-size:clamp(36px,4.8vw,56px)}
/* 4.8vw is below the 36px floor for every viewport under ~750px, so the clamp
   NEVER scales these down on a phone — it is pinned at 36px all the way to
   320px. The longest word in the set is "collaboration": 249px at 36px, in a
   column that is only ~216px wide at a 320px viewport. It overflowed by 21px,
   and nothing caught it (overflow-wrap is normal, hyphens is manual).
   Stepping the size down keeps the word whole rather than breaking it: 207px
   at 30px, which clears 216px. Applies to the small-phone range only. */
@media (max-width:360px){
  #page-home .hero h1.display,
  #page-source-connect .hero h1.display,
  #page-source-nexus .hero h1.display,
  #page-source-live .hero h1.display,
  #page-apps .hero h1.display{font-size:30px}
}
h2.h-section{
  font-family:var(--font-primary);font-weight:800;
  font-size:clamp(28px,3.6vw,42px);line-height:1.1;letter-spacing:-.018em;
  color:var(--se-text-white);max-width:22ch;text-wrap:balance;
}
/* Statement headline — a full sentence set smaller than .h-section.
   Needs its own leading/tracking/measure: .h-section's 1.1 line-height and 22ch
   measure are tuned for a short 42px display line and crowd badly at this size. */
h2.h-statement{
  font-family:var(--font-primary);font-weight:800;
  font-size:clamp(21px,2.4vw,28px);line-height:1.34;letter-spacing:-.008em;
  color:var(--se-text-white);max-width:32ch;text-wrap:balance;
}
/* Question heading on a product page (Ross 2026-10-05). The 22ch measure above
   is tuned for a short display line; a question set at that measure wraps into a
   narrow three-line stack inside a much wider column ("Which surround formats does
   Source-Connect support?" used 541px of 772px). The class lifts only the cap: the
   heading takes its column's width, keeps balance, and keeps whatever centring its
   context gives it. Applied by hand to h2.h-section headings ending in "?" on the
   three product pages; the global 22ch rule and every other heading are untouched.
   Specificity (0,2,1) also beats .mf-q's 30ch, which never won against
   h2.h-section anyway. */
h2.h-section.h-section--q{max-width:none}
/* Typography tokens — replace inline font-size overrides (zero visual change) */
.card p.eyebrow-sm{font-size:10.5px;margin-bottom:10px}
.stat-num{font-family:var(--font-mono);font-size:30px;font-weight:600;color:var(--se-text-white)}
.stat-label{font-family:var(--font-secondary);font-size:12.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--se-text-caption)}
.note{font-size:15px;color:var(--se-text-dim);margin-bottom:20px}
.credit-line{font-size:14px;color:var(--se-text-secondary)}
.credit-line b{color:var(--se-text-white)}
.card h3.h-sub{font-size:20px}
.tc-row .val.val-lg{font-size:22px}
.sync-lock.sync-lock-lg{font-size:11px}
/* Certification / partner mark. Height-driven so width follows the real asset's
   aspect on swap-in; margins provide the logo's clear space. */
.brand-mark{
  /* +20% on Ross's Sept-15 note ("Dolby logo a bit bigger"), applied 2026-09-21.
     34/3.2vw/44 -> 41/3.84vw/53. The class is used exactly ONCE across all 383
     built pages -- the Dolby Atmos lockup on the home page -- so sizing it here
     is safe and needs no Dolby-specific class. width:auto holds the aspect;
     only the clamp moves. */
  display:block;height:clamp(41px,3.84vw,53px);width:auto;
  margin:18px 0 22px;
}
/* Renders black-artwork partner logos white for the dark band. Accepted treatment:
   inverting a flat monochrome mark is pixel-identical to its official white version. */
.brand-mark--reversed{filter:invert(1);}
.section-head{margin-bottom:clamp(36px,5vw,56px)}
.section-head .sub{color:var(--se-text-dim);max-width:56ch;margin-top:14px;font-size:17px}
.lede{font-size:clamp(17px,1.8vw,19px);color:var(--se-text-secondary);max-width:52ch;margin:22px 0 34px}
.center{text-align:center}
.center h2.h-section,.center .sub,.center .lede{margin-left:auto;margin-right:auto}
.center .eyebrow{justify-content:center}
.dim{color:var(--se-text-caption)}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--font-primary);font-weight:700;font-size:15px;line-height:1;
  padding:15px 28px;border-radius:var(--r-pill);border:1px solid transparent;
  cursor:pointer;transition:transform var(--dur-fast) ease,box-shadow .3s var(--ease-settle),background var(--dur-fast) ease,border-color var(--dur-fast) ease,color var(--dur-fast) ease;
  white-space:nowrap;
}
.btn:active{transform:translateY(1px) scale(.99)}
a.chip{transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease,transform var(--dur-fast) ease}
a.chip:hover{transform:translateY(-1px);border-color:rgba(var(--accent-rgb),.55);color:var(--accent)}
.btn-primary{
  background:linear-gradient(135deg,var(--accent) 0%,var(--accent-hover) 120%);
  color:var(--accent-ink);
  box-shadow:0 0 0 1px rgba(var(--accent-rgb),.35),0 8px 28px rgba(var(--accent-rgb),.22);
}
.btn-primary:hover{color:var(--accent-ink);box-shadow:0 0 0 1px rgba(var(--accent-rgb),.6),0 10px 34px rgba(var(--accent-rgb),.34);transform:translateY(-1px)}
.btn-ghost{
  background:rgba(255,255,255,.03);color:var(--se-text);
  border-color:rgba(var(--se-border-teal-rgb),.45);
}
.btn-ghost:hover{border-color:var(--accent);color:var(--se-text-white);background:rgba(var(--accent-rgb),.06)}
.btn-sm{padding:11px 20px;font-size:13.5px}
/* The small variant measures 37.5px — fine under a mouse, under the 44px target under a
   thumb. Two rules on purpose: `pointer:coarse` catches touch devices at ANY width (tablets,
   touch laptops), and the width-based rule further down catches phone-sized layouts. The
   coarse query cannot be verified in this desktop browser — it reports `pointer:fine` — so
   the width rule is the one under test here, and the belt-and-braces pair is deliberate
   rather than redundant. */
@media (pointer:coarse){ .btn-sm{min-height:44px} }
.btn-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
/* A centred section head centres its heading and sub via text-align, but
   .btn-row is a FLEX container — text-align does not move flex items, so the
   buttons sat hard against the left edge of a full-width row while everything
   above them was centred. Measured 272px off at 1880px wide. */
.section-head.center .btn-row{justify-content:center}


/* ---------- Header ---------- */
.site-header{
  position:sticky;top:0;z-index:50;
  background:rgba(var(--se-bg-rgb),.78);
  backdrop-filter:blur(16px) saturate(1.4);
  -webkit-backdrop-filter:blur(16px) saturate(1.4);
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14);
}
/* --hdr-gutter is shared, not repeated: the open mobile nav panel indents its
   items by this same value so their text lines up with the logo. Hardcoding it
   in two places would break the moment one of them changed at a breakpoint. */
.header-in{--hdr-gutter:24px;max-width:1240px;margin:0 auto;padding:0 var(--hdr-gutter);display:flex;align-items:center;gap:28px;height:var(--hdr-h)}
/* THE REAL MARK. What was here before was invented: five coloured equaliser
   bars beside a CSS-set wordmark. The actual Source Elements logo is one piece
   of artwork — "SOURCE" over "ELEMENTS", uppercase and letterspaced, with the
   O of SOURCE replaced by a solid lime disc — and the wordmark is drawn as
   paths, so it cannot be reproduced with a font. It is served from SE's own
   CDN rather than redrawn.
   White + #C5E86C on transparent, which suits every surface it sits on here;
   this build has no light theme (0 matches for prefers-color-scheme), so no
   dark-background variant is needed. If a light theme ever lands, this needs
   an inverted asset. */
.logo{display:flex;align-items:center;flex:none}
.logo img{height:34px;width:auto;display:block}
.logo:focus-visible{outline:2px solid var(--se-focus);outline-offset:4px;border-radius:4px}
.main-nav{display:flex;align-items:center;gap:4px;flex:1}
.main-nav a,.nav-dd summary{
  font-family:var(--font-primary);font-weight:600;font-size:14px;color:var(--se-text-secondary);
  padding:9px 13px;border-radius:var(--r-lg);transition:color var(--dur-fast) ease,background var(--dur-fast) ease;
  list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px;
}
.main-nav a:hover,.nav-dd summary:hover{color:var(--se-text-white);background:rgba(255,255,255,.05)}
.main-nav a.active{color:var(--accent)}
.nav-dd{position:relative}
.nav-dd summary::-webkit-details-marker{display:none}
.nav-dd summary::after{content:"";width:7px;height:7px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translateY(-2px);transition:transform var(--dur-fast) ease}
.nav-dd[open] summary::after{transform:rotate(-135deg) translateY(-2px)}
.nav-dd .dd-menu{
  position:absolute;top:calc(100% + 10px);left:0;min-width:230px;
  background:var(--se-frame);border:5px solid var(--se-bg);border-radius:var(--r-xl);
  box-shadow:0 0 0 1px rgba(var(--se-border-teal-rgb),.18),0 20px 50px rgba(0,0,0,.4);
  padding:8px;display:flex;flex-direction:column;gap:2px;
}
/* `align-items:flex-start` is a FIX, not decoration. `.dd-menu a` also matches `.main-nav a`
   above, which sets `align-items:center` to vertically centre its inline-flex row. These are
   `flex-direction:column`, so that same declaration was centring the title and description
   HORIZONTALLY — every dropdown item was centre-set (measured: the <b> sat 45px in from a
   12px padding edge). Centred multi-line entries in a 230px menu are hard to scan and are not
   what the rest of the nav does. */
.dd-menu a{display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:1px;padding:10px 12px;border-radius:var(--r-md)}
/* A dropdown trigger now says when you are inside its section — direct nav links already did
   (`.main-nav a.active`), so without this the nav told you where you were only for the items
   that happen to sit at top level. Set by render(). */
.nav-dd summary.in-section{color:var(--accent)}
.dd-menu a b{color:var(--se-text-white);font-size:14px}
/* --se-text-dim (6.10:1), NOT --se-text-caption: this sits on --se-frame, where caption's
   .5 alpha measures 4.31:1 — below AA 4.5:1 for 12px normal text. Measured 2026-07-17. */
.dd-menu a span{font-size:12px;color:var(--se-text-dim);font-weight:400}
.header-actions{display:flex;align-items:center;gap:12px;flex:none}
.header-actions .login{font-weight:600;font-size:14px;color:var(--se-text-secondary);padding:9px 6px}
.header-actions .login:hover{color:var(--se-text-white)}
/* 44x44 is not padding for its own sake: this is the ONLY route to navigation once the nav
   collapses, and it measured 42x38 — under the 44px target every touch guideline asks for,
   on the single most important control on a phone. The bars inside are unchanged; only the
   hit area grew. */
/* `flex:none` is load-bearing, not tidiness: `.nav-toggle` is a flex child of `.header-in`,
   so it defaults to shrinkable — setting `width:44px` alone still rendered it **30.4px** wide
   on a 390px header, because the row squeezed it. Measured before and after. */
.nav-toggle{display:none;flex:none;background:none;border:1px solid rgba(var(--se-border-teal-rgb),.4);border-radius:var(--r-md);width:44px;height:44px;cursor:pointer;position:relative}
.nav-toggle span,.nav-toggle span::before,.nav-toggle span::after{content:"";position:absolute;left:10px;right:10px;height:2px;background:var(--se-text);border-radius:1px;transition:transform .2s ease,opacity .2s ease}
.nav-toggle span{top:50%;margin-top:-1px}
.nav-toggle span::before{top:-6px;left:0;right:0}
.nav-toggle span::after{top:6px;left:0;right:0}

/* ---------- Panels — the double-frame spatial signature ---------- */
.panel{
  background:var(--se-frame);
  border:5px solid var(--se-bg);
  border-radius:var(--r-2xl);
  box-shadow:0 0 0 1px rgba(var(--se-border-teal-rgb),.16),0 24px 60px rgba(0,0,0,.35);
  overflow:hidden;
}
.panel-head{
  display:flex;align-items:center;gap:14px;
  padding:13px 18px;border-bottom:1px solid rgba(var(--se-bg-rgb),.6);
  font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.08em;
  color:var(--se-text-secondary);
}
.panel-head .spacer{flex:1}
.panel-body{padding:20px 18px}
.recess{
  background:var(--se-bg);
  border-radius:var(--r-md);
  box-shadow:inset 0 0 10px 5px rgba(0,0,0,.05),inset 0 2px 6px rgba(0,0,0,.25);
}
.status-dot{width:8px;height:8px;border-radius:2px;background:var(--se-selected);box-shadow:0 0 10px rgba(167,225,99,.7);flex:none}
.status-dot.pulse{animation:pulse 1.5s ease-in-out infinite}
@keyframes pulse{0%,100%{box-shadow:0 0 4px rgba(167,225,99,.4)}50%{box-shadow:0 0 12px rgba(167,225,99,.9)}}

/* ---------- Chips ---------- */
.chip-row{display:flex;flex-wrap:wrap;gap:8px}
.chip{
  font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.05em;
  color:var(--se-text-secondary);
  background:var(--se-bg);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-sm);padding:6px 11px;white-space:nowrap;
}
.chip-accent{color:var(--accent);border-color:rgba(var(--accent-rgb),.45)}

/* ---------- Cards ---------- */
.grid{display:grid;gap:20px}
.grid-2{grid-template-columns:repeat(2,1fr)}
.grid-3{grid-template-columns:repeat(3,1fr)}
.grid-4{grid-template-columns:repeat(4,1fr)}
/* Flex column so the CTA can be pinned to the bottom. Grid already stretches these to equal
   height, but `.card` was `display:block`, so a link sat immediately after its paragraph and
   floated wherever that copy happened to end — measured on the Academy course row (all three
   cards 535px tall): the three "Start the course" links sat 106px, 29px and 130px above their
   card bottoms. `.craft` already solved this with `margin-top:auto`; `.card` never got it. */
.card{
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);
  border-radius:var(--r-xl);
  padding:26px 24px;
  display:flex;flex-direction:column;
  transition:transform var(--dur-slow) var(--ease-settle),box-shadow var(--dur-slow) var(--ease-settle),border-color var(--dur-slow) ease;
}
.card:hover{transform:translateY(-4px);border-color:rgba(var(--accent-rgb),.4);box-shadow:0 20px 50px rgba(0,0,0,.3)}
/* Product tiles only (#products) — accent-tinted glow layered on the base hover shadow. */
#products .card:hover{box-shadow:0 20px 50px rgba(0,0,0,.3),0 0 46px rgba(var(--accent-rgb),.14)}
.card .led{width:9px;height:9px;border-radius:2px;background:var(--accent);box-shadow:0 0 12px rgba(var(--accent-rgb),.65);margin-bottom:18px}
.card h3{font-size:17px;font-weight:700;color:var(--se-text-white);margin-bottom:8px;letter-spacing:-.01em}
.card p{font-size:14.5px;color:var(--se-text-dim);line-height:1.65}
/* `margin-top:auto` pins the CTA to the card's bottom so a row of them lines up regardless of
   how long each card's copy runs; `align-self:flex-start` keeps the link's own hit area to its
   text rather than stretching it across the card (flex children stretch by default). */
.card .guide-link{display:inline-block;align-self:flex-start;margin-top:auto;padding-top:14px;font-size:13px;font-weight:600}
/* Card-top media (2026-07-19: course cards want an image each; the Support guide index
   wants a screenshot per product). Bleeds to the card's edges by cancelling its 26px/24px
   padding, so the image reads as the card's head rather than a floating thumbnail.
   `--card-media-ar` lets a card set its own ratio: 16/9 for the real Academy course
   thumbnails (which are ~1.78), 1/1 for our natively-square UI shots. `cover` is exact, not
   a crop, when the art already matches the ratio — chosen so the shots' visible
   "SCREENSHOT ·" honesty badge is never cropped away. */
.card-media{
  /* `max-width:none` is load-bearing: the global `img,svg,canvas{max-width:100%}` reset on
     L32 otherwise clamps the calc() below back to the content box, and the image stops 49px
     short of the card's right edge instead of bleeding flush. */
  display:block;width:calc(100% + 48px);max-width:none;margin:-26px -24px 20px;
  aspect-ratio:var(--card-media-ar,16/9);object-fit:cover;
  border-radius:var(--r-xl) var(--r-xl) 0 0;
  background:var(--se-deep);
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16);
}
/* height:auto is load-bearing beside aspect-ratio. The HTML width/height
   attributes are presentational hints that set a DEFINITE height, and a definite
   height BEATS aspect-ratio — so a card declaring height="520" in a 241px-wide
   square slot rendered 241x520. The attributes stay, because they are what
   prevents layout shift; this makes CSS decide the shape.
   DELIBERATELY SCOPED to --square rather than to .card-media: the unscoped rule
   also changes pages this change was not asked to touch. See the academy note in
   the handoff — one placement there is oversized for the same reason and is a
   real defect, but correcting it is a separate, reviewed change. */
.card-media--square{--card-media-ar:1/1;height:auto}
/* A product shot that sits INSIDE its column rather than bleeding out of it.
   `.card-media` is the wrong component here: its `width:calc(100% + 48px)` and
   negative margins are tuned to bleed through a `.card`'s 26px/24px padding,
   so dropped into a bare `.split` column with no padding it simply overflowed
   — 532px of image in a 484px column, 24px proud on each side. */
.app-shot{display:block;width:100%;height:auto;border-radius:var(--r-xl);
  border:1px solid rgba(var(--se-border-teal-rgb),.16)}

/* ---------- App launcher grid (/apps) ---------- */
/* A launcher, not a marketing layout: icon, name, one line of what it is.
   Each tile carries its product's own accent via data-accent, so the grid
   reads as a family rather than a borrowed palette. minmax(148px) gives 6
   across at full width and never fewer than 2 on a phone. */
/* grid-auto-rows:1fr because the longest name ("Source-Nexus Suite") wraps to
   two lines while its neighbours do not — without it the second row of a 2-up
   phone layout sits taller than the first. */
.app-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));
  grid-auto-rows:1fr;gap:16px}
/* Recorder's waveform (T11, moment 4): a decorative stroke band the engine
   draws left-to-right when armed; unarmed it is simply a drawn waveform.
   preserveAspectRatio=none lets it stretch to the column. */
.rec-wave{max-width:724px;margin:18px auto 6px}
.rec-wave svg{display:block;width:100%;height:72px}
.app-tile{
  display:flex;flex-direction:column;align-items:center;text-align:center;gap:9px;
  padding:26px 14px 22px;border-radius:var(--r-xl);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  transition:transform var(--dur-slow) var(--ease-settle),border-color var(--dur-slow) ease;
}
.app-tile:hover{transform:translateY(-3px);border-color:rgba(var(--accent-rgb),.35)}
.app-tile:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px}
/* The squircle. Sized so a 6-up row still reads at a glance, and tinted with
   the tile's accent rather than filled with it — a solid block of lime at this
   size overwhelms the card it sits on. */
.app-tile__icon{
  width:78px;height:78px;border-radius:21px;flex:none;
  display:flex;align-items:center;justify-content:center;
  color:var(--accent);background:rgba(var(--accent-rgb),.12);
  border:1px solid rgba(var(--accent-rgb),.30);
}
.app-tile__icon svg{width:42px;height:42px;display:block}
.app-tile__name{font-size:14.5px;font-weight:700;color:var(--se-text-white);line-height:1.25}
.app-tile__meta{font-size:12px;color:var(--se-text-dim);line-height:1.45}
/* LABS marker. Deliberately on the tile rather than in the name, because the
   product name is Source-Connect either way — Labs is the build, not the app. */
.app-tile__badge{
  font-family:var(--font-secondary);font-size:9.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent);
  border:1px solid rgba(var(--accent-rgb),.34);border-radius:var(--r-pill);
  padding:3px 8px;margin-top:1px;
}
@media (max-width:560px){.app-grid{grid-template-columns:repeat(2,1fr)}}

/* ---------- Hero ---------- */
.hero{padding:clamp(64px,8vw,104px) 0 clamp(56px,7vw,88px);position:relative}
.hero::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:2;
  background:
    radial-gradient(900px 480px at 18% -10%,rgba(var(--accent-rgb),.09),transparent 62%),
    radial-gradient(760px 420px at 88% 8%,rgba(var(--se-border-teal-rgb),.07),transparent 60%),
    radial-gradient(1200px 700px at 50% 115%,rgba(10,10,10,.55),transparent 70%);
}
.hero .wrap{position:relative;z-index:3;display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(32px,5vw,64px);align-items:center}

/* Home hero signal-field (subtle scrolling waveform) */
.hero-field{
  /* width/height are NOT redundant with inset:0: <canvas> is a replaced element and won't stretch without them */
  position:absolute;inset:0;width:100%;height:100%;z-index:1;pointer-events:none;
  /* The #000 below is a MASK ALPHA PRIMITIVE meaning "fully opaque" — not a brand colour.
     Do NOT route it through a colour token: it is semantically wrong and breaks the fade. */
  -webkit-mask:linear-gradient(180deg,transparent,#000 22%,#000 86%,transparent);
  mask:linear-gradient(180deg,transparent,#000 22%,#000 86%,transparent);
}
#page-home .hero::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(90deg,rgba(var(--se-bg-rgb),.9),rgba(var(--se-bg-rgb),.4) 46%,rgba(var(--se-bg-rgb),0) 66%);
}
/* Hero CTA treatment — UNSCOPED and ACCENT-AWARE (verdict 5, Phase 2).
   Deliberately overrides the base .btn-primary ring+glow (L120) with a softer, ring-less
   glow for hero CTAs only. --accent-rgb makes it follow the page: lime on /, blue on
   /source-nexus, amber on /source-live — [data-accent] already sets it per page. */
/* Home-only hero CTA: deliberately overrides the base .btn-primary ring+glow with a softer,
   RING-LESS glow. Scope is load-bearing — unscoping strips the 1px accent ring from the
   SC/NX/SL hero CTAs (base L125/L127 is already accent-aware). the scope was re-confirmed
   2026-07-17 after that was measured. Do not unscope without re-deciding it. */
#page-home .hero .btn-primary{
  box-shadow:0 6px 22px rgba(var(--accent-rgb),.24);
  transition:transform var(--dur-fast) var(--ease-settle),box-shadow var(--dur-fast) var(--ease-settle),background var(--dur-fast) var(--ease-settle);
}
#page-home .hero .btn-primary:hover{
  transform:translateY(-2px);
  box-shadow:0 10px 30px rgba(var(--accent-rgb),.34);
}
/* The card-free claim is a CONVERSION line, not a credibility mark. Putting it
   in .trust-row was tried and rejected: it pushed that row to two lines and
   left a dangling separator dot, and the row's dim 11px caps under-serve a
   claim that is true of EVERY Source Elements product. Sentence case, and
   brighter than the caps row, directly under the buttons it qualifies. */
.cta-note{margin:16px 0 0;font-size:13.5px;line-height:1.5;color:var(--se-text-secondary)}
.trust-row{display:flex;align-items:center;flex-wrap:wrap;gap:16px;margin-top:30px}
.trust-row span:not(.trust-dot){
  font-family:var(--font-secondary);font-size:11px;letter-spacing:1.5px;text-transform:uppercase;
  color:var(--se-a11y-muted);
}
.trust-dot{width:4px;height:4px;border-radius:50%;background:rgba(var(--se-border-teal-rgb),.5)}
/* Single-column hero, for a page with no paired visual.
   CURRENTLY UNUSED — and it has never shipped on a page. Academy/Support briefly used it on
   2026-07-19 before both gained real persona portraits and reverted to the standard 2-column
   `.hero`. Keep the finding from that brief use: the rule originally carried
   `max-width:820px`, which indented the hero 130px per side against the 1080px `.wrap` every
   section below uses, so the hero visibly failed to line up with its own page. Cap dropped —
   the modifier now does one thing, collapse the grid, and inherits `.wrap`'s measure.
   TREAT AS UNVALIDATED: like any never-shipped rule, re-check it on first real use. */
.hero-single .wrap{grid-template-columns:1fr}
/* Docs register (/support). Not the persona hero: no portrait, shorter drop, and an index
   panel where the other pages put a face or a mock. Academy and Support were flagged as
   looking too similar; the fix is compositional, not chromatic.
   SECOND PASS 2026-07-19: the first attempt was single-column, which left 437px of dead space
   to the right of a 630px text block and put a full-width rule under it — the rule drew the
   eye straight to the emptiness. It also kept the full 66px marketing display size, so
   "compact" was only ever true of the padding. Now genuinely two-column and genuinely
   smaller-set. */
.hero-docs{padding:clamp(44px,5vw,68px) 0 clamp(40px,4.5vw,60px)}
.hero-docs .wrap{grid-template-columns:1.15fr .85fr;align-items:start}
.hero-docs .display{font-size:clamp(34px,4.2vw,50px);max-width:14ch}
.hero-docs .lede{max-width:46ch}
/* The index panel — a docs landing's "start here", and the thing that balances the column.
   Every entry is a real destination already used elsewhere on this page. */
.docs-index{border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);padding:8px 0;overflow:hidden}
.docs-index .section-label{padding:14px 22px 10px;margin:0}
.docs-index a{display:flex;justify-content:space-between;align-items:center;gap:14px;
  padding:13px 22px;font-family:var(--font-secondary);font-size:13.5px;font-weight:600;
  color:var(--se-text-secondary);border-top:1px solid rgba(var(--se-border-teal-rgb),.12);
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease}
.docs-index a::after{content:"→";color:var(--accent);opacity:.65}
.docs-index a:hover{background:rgba(var(--accent-rgb),.07);color:var(--se-text-white)}
.docs-index a:hover::after{opacity:1}

/* --- Support hero search --- */
/* The field IS the primary action on a docs landing, so it takes the weight
   the primary button used to carry and both buttons drop to ghost. */
.ds-search{margin:28px 0 0;max-width:520px}
.ds-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:14.5px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.3);
  border-radius:var(--r-md);transition:border-color var(--dur-fast) ease}
.ds-search input::placeholder{color:var(--se-text-caption)}
.ds-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.13)}
.ds-count{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

.ds-results{margin:14px 0 0;max-width:520px}
.ds-list{list-style:none;margin:0;padding:0;
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-lg);
  background:var(--se-frame);overflow:hidden}
.ds-list li+li{border-top:1px solid rgba(var(--se-border-teal-rgb),.16)}
.ds-list a{display:flex;align-items:baseline;gap:12px;padding:11px 15px;
  font-family:var(--font-secondary);font-size:13.5px;line-height:1.45;
  color:var(--se-text-secondary);transition:background var(--dur-fast) ease}
.ds-list a:hover{background:rgba(var(--accent-rgb),.07);color:var(--se-text-white)}
.ds-list a:focus-visible{outline:2px solid var(--se-focus);outline-offset:-2px}
.ds-hit{flex:1}
/* --accent-hover and caption sizing: this badge sits on --se-frame, where the
   plain accent measures 4.48:1. Same trap as every other panel on this site. */
.ds-badge{flex:none;font-family:var(--font-secondary);font-style:normal;
  font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--accent-hover);white-space:nowrap}
.ds-more{display:block;width:100%;margin-top:8px;padding:9px 12px;cursor:pointer;
  font-family:var(--font-secondary);font-size:12.5px;font-weight:600;
  color:var(--accent-hover);background:none;
  border:1px dashed rgba(var(--se-border-teal-rgb),.35);border-radius:var(--r-md)}
.ds-more:hover{background:rgba(var(--accent-rgb),.08);border-color:var(--accent)}
.ds-more:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.ds-foot{display:flex;flex-wrap:wrap;gap:6px;margin:12px 0 0}
.ds-foot a{display:inline-flex;align-items:center;gap:7px;min-height:40px;padding:6px 13px;
  font-family:var(--font-secondary);font-size:12px;font-weight:600;
  color:var(--se-text-dim);border:1px solid rgba(var(--se-border-teal-rgb),.26);
  border-radius:var(--r-pill);transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease}
.ds-foot a:hover{color:var(--se-text-white);border-color:var(--accent)}
.ds-foot em{font-family:var(--font-mono);font-style:normal;font-size:11px;
  color:var(--se-text-caption)}
.ds-empty{margin:0;padding:14px 16px;font-family:var(--font-secondary);font-size:13px;
  line-height:1.6;color:var(--se-text-dim);
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-lg);
  background:var(--se-frame)}
.ds-empty a{color:var(--accent-hover);font-weight:600}

@media (max-width:1020px){ .hero-docs .wrap{grid-template-columns:1fr} }

/* --- Support hub: audience doors + inventory band (task T6, moment 13 "We wrote
     it down") --- Doors reuse .grid.grid-3/.card/.guide-link verbatim, same shape as
     the Documentation hubs cards just below them — no new card rule needed. The
     inventory band reuses .stat-num/.stat-label from the Source-Connect stats strip;
     this rule only centers the four figures and sizes them up from that strip's 30px,
     since this band is the page's one signature moment rather than a secondary stat
     line. */
.sup-inv-grid{gap:14px;text-align:center}
.sup-inv-grid .stat-num{font-size:34px}

/* Sector hero proportions. The constraints these rules exist to hold, measured across
   all four sector pages before they were set:
     hero height 1266–1435px (TALLER THAN THE VIEWPORT)
     photo column 508px vs copy column 460px — picture outweighing message
     H1 breaking to 4 and 5 lines
   The extra fault: the copy column also carried a 460px-tall `.ui-shot`, so the column ran
   ~1100px in a 460px measure. Because `.hero .wrap` is `align-items:center`, that tall column
   pushed the vertically-centred portrait down to the middle of the hero, leaving the top-left
   empty while the product shot fell below the fold — the one place it could not do its job.
   So: copy column leads, portrait trimmed, display set smaller (these H1s are full sentences,
   unlike the product pages' short ones), and the hero `.ui-shot` REMOVED in the markup. No product imagery is lost —
   every sector page carries five other shots, and this one was the sole reason the hero ran
   to viewport height. */
.hero-sector .wrap{grid-template-columns:.86fr 1.14fr}
.hero-sector .sl-person{height:430px}
.hero-sector .display{font-size:clamp(34px,4.6vw,56px)}
/* Companion override — REQUIRED. `.hero .wrap`'s collapse below is the same specificity
   (0,2,0) and comes later in the file, so without this the sector heroes would win at desktop
   and lose at mobile in a way that depends purely on source order. Same trap that crushed
   Academy's photo column to 57px. */
@media (max-width:1020px){ .hero-sector .wrap{grid-template-columns:1fr} }

/* ACADEMY HERO — the site's only CENTRED hero, and its only banner-format portrait.
   Design review, 2026-08: Academy and the sector pages had become the same composition (persona column
   left, copy right), so no amount of proportion tuning would separate them. Every other hero
   is a two-column left-to-right split; this one centres and puts its portrait beneath the copy
   as a wide cinematic band. Structurally unique at a glance, persona and TL;DR both kept.
   Single column at every width, so — unlike the previous ID-scoped rule here — it needs no
   companion override inside the responsive collapse; there is no two-column state to undo. */
#page-academy .hero .wrap{grid-template-columns:1fr;justify-items:center;text-align:center;gap:clamp(28px,3.4vw,40px)}
.hero-academy .academy-intro{max-width:760px}
.hero-academy .display{max-width:20ch;margin-inline:auto}
.hero-academy .lede{max-width:62ch;margin-inline:auto}
/* `justify-content` is REQUIRED here, not `text-align`. `.eyebrow` is `display:flex` (the rule
   builds its leading dash with a `::before` flex item), and text-align does not move flex
   items — so the eyebrow's BOX centred at 760px while its dash-and-text packed hard against
   the left edge of that box. Measured: box centre 633 matching the H1, but the content sitting
   at x=253. It was reported as the first element looking off-centred. Same failure the nav
   dropdown had, where an inherited `align-items` acted on a column flex. */
.hero-academy .eyebrow{justify-content:center}
.hero-academy .btn-row{justify-content:center}
/* The banner is the portrait re-cut as a 16:5 band. `object-position` favours the upper third
   so the face survives a very wide crop — the same lesson the craft-card photos taught. */
.academy-banner{
  position:relative;width:100%;margin:0;border-radius:var(--r-2xl);overflow:hidden;
  aspect-ratio:16/5;border:1px solid rgba(var(--se-border-teal-rgb),.18);
}
.academy-banner img{width:100%;height:100%;object-fit:cover;object-position:center 32%;
  filter:grayscale(1) contrast(1.05);display:block}
.academy-banner::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 45%,rgba(var(--se-bg-rgb),.85));
}
/* Caption sits on the scrimmed lower band, left-aligned against the centred copy above so the
   band reads as an image with a credit rather than more centred text. */
.academy-banner .sl-cap{left:22px;bottom:16px;text-align:left;z-index:2}
/* The centring is for the hero's copy, not for prose blocks. The TL;DR inherited it and set
   its summary as centred multi-line text, which is measurably harder to scan than ranged-left
   — and it is left-aligned on every other page, so centring it here broke that consistency
   too. Block stays centred; its text does not. */
.hero-academy .tldr{text-align:left}
@media (max-width:600px){
  .academy-banner{aspect-ratio:4/3}
  .academy-banner img{object-position:center 28%}
}
.meter-canvas{width:100%;height:170px}
.session-readout{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
/* TL;DR summary — the pull-quotable 2-sentence box answer engines lift (colleague notes).
   Copy = the route meta descriptions, so page and snippet never drift. */
.tldr{
  grid-column:1/-1;display:flex;align-items:baseline;gap:14px;
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.16);
  border-left:2px solid var(--accent);border-radius:0 var(--r-lg) var(--r-lg) 0;
  padding:14px 18px;margin-top:10px;
}
.tldr__tag{font-family:var(--font-secondary);font-size:10px;font-weight:600;letter-spacing:.14em;color:var(--accent);flex:none}
.tldr p{font-size:14px;color:var(--se-text-secondary);line-height:1.55;margin:0}

/* ---------- Trust wall ---------- */
.logo-wall{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.logo-wall span{
  font-family:var(--font-secondary);font-weight:600;font-size:14px;letter-spacing:1.8px;text-transform:uppercase;
  color:rgba(255,255,255,.42);text-align:center;padding:20px 8px;
  border:1px solid rgba(var(--se-border-teal-rgb),.12);border-radius:var(--r-lg);
  background:rgba(46,52,58,.5);
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease;
}
.logo-wall span:hover{color:rgba(255,255,255,.85);border-color:rgba(var(--se-border-teal-rgb),.3)}
.award-row{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:26px}
.award{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--font-secondary);font-size:11.5px;font-weight:600;letter-spacing:.06em;color:var(--se-live);
  border:1px solid rgba(var(--se-live-rgb),.4);background:rgba(var(--se-live-rgb),.06);
  border-radius:var(--r-pill);padding:8px 16px;
}
.award::before{content:"◆";font-size:9px}

/* Documented credits — registry-confirmed facts. */
/* auto-fit, not repeat(4): the grid is used with 3, 4 and — once the rest of
   the testimonials land — a dozen entries. A fixed four columns leaves an
   empty track whenever the count is not a multiple of four, which is what
   removing the certification card exposed. */
.credits-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:16px}
.credit{
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);border-radius:var(--r-xl);
  padding:22px 20px;display:flex;flex-direction:column;gap:8px;
  transition:transform var(--dur-slow) var(--ease-settle),border-color var(--dur-slow) ease;
}
.credit:hover{transform:translateY(-3px);border-color:rgba(var(--accent-rgb),.35)}
.credit .credit-mark{font-family:var(--font-secondary);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--accent);display:flex;align-items:center;gap:8px}
.credit .credit-mark::before{content:"";width:7px;height:7px;border-radius:2px;background:var(--accent);box-shadow:0 0 8px rgba(var(--accent-rgb),.6)}
.credit b{font-size:16px;color:var(--se-text-white);letter-spacing:-.01em;line-height:1.25}
.credit p{font-size:13px;color:var(--se-text-dim);line-height:1.55;margin:0}
/* --- The media slot --- */
/* A FIXED HEIGHT holding either a 4:5 portrait or a horizontal partner mark.
   The height is what matters: it is why all four eyebrows and names in a row
   share a baseline. Before this the certification card had no slot at all and
   sat a portrait's width out of line with its three neighbours. */
.credit-media{height:92px;display:flex;align-items:center;margin-bottom:4px}
.credit-media img{display:block}
/* 4:5, the ratio the portrait artwork is drawn at, so a real photograph drops
   into the same slot without a re-crop. Was 52x64 — small enough that a face
   would have been unreadable. */
.credit--person .credit-media img{width:74px;height:92px;object-fit:cover;
  border-radius:var(--r-md);border:1px solid rgba(var(--se-border-teal-rgb),.22)}
/* A wordmark is contained, never cropped, and never larger than the artwork. */
.credit--org .credit-media img{width:auto;height:auto;max-width:100%;max-height:40px}
.credit .src{font-family:var(--font-secondary);font-size:11px;letter-spacing:.04em;
  color:var(--se-text-caption);margin-top:auto;padding-top:10px}
/* A source you can follow. The credibility of this whole section is that the
   claims are checkable, so where there is a real URL it is a real link. */
a.src{transition:color var(--dur-fast) ease}
a.src:hover{color:var(--accent-hover)}
a.src:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px;border-radius:2px}
/* One icon, not two. These cards used to print a literal "▶" in the label AND
   carry the square ::before dot, so they read "● ▶ OVERVIEW". The dot becomes
   the play triangle instead. */
.credit--video .credit-mark::before{width:0;height:0;border-radius:0;background:none;
  box-shadow:none;border-left:7px solid var(--accent);
  border-top:4.5px solid transparent;border-bottom:4.5px solid transparent}
/* --- Testimonial cards --- */
/* A wider minimum than the base grid. These carry a paragraph rather than a
   caption, and at 230px a quote sets to about four words a line. Declared
   ABOVE the responsive rules below so the 2-up and 1-up overrides still win —
   both selectors are one class, so source order is what decides. */
.credits-grid--quotes{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
/* The portrait sits BESIDE the name here instead of above it, and it is a
   circle rather than a 4:5 crop, because source-elements.com publishes every
   one of these headshots at 63x63 and that is the only size it publishes. The
   74x92 slot would upscale them 1.17x and soften every face; 52px keeps all of
   them under their intrinsic size. */
.credit-who{display:flex;align-items:center;gap:12px}
.credit-who img{width:52px;height:52px;border-radius:50%;object-fit:cover;flex:none;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);background:var(--se-inner)}
.credit-who b{display:block;margin-bottom:1px}
.credit-who .credit-role{margin:0}
/* Source Elements publishes no photograph of some of these people — not on the
   page carrying their quote, not anywhere on the site. A grey silhouette sitting
   among five real faces reads as an image that failed to load, so the absence is
   made deliberate instead: initials, in the accent, at the same 52px. */
.credit-mono{width:52px;height:52px;border-radius:50%;flex:none;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-secondary);font-size:15px;letter-spacing:.06em;
  color:var(--accent);background:rgba(var(--accent-rgb),.10);
  border:1px solid rgba(var(--accent-rgb),.28)}
/* Education pricing enquiry. A BOUNDED panel rather than another full-width
   centred CTA, because the page already closes with one and two stacked calls
   to action read as a mistake. Being a contained object also keeps it legible
   sitting between two plain sections, where the page's usual band/section
   alternation does not apply. */
.edu-ask{
  display:flex;align-items:center;gap:26px;flex-wrap:wrap;
  padding:26px 28px;border-radius:var(--r-xl);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
}
.edu-ask__copy{flex:1 1 320px;min-width:0}
.edu-ask h3{font-size:20px;color:var(--se-text-white);margin:6px 0 8px;letter-spacing:-.01em}
.edu-ask p{font-size:14px;color:var(--se-text-secondary);line-height:1.6;margin:0;max-width:62ch}
.edu-ask .btn{flex:none}
@media (max-width:560px){.edu-ask{padding:22px 20px;gap:18px}.edu-ask .btn{width:100%;justify-content:center}}
/* ---------- Stories rail (global, sits above the footer) ---------- */
/* CARD WIDTH IS SET BY THE ARTWORK, not the other way round. The published
   story images run 300x200 up to 700x394 — the narrowest is 300px, so the
   media slot is 300px and nothing is ever upscaled. 3:2 crops all six
   cleanly, including the 400x600 portrait and the 600x600 square. */
.stories{padding:clamp(56px,6vw,84px) 0;border-top:1px solid rgba(var(--se-border-teal-rgb),.14);
  background:radial-gradient(120% 140% at 50% 0%,rgba(var(--accent-rgb),.05) 0%,transparent 60%)}
.stories-head{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;
  flex-wrap:wrap;margin-bottom:26px}
.stories-head .h-section{margin:6px 0 0}
/* THE ARROWS FLANK THE RAIL. They used to sit top-right beside the heading,
   which is where Javier lost them. Absolute so they overlay the rail's edges
   rather than stealing a row of height; the wrapper is the positioning
   context. Below 900px they go back to a row under the rail, because at that
   width they would sit on top of the cards. */
.stories-railwrap{position:relative}
.stories-controls{display:flex;gap:8px}
.stories-railwrap>.stories-controls{position:absolute;top:50%;left:0;right:0;
  transform:translateY(-50%);justify-content:space-between;pointer-events:none;z-index:3;
  margin:0 -21px}
.stories-railwrap>.stories-controls .stories-arrow{pointer-events:auto;
  background:var(--se-bg);box-shadow:0 6px 20px rgba(0,0,0,.45)}
@media (max-width:900px){
  .stories-railwrap>.stories-controls{position:static;transform:none;margin:14px 0 0;
    justify-content:flex-end;pointer-events:auto}
  .stories-railwrap>.stories-controls .stories-arrow{box-shadow:none;background:var(--se-frame)}
}
.stories-arrow{
  width:42px;height:42px;border-radius:50%;cursor:pointer;flex:none;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);background:var(--se-frame);
  position:relative;transition:border-color var(--dur-fast) ease,opacity var(--dur-fast) ease;
}
.stories-arrow::before{content:"";position:absolute;top:50%;left:50%;width:8px;height:8px;
  border-left:2px solid var(--accent);border-bottom:2px solid var(--accent);
  transform:translate(-30%,-50%) rotate(45deg)}
.stories-arrow[data-dir="1"]::before{transform:translate(-70%,-50%) rotate(-135deg)}
.stories-arrow:hover{border-color:rgba(var(--accent-rgb),.5)}
.stories-arrow:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px}
.stories-arrow[disabled]{opacity:.3;cursor:default}
/* The rail. scroll-snap so a drag always lands on a card edge; the scrollbar is
   hidden because the arrows and the edge fade already say "there is more". */
.stories-rail{
  display:grid;grid-auto-flow:column;grid-auto-columns:300px;gap:18px;
  overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;
  padding:4px 4px 10px;margin:0 -4px;
  scrollbar-width:none;-ms-overflow-style:none;
}
.stories-rail::-webkit-scrollbar{display:none}
.stories-rail:focus-visible{outline:2px solid var(--se-focus);outline-offset:4px;border-radius:var(--r-xl)}
.story-card{
  scroll-snap-align:start;display:flex;flex-direction:column;
  border-radius:var(--r-xl);overflow:hidden;
  border:1px solid rgba(var(--se-border-teal-rgb),.16);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  transition:transform var(--dur-slow) var(--ease-settle),border-color var(--dur-slow) ease;
}
.story-card:hover{transform:translateY(-4px);border-color:rgba(var(--accent-rgb),.38)}
.story-card:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px}
.story-card__media{display:block;aspect-ratio:3/2;overflow:hidden;position:relative;background:var(--se-inner)}
.story-card__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform var(--dur-slow) var(--ease-settle)}
.story-card:hover .story-card__media img{transform:scale(1.04)}
/* A wash of the page accent over the photograph, so a rail of images shot in
   six different rooms still reads as one branded set. */
.story-card__media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(var(--accent-rgb),.10) 0%,transparent 45%,rgba(20,24,28,.55) 100%)}
.story-card__kicker{font-family:var(--font-secondary);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent);padding:18px 18px 0}
.story-card__title{font-size:15px;font-weight:700;line-height:1.35;color:var(--se-text-white);
  letter-spacing:-.01em;padding:8px 18px 0}
.story-card__more{font-family:var(--font-secondary);font-size:11.5px;letter-spacing:.04em;
  color:var(--se-text-caption);padding:12px 18px 18px;margin-top:auto}
.story-card:hover .story-card__more{color:var(--accent-hover)}
/* The tail card has no photograph, so it earns its height with the accent instead. */
.story-card--all{justify-content:center;
  background:linear-gradient(160deg,rgba(var(--accent-rgb),.14) 0%,var(--se-inner) 70%)}
.story-card--all .story-card__title{font-size:17px;padding-top:10px}
@media (max-width:560px){.stories-rail{grid-auto-columns:262px}.stories-controls{display:none}}
/* ---------- Store chrome ---------- */
/* /store deliberately does NOT use .hero. A hero is a marketing device — one
   big claim, then persuasion. A storefront's job is the opposite: put goods and
   utilities in reach immediately. So the page opens on a compact bar (identity
   + account + cart), a category rail, and a reassurance strip, and the first
   product card sits above the fold instead of below a display headline. */
.store-bar{border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16);
  background:linear-gradient(180deg,rgba(var(--accent-rgb),.06) 0%,transparent 100%)}
.store-bar__in{display:flex;align-items:center;justify-content:space-between;
  gap:24px;flex-wrap:wrap;padding:22px 0 20px}
.store-bar__mark{font-family:var(--font-secondary);font-size:10px;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--accent);display:block}
/* The H1 is deliberately small. On a storefront the merchandise is the headline;
   the page still needs one H1 for structure, so it states the errand instead of
   making a claim. */
.store-bar__title{font-family:var(--font-primary);font-weight:700;font-size:21px;
  line-height:1.25;letter-spacing:-.01em;color:var(--se-text-white);margin:5px 0 0}
.store-bar__id{flex:0 1 auto}
/* The bar's middle was dead width. A storefront's answer to that space is a
   SEARCH FIELD, not a button — and this one is real: a GET form straight to
   the store's own /catalogsearch/result/, which takes ?q= and returns results. */
.store-search{flex:1 1 300px;max-width:460px;min-width:0}
.store-search input{
  width:100%;font-family:var(--font-primary);font-size:13.5px;color:var(--se-text-white);
  padding:11px 16px;border-radius:var(--r-pill);
  border:1px solid rgba(var(--se-border-teal-rgb),.24);background:var(--se-inner);
  transition:border-color var(--dur-fast) ease;
}
.store-search input::placeholder{color:var(--se-text-caption)}
/* Every search box on the site sits on --se-inner, where --se-text-caption is
   4.42:1 and fails AA (tokens.css). One rule for all of them, outranking each
   box's own placeholder colour. */
form[role=search] input::placeholder{color:var(--se-a11y-muted)}
.store-search input:focus{outline:none;border-color:rgba(var(--accent-rgb),.55)}
.store-search input:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.store-bar__acts{display:flex;align-items:center;gap:8px;flex:none}
.store-util{font-family:var(--font-secondary);font-size:12px;letter-spacing:.04em;
  color:var(--se-text-secondary);padding:9px 15px;border-radius:var(--r-pill);
  border:1px solid rgba(var(--se-border-teal-rgb),.22);white-space:nowrap;
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease}
.store-util:hover{color:var(--se-text-white);border-color:rgba(var(--accent-rgb),.45)}
.store-util:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.store-util--cart{color:var(--se-bg);background:var(--accent);border-color:transparent;font-weight:600}
.store-util--cart:hover{color:var(--se-bg);background:var(--accent-hover)}
/* Category rail — horizontal and scrollable rather than wrapping, so the row
   reads as "a shop's departments" at every width. */
.store-cats{display:flex;gap:8px;overflow-x:auto;padding:20px 0 4px;
  scrollbar-width:none;-ms-overflow-style:none}
.store-cats::-webkit-scrollbar{display:none}
/* 11px vertical, not 9px: these became real controls when the rail started
   filtering in place, and at 9px they measured 38px tall — under the 40px
   touch target the rest of the project holds to. */
.store-cat{flex:none;font-size:13px;font-weight:600;color:var(--se-text-secondary);
  padding:11px 16px;border-radius:var(--r-pill);white-space:nowrap;
  border:1px solid rgba(var(--se-border-teal-rgb),.22);background:var(--se-frame);
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease}
.store-cat:hover{color:var(--se-text-white);border-color:rgba(var(--accent-rgb),.45)}
.store-cat:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.store-cat{cursor:pointer;font-family:inherit}
/* The selected department. Filled rather than merely outlined, because on a
   scrolling rail an outline-only selected state is easy to lose. */
.store-cat.is-on{color:var(--se-bg);background:var(--accent);border-color:transparent}
.store-cat.is-on:hover{color:var(--se-bg);background:var(--accent-hover)}
.store-empty{font-size:14px;color:var(--se-text-dim);padding:28px 0 0;margin:0}
.store-trust{display:flex;flex-wrap:wrap;gap:8px 22px;list-style:none;padding:16px 0 0;margin:0}
.store-trust li{font-size:12.5px;color:var(--se-text-dim);display:flex;align-items:center;gap:7px}
.store-trust li::before{content:"";width:5px;height:5px;border-radius:50%;
  background:var(--accent);flex:none}
/* Density. The marketing pages' .section carries 116px of top padding, which on
   a storefront put 116px of NOTHING between the department rail and the first
   product — measured, and the single biggest reason the page read as empty. */
#page-store .section{padding-top:clamp(38px,3.4vw,54px);padding-bottom:clamp(38px,3.4vw,54px)}
#page-store > .wrap + .section{padding-top:26px}
@media (max-width:560px){
  .store-bar__in{padding:18px 0 16px;gap:14px}
  .store-bar__title{font-size:18px}
  .store-search{flex:1 1 100%;order:3;max-width:none}
  .store-bar__acts{order:2}
  .store-util{flex:1;text-align:center}
}

/* Store section heads are LEFT-ALIGNED AND SMALL, not the centred display
   heads the marketing pages use. A centred 40px h2 costs ~200px before the
   first product and reads as persuasion; a shop announces a department and
   gets out of the way. The h2 text is unchanged — the question form still
   serves AEO, it just is not set like a billboard. */
.store-sec-head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  padding-bottom:14px;margin-bottom:22px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14)}
.store-sec-head .section-label{margin:0;order:-1;flex:none}
.store-sec-head .h-section{font-size:22px;line-height:1.25;margin:0;letter-spacing:-.01em}
.store-sec-head .sub{font-size:13px;color:var(--se-text-dim);margin:0;
  flex:1 1 100%;max-width:none}
@media (max-width:560px){.store-sec-head .h-section{font-size:19px}}

/* Store "from" price. ONE number per product on this page, deliberately: the
   authoritative tables live in each product's own pricing section, and a price
   repeated in two places will drift. Everything here links back to those. */
.store-from{font-size:15px !important;color:var(--se-text-secondary) !important;margin:2px 0 6px !important}
.store-from b{color:var(--accent);font-size:19px;letter-spacing:-.01em}
/* MOMENT — "Prices arrive honestly" (Delight & Creation spec, moment 12).
   The shop grid's cards (#storeItems) carry .mo-seq/.mo-reveal from the
   shared engine directly — no page-local CSS needed for the reveal itself.
   The whole-dollar figures inside .store-from are wrapped in .mo-count
   (engine rule at "Motion engine (js/motion.js)" above sets tabular-nums
   and the count-up); a .mo-count nested in <b> inherits this rule's accent
   colour and size for free, so no override belongs here. Figures with
   cents, or hedged "about $X" equivalents, are left unwrapped — see the
   inline HTML comments beside each card in index.html for which and why. */

/* Cost over time — the Buy-In comparator (positioning brief §6). Part of the
   SAME moment as the cards above, which is why it is styled here and not in a
   block of its own. Desktop rich, mobile calm, and the swap is CSS ONLY: below
   768px — the same threshold motion.js uses to decide whether to arm at all —
   the range and the counting readout go away and the static 3/5-year table
   takes their place. The tier control stays in both, because choosing a tier
   is not motion, it is the question the reader came with. Nothing here hides
   anything from a reader without JavaScript: at >=768px the readout IS the
   answer for the default tier and horizon, written into the markup. */
.store-calc{
  margin:20px 0 4px;padding:18px 20px 16px;border-radius:var(--r-md);
  border:1px solid rgba(var(--se-border-teal-rgb),.18);background:rgba(46,52,58,.34);
}
.store-calc__h{font-size:14px;letter-spacing:.02em;margin:0 0 12px;color:var(--se-text-white)}
.store-calc__tiers{display:flex;flex-wrap:wrap;gap:8px}
.store-calc__tier{
  flex:none;font-family:inherit;cursor:pointer;font-size:13px;font-weight:600;
  color:var(--se-text-secondary);background:transparent;padding:7px 14px;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);border-radius:var(--r-pill);
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease,background var(--dur-fast) ease;
}
.store-calc__tier:hover{color:var(--se-text-white);border-color:rgba(var(--accent-rgb),.45)}
.store-calc__tier:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.store-calc__tier.is-on{color:var(--se-bg);background:var(--accent);border-color:transparent}
.store-calc__tier.is-on:hover{color:var(--se-bg);background:var(--accent-hover)}
.store-calc__years{display:flex;align-items:center;gap:14px;margin:18px 0 4px}
.store-calc__yearsLab{font-size:12.5px;color:var(--se-text-dim);flex:none}
.store-calc__track{position:relative;flex:1 1 auto;min-width:120px;display:flex;align-items:center}
.store-calc__range{width:100%;accent-color:var(--accent);cursor:pointer}
.store-calc__range:focus-visible{outline:2px solid var(--se-focus);outline-offset:4px}
/* The break-even mark. Its LEFT is written by the page as break-even / 60 of
   the track — arithmetic, not a hand-placed decoration — and its tooltip says
   which month that is. `pointer-events:none` so it can never eat a drag. */
.store-calc__mark{
  position:absolute;top:50%;width:2px;height:16px;margin-top:-8px;pointer-events:none;
  background:rgba(var(--accent-rgb),.85);border-radius:1px;
}
.store-calc__yearsOut{font-size:12.5px;color:var(--se-text-secondary);flex:none;min-width:56px;text-align:right}
.store-calc__out{display:flex;flex-wrap:wrap;gap:6px 34px;align-items:baseline;margin-top:10px}
.store-calc__fig{margin:0;display:flex;flex-direction:column;gap:2px}
.store-calc__figLab{font-size:12px;color:var(--se-text-dim)}
.store-calc__fig b{color:var(--accent);font-size:22px;letter-spacing:-.01em;line-height:1.1}
.store-calc__say{flex:1 1 100%;margin:8px 0 0;font-size:14px;color:var(--se-text-secondary)}
.store-calc__note{margin:12px 0 0;font-size:12px;color:var(--se-text-dim);line-height:1.5}
.store-calc__table{display:none}
@media (max-width:767px){
  .store-calc__years,.store-calc__out{display:none}
  .store-calc__table{display:table;width:100%;border-collapse:collapse;margin-top:16px;font-size:13.5px}
  .store-calc__table th,.store-calc__table td{
    text-align:right;padding:7px 0 7px 12px;
    border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14);
  }
  .store-calc__table thead th{font-size:12px;color:var(--se-text-dim);font-weight:600}
  .store-calc__table tbody th{text-align:left;padding-left:0;color:var(--se-text-secondary);font-weight:600}
  .store-calc__table td{color:var(--accent);font-variant-numeric:tabular-nums}
}
.affil-wall{display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
.affil{
  font-family:var(--font-secondary);font-weight:600;font-size:12.5px;letter-spacing:1.4px;text-transform:uppercase;
  color:rgba(255,255,255,.6);padding:11px 18px;
  border:1px solid rgba(var(--se-border-teal-rgb),.16);border-radius:var(--r-pill);background:rgba(46,52,58,.5);
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease,transform var(--dur-fast) var(--ease-settle);
}
.affil:hover{color:rgba(255,255,255,.85);border-color:rgba(var(--se-border-teal-rgb),.32);transform:translateY(-1px)}
@media (max-width:900px){.credits-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.credits-grid,.craft-grid{grid-template-columns:1fr}}

/* ---------- Pricing ---------- */
.tab-list{
  display:inline-flex;gap:4px;padding:5px;border-radius:var(--r-pill);
  background:var(--se-bg);box-shadow:inset 0 2px 6px rgba(0,0,0,.3);
  margin-bottom:38px;flex-wrap:wrap;position:relative;
}
/* Positioned on BOTH axes by moveIndicator(), not just X. It used to be `top:5px;bottom:5px`,
   which pins it to the full height of the tab list — fine while the list is one row, wrong the
   moment it wraps. At 390px the three purchase-mode tabs wrap to two rows, and the indicator
   became a single 78px-tall block spanning both of them instead of sitting behind the 37px
   tab that is actually selected. Height and Y now come from the selected tab's own box, so it
   is correct at any wrap configuration. */
.tab-indicator{
  position:absolute;top:0;left:0;width:0;height:0;border-radius:var(--r-pill);
  background:var(--se-frame-hover);border:1px solid rgba(var(--accent-rgb),.45);
  z-index:0;transition:transform .3s var(--ease-settle),width .3s var(--ease-settle),height .3s var(--ease-settle);
  pointer-events:none;
}
.tab{
  position:relative;z-index:1;
  font-family:var(--font-secondary);font-weight:500;font-size:13px;letter-spacing:1.12px;text-transform:uppercase;
  color:var(--se-text-dim);background:none;border:1px solid transparent;border-radius:var(--r-pill);
  padding:10px 22px;cursor:pointer;transition:color var(--dur-fast) ease;
}
.tab:hover{color:var(--se-text-white)}
.tab[aria-selected="true"]{color:var(--accent)}
/* CARDS SHARE ONE GRID SO THEIR ROWS LINE UP ACROSS THE ROW, not merely within
   each card. Each card is its own flex column otherwise, which lets every row
   below the tallest element drift: measured on the Subscriptions tab, the
   highlighted card's title, price, note and description all sat 14px lower than
   its neighbours', and the feature lists were 22px apart. Only the eyebrow and
   the button lined up — the button because margin-top:auto pinned it — which is
   what made it read as almost-right rather than obviously broken.
   `subgrid` makes each card adopt the container's rows, so row N is the same
   height in all three. It also removes the need for the empty `&nbsp;`
   paragraphs that used to force this by hand. */
/* COLUMN-GAP ONLY. `gap` applies to rows as well as columns, and with each card
   spanning eight rows that put 24px between every part — 168px of a 661px card,
   a quarter of its height, on top of the margins the parts already carry. The
   flex column this replaced had no row gap at all; its rhythm came from those
   margins, and it still should. */
.price-grid{display:grid;grid-template-columns:repeat(3,1fr);column-gap:24px;row-gap:0;
  /* eyebrow · title · price · note · description · features · action · footnote */
  grid-template-rows:auto auto auto auto auto 1fr auto auto}
.price-grid--4{grid-template-columns:repeat(4,1fr)}
.price-card{
  background:var(--se-frame);border:5px solid var(--se-bg);border-radius:var(--r-2xl);
  box-shadow:0 0 0 1px rgba(var(--se-border-teal-rgb),.16);
  padding:30px 28px;
  transition:transform var(--dur-slow) var(--ease-settle),box-shadow var(--dur-slow) var(--ease-settle);
}
.price-grid>.price-card{grid-row:span 8;display:grid;grid-template-rows:subgrid}
/* EVERY PART IS PLACED EXPLICITLY. Subgrid otherwise maps children to rows in
   DOM order, so a card missing one part — most have no billing note, only one
   has an action link — pulls everything below it up a row and the alignment is
   worse than before. Explicit rows let a missing part leave its row empty. */
.price-grid>.price-card>.rec{grid-row:1}
.price-grid>.price-card>h3{grid-row:2}
.price-grid>.price-card>.price-line{grid-row:3}
.price-grid>.price-card>.price-note{grid-row:4}
.price-grid>.price-card>.desc{grid-row:5}
.price-grid>.price-card>ul{grid-row:6}
.price-grid>.price-card>.btn{grid-row:7;align-self:end}
.price-grid>.price-card>.price-action,
.price-grid>.price-card>.price-footnote{grid-row:8}
/* Everywhere else a .price-card is used on its own (Source-Live has a single
   card in no grid), it keeps the original column behaviour. */
.price-card:not(.price-grid>*){display:flex;flex-direction:column}
.price-card:hover{transform:translateY(-4px);box-shadow:0 0 0 1px rgba(var(--se-border-teal-rgb),.24),0 24px 60px rgba(0,0,0,.35)}
.price-card.highlight{
  transform:scale(1.02);
  box-shadow:0 0 0 1px rgba(var(--accent-rgb),.65),0 0 60px rgba(var(--accent-rgb),.2),0 24px 60px rgba(0,0,0,.35);
}
.price-card.highlight:hover{transform:scale(1.02) translateY(-4px)}
/* min-height, because the highlighted card's eyebrow is a padded pill (32px)
   and the others are plain text (18px). Without it that 14px difference pushes
   one card's entire contents down relative to its neighbours. */
.price-card .rec,.price-free .rec{font-family:var(--font-secondary);font-size:10.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);margin:0 0 12px;display:flex;align-items:center;gap:8px;min-height:32px}
/* was an inline style="width:6px;height:6px" repeated on all 15 cards */
.rec-dot{flex:none;width:6px;height:6px;border-radius:50%;background:var(--accent);
  box-shadow:0 0 8px rgba(var(--accent-rgb),.6)}
.price-card.highlight .rec{
  background:rgba(var(--accent-rgb),.12);border:1px solid rgba(var(--accent-rgb),.4);
  border-radius:var(--r-pill);padding:6px 12px;align-self:flex-start;
}
.price-card h3,.price-free h3{font-size:19px;font-weight:700;color:var(--se-text-white);margin:0}
.price-line{display:flex;align-items:baseline;gap:7px;margin:16px 0 6px}
.price-line .amt{font-size:42px;font-weight:800;color:var(--se-text-white);letter-spacing:-.02em;line-height:1}
.price-line .per{font-size:13.5px;color:var(--se-text-caption)}
.price-note{font-size:12.5px;color:var(--se-a11y-muted);margin:0 0 16px}
.price-card p.desc{font-size:13.5px;color:var(--se-text-dim);line-height:1.6;margin-bottom:18px}
.price-card ul{list-style:none;margin:0 0 24px;display:flex;flex-direction:column;gap:9px;align-content:start}
.price-card li,.price-free-list li{font-size:13.5px;color:var(--se-text-secondary);padding-left:22px;position:relative;line-height:1.45}
.price-card li::before,.price-free-list li::before{content:"";position:absolute;left:0;top:6px;width:9px;height:5px;border-left:2px solid var(--se-selected);border-bottom:2px solid var(--se-selected);transform:rotate(-45deg)}
.price-card li.off,.price-free-list li.off{color:var(--se-text-disabled,rgba(255,255,255,.28))}
.price-card li.off::before,.price-free-list li.off::before{border-color:rgba(255,255,255,.22);transform:none;width:8px;height:0;border-left:none;border-bottom-width:2px;top:9px}
.price-card .btn{justify-content:center}
/* TWO CLASSES, BECAUSE THIS SLOT HELD TWO DIFFERENT THINGS. On Standard/Talent
   it was a link — an action ("Switch to yearly billing"). On Pro/Studio and
   Pro X it was plain specification text. Identical styling, one of them
   clickable, in the row where a reader is deciding what to spend money on. */
.price-action,.price-footnote{font-size:12.5px;text-align:center;margin:12px 0 0}
.price-footnote{color:var(--se-text-caption)}
.price-action a{color:var(--accent-hover);font-weight:600;text-decoration:underline;
  text-underline-offset:2px;text-decoration-color:rgba(var(--accent-rgb),.4)}
.price-action a:hover{color:var(--accent)}
.tabpanel[hidden]{display:none}

/* ---------- Source-Connect tier table (.sctab-) ----------
   Sits beside the pricing rules on purpose: this table and .price-grid are the
   two places on the page where a reader compares Talent / Studio / Facility, and
   they have to agree. The table is CANON for every figure — the hero spec chips
   were retired so the numbers live in exactly one place.

   The wrapper scrolls, never the page. min-width is set on the TABLE, not the
   wrapper, so the columns keep their measure and the wrapper takes the overflow;
   a narrow phone gets a horizontal scroller instead of four crushed columns or a
   body that scrolls sideways. */
.sctab-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-md);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%)}
.sctab{width:100%;min-width:720px;border-collapse:collapse;
  font-family:var(--font-secondary);font-size:13.5px;line-height:1.55}
.sctab th,.sctab td{text-align:left;vertical-align:top;padding:14px 18px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16)}
.sctab thead th{font-size:11.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--accent);white-space:nowrap;
  background:rgba(var(--accent-rgb),.06)}
/* The row header is the question being asked; the cells are the three answers. */
.sctab tbody th{width:24%;font-weight:700;color:var(--se-text-white)}
.sctab td{color:var(--se-text-secondary);width:25.33%}
.sctab tbody tr:last-child th,.sctab tbody tr:last-child td{border-bottom:0}
/* The top edition, marked the way the reviewer marked it in the source table:
   brighter, not bigger. No second visual language for one column. */
.sctab .sctab-top{color:var(--se-text-white);font-weight:600;
  background:rgba(var(--accent-rgb),.045)}
.sctab thead th.sctab-top{background:rgba(var(--accent-rgb),.11)}
/* Mono is rationed to NUMBER DATA — the figures only, never the words around
   them, which is why these are spans inside the cell rather than a cell class. */
.sctab-fig{font-family:var(--font-mono);font-weight:600;color:var(--se-text-white);
  font-size:13px;letter-spacing:.01em}
.sctab tbody tr{transition:background .18s ease}
.sctab tbody tr:hover{background:rgba(var(--accent-rgb),.05)}
@media (prefers-reduced-motion:reduce){.sctab tbody tr{transition:none}}
/* Delight moment 2 ("the spec sheet performs itself", T9): .sctab is
   border-collapse:collapse above, and per the CSS Transforms spec transform
   does not apply to internal table rows on a collapsed table — the shared
   .mo-reveal primitive's translateY is architecturally inert on these <tr>s.
   Cancelled explicitly rather than left a silent no-op, so the row reveal is
   what it visibly is: opacity-only. Two classes beats the engine's one
   (.sctab tbody tr.mo-reveal = 0,2,2 vs html.mo-armed .mo-reveal = 0,2,1), so
   this wins the cascade without needing an html.mo-armed prefix. */
.sctab tbody tr.mo-reveal{transform:none}
@media (max-width:700px){
  .sctab th,.sctab td{padding:12px 14px}
}

/* ---------- Source-Live capability table (.sltab-) ----------
   The .sctab idiom directly above, minus the tiers. Source-Live is one product
   priced by the hours you stream, so there is nothing to compare ACROSS: a row
   is a capability and its single answer, not a question with three answers.

   Kept as its own family rather than a modifier on .sctab because the ONLY
   thing the two tables share is the frame; .sctab's whole geometry is the
   three-answer split (24% + 25.33% x3) and its .sctab-top column marking, and
   both are exactly what does not apply here. A modifier would have had to
   unset more than it set.

   Same wrapper law as .sctab: the WRAPPER scrolls, min-width sits on the
   TABLE, so a narrow phone gets a horizontal scroller rather than a body that
   scrolls sideways. */
.sltab-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-md);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%)}
.sltab{width:100%;min-width:520px;border-collapse:collapse;
  font-family:var(--font-secondary);font-size:13.5px;line-height:1.55}
.sltab th,.sltab td{text-align:left;vertical-align:top;padding:14px 18px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16)}
.sltab thead th{font-size:11.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--accent);white-space:nowrap;
  background:rgba(var(--accent-rgb),.06)}
.sltab tbody th{width:34%;font-weight:700;color:var(--se-text-white)}
.sltab td{color:var(--se-text-secondary)}
.sltab tbody tr:last-child th,.sltab tbody tr:last-child td{border-bottom:0}
/* Mono is rationed to NUMBER DATA — the figure only, never the words around
   it. Same reason .sctab-fig is a span inside the cell and not a cell class. */
.sltab-fig{font-family:var(--font-mono);font-weight:600;color:var(--se-text-white);
  font-size:13px;letter-spacing:.01em}
.sltab tbody tr{transition:background .18s ease}
.sltab tbody tr:hover{background:rgba(var(--accent-rgb),.05)}
@media (prefers-reduced-motion:reduce){.sltab tbody tr{transition:none}}
@media (max-width:700px){
  .sltab th,.sltab td{padding:12px 14px}
}

/* ---------- FAQ ---------- */
.faq{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:10px}
.faq details{
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.14);border-radius:var(--r-xl);
  overflow:hidden;transition:border-color var(--dur-fast) ease;
}
.faq details[open]{border-color:rgba(var(--accent-rgb),.4)}
.faq summary{
  cursor:pointer;list-style:none;display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:19px 22px;font-weight:700;font-size:15.5px;color:var(--se-text-white);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font-family:var(--font-mono);font-size:18px;color:var(--accent);transition:transform .2s ease;flex:none}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq .a{padding:0 22px 20px;font-size:14.5px;color:var(--se-text-dim);line-height:1.7;max-width:64ch}

/* ---------- Bands ---------- */
.band{
  background:linear-gradient(180deg,var(--se-inner),var(--se-frame));
  border-top:1px solid rgba(var(--se-border-teal-rgb),.12);
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.12);
}
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,64px);align-items:center}
.notch-list{list-style:none;display:flex;flex-direction:column;gap:13px;margin-top:22px}
.notch-list li{padding-left:26px;position:relative;color:var(--se-text-secondary);font-size:15px}
.notch-list li::before{content:"";position:absolute;left:0;top:8px;width:10px;height:10px;border-radius:2px;background:rgba(var(--accent-rgb),.2);border:1px solid var(--accent)}
.notch-list li b{color:var(--se-text-white)}
.notch-list.seq{counter-reset:step}
.notch-list.seq li{counter-increment:step;padding-left:38px}
.notch-list.seq li::before{
  content:counter(step,decimal-leading-zero);
  font-family:var(--font-mono);font-size:11px;font-weight:600;color:var(--accent);
  width:auto;height:auto;background:none;border:none;border-radius:0;
  top:3px;letter-spacing:.05em;
}

/* ---------- Signup / CTA ---------- */
.signup-form{display:flex;gap:12px;max-width:480px;margin:26px auto 14px}
.signup-form input{
  flex:1;background:var(--se-bg);border:1px solid rgba(var(--se-border-teal-rgb),.35);border-radius:var(--r-pill);
  padding:14px 22px;color:var(--se-text);font-family:var(--font-primary);font-size:15px;
  box-shadow:inset 0 2px 6px rgba(0,0,0,.25);
}
.signup-form input::placeholder{color:var(--se-a11y-muted)}
.signup-form input:focus-visible{outline:2px solid var(--se-focus);outline-offset:0;border-color:transparent}
.legal-line{font-size:12.5px;color:var(--se-a11y-muted)}
.legal-line a{color:var(--se-text-caption);text-decoration:underline;text-underline-offset:2px}
.legal-line a:hover{color:var(--se-text-secondary)}

/* ---------- Footer ---------- */
/* .footer-cta rule removed S1 2026-08-28: its only markup (the global closing-CTA band) was removed from index.html; the class is still referenced in shared multi-class selectors elsewhere in this file (harmless no-ops) and left alone. */
/* The chrome states its own typography rather than inheriting it. Four pages
   carry inline CSS written for their old standalone layout, and a `body` rule
   in there reaches the shared header and footer by inheritance: the podcasting
   page set body colour to #c0c5ca and the footer went grey; the Nexus landing
   page set body weight to 500 and every footer link thickened. Scoping the
   page rules to #main fixes the selectors that TARGET the chrome; only this
   fixes what merely INHERITS into it. */
.site-header,.site-footer{color:var(--se-text);font-weight:400;line-height:1.5}
.site-footer{background:var(--se-deep);border-top:1px solid rgba(var(--se-border-teal-rgb),.12);padding:60px 0 36px}
/* Brand block, then the five link columns as one flowing unit.
   REBUILT 2026-07-19 (reported: the footer does not look great in narrower windows — messy,
   unsymmetrical"). It used to be a 6-track grid that dropped straight to TWO tracks at
   ≤1020px, so every width from ~1020 down to ~600 paired a 4-link column with the 8-link
   Company column: a tall empty hole beside Support, and Legal orphaned alone on a third row.
   A row-based grid cannot pack blocks of 4/4/4/8/3 links tidily at any column count.
   Multi-column balances by HEIGHT instead, so the columns even out at every width and no
   block is left stranded. `break-inside:avoid` keeps each list whole. */
/* 2026-08-17: the brand is a BAND ABOVE the columns, not a track beside them.
   Measured before the change: the brand track was 266px wide holding a 201px
   mark, and 65px tall inside a 350px row — 285px of void under the logo, with
   the mark stranded in the corner of a tall empty column. Nothing else used
   that 1.6fr track.
   The footer is now four full-width bands — mark, links, blurb, bottom bar —
   each on the same measure, which is the symmetry that was missing. The links
   keep the whole width instead of 4.4fr of it. */
.footer-grid{display:block;margin-bottom:44px}
/* The mark and the blurb share ONE full-width row above the links. Separately
   they were two thin bands stacked on each other with the columns below; paired,
   the row states who this is and what they do in a single move, and the link
   columns get the whole width beneath it. The rule below it is what makes the
   row read as its own band rather than as a caption floating above the columns. */
.footer-brand{
  display:flex;align-items:center;gap:clamp(24px,4vw,56px);
  margin-bottom:34px;padding-bottom:30px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.1);
}
.footer-brand .logo{flex:none}
.footer-links{column-count:5;column-gap:32px}
.footer-col{break-inside:avoid;-webkit-column-break-inside:avoid;page-break-inside:avoid;padding-bottom:26px}
/* The brand column is the mark alone now — the blurb spans the full width
   beneath every column instead. Left-aligned, so it starts on the same line as
   the wrap and the link columns rather than floating in the middle of its own
   track. Kept at 65px (~201px wide): the size was chosen against the blurb, but
   it still reads as a proper mark rather than an icon. */
.footer-brand .logo img{height:65px}
/* Sits beside the mark and takes whatever width is left, so it sets to two or
   three long lines rather than the seven short ones it made at 34ch. No
   border-top any more — the row it belongs to carries the rule now. */
.footer-blurb{
  flex:1;min-width:0;margin:0;
  font-size:14.5px;color:var(--se-text-caption);line-height:1.7;
}
/* THE HIERARCHY WAS INVERTED. The heading sat at --se-a11y-muted (60% white,
   6.79:1) while its own links sat at --se-text-secondary (75%, 9.88:1) — the
   label was 3.09 DIMMER than the things it labelled, so nothing signalled where
   one group ended and the next began. The heading is now the brightest text in
   the column and the links step down, which is the order the eye expects.
   Weight also goes 500 -> 600: at 12px with 1.6px tracking, colour alone is a
   thin signal. */
.footer-col h4{font-family:var(--font-secondary);font-weight:600;font-size:12px;letter-spacing:1.6px;text-transform:uppercase;color:var(--se-text-white);margin-bottom:14px}
.footer-col ul{list-style:none;display:flex;flex-direction:column;gap:10px}
.footer-col a{color:var(--se-text-dim);font-size:14px;font-weight:400}
.footer-col a:hover{color:var(--se-text-white)}
.footer-bottom{border-top:1px solid rgba(var(--se-border-teal-rgb),.1);padding-top:26px;display:flex;align-items:center;gap:22px;flex-wrap:wrap}
.footer-bottom .copy{font-size:13px;color:var(--se-a11y-muted);margin-right:auto}
/* Legal lives in the BOTTOM BAR, not as a sixth column — Ross's Website
   Optimization doc, Part 3: "Bottom Bar: Copyright, Privacy Policy, Terms of
   Service". Moving it is also what frees the fifth column slot for Learn: six
   columns across this measure would be ~145px each and the longer labels
   ("Musicians & Composers") would start wrapping again. */
.legal-inline{display:flex;flex-wrap:wrap;gap:6px 18px;list-style:none;padding:0;margin:0}
.legal-inline a{font-size:13px;color:var(--se-a11y-muted)}
.legal-inline a:hover{color:var(--se-text-secondary)}

.socials{display:flex;gap:8px}
.socials a{
  width:36px;height:36px;border-radius:var(--r-md);display:grid;place-items:center;
  color:var(--se-text-caption);border:1px solid rgba(var(--se-border-teal-rgb),.2);
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease;
}
/* ALWAYS LIME — pairs with color:var(--se-primary) on this same line; accent-routing the
   border would mismatch the icon colour it sits around. Keep --se-primary-rgb. */
.socials a:hover{color:var(--se-primary);border-color:rgba(var(--se-primary-rgb),.5)}
.socials svg{width:16px;height:16px;fill:currentColor}

/* ---------- Reveal motion ---------- */
.reveal{opacity:0;transform:translateY(28px);transition:opacity .6s var(--ease-settle),transform .6s var(--ease-settle)}
.reveal.in{opacity:1;transform:none}
.reveal[data-d="1"]{transition-delay:.08s}
.reveal[data-d="2"]{transition-delay:.16s}
.reveal[data-d="3"]{transition-delay:.24s}
.reveal[data-d="4"]{transition-delay:.32s}
.reveal[data-d="5"]{transition-delay:.40s}

/* ---------- Motion engine (js/motion.js) ----------
   Sits beside .reveal above because it is the same job done under a stricter law. Where
   .reveal hides first and asks JS to un-hide, every rule here is gated behind html.mo-armed,
   which motion.js adds only at >=768px with prefers-reduced-motion unset. So the unarmed page —
   no JS, a phone, reduced motion, or a thrown error — matches NONE of this and renders at its
   final state. The initial DOM is the destination; motion is the only thing added. */
.mo-count{font-variant-numeric:tabular-nums}
html.mo-armed .mo-reveal{
  opacity:0;transform:translateY(14px);
  transition:opacity 600ms ease-out,transform 600ms ease-out;
  transition-delay:var(--mo-delay,0ms);
}
html.mo-armed .mo-reveal.mo-in{opacity:1;transform:none}
/* Geometry (dasharray/offset) is measured and set inline by motion.js; the timing is here so
   the two halves of a draw can be read in one place. */
html.mo-armed .mo-draw,html.mo-armed .mo-draw path,html.mo-armed .mo-draw line,
html.mo-armed .mo-draw polyline,html.mo-armed .mo-draw circle,html.mo-armed .mo-draw ellipse,
html.mo-armed .mo-draw rect{
  transition:stroke-dashoffset var(--mo-draw-dur,1400ms) ease-out;
}

/* ---------- Router pages ---------- */
.page{display:none}
.page.current{display:block}

/* ---------- Photography & perspective UI shots ---------- */
.showcase{display:grid;grid-template-columns:minmax(320px,420px) 1fr;gap:clamp(40px,6vw,88px);align-items:stretch}
.showcase.flip{grid-template-columns:1fr minmax(320px,420px)}
.showcase.flip .showcase-copy{order:2}
.showcase.flip .showcase-media{order:1}
.showcase-media{display:flex;align-items:stretch;justify-content:center}
/* The card's height matches the copy column's content height (via grid stretch + flex stretch);
   width is DERIVED from that height at 4:3, not the reverse — so it's exactly as tall as the copy. */
.ui-shot{position:relative;perspective:2200px;perspective-origin:36% 46%;max-width:100%}
.ui-shot::before{
  content:"";position:absolute;inset:-8% -12%;z-index:0;pointer-events:none;
  background:radial-gradient(closest-side,rgba(var(--accent-rgb),.16),transparent 72%);filter:blur(24px);
}
.ui-shot__frame{
  --tiltY:-19deg;--tiltX:7deg;--tiltZ:1.2deg;--glareAngle:115deg;
  position:relative;z-index:1;height:100%;border-radius:16px;
  transform:rotateY(var(--tiltY)) rotateX(var(--tiltX)) rotateZ(var(--tiltZ));
  transform-style:preserve-3d;
  transition:transform 1s var(--ease-settle),filter 1s var(--ease-settle);
  will-change:transform;
}
.ui-shot__frame.tracking{transition-duration:.12s}
.showcase.flip .ui-shot{perspective-origin:64% 46%}
.showcase.flip .ui-shot__frame{--tiltY:19deg;--tiltZ:-1.2deg}
.ui-shot__frame img{
  /* object-fit is NOT optional here. The frame is aspect-ratio:1/1 with no
     intrinsic shape of its own, so without this the default `fill` STRETCHES
     any non-square picture to a square — silently, no warning, no clue in the
     markup. Every image in these five slots is a square drawing today, so
     `cover` changes nothing now; it is here so the first real screenshot to
     land is cropped rather than distorted. Per-image framing overrides
     object-position inline. (2026-09-03, prerequisite for the image swap.) */
  display:block;height:100%;width:auto;aspect-ratio:1/1;max-width:100%;border-radius:14px;
  object-fit:cover;object-position:50% 50%;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);
  box-shadow:46px 54px 100px rgba(0,0,0,.6),8px 10px 24px rgba(0,0,0,.5),0 0 0 1px rgba(0,0,0,.5);
}
.showcase.flip .ui-shot__frame img{box-shadow:-46px 54px 100px rgba(0,0,0,.6),-8px 10px 24px rgba(0,0,0,.5),0 0 0 1px rgba(0,0,0,.5)}
.ui-shot__frame::after{ /* glare — angle tracks pointer position while .tracking is active */
  content:"";position:absolute;inset:0;border-radius:14px;pointer-events:none;
  background:linear-gradient(var(--glareAngle),rgba(255,255,255,.1),rgba(255,255,255,0) 42%);
}
.ui-shot__chip{
  position:absolute;right:-22px;bottom:12%;z-index:2;transform:translateZ(100px);
  background:var(--se-frame);border:1px solid rgba(var(--accent-rgb),.5);
  border-radius:10px;padding:11px 15px;display:flex;gap:10px;align-items:center;
  box-shadow:0 22px 44px rgba(0,0,0,.55);font-family:var(--font-mono);font-size:12px;font-weight:600;color:var(--accent);white-space:nowrap;
}
.showcase.flip .ui-shot__chip{right:auto;left:-22px}
.ui-shot__chip .status-dot{width:8px;height:8px}

/* ---------- Surround speaker map (Source-Connect, js/surround-map.js) ----------
   The inline SVG takes the <img>'s place in the ui-shot frame, so it wears the
   same square, border and shadow. Its colours are the page tokens: ear-level
   speakers filled with the accent, height speakers outlined in it, the LFE in
   the teal border colour because it has no direction to claim. */
.ui-shot__frame svg.sm-svg{
  display:block;width:100%;height:auto;aspect-ratio:1/1;border-radius:14px;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);
  box-shadow:46px 54px 100px rgba(0,0,0,.6),8px 10px 24px rgba(0,0,0,.5),0 0 0 1px rgba(0,0,0,.5);
  font-family:var(--font-secondary);
}
.sm-ground{fill:var(--se-frame)}
.sm-screen{stroke:rgba(255,255,255,.55);stroke-width:4;stroke-linecap:round}
.sm-front{fill:var(--se-text-caption);font-size:11px;font-weight:500;letter-spacing:.12em}
.sm-ring{fill:none;stroke:rgba(var(--se-border-teal-rgb),.24);stroke-width:1.5;stroke-dasharray:6 9}
.sm-ring--height{stroke:rgba(var(--se-border-teal-rgb),.18)}
.sm-listener{fill:rgba(255,255,255,.82)}
.sm-layer{transition:opacity .22s ease}
.sm-cap{fill:var(--se-text-secondary);font-size:13px;font-weight:500}
.sm-count{fill:var(--se-text-dim);font-family:var(--font-mono);font-size:12.5px;font-weight:500}
.sm-range{fill:none;stroke-linecap:round}
.sm-range--ear{stroke:rgba(var(--accent-rgb),.26);stroke-width:9}
.sm-range--height{stroke:rgba(var(--accent-rgb),.2);stroke-width:7}
.sm-spk text,.sm-lfe text,.sm-top text{font-size:13px;font-weight:600}
.sm-spk--ear circle{fill:var(--accent);stroke:var(--se-frame);stroke-width:2}
.sm-spk--ear text{fill:var(--accent-ink)}
.sm-spk--height circle{fill:var(--se-bg);stroke:var(--accent);stroke-width:2}
.sm-spk--height text{fill:var(--accent);font-size:12px}
.sm-top circle{fill:none;stroke:var(--accent);stroke-width:1.75;stroke-dasharray:4 4}
.sm-top .sm-top-tab{fill:var(--se-bg);stroke-dasharray:none}
.sm-top text{fill:var(--accent);font-size:12px}
.sm-lfe rect{fill:var(--se-bg);stroke:rgba(var(--se-border-teal-rgb),.7);stroke-width:1.5}
.sm-lfe text{fill:var(--se-text-secondary);font-size:12px}
.sm-legend text{fill:var(--se-text-dim);font-size:11.5px}
.sm-key--ear{fill:var(--accent)}
.sm-key--height{fill:none;stroke:var(--accent);stroke-width:1.75}
.sm-key--top{fill:none;stroke:var(--accent);stroke-width:1.5;stroke-dasharray:2.5 2.5}
.sm-key--lfe{fill:none;stroke:rgba(var(--se-border-teal-rgb),.7);stroke-width:1.5}
.sm-key--range{stroke:rgba(var(--accent-rgb),.32);stroke-width:7;stroke-linecap:round}
/* the format chips once the script has made them buttons */
button.chip{cursor:pointer;line-height:inherit;transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease,background-color var(--dur-fast) ease}
button.chip:hover{border-color:rgba(var(--accent-rgb),.55);color:var(--accent)}
button.chip[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
@media (prefers-reduced-motion:reduce){.sm-layer,button.chip{transition:none}}

/* Photographic frames (people / environments) */
.photo{position:relative;border-radius:var(--r-2xl);overflow:hidden;background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.16)}
.photo img{display:block;width:100%;height:100%;object-fit:cover}
.photo::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,transparent 45%,rgba(26,30,34,.5))}
.photo-tint img{filter:grayscale(.35) saturate(.9) contrast(1.04)}

/* Choose your craft — audience matrix (colleague notes). Cards are link-ready for the
   future sector landing pages. [data-accent="teal"] reuses the existing --se-border-teal
   token for the fourth card. Originally accent-hover/ink were left undefined ("no buttons
   inside cards") — extended 2026-07-19 for the Education & Facilities sector page, which
   DOES have buttons (hero CTA). Hover = base lightened ~30% toward white; ink = base
   darkened to ~11% brightness, hue preserved — same derivation pattern as nexus/live. */
.craft-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.craft{
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);border-radius:var(--r-xl);
  padding:22px 20px;display:flex;flex-direction:column;gap:10px;
  transition:transform var(--dur-slow) var(--ease-settle),border-color var(--dur-slow) ease;
}
/* THE WHOLE CARD IS THE LINK. Javier: "make photos clickable, ideally the
   entire craft area. too easy to lose where it can be clickable. make more
   obvious hover effect." Only the "Explore for…" line was a hit target.

   Done as a stretched link rather than by wrapping the card in <a>: one real
   anchor, so the heading, the paragraph and the image do not each become
   another tab stop reading out the same destination. The overlay sits under
   nothing — there is no other interactive element inside a craft card. */
.craft{position:relative;overflow:hidden}
/* overflow:hidden earns its place twice: it clips the hover zoom to the card's
   rounded corners, and .card-media already bleeds 20px past each edge by
   design (width:calc(100% + 40px)), so scaling it without clipping pushes the
   photo outside the border. */
.craft .guide-link::after{content:"";position:absolute;inset:0;border-radius:inherit;z-index:1}
.craft:hover{transform:translateY(-5px);border-color:rgba(var(--accent-rgb),.6);
  box-shadow:0 0 0 1px rgba(var(--accent-rgb),.28),0 18px 40px rgba(0,0,0,.42)}
.craft:hover .card-media{transform:scale(1.04)}
.craft .card-media{transition:transform .45s cubic-bezier(.2,.7,.3,1)}
.craft:hover .guide-link{color:var(--accent)}
/* the keyboard route has to show as clearly as the mouse one */
.craft:focus-within{border-color:rgba(var(--accent-rgb),.6)}
.craft .guide-link:focus-visible{outline:none}
.craft:focus-within{outline:2px solid var(--accent);outline-offset:3px}
@media (prefers-reduced-motion:reduce){
  .craft:hover{transform:none}
  .craft:hover .card-media{transform:none}
  .craft .card-media{transition:none}
}
.craft__icon{width:42px;height:42px;color:var(--accent);margin-bottom:2px}
.craft__icon svg{width:100%;height:100%;display:block}
.craft h3{font-size:15.5px;font-weight:700;color:var(--se-text-white);letter-spacing:-.01em}
.craft p{font-size:13px;color:var(--se-text-dim);line-height:1.55;margin:0}
.craft .guide-link{display:inline-block;font-size:12.5px;font-weight:600;margin-top:auto;padding-top:8px}
/* `.card-media`'s bleed is tuned to `.card`'s 26px/24px padding; `.craft` uses 22px/20px, so
   the offsets are retuned here rather than the component being duplicated. Bottom margin is 0
   because `.craft` is a flex column with its own `gap:10px` — a bottom margin would stack on
   top of that gap. `object-position` favours the upper third so faces survive the crop. */
.craft .card-media{--card-media-ar:4/3;width:calc(100% + 40px);margin:-22px -20px 0;object-position:center 28%}
/* ⚠️ ACCENT-COLOURED SMALL TEXT ON `.card` IS THE PROJECT'S TIGHTEST AA CASE.
   Measured 2026-07-19 (WCAG 2.x) against the .card gradient (--se-frame #31373E → --se-inner
   #2E343A). Worst measured `.guide-link` per accent, across every card that has one:
     lime  #C5E86C  9.02:1  — ample
     live  #F7B226  6.78:1  — ample
     teal  #7EA4B0  4.57:1  — TIGHT   (/support, /education)
     nexus #3DA5D9  4.52:1  — TIGHTEST (the Source-Nexus modules grid) — 0.02 of margin
   Teal is 4.48:1 on the gradient's TOP stop — i.e. BELOW the 4.5 floor — rising to 4.69:1 at
   the bottom; nexus behaves the same way. Everything passes today ONLY because every accent
   `.guide-link` sits low in its card, where the gradient has darkened. That is positional,
   not structural: move a 13px accent link toward the TOP of a card, or put one on the lighter
   --se-frame, and it silently fails AA. If you need accent text up there, use --accent-hover
   (teal #A5BFC8, nexus #6FC4EA) instead. On --se-bg all four accents clear comfortably. */
[data-accent="teal"]{--accent:var(--se-border-teal);--accent-hover:#A5BFC8;--accent-rgb:126,164,176;--accent-ink:#0E1213}

/* Two-universe product tabs (colleague notes; matches the ratified 2-branch catalog) */
.product-pane{align-items:center}
.product-pane h3{font-size:clamp(20px,2.2vw,26px);font-weight:800;color:var(--se-text-white);letter-spacing:-.015em;margin-bottom:10px}
.product-pane .pane-desc{font-size:14.5px;color:var(--se-text-dim);line-height:1.65}
.pane-viz{height:240px;margin-bottom:0}
.addon-strip{
  display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(24px,4vw,56px);align-items:center;
  margin-top:34px;padding:24px 26px;
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);border-radius:var(--r-xl);
}
.addon-strip h3{font-size:17px;font-weight:700;color:var(--se-text-white);margin-bottom:6px}
.addon-copy .addon-desc{font-size:13.5px;color:var(--se-text-dim);line-height:1.6;margin-bottom:16px}
.addon-viz{height:auto;margin:0;padding:14px 16px}
@media (max-width:860px){.addon-strip{grid-template-columns:1fr}}

/* Portrait chip inside credit cards */
.credit-head{display:flex;align-items:center;gap:13px}
.credit-portrait{width:52px;height:64px;border-radius:8px;object-fit:cover;flex:none;border:1px solid rgba(var(--se-border-teal-rgb),.28);background:var(--se-inner)}

/* Sector-page overflow (860-1150px), diagnosed 2026-07-19 on /audio-engineers +
   /musicians-composers (identical boundary on both: broken 861-1150px, clean at 1170px).
   TWO real, independent contributors — measured by isolating each (temporarily hiding it and
   re-checking scrollWidth), not assumed from a single "obvious" culprit (the same trap Phase 2
   already hit once with this exact chip/glow pair):
   1. .ui-shot::before's accent-glow bleed (inset:-8% -12%, defined below) is the DOMINANT one —
      isolating it alone accounted for the FULL measured overflow (72px at the worst point,
      861px). It's already clamped to inset:-8% 0 at ≤860px (Phase 2); this reuses that exact
      proven value for the gap the 860px block doesn't reach.
   2. .ui-shot__chip ALSO independently overflows here (its base rule bleeds right:-22px past
      the frame, safe only where .wrap's padding gives it room) — up to 23px at 861px, measured
      by isolating it before finding #1. Real but not binding once #1 is masked underneath it;
      fixed anyway since it's a genuine, separate overflow source.
   Both placed BEFORE the ≤860px block below so ITS OWN values (a bigger repositioning tied to
   the flattened/stacked mobile layout) still win there by source order — this block only fills
   the 861-1190px gap. */
@media (max-width:1190px){
  .ui-shot::before{inset:-8% 0}
  .ui-shot__chip{right:12px}
  .showcase.flip .ui-shot__chip{right:auto;left:12px}
}
@media (max-width:860px){
  .showcase,.showcase.flip{grid-template-columns:1fr;gap:44px;align-items:stretch}
  .showcase.flip .showcase-copy{order:1}
  .showcase.flip .showcase-media{order:2}
  /* Stacked layout: no sibling to match height against — fall back to width-driven sizing. */
  .ui-shot{max-width:none}
  /* Horizontal page overflow at narrow widths (measured 2026-07-17, Phase 2).
     The accent bloom is inset:-8% -12%, so it bleeds 12% of .ui-shot's width past each
     edge. Stacked, .ui-shot fills the wrap, whose padding (18px) is far less than that
     bleed (~41px at 380px) — so the bloom's BOX overhangs the viewport and shows up as
     document scrollWidth (404 vs 380 at 380px; ablating this ::before alone returned 0).
     Dropping only the horizontal bleed fixes it; filter:blur(24px) still feathers the glow
     outward as ink, which costs no layout. Vertical bleed is untouched. */
  .ui-shot::before{inset:-8% 0}
  .ui-shot__frame{height:auto}
  .ui-shot__frame,.showcase.flip .ui-shot__frame{transform:rotateY(0) rotateX(0) rotateZ(0)}
  .ui-shot__frame img{height:auto;width:100%;max-width:none}
  .ui-shot__chip{transform:translateZ(0);left:12px;right:auto;bottom:12px}
  .showcase.flip .ui-shot__chip{right:auto;left:12px}
  .craft-grid{grid-template-columns:repeat(2,1fr)}
}

/* ---------- Mini visualizations ---------- */
.mini-viz{height:118px;margin-bottom:22px;position:relative;overflow:hidden;padding:14px;transition:filter var(--dur-fast) var(--ease-settle)}
.card:hover .mini-viz{filter:brightness(1.12) saturate(1.15)}
.mini-viz canvas,.mini-viz svg{width:100%;height:100%}
.cable{fill:none;stroke-width:2;stroke-linecap:round;stroke-dasharray:6 8;animation:flow 1.6s linear infinite}
.card:hover .cable{animation-duration:.75s}
@keyframes flow{to{stroke-dashoffset:-28}}
.tc-panel{display:flex;flex-direction:column;gap:12px;justify-content:center;height:100%}
.tc-row{display:flex;align-items:center;justify-content:space-between;gap:12px;font-family:var(--font-mono);font-size:12px}
.tc-row .lbl{font-size:10px;letter-spacing:.14em;color:var(--se-a11y-muted)}
.tc-row .val{color:var(--se-text);font-weight:600;font-size:15px;letter-spacing:.06em}
.sync-lock{font-family:var(--font-mono);font-size:10px;letter-spacing:.16em;color:var(--se-selected);display:inline-flex;align-items:center;gap:7px}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .reveal{opacity:1;transform:none;transition:none}
  .cable,.status-dot.pulse{animation:none}
  *{transition-duration:.01ms!important}
}

/* ---------- Responsive ---------- */
/* Nav collapses to the hamburger earlier than the 860px breakpoints below, because the full
   nav simply needs more room than the header has. Kept as its own block so it doesn't touch
   the unrelated grid-3/split/panel-head rules that still switch at 860px.
   Why the value is where it is — it has moved twice, and both reasons still bind:
   - Originally 1060px, sized when the nav had three top-level triggers (Products, Sectors +
     plain links). `.nav-dd .dd-menu` is `position:absolute`, i.e. OUT of `.main-nav`'s flex
     layout, so the number of ENTRIES inside a dropdown can never change the bar's width —
     only a new top-level TRIGGER can. That was verified at 2, 3 and 4 Sectors entries.
   - RAISED TO 1140px. Adding the Pricing dropdown was exactly that predicted new trigger: it widened `.main-nav` from ~512px to **602px**. The header then needs
     logo 193 + nav 602 + actions 237 + two 10px gaps + 48px padding = **~1100px of content**.
     At 1060 the hamburger appeared correctly, but from ~1061 to ~1128 the nav was still shown
     with only 1046–1112px of content available, so the document scrolled horizontally by up
     to **66px**. Measured: 66px @1061 · 7px @1120 · 0 @1140.
   - THE RULE THAT MATTERS MORE THAN THE NUMBER: measuring only AT 1060 reports 0px overflow
     and looks correct, because the break sits in the band ABOVE it. **A breakpoint is a
     RANGE, not a boundary — sweep the width band on both sides, never just the edge.**
   - SEVENTH TRIGGER ADDED (Company), and this time the band was MEASURED, not
     reasoned about — `navband.py --floor` moves this breakpoint down to 820px
     so the desktop bar can be seen at narrow widths, and sweeps 830-1160.
     Result: the seven triggers need 663px and stop shrinking there, so the
     document begins scrolling sideways at 1040px and is clean from 1050 up.
     The floor is 1050; this breakpoint is 1140; the headroom is 90px. No move
     needed. Above 1150 the nav only GROWS (flex:1 fills the spare room) —
     squeeze and clipping measured 0 at every width to 1400.
     Note for whoever measures next: forcing `.main-nav{display:flex}` below
     the breakpoint does NOT show you the desktop bar. It shows the mobile
     panel with its dropdowns expanded, and reports a 4191px requirement.
   - RAISED AGAIN TO 1230px, for the EN|ES picker. It is not a nav trigger —
     it sits in .header-actions — but the arithmetic does not care WHICH block
     grew: the actions block went 194 -> ~284px and the floor moved 1050 ->
     1140. That put the floor exactly ON the old 1140 breakpoint, i.e. the nav
     was clean at 1141 by a single pixel. 1230 restores the same 90px of
     headroom the previous measurement had.
   If another top-level trigger is ever added, OR anything in .header-actions
   changes width, re-measure the whole band again (`python3 navband.py --floor`). */
@media (max-width:1230px){
  .nav-toggle{display:block}
  /* Controls belong together at the right edge: logo … [CTA] [☰]. The toggle
     sits straight after the logo in the DOM — correct for source order, and it
     precedes the panel it controls — but rendered there it reads as though it
     belongs to the wordmark, marooned mid-header while the CTA sits at the far
     edge. `order` moves the box without disturbing the source order.
     margin-left:auto lives HERE, not at a narrower breakpoint: the hamburger
     appears from 1140px down, and .main-nav (which normally pushes the actions
     right via flex:1) is out of flow the whole way. */
  .header-actions{margin-left:auto;order:2}
  .nav-toggle{order:3}
  /* Panel gutters are ZERO so each row's hover background can run edge to edge;
     the indent is moved onto the rows themselves, at exactly --hdr-gutter, so
     their text starts on the same line as the logo. It was 24px of panel
     padding PLUS 13px of item padding — text landing 21px inside the logo. */
  .main-nav{
    display:none;position:absolute;top:66px;left:0;right:0;
    background:var(--se-deep);border-bottom:1px solid rgba(var(--se-border-teal-rgb),.15);
    flex-direction:column;align-items:stretch;padding:16px 0 22px;gap:2px;
  }
  .main-nav > a,
  .main-nav > .nav-dd > summary{padding-left:var(--hdr-gutter);padding-right:var(--hdr-gutter)}
  .main-nav > .nav-dd .dd-menu{margin-left:var(--hdr-gutter);margin-right:var(--hdr-gutter)}
  /* The panel MUST cap its height and scroll. `.site-header` is `position:sticky` and this
     panel is `position:absolute` inside it, so the panel travels with the header — scrolling
     the page does NOT bring more of the menu into view. Without a cap, anything past the fold
     is simply unreachable: measured on a 390x560 viewport with Sectors expanded, the panel ran
     to 760px, i.e. 200px beyond the viewport, and the last items could not be reached at all.
     `dvh` first so mobile browser chrome is accounted for, with `vh` as the fallback. */
  .site-header.nav-open .main-nav{
    display:flex;
    max-height:calc(100vh - 66px);
    max-height:calc(100dvh - 66px);
    overflow-y:auto;overscroll-behavior:contain;
  }
  .nav-dd .dd-menu{position:static;margin-top:4px;box-shadow:none;border-width:1px;border-color:rgba(var(--se-border-teal-rgb),.2)}
}
@media (max-width:1020px){
  .hero .wrap{grid-template-columns:1fr}
  .grid-4{grid-template-columns:repeat(2,1fr)}
  /* Two columns means the four cards wrap onto two rows, so row-gap is once
     again separating CARDS rather than the parts inside them. */
  .price-grid--4{grid-template-columns:repeat(2,1fr);row-gap:24px}
  /* Brand goes full width and the links flow beneath it, still five across — at 1000px they
     fit comfortably, so collapsing to two columns here is premature.
     The brand block turns into a ROW here (logo left, blurb beside it). Stacked, its paragraph
     kept the 34ch measure it needs for readability at desktop, which left a wide void to its
     right — a lone narrow paragraph under a full-width band. Side by side, the row fills its
     width without the line ever getting long enough to hurt. */
  .footer-grid{grid-template-columns:1fr;gap:30px}
  .footer-brand .logo img{height:52px}
  #page-home .hero::after{background:linear-gradient(180deg,rgba(var(--se-bg-rgb),.55),rgba(var(--se-bg-rgb),.82))}
}
@media (max-width:860px){
  .grid-3{grid-template-columns:1fr}
  /* One column: there is no longer a row to align ACROSS, and holding the
     subgrid would make every card reserve the tallest card's empty rows. Back
     to a plain column, which is what the parts were designed to do anyway. */
  /* row-gap comes back here: stacked, each row IS a card, so 0 leaves them
     separated only by their 5px border. */
  .price-grid,.price-grid--4{grid-template-columns:1fr;grid-template-rows:none;row-gap:24px}
  .price-grid>.price-card{grid-row:auto;display:flex;flex-direction:column}
  .price-grid>.price-card>*{grid-row:auto}
  .price-grid>.price-card>ul{flex:1}
  .split{grid-template-columns:1fr}
  .btn-sm{min-height:44px}   /* phone-sized layouts — the verifiable half of the pair above */
  /* Straight from five to TWO — never three or four. With these block heights (4/4/4/8/3
     links) and DOM order fixed, three columns balance to 402/201/514: one column nearly
     empty beside one overfull. Two fills evenly and orphans nothing. Measured, not assumed. */
  .footer-links{column-count:2}
  /* Panel chrome must never overflow its frame */
  .panel-head{flex-wrap:wrap;gap:8px 10px}
}
@media (max-width:600px){
  /* Left-aligned, NOT centred. Centring was the right answer for ONE column,
     where nothing gave the left edge a reference. With two columns it is the
     wrong one: each column centres on its own axis, so the two ragged edges
     face each other across the gutter. Measured left-aligned: headings and
     links share exactly two axes, x=18 and x=204, and nothing else.
     The bottom bar still wraps at this width, but flows from the left. */
  .footer-bottom{flex-wrap:wrap;gap:14px 20px}
  .footer-bottom .copy{margin-right:0;flex:1 1 100%}
  /* Stacked, because at this width the blurb beside a 161px mark would be a
     column of ~4-word lines.
     The MARK is the one thing here that centres, and it is scaled to fill.
     Left at 161px it sat 45% across a 354px column and read as an orphan
     rather than as a brand; at 96px tall it is ~296px, 84% of the measure, and
     centring balances the small margin left over. Everything else — blurb,
     columns, bottom bar — stays on the left edge, because those are things you
     read down and the mark is not. 296px from a 534px source: no upscaling. */
  /* The mark sits in its own band, so the air above and below it should match.
     Measured before: 61px above (the footer's 60px top padding) against 18px
     below — the mark floated high and pressed onto the blurb. Trimming the
     footer's top padding and opening the gap under the mark brings the two to
     ~44/38, which reads as centred in the space. Horizontal centring was
     already exact: 20px each side at 372px wide. */
  .site-footer{padding-top:44px}
  .footer-brand{display:block;padding-bottom:24px;margin-bottom:26px}
  .footer-brand .logo{justify-content:center}
  .footer-brand .logo img{height:96px}
  .footer-brand .footer-blurb{margin-top:38px}
  /* ONE column on a phone. Two columns of multi-column flow balance by HEIGHT,
     so the five headings land at five unrelated vertical positions — measured at
     390px: Products 210, Company 210, Solutions 448, Legal 560, Support 649.
     Balanced, but with no horizontal rhythm at all, which is what reads as
     messy. A row grid is NOT the alternative — it was tried and reverted on
     2026-07-19 because 4/4/4/8/3-link blocks leave holes and orphan Legal (see
     the note above .footer-grid). One column has neither problem: every heading
     aligns, nothing is stranded, and it costs only height. */
  /* TWO COLUMNS AS A ROW GRID, not multi-column flow. Multi-column balances by
     HEIGHT, which is what put the five headings at five unrelated vertical
     positions. A grid puts them in rows, so each pair starts on the same line.
     The 2026-07-19 note rejecting a row grid was measured against counts of
     4/4/4/8/3 — the 8-item Company column was what could not pair. The set is
     now 5/5/3/4/5 and it pairs cleanly.
     Learn is ordered LAST so the one unavoidable empty cell (5 groups into 2
     columns) is the smallest one, sitting bottom-right as white space rather
     than as a hole beside a tall column. */
  .footer-links{column-count:auto;display:grid;grid-template-columns:repeat(2,1fr);
    gap:28px 18px;align-items:start}
  .footer-col{padding-bottom:0}
  .footer-col:nth-child(3){order:5}
  .grid-2,.grid-4{grid-template-columns:1fr}
  .signup-form{flex-direction:column}
  .header-actions .login{display:none}
  .price-line .amt{font-size:36px}
  .header-in{gap:12px}
  .section-head .sub,.lede{font-size:16px}
  /* Timecode rows stack cleanly instead of colliding */
  .tc-row{flex-wrap:wrap;gap:2px 10px}
  .tc-row .lbl{flex-basis:100%}
  /* Meter panels: keep readouts from crowding */
  .session-readout{gap:6px}
}
@media (max-width:400px){
  .wrap{padding:0 18px}
  .header-in{--hdr-gutter:16px;gap:10px}
  .logo{font-size:12px;letter-spacing:1.4px;gap:8px}
  .logo svg{width:19px}
  /* Keeps the tighter horizontal padding a 390px header needs, but not at the cost of the
     target height — this is the site's primary conversion button and it measured 34.5px. */
  .header-actions .btn-sm{padding:10px 14px;font-size:12.5px;min-height:44px}
  h1.display{font-size:clamp(32px,10vw,40px)}
  .panel-head .dim:not(:last-child){display:none} /* drop secondary readouts on tiny screens */
}

/* ---------- Session Line — two people + the shared UI ---------- */
.session-line{position:relative;display:grid;grid-template-columns:1fr 1.35fr 1fr;align-items:center;margin-top:34px}
.sl-link{position:absolute;top:50%;left:8%;right:8%;height:2px;transform:translateY(-50%);z-index:3;
  background:linear-gradient(90deg,transparent,rgba(var(--accent-rgb),.65) 18%,rgba(var(--accent-rgb),.65) 82%,transparent)}
.sl-link::before,.sl-link::after{content:"";position:absolute;top:50%;width:9px;height:9px;border-radius:50%;
  background:var(--accent);transform:translateY(-50%);box-shadow:0 0 0 5px rgba(var(--accent-rgb),.16)}
.sl-link::before{left:0}
.sl-link::after{right:0}
.sl-pulse{position:absolute;top:50%;left:0;width:10px;height:10px;border-radius:50%;transform:translate(-50%,-50%);
  background:var(--accent);box-shadow:0 0 12px 3px rgba(var(--accent-rgb),.7);animation:sl-travel 3.2s var(--ease-settle) infinite}
@keyframes sl-travel{0%{left:0;opacity:0}12%{opacity:1}88%{opacity:1}100%{left:100%;opacity:0}}
.sl-person{position:relative;margin:0;height:340px;border-radius:14px;overflow:hidden;z-index:2;
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.16)}
.sl-person--l{transform:translateX(18px)}
.sl-person--r{transform:translateX(-18px)}
.sl-person img{display:block;width:100%;height:100%;object-fit:cover;filter:grayscale(1) contrast(1.05)}
.sl-person::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 46%,rgba(10,10,10,.74))}
.sl-role{position:absolute;top:13px;left:14px;z-index:3;font-family:var(--font-secondary);
  font-size:10px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  background:rgba(10,10,10,.5);border:1px solid rgba(var(--accent-rgb),.4);border-radius:20px;padding:4px 11px}
.sl-cap{position:absolute;left:15px;bottom:13px;z-index:3}
.sl-cap b{display:block;font-size:15px;color:var(--se-text-white);letter-spacing:-.01em;line-height:1.25}
.sl-cap span{font-family:var(--font-secondary);font-size:10.5px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:rgba(255,255,255,.86)}
.sl-stage{position:relative;z-index:4;padding:0 6px}
/* The centre stage sits at z-index:4 over the people (z-index:2) and the right-hand figure
   is pulled under it by `translateX(-18px)`. The right caption is anchored at the figure's
   LEFT edge — i.e. exactly the strip the stage covers — so its first characters can be
   painted over — the caption loses its opening characters entirely.
   Fix: anchor the RIGHT figure's caption to its right edge, so both captions sit on the
   OUTSIDE of the composition and neither can collide with the stage.
   When re-checking this: `getBoundingClientRect` does NOT reveal it (the layout
   boxes clear each other by a couple of px) — judge it from a rendered screenshot, and only
   on a fully loaded page: measuring while images are mid-reload collapses the shot's height
   and produces bogus overlap numbers. */
.sl-person--r .sl-cap{left:auto;right:15px;text-align:right}
.sl-footer{margin-top:34px}
.sl-footer .chip-row{justify-content:center;margin-bottom:24px}
@media (max-width:860px){
  .session-line{grid-template-columns:1fr;gap:26px;max-width:440px;margin-inline:auto}
  .sl-person--l,.sl-person--r{transform:none}
  .sl-link{display:none}
  .sl-stage{padding:0}
  /* Stacked here, so nothing overlaps the right figure's caption — put it back on the left
     to match its sibling. The outer-alignment above exists only to dodge the centre stage,
     which does not exist in this single-column layout. */
  .sl-person--r .sl-cap{left:15px;right:auto;text-align:left}
}
@media (prefers-reduced-motion:reduce){ .sl-pulse{display:none} }

/* Sector-page hero portrait — shared by EVERY sector page's hero (Engineers,
   and Musicians/VO/Education as they ship), not page-scoped. The Session
   Line's base .sl-person is 340px, sized for its 3-across homepage row; a
   single full-height hero portrait needs the taller column. Scoped by
   ANCESTOR (.hero), not by page id, specifically so future sector pages
   reuse this for free — do not copy this into a new #page-xxx selector. */
.hero .sl-person{height:520px}

/* ================================================================
   HOW-TO LIBRARY (#/how-to)
   A redesign of the live KB's how-to index. The whole page is a finder,
   so the visual system is deliberately DENSER and more tabular than any
   marketing page here — data, not narrative. It shares Support's teal
   accent (it is a child of Support) but shares none of its composition,
   a colour change cannot differentiate two pages built the same way.
================================================================ */

/* Screen-reader-only. The site had no such utility until this page needed
   one for the matrix's cell labels ("Send" alone is meaningless out of
   its row/column context) and its <caption>. Standard clip-rect recipe. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* --- Finder hero. Single column: the search field is the subject, and a
       second column beside it would compete with the thing you must type in. */
.hero-howto{padding:clamp(44px,5vw,64px) 0 clamp(34px,4vw,48px)}
/* Two columns, but NOT the marketing hero's 1.05/.95 — the finder column is
   the subject and the contents panel is the counterweight. The eyebrow spans
   both so the breadcrumb reads across the top rather than crowding the H1. */
.hero-howto .wrap{grid-template-columns:1.02fr .98fr;align-items:start;
  gap:0 clamp(32px,4vw,60px)}
/* Row rhythm is set by margins, NOT grid row-gap. Measured before this change:
   a 44px row-gap stacked on the lede's own 22/34px margins and the search's
   26px, so the field that IS this page's primary control sat 105px adrift of
   the text explaining it. Grid gap is uniform; this rhythm is not. */
.hero-howto .eyebrow{grid-column:1/-1;margin-bottom:22px}
.hero-howto .display{font-size:clamp(32px,4vw,48px);max-width:15ch;grid-column:1;margin:0}
.hero-howto .lede{max-width:52ch;grid-column:1;margin:20px 0 0}
.hero-howto .ht-search{grid-column:1;margin-top:32px}
.hero-howto .ht-toc{grid-column:2;grid-row:2/span 3}

/* 2026-08-30, task T1 — the library moved to #/support, where it is a SECTION,
   not a hero, so the two rules above no longer reach it. This is the same
   relationship in the section's own vocabulary: the search field is the
   subject, the contents panel is the counterweight. Same 1.02/.98 split, same
   1020px collapse point, measured the same way. */
.ht-lib-head{display:grid;grid-template-columns:1.02fr .98fr;
  gap:0 clamp(32px,4vw,60px);align-items:start}
.ht-lib-head .ht-search{margin-top:0;max-width:none}

/* Contents panel — deliberately built on .docs-index's vocabulary (same border,
   same gradient, same row rhythm) so Support and its child page read as one
   family, then diverges where its job differs: it carries a count per row. */
.ht-toc{border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  padding:8px 0;overflow:hidden}
.ht-toc .section-label{padding:14px 22px 10px;margin:0}
.ht-toc button{display:flex;width:100%;box-sizing:border-box;justify-content:space-between;
  align-items:center;gap:16px;text-align:left;padding:14px 22px;background:none;border:0;
  border-top:1px solid rgba(var(--se-border-teal-rgb),.12);cursor:pointer;
  transition:background var(--dur-fast) ease}
.ht-toc button:hover{background:rgba(var(--accent-rgb),.07)}
.ht-toc button:focus-visible{outline:2px solid var(--se-focus);outline-offset:-2px}
.ht-toc span{display:block;font-family:var(--font-secondary);font-size:12.5px;line-height:1.5;
  color:var(--se-text-dim)}
.ht-toc b{display:block;font-size:14px;font-weight:600;color:var(--se-text-white);margin-bottom:3px}
/* Article counts are measured NUMBER DATA — mono is correct here. */
.ht-toc em{flex:none;font-family:var(--font-mono);font-style:normal;font-size:16px;
  font-weight:500;color:var(--accent)}
.hero-howto .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-howto .eyebrow a:hover{color:var(--accent)}

.ht-search{margin-top:26px;max-width:560px}
.ht-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.ht-search input::placeholder{color:var(--se-text-caption)}
.ht-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
/* Count is measured NUMBER DATA — the one place mono is legal here. */
.ht-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

/* --- The timecode matrix. The reason this page exists. --- */
.ht-matrix-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%)}
.ht-matrix{width:100%;min-width:640px;border-collapse:collapse;text-align:left}
.ht-matrix th,.ht-matrix td{padding:0;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.12)}
.ht-matrix tbody tr:last-child th,.ht-matrix tbody tr:last-child td{border-bottom:0}
.ht-matrix thead th{padding:16px 18px 13px;font-family:var(--font-secondary);
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--se-text-secondary);vertical-align:bottom;white-space:nowrap}
.ht-matrix thead th span{display:block;margin-top:5px;font-size:10.5px;font-weight:600;
  letter-spacing:.06em;text-transform:none;color:var(--se-text-caption)}
/* The second column of each pair carries no repeated header text of its own —
   the visual pairing comes from the divider, so MTC/LTC reads as one span. */
.ht-matrix thead th.ht-col2{color:transparent}
.ht-matrix thead th.ht-col2 span{color:transparent}
.ht-matrix thead th:nth-child(4),.ht-matrix tbody td:nth-child(4){
  border-left:1px solid rgba(var(--se-border-teal-rgb),.2)}
.ht-matrix tbody th{padding:0 18px;font-family:var(--font-secondary);font-size:14.5px;
  font-weight:600;color:var(--se-text-white);white-space:nowrap}
.ht-matrix tbody a{display:block;padding:15px 18px;font-family:var(--font-secondary);
  font-size:13.5px;font-weight:600;color:var(--se-text-secondary);
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease}
.ht-matrix tbody a::after{content:" →";opacity:.5}
.ht-matrix tbody a:hover{background:rgba(var(--accent-rgb),.09);color:var(--se-text-white)}
.ht-matrix tbody a:hover::after{opacity:1;color:var(--accent)}
.ht-swipe{margin:12px 2px 0;font-family:var(--font-secondary);font-size:12.5px;
  font-weight:600;letter-spacing:.02em;color:var(--accent)}
.ht-foot{margin-top:20px;font-family:var(--font-secondary);font-size:14px;color:var(--se-text-dim)}
.ht-foot a{color:var(--accent);font-weight:600}
.ht-foot a:hover{color:var(--accent-hover)}

/* --- The four chip pickers --- */
/* align-items:start, not the grid default stretch: the four questions have 5
   or 6 chips each and wrap to different heights, so stretching left ~40px of
   dead space under the shorter card's chips. Each card hugs its own content. */
.ht-pickers{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;align-items:start}
.ht-picker{border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:var(--se-frame);padding:24px 22px}
.ht-picker h3{font-size:18px;line-height:1.3;margin:0 0 8px}
.ht-picker p{font-family:var(--font-secondary);font-size:14px;color:var(--se-text-dim);
  margin:0 0 16px;max-width:46ch}
.ht-chips{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
/* 2.5.8: 40px tall x >=44px wide with 8px spacing on all sides — clears the
   24px minimum outright, and meets the 44px touch convention on the long axis. */
.ht-chips a{display:flex;align-items:center;min-height:40px;padding:0 16px;
  font-family:var(--font-secondary);font-size:13.5px;font-weight:600;
  color:var(--se-text-secondary);background:var(--se-inner);
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-pill);
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease,border-color var(--dur-fast) ease}
.ht-chips a:hover{background:rgba(var(--accent-rgb),.12);border-color:var(--accent);
  color:var(--se-text-white)}

/* --- The remainder, by product --- */
.ht-groups{column-count:2;column-gap:32px}
.ht-group{break-inside:avoid;margin-bottom:34px}
.ht-group-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  margin:0 0 12px;padding-bottom:10px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
.ht-count{font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-caption)}
.ht-list{list-style:none;margin:0;padding:0}
/* NOT flex. As a flex row the host chip became its own line item whenever the
   title wrapped, and an orphaned "Ableton" on its own line reads as a separate
   entry rather than a qualifier. Inline-block trails the last word instead. */
.ht-list li{padding:7px 0}
.ht-list a{font-family:var(--font-secondary);font-size:14.5px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.ht-list a:hover{color:var(--accent)}
/* The repeated "How to" opener, de-emphasised but present verbatim in the DOM.
   This is the single biggest scanning win on the page: 84 titles that all
   began with the same two words now begin with the distinguishing one. */
.ht-pre{color:var(--se-text-caption);font-weight:400}
.ht-host{display:inline-block;margin-left:8px;font-family:var(--font-secondary);
  font-size:11px;font-weight:600;letter-spacing:.04em;color:var(--se-text-caption);
  white-space:nowrap;vertical-align:1px;
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-sm);padding:1px 7px}
.ht-empty{margin-top:8px;font-family:var(--font-secondary);font-size:15px;color:var(--se-text-dim)}
.ht-empty .btn{margin:0 4px;padding:8px 16px;font-size:13.5px;vertical-align:middle}
.ht-empty a{color:var(--accent);font-weight:600}
/* Badge on the Support quick-link that now points here rather than off-site. */
.ht-badge{flex:none;font-family:var(--font-secondary);font-size:10.5px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;color:var(--accent-ink);
  background:var(--accent);border-radius:var(--r-sm);padding:2px 7px}

@media (max-width:900px){
  .ht-pickers{grid-template-columns:1fr}
  .ht-groups{column-count:1}
}
/* The two-column hero collapses BEFORE the pickers do: the contents panel needs
   ~360px to keep its label and count on one line, and the search field wants
   more than half of a 1020px wrap. Measured, not guessed. */
@media (max-width:1020px){
  .hero-howto .wrap{grid-template-columns:1fr}
  .hero-howto .display,.hero-howto .lede,.hero-howto .ht-search,.hero-howto .ht-toc{grid-column:1}
  .hero-howto .ht-toc{grid-row:auto;margin-top:6px}
  .hero-howto .ht-search{max-width:none}
  .ht-lib-head{grid-template-columns:1fr;gap:6px 0}
}
@media (max-width:640px){
  .ht-matrix{min-width:560px}
  .hero-howto .display{max-width:none}
}

/* ================================================================
   SOURCE ELEMENTS WORKFLOWS (#/how-to)
   Sits right under the how-to library family because it is the same
   building: the library moved to Support (task T1) and this page took
   its route. It keeps Support's teal, and it keeps the library's search
   vocabulary — .wf-search reuses .ht-search's field metrics — but the
   composition is marketing, not tabular: 16 long-form guides that open
   in place, filtered by nine product/role pills.
================================================================ */

/* Single column. The old finder hero paired the H1 with a search field;
   the search now belongs to the guides section, so the hero is a plain
   statement and the lede is allowed its full measure. */
.hero-wf{padding:clamp(52px,6vw,80px) 0 clamp(34px,4vw,48px)}
.hero-wf .wrap{grid-template-columns:1fr;align-items:start;gap:0}
.hero-wf .display{font-size:clamp(32px,4.2vw,52px);max-width:20ch;margin:0}
.hero-wf .lede{max-width:64ch;margin:20px 0 0}
.hero-wf .eyebrow{margin-bottom:22px}
.hero-wf .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px}
.hero-wf .eyebrow a:hover{color:var(--accent)}

/* --- Find bar: one field, nine pills, one live count --- */
.wf-find{margin-bottom:clamp(28px,4vw,40px)}
/* position:relative anchors the suggestion list to the FIELD, not the section — the
   list has to overlay the pills below it rather than shove them down as you type. */
.wf-search{position:relative;max-width:640px}
.wf-search input{width:100%;box-sizing:border-box;padding:15px 92px 15px 18px;
  font-family:var(--font-secondary);font-size:15px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-pill);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.wf-search input::placeholder{color:var(--se-text-caption)}
.wf-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.16)}
.wf-clear{position:absolute;top:50%;right:10px;transform:translateY(-50%);
  font-family:var(--font-secondary);font-size:12.5px;font-weight:600;
  color:var(--se-text-secondary);background:var(--se-frame);
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-pill);
  padding:7px 14px;cursor:pointer}
.wf-clear:hover{color:var(--se-text-white);border-color:var(--accent)}

/* The typeahead. Absolute so it never reflows the grid underneath it. */
.wf-suggest{position:absolute;z-index:6;top:calc(100% + 8px);left:0;right:0;
  list-style:none;margin:0;padding:6px;max-height:320px;overflow-y:auto;
  background:var(--se-frame);border:1px solid rgba(var(--se-border-teal-rgb),.3);
  border-radius:var(--r-xl);box-shadow:0 18px 44px rgba(0,0,0,.45)}
.wf-suggest li{margin:0}
.wf-suggest button{display:block;width:100%;box-sizing:border-box;text-align:left;
  padding:11px 14px;border:0;border-radius:var(--r-md);background:transparent;cursor:pointer;
  font-family:var(--font-secondary);font-size:14px;line-height:1.45;color:var(--se-text-secondary)}
.wf-suggest button b{display:block;font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--se-text-caption);margin-bottom:3px}
.wf-suggest button:hover,.wf-suggest button:focus-visible,.wf-suggest .wf-on button{
  background:rgba(var(--accent-rgb),.12);color:var(--se-text-white);outline:none}

/* Pills. Same 40px/44px touch metrics as .ht-chips — this page inherits that
   decision rather than re-deciding it, so the two rooms feel like one building. */
.wf-pills{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}
.wf-pill{display:flex;align-items:center;min-height:40px;padding:0 16px;
  font-family:var(--font-secondary);font-size:13.5px;font-weight:600;cursor:pointer;
  color:var(--se-text-secondary);background:var(--se-inner);
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-pill);
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease,border-color var(--dur-fast) ease}
.wf-pill:hover{background:rgba(var(--accent-rgb),.12);border-color:var(--accent);color:var(--se-text-white)}
.wf-pill[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}

/* --- The 16 guides --- */
/* One column, not a card grid: every card is a full article once opened, and a
   two-up grid would make an open card shove its neighbour down the page. */
.wf-grid{display:flex;flex-direction:column;gap:12px}
.wf-card[hidden]{display:none}
.wf-guide{border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:var(--se-frame);overflow:hidden}
.wf-guide[open]{border-color:rgba(var(--accent-rgb),.42)}
.wf-guide summary{display:block;position:relative;padding:22px 66px 22px 24px;cursor:pointer;
  list-style:none}
.wf-guide summary::-webkit-details-marker{display:none}
.wf-guide summary:focus-visible{outline:2px solid var(--se-focus);outline-offset:-2px}
.wf-guide summary::after{content:"+";position:absolute;top:24px;right:24px;
  font-family:var(--font-mono);font-size:20px;line-height:1;color:var(--accent);
  transition:transform var(--dur-fast) ease}
.wf-guide[open] summary::after{transform:rotate(45deg)}
.wf-guide summary:hover{background:rgba(var(--accent-rgb),.05)}
.wf-kicker{display:block;font-family:var(--font-secondary);font-size:11px;font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--accent);margin-bottom:8px}
.wf-title{display:block;font-size:19px;font-weight:700;line-height:1.32;
  color:var(--se-text-white);max-width:56ch}
.wf-dek{display:block;margin-top:9px;font-family:var(--font-secondary);font-size:14.5px;
  line-height:1.6;color:var(--se-text-dim);max-width:74ch}
.wf-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:14px}
.wf-tags em{font-family:var(--font-secondary);font-size:10.5px;font-style:normal;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;color:var(--se-text-caption);
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-sm);padding:3px 8px}
.wf-tags .wf-prod{color:var(--accent);border-color:rgba(var(--accent-rgb),.4)}

/* The article itself. Measure is capped at 78ch — these are long technical
   walkthroughs and a full-bleed line length is unreadable at 1200px. */
.wf-body{padding:4px 24px 26px;border-top:1px solid rgba(var(--se-border-teal-rgb),.14);
  margin-top:2px}
.wf-body p,.wf-body li{font-family:var(--font-secondary);font-size:14.5px;line-height:1.72;
  color:var(--se-text-dim);max-width:78ch}
.wf-body p{margin:16px 0 0}
.wf-body b{color:var(--se-text-secondary);font-weight:700}
.wf-body a{color:var(--accent);font-weight:600}
.wf-body a:hover{color:var(--accent-hover)}
.wf-body h4{margin:26px 0 0;font-size:15px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--accent)}
.wf-body h5{margin:22px 0 0;font-size:15.5px;font-weight:700;color:var(--se-text-white);
  letter-spacing:0;text-transform:none}
.wf-body ul,.wf-body ol{margin:12px 0 0;padding-left:22px}
.wf-body li{margin:8px 0}
.wf-body ul{list-style:disc}
/* The export's "○" sub-bullets keep their own indent rather than being folded into
   the parent line — two of the sixteen guides branch a step into named options. */
.wf-body .wf-sub{margin:6px 0 0;padding-left:20px;list-style:circle}
.wf-body .wf-sub li{margin:5px 0;font-size:14px}
.wf-body ol{list-style:decimal}
.wf-body li::marker{color:var(--se-text-caption)}

/* --- Video tutorials. House cards: no embed, no remote thumbnail. --- */
.wf-videos{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.wf-video{display:flex;flex-direction:column;padding:26px 24px 24px;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:var(--se-frame);transition:border-color var(--dur-fast) ease,transform var(--dur-fast) ease}
.wf-video:hover{border-color:var(--accent);transform:translateY(-2px)}
.wf-play{display:flex;align-items:center;justify-content:center;width:46px;height:46px;
  border-radius:50%;background:rgba(var(--accent-rgb),.14);
  border:1px solid rgba(var(--accent-rgb),.42);margin-bottom:18px}
.wf-play svg{fill:var(--accent);margin-left:2px}
.wf-vtitle{display:block;font-size:18px;font-weight:700;line-height:1.3;color:var(--se-text-white)}
.wf-vsub{display:block;margin-top:9px;font-family:var(--font-secondary);font-size:14px;
  line-height:1.6;color:var(--se-text-dim);flex:1}
.wf-vgo{display:block;margin-top:18px;font-family:var(--font-secondary);font-size:13.5px;
  font-weight:600;color:var(--accent)}

@media (max-width:900px){
  .wf-videos{grid-template-columns:1fr}
}
@media (max-width:640px){
  .wf-guide summary{padding:20px 52px 20px 18px}
  .wf-guide summary::after{top:21px;right:18px}
  .wf-body{padding:4px 18px 22px}
  /* The placeholder is a long example string; a phone shows the first few words
     and the pills are the real controls at this width. */
  .wf-search input{padding-right:82px;font-size:14.5px}
}

/* ================================================================
   ERROR MESSAGE REPOSITORY (#/error-codes)
   Denser again than the how-to library, because this page is a lookup
   table with a story on top rather than a browse. Shares Support's teal
   and the how-to page's search/list vocabulary — it is the third room in
   the same building, not a fourth design language.
================================================================ */

.hero-codes{padding:clamp(44px,5vw,64px) 0 clamp(34px,4vw,48px)}
.hero-codes .wrap{grid-template-columns:1.02fr .98fr;align-items:start;gap:0 clamp(32px,4vw,60px)}
.hero-codes .eyebrow{grid-column:1/-1;margin-bottom:22px}
.hero-codes .display{font-size:clamp(32px,4vw,48px);max-width:15ch;margin:0;grid-column:1}
.hero-codes .lede{max-width:52ch;margin:20px 0 0;grid-column:1}
.hero-codes .ec-search{grid-column:1}
.hero-codes .ec-figures{grid-column:2;grid-row:2/span 3}

/* Figures panel. The count leads and is set in mono — these are measured
   figures, which is exactly what mono is reserved for on this site. */
.ec-figures{border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%);
  padding:6px 0;overflow:hidden}
.ec-figures button{display:flex;width:100%;box-sizing:border-box;align-items:baseline;gap:18px;
  text-align:left;padding:18px 22px;background:none;border:0;cursor:pointer;
  border-top:1px solid rgba(var(--se-border-teal-rgb),.12);
  transition:background var(--dur-fast) ease}
.ec-figures button:first-child{border-top:0}
.ec-figures button:hover{background:rgba(var(--accent-rgb),.07)}
.ec-figures button:focus-visible{outline:2px solid var(--se-focus);outline-offset:-2px}
/* Right-aligned so 6, 118 and 173 share a decimal edge — left-aligned, the
   single-digit row visibly broke the column. */
.ec-figures em{flex:none;min-width:58px;text-align:right;font-family:var(--font-mono);
  font-style:normal;font-size:26px;font-weight:500;line-height:1;color:var(--accent)}
.ec-figures span{display:block;font-family:var(--font-secondary);font-size:12.5px;line-height:1.5;
  color:var(--se-text-dim)}
.ec-figures b{display:block;font-size:14px;font-weight:600;color:var(--se-text-white);margin-bottom:3px}
.hero-codes .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-codes .eyebrow a:hover{color:var(--accent)}
.ec-search{margin-top:32px;max-width:560px}
.ec-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.ec-search input::placeholder{color:var(--se-text-caption)}
.ec-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
.ec-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

/* --- Band map --- */
.ec-map-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%)}
.ec-map{width:100%;min-width:600px;border-collapse:collapse;text-align:left}
.ec-map th,.ec-map td{padding:13px 18px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.12);
  font-family:var(--font-secondary);font-size:13.5px;vertical-align:middle}
.ec-map tbody tr:last-child th,.ec-map tbody tr:last-child td{border-bottom:0}
.ec-map thead th{font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--se-text-secondary)}
.ec-map tbody th{padding:0}
/* The range is a filter control, so it is a button — and a full-cell one, so the
   hit target is the whole cell rather than a 60px number. */
.ec-map tbody th button{display:block;width:100%;padding:13px 18px;text-align:left;
  background:none;border:0;cursor:pointer;font-family:var(--font-mono);font-size:14px;
  font-weight:500;color:var(--se-text-white);white-space:nowrap;
  transition:color var(--dur-fast) ease}
/* A range is one token — without nowrap it breaks at the en-dash on a phone and
   "100–199" reads as two rows. Same for the empty-band row's label. */
.ec-gap th{white-space:nowrap}
.ec-map tbody th button:hover{color:var(--accent)}
.ec-map tbody tr:hover{background:rgba(var(--accent-rgb),.05)}
.ec-map tbody tr.ec-band-on{background:rgba(var(--accent-rgb),.1)}
.ec-quote{color:var(--se-text-secondary)}
/* The placeholder caveat is a footnote, not a second lede — smaller and dimmer
   than .sub so it does not compete with the section's own sentence. */
.ec-caveat{margin-top:12px;font-size:14px;color:var(--se-text-caption)}
.ec-src{font-family:var(--font-mono);font-size:11.5px;color:var(--se-text-caption);white-space:nowrap}
.ec-n{font-family:var(--font-mono);font-size:13.5px;color:var(--accent);text-align:right}
/* An empty band is a fact about the numbering, not a row to skip. */
.ec-gap th,.ec-gap td{color:var(--se-text-caption);font-style:italic}
.ec-gap th{padding:13px 18px !important;font-family:var(--font-mono);font-style:normal}

/* --- Collisions. The one section with no upstream equivalent, so it gets the
       most visual weight on the page. --- */
.ec-clashes{display:grid;grid-template-columns:repeat(2,1fr);gap:18px;align-items:start}
.ec-clash{display:grid;grid-template-columns:76px 1fr;gap:18px;align-items:start;
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-xl);
  background:var(--se-frame);padding:20px 22px}
/* The number IS the thing the reader is holding — it gets to be big and mono. */
.ec-num{margin:0;font-family:var(--font-mono);font-size:34px;font-weight:500;
  line-height:1;color:var(--accent)}
.ec-clash ul{list-style:none;margin:0;padding:0;display:grid;gap:12px}
.ec-clash li{display:block}
/* --se-text-dim, NOT --se-text-caption. Caption alpha (.5) measures 6.10:1 on the
   page background but only 4.31:1 here, because these cards sit on the lighter
   --se-frame panel — same alpha, different contrast. Measured, then raised. */
.ec-sys{display:block;margin-bottom:3px;font-family:var(--font-secondary);font-size:10.5px;
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--se-text-dim)}
.ec-clash a{font-family:var(--font-secondary);font-size:14px;line-height:1.45;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.ec-clash a:hover{color:var(--accent)}

/* --- Code lists --- */
.ec-bands,.ec-groups{column-count:2;column-gap:34px}
.ec-band,.ec-group{break-inside:avoid;margin-bottom:32px}
.ec-band-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  margin:0 0 10px;padding-bottom:10px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
.ec-count{font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-caption)}
.ec-note{margin:0 0 12px;font-family:var(--font-secondary);font-size:12.5px;line-height:1.5;
  color:var(--se-text-dim)}
.ec-list{list-style:none;margin:0;padding:0}
/* Grid, not flex: the code column must align down the whole list, and a wrapping
   message must indent under itself rather than under the number. */
.ec-list li{display:grid;grid-template-columns:56px 1fr;gap:12px;align-items:baseline;padding:6px 0}
.ec-list b{font-family:var(--font-mono);font-size:13px;font-weight:500;color:var(--se-text-white)}
.ec-list a{font-family:var(--font-secondary);font-size:14px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.ec-list a:hover{color:var(--accent)}
.ec-list--msg li{grid-template-columns:1fr}
/* A link that is a redirect loop upstream is shown, but not as a link — nobody
   gets sent into the loop, and nothing is silently dropped. */
.ec-dead{font-family:var(--font-secondary);font-size:14px;line-height:1.5;
  color:var(--se-text-caption)}
.ec-dead em{display:inline-block;margin-left:8px;font-style:normal;font-size:10.5px;
  font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--se-live);
  border:1px solid rgba(var(--se-live-rgb),.45);border-radius:var(--r-sm);padding:1px 6px}

@media (max-width:1020px){
  .ec-clashes{grid-template-columns:1fr}
  .hero-codes .wrap{grid-template-columns:1fr}
  .hero-codes .display,.hero-codes .lede,.hero-codes .ec-search,.hero-codes .ec-figures{grid-column:1}
  .hero-codes .ec-figures{grid-row:auto;margin-top:8px}
  .hero-codes .ec-search{max-width:none}
}
@media (max-width:900px){
  .ec-bands,.ec-groups{column-count:1}
  .ec-clash{grid-template-columns:60px 1fr;gap:14px}
  .ec-num{font-size:28px}
}

/* ================================================================
   QUICK SHEETS (#/quick-sheets)
   The third Support child, and the only one whose content is PICTURES.
   So this page is a gallery, not a list — the thumbnail is the label a
   returning user actually recognises, and the caption confirms it.
================================================================ */

.hero-sheets{padding:clamp(44px,5vw,64px) 0 clamp(30px,3.5vw,42px)}
.hero-sheets .wrap{grid-template-columns:1.04fr .96fr;align-items:center;gap:0 clamp(32px,4vw,56px)}
.hero-sheets .eyebrow{grid-column:1/-1;margin-bottom:22px;align-self:start}
.hero-sheets .display{font-size:clamp(32px,4vw,48px);max-width:15ch;margin:0;grid-column:1}
.hero-sheets .lede{max-width:52ch;margin:20px 0 0;grid-column:1}
.hero-sheets .qs-search{grid-column:1}
.hero-sheets .qs-chips{grid-column:1}
.hero-sheets .qs-fan{grid-column:2;grid-row:2/span 4}

/* Decorative fan of three real sheets. aria-hidden in the markup; here it is
   also pointer-events:none so it can never intercept a click meant for the
   search field beside it. */
/* A flex row with negative margins, NOT three absolutely-positioned children.
   Absolute children leave the container zero-width, so justify-self:center
   centres a POINT rather than the artwork — measured 50px off its column. This
   way the fan has a real width and centres on what you can actually see. */
.qs-fan{display:flex;justify-content:center;align-items:center;
  pointer-events:none;justify-self:center}
.qs-fan img{flex:none;width:168px;height:auto;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);border-radius:var(--r-md);
  box-shadow:0 18px 40px rgba(0,0,0,.45);background:var(--se-deep)}
.qs-fan img:nth-child(1){transform:rotate(-7deg);margin-right:-34px}
.qs-fan img:nth-child(2){transform:rotate(1.5deg);z-index:2}
.qs-fan img:nth-child(3){transform:rotate(8deg);margin-left:-34px}
.hero-sheets .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-sheets .eyebrow a:hover{color:var(--accent)}
.qs-search{margin-top:30px;max-width:560px}
.qs-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.qs-search input::placeholder{color:var(--se-text-caption)}
.qs-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
.qs-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

/* The product chips that lived here are gone; the sticky index beside the
   grid (.side-nav) is now the only control for the same state. Two of the
   notes they carried are worth keeping, because they apply to any chip added
   later: text over an --accent fill must be full-strength --accent-ink (at .7
   it composites to 4.15:1, under AA at 11.5px), and measuring that needs
   transitions disabled — in a document.hidden pane the background transition
   never advances and computed style returns the PRE-click fill. */

/* --- Gallery --- */
.qs-group{margin-bottom:54px}
.qs-group:last-child{margin-bottom:0}
.qs-group-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  margin:0 0 20px;padding-bottom:10px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
.qs-count{font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-caption)}
/* auto-fill, not fixed columns: the last group has 13 sheets and the smallest
   has 2, and a fixed 4-up would leave the Source-Live row two-thirds empty. */
/* Five across, not four. These are 1:2 sheets, so card height is set almost
   entirely by the thumbnail: at 242px wide the shot alone was 510px and twelve
   rows of that made the page 11.2 screens. At 189px it is 397px and the grid
   loses three rows. Going to six (154px) saves only another 0.6 screens and
   shrinks the sheet past the point of being recognisable. */
/* The 198px ceiling is the thumbnail's own size, not a taste call: the images
   are 180px wide, and 198 is the widest a track ever got when this grid ran
   full-bleed. With the index taking 236px the column is narrower, so a plain
   1fr stretches three tracks to 235px and upscales every sheet 1.29x — soft
   type on the one page whose subject IS legible type. Leftover width goes to
   the gaps instead. */
.qs-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,198px));gap:22px;
  justify-content:space-between;align-items:start}
.qs-card{margin:0;display:flex;flex-direction:column;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-lg);
  background:var(--se-frame);overflow:hidden;
  transition:border-color var(--dur-fast) ease,transform var(--dur-fast) var(--ease-settle)}
.qs-card:hover{border-color:rgba(var(--accent-rgb),.55);transform:translateY(-2px)}
/* The sheets are 1600x3200 — a true 1:2. The frame states that ratio so the
   thumbnail never letterboxes or stretches, and so the grid does not reflow
   as lazy images arrive. */
/* Ratio per card, from --qs-ar, because THE SET IS NOT UNIFORM: the eight
   Source-Connect 4 sheets are 1694x3600 and the other 29 are 1600x3200
   (measured on all 37 originals). A flat 1:2 frame cropped 6% off the bottom
   of every SC4 thumbnail. Cards within a group share a ratio, so rows still
   line up. The 1/2 fallback only applies if the inline var goes missing. */
.qs-shot{display:block;aspect-ratio:var(--qs-ar,1/2);background:var(--se-deep);overflow:hidden}
.qs-shot img{display:block;width:100%;height:100%;object-fit:cover;object-position:top center}
.qs-card figcaption{padding:14px 16px 16px;display:flex;flex-direction:column;flex:1}
/* Clamped to three lines, not two. Two is shorter by only 0.2 screens but
   truncates 26 of the 37 captions instead of 5 — and several sheets differ
   only in their last word ("...in Source-Connect 4" vs "...3"), so cutting
   tails is exactly the wrong economy. Full text stays in the DOM for screen
   readers and for the title tooltip. */
.qs-cap{margin:0;font-family:var(--font-secondary);font-size:13.5px;line-height:1.45;
  color:var(--se-text-secondary);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
/* Sits at the card foot whatever the caption's length, so the row of actions
   lines up across a grid of very unequal captions. */
/* --accent-hover at REST, not --accent. On this page's teal, --accent measures
   4.48:1 against the card panel — under AA for 12.5px text. The lighter step
   is 6.23:1. Hover then goes to white rather than to accent-hover, so the
   state change is still visible. */
/* flex-wrap + a wrapped LABEL. Left as a bare text node, "Open full size" is an
   anonymous flex item that breaks internally, so on a narrow card it read
   "Open  1694 x 3600 / full size". The label is now one unbreakable item and
   the dimensions drop to their own line instead. */
.qs-open{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin-top:auto;padding-top:12px;
  font-family:var(--font-secondary);font-size:12.5px;font-weight:600;color:var(--accent-hover)}
/* Pixel dimensions are measured NUMBER DATA — mono is correct, and this is the
   only mono on the card. --se-text-dim, not --se-text-caption: caption alpha
   measures 4.31:1 on the card panel. */
.qs-lbl{white-space:nowrap}
.qs-dim{font-family:var(--font-mono);font-size:10.5px;font-weight:500;
  color:var(--se-text-dim);white-space:nowrap}
.qs-open:hover{color:var(--se-text-white)}
/* A correction printed beside a quoted caption, never in place of it. */
.qs-flag{margin:10px 0 0;padding:8px 10px;font-family:var(--font-secondary);font-size:11.5px;
  line-height:1.45;color:var(--se-text-secondary);
  background:rgba(var(--se-live-rgb),.1);border-left:2px solid var(--se-live);
  border-radius:0 var(--r-sm) var(--r-sm) 0}
.qs-flag b{color:var(--se-text-white)}

/* The fan needs ~420px of its own to sit clear of the text column; below that
   the hero goes single column and the fan is dropped entirely rather than
   shrunk — it is decoration, and a phone should spend its height on sheets. */
@media (max-width:1020px){
  .hero-sheets .wrap{grid-template-columns:1fr}
  .hero-sheets .display,.hero-sheets .lede,.hero-sheets .qs-search,.hero-sheets .qs-chips{grid-column:1}
  .hero-sheets .qs-fan{display:none}
  .hero-sheets .qs-search{max-width:none}
}
@media (max-width:640px){
  .qs-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:16px}
}

/* The page's own promise is "print". Make that true: drop the chrome, let the
   thumbnails and their captions flow, and never break a card across a page. */
@media print{
  .site-header,.footer-cta,.site-footer,.qs-search,.qs-chips,.hero-sheets .btn-row{display:none !important}
  .qs-card{break-inside:avoid;border-color:#999}
  .qs-grid{grid-template-columns:repeat(4,1fr)}
}

/* ================================================================
   SOURCE-CONNECT 4 HUB (#/source-connect-4-hub)
   Reuses the Support finders' vocabulary deliberately — this is the fourth
   room in the same building. Its one new component is the cross-reference
   card, which is the point of having rebuilt all four pages.
================================================================ */

.hero-hub{padding:clamp(44px,5vw,64px) 0 clamp(30px,3.5vw,42px)}
.hero-hub .wrap{grid-template-columns:1fr;gap:0}
.hero-hub .eyebrow{margin-bottom:22px}
.hero-hub .display{font-size:clamp(32px,4vw,48px);max-width:17ch;margin:0}
.hero-hub .lede{max-width:60ch;margin:20px 0 0}
.hero-hub .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-hub .eyebrow a:hover{color:var(--accent)}
.hub-search{margin-top:30px;max-width:560px}
.hub-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.hub-search input::placeholder{color:var(--se-text-caption)}
.hub-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
.hub-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

.hub-groups{column-count:2;column-gap:34px}
.hub-group{break-inside:avoid;margin-bottom:32px}
.hub-group-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  margin:0 0 10px;padding-bottom:10px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
.hub-count{font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-caption)}
.hub-note{margin:0 0 10px;font-family:var(--font-secondary);font-size:12px;line-height:1.5;
  color:var(--se-text-dim)}
.hub-note b{color:var(--se-text-white)}
.hub-list{list-style:none;margin:0;padding:0}
.hub-list li{padding:6px 0}
.hub-list a{font-family:var(--font-secondary);font-size:14px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.hub-list a:hover{color:var(--accent)}

/* Cross-reference cards — the count leads, because the count IS the argument:
   this much Source-Connect 4 material is filed somewhere the hub never says. */
.hub-else{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.hub-else-card{display:flex;align-items:baseline;gap:18px;padding:24px 22px;
  border:1px solid rgba(var(--se-border-teal-rgb),.2);border-radius:var(--r-xl);
  background:var(--se-frame);
  transition:border-color var(--dur-fast) ease,transform var(--dur-fast) var(--ease-settle)}
.hub-else-card:hover{border-color:rgba(var(--accent-rgb),.55);transform:translateY(-2px)}
.hub-else-card em{flex:none;font-family:var(--font-mono);font-style:normal;font-size:30px;
  font-weight:500;line-height:1;color:var(--accent-hover)}
.hub-else-card span{display:block;font-family:var(--font-secondary);font-size:12.5px;
  line-height:1.55;color:var(--se-text-dim)}
.hub-else-card b{display:block;font-size:14.5px;font-weight:600;color:var(--se-text-white);
  margin-bottom:5px}

@media (max-width:900px){
  .hub-groups{column-count:1}
  .hub-else{grid-template-columns:1fr}
}

/* ================================================================
   SOURCE-NEXUS SUITE HUB (#/source-nexus-suite)
   Fifth room in the Support building. Its one new idea is the component
   card that is ALSO the filter control — the counts are the argument, so
   the thing displaying them should be the thing you act on.
================================================================ */

.hero-nexus{padding:clamp(44px,5vw,64px) 0 clamp(30px,3.5vw,42px)}
.hero-nexus .wrap{grid-template-columns:1fr;gap:0}
.hero-nexus .eyebrow{margin-bottom:22px}
.hero-nexus .display{font-size:clamp(32px,4vw,48px);max-width:17ch;margin:0}
.hero-nexus .lede{max-width:58ch;margin:20px 0 0}
.hero-nexus .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-nexus .eyebrow a:hover{color:var(--accent)}
.nx-search{margin-top:30px;max-width:560px}
.nx-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.nx-search input::placeholder{color:var(--se-text-caption)}
.nx-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
.nx-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

/* --- Component cards, which double as the filter --- */
.nx-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.nx-card{display:flex;align-items:baseline;gap:16px;text-align:left;padding:22px 20px;
  border:1px solid rgba(var(--se-border-teal-rgb),.2);border-radius:var(--r-xl);
  background:var(--se-frame);cursor:pointer;
  transition:border-color var(--dur-fast) ease,background var(--dur-fast) ease,transform var(--dur-fast) var(--ease-settle)}
.nx-card:hover{border-color:rgba(var(--accent-rgb),.55);transform:translateY(-2px)}
.nx-card:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.nx-card.on{border-color:var(--accent);background:rgba(var(--accent-rgb),.1)}
/* Article counts are measured NUMBER DATA, and here they are the whole point
   of the card — so they lead, in mono, at a size you cannot miss. */
.nx-card em{flex:none;min-width:44px;text-align:right;font-family:var(--font-mono);
  font-style:normal;font-size:28px;font-weight:500;line-height:1;color:var(--accent-hover)}
.nx-card span{display:block;font-family:var(--font-secondary);font-size:12.5px;line-height:1.5;
  color:var(--se-text-dim)}
.nx-card b{display:block;font-size:14.5px;font-weight:600;color:var(--se-text-white);margin-bottom:5px}

/* --- Contents --- */
/* Sticky index beside the articles. The single biggest list on the site —
   159 articles — and the multi-column flow it used before made it worse: two
   columns meant reading down one and back up the other, with no way to tell
   where you were. Single column now, with a persistent index. */
/* One shell for every long list on the site: the Suite hub, both error lists
   and the Source-Connect 4 hub. Sticky index left, single column right. */
.list-shell{display:grid;grid-template-columns:236px 1fr;gap:48px;align-items:start}
.list-shell .nx-groups,.list-shell .ec-bands,.list-shell .ec-groups,
.list-shell .hub-groups,.list-shell .ht-groups{column-count:1}
/* THE RAIL IS THE BASE FORM, and the sticky column is the override. Written
   this way round on purpose: the column is the special case (wide screen, and
   a page with room beside its list), so every declaration is stated once and
   the narrow case cannot be forgotten — which is exactly how the index came to
   be display:none on phones while the switcher still opened on one group. */
.side-nav{display:flex;flex-direction:row;gap:8px;margin:0 0 26px;padding-bottom:6px;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.side-nav::-webkit-scrollbar{display:none}
.side-nav button{display:flex;align-items:center;gap:8px;flex:0 0 auto;min-height:40px;
  padding:10px 15px;text-align:left;background:none;cursor:pointer;
  border:1px solid rgba(var(--se-border-teal-rgb),.28);border-radius:var(--r-pill);
  font-family:var(--font-secondary);font-size:13px;font-weight:600;
  color:var(--se-text-dim);transition:color var(--dur-fast) ease,background var(--dur-fast) ease,
  border-color var(--dur-fast) ease}
.side-nav button:hover{color:var(--se-text-white);background:rgba(var(--accent-rgb),.06)}
.side-nav button:focus-visible{outline:2px solid var(--se-focus);outline-offset:-2px}
.side-nav button.on{color:var(--se-text-white);border-color:var(--accent);
  background:rgba(var(--accent-rgb),.12)}
.side-nav em{font-family:var(--font-mono);font-style:normal;font-size:11px;
  font-weight:500;color:var(--se-text-caption)}
.side-nav button.on em{color:var(--accent-hover)}
/* A section the chosen edition has nothing in. NOT dimmed with opacity: the
   "0" is the answer to "does the Talent guide cover this?", so it has to stay
   readable. A fainter border and the caption colour say inert without hiding
   the information. */
.side-nav button:disabled{cursor:default;color:var(--se-text-caption);
  border-color:rgba(var(--se-border-teal-rgb),.13)}
.side-nav button:disabled:hover{color:var(--se-text-caption);background:none}
/* The edge fade is the only affordance that a horizontal scroller keeps going,
   so it is applied by script (railFades) only while there is more that way. A
   permanent fade would leave the last chip's count looking half-erased.
   Unprefixed, because the tier table on the guides page scrolls the same way
   and deserves the same affordance. */
.rail-r{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 30px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 30px),transparent)}
.rail-l{-webkit-mask-image:linear-gradient(90deg,transparent,#000 30px);
  mask-image:linear-gradient(90deg,transparent,#000 30px)}
.rail-l.rail-r{
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 30px,#000 calc(100% - 30px),transparent);
  mask-image:linear-gradient(90deg,transparent,#000 30px,#000 calc(100% - 30px),transparent)}

/* Sticky column form. top clears the sticky site header (67px) plus a breath.
   Every .side-nav takes this above 900px. There used to be a --rail modifier
   that opted out at all widths, for the guides page while it still spent its
   width on three comparison columns; that page is a single column now, so the
   modifier had no users and is gone rather than left as a dead escape hatch. */
@media (min-width:901px){
  .side-nav{position:sticky;top:83px;flex-direction:column;gap:2px;
    margin:0;padding-bottom:0;overflow:visible}
  .side-nav button{width:100%;box-sizing:border-box;align-items:baseline;
    gap:10px;min-height:0;padding:9px 12px;border:0;border-left:2px solid transparent;
    border-radius:0 var(--r-sm) var(--r-sm) 0}
  .side-nav button.on{border-left-color:var(--accent);
    background:rgba(var(--accent-rgb),.09)}
  .side-nav em{margin-left:auto}
  /* A column never needs the horizontal edge fade. */
  .side-nav.rail-l,.side-nav.rail-r{-webkit-mask-image:none;mask-image:none}
}
.nx-groups{column-count:1}

@media (max-width:900px){
  .list-shell{grid-template-columns:1fr;gap:0}
}
.nx-group{break-inside:avoid;margin-bottom:32px}
.nx-group-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  margin:0 0 10px;padding-bottom:10px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
.nx-count{font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-caption)}
.nx-desc{margin:0 0 12px;font-family:var(--font-secondary);font-size:12px;line-height:1.55;
  color:var(--se-text-dim)}
.nx-list{list-style:none;margin:0;padding:0}
.nx-list li{padding:6px 0}
.nx-list a{font-family:var(--font-secondary);font-size:14px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.nx-list a:hover{color:var(--accent)}

@media (max-width:1020px){ .nx-cards{grid-template-columns:repeat(2,1fr)} }
@media (max-width:760px){ .nx-cards{grid-template-columns:1fr} }

/* ================================================================
   SOURCE-NEXUS SUITE PRODUCT PAGE (#/source-nexus) — 2026-08-28
   Placed with the other nx- rules rather than at the file tail so a
   parallel edit elsewhere in the sheet cannot collide with it.

   Two additions the stakeholder rebuild needed and the sheet had no
   pattern for: the module card's two-line preamble (a parenthetical
   KIND, then the quoted claim), and a two-column feature table.
================================================================ */

/* The kind line is the feedback's parenthetical — "(Virtual Driver
   Engine)". It reads as a subtitle to the module name, so it sits
   tight under the h3 and gives the claim its own breathing room. */
.nxmod-kind{margin:-4px 0 10px;font-family:var(--font-secondary);
  font-size:11.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--se-text-caption)}
.nxmod-claim{margin:0 0 10px;font-size:15px;font-weight:700;line-height:1.4;
  letter-spacing:-.01em;color:var(--se-text-white);text-wrap:balance}

/* Round-4 addition: three of the six module cards (Review, I/O, Control
   Panel) now carry a short bullet list under the body paragraph. Deliberately
   QUIET — it is the same 14.5px/dim body voice as the .card p above it, one
   notch tighter in line-height, so a card with bullets and a card without
   still read as the same object at a glance. The marker is the sheet's
   existing small square notch (see .notch-list) rather than a new shape, at
   the accent colour and half-strength fill; no list-style, so no browser
   bullet glyph competes with it. */
.nxmod-points{list-style:none;margin:0 0 12px;padding:0;
  display:flex;flex-direction:column;gap:7px}
.nxmod-points li{position:relative;padding-left:18px;
  font-family:var(--font-secondary);font-size:13.5px;line-height:1.5;
  color:var(--se-text-dim)}
.nxmod-points li::before{content:"";position:absolute;left:0;top:7px;
  width:7px;height:7px;border-radius:2px;
  background:rgba(var(--accent-rgb),.2);border:1px solid var(--accent)}

/* --- MOMENT: "The signal chain lights up" (spec 2026-08-28, moment 3) ---
   ROUND 4 (2026-08-31) REWROTE THE ORDER. Round 3 shipped the cards in one
   fixed DOM order (Gateway, Control Panel, Review, Router, I/O, Mute-On) and
   REVEALED them in a different, signal-flow order. The round-4 stakeholder
   feedback fixes the card order itself — Gateway, Review, I/O, Router,
   Mute-On, Control Panel — and their order supersedes that routing-order
   judgment: reveal order is now DOM order, staggered 0/90/180/270/360/450ms
   from the top-left card onward, so the eye's scan path and the stagger
   agree. The inline per-card --mo-delay is kept rather than swapped for
   .mo-seq: the mapping stays legible in the markup, and the next re-order is
   a one-value-per-card edit with nothing implicit to re-derive. Only
   .mo-reveal/.mo-draw are consumed from the engine, as before.

   CONNECTOR WAYPOINTS ARE MEASURED, NOT ASSUMED — and the measurement
   corrected the round-3 column figures. The path visits the six card centres
   in the new order. Round 3 assumed column centres of 16.7/50/83.3%
   ("repeat(3,1fr) is symmetric"); a headless read of getBoundingClientRect
   at 1024/1060/1100/1140/1180/1400/1600px says otherwise. The 1fr tracks are
   (grid - 2*gap)/3 wide, so the OUTER centres sit INWARD of the thirds, at
   15.97-16.02% and 83.98-84.03%. Row centres survive the round-4 copy almost
   unchanged (24.77-25.06% and 75.33-75.62% across the seven widths) even
   though row 1 now carries two bullet lists to row 2's one: the rows differ
   by only ~24px out of ~1790, because the bullet lists mostly consume slack
   the tallest card in each row already had. The widest row spread is at
   ~1060px, the band where the wrap is not yet capped at its max-width.

   THE ROW FIGURE HAS A TRAP, and this note exists so the next editor does
   not fall in it. Read the rects a moment too early — while .mo-reveal's
   translateY(14px) is still on the cards — and row 2's centre measures
   ~0.8pp LOW (76.4% instead of 75.6%), because getBoundingClientRect
   includes the transform. The figures above are read only after the moment
   has landed: opacity 1, transform none. The path therefore ships 16/50/84
   and 24.9/75.5, the mid-points of the measured ranges — within 0.17pp at
   every verified width, ~3px of a ~1790px grid, against a .45 stroke that
   is itself ~8px tall in this preserveAspectRatio="none" space. The line
   sits inside its own stroke of every card centre.

   THE INITIAL DOM IS THE DESTINATION: .mo-reveal defaults to visible (the
   engine only hides it once html.mo-armed is added) and the connector path
   ships as a plain, fully-stroked <path> — motion.js only borrows it into a
   dash pattern once armed. So no-JS, reduced-motion and <1024px readers all
   see six visible cards; >=1024px readers additionally see one fully-drawn
   connecting line even with JS off or motion reduced. Below 1024px the
   overlay is a flat display:none: the row heights across six cards of
   uneven copy length aren't verified to hold the connector's percentage
   waypoints at narrower widths, and hiding this decoration is allowed where
   hiding a card would not be. The line threads the GAPS between cards, not
   their faces — z-index:-1 keeps it under the opaque card backgrounds, so
   what reads on screen is a line that visits each module's neighborhood in
   routing order, not a line drawn over the copy. */
#nx-modules .grid{position:relative}
.nxmod-connector{
  display:none;position:absolute;inset:0;width:100%;height:100%;
  z-index:-1;pointer-events:none;
  /* The 60% dimming lives on the WRAPPER, not the path: the path is a
     .mo-draw element and the motion law asserts its settled opacity is 1.
     Opacity multiplies down, so the wire looks identical. */
  opacity:.6;
}
.nxmod-connector path{
  fill:none;stroke:var(--accent);stroke-width:.45;
  stroke-linejoin:round;stroke-linecap:round;
  filter:drop-shadow(0 0 4px rgba(var(--accent-rgb),.55));
}
@media (min-width:1024px){
  .nxmod-connector{display:block}
}

/* Feature table. Two columns, so the house min-width + horizontal
   scroll would be the wrong trade at phone width — there is nothing
   to compare ACROSS, only a label and its value. Below 640px each
   row becomes a stacked label/value pair instead of a scroll. */
.nxtab-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid rgba(var(--se-border-teal-rgb),.18);
  border-radius:var(--r-2xl);
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%)}
.nxtab{width:100%;min-width:600px;border-collapse:collapse;text-align:left;
  font-family:var(--font-secondary);font-size:13.5px;line-height:1.55}
.nxtab th,.nxtab td{text-align:left;vertical-align:top;padding:14px 20px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14)}
.nxtab thead th{font-size:11.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--accent);white-space:nowrap;
  background:rgba(var(--accent-rgb),.06)}
.nxtab tbody th{width:42%;font-weight:600;color:var(--se-text-white)}
.nxtab tbody td{color:var(--se-text-secondary);font-weight:600}
.nxtab tbody tr:last-child th,.nxtab tbody tr:last-child td{border-bottom:0}

@media (max-width:640px){
  .nxtab-wrap{overflow-x:visible}
  .nxtab{min-width:0}
  .nxtab thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
  .nxtab,.nxtab tbody,.nxtab tr{display:block;width:auto}
  .nxtab tr{padding:14px 18px;
    border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14)}
  .nxtab tr:last-child{border-bottom:0}
  .nxtab tbody th,.nxtab tbody td{display:block;width:auto;padding:0;border:0}
  .nxtab tbody th{font-size:12px;letter-spacing:.04em;
    text-transform:uppercase;color:var(--se-text-caption);margin-bottom:5px}
  .nxtab tbody td{font-size:14.5px;color:var(--se-text-white)}
}

/* Nothing here animates; the rule is a guard against a future
   transition being added to these without one. */
@media (prefers-reduced-motion:reduce){
  .nxtab-wrap,.nxtab th,.nxtab td{transition:none;animation:none}
}

/* ================================================================
   SOURCE-LIVE PRO LL USER GUIDE (#/source-live-guide)
   The only one of these KB pages whose ORDER was already right, so this
   is the only one that renders as a numbered sequence rather than a
   searchable index. The numbers are positions in the upstream listing.
================================================================ */

.hero-live{padding:clamp(44px,5vw,64px) 0 clamp(30px,3.5vw,42px)}
.hero-live .wrap{grid-template-columns:1fr;gap:0}
.hero-live .eyebrow{margin-bottom:22px}
.hero-live .display{font-size:clamp(32px,4vw,48px);max-width:16ch;margin:0}
.hero-live .lede{max-width:58ch;margin:20px 0 0}
.hero-live .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-live .eyebrow a:hover{color:var(--accent)}
.sl-search{margin-top:30px;max-width:560px}
.sl-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.sl-search input::placeholder{color:var(--se-text-caption)}
.sl-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
.sl-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

/* --- The sequence --- */
.sl-runs{column-count:2;column-gap:40px}
.sl-run{break-inside:avoid;margin-bottom:34px}
.sl-run-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  margin:0 0 10px;padding-bottom:10px;border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
/* The range is the run's position in the upstream sequence — number data. */
.sl-range{flex:none;font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;color:var(--se-text-caption)}
.sl-count{margin-left:auto;font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-caption)}
.sl-blurb{margin:0 0 12px;font-family:var(--font-secondary);font-size:12px;line-height:1.55;
  color:var(--se-text-dim)}
/* list-style:none on an <ol> strips its semantics in Safari; the numbers are
   rendered explicitly anyway, so the list keeps role="list" via the markup. */
.sl-list{list-style:none;margin:0;padding:0}
.sl-list li{display:grid;grid-template-columns:26px 1fr;gap:10px;align-items:baseline;padding:6px 0}
.sl-n{font-family:var(--font-mono);font-size:11.5px;font-weight:500;color:var(--se-text-caption);
  text-align:right}
.sl-list a{font-family:var(--font-secondary);font-size:14px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.sl-list a:hover{color:var(--accent)}
/* The product name that ends 15 of 28 titles: present in the DOM, receded. */
.sl-dim{color:var(--se-text-caption)}

@media (max-width:900px){ .sl-runs{column-count:1} }

/* ================================================================
   SOURCE-CONNECT 3.9 GUIDES (#/source-connect-39)
   Two doors, then one guide — the same shape as the Source-Connect 4
   guides page, and it shares that page's .cg-door* components. The one
   difference is real rather than stylistic: neither 3.9 guide index
   publishes section headings (the 4 guides publish seven and eight), so
   3.9 renders as a numbered sequence with no section rail.
================================================================ */

.hero-cc{padding:clamp(44px,5vw,64px) 0 clamp(30px,3.5vw,42px)}
.hero-cc .wrap{grid-template-columns:1fr;gap:0}
.hero-cc .eyebrow{margin-bottom:22px}
/* `h1.display em` is white-space:nowrap SITEWIDE. This page's accent phrase is
   28 characters, so on a phone it ran 463px wide inside a 354px column — the
   body's overflow-x:hidden clipped it silently, so there was no scrollbar to
   notice, just an unreadable headline. Same override home and Source-Nexus
   already carry. Any new hero with a long accent phrase needs this. */
.hero-cc .display{font-size:clamp(32px,4vw,48px);max-width:19ch;margin:0}

/* THE ACCENT PHRASE MUST BE ALLOWED TO WRAP on every Support finder.
   `h1.display em` is white-space:nowrap sitewide and `body` is
   overflow-x:hidden, so a long accent phrase is not merely awkward — it is
   SILENTLY CLIPPED, and it also inflates the hero grid's min-content width,
   which drags the eyebrow and panel column out with it. This is a blanket rule for the whole family rather than a per-page patch. Any new hero added here
   inherits the fix; any new hero added elsewhere still needs its own. */
.hero-howto .display em,
.hero-codes .display em,
.hero-sheets .display em,
.hero-hub .display em,
.hero-nexus .display em,
.hero-live .display em,
.hero-cc .display em{white-space:normal}
.hero-cc .lede{max-width:60ch;margin:20px 0 0}
.hero-cc .eyebrow a{color:inherit;text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(var(--accent-rgb),.45)}
.hero-cc .eyebrow a:hover{color:var(--accent)}
.cc-search{margin-top:30px;max-width:560px}
.cc-search input{width:100%;box-sizing:border-box;padding:15px 18px;
  font-family:var(--font-secondary);font-size:16px;color:var(--se-text-white);
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.28);
  border-radius:var(--r-lg);transition:border-color var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
.cc-search input::placeholder{color:var(--se-text-caption)}
.cc-search input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
.cc-count-live{margin:10px 2px 0;min-height:19px;font-family:var(--font-mono);
  font-size:12.5px;letter-spacing:.02em;color:var(--se-text-dim)}

/* The article title link. Scoped to the row so it never reaches the links
   inside an expanded article body, which .cg-body a styles instead. */
/* The three-column diff and its T#/S# position badges are gone from both
   guide pages — .cc-cols, .cc-col, .cc-pos, .cc-s, .cc-p and .cc-col-h with
   them. What survives is the shared list vocabulary the guide bodies still
   use. The contrast note those rules carried is worth keeping: a component moved
   ONTO a panel must be re-measured.
   --accent on --se-frame is 4.48:1 and caption alpha 4.31:1, both under AA,
   while the identical component passes on the darker page background. */
.cc-n{font-family:var(--font-mono);font-size:12px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--se-text-dim)}
.cc-list{list-style:none;margin:0;padding:0}
.cc-list>li>a{font-family:var(--font-secondary);font-size:13.5px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.cc-list>li>a:hover{color:var(--accent)}
.cc-flag{font-family:var(--font-secondary);font-size:10px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;
  color:var(--se-live);border:1px solid rgba(var(--se-live-rgb),.45);
  border-radius:var(--r-sm);padding:1px 6px}

/* ================================================================
   SOURCE-CONNECT 4 GUIDES (#/source-connect-4-guides)
   Two doors, then one guide, with the guide's own chapters as a sticky
   index beside it. The comparison this page used to lead with is a
   demoted section at the foot, for people still choosing.
================================================================ */

/* --- The doors --- */
.cg-doors{display:grid;grid-template-columns:1fr 1fr;gap:24px;align-items:stretch}
/* Buttons, not links: they open a panel on this page. Everything inside is
   left-aligned because it is a card of prose, not a label. */
.cg-door{display:flex;flex-direction:column;text-align:left;cursor:pointer;
  padding:26px 26px 22px;background:var(--se-frame);
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-xl);
  transition:border-color var(--dur-fast) ease,background var(--dur-fast) ease,
  transform var(--dur-fast) var(--ease-settle)}
.cg-door:hover{border-color:rgba(var(--accent-rgb),.55);transform:translateY(-2px)}
.cg-door:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.cg-door.on{border-color:var(--accent);background:var(--se-inner)}
/* --accent-hover, not --accent: this sits on --se-frame, where the teal
   accent measures 4.48:1. Moving a component onto a panel invalidates its contrast — always re-measure. */
.cg-door-tier{margin:0 0 10px;font-family:var(--font-secondary);font-size:11.5px;
  font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-hover)}
.cg-door-h{margin:0 0 12px;font-size:clamp(19px,2vw,23px);line-height:1.2;
  color:var(--se-text-white)}
.cg-door-who{margin:0 0 16px;font-family:var(--font-secondary);font-size:14px;
  line-height:1.6;color:var(--se-text-secondary)}
.cg-door-pts{list-style:none;margin:0 0 20px;padding:0;display:flex;
  flex-direction:column;gap:7px}
.cg-door-pts li{position:relative;padding-left:18px;font-family:var(--font-secondary);
  font-size:13px;line-height:1.5;color:var(--se-text-dim)}
.cg-door-pts li::before{content:"";position:absolute;left:0;top:8px;width:6px;height:6px;
  border-radius:50%;background:rgba(var(--accent-rgb),.55)}
.cg-door-go{display:flex;align-items:baseline;gap:10px;margin:auto 0 0;
  padding-top:16px;border-top:1px solid rgba(var(--se-border-teal-rgb),.18);
  font-family:var(--font-secondary);font-size:13px;color:var(--se-text-dim)}
.cg-door-go em{font-family:var(--font-mono);font-style:normal;font-size:19px;
  font-weight:500;color:var(--se-text-white)}
.cg-door-go span{margin-left:auto;font-weight:600;color:var(--accent-hover)}
.cg-door-help{margin:22px 0 0;max-width:78ch;font-family:var(--font-secondary);
  font-size:13px;line-height:1.65;color:var(--se-text-dim)}
.cg-door-help a{color:var(--accent-hover);font-weight:600}

/* --- The open guide --- */
.cg-guide-head{display:flex;align-items:flex-end;gap:24px;margin-bottom:8px}
.cg-guide-head .section-label,.cg-guide-head .h-section,.cg-guide-head .sub{margin-bottom:0}
.cg-guide-head .sub{margin-top:10px}
.cg-guide-head>div{flex:1}
.cg-guide-head button{flex:none;white-space:nowrap}
.cg-secs{display:flex;flex-direction:column;gap:34px}
.cg-sec-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--accent);
  margin:0 0 12px;padding-bottom:10px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
/* ORDER NEEDS A FLEX PARENT. Each row's `order` is its position in the guide
   being read, which is how one DOM serves two reading orders — but `order` is
   ignored on a block container, so this list must be flex. */
.cg-secs .cc-list{display:flex;flex-direction:column}
/* Child combinator throughout: an expanded article is injected inside its row
   and is full of its own <li>, which a descendant selector would restyle. */
.cg-secs .cc-list>li{display:block;padding:7px 0}
.cg-secs .cc-list>li>.cc-flag{display:inline-block;margin:0 0 0 9px;vertical-align:1px}

/* --- Testimonials: short by default, full on demand ---
   The collapsed card carries a lead line and the attribution and nothing else,
   so a row of them can be scanned. Anything longer lives in .credit-rest and
   is revealed in place. THE BUTTON ONLY APPEARS WHEN THERE IS A REST: a short
   entry renders as a plain card with no affordance promising more. */
.credit-rest[hidden]{display:none}
.credit-rest p{margin:0 0 10px}
.credit-rest p:last-child{margin-bottom:0}
.credit-more{align-self:flex-start;margin-top:10px;padding:6px 0;cursor:pointer;
  background:none;border:0;font-family:var(--font-secondary);font-size:12.5px;
  font-weight:600;color:var(--accent-hover);
  display:inline-flex;align-items:center;gap:7px}
.credit-more::after{content:"";width:7px;height:7px;flex:none;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg) translate(-1px,-1px);
  transition:transform var(--dur-fast) ease}
.credit.open .credit-more::after{transform:rotate(-135deg) translate(-2px,-2px)}
.credit-more:hover{color:var(--accent)}
.credit-more:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px;border-radius:2px}
/* A longer quote is a quote, so it is set as one. The opening mark is a
   decorative glyph on the blockquote, NOT generated quote characters on the
   paragraphs: the lead paragraph is both :first-child and :last-of-type while
   the rest is collapsed, so it took an opening AND a closing mark, printing a
   quote mark in the middle of the quote the moment it expanded. A single
   opening glyph has no such state to get wrong. */
.credit blockquote{margin:0;font-size:13.5px;line-height:1.6;color:var(--se-text-secondary);
  position:relative;padding-top:16px}
.credit blockquote::before{content:"\201C";position:absolute;top:-4px;left:-2px;
  font-size:32px;line-height:1;color:rgba(var(--accent-rgb),.4);pointer-events:none}
.credit-role{margin:0 0 10px;font-family:var(--font-secondary);font-size:12px;
  line-height:1.4;color:var(--se-text-caption)}
.credit blockquote strong{color:var(--se-text-white);font-weight:600}

/* --- An article, expanded under its title --- */
/* The row becomes the heading of an open article, so it needs to read as one. */
.cg-secs .cc-list>li.open>a{color:var(--se-text-white);font-weight:600}
.cg-secs .cc-list>li.open{padding-bottom:0}
.cg-body{margin:12px 0 26px;padding:20px 22px 18px;
  border:1px solid rgba(var(--accent-rgb),.22);border-left:2px solid var(--accent);
  border-radius:0 var(--r-lg) var(--r-lg) 0;background:var(--se-frame)}
.cg-body-note{margin:0;font-family:var(--font-secondary);font-size:13px;color:var(--se-text-dim)}
.cg-body-foot{margin:18px 0 0;padding-top:14px;
  border-top:1px solid rgba(var(--se-border-teal-rgb),.18)}
.cg-body-foot a{font-family:var(--font-secondary);font-size:12.5px;font-weight:600;
  color:var(--accent-hover)}
.cg-body-foot a:hover{color:var(--accent)}

/* THIS BLOCK STYLES MARKUP THIS PROJECT DOES NOT AUTHOR. It is whatever the
   Knowledge Base editor produced, so it is addressed by tag rather than by
   class, and it is scoped to .cg-body so it can never leak onto the site. */
.cg-body p,.cg-body li{font-family:var(--font-secondary);font-size:14px;line-height:1.65;
  color:var(--se-text-secondary)}
.cg-body p{margin:0 0 14px}
.cg-body>*:last-child{margin-bottom:0}
.cg-body h1,.cg-body h2,.cg-body h3,.cg-body h4{
  margin:26px 0 10px;line-height:1.25;color:var(--se-text-white);font-weight:600}
.cg-body h1,.cg-body h2{font-size:17px}
.cg-body h3{font-size:15px}
.cg-body h4{font-size:14px}
.cg-body ul,.cg-body ol{margin:0 0 14px;padding-left:22px}
.cg-body li{margin:0 0 6px}
.cg-body strong,.cg-body b{color:var(--se-text-white);font-weight:600}
.cg-body a{color:var(--accent-hover);text-decoration:underline;
  text-underline-offset:2px;text-decoration-color:rgba(var(--accent-rgb),.4)}
.cg-body a:hover{color:var(--accent)}
.cg-body figure{margin:16px 0}
.cg-body figcaption{margin-top:8px;font-family:var(--font-secondary);font-size:12px;
  color:var(--se-text-caption)}
/* Screenshots of a dark application on a dark page: a hairline keeps the
   edges from dissolving into the panel. Width caps the KB's inline pixel
   widths (one image declares 583px) without stripping the attribute. */
.cg-body img{display:block;max-width:100%;height:auto;margin:14px 0;
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-md)}
.cg-body table{width:100%;border-collapse:collapse;margin:0 0 16px;
  font-family:var(--font-secondary);font-size:13px}
.cg-body th,.cg-body td{text-align:left;padding:9px 12px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16);color:var(--se-text-secondary)}
.cg-body th{color:var(--se-text-white);font-weight:600}

/* No !important anywhere in this block, and that is deliberate: the KB's
   light-theme inline colours and font sizes are REMOVED from the markup in
   cgSanitise rather than overridden here, so these rules apply normally. */

/* --- Source-Live <-> Source-Nexus, the step between them --- */
.sl-step{margin:20px 0 0;font-family:var(--font-secondary);font-size:13.5px;
  line-height:1.6;color:var(--se-text-dim);padding-left:16px;
  border-left:2px solid rgba(var(--accent-rgb),.35)}
.sl-step a{color:var(--accent-hover);font-weight:600}
.sl-step a:hover{color:var(--accent)}
/* The Source-Live hours ladder. On /products/source-live/ this was a drag
   slider, which cannot be operated by keyboard and, with JS off, showed a
   figure with no hours attached to it. Buttons fix both: the ten-hour tier
   is in the markup and these only change it. Selected state follows the
   .nx-card.on idiom rather than a solid fill — the accent here is amber. */
.sl-calc{max-width:520px;margin:0 auto 26px;text-align:center}
.sl-calc-q{font-family:var(--font-secondary);font-size:13.5px;color:var(--se-text-dim);margin:0 0 12px}
.sl-hours{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}
.sl-hour{
  font-family:var(--font-mono);font-size:12.5px;font-weight:600;letter-spacing:.04em;
  color:var(--se-text-secondary);background:var(--se-bg);
  border:1px solid rgba(var(--se-border-teal-rgb),.28);border-radius:var(--r-sm);
  padding:9px 15px;cursor:pointer;
  transition:color .18s ease,border-color .18s ease,background .18s ease;
}
.sl-hour:hover{color:var(--se-text-white);border-color:rgba(var(--accent-rgb),.5)}
.sl-hour.on{color:var(--se-text-white);border-color:var(--accent);background:rgba(var(--accent-rgb),.12)}
.sl-hour:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* "Contact us" is a phrase, not a figure — 42px/800 is sized for "$395". */
.price-line .amt.text{font-size:26px}
@media (prefers-reduced-motion:reduce){.sl-hour{transition:none}}

.sl-addon{margin:22px auto 0;max-width:56ch;font-family:var(--font-secondary);
  font-size:13px;line-height:1.6;color:var(--se-text-dim)}
.sl-addon b{color:var(--se-text-white);font-weight:600}
.sl-addon a{color:var(--accent-hover);font-weight:600}
.sl-addon a:hover{color:var(--accent)}


/* --- MOMENT: "Two frames lock into sync" (spec 2026-08-28, moment 11) ---
   The page's own claim, performed once. Sits at the end of the Source-Live
   family because that is what it belongs to, not near the engine block: the
   engine is the vocabulary, this is the sentence.

   THE INITIAL DOM IS THE DESTINATION. Not one rule below moves anything until
   html.mo-armed matches, and motion.js sets that only at >=768px with
   prefers-reduced-motion unset. A phone, reduced motion, JS off or a thrown
   error therefore all render the two frames ALREADY level with the label
   ALREADY read — the offset is something the armed page borrows and gives
   back on .mo-in, never a state the markup ships in.

   Plays once: .mo-in is added by the engine's observer on the first crossing
   and nothing anywhere removes it. */
.sl-sync{display:flex;flex-direction:column;align-items:center;
  gap:clamp(18px,2.4vw,28px)}
.sl-sync-stage{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(16px,2.6vw,34px);width:100%;max-width:900px;align-items:center}
.sl-frame{display:block;width:100%;height:auto;border-radius:12px;
  border:1px solid rgba(var(--se-border-teal-rgb),.24);
  box-shadow:0 26px 54px rgba(0,0,0,.45)}
.sl-sync-label{margin:0;text-align:center;
  font-family:var(--font-secondary);font-size:clamp(15px,1.7vw,19px);
  font-weight:700;letter-spacing:-.01em;color:var(--se-text-white)}
.sl-sync-label::before{content:"";display:inline-block;vertical-align:2px;
  width:8px;height:8px;border-radius:50%;margin-right:10px;
  background:var(--accent);box-shadow:0 0 10px rgba(var(--accent-rgb),.65)}
/* The moment. The review frame arrives low, right, and a degree off square;
   on first view it settles onto the source frame's axis. The 320ms delay lets
   the stage's own .mo-reveal fade get most of the way in first, so the offset
   is SEEN before it resolves rather than resolving inside a fade — and the
   label's turn comes after, via the .mo-seq step on the container. */
html.mo-armed .sl-sync-stage .sl-frame-b{
  transform:translate(14px,30px) rotate(1.2deg);
  transition:transform 900ms var(--ease-settle) 320ms;
}
html.mo-armed .sl-sync-stage.mo-in .sl-frame-b{transform:none}
/* Calm at phone width: one column, both frames level, nothing transformed.
   motion.js does not arm below 768px, so this rule is layout only — it is the
   composition the moment resolves TO, shown without the moment. */
@media (max-width:767px){
  .sl-sync-stage{grid-template-columns:1fr;max-width:430px;gap:14px}
}

/* --- Nexus: the free tier, and the spec stated once --- */
/* Free is not a term, so it is not a fourth column in the term comparison.
   Horizontal, so it reads as a way in rather than a cheaper plan. */
.price-free{display:grid;grid-template-columns:minmax(220px,1fr) auto auto;gap:28px 40px;
  align-items:center;padding:26px 28px;margin-bottom:22px;
  background:var(--se-frame);border:1px solid rgba(var(--se-border-teal-rgb),.18);
  border-radius:var(--r-2xl)}
.price-free .rec{margin:0 0 8px;min-height:0}
.price-free h3{margin:0 0 4px}
.price-free .price-line{margin:0 0 4px}
.price-free .price-note{margin:0}
.price-free-list{list-style:none;margin:0;display:flex;flex-direction:column;gap:7px}
.price-free .btn{white-space:nowrap}

/* The three term cards carried these three lines EACH, and the legal line under
   the grid repeated them a fourth time. Said once, they stop being noise and
   start being the answer to "what am I actually buying". */
.price-includes{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px 22px;
  margin:0 0 22px;padding:14px 20px;
  background:var(--se-inner);border:1px solid rgba(var(--se-border-teal-rgb),.14);
  border-radius:var(--r-lg);
  font-family:var(--font-secondary);font-size:13px;color:var(--se-text-secondary)}
.price-includes b{font-size:11px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--accent-hover)}
.price-includes span{position:relative;padding-left:20px}
.price-includes span::before{content:"";position:absolute;left:0;top:5px;width:9px;height:5px;
  border-left:2px solid var(--se-selected);border-bottom:2px solid var(--se-selected);
  transform:rotate(-45deg)}

@media (max-width:760px){
  .price-free{grid-template-columns:1fr;gap:18px;align-items:start}
  .price-free .btn{width:100%}
}

/* --- The demoted comparison --- */
.cg-tier-wrap{overflow-x:auto;margin-bottom:34px;-webkit-overflow-scrolling:touch}
.cg-tier{width:100%;min-width:640px;border-collapse:collapse;
  font-family:var(--font-secondary);font-size:13px;line-height:1.5}
.cg-tier th,.cg-tier td{text-align:left;vertical-align:top;padding:13px 16px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16)}
.cg-tier thead th{font-size:11.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--accent);white-space:nowrap}
.cg-tier tbody th{width:22%;font-weight:600;color:var(--se-text-white)}
.cg-tier td{color:var(--se-text-secondary)}
.cg-tier tbody tr:last-child th,.cg-tier tbody tr:last-child td{border-bottom:0}
.cg-no{color:var(--se-text-caption)}

/* --- The guide as a numbered sequence (3.9) --- */
/* Flex, because each row's `order` is its position in the guide being read —
   `order` is ignored on a block container. The li is still a grid inside. */
.cg-seq{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}
.cg-seq li{display:grid;grid-template-columns:28px 1fr;gap:12px;align-items:baseline;padding:7px 0}
.cg-n{font-family:var(--font-mono);font-size:11.5px;font-weight:500;
  color:var(--se-text-caption);text-align:right}
.cg-seq a{font-family:var(--font-secondary);font-size:14px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.cg-seq a:hover{color:var(--accent)}

/* --- "What only one guide covers" --- */
.cg-only{display:grid;grid-template-columns:1fr 1fr;gap:26px;align-items:start}
.cg-only-side{border:1px solid rgba(var(--se-border-teal-rgb),.18);
  border-radius:var(--r-xl);background:var(--se-frame);padding:22px 20px}
/* --accent-hover, not --accent: inside a panel. See the note above. */
.cg-only-h{display:flex;align-items:baseline;gap:10px;font-size:13px;font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--accent-hover);
  margin:0 0 14px;padding-bottom:10px;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.18)}
.cg-only-list{list-style:none;margin:0;padding:0}
.cg-only-list li{padding:6px 0}
.cg-only-list a{font-family:var(--font-secondary);font-size:13.5px;line-height:1.5;
  color:var(--se-text-secondary);transition:color var(--dur-fast) ease}
.cg-only-list a:hover{color:var(--accent)}
.cg-only-note{margin:22px 0 0;max-width:80ch;font-family:var(--font-secondary);
  font-size:13px;line-height:1.65;color:var(--se-text-dim)}
.cg-only-note b{color:var(--se-text-white);font-weight:600}

@media (max-width:820px){
  .cg-doors,.cg-only{grid-template-columns:1fr}
  .cg-guide-head{flex-direction:column;align-items:flex-start;gap:16px}
}

/* The one difference that changes what you can do. */
.cg-fact{display:grid;grid-template-columns:1fr 1fr;gap:0;
  border:1px solid rgba(var(--se-border-teal-rgb),.22);border-radius:var(--r-xl);
  background:var(--se-frame);overflow:hidden}
.cg-fact-side{padding:26px 26px 22px}
.cg-fact-side+.cg-fact-side{border-left:1px solid rgba(var(--se-border-teal-rgb),.18);
  background:rgba(var(--accent-rgb),.05)}
.cg-fact-h{margin:0 0 10px;font-family:var(--font-secondary);font-size:12px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent-hover)}
/* The count is the argument; mono, and big enough to compare across the rule. */
.cg-fact-n{margin:0 0 8px;font-family:var(--font-secondary);font-size:15px;
  color:var(--se-text-secondary)}
.cg-fact-n b{font-family:var(--font-mono);font-size:34px;font-weight:500;line-height:1;
  color:var(--se-text-white);margin-right:10px}
.cg-fact-d{margin:0;font-family:var(--font-secondary);font-size:13px;line-height:1.55;
  color:var(--se-text-dim)}
.cg-fact-d b{color:var(--se-text-white);font-weight:600}
.cg-fact-note{grid-column:1/-1;margin:0;padding:16px 26px;font-family:var(--font-secondary);
  font-size:13px;line-height:1.6;color:var(--se-text-dim);
  border-top:1px solid rgba(var(--se-border-teal-rgb),.18);background:var(--se-inner)}
.cg-fact-note a{color:var(--accent-hover);font-weight:600;white-space:nowrap}

@media (max-width:760px){
  .cg-fact{grid-template-columns:1fr}
  .cg-fact-side+.cg-fact-side{border-left:0;
    border-top:1px solid rgba(var(--se-border-teal-rgb),.18)}
}

/* The edition switch is gone from both guide pages; the doors replaced it.
   ITS CLOSING BRACE WAS LEFT BEHIND when the rules were deleted, and sat here
   as a stray `}` at the end of the stylesheet. Found 2026-08-21 while adding
   the language picker: the new rules parsed in the file and matched NOTHING in
   the browser — CSS.getMatchedStylesForNode returned only the `div` reset. */

/* The "Show all N" button that used to cap each column is gone; the section
   rail replaced it. Nothing renders .cc-more any more, so its rules went too. */

/* ---------- Language picker (EN | ES) ----------
   The live site puts this at the far right of the nav, after the CTA. It is a
   SITE-level switch: ES goes to es.source-elements.com, which is its own
   edition, not a translation layer on this one. */
.language-picker{display:flex;align-items:center;gap:6px;flex:none;
  font-family:var(--font-mono);font-size:11.5px;font-weight:600;letter-spacing:.06em}
.language-picker .lang-btn{color:var(--se-text-caption);padding:6px 2px;line-height:1;
  transition:color .18s ease}
.language-picker .lang-btn:hover{color:var(--se-text-white)}
.language-picker .lang-active{color:var(--accent)}
.language-picker .lang-active:hover{color:var(--accent)}
.language-picker .lang-sep{color:var(--se-text-disabled,rgba(255,255,255,.28))}
.language-picker .lang-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:2px}
.language-picker--mobile{display:none}
/* At 320px the logo, CTA, 44px menu control and edition switch cannot share
   one header row. Keep EN|ES available as the final item of the opened menu
   instead of sending the menu button past the viewport edge. */
@media(max-width:380px){
  .header-actions .language-picker{display:none}
  .main-nav .language-picker--mobile{display:flex;padding:14px var(--hdr-gutter) 2px}
  /* This showcase image has no intrinsic width after the stacked flex layout
     takes over. Give its socket the available measure so the route badge has
     a real containing block instead of hanging beyond the viewport. */
  .showcase-media .ui-shot{width:100%}
}
@media (prefers-reduced-motion:reduce){.language-picker .lang-btn{transition:none}}

/* The affiliations wall names the bodies; this is the way to the page about
   them. Javier: "members section: link to our community page". */
.affil-more{margin:26px 0 0;text-align:center;font-family:var(--font-secondary);font-size:14.5px}
.affil-more a{color:var(--accent-hover);font-weight:600;text-decoration:underline;
  text-underline-offset:3px;text-decoration-color:rgba(var(--accent-rgb),.4)}
.affil-more a:hover{color:var(--accent);text-decoration-color:var(--accent)}

/* ---------- The pedigree line ----------
   A brand statement, given its own band between the hero and the craft grid.
   Not a heading: it carries no rank in the outline, because the hero's h1
   already owns that level and a second one here would compete with it. */
.pedigree{border-top:1px solid rgba(var(--se-border-teal-rgb),.14);
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14);
  background:linear-gradient(180deg,rgba(var(--accent-rgb),.045) 0%,transparent 70%);
  padding:clamp(30px,4vw,46px) 0}
.pedigree-line{margin:0;text-align:center;font-family:var(--font-primary);
  font-size:clamp(20px,2.5vw,30px);font-weight:700;line-height:1.28;
  letter-spacing:-.015em;color:var(--se-text-white);
  margin-inline:auto;text-wrap:balance}
.pedigree-line em{font-style:normal;color:var(--accent)}

/* ---------- The stat band (home page, moment 1) ----------
   The quietest thing on the page, by design. It follows the pedigree line
   because that sentence is the claim and these five figures are its receipts,
   and it must not become a second hero: no card, no panel, no accent fill, no
   surface of its own. One hairline under the row is the entire chrome — the
   pedigree band above already draws the rule the two of them share, so this
   band carries no border-top and no background.

   Mono is on the FIGURES only (.hsb-fig), never on the words beside them: the
   .sctab-fig / .sltab-fig ration, applied a third time.

   The separator is a property of the SPACE between items, not of an item, so
   it is drawn on every item but the first and its margin equals the row gap —
   which is what puts the dot in the middle of the space rather than against
   the item it belongs to. When the row stacks at phone width the dots go. */
.home-statband{
  --hsb-gap:clamp(16px,2.4vw,30px);
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14);
  padding:clamp(15px,1.9vw,21px) 0;
}
.hsb-row{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;
  gap:8px var(--hsb-gap);list-style:none;margin:0;padding:0;
}
.hsb-item{
  display:inline-flex;align-items:baseline;gap:7px;
  font-family:var(--font-secondary);font-size:13px;letter-spacing:.02em;
  color:var(--se-text-caption);
}
.hsb-item+.hsb-item::before{
  content:"\00B7";margin-right:var(--hsb-gap);
  color:rgba(var(--se-border-teal-rgb),.55);
}
.hsb-fig{
  font-family:var(--font-mono);font-weight:600;font-size:14px;letter-spacing:.01em;
  color:var(--se-text-white);font-variant-numeric:tabular-nums;
}
/* The one item a reader can follow: it goes to the twenty-year timeline. Its
   underline is a hairline in the band's own border colour so the link reads as
   part of the band until it is hovered, and only then takes the accent. */
.hsb-link{
  display:inline-flex;align-items:baseline;gap:7px;color:inherit;text-decoration:none;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.34);padding-bottom:2px;
  transition:color var(--dur-fast) ease,border-color var(--dur-fast) ease;
}
.hsb-link .hsb-fig{transition:color var(--dur-fast) ease}
.hsb-link:hover{color:var(--se-text-secondary);border-bottom-color:var(--accent)}
.hsb-link:hover .hsb-fig{color:var(--accent)}
@media (prefers-reduced-motion:reduce){
  .hsb-link,.hsb-link .hsb-fig{transition:none}
}
/* Phone and small tablet: one figure per line, dots dropped. The engine is
   already still at these widths (motion.js declines to arm below 768px), so
   this is only the layout.
   MEASURED, not guessed: the row sets on ONE line from 690px up, and between
   641 and ~689 it wrapped onto a second line that STARTED WITH A SEPARATOR
   DOT — a dot with nothing before it. The break is at 700px, the same width
   .sctab and .sltab already break at, so the two-line state cannot occur. */
@media (max-width:700px){
  /* Left-aligned ON PURPOSE, not by default: a stacked column of five figures
     of different lengths reads as a spec list against a straight left edge,
     and that edge is the one the craft cards below already use. Centering it
     would rag both sides of a five-line block under a centred sentence. */
  .hsb-row{flex-direction:column;align-items:flex-start;gap:9px}
  .hsb-item+.hsb-item::before{content:none}
}

/* .soc2 removed with the badge, 2026-08-24 (Ross: "SOC2 tag should be removed
   from the page" — hero trust row and footer, both). The rules went with the
   markup rather than being left to style nothing. */

/* The period beside a short-term price. The other store rows carry a single
   figure; these are "$25 / 2 days", and the period must not read as loudly as
   the number. */
.store-per{font-size:13px;font-weight:400;color:var(--se-text-caption);letter-spacing:0}

/* ---------- Social proof ----------
   The live site scrolls these as a marquee. Still, here: a moving row reads as
   an advert, a still one reads as a fact — and a reader can actually take the
   names in. Seven fit one line at desktop; at 26px with a wide gap the seventh
   wrapped and Netflix sat alone, which reads as an afterthought, not a peer. */
.proof{border-top:1px solid rgba(var(--se-border-teal-rgb),.14);
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.14);
  background:linear-gradient(180deg,rgba(255,255,255,.018),transparent);
  padding:clamp(30px,3.6vw,42px) 0}
.proof-lead{margin:0 0 22px;text-align:center;font-family:var(--font-mono);
  font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--se-text-caption)}
.proof-logos{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:clamp(18px,2.6vw,38px)}
.proof-logos img{height:22px;width:auto;opacity:.72;filter:grayscale(1) brightness(1.7);
  transition:opacity var(--dur-fast) ease,filter var(--dur-fast) ease}
.proof-logos img:hover{opacity:1;filter:grayscale(0) brightness(1)}
/* the wordmarks carry different amounts of padding inside their own artwork */
.proof-logos img[alt="Netflix"]{height:19px}
.proof-logos img[alt="Warner Bros."]{height:26px}
.proof-credential{display:flex;align-items:center;justify-content:center;gap:12px;
  margin:26px 0 0;padding-top:22px;
  border-top:1px solid rgba(var(--se-border-teal-rgb),.10)}
.proof-credential img{height:17px;width:auto;opacity:.8;filter:grayscale(1) brightness(1.8)}
.proof-credential span{font-family:var(--font-secondary);font-size:13px;color:var(--se-text-dim)}
.proof-more{margin:18px 0 0;text-align:center;font-family:var(--font-secondary);font-size:13.5px}
.proof-more a{color:var(--accent-hover);font-weight:600}
.proof-more a:hover{color:var(--accent)}
@media (max-width:700px){
  .proof-logos img{height:18px}
  .proof-logos img[alt="Warner Bros."]{height:21px}
  .proof-credential{flex-direction:column;gap:8px;text-align:center}
}
@media (prefers-reduced-motion:reduce){.proof-logos img{transition:none}}

/* ================================================================
   SECTOR PAGE TEMPLATE — #/voiceover-adr (task T1, 2026-08-28)
   Three new blocks, in the order a performer reads them: the answer
   ("Made for you"), the toolkit ("Unlocking your potential"), the
   guides rail, then the proof. Set here rather than on the page so
   the three sibling sector pages can clone the markup unchanged.
================================================================ */

/* --- "Made for you": an editorial answer, not a card row ---------
   Deliberately NOT .grid-3. The section directly below it is a
   three-column matrix, and two card rows back to back read as one
   undifferentiated slab. A numbered rule-separated list gives the
   answer to the section's question the cadence of prose, and lets
   each block keep a readable 62ch measure instead of a 30ch column. */
.mf-q{max-width:30ch}
.mf-list{list-style:none;display:flex;flex-direction:column;
  border-top:1px solid rgba(var(--se-border-teal-rgb),.16)}
.mf-item{display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:clamp(20px,3.2vw,44px);align-items:start;
  padding:clamp(22px,2.6vw,34px) 0;
  border-bottom:1px solid rgba(var(--se-border-teal-rgb),.16)}
/* mono is rationed to NUMBER DATA — an index numeral qualifies */
.mf-n{font-family:var(--font-mono);font-size:clamp(26px,3.2vw,40px);font-weight:600;
  line-height:1;letter-spacing:-.02em;color:rgba(var(--accent-rgb),.45);
  min-width:2.4ch;padding-top:3px}
/* Title beside copy, not above it. Stacked, a 62ch measure left ~300px of the
   1080 wrap empty to the right of every row and the section read as a column
   floating in a wide band. Side by side, the row fills its width and the three
   titles share one axis, which is what makes a list of three read as a set. */
.mf-body{display:grid;grid-template-columns:minmax(0,15rem) minmax(0,1fr);
  gap:clamp(18px,2.6vw,38px);align-items:start}
.mf-body h3{font-size:clamp(19px,1.9vw,23px);font-weight:800;letter-spacing:-.015em;
  color:var(--se-text-white);line-height:1.25}
.mf-body p{font-size:16px;line-height:1.72;color:var(--se-text-dim);max-width:60ch}

/* --- "Unlocking your potential": the three-column matrix ---------
   One frame with column rules, not three floating cards: the copy
   calls it a matrix, and a shared frame is what makes three blocks
   read as one comparison rather than three offers. */
.uyp-matrix{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-2xl);
  overflow:hidden;
  background:linear-gradient(180deg,var(--se-frame) 0%,var(--se-inner) 100%)}
.uyp-col{padding:clamp(24px,2.6vw,32px);
  border-left:1px solid rgba(var(--se-border-teal-rgb),.18)}
.uyp-col:first-child{border-left:0}
.uyp-n{display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;border-radius:var(--r-sm);margin-bottom:16px;
  font-family:var(--font-mono);font-size:13px;font-weight:600;color:var(--accent);
  background:rgba(var(--accent-rgb),.10);border:1px solid rgba(var(--accent-rgb),.42)}
.uyp-h{font-size:19px;font-weight:800;letter-spacing:-.015em;
  color:var(--se-text-white);line-height:1.3;margin-bottom:12px}
.uyp-h a{color:inherit;text-decoration:underline;text-underline-offset:5px;
  text-decoration-thickness:1.5px;text-decoration-color:rgba(var(--accent-rgb),.6);
  transition:color var(--dur-fast) ease,text-decoration-color var(--dur-fast) ease}
.uyp-h a:hover{color:var(--accent);text-decoration-color:var(--accent)}
.uyp-col p{font-size:14.5px;line-height:1.7;color:var(--se-text-dim)}
.uyp-col p+p{margin-top:14px}
.uyp-col p b{color:var(--se-text-white);font-weight:700}

/* Round 4, stakeholder: "please adjust the content in the box with after paragraph
   spaces and icons". Columns 1 and 2 on all four sector pages split their single
   paragraph into one paragraph per bullet, each led by a 20px line-art glyph. Two
   columns of grid rather than a float or an inline SVG: the icon keeps its own
   column, so a paragraph that wraps to four lines stays flush against the text
   edge instead of tucking back under the glyph on line two.
   The gap between these paragraphs is wider than the plain .uyp-col p+p rule above
   (which still serves column 3's untouched two-paragraph copy) - that extra air IS
   the "after paragraph spaces" the note asks for.
   fill, stroke, stroke-width, stroke-linecap and stroke-linejoin are all INHERITED
   SVG presentation properties, so setting them on .uyp-i cascades into the <use>
   shadow instance the same way currentColor already does for the mo-digit numerals. */
.uyp-p{display:grid;grid-template-columns:20px minmax(0,1fr);gap:11px;align-items:start}
.uyp-col .uyp-p+.uyp-p{margin-top:18px}
.uyp-i{width:20px;height:20px;margin-top:2px;color:var(--accent);
  fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}

/* --- MOMENT: "The numbers draw themselves" (spec 2026-08-28, moments 7-10) ---
   One moment class, four deployments — built once here for Voiceover & ADR,
   cloned VERBATIM onto #page-audio-engineers, #page-musicians-composers and
   #page-education-facilities. Every rule below targets the mf- and uyp- class
   families the shared block above already serves all four sector pages, so a clone adds
   ZERO new CSS — only markup (see the recipe in the task report).

   Beat 1 — the Made-for-you numerals stroke-draw as each block reveals.
   .mf-list carries .mo-seq; each .mf-item carries .mo-reveal — MIGRATED OFF the
   legacy .reveal system (.reveal{opacity:0;...} applies unconditionally, not
   gated behind an armed state, so leaving it on an .mo-reveal element would
   hide the block forever outside the armed path — the Wave-2 lesson). Each
   numeral is an inline SVG composed from <use> pairs against the ten reusable
   digit symbols defined once, at the top of #page-voiceover-adr's markup (ids
   mo-digit-0..mo-digit-9). SVG ids are document-global, so every sector page's
   clone just writes <use href="#mo-digit-N"> against those SAME ids — nobody
   redeclares a digit path.

   Why the draw is pure CSS and not motion.js's own .mo-draw geometry: that
   engine measures stroke length via getTotalLength() and only ever looks at
   direct path/line/polyline/circle/ellipse/rect children of the .mo-draw
   element — a <use> clones its target into a shadow instance tree that
   querySelectorAll cannot see, so the engine finds zero drawable shapes and
   quietly leaves the numeral alone (harmless — it stays fully drawn — but
   inert). Its IntersectionObserver still adds .mo-in to the <svg class="mo-draw">
   itself on first crossing regardless of what was measured (motion.js does
   that unconditionally, before checking whether anything was found) — so this
   block hangs the actual draw off .mo-in with plain CSS, using the SVG2
   pathLength="1" attribute set on each digit's <path> (in the symbol) to
   normalize its stroke-dasharray math to exactly 1 unit no matter the path's
   real length. stroke-dasharray/stroke-dashoffset are inherited SVG
   properties, so setting them on <use> cascades into its cloned instance the
   same way currentColor already does for stroke colour. Verified rendering
   correctly through <use> in Chrome before shipping (see task report).

   Unarmed/no-JS/reduced-motion/mobile: every rule here is gated behind
   html.mo-armed, same law as the rest of the engine — with no class on <html>,
   stroke-dasharray is never set and every digit renders fully stroked
   immediately. The initial DOM is the destination. */
.mf-n svg.mo-num{display:block;height:1em;width:auto;
  stroke:currentColor;fill:none;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
html.mo-armed .mo-num use{
  stroke-dasharray:1;stroke-dashoffset:1;
  transition:stroke-dashoffset var(--mo-draw-dur,900ms) ease-out;
  transition-delay:var(--mo-delay,0ms);
}
html.mo-armed .mo-num.mo-in use{stroke-dashoffset:0}

/* Beat 2 — the capability matrix columns rise in sequence. .uyp-matrix
   carries .mo-seq; each .uyp-col carries .mo-reveal (same legacy-.reveal
   migration as beat 1 — the badge number stays plain text, unlike the
   Made-for-you numerals: the spec's draw treatment is for the numbered list
   only). No page-local CSS is needed for the rise itself — the shared engine
   rule (html.mo-armed .mo-reveal / .mo-reveal.mo-in, see "Motion engine
   (js/motion.js)" above) already does the opacity+translateY reveal with the
   .mo-seq-assigned --mo-delay stagger, the same zero-CSS idiom the Store's
   card grid already uses for #storeItems (moment 12). */

/* --- How-to rail ------------------------------------------------ */
.howto-head{margin-bottom:26px}
.howto-rail{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.howto-card{display:flex;flex-direction:column;gap:9px;
  padding:18px 18px 16px;border-radius:var(--r-lg);color:var(--se-text);
  border:1px solid rgba(var(--se-border-teal-rgb),.16);background:var(--se-frame);
  transition:border-color var(--dur-fast) ease,background var(--dur-fast) ease,
             transform var(--dur-fast) var(--ease-settle)}
.howto-card:hover{border-color:rgba(var(--accent-rgb),.45);background:var(--se-inner);
  color:var(--se-text);transform:translateY(-2px)}
.howto-kicker{display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  font-family:var(--font-secondary);font-size:10.5px;font-weight:600;
  letter-spacing:.13em;text-transform:uppercase;color:var(--accent)}
.howto-kicker em{font-style:normal;color:var(--se-text-caption);
  border-left:1px solid rgba(var(--se-border-teal-rgb),.4);padding-left:8px}
.howto-title{font-size:14.5px;font-weight:600;line-height:1.45;
  letter-spacing:-.005em;color:var(--se-text-white)}
.howto-go{margin-top:auto;padding-top:12px;font-family:var(--font-secondary);
  font-size:11.5px;letter-spacing:.04em;color:var(--se-text-caption)}
.howto-go::after{content:" \2192"}
.howto-card:hover .howto-go{color:var(--accent-hover)}
.howto-foot{margin-top:20px;font-size:13.5px;color:var(--se-text-caption)}

/* --- Featured case study + In Sessions episodes ------------------ */
.case-panel{display:grid;grid-template-columns:minmax(0,320px) minmax(0,1fr);
  gap:clamp(24px,3.2vw,44px);align-items:center;
  padding:clamp(24px,2.8vw,38px);
  border:1px solid rgba(var(--se-border-teal-rgb),.18);border-radius:var(--r-2xl);
  background:linear-gradient(150deg,rgba(var(--accent-rgb),.07) 0%,
             var(--se-frame) 42%,var(--se-inner) 100%)}
/* 1080x1094 natural. Capped well under 1x so it can never be upscaled. */
.case-media img{display:block;width:100%;height:auto;max-width:420px;
  border-radius:var(--r-xl);background:var(--se-deep);
  border:1px solid rgba(var(--se-border-teal-rgb),.18)}
.case-h{font-size:clamp(20px,2.1vw,26px);font-weight:800;letter-spacing:-.018em;
  line-height:1.28;color:var(--se-text-white);margin-bottom:14px;text-wrap:balance}
.case-h em{font-style:italic;color:var(--accent)}
.case-body p{font-size:15.5px;line-height:1.72;color:var(--se-text-dim);max-width:64ch}
.case-body p em{font-style:italic;color:var(--se-text-secondary)}
.case-go{display:inline-block;margin-top:18px;font-size:13.5px;font-weight:600}
.case-eps{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin-top:18px}
.case-ep{display:flex;flex-direction:column;gap:9px;padding:20px;color:var(--se-text);
  border-radius:var(--r-xl);border:1px solid rgba(var(--se-border-teal-rgb),.16);
  background:var(--se-frame);
  transition:border-color var(--dur-slow) ease,transform var(--dur-slow) var(--ease-settle)}
.case-ep:hover{border-color:rgba(var(--accent-rgb),.42);color:var(--se-text);
  transform:translateY(-3px)}
.case-ep-kicker{font-family:var(--font-secondary);font-size:10.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent)}
.case-ep-title{font-size:16px;font-weight:700;line-height:1.4;
  letter-spacing:-.01em;color:var(--se-text-white)}
.case-ep-go{margin-top:auto;padding-top:12px;font-family:var(--font-secondary);
  font-size:11.5px;letter-spacing:.04em;color:var(--se-text-caption)}
.case-ep-go::after{content:" \2192"}
.case-ep:hover .case-ep-go{color:var(--accent-hover)}

@media (max-width:900px){
  .uyp-matrix{grid-template-columns:1fr}
  .uyp-col{border-left:0;border-top:1px solid rgba(var(--se-border-teal-rgb),.18)}
  .uyp-col:first-child{border-top:0}
  .howto-rail{grid-template-columns:repeat(2,minmax(0,1fr))}
  .case-panel{grid-template-columns:1fr;justify-items:start}
  .case-media img{max-width:300px}
}
@media (max-width:900px){
  .mf-body{grid-template-columns:1fr;gap:9px}
}
@media (max-width:560px){
  .mf-item{grid-template-columns:1fr;gap:10px}
  .mf-n{font-size:22px;padding-top:0}
  .howto-rail{grid-template-columns:1fr}
  .case-eps{grid-template-columns:1fr}
  .case-media img{max-width:100%}
}
@media (prefers-reduced-motion:reduce){
  .howto-card,.case-ep,.uyp-h a{transition:none}
  .howto-card:hover,.case-ep:hover{transform:none}
}

/* ---------- Source-Connect hero: live UI over a chrome-only plate ----------
   The plate (ui-sc-compact-plate.webp) deliberately contains NO meter troughs
   and NO faders — modules.js builds both, so a control and its geometry cannot
   disagree. Everything here is positioned as a PERCENTAGE of the plate box, so
   it is resolution-independent and survives any render size.
   Scoped by .sc-hero; no other page has one. */
#page-source-connect .hero{overflow:hidden}          /* the tilted plane overhangs */
#page-source-connect .hero::after{
  /* the headline has to stay readable over a moving field — the home page does
     exactly this with #page-home .hero::after */
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(90deg,
    rgba(var(--se-bg-rgb),.94),rgba(var(--se-bg-rgb),.55) 42%,rgba(var(--se-bg-rgb),0) 64%);
}

/* the window FLOATS on the hero background — not a filled panel, so the hero's
   radial wash reads around and behind it */
.sc-hero{
  position:relative;display:block;line-height:0;isolation:isolate;
  border-radius:1.6%/1.7%;overflow:hidden;
  box-shadow:0 0 0 1px rgba(var(--se-border-teal-rgb),.16),0 30px 70px rgba(0,0,0,.45);
  will-change:transform;
}
.sc-hero img.sc-hero__plate{display:block;width:100%;height:auto}

.sc-hero__meter{
  position:absolute;overflow:hidden;border-radius:2px;background:#131A20;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.6),inset 0 0 0 1px rgba(255,255,255,.04);
}
.sc-hero__fill{
  position:absolute;inset:0 auto 0 0;width:0;will-change:width;
  background:linear-gradient(90deg,#78B944 0%,#8FCB4A 45%,#A7E163 74%,#CFE455 88%,#EBD44C 100%);
}
/* Segment gutters sit over the WHOLE meter, not just the fill — in the app the
   unlit part of the trough is segmented too. 100 segments, matched to the app
   (measured: ~3.4px period across a 336px meter). Percentage units keep the
   segment COUNT fixed at every render size instead of the segment WIDTH. */
.sc-hero__meter::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(90deg,
    rgba(0,0,0,0) 0,rgba(0,0,0,0) .70%,rgba(0,0,0,.55) .70%,rgba(0,0,0,.55) 1%);
}
.sc-hero__peak{position:absolute;top:1px;bottom:1px;width:2px;left:0;background:#F2E15C;opacity:.9;will-change:left}

/* A MUTED connection still shows its level — you can see the person is talking —
   but desaturated, because nothing is being transmitted. Exactly one connection
   is muted, and the plate carries the matching orange crossed-out microphone. */
.sc-hero__meter.is-muted .sc-hero__fill{filter:grayscale(1) brightness(.78)}
.sc-hero__meter.is-muted .sc-hero__peak{background:#9AA3A8;opacity:.75}

/* each row's faders sit INSIDE the card on their own groove, spanning the meter */
.sc-hero__fader{position:absolute}
.sc-hero__fader i{
  position:absolute;left:0;right:0;top:50%;height:3px;margin-top:-1.5px;border-radius:2px;
  background:rgba(0,0,0,.42);box-shadow:inset 0 1px 2px rgba(0,0,0,.6),0 1px 0 rgba(255,255,255,.055);
}
.sc-hero__thumb{
  position:absolute;top:50%;transform:translate(-50%,-50%);border-radius:2px;
  background:linear-gradient(180deg,#C6CBD0 0%,#A8AEB4 55%,#8E949A 100%);
  box-shadow:0 1px 2px rgba(0,0,0,.55);
}
.sc-hero__thumb::before{content:"";position:absolute;left:50%;top:18%;bottom:18%;width:1px;background:rgba(0,0,0,.28)}

.sc-hero__tc{
  position:absolute;display:flex;align-items:center;justify-content:center;
  font-family:var(--font-mono);font-weight:600;color:var(--se-text-secondary);
  letter-spacing:.04em;line-height:1;white-space:nowrap;
}
.sc-hero__dot{
  position:absolute;border-radius:50%;background:var(--se-selected);
  box-shadow:0 0 6px rgba(167,225,99,.55);animation:sc-hero-dot 1.6s ease-in-out infinite;
}
@keyframes sc-hero-dot{
  0%,100%{opacity:.55;box-shadow:0 0 4px rgba(167,225,99,.35)}
  50%    {opacity:1;  box-shadow:0 0 9px rgba(167,225,99,.75)}
}

/* Reduced motion is NONE, not less. The site-wide rule only shortens
   transitions, which would strand a meter mid-travel and leave the plane tilted
   at whatever angle it happened to hold. modules.js also stops the dot and never
   arms the plane; this is the no-JS fallback. */
@media (prefers-reduced-motion:reduce){
  .sc-hero__dot{animation:none;opacity:.9}
  .sc-hero,.js-herofield{transform:none!important}
}


/* ══════════════════════════════════════════════════════════════════════════
   /* ── UI-SHOT: native aspect, mirrored by side, centre stage flat ──
   ══════════════════════════════════════════════════════════════════════════
   Ross, 2026-09-21, three rulings on the product sections:

   1. "treated these as UI native aspect ratio. Like, mute-on is the only one
      that looks natural" — the frame above declares `aspect-ratio:1/1` with
      `object-fit:cover`, so every product was cover-cropped into a square.
      Mute-On only looked right because its window IS ~1:1 (1.024). The three
      declarations below are NOT new: they are this file's own STACKED
      behaviour from the narrow-width media query, promoted to every width.

   2. "should be alternating angle planes depending on which page side they
      are on, e,g, review should be facing inwards towards page centre" — one
      absolute `--tiltY:-19deg` reads as INWARD on the right of the centreline
      and OUTWARD on the left. `.showcase.flip` above already solves this and
      mirrors THREE things: the tilt, the image's shadow direction, and the
      perspective origin. It was only ever wired to `.showcase`; five of the
      six shots live in `.wrap.split`, where the shot is the first child when
      it sits on the left. So the same rules simply gain that selector — no
      second mechanism.

   3. "The centred image ... should not have a tilt one way or another
      (centred and elevated above)" — the shot inside `.session-line` has no
      side to face away from, so it sits square on and is lifted instead.
   ══════════════════════════════════════════════════════════════════════════ */
.ui-shot__frame{height:auto}
.ui-shot__frame img{height:auto;width:100%;aspect-ratio:auto;max-width:none}

/* the LEFT-hand shot of a split row joins the existing flip mirror */
.wrap.split > *:first-child .ui-shot__frame{--tiltY:19deg;--tiltZ:-1.2deg}
.wrap.split > *:first-child .ui-shot__frame img{
  box-shadow:-46px 54px 100px rgba(0,0,0,.6),-8px 10px 24px rgba(0,0,0,.5),0 0 0 1px rgba(0,0,0,.5);
}
.wrap.split > *:first-child .ui-shot{perspective-origin:64% 46%}

/* the centre stage: square on, lifted, shadow straight down rather than to
   either side — a mirrored shadow here would imply a side it does not have */
.session-line .ui-shot{perspective-origin:50% 46%}
.session-line .ui-shot__frame{--tiltY:0deg;--tiltX:0deg;--tiltZ:0deg;transform:translateY(-14px)}
.session-line .ui-shot__frame img{
  box-shadow:0 60px 110px rgba(0,0,0,.62),0 14px 30px rgba(0,0,0,.5),0 0 0 1px rgba(0,0,0,.5);
}


/* ══════════════════════════════════════════════════════════════════════════
   /* -- SC craft-card hover, promoted to the square product cards --
   ══════════════════════════════════════════════════════════════════════════
   Sept-15 stakeholder note: "Section 'The best platform for remote recording',
   animate on hover the graphics as it encourages people to investigate."

   This is NOT a new motion. `.craft` cards already carry a proven hover:
   the card lifts 5px and takes an accent border, the media scales to 1.04 over
   .45s on cubic-bezier(.2,.7,.3,1), and a reduced-motion block cancels all of
   it. The eight cards in that section use `.card` + `.card-media--square`
   instead, so they simply inherit the SAME values -- one motion vocabulary on
   the page, not two.

   Scoped to cards that CONTAIN a square media, so the generic `.card` used
   elsewhere (the Nexus grid, support) is unaffected unless it opts in by
   carrying that element.
   ══════════════════════════════════════════════════════════════════════════ */
.card:has(.card-media--square){transition:transform .45s cubic-bezier(.2,.7,.3,1),
  border-color .45s cubic-bezier(.2,.7,.3,1),box-shadow .45s cubic-bezier(.2,.7,.3,1)}
.card .card-media--square{transition:transform .45s cubic-bezier(.2,.7,.3,1)}
.card:has(.card-media--square):hover{transform:translateY(-5px);
  border-color:rgba(var(--accent-rgb),.6)}
.card:has(.card-media--square):hover .card-media--square{transform:scale(1.04)}

@media (prefers-reduced-motion:reduce){
  .card:has(.card-media--square):hover{transform:none}
  .card:has(.card-media--square):hover .card-media--square{transform:none}
  .card:has(.card-media--square),
  .card .card-media--square{transition:none}
}

/* ---------- Home hero: THE FAMILY SEQUENCE (js/hero-family.js, 2026-09-25) ----------
   One camera over one fixed cluster of the typed product interfaces. The stage
   grows to take roughly half the hero (the storyboard: 460px is small for a
   family); on phones it moves ABOVE the lede, or the first 15 s would play off
   screen (measured: the old panel started at y=650 of 844). The tape (.hf-field)
   is the take as a recorder writes it; it runs in a band just under the stage,
   positioned by the script from the stage's own box. */
#page-home .hero-family .wrap{max-width:1320px;grid-template-columns:.8fr 1.2fr;gap:clamp(28px,4vw,56px)}
.hero-family .hf-field{-webkit-mask:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
#page-home .hero-family::after{background:linear-gradient(90deg,rgba(var(--se-bg-rgb),.86),rgba(var(--se-bg-rgb),.35) 40%,rgba(var(--se-bg-rgb),0) 58%)}
.hf{position:relative;margin-bottom:118px}
/* Hero copy and poster paint together; generic entrance tweens are not film frames. */
.hero-family .reveal{opacity:1;transform:none;transition:none}
.hf-view{position:relative;aspect-ratio:16/10;overflow:clip;border-radius:14px;
  background:radial-gradient(120% 90% at 50% 40%,rgba(var(--se-border-teal-rgb),.07),transparent 70%),var(--se-bg);
  box-shadow:inset 0 0 0 1px rgba(var(--se-border-teal-rgb),.14)}
.hf-poster{position:absolute;inset:0;background:url(../assets/hero/family-poster.webp) center/contain no-repeat}
.hf-poster.hf-poster--world{inset:auto;background-size:100% 100%;transition:none}
.hf-world{position:absolute;left:0;top:0;transform-origin:0 0;visibility:hidden;pointer-events:none}
.hf.is-ready .hf-world{visibility:visible}
.hf-win{position:absolute;border-radius:12px}
.hf-f{display:block;border:0;background:transparent;opacity:0;transition:none}
.hf-win.is-live .hf-f{opacity:1}
.hf.is-settled .hf-win .hf-f{opacity:0;transition:none}
/* the inline stand-ins are always there (the poster draws them too) */
.hf-win::after{content:"";position:absolute;inset:-8px;border-radius:16px;pointer-events:none;opacity:var(--wake,0);box-shadow:0 0 28px rgba(197,232,108,.45)}
.hf-win.is-waking::after{animation:none}
@keyframes hf-wake{
  0%{opacity:0;box-shadow:0 0 0 0 rgba(197,232,108,0)}
  16%{opacity:1;box-shadow:0 0 0 9px rgba(197,232,108,.55),0 0 70px 18px rgba(197,232,108,.22)}
  100%{opacity:0;box-shadow:0 0 0 20px rgba(197,232,108,0),0 0 70px 18px rgba(197,232,108,0)}}
/* the two stand-in cards, at their WORLD size (600px wide), in the site's own grammar */
.hf-card{box-sizing:border-box;height:100%;display:flex;flex-direction:column;border-radius:12px;
  background:var(--se-frame);border:5px solid var(--se-bg);box-shadow:0 18px 50px rgba(0,0,0,.45);
  font-family:var(--font-mono);color:var(--se-text);overflow:hidden}
.hf-card__head{display:flex;align-items:center;gap:14px;padding:18px 22px;font-size:15px;letter-spacing:.14em;
  color:rgba(249,249,249,.62);border-bottom:1px solid rgba(255,255,255,.07)}
.hf-card__head b{color:var(--se-text);font-weight:600}
.hf-card__dot{width:11px;height:11px;border-radius:3px;background:#A7E163;box-shadow:0 0 12px rgba(167,225,99,.7)}
.hf-sp{flex:1}
.hf-card__body{flex:1;margin:18px 22px;border-radius:8px;background:var(--se-inner);box-shadow:inset 0 2px 8px rgba(0,0,0,.35);
  display:flex;flex-direction:column;justify-content:center;gap:22px;padding:26px 28px;min-height:0}
.hf-card__chips{display:flex;gap:10px;padding:0 22px 20px;font-size:13px;letter-spacing:.12em}
.hf-card__chips span{border:1px solid rgba(255,255,255,.16);border-radius:999px;padding:6px 12px;color:rgba(249,249,249,.72)}
.hf-card__chips .is-accent{border-color:rgba(167,225,99,.5);color:#C5E86C}
.hf-live__row{display:flex;align-items:baseline;justify-content:space-between;gap:16px}
.hf-live__lbl{font-size:14px;letter-spacing:.14em;color:rgba(249,249,249,.62)}
.hf-live__tc{font-size:34px;font-weight:600;letter-spacing:.06em;font-variant-numeric:tabular-nums}
.hf-live__lock{display:inline-flex;align-items:center;gap:10px;font-size:15px;letter-spacing:.16em;color:rgba(249,249,249,.35);transition:none}
.hf-live__lock i{width:10px;height:10px;border-radius:3px;background:rgba(249,249,249,.25);transition:none}
.hf-live.is-locked .hf-live__lock{color:#A7E163}
.hf-live.is-locked .hf-live__lock i{background:#A7E163;box-shadow:0 0 0 6px rgba(167,225,99,0),0 0 14px rgba(167,225,99,.8)}
.hf-live:not(.is-locked) .hf-live__tc[data-tc="dest"]{color:#E8EB58}
.hf-rec__wave{width:100%;height:100%;min-height:0}
.hf-rec__wave path{stroke:#A7E163;stroke-width:4.5;stroke-linecap:round;opacity:.85}
/* THE ONLY CHROME: one Pause / Play / Replay control (WCAG 2.2.2) */
/* The optional caption sits below the image, in the existing tape margin;
   it never moves the copy or covers the product controls. No private clock. */
.hf-caption{position:absolute;top:calc(100% + 12px);left:0;right:0;text-align:center;
  font:600 14px/1.5 var(--font-primary);color:var(--se-text);pointer-events:none}
.hf-caption[hidden],.hf-caption [hidden]{display:none}
/* The optional reduced-motion reading list follows the poster and its static
   tape band in normal flow. It cannot overlay the copy or clip on zoom. */
.hf-rm-story{margin-top:112px;color:var(--se-text);font:400 1rem/1.6 var(--font-primary)}
.hf-rm-story[hidden]{display:none}
.hf-rm-story h2{margin:0 0 .75rem;font-size:1.125rem;line-height:1.4}
.hf-rm-story ol{margin:0;padding-inline-start:1.5em}
.hf-rm-story li+li{margin-top:.35em}

.hf-ctl{position:absolute;right:10px;bottom:10px;z-index:4;display:inline-flex;align-items:center;gap:6px;
  padding:6px 12px 6px 9px;border-radius:999px;border:1px solid rgba(255,255,255,.2);background:rgba(20,24,27,.82);
  color:var(--se-text);font:600 12px/1 var(--font-primary);letter-spacing:.02em;cursor:pointer;
  transition:none}
.hf-ctl[hidden]{display:none}
.hf-ctl:hover{border-color:rgba(var(--accent-rgb),.65);background:rgba(20,24,27,.95)}
.hf-ctl:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}
.hf-ctl__i{width:13px;height:13px;fill:currentColor;display:none}
.hf-ctl[data-state="pause"] .hf-ctl__i--pause,.hf-ctl:not([data-state]) .hf-ctl__i--pause,
.hf-ctl[data-state="play"] .hf-ctl__i--play,.hf-ctl[data-state="replay"] .hf-ctl__i--replay{display:block}
@media (max-width:1020px){
  /* one column: the stage goes UNDER THE H1 and ABOVE THE LEDE */
  .hero-family .hf-copy{display:contents}
  .hero-family .wrap > .hf-copy > .eyebrow{order:1}
  .hero-family .wrap > .hf-copy > h1{order:2}
  .hero-family .wrap > .hf,.hero-family .wrap > .hf-copy > .hf{order:3}
  .hero-family .wrap > .lede,.hero-family .wrap > .hf-copy > .lede{order:4}
  .hero-family .wrap > .btn-row,.hero-family .wrap > .hf-copy > .btn-row{order:5}
  .hero-family .wrap > .cta-note,.hero-family .wrap > .hf-copy > .cta-note{order:6}
  .hero-family .wrap > .trust-row,.hero-family .wrap > .hf-copy > .trust-row{order:7}
  #page-home .hero-family .wrap{grid-template-columns:1fr;row-gap:0}
  .hero-family .wrap > .hf-copy > .eyebrow,.hero-family .wrap > .hf-copy > h1{margin-bottom:22px}
  .hero-family .wrap > .lede,.hero-family .wrap > .hf-copy > .lede{margin-top:0}
  .hf{margin-bottom:96px}
  .hf-caption{top:calc(100% + 72px)}
  .hf-rm-story{margin-top:80px}
  #page-home .hero-family::after{background:none}
}
@media (max-width:640px){
  .hf-view{aspect-ratio:6/5}
  .hf{margin-bottom:100px}
  .hf-ctl{right:8px;bottom:8px}
}

/* Active caption variants reserve space below the entire tape, at every width. */
.hf.has-captions{margin-bottom:calc(var(--hf-caption-top) + 3rem)}
.hf.has-captions .hf-caption{top:calc(100% + var(--hf-caption-top))}

/* /landing/nexusz830fjdhs932oe/ — its e-mail pop-up keeps the stylesheet it
   arrived with (standalone.py carries it over), and that sheet greys its
   label, placeholder, legal line and close button with #6E7378: 2.6-2.95:1,
   failing AA. These lift them to the site's AA tokens, and give the field the
   site's keyboard focus ring, which its outline:none had taken away. */
#main .modal-card .modal-field label,
#main .modal-card .modal-legal,
#main .modal-card .modal-close{color:var(--se-text-dim)}
#main .modal-card .modal-field input::placeholder{color:var(--se-a11y-muted)}
#main .modal-card .modal-field input:focus-visible{outline:2px solid var(--se-focus);outline-offset:2px}

/* ============================================================
   THE START-FOR-FREE POP-UP (sf-) — js/start-free.js
   Moved here from an inline <style> on the home page when the dialog became
   shared: every link with data-start-free opens it, on any page. Values are
   unchanged from the home page's AA-fixed version (2026-10, the forms pass);
   the centring and text colour come from the `dialog{}` rule at the top of
   this file. Every rule is scoped under .sf-dialog, and the field classes are
   sf-* rather than the contact form's lf-*: page sheets load AFTER this one
   (seforms.css on /contact/, /about-us/, /labs/ has unscoped .lf-* rules), so
   an unscoped or lf-named rule here would lose ties to them.
   ============================================================ */
.sf-backdrop{position:fixed;inset:0;z-index:9998;background:rgba(10,10,10,.6)}
.sf-dialog{border:0;padding:0;background:transparent;max-width:min(460px,calc(100vw - 32px));
  width:100%;max-height:calc(100vh - 40px);overflow:auto;box-sizing:border-box;
  /* This is intentionally a regular stacking context, rather than a native
     `showModal()` top-layer dialog. Google appends its visual reCAPTCHA
     challenge to <body>; keeping this under that challenge makes it clickable. */
  position:fixed;inset:0;z-index:9999;
  /* the site face, not the page's: the story/news sheets set their own body
     font stack, and a dialog inherits from <body> */
  font-family:var(--font-primary)}
.sf-dialog form{
  background:var(--se-frame);border:5px solid var(--se-bg);border-radius:var(--r-xl);
  box-shadow:0 0 0 1px rgba(var(--se-border-teal-rgb),.16),0 24px 60px rgba(0,0,0,.45);
  padding:22px 22px 24px;box-sizing:border-box
}
.sf-dialog .sf-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:6px}
.sf-dialog .sf-title{margin:0;font-size:22px}
.sf-dialog .sf-close{flex:none;width:34px;height:34px;display:flex;align-items:center;justify-content:center;
  background:none;border:1px solid rgba(var(--se-border-teal-rgb),.3);border-radius:var(--r-md);
  color:var(--se-text-secondary);cursor:pointer}
.sf-dialog .sf-close:hover{color:var(--se-text-white);border-color:rgba(var(--se-border-teal-rgb),.55)}
.sf-dialog .sf-body{margin:14px 0 4px}
.sf-dialog .sf-lede{margin:0 0 14px;color:var(--se-text-secondary);font-size:14.5px}
.sf-dialog .sf-group{display:flex;flex-direction:column;gap:8px;margin-bottom:4px}
.sf-dialog .sf-group label{font-size:14px;font-weight:600;color:var(--se-text-white)}
.sf-dialog .sf-group .req{color:var(--accent);font-weight:700}
/* field, placeholder, error and hint match seforms.css (the /contact/ form):
   same face, same 46px field, and colours that pass AA on this --se-frame
   panel — the hint's caption grey was 4.31:1, the red 3.89:1, and the
   unstyled placeholder the browser's own #757575 at 3.07:1 */
.sf-dialog input[type=email]{
  width:100%;box-sizing:border-box;background:var(--se-bg);color:var(--se-text-white);
  border:1px solid rgba(var(--se-border-teal-rgb),.3);border-radius:var(--r-md);
  padding:13px 15px;font-family:var(--font-secondary);font-size:15px
}
.sf-dialog input[type=email]::placeholder{color:var(--se-text-caption)}
.sf-dialog input[aria-invalid=true]{border-color:#ec8a75}
.sf-dialog .sf-error{display:block;margin-top:6px;font-size:12.5px;color:#ec8a75;min-height:1em}
.sf-dialog .sf-hint{margin:12px 0 0;font-size:13px;color:var(--se-text-dim);max-width:52ch}
.sf-dialog .sf-hint a{color:var(--accent)}
.sf-dialog .sf-status{font-size:14px;color:var(--accent);margin:12px 0 0;min-height:1em}
.sf-dialog .sf-actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:16px}
/* The Terms / Log-in lines: small and secondary, but on --se-frame they use
   --se-text-dim (the hint's AA-fixed grey) and underlined --se-text-secondary
   links, never the page's .legal-line --se-a11y-muted, which is tuned for
   --se-bg. Left-aligned like everything else in this dialog. */
.sf-dialog .sf-legal{margin-top:18px}
.sf-dialog .sf-legal[hidden]{display:none}
.sf-dialog .sf-legal p{margin:0;font-size:12.5px;line-height:1.5;color:var(--se-text-dim)}
.sf-dialog .sf-legal p + p{margin-top:8px}
.sf-dialog .sf-legal a{color:var(--se-text-secondary);text-decoration:underline;text-underline-offset:2px}
.sf-dialog .sf-legal a:hover{color:var(--se-text-white)}
.sf-dialog .sf-legal a:focus-visible{outline:2px solid var(--se-focus);outline-offset:3px;border-radius:2px}
.sf-dialog .sf-out{margin-top:20px;padding-top:18px;border-top:1px solid rgba(var(--se-border-teal-rgb),.2)}
.sf-dialog .sf-thanks{margin:0 0 14px;font-size:14.5px;color:var(--se-text-secondary)}
.sf-dialog .sf-out label{display:block;font-size:13px;font-weight:600;color:var(--se-text-white);margin-bottom:8px}
.sf-dialog .sf-out textarea{width:100%;box-sizing:border-box;font-family:var(--font-mono);font-size:13px;
  background:var(--se-bg);color:var(--se-text-secondary);border:1px solid rgba(var(--se-border-teal-rgb),.24);
  border-radius:var(--r-md);padding:10px 12px;resize:vertical}
.sf-dialog .sf-out .btn-row{margin-top:12px;display:flex;flex-wrap:wrap;gap:10px}
.sf-dialog .sf-actions--done{margin-top:14px}
@media (prefers-reduced-motion: no-preference){
  .sf-dialog[open]{animation:sf-in .18s ease}
  @keyframes sf-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
}
