/* Trihelix. Generated by build.mjs from "Trihelix Site v2.dc.html".
   Do not hand-edit: re-run the build instead. */

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f0.woff2") format('woff2');
  unicode-range:U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f1.woff2") format('woff2');
  unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f2.woff2") format('woff2');
  unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f3.woff2") format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f4.woff2") format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f5.woff2") format('woff2');
  unicode-range:U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f6.woff2") format('woff2');
  unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f7.woff2") format('woff2');
  unicode-range:U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f8.woff2") format('woff2');
  unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f9.woff2") format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/f10.woff2") format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

body{margin:0;font-family:'Geist',sans-serif;background:var(--bg);color:var(--text);
--bg:#0A0C10;--card:#12161E;--card2:#171C26;--border:#242B38;--text:#E7EBF2;--text2:#94A1B4;--text3:#5F6C80;
--accent:#3AA8D4;--accentText:#61BFE4;--accentSoft:#0F2A38;--warn:#E0A93F;--display:#D9DCE1;
--navBg:rgba(10,12,16,.82);--road:#0E1219;--markFlip:0;--onAccent:#08131A;}
html.light body {--bg:#F6F7F9;--card:#FFFFFF;--card2:#FAFBFC;--border:#E5E8EC;--text:#16191D;--text2:#525F6D;--text3:#5F6B78;
--accent:#0E7DA8;--accentText:#0B6B90;--accentSoft:#E4F2F8;--warn:#7A5100;--display:#2A303A;
--navBg:rgba(246,247,249,.86);--road:#E9EDF1;--markFlip:1;--onAccent:#FFFFFF;}
*{box-sizing:border-box;}
a{color:var(--accentText);text-decoration:none;} a:hover{text-decoration:underline;}
::selection{background:var(--accentSoft);}
input,textarea,select{font-family:'Geist',sans-serif;}
input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.tx-mark{filter:invert(var(--markFlip));}

html { -webkit-text-size-adjust: 100%; color-scheme: dark; }
html.light { color-scheme: light; }
img { max-width: 100%; }

/* Both diagrams label their text with the SVG presentation attribute
   font-family="Geist Mono". Chrome does not reliably resolve a webfont from a
   presentation attribute, so the labels fall back to a serif. A CSS rule wins
   over a presentation attribute and pulls them back onto the real face. Every
   <text> in both diagrams is meant to be mono, so this can be blanket. */
svg text { font-family: 'Geist Mono', ui-monospace, monospace; }

/* Follow the OS when the visitor has set no preference and the script is
   blocked, so a failed load lands on their choice rather than always-dark. */
@media (prefers-color-scheme: light) {
  html:not(.js):not(.light) body {
    --bg:#F6F7F9; --card:#FFFFFF; --card2:#FAFBFC; --border:#E5E8EC;
    --text:#16191D; --text2:#525F6D; --text3:#5F6B78;
    --accent:#0E7DA8; --accentText:#0B6B90; --accentSoft:#E4F2F8; --warn:#7A5100;
    --display:#2A303A; --navBg:rgba(246,247,249,.86); --road:#E9EDF1;
    --markFlip:1; --onAccent:#FFFFFF;
  }
}

/* Links converted from the design's click targets keep the surrounding colour
   rather than picking up the global anchor style. */
a.x-a, a.x-a:hover { color: inherit; text-decoration: none; }
a.x-a:focus-visible, .x-chip:focus-within, .x-submit:focus-visible,
.x-theme:focus-visible, .x-figscroll:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* Hover states the runtime keeps in the CSSOM, captured at render time.
   They are inserted with insertRule, so --dump-dom serializes an empty
   <style> and they would otherwise be lost. */
.scp0:hover { color: var(--text) !important; }
.scp1:hover { border-color: var(--accent) !important; color: var(--accentText) !important; }
.scp2:hover { background: var(--accentSoft) !important; }
.scp3:hover { background: var(--accent) !important; color: var(--onAccent) !important; }

/* The theme control does nothing without scripting, so it is not rendered
   until scripting announces itself. */
.x-theme { display: none; font: inherit; background: none; }
html.js .x-theme { display: flex; }

/* The oversized "Refraction" wordmark is set with margin-left:-2.2vw so it runs
   off the left edge. On a wide display that is ~75px, which cuts the R in half
   and reads as a broken layout rather than a deliberate crop. Flush to the edge
   keeps the full-bleed intent with the letterform intact. To restore the
   designer's exact value, delete this rule. */
.x-bleed { margin-left: 0 !important; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: var(--onAccent); padding: 10px 16px;
  border-radius: 0 0 8px 0; font-size: 13px;
}
.skip:focus { left: 0; }

/* Role chips: real radios, selected state in CSS, so the choice submits with
   the form and the page needs no script. Uses input:checked + span rather than
   :has(), which Firefox only shipped in 121. */
.x-chip { display: inline-flex; cursor: pointer; }
.x-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.x-chip span {
  padding: 9px 15px; border-radius: 9px; font-size: 13px;
  border: 1px solid var(--border); background: transparent; color: var(--text2);
}
.x-chip input:checked + span {
  border-color: var(--accent); background: var(--accentSoft); color: var(--accentText);
}
.x-submit { cursor: pointer; width: 100%; border: 1px solid var(--accent); font: inherit; }
.x-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.x-note {
  border-radius: 9px; padding: 13px 15px; font-size: 14px; line-height: 1.6;
  margin-bottom: 18px; border: 1px solid var(--warn); background: var(--card2);
  color: var(--text);
}

/* Fragment links do the in-page scrolling, so it works with the script
   blocked. scroll-margin clears the fixed nav pill. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
section[id^="sec-"] { scroll-margin-top: 90px; }

/* Both diagrams carry small type inside a wide viewBox. Below the point where
   that stops being legible they scroll horizontally inside a focusable region
   rather than shrinking further. */
.x-figscroll { width: 100%; }
@media (max-width: 900px) {
  .x-figscroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .x-figscroll > svg { min-width: 900px; }
  /* The fixed left index collides with content once the gutter closes up. */
  .x-secindex { display: none !important; }
}

/* Every multi-column grid in the design is declared inline and does not
   collapse on its own. Stacked below 760px, or the Founder text column ends up
   a few characters wide next to a fixed 300px photograph. */
@media (max-width: 760px) {
  .x-grid { grid-template-columns: minmax(0, 1fr) !important; }
}

/* The design's asymmetric 66px/40px gutters close up on small screens. */
@media (max-width: 720px) {
  #main section, #main > div > div { padding-left: 20px !important; padding-right: 20px !important; }
  #main [style*="margin-left:-2.2vw"], #main [style*="margin-left: -2.2vw"] { margin-left: 0 !important; }
}

@media print {
  @page { margin: 0.5cm; }
  .x-theme, .x-secindex { display: none !important; }
  *, *::before, *::after {
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
    backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
  }
}
