/* ── KRYONEX SHARED STYLES ───────────────────────────────────────────────
   One stylesheet for all pages. Linked via <link rel="stylesheet" href="./kryonex.css">
   inside each page's <helmet> (dc-runtime clones <link> into <head>; support.js:1332).
   Edit the design system ONCE here instead of per-page inline copies. */

*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
html,body{margin:0;padding:0;background:var(--kx-bg);}
body{color:var(--kx-fg);font-family:'Sora',sans-serif;-webkit-font-smoothing:antialiased;overflow-x:clip;}
::selection{background:var(--kx-orange);color:var(--kx-bg);}
a{color:inherit;text-decoration:none;}
input,textarea{font-family:'Sora',sans-serif;}

@keyframes kx-in{from{opacity:0;transform:translateY(26px);}to{opacity:1;transform:none;}}
@keyframes kx-bar{0%,100%{transform:scaleY(.8);}50%{transform:scaleY(1);}}
@keyframes kx-blink{0%,100%{opacity:.2;}50%{opacity:1;}}
@keyframes kx-pulse{0%,100%{opacity:.5;transform:scale(1);}50%{opacity:1;transform:scale(1.14);}}
@keyframes kx-cue{0%,100%{transform:translateY(0);opacity:.5;}50%{transform:translateY(8px);opacity:1;}}
@keyframes kx-menu-in{from{opacity:0;transform:translateY(-12px);}to{opacity:1;transform:none;}}

.kx-hamburger{display:none;}
.kx-bar{display:block;width:20px;height:2px;background:var(--kx-fg);border-radius:2px;transition:transform .28s cubic-bezier(.4,0,.2,1),opacity .18s ease;}
.kx-hamburger[data-open="true"] .kx-bar:nth-child(1){transform:translateY(7px) rotate(45deg);}
.kx-hamburger[data-open="true"] .kx-bar:nth-child(2){opacity:0;}
.kx-hamburger[data-open="true"] .kx-bar:nth-child(3){transform:translateY(-7px) rotate(-45deg);}

@media (max-width:768px){
  .kx-nav-desktop{display:none !important;}
  .kx-hamburger{display:inline-flex !important;}
}
@media (max-width:900px){
  .kx-split{grid-template-columns:1fr !important;}
  .kx-split-3d{min-height:46vh !important;}
  .kx-bento{grid-template-columns:1fr !important;grid-auto-rows:auto !important;}
  /* The cards are flex columns with justify-content:space-between, and with 2 children that means
     "separation == free space". The flagship is sized for a TWO-ROW slot (426px), where ~90px of free
     space becomes a comfortable gap; the line above collapses it to one auto row, free space drops to
     2px, and the "// in practice" box slams into the last line of the paragraph. gap is a MINIMUM, and
     space-between subtracts it before distributing — so separation stays (free - gap) + gap = free
     wherever free space already exceeds it. It only bites where the collision is. */
  .kx-bento > div{grid-column:auto !important;grid-row:auto !important;min-height:168px;gap:18px;}
}
/* "[ 01 ]" is 6 chars of JetBrains Mono at 11px with .1em tracking = 46.2px, and the mobile
   .kx-inc-row gives its column 44px — so it wrapped, dropping the "]" onto a second line. The 2px
   overflow lands in the 20px column gap. Declared here rather than in the six services-*.dc.html
   <style> blocks that define .kx-inc-row: white-space is a property none of them set, so cascade
   order between this file and the page's inline block is irrelevant. */
.kx-inc-row > span:first-child{white-space:nowrap;}

/* ── DESIGN SYSTEM ──────────────────────────────────────────────────────
   Change the glass look in ONE place: .kx-glass / --kx-glass-o / --kx-glass-b. */
:root{
  --kx-orange:#FF5500;--kx-orange-hi:#FF7A33;--kx-orange-read:#FF7A33;--kx-blue:#2E9BFF;
  --kx-bg:#09090B;--kx-fg:#FAFAFA;--kx-fg-2:#D4D4D8;--kx-muted:#B3B3BC;--kx-dim:#94949E;
  --kx-surface:#18181B;--kx-border:#27272A;--kx-border-hi:#3F3F46;--kx-hair:rgba(var(--kx-overlay-rgb),.1);
  /* rgb triplets: every alpha-varying fill references one of these, so light mode flips them all in one place (see [data-theme="light"]). muted/dim raised from #A1A1AA/#808089 for AA contrast. */
  --kx-overlay-rgb:255,255,255;--kx-bg-rgb:9,9,11;--kx-surface-rgb:24,24,27;--kx-orange-rgb:255,85,0;--kx-blue-rgb:46,155,255;
  --kx-glass-o:.055;              /* light-glass tint opacity; CMS theme may override */
  --kx-glass-b:24px;              /* glass blur radius;      CMS theme may override */
}
/* Component classes — the canonical glass/button styling.
   The blur is BACK. It was killed site-wide on Jul 9 as "the dominant Safari/Arc compositor cost and the
   WebGL crash trigger". That was wrong: the reference build (kryonex-labs.github.io) composites 34 live
   blurs alongside an UNCAPPED 11k-particle orb at DPR 1.5 with MSAA on, and never freezes in any browser.
   The freeze was a kill switch in kx-app.js, not the glass. We gave up the design for a phantom. */
