/* ============================================================================
   GC TOTAL — SHARED DESIGN SYSTEM
   ----------------------------------------------------------------------------
   Every page wraps its content in <section class="site">. Everything here is
   scoped to .site so this file can never leak into an embed or a future host
   page. See DESIGN.md for the rules behind these choices.

   Hero-only styling (the line-sketch headline machinery, measuring rulers,
   grid pulse and parallax) lives in home.css, because only the home page
   carries it. Anything a second page needs belongs in this file.
   ========================================================================= */

.site{
  --gc-bg:#0A0A0A; --gc-bg2:#111111; --gc-ink:#F2F2F2; --gc-mid:#8C8C8C;
  --gc-line:#262626; --gc-line2:#3A3A3A; --gc-edge:#6E6E6E;
  --gc-o:var(--gct-o,#F25513);
  --gc-tick:#3C3C3C; --gc-tick2:#585858;
  /* copy tints, restated by .gc-sec-light and .gc-sec-accent */
  --gc-txt:#ABABAB; --gc-dim:#979797; --gc-prose-c:#B4B4B4;
  --gc-note-c:#7A7A7A; --gc-icon:#6E6E6E; --gc-faint:#5A5A5A;
  --gc-on-o:#0A0A0A;
  /* CTA hover. Each ground restates these -- see .gc-b:hover. */
  --gc-o-hi:#FF6E30; --gc-on-o-hi:#0A0A0A;
  --gc-draw:rgba(242,242,242,.3); --gc-draw-fine:rgba(242,242,242,.12);
  --gc-plate:#0C0C0C;
  --gc-mono:"IBM Plex Mono",ui-monospace,monospace;
  --gc-disp:Archivo,system-ui,sans-serif;
  --gc-body:"Inter Tight",system-ui,sans-serif;
  display:block;width:100%;background:var(--gc-bg);color:var(--gc-ink);
  font-family:var(--gc-mono);-webkit-font-smoothing:antialiased;
  /* clip, NOT hidden. `overflow:hidden` computes overflow-y to auto, which makes
     this a scroll container and silently breaks the sheet stack's position:sticky
     against the viewport. This is the single most important line in the file. */
  overflow-x:clip}
.site *{box-sizing:border-box}
.site h1,.site h2,.site h3,.site h4,.site p,.site ul,.site ol,.site li{margin:0;padding:0}
.site ul{list-style:none} .site a{color:inherit;text-decoration:none}

/* ---------------------------------------------------------------------------
   FOCUS
   Keyboard users must always be able to see where they are. Nothing here is
   visible to a pointer user, so there is no visual cost to keeping it.

   The ring is the accent because "act here" is exactly what focus means, and
   it resolves against each ground's own `--gc-o` — darkening to #B03400 on
   paper and inverting to #1A0700 on the orange ground without a second rule.

   That fallback chain is deliberate and must not be "simplified" to a single
   `--gc-focus` declared on `.site`. A custom property holding `var(--gc-o)` is
   substituted where it is DECLARED, so it would freeze to #F25513 and inherit
   that everywhere — measured at 1.00:1 on the orange ground, i.e. a completely
   invisible ring. Written this way, `var(--gc-o)` resolves at the focused
   element instead. Declare `--gc-focus` only to pin the ring to a fixed colour.

   The 2px offset is load-bearing. On an accent-filled button the ring is the
   same colour as the button, and it is the ground-coloured gap between them
   that makes the indicator perceivable. Remove the offset and the ring
   disappears into the primary button.
   ------------------------------------------------------------------------ */
.site :focus-visible{outline:2px solid var(--gc-focus,var(--gc-o));outline-offset:2px}
/* suppress the ring for pointer users without suppressing it for keyboards */
.site :focus:not(:focus-visible){outline:none}
/* Keep the keyboard shortcut out of the visual layout until a keyboard user
   reaches it. Fixed positioning prevents it from shifting the header. */
.site .gc-skip{position:fixed;top:12px;left:12px;z-index:1000;
  transform:translateY(calc(-100% - 24px));padding:10px 14px;
  border:1px solid var(--gc-o);background:var(--gc-bg);color:var(--gc-ink);
  font-family:var(--gc-mono);font-size:14px;font-weight:600;line-height:1.2}
.site .gc-skip:focus-visible{transform:translateY(0)}
.site .gc-w{width:100%;max-width:1300px;margin:0 auto;padding:0 14px}
@media(min-width:900px){.site .gc-w{padding:0 30px}}
.site .gc-w-narrow{max-width:860px}

/* ---------------------------------------------------------------------------
   SMALL TEXT — the CAD register.
   These sizes are floors, not suggestions. 12px/500/.10em is the smallest
   combination that still holds its strokes; going back to 10.5px/400/.16em
   turns the monoline face to mush. Never set .site type below 11.5px.
   ------------------------------------------------------------------------ */
.site .gc-m{font-size:13.5px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;
  color:var(--gc-mid);line-height:1.65}
.site .gc-m b{color:var(--gc-ink);font-weight:500}
.site .gc-m i{font-style:normal;color:var(--gc-o)}
.site .gc-m a{color:var(--gc-ink);border-bottom:1px solid var(--gc-line2)}
.site .gc-m a:hover{color:var(--gc-o);border-color:var(--gc-o)}

/* ---------- header: logo left, strong nav right ---------- */
/* The mark sat 13px off the top of the window, which reads as the page having
   been cropped rather than as a masthead. Padding stays symmetric so the mark
   remains centred in the bar; the bar simply gets taller. */
.site .gc-top{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:22px 14px;border-bottom:1px solid var(--gc-line)}
@media(min-width:900px){.site .gc-top{padding:28px 30px}}
/* ---------------------------------------------------------------------------
   THE LOCKUP
   The real brand mark, inlined by `build.lockup()`: `GC` in Barlow Black knocked
   out of the chamfered slab, `TOTAL` in Archivo 800, both as outlined
   path data. This replaced a CSS imitation that set `GC` and `Total` as Archivo
   800 text inside a `clip-path` plate. That version had two faults: it was not
   the mark the brand kit ships and the client web app inlines, and it depended on
   a webfont arriving from Google, so with fonts blocked the logo rendered in a
   fallback sans and quietly stopped being the logo.

   Sized by HEIGHT, never width. The footer retains the 28px mark. The header
   restores that visual weight instead of shrinking the lockup to nav-cap size,
   while the link around it retains a full mobile touch target.
   ------------------------------------------------------------------------ */
.site .gc-brand{display:inline-flex;align-items:center;flex:none;color:var(--gc-ink)}
.site .gc-lockup{display:block;height:28px;width:auto}
/* The brand is intentionally more prominent than the navigation labels. */
.site .gc-top .gc-lockup{height:24px}
@media(min-width:900px){.site .gc-top .gc-lockup{height:28px}}
/* The slab reads --gct-o, the ROOT accent, and NOT the ground-scoped --gc-o.
   --gc-o inverts per ground on purpose -- #B03400 on paper, #1A0700 on the accent
   sheet -- and a logo must not repaint itself when it lands somewhere else. The
   wordmark is `currentColor` so it does take the ground's ink, which is correct:
   that is contrast, not identity. */
.site .gc-lockup .gc-slab{fill:var(--gct-o,#F25513)}

.site .gc-nav{display:flex;align-items:center;gap:26px;min-width:0}
@media(min-width:900px){.site .gc-nav{gap:34px}}
.site .gc-nav-toggle{display:none;align-items:center;justify-content:center;gap:9px;
  min-width:72px;min-height:44px;padding:0 10px;border:1px solid var(--gc-edge);
  background:var(--gc-bg);color:var(--gc-ink);font-family:var(--gc-disp);
  font-size:14px;font-weight:700;line-height:1;letter-spacing:.02em;text-transform:uppercase;cursor:pointer}
.site .gc-nav-toggle-mark{display:grid;gap:4px;width:15px}
.site .gc-nav-toggle-mark i{display:block;width:15px;height:1px;background:currentColor;
  transform-origin:center;transition:transform .16s ease}
.site .gc-nav-toggle[aria-expanded="true"] .gc-nav-toggle-mark i:first-child{transform:translateY(2.5px) rotate(45deg)}
.site .gc-nav-toggle[aria-expanded="true"] .gc-nav-toggle-mark i:last-child{transform:translateY(-2.5px) rotate(-45deg)}
.site .gc-node{display:inline-flex;align-items:center;flex:none;font-family:var(--gc-disp);font-weight:700;font-size:15px;line-height:1;
  letter-spacing:.01em;text-transform:uppercase;color:var(--gc-ink);
  transition:color .16s ease;white-space:nowrap}
@media(min-width:900px){.site .gc-node{font-size:16px}}
.site .gc-node:hover{color:var(--gc-o)}
.site .gc-node[aria-current="page"]{color:var(--gc-o)}
@media(max-width:460px){
  .site .gc-top .gc-lockup{height:22px}
  .site .gc-nav{gap:18px}
  .site .gc-node{font-size:14px}
}

/* Touch layouts keep the compact glyphs but expand the clickable line to the
   required 44px target. This changes hit area, not the visual baseline. */
@media(max-width:899px){
  .site .gc-top .gc-brand{min-width:44px;min-height:44px}
  .site .gc-node{min-height:44px}
}

/* Login opens the prelaunch wait-list intake. The warm sweep stays inside the
   chip and the matching outer ring makes the hover state explicit. */
.site .gc-node-login{position:relative;isolation:isolate;border:1px solid transparent;padding:7px 12px 6px;
  appearance:none;font-family:var(--gc-disp);font-weight:700;text-transform:uppercase;cursor:pointer;
  background:linear-gradient(105deg,
    oklch(.48 .18 30),var(--gct-o,#F25513),oklch(.82 .16 88),
    var(--gct-o,#F25513),oklch(.48 .18 30));
  background-size:260% 100%;background-position:0 50%;
  color:oklch(.18 .02 38);
  animation:gc-login-flow 5.2s cubic-bezier(.45,0,.55,1) infinite alternate}
.site .gc-node-login::after{content:"";position:absolute;inset:-5px;z-index:1;
  background:linear-gradient(105deg,#5A160F,#7A2A0D,#8A6200,#7A2A0D,#5A160F);
  background-size:260% 100%;background-position:0 50%;opacity:0;pointer-events:none;padding:2px;
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  animation:gc-login-flow 5.2s cubic-bezier(.45,0,.55,1) infinite alternate}
.site .gc-node-login:hover{border-color:transparent;
  background-image:linear-gradient(105deg,#5A160F,#7A2A0D,#8A6200,#7A2A0D,#5A160F);
  color:var(--gc-ink)}
.site .gc-node-login:hover::after{opacity:1}
@keyframes gc-login-flow{
  from{background-position:0 50%}
  to{background-position:100% 50%}
}
/* the Services node opens a small panel rather than a full dropdown system:
   three items, no nesting, no JS dependency for keyboard users */
.site .gc-menu{position:relative;display:flex;align-items:center}
.site .gc-menu>.gc-node{cursor:pointer;background:none;border:0;padding:0;font-family:var(--gc-disp)}
.site .gc-menu-p{position:absolute;top:calc(100% + 13px);right:0;z-index:40;min-width:262px;
  background:var(--gc-bg2);border:1px solid var(--gc-line2);padding:5px;
  opacity:0;visibility:hidden;transform:translateY(-4px);
  transition:opacity .15s ease,transform .15s ease,visibility .15s}
.site .gc-menu.on .gc-menu-p{opacity:1;visibility:visible;transform:translateY(0)}
.site .gc-menu-p a{display:block;padding:10px 12px;border-bottom:1px solid var(--gc-line)}
.site .gc-menu-p a:last-child{border-bottom:0}
.site .gc-menu-p a:hover{background:#171717}
.site .gc-menu-p b{display:block;font-family:var(--gc-disp);font-weight:700;font-size:16px;
  letter-spacing:-.005em;color:var(--gc-ink)}
.site .gc-menu-p span{display:block;margin-top:3px;font-size:13.5px;font-weight:500;
  letter-spacing:.04em;text-transform:uppercase;color:var(--gc-mid)}
/* Service reference, top right of each menu row. Deliberately quiet: it is a
   wayfinding aid for people who already know the numbering, not a label the
   menu is built around. The row keeps padding-right so no title or subtitle
   can run under it. */
.site .gc-menu-p a{position:relative;padding-right:46px}
.site .gc-menu-p em{position:absolute;top:11px;right:12px;font-style:normal;
  font-family:var(--gc-mono);font-size:11px;font-weight:500;letter-spacing:.12em;
  color:var(--gc-faint)}
.site .gc-menu.on>.gc-node{color:var(--gc-o)}

/* A compact Menu trigger replaces the compressed navigation on phones. The
   same links remain in one shared nav, so desktop and mobile cannot drift. */
@media(max-width:720px){
  .site .gc-top{padding:16px 14px;flex-wrap:wrap}
  .site .gc-top .gc-lockup{height:22px}
  .site .gc-nav-toggle{display:inline-flex}
  .site .gc-nav{flex:1 0 100%;display:grid;align-items:stretch;gap:0;width:100%;
    border:1px solid var(--gc-line2);background:var(--gc-bg2);padding:6px}
  .gc-js .site .gc-nav{position:absolute;top:calc(100% + 1px);left:14px;right:14px;
    width:auto;opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-5px);
    transition:opacity .16s ease,transform .16s ease,visibility .16s}
  .gc-js .site .gc-nav.on{opacity:1;visibility:visible;pointer-events:auto;transform:translateY(0)}
  .site .gc-node{width:100%;min-height:44px;padding:0 12px;justify-content:space-between;font-size:15px}
  .site .gc-menu{display:block;width:100%}
  .site .gc-menu>.gc-node{padding:0 12px}
  .site .gc-menu-p{position:static;min-width:0;width:100%;max-height:0;overflow:hidden;
    padding:0;border:0;opacity:0;visibility:hidden;transform:none}
  .site .gc-menu.on .gc-menu-p{max-height:240px;padding:5px;border:1px solid var(--gc-line2);
    opacity:1;visibility:visible;transform:none}
  .site .gc-menu-p a{display:flex;min-height:44px;padding:8px 12px;flex-direction:column;justify-content:center}
  .site .gc-node-login{min-height:44px;height:44px;padding:0 12px}
}

/* ---------- prelaunch wait-list intake ---------- */
.site .gc-foot-link{display:inline-flex;align-items:center;min-height:44px;appearance:none;
  border:0;background:none;padding:0;color:inherit;font:inherit;text-align:left;cursor:pointer}
.site .gc-foot-link:hover{color:var(--gc-o)}
.site .gc-waitlist{width:min(620px,calc(100% - 32px));max-height:calc(100dvh - 32px);
  margin:auto;padding:0;border:1px solid var(--gc-line2);background:var(--gc-bg2);
  color:var(--gc-ink);box-shadow:0 28px 80px rgba(0,0,0,.62);overflow:auto}
.site .gc-waitlist::backdrop{background:rgba(0,0,0,.78)}
.site .gc-waitlist-head{display:flex;align-items:flex-start;justify-content:space-between;
  gap:24px;padding:24px 24px 18px;border-bottom:1px solid var(--gc-line)}
.site .gc-waitlist-head .gc-m{margin:0 0 6px;color:var(--gc-o)}
.site .gc-waitlist h2{margin:0;font-family:var(--gc-disp);font-size:clamp(2rem,7vw,3.25rem);
  line-height:.94;letter-spacing:-.035em;text-transform:uppercase}
.site .gc-waitlist-close{flex:0 0 44px;width:44px;height:44px;padding:0;border:1px solid var(--gc-edge);
  background:transparent;color:var(--gc-ink);font:400 30px/1 var(--gc-disp);cursor:pointer}
.site .gc-waitlist-close:hover{border-color:var(--gc-o);color:var(--gc-o)}
.site .gc-waitlist-intro{margin:0;padding:18px 24px 0;max-width:54ch;color:var(--gc-mid)}
.site .gc-waitlist form{padding:20px 24px 24px}
.site .gc-waitlist-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.site .gc-waitlist label span{display:block;margin:0 0 6px;font-family:var(--gc-mono);
  font-size:14px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--gc-mid)}
.site .gc-waitlist input{box-sizing:border-box;width:100%;min-height:44px;border:1px solid var(--gc-edge);
  border-radius:0;background:var(--gc-bg);color:var(--gc-ink);padding:10px 12px;font:500 16px/1.35 var(--gc-body)}
.site .gc-waitlist input:focus-visible,.site .gc-waitlist-close:focus-visible{
  outline:2px solid var(--gc-o);outline-offset:2px}
.site .gc-waitlist-trap{position:absolute!important;width:1px!important;height:1px!important;
  overflow:hidden!important;clip:rect(0 0 0 0)!important;white-space:nowrap!important}
.site .gc-waitlist-privacy{margin:16px 0 0;font-size:14px;color:var(--gc-mid)}
.site .gc-waitlist-privacy a{display:inline-flex;align-items:center;min-height:44px;
  text-decoration:underline;text-underline-offset:2px}
.site .gc-waitlist-status{min-height:22px;margin:10px 0;color:var(--gc-ink)}
.site .gc-waitlist-status.is-error{color:#FFB49E}
.site .gc-waitlist .gc-b{min-height:44px;border:0;cursor:pointer}
.site .gc-waitlist .gc-b:disabled{cursor:wait;opacity:.66}
@media(max-width:520px){
  .site .gc-waitlist{width:calc(100% - 20px);max-height:calc(100dvh - 20px)}
  .site .gc-waitlist-head{padding:18px 18px 14px}
  .site .gc-waitlist-intro{padding:14px 18px 0}
  .site .gc-waitlist form{padding:16px 18px 18px}
  .site .gc-waitlist-grid{grid-template-columns:1fr;gap:12px}
}

/* ---------- numbered index rail ---------- */
.site .gc-rail{display:flex;align-items:stretch;border-bottom:1px solid var(--gc-line);overflow:hidden}
.site .gc-rail span{flex:1 1 0;min-width:0;padding:6px 0 5px;text-align:center;
  font-size:11.5px;font-weight:500;letter-spacing:.06em;color:var(--gc-faint);
  border-right:1px solid var(--gc-line)}
.site .gc-rail span:nth-child(4n+1){color:var(--gc-mid)}
.site .gc-rail span.on{color:var(--gc-o)}
@media(max-width:640px){.site .gc-rail span:nth-child(n+9){display:none}}

/* ---------- tiling ---------- */
.site .gc-tile{background-image:repeating-linear-gradient(45deg,var(--gc-line2) 0 1px,transparent 1px 7px)}
.site .gc-tile-o{background-image:repeating-linear-gradient(45deg,var(--gc-o) 0 2px,transparent 2px 9px);opacity:.55}

/* ---------------------------------------------------------------------------
   THE LINE-SKETCH HEADLINE
   Each line is drafted twice: an outline layer (text-stroke) appears first,
   then the solid layer wipes across it. Construction guides rule in beforehand.
   It plays once and holds — a framework that keeps un-solidifying reads broken.
   ------------------------------------------------------------------------ */
.site .gc-h1{position:relative;font-family:var(--gc-disp);font-weight:800;
  font-size:clamp(3rem,13.5vw,9.5rem);line-height:.84;letter-spacing:-.05em;
  text-transform:uppercase;display:block}

.site .gc-guides{position:absolute;inset:-14px -10px -14px -10px;pointer-events:none;z-index:0}
.site .gc-guides span{position:absolute;background:var(--gc-o);opacity:.5}
.site .gc-guides .gh{left:0;right:0;height:1px;transform:scaleX(0);transform-origin:0 50%;
  animation:gc-rule-x .8s cubic-bezier(.2,.8,.3,1) both}
.site .gc-guides .gv{top:0;bottom:0;width:1px;transform:scaleY(0);transform-origin:50% 0;
  animation:gc-rule-y .7s cubic-bezier(.2,.8,.3,1) both}
.site .gc-guides .g1{top:0}
.site .gc-guides .g2{top:50%}
.site .gc-guides .g3{bottom:0;animation-delay:.12s}
.site .gc-guides .g4{left:0;animation-delay:.06s}
.site .gc-guides .g5{right:0;animation-delay:.2s}
@keyframes gc-rule-x{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes gc-rule-y{from{transform:scaleY(0)}to{transform:scaleY(1)}}
.site .gc-guides{animation:gc-guides-out 1.4s ease 1.9s both}
@keyframes gc-guides-out{from{opacity:1}to{opacity:.13}}

.site .gc-ln{position:relative;display:block;--gc-stroke:rgba(255,255,255,.9)}
.site .gc-ln-o{--gc-stroke:var(--gc-o)}
/* nowrap makes a one-line set a guarantee rather than a hope */
.site .gc-ln-fit{font-size:clamp(1.35rem,6.4vw,6.3rem);white-space:nowrap}
/* Interior fitted lines have more room than the home hero's stacked slogan.
   Keep them assertive on phones while preserving the same desktop cap. */
.site .gc-phero .gc-ln-fit{font-size:clamp(2.1rem,7.2vw,6.3rem)}
.site .gc-ln::before{content:attr(data-t);position:absolute;left:0;top:0;width:100%;
  color:transparent;-webkit-text-stroke:1.5px var(--gc-stroke);
  opacity:0;pointer-events:none;
  animation:gc-outline 2s ease both}
.site .gc-ln-o::before{animation-delay:.12s}
@keyframes gc-outline{
  0%{opacity:0} 10%{opacity:1} 66%{opacity:1} 100%{opacity:.34}}
.site .gc-ln i{font-style:normal;display:block;position:relative;
  clip-path:inset(0 100% 0 0);
  animation:gc-solid 1.05s cubic-bezier(.3,.75,.25,1) .5s both}
.site .gc-ln-o i{color:var(--gc-o);animation-delay:.72s}
@keyframes gc-solid{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes gc-fade{from{opacity:0}to{opacity:1}}

.site .gc-sub{font-family:var(--gc-body);font-size:clamp(17px,1.5vw,21px);line-height:1.45;
  color:var(--gc-txt);max-width:60ch;margin-top:20px;letter-spacing:0;text-transform:none;
  opacity:0;animation:gc-fade .45s ease 1s both}
.site .gc-sub span{display:block}
.site .gc-cta{display:flex;flex-wrap:wrap;gap:9px;margin-top:22px;
  opacity:0;animation:gc-fade .45s ease 1.18s both}

/* interior pages skip the long hero choreography — the copy should be readable
   the instant the page paints, not 3.4 seconds later */
.site .gc-instant .gc-sub,
.site .gc-instant .gc-cta{animation-delay:.35s;animation-duration:.5s}
.site .gc-instant .gc-ln::before{animation-duration:1.5s}
.site .gc-instant .gc-ln i{animation-delay:.5s;animation-duration:.9s}
.site .gc-instant .gc-ln-o::before{animation-delay:.12s}
.site .gc-instant .gc-ln-o i{animation-delay:.68s}
.site .gc-instant .gc-guides{animation-delay:1.4s}

/* Calls to action carry the display face at the same weight as the header's
   login chip, so the one thing we want clicked is not set in lighter type
   than the navigation above it.

   Every conversion action is a <button> that opens the wait-list dialog, so
   the rule has to neutralise the user-agent button styling as well: without
   appearance:none a platform chrome and corner radius leak through and the
   same label renders differently from the <a> variants beside it. */
.site .gc-b{display:inline-flex;align-items:center;justify-content:center;
  min-height:48px;padding:0 24px;appearance:none;border-radius:0;cursor:pointer;
  font-family:var(--gc-disp);font-size:15px;letter-spacing:.1em;
  text-transform:uppercase;font-weight:700;text-align:center;
  background:var(--gc-o);color:var(--gc-on-o);border:1px solid var(--gc-o)}
.site .gc-b{transition:transform .18s cubic-bezier(.2,.8,.3,1),
  box-shadow .22s ease, background-color .18s ease, color .18s ease,
  border-color .18s ease}
@media (hover:hover) and (pointer:fine){
  /* The glow is tinted with the hover fill rather than a neutral shadow, so it
     reads as the button throwing light rather than casting a drop shadow. */
  .site .gc-b:not(.gc-b2):hover{background:var(--gc-o-hi); color:var(--gc-on-o-hi);
    border-color:var(--gc-o-hi); transform:translateY(-2px) scale(1.025);
    box-shadow:0 10px 30px -8px color-mix(in srgb,var(--gc-o-hi) 62%,transparent),
               0 3px 10px -4px rgba(0,0,0,.28)}
  .site .gc-b:active{transform:translateY(0) scale(.99);
    box-shadow:0 2px 8px -4px rgba(0,0,0,.3)}
  /* Same gesture, lower volume. A wash of the ink colour rather than the brand
     fill, so the ghost button stays a ghost and the pair keeps its hierarchy. */
  .site .gc-b2:hover{background:color-mix(in srgb,var(--gc-ink) 9%,transparent);
    color:var(--gc-ink); transform:translateY(-2px) scale(1.025);
    box-shadow:0 8px 24px -10px rgba(0,0,0,.4)}
}
@media (prefers-reduced-motion:reduce){
  .site .gc-b{transition:background-color .18s ease, color .18s ease,
    border-color .18s ease}
  .site .gc-b:hover,.site .gc-b:active{transform:none; box-shadow:none}
}
.site .gc-b2{background:transparent;color:var(--gc-ink);border-color:var(--gc-line2);font-weight:600}
.site .gc-b2:hover{border-color:var(--gc-mid)}

/* ---------- 1-2-3 band ---------- */
.site .gc-band{border-top:1px solid var(--gc-line);border-bottom:1px solid var(--gc-line)}
.site .gc-three{display:grid;grid-template-columns:1fr}
@media(min-width:860px){.site .gc-three{grid-template-columns:repeat(3,1fr)}}
.site .gc-st{padding:26px 16px 28px;border-bottom:1px solid var(--gc-line);position:relative}
@media(min-width:860px){.site .gc-st{border-bottom:0;border-right:1px solid var(--gc-line)}
  .site .gc-st:last-child{border-right:0}}
.site .gc-st .n{font-family:var(--gc-disp);font-weight:800;font-size:clamp(2.4rem,7vw,3.6rem);
  line-height:.86;letter-spacing:-.045em;color:var(--gc-o)}
.site .gc-st h3{font-family:var(--gc-disp);font-size:clamp(1.15rem,2.2vw,1.35rem);font-weight:700;margin-top:10px;
  letter-spacing:-.008em;text-transform:none}
.site .gc-st p{font-family:var(--gc-body);font-size:16px;color:var(--gc-dim);
  margin-top:6px;letter-spacing:0;text-transform:none;line-height:1.5}
.site .gc-st .bar{height:3px;margin-top:16px}

/* four-across variant, for process strips that genuinely have four steps */
.site .gc-four{display:grid;grid-template-columns:1fr}
@media(min-width:700px){.site .gc-four{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1060px){.site .gc-four{grid-template-columns:repeat(4,1fr)}}
.site .gc-four .gc-st{border-right:1px solid var(--gc-line)}
@media(max-width:1059px){.site .gc-four .gc-st{border-bottom:1px solid var(--gc-line)}}

/* Custom work is sold as a connected system, so its four stages sit inside the
   same page measure instead of touching the viewport edges. The light hover is
   a temporary "paper on the workbench" state for pointer users. */
.site .gc-custom-process>.gc-w{padding-top:48px;padding-bottom:56px}
@media(min-width:900px){.site .gc-custom-process>.gc-w{padding-top:68px;padding-bottom:76px}}
.site .gc-custom-stages{margin-top:18px;gap:1px;background:var(--gc-line);
  border:1px solid var(--gc-line)}
.site .gc-custom-stages .gc-st{border:0;background:var(--gc-bg);min-width:0;
  transition:background-color .22s cubic-bezier(.25,1,.5,1),color .22s cubic-bezier(.25,1,.5,1)}
.site .gc-custom-stages .gc-st:hover{background:#F4F3EE;color:#14140F}
.site .gc-custom-stages .gc-st:hover>p:not(.n){color:#55544C}
.site .gc-custom-stages .gc-st:hover .gc-ic{color:#6B685F}
/* The band's own action, under the four steps. Deliberately not .gc-cta: that
   class carries the hero's entrance timing and would hold this button
   invisible for three and a half seconds after load. */
.site .gc-custom-start-cta{display:flex;flex-wrap:wrap;gap:9px;margin-top:34px}

/* Custom Automations starts with the buyer's lived before/after, not another
   systems diagram. The two states share one ruled field so they read as one
   changed workday. On narrow screens the field turns into a vertical handoff.

   The hero used to override .gc-ln-fit down to 3.8rem because its headline ran
   to five and four words. The line is two short ones now, so the override only
   made this page's hero smaller than its two siblings; the shared fitted size
   applies again. */
.site .gc-workday-shift{display:grid;grid-template-columns:1fr;margin-top:40px;
  border-top:1px solid var(--gc-line2);border-bottom:1px solid var(--gc-line2)}
.site .gc-workday-state{min-width:0;padding:30px 0}
.site .gc-workday-state+.gc-workday-state{border-top:1px solid var(--gc-line2)}
.site .gc-workday-state .gc-m{color:var(--gc-mid)}
.site .gc-workday-state h3{margin-top:18px;font-family:var(--gc-disp);font-weight:800;
  font-size:clamp(2.2rem,7vw,5.6rem);line-height:.88;letter-spacing:-.055em;
  text-transform:uppercase;color:var(--gc-mid)}
.site .gc-workday-state h3 i{font-style:normal;color:var(--gc-o)}
.site .gc-workday-state>p:last-child{max-width:52ch;margin-top:24px;
  font-family:var(--gc-body);font-size:17px;line-height:1.6;color:var(--gc-txt)}
.site .gc-workday-after h3{color:var(--gc-ink)}
@media(min-width:800px){
  .site .gc-workday-shift{grid-template-columns:1fr 1fr;margin-top:64px}
  .site .gc-workday-state{padding:52px 42px 56px 0}
  .site .gc-workday-state+.gc-workday-state{border-top:0;
    border-left:1px solid var(--gc-line2);padding-left:42px;padding-right:0}
}

/* Custom work is too varied for a catalogue of identical cards. These three
   ruled examples read like scoped possibilities: the company app leads, while
   the difficult-system and local-processing examples show two different seams. */
.site .gc-custom-offers{margin-top:34px;border-top:1px solid var(--gc-line)}
.site .gc-custom-offer{display:grid;gap:24px;padding:36px 0 38px;
  border-bottom:1px solid var(--gc-line)}
.site .gc-custom-offer h3{font-family:var(--gc-disp);font-size:clamp(1.25rem,3vw,1.8rem);
  font-weight:800;line-height:1.04;letter-spacing:-.025em;text-transform:none}
.site .gc-custom-offer>div>p{font-family:var(--gc-body);font-size:16.5px;
  line-height:1.62;color:var(--gc-dim);letter-spacing:0;text-transform:none;margin-top:10px}
.site .gc-custom-offer .gc-b{margin-top:20px}
/* Each example carries a real drawing rather than a miniature of itself in
   markup. Those plates are authored at the shared 620-unit width, so the side
   column only earns its place once it can hold one without panning; below that
   the drawing sits under its copy at full measure. */
/* The reveal wrapper carries a 44px top margin meant to separate a full-width
   plate from prose above it. There is no prose above it in a two-column cell,
   and the row is align-items:start, so the margin would drop each drawing 44px
   below its own heading. */
.site .gc-custom-offer .gc-fig,
.site .gc-custom-offer .gc-fig-plate{min-width:0}
.site .gc-custom-offer .gc-fig{margin-top:0}
@media(min-width:1240px){
  .site .gc-custom-offer{grid-template-columns:minmax(300px,1fr) minmax(620px,1.3fr);
    align-items:start;gap:44px;padding:54px 0 56px}
}

/* ---------- proof stats ----------
   A figure carries the argument, so the numeral leads and the prose follows.
   Every cited figure owns a <details> disclosure rather than a footnote mark:
   the source has to be reachable from the claim itself, and a native summary
   stays keyboard operable if the scripts never arrive. */
.site .gc-stats{display:grid;grid-template-columns:1fr;margin-top:10px;
  border-top:1px solid var(--gc-line2)}
.site .gc-stat{min-width:0;padding:30px 0 28px;border-bottom:1px solid var(--gc-line2)}
/* The caption sits beside the figure, not under it: read together they are one
   sentence, and stacking them broke that reading in half. */
.site .gc-stat-head{display:grid;grid-template-columns:1fr;gap:6px;align-items:baseline}
.site .gc-stat-n{display:block;font-family:var(--gc-disp);font-weight:800;
  font-size:clamp(5rem,17vw,11rem);line-height:.82;letter-spacing:-.055em;
  color:var(--gc-o)}
.site .gc-stat h3{max-width:26ch;font-family:var(--gc-disp);
  font-size:clamp(1.1rem,2.1vw,1.55rem);font-weight:700;line-height:1.2;
  letter-spacing:-.015em;color:var(--gc-ink)}
.site .gc-stat>p{margin-top:12px;max-width:62ch;font-family:var(--gc-body);
  font-size:16.5px;line-height:1.6;color:var(--gc-txt)}
.site .gc-cite{margin-top:14px}
/* One disclosure for the whole sheet, sitting under the closing rule rather
   than per figure: two buttons beside two numbers competed with the numbers. */
.site .gc-cite-page{margin-top:6px}
.site .gc-stats-cta{margin-top:26px}
.site .gc-cite summary{display:inline-flex;align-items:center;gap:8px;
  min-height:44px;min-width:44px;cursor:pointer;list-style:none;
  font-family:var(--gc-mono);font-size:13px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gc-mid)}
.site .gc-cite summary::-webkit-details-marker{display:none}
.site .gc-cite-i{display:inline-grid;place-items:center;width:18px;height:18px;
  border:1px solid var(--gc-line);border-radius:50%;font-family:var(--gc-disp);
  font-size:11px;font-weight:700;line-height:1}
.site .gc-cite summary:hover,.site .gc-cite summary:focus-visible,
.site .gc-cite[open] summary{color:var(--gc-o)}
.site .gc-cite summary:hover .gc-cite-i,
.site .gc-cite summary:focus-visible .gc-cite-i,
.site .gc-cite[open] .gc-cite-i{border-color:var(--gc-o)}
.site .gc-cite summary:focus-visible{outline:2px solid var(--gc-o);outline-offset:4px}
.site .gc-cite-b{max-width:54ch;padding-bottom:4px;font-family:var(--gc-body);
  font-size:14px;line-height:1.6;color:var(--gc-mid)}
.site .gc-cite-b b{color:var(--gc-txt);font-weight:600}
@media(min-width:720px){
  .site .gc-stat{padding:38px 0 36px}
  .site .gc-stat-head{grid-template-columns:auto minmax(0,1fr);gap:34px}
  .site .gc-stat>p{margin-top:16px}
}

/* ---------- finding ---------- */
.site .gc-find{padding:38px 0 34px;display:grid;grid-template-columns:1fr;gap:20px}
@media(min-width:900px){.site .gc-find{grid-template-columns:1.1fr .9fr;gap:34px}}
.site .gc-q{font-family:var(--gc-disp);font-weight:800;font-size:clamp(1.45rem,5.2vw,2.5rem);
  line-height:1.05;letter-spacing:-.03em;text-transform:uppercase;margin-top:12px}
.site .gc-q i{font-style:normal;color:var(--gc-o)}
.site .gc-src{margin-top:18px}
.site .gc-src div{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;
  border-top:1px solid var(--gc-line);padding:10px 0;font-size:14px;font-weight:400;
  color:var(--gc-mid);letter-spacing:.01em;text-transform:none}
.site .gc-src b{color:var(--gc-txt);font-weight:500;white-space:nowrap;text-transform:uppercase;letter-spacing:.12em}
.site .gc-pn{font-family:var(--gc-body);font-size:16.5px;color:var(--gc-dim);
  letter-spacing:0;text-transform:none;line-height:1.55}
.site .gc-pn strong{color:var(--gc-ink);font-weight:600}

/* ---------- close ---------- */
.site .gc-close{padding:42px 0 52px;text-align:center;border-top:1px solid var(--gc-line)}
.site .gc-close .gc-h1{font-size:clamp(1.9rem,7vw,4rem)}
.site .gc-close .gc-cta{justify-content:center}
.site .gc-close .gc-sub{margin-left:auto;margin-right:auto}
.site .gc-home-offer{overflow:clip}
.site .gc-home-offer::before,.site .gc-home-offer::after{content:"";position:absolute;
  inset:-16px;pointer-events:none}
.site .gc-home-offer::before{background-image:
  linear-gradient(to right,rgba(255,255,255,.13) 1px,transparent 1px),
  linear-gradient(to bottom,rgba(255,255,255,.13) 1px,transparent 1px);
  background-size:52px 52px;
  -webkit-mask-image:radial-gradient(ellipse 84% 76% at 50% 50%,#000 30%,transparent 100%);
  mask-image:radial-gradient(ellipse 84% 76% at 50% 50%,#000 30%,transparent 100%)}
.site .gc-home-offer::after{opacity:.23;background-image:
  repeating-linear-gradient(90deg,transparent 0 238px,rgba(255,255,255,.55) 238px 240px),
  repeating-linear-gradient(0deg,transparent 0 128px,rgba(255,255,255,.45) 128px 130px);
  background-size:100% 100%;
  -webkit-mask-image:linear-gradient(90deg,transparent 4%,#000 16% 84%,transparent 96%);
  mask-image:linear-gradient(90deg,transparent 4%,#000 16% 84%,transparent 96%)}
.site .gc-home-offer>.gc-w{position:relative;z-index:1}
.site .gc-home-offer .gc-ln{display:block}
.site .gc-home-offer .gc-close-hi{color:var(--gc-on-o)}
/* NO PHONE OVERRIDE HERE, AND THAT IS THE POINT.
   Below 560px this block used to buy a one-line set with `nowrap` and pay for
   it in type size: at 360px "START WITH A FREE BID PACKAGE" only fits on one
   line at 19.2px, which made the page's closing call to action SMALLER than
   every section heading above it -- .gc-h2 floors at 25.6px. The hierarchy
   inverted on phones and nowhere else, on the one block whose whole job is to
   be the last thing read. Two lines at the full clamp(1.9rem,7vw,4rem) is the
   better trade, so the closing headline now just wraps.

   The .gc-ln reveal survives wrapping: the outline is a ::before carrying the
   same string at width:100% in the same box, so it wraps identically and stays
   in register, and the clip wipe is a rectangle over the block rather than
   over one line. The same override existed a second time in source/home.html
   and was deleted with this one -- if it comes back, it must come back in one
   place only. */

/* ===========================================================================
   INTERIOR PAGES
   ======================================================================== */

/* ---------- page hero: a flat band, no ruler machinery ---------- */
.site .gc-phero{position:relative;border-bottom:1px solid var(--gc-line);
  padding:44px 0 40px;overflow:hidden}
@media(min-width:900px){.site .gc-phero{padding:62px 0 56px}}
/* ---------------------------------------------------------------------------
   Interior heroes get an ECHO of the home hero's parallax, not the full thing.
   Two planes at 52px and 156px drifting at different rates reads as depth
   without competing with the headline. Amplitudes are roughly half the home
   page's (2.5/2 and 7/5 against its 5/4 and 15/10) -- deliberately restrained,
   because these pages are read, not arrived at.
   ------------------------------------------------------------------------ */
.site .gc-phero .gc-pgrid{position:absolute;inset:-16px;pointer-events:none;z-index:0;
  background-image:
    linear-gradient(to right,rgba(242,242,242,.03) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(242,242,242,.03) 1px,transparent 1px);
  background-size:52px 52px;
  transform:translate3d(var(--gc-px,0px),var(--gc-py,0px),0);
  transition:transform .35s cubic-bezier(.2,.8,.3,1);will-change:transform}
/* the coarse plane sits nearer the viewer, so it travels further */
.site .gc-phero .gc-pcoarse{position:absolute;inset:-22px;pointer-events:none;z-index:0;
  background-image:
    linear-gradient(to right,rgba(242,242,242,.05) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(242,242,242,.05) 1px,transparent 1px);
  background-size:156px 156px;
  -webkit-mask-image:radial-gradient(120% 90% at 78% 40%,#000 0 42%,transparent 78%);
  mask-image:radial-gradient(120% 90% at 78% 40%,#000 0 42%,transparent 78%);
  transform:translate3d(var(--gc-qx,0px),var(--gc-qy,0px),0);
  transition:transform .45s cubic-bezier(.2,.8,.3,1);will-change:transform}
.site .gc-phero .gc-w{position:relative;z-index:1}
.site .gc-phero .gc-h1{font-size:clamp(2.3rem,8.4vw,5.4rem)}
.site .gc-phero .gc-sub{max-width:64ch}

/* ---------------------------------------------------------------------------
   THE SHEET STACK
   Each section is a drawing sheet. It pins to the top of the viewport, and the
   next one slides up over it like laying a new sheet onto the pile. The effect
   comes from the sheet UNDERNEATH being pinned while the next one travels, so
   every sheet needs an opaque ground and a lifted edge or the stack reads as
   one continuous scroll.

   Three things this depends on, all of them easy to break:

     1. `.site` must use `overflow-x: clip`, never `overflow: hidden` -- see the
        note at the top of this file.
     2. Header, rail and footer must sit ABOVE the sheets. They are static in
        the flow, and positioned elements paint over static ones, so without an
        explicit stacking context a pinned sheet covers the footer.
     3. A sheet taller than the viewport cannot work: sticky pins its top, so
        its own lower half becomes unreachable. site.js measures every sheet and
        marks the tall ones `.is-tall`, which drops them back into normal flow.
        They still slide over the pinned sheet before them -- only the pin is
        given up, not the transition.

   The sheet rules themselves live AFTER the section rules further down this
   file, not here, because `.gc-sec` sets `position: relative` at equal
   specificity -- so whichever is declared last wins. Declared here, four of
   seven sheets silently lost their pin. Do not move them back up.

   The home hero's pin lives in home.css for the same reason: home.css loads
   after this file, so a rule here would lose.
   ------------------------------------------------------------------------ */

/* The fixed furniture outranks the stack. The header must also outrank the RAIL
   that follows it: both were 60, and at equal z-index the later element in the
   document wins, so the index rail painted over the Products dropdown. */
.site .gc-top{position:relative;z-index:70;background:var(--gc-bg)}
.site .gc-rail{position:relative;z-index:60;background:var(--gc-bg)}
.site .gc-foot{position:relative;z-index:50;background:var(--gc-bg)}

/* legal documents are read, not scrolled through as a presentation, so they opt
   out of the stack entirely -- see build/legal.py */

/* ---------------------------------------------------------------------------
   SECTIONS AND GROUND
   Sixteen pages of one flat black with text packed edge to edge reads as a
   wall. Two things fix it and both are needed: real vertical air, and an
   alternating ground so the eye can tell where one idea stops.
   ------------------------------------------------------------------------ */
.site .gc-sec{padding:68px 0 64px;border-top:1px solid var(--gc-line);position:relative}
@media(min-width:900px){.site .gc-sec{padding:96px 0 90px}}
.site .gc-sec-flush{border-top:0}

/* the alternate ground is only four values lighter -- enough to separate, not
   enough to read as a coloured band. The faint grid does most of the work. */
.site .gc-sec-alt{background:#0E0E0E}
.site .gc-sec-alt::before{content:"";position:absolute;inset:0;pointer-events:none;
  background-image:
    linear-gradient(to right,rgba(242,242,242,.022) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(242,242,242,.022) 1px,transparent 1px);
  background-size:52px 52px;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 22%,#000 78%,transparent);
  mask-image:linear-gradient(180deg,transparent,#000 22%,#000 78%,transparent)}
.site .gc-sec-alt>.gc-w{position:relative;z-index:1}

/* ---------------------------------------------------------------------------
   PAPER AND ACCENT GROUNDS
   Two sheets per page break out of the black: one on warm paper, one on solid
   accent. Both work by restating the colour tokens, so every component inside
   them inverts without needing its own override.

   Warm off-white, not pure white: this is a drawing set, and paper stock reads
   correct where #FFFFFF reads like a login form.
   ------------------------------------------------------------------------ */
.site .gc-sec-light{
  --gc-bg:#F4F3EE;            /* cards and plates sit slightly above the ground */
  --gc-bg2:#E4E2DA; --gc-ink:#14140F; --gc-mid:#55544C;
  --gc-line:#D3D0C6; --gc-line2:#B0AC9E;
  --gc-txt:#3B3A33; --gc-dim:#4A4942; --gc-prose-c:#33322C;
  /* #7A796F measured only 3.57:1 on paper -- the sheet counter uses this */
  --gc-note-c:#66655C; --gc-icon:#55544C; --gc-faint:#5F5E55;
  --gc-tick:#B0AC9E; --gc-tick2:#8C887A;
  --gc-draw:rgba(20,20,15,.42); --gc-draw-fine:rgba(20,20,15,.14);
  --gc-plate:#F4F3EE; --gc-on-o:#FFF6F2;
  /* The brand orange is only 2.6:1 on paper, which fails AA for text. Text-
     bearing accent darkens to 5.0:1 here; it is the same hue, not a second
     accent colour, and it applies ONLY on this ground. */
  --gc-o:#B03400;
  /* deeper, not brighter: on paper more ink reads as more emphasis */
  --gc-o-hi:#8F2900; --gc-on-o-hi:#FFF6F2;
  color:var(--gc-ink)}
.site .gc-sheet.gc-sec-light{background:#EAE8E1}
.site .gc-sec-light::before{content:"";position:absolute;inset:0;pointer-events:none;
  background-image:
    linear-gradient(to right,rgba(20,20,15,.045) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(20,20,15,.045) 1px,transparent 1px);
  background-size:52px 52px;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 22%,#000 78%,transparent);
  mask-image:linear-gradient(180deg,transparent,#000 22%,#000 78%,transparent)}
.site .gc-sec-light>.gc-w{position:relative;z-index:1}
.site .gc-sec-light a.gc-card:hover{background:#FFFEFA}
.site .gc-sec-light .gc-tbl th{background:var(--gc-bg2)}
.site .gc-sec-light .gc-callout{background:var(--gc-bg2)}

/* ---- solid accent: orange ground, near-white boxes ---- */
.site .gc-sec-accent{
  --gc-bg:#FFF7F3;            /* the boxes are the light element here */
  --gc-bg2:#FFEDE5; --gc-ink:#1A0700;
  /* These are the tints that sit DIRECTLY on the orange, so they carry darker
     values than any other ground needs; anything inside a box is measured
     against #FFF7F3 instead and uses --gc-dim.

     The whole ladder shifted down one step on 2026-07-31 when the accent moved
     from #FF4D00 to the brand #F25513. The new orange is darker, so dark text on
     it loses ~0.2 of contrast, and the quiet register had fallen to 4.66:1 --
     still passing, but the previous value was itself chosen because #4A1600
     measured 4.49:1, a hair UNDER AA. Restoring margin by darkening only the
     quiet register would have made it darker than body copy and inverted the
     hierarchy, so all three steps moved together:

       quiet  --gc-mid/note/faint  #3A1000  4.85:1  (was 4.84 on the old orange)
       body   --gc-txt             #350E00  5.01:1  (was 5.03)
       prose  --gc-prose-c         #2A0B00  5.31:1  (was 5.51)

     Ordering is load-bearing: quiet must stay the LOWEST contrast of the three.
     Re-measure all three if the accent ever moves again. */
  --gc-mid:#3A1000; --gc-note-c:#3A1000; --gc-faint:#3A1000;
  --gc-line:rgba(26,7,0,.20); --gc-line2:rgba(26,7,0,.38);
  --gc-txt:#350E00; --gc-dim:#4A1600; --gc-prose-c:#2A0B00;
  --gc-icon:#5E2100;
  --gc-tick:rgba(26,7,0,.3); --gc-tick2:rgba(26,7,0,.5);
  --gc-draw:rgba(26,7,0,.45); --gc-draw-fine:rgba(26,7,0,.16);
  --gc-plate:#FFF7F3;
  /* accent-on-accent has to invert or it disappears into the ground */
  --gc-o:#1A0700; --gc-on-o:#FFF7F3;
  /* the button is already near-black here, so hover inverts instead */
  --gc-o-hi:#FFF7F3; --gc-on-o-hi:#1A0700;
  color:var(--gc-ink)}
.site .gc-sheet.gc-sec-accent{background:var(--gct-o,#F25513);border-top-color:rgba(26,7,0,.35)}
/* kept in step with --gc-txt above -- this is body copy sitting on the orange */
.site .gc-sec-accent .gc-sub{color:#350E00}
.site .gc-sec-accent .gc-ln{--gc-stroke:rgba(26,7,0,.55)}
.site .gc-sec-accent .gc-guides span{background:#1A0700;opacity:.35}
.site .gc-sec-accent .gc-b2{color:#1A0700;border-color:rgba(26,7,0,.45)}
.site .gc-sec-accent .gc-b2:hover{border-color:#1A0700}
/* The card hover further down is written for the dark grounds: it drops the box
   to #131313. On this ground the boxes are near-white with #1A0700 text, so
   that rule flips a readable card to black-on-black -- measured 1.05:1. The
   paper ground already carries its own hover for the same reason; this is the
   matching one. Lift to pure white and let the ink hairline carry the state,
   because #FFF7F3 -> #FFFFFF alone is too small a step to read as hover. */
.site .gc-sec-accent a.gc-card:hover{background:#FFFFFF;
  box-shadow:inset 0 0 0 1px var(--gc-line2)}

/* ---------------------------------------------------------------------------
   SHEET TITLE BLOCK
   The strip across the top of every sheet: sheet number, what the sheet is, a
   dotted leader, and its place in the set. Two parallel hairlines run the full
   bleed underneath it, which is what makes a sheet read as a sheet.

   It is absolutely positioned so it sits at the top edge while the sheet's
   content stays vertically centred. Sheets that fall back to normal flow
   (.is-tall) get explicit top padding instead, or the content would run under it.
   ------------------------------------------------------------------------ */
.site .gc-shead{position:absolute;top:0;left:0;right:0;z-index:3;
  height:46px;display:flex;align-items:center;gap:12px;padding:0 14px;
  font-family:var(--gc-mono);font-size:11.5px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gc-icon);white-space:nowrap;pointer-events:none}
@media(min-width:900px){.site .gc-shead{height:52px;padding:0 30px;gap:16px}}
/* the two parallel rules, full bleed */
.site .gc-shead::before,.site .gc-shead::after{content:"";position:absolute;
  left:0;right:0;height:1px}
.site .gc-shead::before{bottom:5px;background:var(--gc-line)}
.site .gc-shead::after{bottom:0;background:var(--gc-line2)}

.site .gc-shead .id{color:var(--gc-o);flex:none}
/* dotted leader, the way a drawing index runs to its page number */
.site .gc-shead .r{flex:1 1 auto;min-width:20px;height:1px;
  background-image:repeating-linear-gradient(90deg,var(--gc-line2) 0 2px,transparent 2px 6px)}
.site .gc-shead .n{flex:none;color:var(--gc-faint)}
@media(max-width:560px){
  .site .gc-shead{gap:9px;letter-spacing:.1em}
  .site .gc-shead .n{display:none}
}

/* content must clear the sheet header when a sheet is in normal flow */
.site .gc-sheet.is-tall{padding-top:96px}

/* ---- the sheet stack, declared here so it outranks .gc-sec's position ---- */
.site .gc-sheet{position:sticky;top:0;min-height:92vh;
  display:flex;flex-direction:column;justify-content:center;
  background:var(--gc-bg);border-top:1px solid var(--gc-line2);
  box-shadow:0 -30px 60px -20px rgba(0,0,0,.8)}
.site .gc-sheet.gc-sec-alt{background:#0E0E0E}
/* A sheet taller than the viewport still pins -- it just pins by its BOTTOM
   edge instead of its top. site.js sets a negative `top` equal to
   (viewport - sheet height), so the sheet scrolls until its bottom meets the
   bottom of the screen, holds there, and the next sheet slides over it.

   The earlier fix dropped these back to `position: relative`, which read as
   three sections scrolling normally in the middle of the stack. Pinning at the
   bottom keeps the whole sheet readable AND keeps the page-turn. */
.site .gc-sheet.is-tall{min-height:0;justify-content:flex-start}

/* THE LAST THING IN A SHEET NEEDS ROOM UNDER IT.
   Every sheet is uncovered from its bottom edge by the sheet that follows, so
   whatever sits lowest is only reachable for the moment before the next one
   slides across. For prose that is invisible. For a button it is a bug: you
   scroll it into view, reach for it, and it is gone under the incoming sheet
   before the pointer lands.

   Declared after .gc-sec and .gc-phero, both of which set padding as a
   shorthand, so this overrides only their bottom value and leaves the rest of
   the vertical rhythm alone. */
.site .gc-sheet{padding-bottom:170px}
@media(min-width:900px){.site .gc-sheet{padding-bottom:260px}}

/* ---- THE STACK IS A DESKTOP AFFORDANCE ----
   The page-turn only reads because scroll-snap holds a finished sheet still
   while the next one travels, and that snap is gated to min-width:900px and
   pointer:fine (the block lives in source/home.html). Without the hold, the
   incoming sheet begins covering the sheet you are reading the instant that
   sheet stops scrolling. Measured at 360x640 and 390x844: the last rows of
   each sheet were fully uncovered across only 280-460px of scroll, and one
   thumb flick moves several times that. Nothing was unreachable, but on a
   phone every sheet lost its closing lines to the next one.

   So below the snap breakpoint, and on any coarse pointer at any width, the
   pin is given up: sheets are ordinary sections again and nothing can overlap
   anything. The hairline, the lifted shadow and the sheet header all stay, so
   a sheet still reads as a sheet -- only the overlap goes. `relative`, not
   `static`: .gc-shead and the ground grids are absolutely positioned against
   the sheet and would escape to the viewport without it. site.js skips its
   sheet gauging under the same query so no inline `top` is left behind.

   The 170px bottom pad existed only to hold the last element clear of the
   incoming sheet. With nothing incoming it is dead space, so the bottom drops
   back to .gc-sec's own 64px. The TOP does not: it stays at 96px, 28px more
   than .gc-sec's 68px, because .gc-shead is absolutely positioned across the
   first 46px of every sheet and content set to .gc-sec's rhythm would run
   under it. That is the same 96px .is-tall uses, for the same reason.

   ONE SOURCE OF TRUTH. --gc-stack is the state, and site.js reads it back
   rather than carrying a hand-inverted copy of this query. A second query
   written as the logical negation of this one has to be re-derived by hand
   every time either moves, leaves a sub-pixel band between 899 and 900 that
   belongs to neither, and cannot notice a device that changes pointer type
   mid-session. Reading the computed value costs one style lookup per gauge
   and is right by construction. */
@media (max-width:899px), (hover:none), (pointer:coarse){
  .site{--gc-stack:released}
  .site .gc-sheet{position:relative;top:auto;min-height:0;
    justify-content:flex-start;padding-top:96px;padding-bottom:64px}
}
.site .gc-h2{font-family:var(--gc-disp);font-weight:800;
  font-size:clamp(2.2rem,6vw,4.6rem);line-height:.98;letter-spacing:-.035em;
  text-transform:uppercase;margin-top:12px}
.site .gc-h2 i{font-style:normal;color:var(--gc-o)}
.site .gc-lede{font-family:var(--gc-body);font-size:clamp(16px,1.4vw,21px);line-height:1.5;color:var(--gc-txt);
  max-width:68ch;margin-top:14px;letter-spacing:0;text-transform:none}
.site .gc-lede-line{display:block}

/* The old comparison table made the emotional shift read like specifications.
   Three plain pairs keep the before/after contrast and let it scan in seconds. */
.site .gc-compare{margin-top:12px;border:1px solid var(--gc-line)}
.site .gc-compare-head,.site .gc-compare-row{display:grid;grid-template-columns:1fr 1fr}
.site .gc-compare-head{background:var(--gc-bg2);border-bottom:1px solid var(--gc-line)}
.site .gc-compare-head span{padding:9px 13px;font-size:12.5px;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--gc-mid)}
.site .gc-compare-head span:last-child{color:var(--gc-o);border-left:1px solid var(--gc-line)}
.site .gc-compare-row{border-bottom:1px solid var(--gc-line)}
.site .gc-compare-row:last-child{border-bottom:0}
.site .gc-compare-row span,.site .gc-compare-row strong{padding:12px 13px;
  font-family:var(--gc-body);font-size:15.5px;line-height:1.4;letter-spacing:0;text-transform:none}
.site .gc-compare-row span{color:var(--gc-dim)}
.site .gc-compare-row strong{border-left:1px solid var(--gc-line);color:var(--gc-ink);font-weight:600}

/* ---------- FAQ ----------
   Native details/summary keeps the disclosure keyboard-operable without JS.
   The ruled rows keep it in the drawing-register language and make long-answer
   pages scan like a specification index rather than a stack of cards. */
.site .gc-faq-list{margin-top:28px;border-top:1px solid var(--gc-line2)}
.site .gc-faq-item{border-bottom:1px solid var(--gc-line2)}
.site .gc-faq-item summary{display:grid;grid-template-columns:1fr auto;gap:20px;
  align-items:center;padding:19px 0;cursor:pointer;list-style:none;
  font-family:var(--gc-disp);font-size:clamp(15px,2vw,18px);font-weight:700;
  line-height:1.25;letter-spacing:-.01em;color:var(--gc-ink)}
.site .gc-faq-item summary::-webkit-details-marker{display:none}
.site .gc-faq-item summary::after{content:"+";font-family:var(--gc-mono);
  font-size:20px;font-weight:400;line-height:1;color:var(--gc-o)}
.site .gc-faq-item[open] summary::after{content:"-"}
.site .gc-faq-item summary:hover,.site .gc-faq-item summary:focus-visible{color:var(--gc-o)}
.site .gc-faq-item summary:focus-visible{outline:2px solid var(--gc-o);outline-offset:4px}
.site .gc-faq-item p{max-width:76ch;padding:0 42px 20px 0;
  font-family:var(--gc-body);font-size:16.5px;line-height:1.6;
  letter-spacing:0;text-transform:none;color:var(--gc-txt)}
@media(min-width:900px){
  .site .gc-faq-item summary{padding:22px 0}
  .site .gc-faq-item p{font-size:17px;padding-bottom:23px}
}

/* ---------- cards ---------- */
.site .gc-cards{display:grid;grid-template-columns:1fr;gap:1px;margin-top:26px;
  background:var(--gc-line);border:1px solid var(--gc-line)}
@media(min-width:720px){.site .gc-cards-2{grid-template-columns:repeat(2,1fr)}}
@media(min-width:720px){.site .gc-cards-3{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1040px){.site .gc-cards-3{grid-template-columns:repeat(3,1fr)}}
/* Between those two breakpoints a `.gc-cards-3` grid runs in TWO columns, so any
   odd number of cards leaves the last one beside an empty cell -- and an empty
   cell is not blank, it is a hole showing `--gc-line`: a grey block on the dark
   grounds, a dark notch punched out of the orange on the accent one. Let the
   last card finish the row instead.

   `:last-child:nth-child(odd)` is the whole test: in a two-column grid the last
   child sits alone exactly when its index is odd. That covers the three-card
   product and contact grids AND the nine-card legal index, and correctly leaves
   an even count alone. Writing this as `:nth-child(3)` instead would have fixed
   the three-card grids and silently left the legal index holed.

   If a `.gc-cards-3` grid is ever given its own three-column rule inside this
   range again, exclude it here -- spanning `1 / -1` across three columns stretches
   the last card over the whole block. That is what the retired `.gc-bento-3` did. */
@media(min-width:720px) and (max-width:1039px){
  .site .gc-cards-3>*:last-child:nth-child(odd){grid-column:1 / -1}
}
@media(min-width:720px){.site .gc-cards-4{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1100px){.site .gc-cards-4{grid-template-columns:repeat(4,1fr)}}
.site .gc-card{background:var(--gc-bg);padding:30px 26px 32px;position:relative}
@media(min-width:900px){.site .gc-card{padding:36px 30px 38px}}
.site .gc-sec-alt .gc-card{background:#0E0E0E}
.site .gc-sec-alt .gc-cards{background:var(--gc-line);border-color:var(--gc-line)}
.site .gc-sec-alt a.gc-card:hover{background:#141414}
.site .gc-card h3{font-family:var(--gc-disp);font-size:clamp(1.15rem,2.2vw,1.35rem);font-weight:700;
  letter-spacing:-.008em;text-transform:none}
.site .gc-card p{font-family:var(--gc-body);font-size:16px;color:var(--gc-dim);margin-top:8px;
  letter-spacing:0;text-transform:none;line-height:1.55}
.site .gc-card .k{font-size:13px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;
  color:var(--gc-o);display:block;margin-bottom:10px}
.site a.gc-card:hover{background:#131313}
.site a.gc-card:hover h3{color:var(--gc-o)}

/* ---------------------------------------------------------------------------
   BENTO
   Same hairline grid, uneven cells. Breaks the "row of identical boxes" read
   without introducing a second layout system: it is the card grid with a
   couple of spans, so everything inside keeps working.
   ------------------------------------------------------------------------ */
/* **There is no `.gc-bento-3`.** It existed and was retired: the three service-producing
   offerings on the home page use equal cards so visitors can scan the engagement paths.
   Equal layout does not make them three software products or change delivery priority, so
   "What we do" now uses plain `.gc-cards-3`. Do not reintroduce a 3-up bento there.

   The lesson from it is still worth keeping, because it applies to any bento: the
   lead cell must span BOTH axes or the grid does not close. Three items in three
   columns with the first spanning two of them fills 4 of 6 cells, and the two it
   leaves are not neutral — `.gc-cards` paints `--gc-line`, so on the accent ground
   the hole read as a hard-edged orange notch bitten out of the block.
   `grid-auto-flow:dense` cannot save it: there are no later items to backfill with.
   `.gc-bento-4` below spans its first child across two rows and two columns and
   closes exactly, which is why it is the one that survives. */
@media(min-width:1100px){
  .site .gc-bento-4{grid-template-columns:repeat(4,1fr);grid-auto-flow:dense}
  .site .gc-bento-4>*:nth-child(1){grid-column:span 2;grid-row:span 2}
  .site .gc-bento-4>*:nth-child(1) h3{font-size:clamp(1.2rem,2.3vw,1.6rem)}
  .site .gc-bento-4>*:nth-child(1) .gc-ic{width:52px;height:52px}
  .site .gc-bento-4>*:nth-child(6){grid-column:span 2}
}

/* the three-product cards on the home page carry a little more weight */
.site .gc-prod h3{font-size:clamp(1.15rem,3vw,1.5rem);font-weight:800;
  text-transform:uppercase;letter-spacing:-.025em}
.site .gc-prod .go{display:block;margin-top:16px;font-size:13px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--gc-mid)}
.site a.gc-prod:hover .go{color:var(--gc-o)}
/* These three sit inside the near-white card boxes on the accent sheet, so
   the backing is that box colour and not a token: --gc-bg2 would resolve to
   the dark raised surface and paint a black band across the top of every
   product card on the orange ground. #FFF7F3 is the same value .gc-sec-accent
   gives its boxes, and the same ground the illustrations are drawn on. */
.site .gc-offer-art{display:block;margin:-12px -8px 24px;padding:0 0 16px;
  border-bottom:1px solid var(--gc-line);background:#FFF7F3;overflow:hidden}
/* Square, because the drawings are: measured, their ink is 1.14, 1.04 and 0.85
   wide-to-tall. Card 3 is genuinely taller than wide, so a 3/2 slot would have
   cut it -- and `object-fit:cover` is gone for the same reason. The slot is
   sized to the art rather than the art cropped to the slot, which costs card
   height and is the price of this artwork. */
.site .gc-offer-art img{display:block;width:100%;height:auto;aspect-ratio:1 / 1;
  transition:transform .45s cubic-bezier(.16,1,.3,1)}
.site a.gc-prod:hover .gc-offer-art img{transform:scale(1.018)}

/* ---------- testimonial placeholders ---------- */
.site .gc-testimonials{display:grid;grid-template-columns:1fr;gap:1px;margin-top:28px;
  border:1px solid var(--gc-line);background:var(--gc-line)}
.site .gc-testimonial{background:var(--gc-bg);padding:24px 22px;min-width:0}
.site .gc-testimonial-company{font-size:13px;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gc-o)}
.site .gc-testimonial-quote{font-family:var(--gc-disp);font-size:clamp(1.25rem,3.2vw,2rem);
  font-weight:800;line-height:1.08;letter-spacing:-.025em;color:var(--gc-ink);
  text-transform:none;margin-top:24px}
.site .gc-testimonial .gc-m{margin-top:28px;color:var(--gc-mid)}
.site .gc-testimonial-note{font-family:var(--gc-body);font-size:17px;line-height:1.5;
  color:var(--gc-note-c);margin-top:12px;letter-spacing:0;text-transform:none}
@media(min-width:820px){
  .site .gc-testimonials{grid-template-columns:1.35fr .65fr;grid-template-rows:1fr 1fr}
  .site .gc-testimonial-featured{grid-row:1 / 3;display:flex;flex-direction:column;
    justify-content:space-between;padding:34px 32px}
  .site .gc-testimonial-featured .gc-testimonial-quote{font-size:clamp(2rem,4.2vw,3.4rem);
    max-width:15ch}
}

/* ---------- plain checklist ---------- */
.site .gc-list{margin-top:20px;border-top:1px solid var(--gc-line)}
.site .gc-list li{display:grid;grid-template-columns:auto minmax(0,1fr);gap:13px;
  align-items:baseline;padding:12px 0;border-bottom:1px solid var(--gc-line);
  font-family:var(--gc-body);font-size:16.5px;line-height:1.55;color:var(--gc-txt);
  letter-spacing:0;text-transform:none}
.site .gc-list li::before{content:"";width:9px;height:9px;background:var(--gc-o);
  transform:translateY(-1px);
  clip-path:polygon(0 0,calc(100% - 3px) 0,100% 3px,100% 100%,0 100%)}
.site .gc-list strong{color:var(--gc-ink);font-weight:600}

/* The Bid Scope output labels need to read as deliverable names on the orange
   outcome sheet. Warm-white text directly on brand orange does not meet the
   small-text contrast floor, so each name sits on a compact ink label while
   its explanation remains black on orange. */
.site .gc-bsc-outcome .gc-list li{color:#1A0700}
.site .gc-bsc-outcome .gc-list li::before{background:#1A0700}
.site .gc-bsc-outcome .gc-list strong{color:#FFF7F3;background:#1A0700;
  font-weight:700;padding:.08em .34em;margin-right:.2em;
  -webkit-box-decoration-break:clone;box-decoration-break:clone}

/* ---------- table: trigger / action / result ---------- */
.site .gc-tblwrap{margin-top:24px;overflow-x:auto;border:1px solid var(--gc-line)}
.site .gc-tbl{width:100%;border-collapse:collapse;min-width:640px}
.site .gc-tbl th{text-align:left;padding:11px 16px;font-size:13.5px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--gc-mid);
  border-bottom:1px solid var(--gc-line);background:var(--gc-bg2);white-space:nowrap}
.site .gc-tbl td{padding:14px 16px;border-bottom:1px solid var(--gc-line);
  font-family:var(--gc-body);font-size:16px;line-height:1.5;color:var(--gc-dim);vertical-align:top}
.site .gc-tbl tr:last-child td{border-bottom:0}
.site .gc-tbl td:first-child{color:var(--gc-ink);font-family:var(--gc-mono);font-size:14px;
  font-weight:500;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}
.site .gc-tbl td:last-child{color:var(--gc-txt)}

/* ---------- pricing ---------- */
.site .gc-tiers{display:grid;grid-template-columns:1fr;gap:1px;margin-top:28px;
  background:var(--gc-line);border:1px solid var(--gc-line)}
/* auto-fit, not repeat(3): Bid Scope shows three plans and the AI Assistant
   shows two, and a fixed three-column track left the second page with an empty
   cell that read as a missing plan. */
@media(min-width:840px){
  .site .gc-tiers{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}}
/* Every card carries the sheet ground. The recommended plan is marked by its
   flag alone: inverting one card to a light ground made the row read as two
   different products rather than three points on one scale. */
.site .gc-tier{background:var(--gc-bg);padding:26px 22px 28px;display:flex;flex-direction:column}
.site .gc-tier .name{font-family:var(--gc-disp);font-weight:800;font-size:17px;
  letter-spacing:.02em;text-transform:uppercase;color:var(--gc-ink)}
/* The open-ended card has no figure to show, so the plus takes the slot the
   price occupies on every other card: same size, same colour, same left edge.
   Centring it on the words above instead left it floating in the middle of an
   otherwise empty block, because there is no figure beside it to hold a centre
   against. Sharing the price's origin keeps one straight figure line across
   the whole row. */
.site .gc-tier-more .gc-tier-plus{font-family:var(--gc-disp);font-weight:800;
  font-size:var(--gc-rate-size);line-height:.9;letter-spacing:-.05em;
  color:var(--gc-o);margin-top:18px}
.site .gc-tier .flag{display:inline-block;margin-left:9px;padding:3px 7px 2px;
  background:var(--gc-o);color:#0A0A0A;font-size:12.5px;font-weight:600;
  letter-spacing:.09em;text-transform:uppercase;vertical-align:2px;
  clip-path:polygon(0 0,calc(100% - 5px) 0,100% 5px,100% 100%,0 100%)}
/* The monthly figure is the headline number — that is what leaves the bank
   account. The per-job rate is the justification, so it sits underneath in the
   quiet register rather than competing with it. Plans carry no feature lists:
   volume is the only variable, and anything printed inside a card would read as
   a feature the other plans lack.

   The figure and its "/ month" are one unit and must not break across lines:
   a five-digit price wrapped the qualifier onto its own line and left the card
   two lines taller than the others. nowrap holds them together, and the size is
   set from the widest string the row can carry ($10,000) with room to spare, so
   a webfont whose metrics differ from the fallback still fits. */
.site .gc-tier{--gc-rate-size:clamp(2.3rem,5.4vw,3rem)}
.site .gc-tier .rate{font-family:var(--gc-disp);font-weight:800;
  font-size:var(--gc-rate-size);line-height:.9;letter-spacing:-.05em;
  color:var(--gc-o);margin-top:18px;white-space:nowrap}
.site .gc-tier .rate small{font-family:var(--gc-mono);font-size:14px;font-weight:500;
  letter-spacing:.05em;color:var(--gc-mid);text-transform:uppercase;
  display:inline-block;margin-left:5px;vertical-align:5px}
.site .gc-tier .vol{font-size:14.5px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:var(--gc-mid);margin-top:14px;
  padding-top:14px;border-top:1px solid var(--gc-line)}
.site .gc-tier .vol b{color:var(--gc-ink);font-weight:500}
.site .gc-tier .per{font-family:var(--gc-body);font-size:15px;color:var(--gc-note-c);
  margin-top:6px;letter-spacing:0;text-transform:none}
.site .gc-tier .per b{color:var(--gc-txt);font-weight:600}
/* margin-top:auto keeps the buttons on one line across all three cards even if
   a plan name ever wraps */
.site .gc-tier .gc-b{margin-top:auto;padding-top:0;justify-content:center;
  animation:none;opacity:1}
.site .gc-tier .per{margin-bottom:24px}
.site .gc-note{font-size:13.5px;font-weight:500;letter-spacing:.06em;color:var(--gc-note-c);
  margin-top:18px;line-height:1.7;text-transform:none}

/* ---------- callout: the boundary/limits block ---------- */
.site .gc-callout{margin-top:26px;border:1px solid var(--gc-line2);padding:24px 22px;
  background:var(--gc-bg2);position:relative}
.site .gc-callout::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--gc-o)}
.site .gc-callout h3{font-family:var(--gc-disp);font-size:16px;font-weight:700;
  letter-spacing:-.008em;text-transform:none}
.site .gc-callout p{font-family:var(--gc-body);font-size:16.5px;line-height:1.6;
  color:var(--gc-txt);margin-top:9px;letter-spacing:0;text-transform:none}

/* ---------- shared service figure animation ---------- */
.site .gc-service-demo{max-width:880px;margin:34px auto 28px}
.site .gc-service-demo .d-fig{max-width:none}
.site .gc-outcome-lead{display:block}
.site .gc-outcome-lead{margin-bottom:4px}
.site .gc-hours-white{color:#FFF7F3!important}
/* No plate: the drawing sits directly on the accent ground in white line,
   so the figure belongs to the sheet instead of floating on a card. The ink
   ladder inverts -- structure at .62 white, detail at .38, and the element
   that carries the point at full white and heavier, since orange accent on an
   orange ground would be invisible. */
/* The frame is cropped to the content, not left at 4:3. Every phase of every
   figure lives inside a 240-unit band. The band was set by whichever phase
   reached lowest -- the sealed envelope -- so every earlier beat floated in a
   frame sized for the last one, which read as the right column sitting low and
   left the blurb stranded below the drawing. The envelope was raised into the
   band the rest of the sequence already occupies rather than the band widened
   to meet it.

   All three share ONE ratio deliberately. The panels stack in a single grid
   cell, so the stage reserves the tallest -- give each figure a frame fitted
   to its own content and the copy below it jumps as you move between
   services. Each viewBox instead centres its own content in the common band. */
.d-fig{ display:block; width:100%; height:auto; aspect-ratio:480 / 240; }
.d-fig .l{ fill:none; stroke:#FFFFFF; stroke-opacity:.62; stroke-width:1.5; }
.d-fig .h{ fill:none; stroke:#FFFFFF; stroke-opacity:.38; stroke-width:1.2; }
.d-fig .o{ fill:none; stroke:#FFFFFF; stroke-width:2.2; }
.d-fig .of{ fill:#FFFFFF; stroke:none; }
.d-fig .pg{ fill:var(--gct-o); }
/* Full white, like .dol and .stamp. Alpha-dimming ink on this ground is the
   failure DESIGN.md section 13 records: .8 composites to 2.69:1, below even
   the large-text floor, on the words that make the sequence readable. Where a
   label needs to sit quieter than the $ beside it, that comes from size and
   weight, never from alpha. */
.d-fig .lab{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace;
  font-size:13px; font-weight:600; letter-spacing:.1em; }
.d-fig .num{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace;
  font-size:13px; font-weight:400; }
/* Smaller than .lab because it has to sit inside an 84-unit puzzle cell
   between two tab necks, not across a 172-unit scope block. Bold and centred
   recovers what the two points of size cost. */
.d-fig .tag{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace;
  font-size:12.5px; font-weight:700; letter-spacing:.06em; text-anchor:middle; }
/* The dollar sign reads as a figure, not a headline -- mono, the same face
   the sheet numbers and drawing labels use, so it belongs to the drawing. */
.d-fig .dol{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace; font-size:18px;
  font-weight:600; text-anchor:middle; }
.d-fig .stamp{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace;
  font-size:12.5px; font-weight:700; letter-spacing:.14em; text-anchor:middle; }
/* Canted in CSS, not as an SVG transform attribute: the reduced-motion block
   resets transform with !important and would flatten an attribute rotation.
   It is re-asserted there for the same reason. */
.d-fig .stampbox{ transform-box:fill-box; transform-origin:50% 50%;
  transform:rotate(-5deg); }

/* Every animation is gated on .go rather than paused/resumed. Pausing meant
   leaving and returning picked the sequence up mid-way; going from
   animation-name:none to a name restarts it from frame zero, which is what
   re-entering a row should do. The class is toggled by the script at the foot
   of this file, which also re-runs the sequence after a hold. */
.d-fig .d{ stroke-dasharray:640; stroke-dashoffset:640; }
/* The shared 640 is tuned for the small strokes and is SHORTER than this
   rect's 780 perimeter, so the pattern repeats and 140 units of its left edge
   never stroke at all. The one long path carries its own dash length rather
   than raising the shared value. */
.d-fig .dl{ stroke-dasharray:900; stroke-dashoffset:900; }
/* d-flow travels stroke-dashoffset to -32, which needs a dash pattern of that
   period to travel ALONG. Without this the keyframe animated an offset on a
   solid stroke and did nothing at all: the flow lines rendered as static full
   white polylines, which is most of why the panel read as dead. */
.d-fig .flow{ stroke-dasharray:8 24; }
.d-fig .f, .d-fig .sl, .d-fig .veil{ opacity:0; }
.d-fig.go .d{ animation:d-draw .7s cubic-bezier(.3,.75,.25,1) both; }
.d-fig.go .f{ animation:d-in .45s ease both; }
.d-fig.go .veil{ animation:d-in .5s ease both; }
.d-fig.go .sl{ animation:d-slide .5s cubic-bezier(.2,.8,.3,1) both; }
.d-fig.go .scan3{ animation:d-read 3.45s cubic-bezier(.4,0,.6,1) 400ms both; }
.d-fig.go .flow{ animation:d-flow 1.1s linear .9s infinite; }
.d-fig.go .blip{ animation:d-blip 1.8s ease 1s infinite; }
.d-fig.go .gone{ animation:d-fadeout .5s ease both; }
.d-fig.go .shift{ animation:d-shift .6s cubic-bezier(.3,.75,.25,1) both; }
/* The scope blocks themselves travel onto the paper -- nothing is redrawn
   there. transform-box:fill-box puts the origin on each group's own bbox
   corner, so one keyframe carries every row with per-row offsets. */
.d-fig .mv{ transform-box:fill-box; transform-origin:0 0; }
.d-fig.go .mv{ animation:d-move .75s cubic-bezier(.4,0,.2,1) both; }
.d-fig.go .rise{ animation:d-rise .6s cubic-bezier(.3,.75,.25,1) both; }
.d-fig.go .post{ animation:d-post .75s cubic-bezier(.5,0,.4,1) both; }

@keyframes d-draw{ to{ stroke-dashoffset:0; } }
@keyframes d-in{ to{ opacity:1; } }
@keyframes d-fadeout{ to{ opacity:0; } }
@keyframes d-slide{ from{ opacity:0; transform:translateX(-64px) }
  to{ opacity:1; transform:translateX(0) } }
@keyframes d-read{
  0%{ transform:translateY(0); opacity:1 }
  16.7%{ transform:translateY(100px) } 33.3%{ transform:translateY(0) }
  50%{ transform:translateY(100px) }   66.7%{ transform:translateY(0) }
  83%{ transform:translateY(100px) }
  96%{ transform:translateY(0); opacity:1 }
  100%{ transform:translateY(0); opacity:0 } }
@keyframes d-shift{ to{ transform:translateX(-196px) } }
@keyframes d-move{ to{ transform:translate(var(--mx),var(--my)) scale(.52) } }
@keyframes d-rise{ from{ transform:translateY(84px); opacity:0 }
  to{ transform:translateY(0); opacity:1 } }
@keyframes d-post{ to{ transform:translate(-118px,38px) } }
@keyframes d-flow{ to{ stroke-dashoffset:-32; } }
@keyframes d-blip{ 0%,100%{ opacity:.25 } 50%{ opacity:1 } }
/* ---- the float ------------------------------------------------------
   Each run -- the piece, its cable, its plug and its pulse -- drifts as one
   rigid thing on two nested translations, x on one period and y on another
   that is not a multiple of it. One axis alone would shuttle a piece back
   and forth along a single line; two running out of phase wander it slowly
   around a small open loop, which is what reads as floating.

   Straight translation and nothing else. An earlier version swung each run
   about the hub instead, which anchored the cables for free but canted
   every box and its label off square.

   Because both ends of a cable now move together, nothing pins it to the
   hub -- so each cable is authored to START under the mark, and the solid
   slab is painted over the top of it. The travelling end is never visible;
   the cable just appears to slide slightly where it runs beneath the logo.
   Break that overlap and every cable will visibly swim at the centre.

   alternate rather than a wrap-around keyframe, so nothing jumps back to
   its start mid-drift, and the two pieces closest to the mark are given
   offsets that only ever carry them away from it. */
.d-fig .fl{ --fx2:0px; --fd:7s; }
.d-fig .fl2{ --fy2:0px; --fd2:9s; }
.d-fig.go .fl{ animation:d-driftx var(--fd) ease-in-out infinite alternate; }
.d-fig.go .fl2{ animation:d-drifty var(--fd2) ease-in-out infinite alternate; }
@keyframes d-driftx{ to{ transform:translateX(var(--fx2)); } }
@keyframes d-drifty{ to{ transform:translateY(var(--fy2)); } }

/* ---- the assistant figure -------------------------------------------
   The other two figures diagram a document. This one has to show an
   exchange, which needs actors that stay put while things move between
   them, so it carries three additions the others do not use.

   .tr is one parametric travel: every path in the sequence is the same
   keyframe reading per-element custom properties, rather than a keyframe
   per move. Everything it carries is authored at its DESTINATION and
   travels in from an offset, so the reduced-motion still frame -- where
   transform is reset to none -- lands each piece where the sequence meant
   to leave it rather than where it started.

   .turn shifts the assistant's glyph inside its own disc so it reads as
   facing whatever it is working on. Turning is the one beat a symmetric
   avatar cannot show by rotation alone. Five separate turns compose as
   nested groups because one element can carry only one delay.

   The assistant is the only solid white shape in the set. On this orange
   ground a white fill is the strongest mark available, and the section 13
   rule against alpha-dimmed ink rules out separating the visitors from it
   by opacity on the same treatment -- so they are outline and it is
   filled, which is also the hierarchy the panel wants. */
.d-fig .disc{ fill:#FFFFFF; stroke:none; }
.d-fig .sil{ fill:#FFFFFF; fill-opacity:.62; stroke:none; }
.d-fig .gcb{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace;
  font-size:12px; font-weight:700; letter-spacing:.06em; text-anchor:middle; }
.d-fig .qm{ fill:#FFFFFF; font-family:"IBM Plex Mono",monospace;
  font-size:26px; font-weight:700; text-anchor:middle; }
/* Every property the two keyframes read is declared here, not left to a
   var() fallback. A travel that carries another travel is the normal case
   in this figure -- a visitor enters, then leaves with what it was handed --
   and custom properties inherit, so an inner .tr with no --tx of its own
   silently ran its parent's exit instead of its own entrance. Declaring the
   full set on .tr gives every group its own baseline; the inline style on
   each one still wins over it. */
.d-fig .tr{ opacity:0;
  --fx:0px; --fy:0px; --tx:0px; --ty:0px; --o0:0; --o1:1; --ad:.7s; }
.d-fig.go .tr{ animation:a-travel var(--ad) cubic-bezier(.4,0,.2,1) both; }
.d-fig .turn{ transform-box:fill-box; transform-origin:50% 50%;
  --gx:0px; --gr:0deg; }
.d-fig.go .turn{ animation:a-turn .55s cubic-bezier(.4,0,.2,1) both; }
.d-fig.go .scan2{ animation:a-scan 2.3s cubic-bezier(.4,0,.6,1) both; }
@keyframes a-travel{
  from{ opacity:var(--o0); transform:translate(var(--fx),var(--fy)); }
  to{   opacity:var(--o1); transform:translate(var(--tx),var(--ty)); } }
@keyframes a-turn{ to{ transform:translateX(var(--gx)) rotate(var(--gr)); } }
/* Two passes, and it leaves at the bottom rather than travelling back up:
   returning to the top is where the line spent its last frames sitting
   across the first record at full strength, reading as structure. */
@keyframes a-scan{
  0%{ opacity:0; transform:translateY(0) }
  10%{ opacity:1 }
  40%{ transform:translateY(116px) }
  52%{ transform:translateY(0) }
  88%{ transform:translateY(116px); opacity:1 }
  100%{ transform:translateY(116px); opacity:0 } }

/* WEIGHT 700, NOT 600, AND THE CONTRAST DEPENDS ON IT.
   White on the accent ground measures 3.45:1. That clears AA only under the
   large-text exemption, and large text is "18 point, or 14 point BOLD" --
   18.66px bold. At 20px this copy is over the bold threshold and under the
   plain one, so the exemption is the only thing holding it up and it needs a
   real bold to claim it. It shipped at 600, which is semibold: not bold by any
   checker's reading, so the true requirement was 4.5:1 and the measured 3.45:1
   failed. The comment below already stated the exemption as the justification;
   this makes the justification true rather than restating it.

   It went unnoticed because the blurb is revealed on hover on desktop and was
   hidden outright on phones. Do not drop this to 600, and do not raise the
   size past this without re-measuring: only the bold branch applies here. */
.site .d-p p{ margin:22px 0 0; padding:0; font-family:"Inter Tight",sans-serif;
  font-size:20px; font-weight:700; line-height:1.5; color:#FFFFFF;
  max-width:42ch; }
/* The link stays dark ink. White at 12px/500 is 3.45:1, and no exemption
   reaches a 12px link at any weight. --gc-txt is 5.01:1 and the underline
   still marks it as a target. */
.site .d-p .a-go{ color:var(--gc-txt); }
/* The stage box is reserved at rest so nothing jumps, which on the options
   sheet cost nothing -- a reviewer is always hovering there. On the home page
   an unhovered visitor met that reservation as empty ground, so the figure is
   capped. That halves the band -- 531px against 845 -- but does not close it:
   the index is 172px, so roughly 360px of the reserved stage is still empty
   until something is hovered. Closing it entirely means showing one service at
   rest, which is a content decision rather than a CSS one. */
.d-fig{ max-width:430px; }
@media (min-width:1000px){ .d-fig{ max-width:470px; } }

/* No stage, no hover: keyed on WIDTH as well as pointer type. The two-column
   stage only exists above 1000px, so a narrow desktop window fell between the
   two paths -- stacked layout with a hover-only panel sitting in row 2, below
   all three names, 200px from the cursor that opened it.

   Reveal depends on hover, focus-within and pointerenter, so on touch the
   three descriptions and their links were unreachable -- the rows are links, and a tap navigates away. Here the index
   becomes what it replaced: name, description, link, three times over.
   display:contents lets the rows leave their wrapper so each one can sit
   directly above its own panel without changing the markup.

   The figures used to be dropped here on the grounds that the sequence cannot
   play without a pointer. That was never true of the sequence, only of the
   trigger: the product pages run the SAME figures from an IntersectionObserver
   in site.js and have done since .gc-service-demo shipped. site.js now drives
   these panels from that observer too, so a phone reader sees the drawing that
   explains each service instead of a bare list of three names. */
@media (max-width:1000px), (hover:none), (pointer:coarse){
  /* the stage state, published once. site.js and the hover driver in
     source/home.html both read this instead of restating the query -- see the
     --gc-stack note above, which this follows for the same reasons. It is what
     decides which of the two drivers owns these figures. */
  .site{ --gc-stage:stacked; }
  .dstage{ display:flex; flex-direction:column; }
  .d-idx{ display:contents; }
  .gc-js .d-p{ opacity:1; visibility:visible; transition:none;
    margin:0 0 34px; max-width:52ch; }
  .site .d-p p{ margin:14px 0 0; }
  .dstage .gc-h2{ order:0; }
  .r1{ order:1 } .p1{ order:2 }
  .r2{ order:3 } .p2{ order:4 }
  .r3{ order:5 } .p3{ order:6 }
  .d-row{ border-bottom:0; padding-bottom:2px; }
  .d-row:first-of-type{ border-top:0; }
  .p1, .p2{ border-bottom:1px solid rgba(26,7,0,.3); padding-bottom:30px; }
}
.d-p .a-go{ margin-top:18px; }
/* The reduced-motion still frame must be the sequence's END state, not
   every phase at once. A blanket reset gives the second: the list never
   vacates, so the deliverable sheet lands on top of it, and the X strokes --
   which the sequence exists to clear -- sit under the checks that replaced
   them. Anything transient is dropped, and anything whose end state is a
   transform keeps that transform. */
@media (prefers-reduced-motion: reduce){
  .d-row, .d-name, .d-p{ transition:none; }
  /* Every reset needs !important: this selector is (0,1,0) and the resting
     state it has to overturn lives on two-class selectors at (0,2,0). */
  .d-fig *{ animation:none !important; opacity:1 !important;
    stroke-dashoffset:0 !important; transform:none !important; }
  /* The read pass is a bare line with nowhere to be at rest: reset to
     transform:none it lies across the top record as if it were structure. */
  .d-fig .gone, .d-fig .veil, .d-fig .scan2{ display:none; }
  .d-fig .shift{ transform:translateX(-196px) !important; }
  .d-fig .mv{ transform:translate(var(--mx),var(--my)) scale(.52) !important; }
  .d-fig .post{ transform:translate(-118px,38px) !important; }
  .d-fig .stampbox{ transform:rotate(-5deg) !important; }
}

@media(max-width:720px){.site .gc-service-demo{margin:24px -8px 22px}}
/* The home panels carry the same drawings at the same widths, so they need the
   same SVG-text compensation -- see the trap in DESIGN.md section 10: SVG text
   renders at authored size times the SVG's scale factor, so a label that reads
   correctly on a desktop becomes mush once the 480-unit viewBox is squeezed
   into a 360px phone. Both selectors move together or the home figures lose
   their labels while the product ones keep theirs. */
@media(max-width:506px){
  .site .gc-service-demo .d-fig .lab,
  .site .gc-service-demo .d-fig .num,
  .site .gc-service-demo .d-fig .tag,
  .site .gc-service-demo .d-fig .dol,
  .site .gc-service-demo .d-fig .stamp,
  .site .dstage .d-p .d-fig .lab,
  .site .dstage .d-p .d-fig .num,
  .site .dstage .d-p .d-fig .tag,
  .site .dstage .d-p .d-fig .dol,
  .site .dstage .d-p .d-fig .stamp{font-size:16.5px;letter-spacing:0}
}
/* 16.5px IS THE LARGEST SIZE THAT FITS, AND THE LIMIT IS GEOMETRY.
   A second tier below 361px used to take these to 19px, chasing the legibility
   floor. It cannot be had that way: this compensation raises the label in
   DRAWING units, and the boxes those labels sit inside are hand-drawn at fixed
   coordinates in the 480x240 space. The text grows; the box never does.

   At 19px, two labels ran through their own borders. LIEN DOCS on Custom
   Automations measured 102.6 units inside a 96-unit tile, and READY FOR BID on
   the Bid Scope stamp measured 148.2 inside the 134-unit INNER rule it sits in
   -- not the 144-unit outer rule, which is the one that looks like the box and
   is not the one that binds. At 16.5px every label on all four figure surfaces
   fits at 390, 360 and 344px.

   AND IT FITS BY VERY LITTLE, so treat this as a fixed budget. One monospace
   character is 9.9 units at this size. LIEN DOCS clears 3.45 units a side and
   READY FOR BID clears 2.69: a single character added to either label puts it
   back through the border. The true ceiling the boxes allow is about 17.2px,
   so there is no useful headroom above 16.5 either.

   The geometry is NOT in build/art.py -- that file draws the unrelated 640x300
   gc-fig-svg plates. These figures are authored in source/home.html and
   source/partials/bid-scope-animation.html. Raising this number means widening
   a box there, or shortening a label.

   The accepted cost, measured rather than implied. Rendered label size, with no
   classic scrollbar in the way, which is what a phone gives you:

     viewport   product pages   home stage
     390px        12.99px         12.44px
     360px        11.96px         11.41px
     344px        11.41px         10.86px

   So the 11.5px floor in DESIGN.md is crossed below about 347px on the product
   pages and below about 362px on the narrower home stage. Ryan chose that over
   text escaping its box on 2026-08-15. An earlier version of this note quoted
   sizes about half a pixel smaller and one threshold of "roughly 365px" for
   both: those were measured in a desktop iframe whose 15px scrollbar ate into
   the plate. Measure with the scrollbar suppressed or the numbers flatter the
   problem. */
/* ---------------------------------------------------------------------------
   DRAFT WATERMARK — legal pages only.
   This banner is the thing that stops an unreviewed policy going live. It is
   deliberately loud and deliberately not dismissible. Remove it per-page only
   when counsel has signed off on that specific document.
   ------------------------------------------------------------------------ */
.site .gc-draft{background:var(--gc-o);color:#0A0A0A;padding:11px 14px;
  font-size:13.5px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  line-height:1.5;text-align:center}
@media(min-width:900px){.site .gc-draft{padding:12px 30px}}
.site .gc-draft b{font-weight:700}

/* ---------- legal prose ---------- */
.site .gc-prose{font-family:var(--gc-body);font-size:17.5px;line-height:1.72;color:var(--gc-prose-c);
  letter-spacing:0;text-transform:none;max-width:76ch}
.site .gc-prose h2{font-family:var(--gc-disp);font-size:20px;font-weight:700;color:var(--gc-ink);
  letter-spacing:-.015em;text-transform:none;margin:54px 0 0;padding-top:30px;
  border-top:1px solid var(--gc-line)}
.site .gc-prose h2:first-child{margin-top:0;padding-top:0;border-top:0}
.site .gc-prose h3{font-family:var(--gc-disp);font-size:16px;font-weight:700;color:var(--gc-ink);
  letter-spacing:-.005em;text-transform:none;margin:32px 0 0}
.site .gc-prose p{margin-top:16px}
.site .gc-prose ul,.site .gc-prose ol{margin-top:16px;padding-left:0}
.site .gc-prose li{position:relative;padding-left:20px;margin-top:10px}
.site .gc-prose ul>li::before{content:"";position:absolute;left:2px;top:9px;
  width:6px;height:6px;background:var(--gc-line2)}
.site .gc-prose ol{counter-reset:gcp}
.site .gc-prose ol>li{counter-increment:gcp}
.site .gc-prose ol>li::before{content:counter(gcp) ".";position:absolute;left:0;top:0;
  font-family:var(--gc-mono);font-size:14px;font-weight:500;color:var(--gc-o)}
.site .gc-prose strong{color:var(--gc-ink);font-weight:600}
.site .gc-prose a{color:var(--gc-ink);border-bottom:1px solid var(--gc-line2)}
.site .gc-prose a:hover{color:var(--gc-o);border-color:var(--gc-o)}
/* every unresolved bracket is visually marked so it cannot be skimmed past */
.site .gc-prose var{font-style:normal;font-family:var(--gc-mono);font-size:14.5px;
  font-weight:500;letter-spacing:.03em;color:var(--gc-o);
  background:rgba(255,77,0,.09);border:1px solid rgba(255,77,0,.3);padding:1px 5px;
  white-space:normal}
.site .gc-prose table{width:100%;border-collapse:collapse;margin-top:18px;font-size:16px}
.site .gc-prose th{text-align:left;padding:10px 12px;font-family:var(--gc-mono);font-size:13.5px;
  font-weight:500;letter-spacing:.09em;text-transform:uppercase;color:var(--gc-mid);
  border:1px solid var(--gc-line);background:var(--gc-bg2)}
.site .gc-prose td{padding:11px 12px;border:1px solid var(--gc-line);vertical-align:top}

.site .gc-legal-meta{display:flex;flex-wrap:wrap;gap:8px 26px;margin-top:20px;
  padding:16px 0;border-top:1px solid var(--gc-line);border-bottom:1px solid var(--gc-line)}

/* on-page contents for long legal documents */
.site .gc-toc{margin-top:24px;border:1px solid var(--gc-line);padding:18px 20px 20px;
  background:var(--gc-bg2)}
.site .gc-toc ol{margin-top:12px;columns:1}
@media(min-width:760px){.site .gc-toc ol{columns:2;column-gap:34px}}
.site .gc-toc li{break-inside:avoid;padding:5px 0;font-family:var(--gc-body);font-size:16px}
.site .gc-toc a{color:var(--gc-txt)}
.site .gc-toc a:hover{color:var(--gc-o)}

/* ---------------------------------------------------------------------------
   ICONS
   Drafting linework, not UI glyphs: hairline strokes, square caps, no fill.
   The base takes currentColor so an icon adopts the mood of its container;
   exactly one element per icon carries .a for the accent.
   ------------------------------------------------------------------------ */
.site .gc-ic{display:block;width:38px;height:38px;margin-bottom:20px;color:var(--gc-icon);
  transition:color .18s ease}
.site .gc-ic svg{display:block;width:100%;height:100%;fill:none;stroke:currentColor;
  stroke-width:1.4;stroke-linecap:square;stroke-linejoin:miter;overflow:visible}
.site .gc-ic .a{stroke:var(--gc-o)}
.site a.gc-card:hover .gc-ic{color:var(--gc-prose-c)}
/* the product cards on the home page carry the icon at a larger size */
.site .gc-prod .gc-ic{width:46px;height:46px;margin-bottom:24px}
/* an icon sitting beside a number in a process step */
.site .gc-st .gc-ic{width:32px;height:32px;margin-bottom:14px}

/* ---------------------------------------------------------------------------
   FIGURE PLATES
   Full-width line drawings in the hero's register.

   The plate scrolls rather than scaling below 640px. This is deliberate: SVG
   text renders at authored size times the SVG scale factor, so a label sized
   to look right on a desktop turns into 5px mush on a phone. Holding the
   drawing at true scale and panning it keeps every label legible. See the
   SVG-text trap in DESIGN.md -- this project has paid for it twice.
   ------------------------------------------------------------------------ */
.site .gc-fig{margin-top:44px}
.site .gc-fig-plate{border:1px solid var(--gc-line);background:var(--gc-plate);
  padding:18px 0;overflow-x:auto;position:relative}
@media(min-width:900px){.site .gc-fig-plate{padding:26px 0}}
.site .gc-sec-alt .gc-fig-plate{background:#0A0A0A}
.site .gc-fig-svg{display:block;width:100%;min-width:620px;height:auto}
.site .gc-fig-image-plate{padding:0;overflow:hidden}
.site .gc-fig-image{display:block;width:100%;height:auto}
.site .gc-fig-cap{margin-top:14px;color:var(--gc-note-c)}

/* A captured screen from the client app. The asset is 1360 wide so it stays
   crisp on a large display, which means it is wider than the measure and must
   be held to its column — without this it runs past the sheet. A hairline keeps
   the app's own dark ground from bleeding into the sheet's edge. */
/* margin:0 first -- a <figure> carries a 40px side margin by default, which
   indented every capture away from the copy it belongs to. */
.site .gc-shot{margin:32px 0 0}
.site .gc-shot img{display:block;width:100%;height:auto;border:1px solid var(--gc-line)}
.site .gc-shot figcaption{margin-top:12px;color:var(--gc-note-c)}
.site .gc-shot figcaption b{color:var(--gc-o);font-weight:500}
@media(min-width:900px){.site .gc-shot{margin-top:40px}}
/* Three UI sketches side by side. These carry no labels, so they are exempt
   from the 620-unit authoring floor that keeps mono type at its true size --
   which is the only reason a figure may be drawn this small. The override is
   scoped to this grid so it cannot leak onto a plate that does have text. */
.site .gc-ui-grid{display:grid;grid-template-columns:1fr;gap:14px;margin-top:30px}
@media(min-width:760px){.site .gc-ui-grid{grid-template-columns:repeat(3,1fr);gap:18px}}
.site .gc-ui-grid .gc-fig-plate{padding:0;overflow:hidden}
.site .gc-ui-grid .gc-fig-svg{min-width:0}
/* same reason as the offer rows: the wrapper's separating margin is wrong
   inside a grid cell, where the grid gap already does that job */
.site .gc-ui-grid .gc-fig{margin-top:0;min-width:0}

/* Hub leads with the product itself rather than a headline over an empty band,
   because it is the one offering that is a screen. The hero keeps its parallax
   planes clipped, so the sheet simply grows to hold the capture. */
.site .gc-hub-hero .gc-shot{margin-top:36px;max-width:1040px}
@media(min-width:900px){.site .gc-hub-hero .gc-shot{margin-top:48px}}
.site .gc-fig-cap b{color:var(--gc-o);font-weight:500}

/* The drawing-plate pen and grid. .gc-flow-art used to drive these and was
   orphaned when A-01 was rebuilt; the plate in source/home.html:333,335 is the
   remaining owner, and it carries its own reduced-motion reset. */
@keyframes gc-plate-pen{
  0%{left:0;opacity:0}10%{opacity:.9}86%{opacity:.9}100%{left:100%;opacity:0}}
@keyframes gc-plate-grid{
  0%{opacity:0}14%{opacity:1}50%{opacity:1}100%{opacity:0}}

.site .gc-fig-svg{fill:none;stroke-linecap:square;stroke-linejoin:miter}
.site .gc-fig-rule{stroke:var(--gc-tick);stroke-width:1}
.site .gc-fig-ln{stroke:var(--gc-draw);stroke-width:1.25}
.site .gc-fig-fine{stroke:var(--gc-draw-fine);stroke-width:1}
.site .gc-fig-acc{stroke:var(--gc-o);stroke-width:1.4}
.site .gc-fig-svg circle{fill:none}
/* authored at 11.5px against a 620-unit minimum width, so the smallest this
   ever renders is 11.5px -- the same floor as the rest of the site */
.site .gc-fig-t{font-family:var(--gc-mono);font-size:13px;font-weight:500;
  letter-spacing:.1em;fill:var(--gc-note-c);stroke:none}
.site .gc-fig-t-a{fill:var(--gc-o)}
/* The brand mark inside a figure. Figures are stroke-only, and DESIGN.md §5
   requires the mark be real outlined path data rather than type -- as type it
   silently degrades to a fallback face and stops being the logo. So the letters
   come from the approved private kit's GC Total mono mark and use this one hook,
   which is also the only place a figure is allowed to fill anything. */
.site .gc-fig-svg .gc-fig-mark{fill:var(--gc-draw);fill-rule:evenodd;stroke:none}

/* ---------------------------------------------------------------------------
   REVEAL
   Sections rule themselves in as they are scrolled to, the same way the hero
   headline drafts itself. One observer, unobserved after firing, so there is
   no standing scroll listener.
   ------------------------------------------------------------------------ */
/* EVERY hiding rule below is gated behind .gc-js, which a one-line inline script
   in <head> sets before first paint. If that script or site.js ever fails to
   run, none of these rules match and the page is simply fully visible. Hiding
   content by default and revealing it with JS would mean a script error blanks
   the site -- never do that. */
.gc-js .site [data-reveal]{opacity:0;transform:translateY(16px);
  transition:opacity .7s cubic-bezier(.2,.8,.3,1),transform .7s cubic-bezier(.2,.8,.3,1)}
.gc-js .site [data-reveal].is-in{opacity:1;transform:none}
.gc-js .site [data-reveal].d1{transition-delay:.08s}
.gc-js .site [data-reveal].d2{transition-delay:.16s}
.gc-js .site [data-reveal].d3{transition-delay:.24s}

/* the figure draws itself: long strokes rule in, small parts fade after */
@keyframes gc-draw{to{stroke-dashoffset:0}}
.gc-js .site .gc-fig .draw{stroke-dasharray:1400;stroke-dashoffset:1400}
.gc-js .site .gc-fig.is-in .draw{animation:gc-draw 1.5s cubic-bezier(.25,.75,.3,1) both}
.gc-js .site .gc-fig .pop,.gc-js .site .gc-fig text{opacity:0}
.gc-js .site .gc-fig.is-in .pop,
.gc-js .site .gc-fig.is-in text{animation:gc-fade .7s ease .75s both}

/* ---------------------------------------------------------------------------
   CLOSING-SHEET ARTWORK
   Lifted out of home.html so the homepage is no longer the only page that can
   carry it. The markup and the drift classes are unchanged; only the home page
   knew them before, which is why the Hub close had to be built twice to get
   this far.

   `overflow:clip` not `hidden`: hidden computes overflow-y to auto and makes
   the sheet a scroll container, which silently breaks the sticky sheet stack.
   ------------------------------------------------------------------------ */
.site .gc-close{overflow:clip}
.site .gc-close>.gc-w{position:relative;z-index:2}
.site .gc-close-bg{position:absolute;inset:0;z-index:0;pointer-events:none}
.site .gc-close-grid{position:absolute;inset:-16px;
  background-image:
    linear-gradient(to right,rgba(255,255,255,.13) 1px,transparent 1px),
    linear-gradient(to bottom,rgba(255,255,255,.13) 1px,transparent 1px);
  background-size:52px 52px;
  -webkit-mask-image:radial-gradient(ellipse 84% 76% at 50% 50%,#000 30%,transparent 100%);
  mask-image:radial-gradient(ellipse 84% 76% at 50% 50%,#000 30%,transparent 100%);
  transform:translate3d(var(--gc-cgx,0px),var(--gc-cgy,0px),0);
  transition:transform .42s cubic-bezier(.2,.8,.3,1)}
/* two depth planes: far moves least, near most, at the interior echo strength
   rather than the home hero's full throw -- a closing sheet should not compete
   with its own button */
.site .gc-close-p1{position:absolute;inset:0;
  transform:translate3d(var(--gc-cpx,0px),var(--gc-cpy,0px),0);
  transition:transform .42s cubic-bezier(.2,.8,.3,1)}
.site .gc-close-p2{position:absolute;inset:0;
  transform:translate3d(var(--gc-cqx,0px),var(--gc-cqy,0px),0);
  transition:transform .45s cubic-bezier(.2,.8,.3,1)}
.site .gc-close-svg{position:absolute;inset:0;width:100%;height:100%;
  display:block;overflow:clip;shape-rendering:geometricPrecision}
.site .gc-close-svg *{vector-effect:non-scaling-stroke}
.site .gc-close-svg .cgl{fill:none;stroke:rgba(255,255,255,.20);stroke-width:1;
  stroke-dasharray:52 11 4 11}
.site .gc-close-svg .ccut{fill:none;stroke:rgba(255,255,255,.30);stroke-width:1.4}
.site .gc-close-svg .cvis{fill:none;stroke:rgba(255,255,255,.22);stroke-width:1}
.site .gc-close-svg .cbub{fill:none;stroke:rgba(255,255,255,.26);stroke-width:1.2}
.site .gc-close-svg .cdot{fill:none;stroke:rgba(255,255,255,.30);stroke-width:1.2}
.site .gc-close-svg .ctx{fill:rgba(255,255,255,.30);font-family:var(--gc-mono);
  font-size:26px;font-weight:500;letter-spacing:.04em;text-anchor:middle}
.site .gc-close-svg .ctxs{fill:rgba(255,255,255,.24);font-family:var(--gc-mono);
  font-size:22px;font-weight:500;letter-spacing:.1em}
.site .gc-close-svg .cdrift{animation:gc-close-drift 46s ease-in-out infinite alternate}
.site .gc-close-svg .cdrift2{animation:gc-close-drift2 29s ease-in-out infinite alternate}
@keyframes gc-close-drift{from{transform:translateY(0)}to{transform:translateY(4px)}}
@keyframes gc-close-drift2{from{transform:translateY(0)}to{transform:translateY(-6px)}}
/* ground-coloured, so it can only subtract the drawing behind the copy */
.site .gc-close-veil{position:absolute;inset:0;
  background:radial-gradient(ellipse 58% 52% at 50% 50%,
    color-mix(in srgb,var(--gct-o) 94%,transparent) 0%,
    color-mix(in srgb,var(--gct-o) 82%,transparent) 46%,
    color-mix(in srgb,var(--gct-o) 34%,transparent) 74%,
    color-mix(in srgb,var(--gct-o) 0%,transparent) 100%)}
@media (prefers-reduced-motion:reduce){
  .site .gc-close-svg .cdrift,.site .gc-close-svg .cdrift2{animation:none}
  .site .gc-close-grid,.site .gc-close-p1,.site .gc-close-p2{
    transform:none;transition:none}
}

/* ---------------------------------------------------------------------------
   THE HUB CLOSE INVERTS UNDER THE POINTER
   Three equal doors into one product, so none of them may be styled as the
   preferred one. What distinguishes them is which you are pointing at: hovering
   any button turns the whole sheet from the accent ground to the dark one and
   fills that button.

   The ground is a variable set, not a background colour, so the flip restores
   the base tokens from .site rather than painting over them -- otherwise the
   copy stays dark-on-dark. Everything .gc-sec-accent restated has to be
   restated back, which is why this block looks longer than the effect.
   ------------------------------------------------------------------------ */
.site .gc-close-flip{transition:background-color .3s cubic-bezier(.2,.8,.3,1)}
/* This restates the transition, so transform and box-shadow have to be listed
   again or the lift lands instantly on the one page that uses the flip. */
.site .gc-close-flip .gc-b{transition:background-color .3s cubic-bezier(.2,.8,.3,1),
  color .3s cubic-bezier(.2,.8,.3,1),border-color .3s cubic-bezier(.2,.8,.3,1),
  transform .18s cubic-bezier(.2,.8,.3,1), box-shadow .22s ease}
.site .gc-close-flip:has(.gc-b:hover){
  background:#0A0A0A;
  --gc-bg:#0A0A0A; --gc-bg2:#111111; --gc-ink:#F2F2F2; --gc-mid:#8C8C8C;
  --gc-line:#262626; --gc-line2:#3A3A3A; --gc-edge:#6E6E6E;
  --gc-txt:#ABABAB; --gc-dim:#979797; --gc-prose-c:#B4B4B4;
  --gc-note-c:#7A7A7A;
  --gc-o:var(--gct-o,#F25513); --gc-on-o:#0A0A0A;
  color:var(--gc-ink)}
.site .gc-close-flip:has(.gc-b:hover) .gc-sub{color:var(--gc-txt)}
.site .gc-close-flip:has(.gc-b:hover) .gc-ln{--gc-stroke:rgba(255,255,255,.9)}
/* the veil is painted in the ground colour, so it has to follow the ground */
.site .gc-close-flip:has(.gc-b:hover) .gc-close-veil{
  background:radial-gradient(ellipse 58% 52% at 50% 50%,
    rgba(10,10,10,.94) 0%,rgba(10,10,10,.82) 46%,
    rgba(10,10,10,.34) 74%,rgba(10,10,10,0) 100%)}
/* The accent ground hard-codes the outlined button's ink and border rather than
   taking them from tokens, so re-declaring the ground cannot reach them: without
   this the two buttons you are NOT pointing at stay near-black on the near-black
   sheet and effectively vanish. Restated against the flipped tokens. */
.site .gc-close-flip:has(.gc-b:hover) .gc-b2{
  color:var(--gc-ink);border-color:var(--gc-line2)}
/* the one being pointed at fills; its two siblings stay outlined */
.site .gc-close-flip .gc-b:hover,
.site .gc-close-flip:has(.gc-b:hover) .gc-b2:hover{
  background:var(--gc-o);color:var(--gc-on-o);border-color:var(--gc-o)}

/* ---------- footer ---------- */
.site .gc-foot{border-top:1px solid var(--gc-line);padding:40px 0 0;margin-top:0}
.site .gc-foot-grid{display:grid;grid-template-columns:1fr;gap:32px;padding-bottom:34px}
@media(min-width:760px){.site .gc-foot-grid{grid-template-columns:1.4fr 1fr 1fr 1fr;gap:26px}}
.site .gc-foot h4{font-size:14px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  color:var(--gc-mid);margin-bottom:14px}
.site .gc-foot li{margin-top:9px}
.site .gc-foot li a{font-family:var(--gc-body);font-size:16px;color:var(--gc-txt);
  letter-spacing:0;text-transform:none}
.site .gc-foot li a:hover{color:var(--gc-o)}
/* A 14px footer link is a 17px-tall target. That CONFORMS to WCAG 2.2 SC
   2.5.8 -- the spacing exception clears an undersized target whose 24px circle
   meets no other, and the measured pitch here is 33px -- so this is a comfort
   change, not a conformance fix, and must not be recorded as one. It is still
   a poor target for a thumb. The target grows, not the type: inline-flex gives
   the anchor a box to fill, and the list spacing gives back MOST of what the
   taller box takes -- the box grows 19px and the margin returns 8, so the
   pitch moves 33px to 37px rather than holding. The Login control is already a
   44px button. Keyed on pointer rather than width: a narrow desktop window
   driven by a mouse does not need bigger targets. */
@media (hover:none), (pointer:coarse){
  .site .gc-foot li{margin-top:1px}
  .site .gc-foot li a{display:inline-flex;align-items:center;min-height:36px}
}
.site .gc-foot-brand p{font-family:var(--gc-body);font-size:16px;line-height:1.6;
  color:#8C8C8C;margin-top:14px;max-width:34ch;letter-spacing:0;text-transform:none}
.site .gc-foot-bar{border-top:1px solid var(--gc-line);padding:16px 0 30px;
  display:flex;flex-wrap:wrap;gap:10px 22px;align-items:center;justify-content:space-between}
.site .gc-foot-bar p{font-size:13px;font-weight:500;letter-spacing:.06em;color:var(--gc-note-c);
  text-transform:none;line-height:1.6}

@media (prefers-reduced-motion: reduce){
  .site .gc-node-login{animation:none;background:var(--gct-o,#F25513)}
  .site .gc-node-login::after{animation:none}
  .site .gc-nav,.site .gc-nav-toggle-mark i{transition:none}
  .site .gc-guides{animation:none;opacity:.13}
  .site .gc-guides .gh{animation:none;transform:scaleX(1)}
  .site .gc-guides .gv{animation:none;transform:scaleY(1)}
  .site .gc-ln::before{animation:none;opacity:.34}
  .site .gc-ln i{animation:none;clip-path:inset(0 0 0 0)}
  .site .gc-sub,.site .gc-cta{animation:none;opacity:1}
  .site .gc-menu-p{transition:none}
  /* reveals resolve to their finished state rather than never arriving */
  .gc-js .site [data-reveal]{opacity:1;transform:none;transition:none}
  .gc-js .site .gc-fig .draw{stroke-dasharray:none;stroke-dashoffset:0;animation:none}
  .gc-js .site .gc-fig .pop,.gc-js .site .gc-fig text{opacity:1;animation:none}
  .site .gc-phero .gc-pgrid,.site .gc-phero .gc-pcoarse{
    transform:none !important;transition:none}
}