.kx-glass{background:rgba(var(--kx-overlay-rgb),var(--kx-glass-o));backdrop-filter:blur(var(--kx-glass-b)) saturate(1.3);-webkit-backdrop-filter:blur(var(--kx-glass-b)) saturate(1.3);border:1px solid var(--kx-hair);box-shadow:inset 0 0 0 1px rgba(var(--kx-overlay-rgb),.04);}
.kx-glass-dark{background:rgba(var(--kx-surface-rgb),.85);border:1px solid var(--kx-hair);}
/* Persistent-orb shell (kx-nav.js SPA): the orb canvas + noise live at body level so a client-side
   page swap never unmounts them. On inner pages this scrim dims the orb to a calm ambient ground so
   dense content stays readable; on home it's transparent (the hero mark is the feature). kx-nav (and a
   synchronous head script for hard-loads) toggles html.kx-inner. */
#kx-orb-dim{position:fixed;inset:0;z-index:2;pointer-events:none;background:rgb(var(--kx-bg-rgb));opacity:0;transition:opacity .45s ease;}
html.kx-inner #kx-orb-dim{opacity:.6;}
/* Light: the salmon mark strokes read louder against the near-black headline than the dark mark does on
   dark, and a light scrim lightens less than a dark scrim darkens — so hold the mark further back. (Fable) */
html.kx-inner[data-theme="light"] #kx-orb-dim{opacity:.75;}
/* A post page is eight minutes of sustained reading — 11,000 drifting particles behind it is not
   ambience, it's competition. Push the scrim further than the .6/.75 inner pages get. Deliberately the
   SCRIM and not a pause/unmount: the orb keeps its SPA persistence and we never touch its runtime.
   The room doesn't go dark when you open a book; the lights just come down. (Fable) */
html.kx-read #kx-orb-dim{opacity:.85;}
html.kx-read[data-theme="light"] #kx-orb-dim{opacity:.92;}

.kx-btn-primary{background:var(--kx-orange);color:var(--kx-bg);}
.kx-btn-primary:hover{background:var(--kx-orange-hi);}

/* ── ARTICLE (blog-post.dc.html) ─────────────────────────────────────────────
   Long-form reading is a new mode for this site, and the marketing type does not survive it: 13.5px
   muted over 1,200 words is fatiguing, and a 1200px container gives lines nobody can read. So a
   ~68ch measure (about.dc.html already proves the idea at 62ch), body one step larger and one step
   brighter, and NO serif — a fourth family would be the first crack in a very disciplined system.
   Everything here is scoped to .kx-article so it cannot leak into the marketing pages. */
.kx-article{max-width:68ch;margin:0 auto;font-size:17px;line-height:1.75;color:var(--kx-fg-2);}
.kx-article > *:first-child{margin-top:0;}
.kx-article p{margin:0 0 1.25em;}
.kx-article h2{font-family:'Space Grotesk';font-weight:600;font-size:26px;letter-spacing:-.015em;line-height:1.25;color:var(--kx-fg);
  margin:2.2em 0 .7em;padding-top:1.4em;border-top:1px solid var(--kx-border);}
.kx-article h3{font-family:'Space Grotesk';font-weight:600;font-size:19px;color:var(--kx-fg);margin:1.8em 0 .5em;}
.kx-article ul,.kx-article ol{margin:0 0 1.25em;padding-left:1.3em;}
.kx-article li{margin:.35em 0;}
.kx-article strong{color:var(--kx-fg);font-weight:600;}
/* The site sets a{text-decoration:none} globally, which makes an in-article link invisible. This is the
   one place the site should underline. --kx-orange-read is the accessible accent (it flips to #E64A00
   in light mode) and exists for exactly this. */
.kx-article a{color:var(--kx-orange-read);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;}
.kx-article a:hover{color:var(--kx-orange);}
.kx-article blockquote{margin:1.6em 0;padding:.2em 0 .2em 18px;border-left:2px solid var(--kx-orange);color:var(--kx-fg-2);}
.kx-article blockquote p:last-child{margin-bottom:0;}
/* Code may break out past the prose measure — code lines are long, and horizontal scrolling at 68ch is
   constant irritation. No syntax highlighting: a rainbow theme would demolish the one-accent rule on
   the most-read pages on the site. */
.kx-article pre{width:min(780px,92vw);margin:1.6em 0 1.6em calc((68ch - min(780px,92vw)) / 2);
  background:rgba(var(--kx-bg-rgb),.8);border:1px solid var(--kx-border);border-radius:4px;
  padding:16px 18px;overflow-x:auto;}
.kx-article pre code{font-family:'JetBrains Mono',monospace;font-size:13px;line-height:1.65;color:var(--kx-fg-2);background:none;border:none;padding:0;}
.kx-article :not(pre) > code{font-family:'JetBrains Mono',monospace;font-size:.9em;background:var(--kx-surface);
  border:1px solid var(--kx-border);border-radius:3px;padding:1px 5px;color:var(--kx-fg);}
.kx-article table{width:100%;border-collapse:collapse;margin:1.6em 0;font-size:14px;}
.kx-article th,.kx-article td{border:1px solid var(--kx-border);padding:8px 12px;text-align:left;}
.kx-article th{font-family:'JetBrains Mono';font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--kx-muted);}
.kx-article img{max-width:100%;height:auto;border-radius:4px;}
@media (max-width:700px){
  .kx-article{font-size:16px;}
  .kx-article pre{width:100%;margin-left:0;}
}

/* ── SERVICES HOVER STRIP (Header.dc.html) ───────────────────────────────────
   Hovering "Services" unfolds the six services as ONE horizontal line under the
   sticky header; clicking "Services" navigates to /services. Reads as a line, not
   a dialog: full-width, two hairlines, no radius, no shadow, no fill per item.
   Resolves against the sticky <header> (the nav + Services item are position:static,
   so absolute climbs to the header). Killed < 1024px — Services is then a plain link;
   the /services hub and the mobile accordion both still enumerate the six. */
.kx-svc-strip{position:absolute;top:100%;left:0;right:0;z-index:60;background:var(--kx-bg);border-top:1px solid var(--kx-hair);border-bottom:1px solid var(--kx-hair);overflow:hidden;animation:kx-menu-in .2s cubic-bezier(.2,.7,.2,1) both;}
.kx-svc-strip-inner{max-width:1312px;margin:0 auto;height:52px;display:flex;align-items:stretch;justify-content:space-between;padding:0 clamp(20px,5vw,64px);}
.kx-svc-item{position:relative;display:flex;align-items:center;gap:9px;padding:0 clamp(8px,1.3vw,18px);white-space:nowrap;}
.kx-svc-item + .kx-svc-item{border-left:1px solid var(--kx-hair);}
.kx-svc-item .kx-svc-idx{font-family:'JetBrains Mono';font-size:11px;color:var(--kx-dim);transition:color .12s ease;}
.kx-svc-item .kx-svc-lbl{font-family:'Sora';font-size:13.5px;color:var(--kx-fg-2);transition:color .12s ease;}
.kx-svc-item::after{content:"";position:absolute;left:clamp(8px,1.3vw,18px);right:clamp(8px,1.3vw,18px);bottom:0;height:1px;background:var(--kx-orange);transform:scaleX(0);transform-origin:left;transition:transform .12s ease;}
.kx-svc-item:hover .kx-svc-idx{color:var(--kx-orange);}
.kx-svc-item:hover .kx-svc-lbl{color:var(--kx-fg);}
.kx-svc-item:hover::after{transform:scaleX(1);}
@media (max-width:1024px){.kx-svc-strip{display:none;}}

/* ── LIGHT THEME ────────────────────────────────────────────────────────────
   Flip the tokens + rgb-triplets so every alpha fill inverts from ONE place
   (the site's colours are token/triplet-driven after Phase C). What stays put:
   --kx-orange-rgb keeps its bright 255,85,0 so the decorative radial glows read
   on the light ground; --kx-orange itself deepens to #E64A00 so SOLID orange
   (small mono labels, links, metric numerals, buttons) clears text contrast on
   white — the split the plan calls for, achieved via the existing colour-vs-rgb
   token split with no per-file sweep. The ORB recolours separately in kx-app.js
   (Phase J). No toggle yet — verify by setting <html data-theme="light">. */
:root[data-theme="light"]{
  --kx-orange:#E64A00;--kx-orange-hi:#C43F00;--kx-orange-read:#E64A00;--kx-blue:#1A73E6;
  --kx-bg:#FAFAF9;--kx-fg:#18181B;--kx-fg-2:#3F3F46;--kx-muted:#52525B;--kx-dim:#71717A;
  --kx-surface:#FFFFFF;--kx-border:#E4E4E7;--kx-border-hi:#D4D4D8;--kx-hair:rgba(0,0,0,.08);
  --kx-overlay-rgb:0,0,0;--kx-bg-rgb:250,250,249;--kx-surface-rgb:255,255,255;--kx-blue-rgb:26,115,230;
}
/* These two override the HAIRLINE TOKEN, never the `border` property — and that is load-bearing, not
   style. dc-runtime compiles style-hover="border-color:…" into a generated rule `.scpN:hover`, whose
   specificity is (0,2,0). A `:root[data-theme="light"] .kx-glass` rule is (0,3,0), so if it declares
   `border` (a shorthand, which re-asserts border-color) it OUTRANKS the hover rule in every state — and
   the light theme silently beat its own hover: the bento cards highlighted in dark and did nothing in
   light. Custom properties inherit instead of competing, so setting --kx-hair sidesteps the cascade
   fight entirely. The idle hairline is unchanged; :hover is simply no longer clobbered.
   Keep it this way: put NO `border` declaration in a theme-scoped .kx-glass rule. */
:root[data-theme="light"] .kx-glass{--kx-hair:rgba(0,0,0,.06);background:rgba(255,255,255,.72);box-shadow:0 1px 3px rgba(0,0,0,.06),0 8px 24px rgba(0,0,0,.04);}
:root[data-theme="light"] .kx-glass-dark{--kx-hair:rgba(0,0,0,.08);background:rgba(255,255,255,.9);box-shadow:0 1px 3px rgba(0,0,0,.05);}
/* Native select styled to match the contact-form inputs: appearance stripped + a mono-ish chevron. */
.kx-select{height:46px;background-color:rgba(var(--kx-bg-rgb),.9);border:1px solid var(--kx-border);border-radius:4px;color:var(--kx-fg);font-family:'Sora',sans-serif;font-size:14px;padding:0 38px 0 14px;outline:none;cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23808089' stroke-width='1.6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;}
.kx-select:focus{border-color:var(--kx-orange);}
.kx-select option{background:var(--kx-surface);color:var(--kx-fg);}

/* Repeated inline-style fragments, hoisted to classes. */
.kx-mono-label{font-family:'JetBrains Mono';font-size:11px;letter-spacing:.14em;color:var(--kx-orange);}
.kx-eyebrow{font-family:'JetBrains Mono';font-size:12px;letter-spacing:.16em;color:var(--kx-orange);}

/* ── SCAN-SEAM THEME TRANSITION (Phase 5, was the Phase L ripple) ─────────────
   One-shot View Transition: the incoming theme wipes in behind a thin, crisp bar of the
   DESTINATION accent, tilted ~12° and sweeping right→left (entering under the toggle). Reads as an
   instrument re-rendering itself, not the Material circle. Compositor-driven — no per-frame JS, no
   running loop, so the orb's steady-state cost is unchanged. Guarded in kx-theme.js (feature-detect +
   reduced-motion); dropping this block + that wrapper reverts to the instant flip.

   The seam itself is not an element: the OLD theme covers everything and shrinks off the left, the NEW
   theme enters from the right trailing the old edge by a CONSTANT 1.2% of viewport width, and that 1.2%
   gap exposes the ::view-transition container background — set below to the destination accent. Both
   clip polygons carry the same 12° tilt (top leads), so the gap never wobbles and the clips never
   overlap. data-theme has already flipped when these run, so the accent is where the flip is GOING. */
::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal;}
html.kx-theme-vt::view-transition-old(root),
html.kx-theme-vt::view-transition-new(root){
  animation-duration:540ms;animation-timing-function:cubic-bezier(.32,0,.24,1);
  animation-fill-mode:both;mix-blend-mode:normal;}
html.kx-theme-vt::view-transition-old(root){z-index:1;animation-name:kx-seam-clear;}
html.kx-theme-vt::view-transition-new(root){z-index:0;animation-name:kx-seam-reveal;}
html.kx-theme-vt[data-theme="dark"]::view-transition{background:#FF5500;}   /* → dark  : orange */
html.kx-theme-vt[data-theme="light"]::view-transition{background:#E64A00;}  /* → light : ember  */
@keyframes kx-seam-clear{
  from{clip-path:polygon(0 0, 104% 0, 116% 100%, 0 100%);}
  to{clip-path:polygon(0 0, -17.2% 0, -5.2% 100%, 0 100%);}}
@keyframes kx-seam-reveal{
  from{clip-path:polygon(105.2% 0, 130% 0, 130% 100%, 117.2% 100%);}
  to{clip-path:polygon(-16% 0, 130% 0, 130% 100%, -4% 100%);}}
@media (prefers-reduced-motion:reduce){
  html.kx-theme-vt::view-transition-old(root),
  html.kx-theme-vt::view-transition-new(root){animation:none;}}
