/* ===== forms.css ===== */
/* The three overlay roots carry the `hidden` attribute in the markup, so a
   page whose stylesheet never arrives does not end with an inline copy of the
   popup form and the booking dialog as readable content. Once this file IS
   loaded, the attribute stops doing the hiding and the existing
   visibility/display rules take over, so opening still works. */
.lp-overlay[hidden],.lp-slide[hidden],.bk-overlay[hidden]{display:revert}

/* ============================================================
   Terso AI lead capture: inline forms + popups.
   Loaded by every page (homepage inlines its own design system,
   subpages load site.css first). Uses only the shared tokens
   defined in :root, so it inherits the site design system and
   never forks it.
   ============================================================ */

/* ---------------------------------------------------------- shared controls */
.lf{--lf-gap:14px}
.lf *{box-sizing:border-box}

.lf-field{display:block;text-align:left}
.lf-field + .lf-field{margin-top:var(--lf-gap)}
.lf-label{display:block;font-family:var(--font-b);font-size:13.5px;font-weight:500;
  letter-spacing:-.004em;color:var(--text-2);margin-bottom:7px}
.lf-label .lf-opt{color:var(--text-3);font-weight:400}
.lf-req{color:var(--accent-deep);margin-left:2px}

.lf-input,.lf-select,.lf-textarea{
  width:100%;display:block;font-family:var(--font-b);font-size:16px;line-height:1.5;
  color:var(--text-1);background:var(--card);
  border:1px solid var(--line-2);border-radius:var(--r-s);
  padding:13px 14px;appearance:none;-webkit-appearance:none;
  transition:border-color .25s ease,box-shadow .25s ease,background .25s ease}
.lf-textarea{min-height:104px;resize:vertical}
.lf-select{padding-right:40px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236d6680' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 13px center;background-size:17px}
.lf-input:hover,.lf-select:hover,.lf-textarea:hover{border-color:var(--text-3)}
.lf-input:focus,.lf-select:focus,.lf-textarea:focus{
  outline:none;border-color:var(--accent-deep);box-shadow:0 0 0 3px var(--accent-ring-strong)}
.lf-input:focus-visible,.lf-select:focus-visible,.lf-textarea:focus-visible{outline:none}
.lf-input[aria-invalid="true"],.lf-select[aria-invalid="true"],.lf-textarea[aria-invalid="true"]{
  border-color:#b4232b;background:#fffafa}
.lf-input[aria-invalid="true"]:focus,.lf-textarea[aria-invalid="true"]:focus{box-shadow:0 0 0 3px rgba(180,35,43,.14)}

.lf-err{display:none;margin-top:6px;font-size:13.5px;line-height:1.45;color:#a51f27}
.lf-field.is-invalid .lf-err{display:block}

/* honeypot: off-screen for sighted users, hidden from assistive tech */
.lf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.lf-row{display:grid;gap:var(--lf-gap);grid-template-columns:1fr 1fr;align-items:start}
.lf-row + .lf-field,.lf-field + .lf-row,.lf-row + .lf-row{margin-top:var(--lf-gap)}
/* inside a row the gap does the spacing, so the sibling rule must not also
   push the second field down and break the baseline across the pair */
.lf-row > .lf-field + .lf-field{margin-top:0}
@media (max-width:620px){.lf-row{grid-template-columns:1fr}}

.lf-actions{margin-top:20px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.lf-submit{display:inline-flex;align-items:center;gap:10px;padding:14px 26px;border:0;
  border-radius:999px;background:var(--ink);color:var(--paper);
  font-family:var(--font-b);font-size:15.5px;font-weight:500;letter-spacing:-.006em;cursor:pointer;
  transition:transform .4s var(--ease),box-shadow .5s var(--ease),opacity .25s ease}
.lf-submit:hover{transform:translateY(-2px);box-shadow:0 22px 46px -20px rgba(16,13,20,.58)}
.lf-submit[disabled]{opacity:.6;cursor:progress;transform:none;box-shadow:none}
.lf-submit .ar{transition:transform .35s var(--ease)}
.lf-submit:hover .ar{transform:translateX(3px)}
.lf-alt{font-size:14.5px;color:var(--text-3)}
.lf-alt a{color:var(--ink);border-bottom:1px solid var(--line-2)}
.lf-alt a:hover{color:var(--accent-deep);border-bottom-color:var(--accent)}

.lf-fine{margin-top:16px;font-size:13px;line-height:1.55;color:var(--text-3);max-width:56ch}
.lf-fine a{border-bottom:1px solid var(--line-2)}

/* status region: reserves no space until it has something to say */
.lf-status{margin-top:16px}
.lf-status:empty{margin-top:0}
.lf-note{display:flex;gap:11px;align-items:flex-start;padding:14px 16px;border-radius:var(--r-s);
  font-size:14.5px;line-height:1.55;text-align:left}
.lf-note.ok{background:#f0fbf4;border:1px solid #bfe6cd;color:#14562f}
.lf-note.bad{background:#fff5f5;border:1px solid #f0c9cb;color:#8f1c23}
.lf-note a{text-decoration:underline}
.lf-note-ic{flex:none;width:18px;height:18px;margin-top:1px}

/* success panel replaces the fields once a lead is stored */
.lf-done{text-align:left;padding:4px 0}
.lf-done h3{font-size:20px;letter-spacing:-.02em}
.lf-done p{margin-top:10px;color:var(--text-2);font-size:15.5px;line-height:1.6}
.lf-done .lf-ref{margin-top:14px;font-family:var(--font-m);font-size:12.5px;color:var(--text-3);
  letter-spacing:.02em}

/* ---------------------------------------------------------- inline section */
.lead-block{background:var(--card);border:1px solid var(--line);border-radius:var(--r-l);
  padding:clamp(24px,3.4vw,40px);box-shadow:0 26px 60px -46px rgba(16,13,20,.42);text-align:left}
.lead-block .lb-head h2,.lead-block .lb-head h3{font-size:clamp(21px,2.4vw,27px);letter-spacing:-.028em;line-height:1.14}
.lead-block .lb-head p{margin-top:11px;color:var(--text-2);font-size:16px;line-height:1.6;max-width:52ch}
.lead-block .lf{margin-top:24px}

/* two-column: copy on the left, form on the right */
.lead-split{display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1fr);
  gap:clamp(28px,4vw,60px);align-items:start;text-align:left}
@media (max-width:900px){.lead-split{grid-template-columns:1fr}}
.lead-split .ls-copy h2{font-size:clamp(27px,3.6vw,42px);line-height:1.08;letter-spacing:-.033em}
.lead-split .ls-copy p{margin-top:18px;color:var(--text-2);font-size:clamp(16px,1.6vw,18px);line-height:1.62;max-width:44ch}
.lead-split .ls-points{margin:24px 0 0;padding:0;list-style:none}
.lead-split .ls-points li{position:relative;padding-left:24px;margin-top:12px;
  color:var(--text-2);font-size:15.5px;line-height:1.58}
.lead-split .ls-points li::before{content:"";position:absolute;left:0;top:9px;width:9px;height:9px;
  border-radius:3px;background:var(--accent);opacity:.55}

/* "What do you want built?" band: centred under a centred head, with the
   free-text box given the height that tells someone to actually write in it */
.ba-block{max-width:760px;margin-inline:auto;margin-top:clamp(28px,3.4vw,40px)}
.ba-block .lf-textarea{min-height:170px}
@media (max-width:600px){.ba-block .lf-textarea{min-height:140px}}

/* the closing CTA is centred, so the form inside it needs a leash */
.cta .lead-block{max-width:620px;margin-inline:auto;margin-top:36px}
.cta .lead-block .lb-head{text-align:left}
.cta-or{margin-top:26px;font-size:14px;color:var(--text-3);letter-spacing:.02em}

/* dark band variant, so a form can sit on the ink sections */
.band-dark .lead-block{background:rgba(255,255,255,.045);border-color:rgba(255,255,255,.14);box-shadow:none}
.band-dark .lead-block .lb-head h2,.band-dark .lead-block .lb-head h3{color:var(--dark-1)}
.band-dark .lead-block .lb-head p,.band-dark .lf-fine{color:var(--dark-3)}
.band-dark .lf-label{color:var(--dark-2)}
.band-dark .lf-input,.band-dark .lf-select,.band-dark .lf-textarea{
  background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.18);color:var(--dark-1)}
.band-dark .lf-input::placeholder,.band-dark .lf-textarea::placeholder{color:var(--dark-3)}
.band-dark .lf-submit{background:var(--paper);color:var(--ink)}
.band-dark .lf-alt,.band-dark .lf-alt a{color:var(--dark-2)}

/* ---------------------------------------------------------- popup: modal */
/* flex-start plus margin:auto centres the panel when it fits and keeps the top
   of it reachable when it does not, which is the case on short phone screens.
   Hidden by visibility rather than display, so closing animates too. */
.lp-overlay{position:fixed;inset:0;z-index:200;
  display:flex;align-items:flex-start;justify-content:center;
  padding:clamp(16px,4vh,48px) clamp(14px,4vw,32px);
  overflow-y:auto;background:rgba(11,8,16,.52);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .32s var(--ease),visibility 0s linear .32s}
.lp-overlay.is-open{opacity:1;visibility:visible;pointer-events:auto;
  transition:opacity .32s var(--ease),visibility 0s linear 0s}
.lp-panel{margin:auto;position:relative;width:100%;max-width:520px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r-l);
  padding:clamp(26px,3.4vw,38px);box-shadow:0 50px 110px -40px rgba(8,6,14,.6);
  text-align:left;
  opacity:0;transform:translateY(16px) scale(.985);
  transition:opacity .36s var(--ease),transform .42s var(--ease)}
.lp-overlay.is-open .lp-panel{opacity:1;transform:none;transition-delay:.04s}
@keyframes lp-rise{from{opacity:0;transform:translateY(16px) scale(.985)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .lp-overlay,.lp-overlay.is-open{transition:visibility 0s linear 0s}
  .lp-panel,.lp-overlay.is-open .lp-panel{transition:none;transform:none}
}
.lp-eyebrow{display:inline-flex;align-items:center;gap:9px;font-family:var(--font-m);font-size:11.5px;
  font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-deep)}
.lp-eyebrow::before{content:"";width:20px;height:1.5px;background:var(--accent);opacity:.7;border-radius:2px}
.lp-panel h2{margin-top:14px;font-size:clamp(22px,2.6vw,28px);line-height:1.13;letter-spacing:-.03em;max-width:20ch}
.lp-panel .lp-sub{margin-top:11px;color:var(--text-2);font-size:15.5px;line-height:1.58;max-width:46ch}
.lp-panel .lf{margin-top:22px}
/* 44px, not 38px: this is the control a thumb hunts for to dismiss a modal. */
.lp-close{position:absolute;top:10px;right:10px;width:44px;height:44px;display:grid;place-content:center;
  border-radius:10px;border:1px solid transparent;background:transparent;color:var(--text-3);cursor:pointer;
  transition:background .25s ease,color .25s ease,border-color .25s ease}
.lp-close:hover{background:var(--paper-2);color:var(--ink);border-color:var(--line)}
.lp-close svg{width:19px;height:19px}
.lp-decline{margin-top:16px;background:none;border:0;padding:12px 0;min-height:44px;cursor:pointer;
  font-family:var(--font-b);font-size:14px;color:var(--text-3);text-align:left}
.lp-decline:hover{color:var(--ink)}
/* a phone screen has no room to spare, so the popup tightens up rather than
   pushing its own submit button below the fold */
@media (max-width:620px){
  .lp-overlay{padding:14px 12px}
  .lp-panel{padding:22px 20px 24px}
  .lp-panel h2{margin-top:12px;font-size:21px}
  .lp-panel .lp-sub{font-size:15px}
  .lp-panel .lf{--lf-gap:11px;margin-top:18px}
  .lp-panel .lf-textarea{min-height:74px}
  .lp-panel .lf-fine{font-size:12.5px}
  /* the free-text field is optional, and on a phone it costs more room than it
     earns, so the popup asks only for the three fields that matter.
     Selected by attribute rather than :has(), because :has() is not universal
     and a browser without it silently showed a four-field popup on a phone,
     which is the one thing the popup rule forbids. */
  .lp-panel .lf-field[data-field="message"]{display:none}
}
/* focus lands on the panel when the popup opens so a screen reader starts at
   the heading. It is a container, never a control, so it paints no ring: the
   dialog role, the modal flag, and the label do the announcing. */
.lp-panel:focus,.lp-panel:focus-visible,
.lp-slide [data-popup-panel]:focus,.lp-slide [data-popup-panel]:focus-visible{outline:none}

/* ---------------------------------------------------------- popup: slide-in */
.lp-slide{position:fixed;z-index:190;right:clamp(14px,2.4vw,26px);bottom:clamp(14px,2.4vw,26px);
  width:min(380px,calc(100vw - 28px));display:none;
  background:var(--card);border:1px solid var(--line-2);border-radius:var(--r-m);
  padding:20px 22px 22px;box-shadow:0 34px 80px -34px rgba(8,6,14,.5);text-align:left}
.lp-slide.is-open{display:block;animation:lp-slide-in .5s var(--ease) both}
@keyframes lp-slide-in{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.lp-slide.is-open{animation:none}}
.lp-slide h2{font-size:18.5px;line-height:1.22;letter-spacing:-.025em;max-width:22ch;padding-right:42px}
.lp-slide p{margin-top:9px;color:var(--text-2);font-size:14.5px;line-height:1.55}
.lp-slide .lp-slide-actions{margin-top:16px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.lp-slide .lf-submit{padding:12px 22px;font-size:15px}
@media (max-width:520px){.lp-slide{left:14px;right:14px;width:auto}}

/* nothing on this page should ever push the document sideways */
.lp-overlay,.lp-slide{max-width:100vw}

/* ============================================================
   BOOKING MODAL (`assets/book.js`)
   Every "book a call" path on the site opens this. Scheduling
   happens inside the page: the calendar is embedded in the
   dialog, and the alternative is a short form in the same
   dialog. No booking link navigates off the site.
   ============================================================ */

/* buttons carry the same visual as the anchor version of the CTA */
button.btn-primary,button.link-arrow{border:0;background-clip:padding-box;cursor:pointer;
  font-family:var(--font-b);letter-spacing:-.006em}
button.link-arrow{background:none;padding:0}

/* The dialog stays in flow and is hidden with visibility rather than
   display:none, so both opening AND closing are animated. `visibility` is in
   the transition list so the overlay is not focusable or hit-testable once the
   fade has finished. book.js only toggles `.is-open`; no JS change was needed
   to get the closing motion. */
.bk-overlay{position:fixed;inset:0;z-index:220;
  display:flex;align-items:flex-start;justify-content:center;
  padding:clamp(12px,3vh,40px) clamp(12px,3vw,28px);overflow-y:auto;
  background:rgba(11,8,16,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .34s var(--ease),visibility 0s linear .34s,backdrop-filter .34s var(--ease)}
.bk-overlay.is-open{opacity:1;visibility:visible;pointer-events:auto;
  transition:opacity .34s var(--ease),visibility 0s linear 0s,backdrop-filter .34s var(--ease)}
.bk-panel{margin:auto;position:relative;width:100%;max-width:760px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r-l);
  padding:clamp(24px,3vw,36px);box-shadow:0 50px 110px -40px rgba(8,6,14,.6);
  text-align:left;
  opacity:0;transform:translateY(18px) scale(.984);
  transition:opacity .38s var(--ease),transform .44s var(--ease)}
.bk-overlay.is-open .bk-panel{opacity:1;transform:none;transition-delay:.04s}
@media (prefers-reduced-motion:reduce){
  .bk-overlay,.bk-overlay.is-open{transition:visibility 0s linear 0s}
  .bk-panel,.bk-overlay.is-open .bk-panel{transition:none;transform:none}
}
.bk-panel:focus,.bk-panel:focus-visible{outline:none}
.bk-panel h2{margin-top:12px;font-size:clamp(22px,2.5vw,29px);line-height:1.12;
  letter-spacing:-.03em;max-width:22ch;padding-right:44px}
.bk-sub{margin-top:10px;color:var(--text-2);font-size:15.5px;line-height:1.58;max-width:56ch}

.bk-tabs{margin-top:22px;display:inline-flex;gap:4px;padding:4px;
  background:var(--paper-2);border:1px solid var(--line);border-radius:999px}
.bk-tab{border:0;background:none;cursor:pointer;font-family:var(--font-b);font-size:14.5px;
  font-weight:500;color:var(--text-2);padding:9px 18px;border-radius:999px;
  transition:background .25s ease,color .25s ease}
.bk-tab:hover{color:var(--ink)}
.bk-tab.is-on{background:var(--card);color:var(--ink);box-shadow:0 2px 8px -4px rgba(16,13,20,.4)}

.bk-pane{margin-top:20px}
.bk-pane[hidden]{display:none}
.bk-cal{border:1px solid var(--line);border-radius:var(--r-m);overflow:hidden;
  background:var(--paper-2);min-height:640px;position:relative}
.bk-cal .calendly-inline-widget{min-width:280px;height:640px}
.bk-fallback{padding:26px;color:var(--text-2);font-size:15px;line-height:1.6}
.bk-note{margin-top:14px;font-size:13px;color:var(--text-3)}

/* CALENDAR LOADING STATE, 2026-08-14. Calendly is fetched on the click that
   asks for it, so there is a real gap between the dialog opening and the
   iframe painting. This fills it from the first frame, so the dialog reads as
   answered rather than broken. assets/book.js creates and removes the node. */
.cal-loading{position:absolute;inset:0;z-index:1;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;background:var(--paper-2);
  color:var(--text-3);font-size:14.5px;letter-spacing:.01em}
.cal-spin{width:26px;height:26px;border-radius:50%;
  border:2px solid var(--line-2);border-top-color:var(--accent);
  animation:cal-spin .8s linear infinite}
@keyframes cal-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .cal-spin{animation:none;border-top-color:var(--line-2);opacity:.5}
}

@media (max-width:620px){
  .bk-overlay{padding:10px}
  .bk-panel{padding:20px 18px 22px}
  .bk-panel h2{font-size:21px;padding-right:40px}
  .bk-tabs{width:100%;justify-content:stretch}
  .bk-tab{flex:1;padding:9px 10px}
  .bk-cal,.bk-cal .calendly-inline-widget{min-height:780px;height:780px}
}
.bk-overlay{max-width:100vw}

/* ---------------------------------------------------------- product lead form
   The compact form the product tiles open. Same controls, fewer fields. */
.bk-panel .lf{margin-top:4px}
.bk-panel .lf-fine{max-width:60ch}

/* ============================================================
   FREE AI OPPORTUNITY AUDIT (`assets/audit.js`)
   One question on screen at a time, then the finished audit in
   the same place. Uses only the shared tokens, so it inherits
   the site design system rather than forking it.
   ============================================================ */

.aw-shell{background:var(--card);border:1px solid var(--line);border-radius:var(--r-l);
  padding:clamp(24px,3.4vw,44px);box-shadow:0 26px 60px -46px rgba(16,13,20,.42);
  text-align:left;max-width:760px;margin-inline:auto}

/* progress: one segment per question, filled as they are answered */
.aw-meta{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}
.aw-count{font-family:var(--font-m);font-size:11.5px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-3)}
.aw-progress{display:flex;gap:5px;flex:1;min-width:140px;max-width:260px}
.aw-progress i{flex:1;height:3px;border-radius:2px;background:var(--line-2);
  transition:background .4s var(--ease)}
.aw-progress i.on{background:var(--accent)}

.aw-step{display:none}
.aw-step.is-on{display:block;animation:aw-in .34s var(--ease) both}
@keyframes aw-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.aw-step.is-on{animation:none}}
.aw-q{margin-top:22px;font-size:clamp(21px,2.5vw,28px);line-height:1.16;letter-spacing:-.03em;
  max-width:24ch}
.aw-hint{margin-top:10px;color:var(--text-2);font-size:15.5px;line-height:1.58;max-width:50ch}
.aw-field{margin-top:20px}

/* chips: a tap answers the question, no dropdown to open */
.aw-options{margin-top:20px;display:flex;flex-wrap:wrap;gap:9px}
.aw-chip{font-family:var(--font-b);font-size:15px;line-height:1.3;color:var(--text-1);min-height:44px;
  background:var(--paper-2);border:1px solid var(--line-2);border-radius:999px;
  padding:11px 18px;cursor:pointer;text-align:left;
  transition:border-color .22s ease,background .22s ease,color .22s ease,transform .22s var(--ease)}
.aw-chip:hover{border-color:var(--text-3);transform:translateY(-1px)}
.aw-chip.is-on{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.aw-chip:focus-visible{outline:2px solid var(--accent-deep);outline-offset:2px}
.aw-multi-note{margin-top:11px;font-size:13px;color:var(--text-3)}

.aw-actions{margin-top:26px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.aw-next{display:inline-flex;align-items:center;gap:10px;padding:14px 28px;border:0;border-radius:999px;
  background:var(--ink);color:var(--paper);font-family:var(--font-b);font-size:15.5px;font-weight:500;
  letter-spacing:-.006em;cursor:pointer;
  transition:transform .4s var(--ease),box-shadow .5s var(--ease)}
.aw-next:hover{transform:translateY(-2px);box-shadow:0 22px 46px -20px rgba(16,13,20,.58)}
.aw-next .ar{transition:transform .35s var(--ease)}
.aw-next:hover .ar{transform:translateX(3px)}
.aw-back{background:none;border:0;padding:6px 2px;cursor:pointer;font-family:var(--font-b);
  font-size:14.5px;color:var(--text-3)}
.aw-back:hover{color:var(--ink)}
.aw-back[hidden]{display:none}

.aw-err{display:none;margin-top:16px;padding:12px 15px;border-radius:var(--r-s);
  background:#fff5f5;border:1px solid #f0c9cb;color:#8f1c23;font-size:14.5px;line-height:1.5}
.aw-err.show{display:block}
.aw-fine{margin-top:20px;padding-top:18px;border-top:1px solid var(--line);
  font-size:13px;line-height:1.55;color:var(--text-3)}
.aw-fine a{border-bottom:1px solid var(--line-2)}

/* the wait: staged progress, because a dead spinner reads as broken */
.aw-loading{max-width:760px;margin-inline:auto;text-align:center;
  padding:clamp(40px,7vw,80px) clamp(20px,4vw,40px)}
.aw-loading[hidden]{display:none}
.aw-loading h2{font-size:clamp(21px,2.5vw,27px);letter-spacing:-.03em}
.aw-loading-msg{margin-top:12px;color:var(--text-2);font-size:16px;min-height:1.6em}
.aw-loading-bar{margin:26px auto 0;max-width:340px;height:4px;border-radius:3px;
  background:var(--line-2);overflow:hidden}
.aw-loading-fill{display:block;height:100%;width:10%;border-radius:3px;background:var(--accent);
  transition:width .45s var(--ease)}

/* ---------------------------------------------------------- the audit itself */
.ao-result[hidden]{display:none}
.ao-result:focus,.ao-result:focus-visible{outline:none}

.ao-hero{background:var(--card);border:1px solid var(--line);border-radius:var(--r-l);
  padding:clamp(26px,3.6vw,44px);box-shadow:0 26px 60px -46px rgba(16,13,20,.42)}
.ao-hero-h{margin-top:12px;font-size:clamp(22px,2.6vw,30px);line-height:1.14;letter-spacing:-.03em}
.ao-figure{margin-top:10px;font-family:var(--font-d);font-weight:700;
  font-size:clamp(30px,5.4vw,52px);line-height:1.04;letter-spacing:-.035em;color:var(--accent-deep)}
.ao-basis{margin-top:14px;color:var(--text-2);font-size:15.5px;line-height:1.6;max-width:60ch}
.ao-tag{margin-top:10px;font-family:var(--font-m);font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--text-3)}

.ao-section-h{margin-top:44px;font-size:clamp(20px,2.3vw,26px);letter-spacing:-.028em}
.ao-grid{margin-top:20px;display:grid;gap:18px;grid-template-columns:1fr}
.ao-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-m);
  padding:clamp(22px,2.8vw,32px)}
.ao-head{display:flex;align-items:center;gap:12px}
.ao-rank{font-family:var(--font-m);font-size:12.5px;font-weight:600;letter-spacing:.06em;
  color:var(--text-3)}
.ao-prio{font-family:var(--font-m);font-size:11px;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;padding:5px 11px;border-radius:999px;
  background:var(--paper-2);border:1px solid var(--line-2);color:var(--text-2)}
.ao-prio.prio-high{background:rgba(225,24,182,.09);border-color:rgba(225,24,182,.26);
  color:var(--accent-deep)}
.ao-title{margin-top:13px;font-size:clamp(18px,2vw,22px);line-height:1.2;letter-spacing:-.025em}
.ao-line{margin-top:12px;color:var(--text-2);font-size:15.5px;line-height:1.62;max-width:66ch}
.ao-line strong{color:var(--text-1);font-weight:600}

.ao-band{margin-top:20px;padding:16px 18px;border-radius:var(--r-s);background:var(--paper-2);
  border:1px solid var(--line)}
.ao-band-label{display:block;font-family:var(--font-m);font-size:11px;font-weight:500;
  letter-spacing:.13em;text-transform:uppercase;color:var(--text-3)}
.ao-band-figure{display:block;margin-top:6px;font-family:var(--font-d);font-weight:700;
  font-size:clamp(19px,2.2vw,24px);letter-spacing:-.025em;color:var(--ink)}
.ao-band-hours{display:block;margin-top:3px;font-size:14px;color:var(--text-3)}
.ao-band-basis{margin-top:10px;font-size:13.5px;line-height:1.55;color:var(--text-3);max-width:64ch}

.ao-win{margin-top:26px;background:var(--card);border:1px solid var(--line);
  border-left:3px solid var(--accent);border-radius:var(--r-m);padding:clamp(22px,2.8vw,32px)}
.ao-win-badge{font-family:var(--font-m);font-size:11px;font-weight:600;letter-spacing:.13em;
  text-transform:uppercase;color:var(--accent-deep)}
.ao-win h3{margin-top:11px;font-size:clamp(18px,2vw,22px);letter-spacing:-.025em;line-height:1.2}
.ao-win p{margin-top:11px;color:var(--text-2);font-size:15.5px;line-height:1.62;max-width:66ch}
.ao-win-time{color:var(--text-3);font-size:14.5px}

.ao-cta{margin-top:30px;background:var(--ink);border-radius:var(--r-l);
  padding:clamp(28px,3.6vw,44px);text-align:center}
.ao-cta h3{color:var(--dark-1);font-size:clamp(20px,2.4vw,27px);line-height:1.18;
  letter-spacing:-.03em;max-width:34ch;margin-inline:auto}
.ao-cta-actions{margin-top:22px;display:flex;justify-content:center}
.ao-cta .btn-primary{background:var(--paper);color:var(--ink)}
.ao-fine{margin-top:20px;color:var(--dark-3);font-size:13px;line-height:1.55;
  max-width:62ch;margin-inline:auto}

@media (min-width:900px){.ao-grid{grid-template-columns:1fr}}
@media (max-width:620px){
  .aw-shell{padding:22px 18px 26px}
  .aw-chip{font-size:14.5px;padding:10px 15px}
  .ao-hero,.ao-card,.ao-win,.ao-cta{padding:22px 18px}
}

/* ===== nav.css ===== */
/* ============================================================================
   NAVIGATION AND IN-PAGE NAVIGATION, 2026-08-13.

   This file exists as its own stylesheet because the homepage carries its CSS
   inline and every other page links assets/site.css. Anything shared between
   the two used to have to be written twice, which is how a nav drifts. Both
   link this file, so the header, the menus, the sticky page bar and the
   directory cards are defined exactly once.

   It loads after site.css and after the homepage's inline block, so a rule
   here wins where the two overlap. That is deliberate.
   ========================================================================== */

/* ---------------------------------------------------------------- MENUS
   Industries and Products are <details>. They work with no JavaScript: the
   summary is a real control, it toggles on click and on Enter or Space, and
   the panel is in the document either way. assets/nav.js only adds click-away,
   Escape, and closing one when the other opens. */
.nav-drop { position: static; }
.nav-drop > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
  font-size: 14.5px; color: var(--text-2); letter-spacing: -.006em;
  transition: color .25s ease;
}
.nav-drop > summary::-webkit-details-marker { display: none; }
.nav-drop > summary:hover, .nav-drop[open] > summary { color: var(--ink); }
.nd-mark {
  width: 8px; height: 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg); opacity: .55;
  transition: transform .28s var(--ease), opacity .28s ease;
}
.nav-drop[open] > .nd-mark, .nav-drop[open] > summary .nd-mark {
  transform: translateY(1px) rotate(-135deg); opacity: .9;
}

/* The panel spans the header rather than hanging off one link, because the
   industries menu is a grid of fourteen destinations and a narrow column would
   need its own scrollbar. */
.nav-panel {
  position: fixed; left: 0; right: 0; top: 66px; z-index: 59;
  /* fully opaque: a translucent menu lets the hero headline read through the
     industry names underneath it, which is unreadable rather than airy */
  background: #fcfbfd;
  border-bottom: 1px solid var(--line);
  box-shadow: 0 34px 60px -34px rgba(16, 13, 20, .34);
  animation: nd-open .26s var(--ease) both;
  max-height: calc(100vh - 66px); overflow-y: auto;
}
@keyframes nd-open { from { opacity: 0; transform: translateY(-8px) } to { opacity: 1; transform: none } }
@media (prefers-reduced-motion: reduce) { .nav-panel { animation: none } .nd-mark { transition: none } }
.nav-panel-in {
  width: 100%; max-width: var(--container); margin-inline: auto;
  padding: 26px var(--gutter) 24px;
}
/* Multi-column, not a grid. Industries carry different numbers of segment
   chips, so on a grid every row grows to the tallest cell in it and the menu
   fills with dead space. Columns pack each entry against the one above it. */
.nd-grid { columns: 4; column-gap: 26px; }
.nd-grid-prod {
  columns: auto; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px 22px;
}
@media (max-width: 1180px) { .nd-grid { columns: 3 } }
.nd-cell {
  break-inside: avoid; -webkit-column-break-inside: avoid; page-break-inside: avoid;
  display: inline-block; width: 100%; padding-bottom: 12px;
}
.nd-item {
  display: block; padding: 9px 11px; border-radius: 10px;
  transition: background .2s var(--ease);
}
.nd-item:hover { background: var(--paper-2); }
.nd-name {
  display: block; font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -.012em;
}
.nd-blurb {
  display: block; margin-top: 3px; font-size: 13px; line-height: 1.45; color: var(--text-2);
}
.nd-segs { display: flex; flex-wrap: wrap; gap: 5px; padding: 2px 11px 0; }
.nd-seg {
  font-size: 12.5px; color: var(--text-2); padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--line-2); background: var(--card);
  transition: color .2s ease, border-color .2s ease;
}
.nd-seg:hover { color: var(--ink); border-color: var(--text-3); }
.nd-foot {
  display: block; margin-top: 14px; padding: 14px 16px; border-radius: 12px;
  border: 1px solid var(--accent-line, var(--line-2)); background: var(--paper-2);
  transition: border-color .22s ease;
}
.nd-foot:hover { border-color: var(--text-3); }
.nd-foot .nd-blurb { max-width: 74ch; }
@media (max-width: 940px) { .nav-panel { display: none } }

/* ---------------------------------------------------------------- MOBILE MENU
   The same destinations, nested one level deep so the panel opens short and
   the visitor chooses how far to go. */
.nav-mob-panel { min-width: min(86vw, 320px); max-height: calc(100vh - 92px); overflow-y: auto; }
/* site.css styles the burger itself with `.nav-mob summary`, a descendant
   selector that also caught these nested summaries and squeezed each one into
   the 42px square the burger uses. Everything that rule sets is undone here. */
.nav-mob-panel .nm-sub > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between;
  width: auto; height: auto; place-content: initial;
  border: 0; background: none;
  padding: 12px 14px; border-radius: 10px; font-size: 15px; color: var(--text-1);
}
.nm-sub > summary::-webkit-details-marker { display: none; }
.nav-mob-panel .nm-sub > summary:hover { background: var(--paper-2); }
.nav-mob-panel .nm-sub[open] > summary { color: var(--ink); font-weight: 600; }
.nav-mob-panel .nm-sub[open] > summary .nd-mark { transform: translateY(1px) rotate(-135deg); }
/* the parent panel is a flex column, which is what made its direct links sit
   one per row. A nested list needs to say so for itself. */
.nm-sub-list {
  display: flex; flex-direction: column; gap: 1px;
  padding: 2px 0 8px 10px; border-left: 1px solid var(--line); margin-left: 14px;
}
.nav-mob-panel .nm-sub-list a { font-size: 14.5px; padding: 9px 12px; }
/* 10px of vertical padding, not 6: at 6 the row measured 31.8px and the site's
   own motion QA holds every mobile tap target to at least 32px */
.nav-mob-panel .nm-sub-list a.nm-seg {
  font-size: 13px; color: var(--text-3); padding: 10px 12px 10px 24px;
}
.nav-mob-panel .nm-sub-list a.nm-more { font-weight: 600; color: var(--ink); }
.nm-blurb { display: block; font-size: 12.5px; line-height: 1.4; color: var(--text-3); margin-top: 2px; }

/* ---------------------------------------------------------------- PAGE BAR
   MOVED ABOVE THE HERO. The bar used to sit under the hero, so on the page
   whose complaint was "they just have to scroll all the way down" the way of
   skipping the scroll was itself below the fold. Sitting above the hero with a
   66px top margin, it renders directly under the fixed header on load and
   sticks there for the rest of the page. */
.seg-bar { margin-top: 66px; top: 66px; }
.seg-bar-links a[aria-current="true"] {
  color: var(--paper); background: var(--ink); border-color: var(--ink);
}
.seg-bar + .page-hero { padding-top: clamp(48px, 7vh, 84px); }
/* the header animates in; the bar under it should arrive with it */
.seg-bar { animation: t-fade .6s var(--ease) both; }
@media (prefers-reduced-motion: reduce) { .seg-bar { animation: none } }
/* Anything the bar jumps to has to land clear of both the header (66px) and
   the bar (54px). The extra room on top of those 120px covers the reveal
   transform, which is still unwinding at the moment the browser computes where
   to stop, and leaves the heading visibly below the chrome instead of tucked
   right against it. */
.seg, [id="problem"], [id="what-we-build"], [id="systems"], [id="segments"],
[id^="g-"], [id^="n-"] { scroll-margin-top: 152px; }

/* ------------------------------------------------- HOMEPAGE "ANOTHER INDUSTRY"
   It used to be a disclosure that opened onto "send us the details", which is
   the thing Jake did not want. It is now the door to the directory page, and
   it runs the full width under the thirteen tiles because it stands for
   everything they leave out. */
.icp2-tile.icp2-any {
  grid-column: span 12; min-height: 0; flex-direction: row; align-items: center;
  gap: clamp(16px, 2vw, 26px); flex-wrap: wrap;
  padding: clamp(20px, 2vw, 26px) clamp(20px, 2.2vw, 28px);
}
.icp2-tile.icp2-any .icp2-ic { flex: none; margin: 0; width: 36px; height: 36px; border-radius: 10px; }
.icp2-tile.icp2-any .icp2-ic svg { width: 18px; height: 18px; }
.icp2-tile.icp2-any h3 { margin: 0; flex: none; font-size: clamp(16px, 1.7vw, 19px); }
.icp2-tile.icp2-any .icp2-body { margin: 0; padding: 0; flex: 1 1 22ch; max-width: 68ch; font-size: 14px; }

/* ---------------------------------------------------------------- DIRECTORY
   The "Another industry" page. One card per business type, each stating the
   problem and the build, each ending somewhere real. */
.niche-grid {
  margin-top: clamp(30px, 4.4vh, 46px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px;
}
@media (max-width: 860px) { .niche-grid { grid-template-columns: 1fr } }
.niche {
  display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-l);
  padding: clamp(20px, 2.4vw, 28px);
}
.niche h3 { font-size: clamp(18px, 2vw, 21px); letter-spacing: -.022em; line-height: 1.2; }
.niche-also {
  margin-top: 7px; font-size: 13px; line-height: 1.5; color: var(--text-3);
}
.niche .seg-pair { margin-top: 14px; }
.niche .seg-pair p { margin-top: 6px; color: var(--text-2); font-size: 15px; line-height: 1.58; }
.niche-go {
  margin-top: auto; padding-top: 18px;
  display: inline-flex; align-items: center; gap: 8px; align-self: flex-start;
  font-family: var(--font-b); font-size: 15px; font-weight: 500; color: var(--ink);
  background: none; border: 0; cursor: pointer; text-align: left;
  transition: color .25s ease;
}
.niche-go .ar { transition: transform .35s var(--ease); }
.niche-go:hover { color: var(--accent-deep); }
.niche-go:hover .ar { transform: translateX(4px); }
@media (max-width: 940px) {
  /* a 44px hit area on the card action without moving the type */
  .niche-go { position: relative; }
  .niche-go::before {
    content: ""; position: absolute; left: 0; right: 0; top: 50%; translate: 0 -50%;
    height: 44px; min-width: 44px;
  }
}
/* book_button() renders a <button>; when it is asked to look like a text link
   it needs the control chrome removed */
button.link-arrow {
  border: 0; background: none; padding: 0; cursor: pointer; font-family: var(--font-b);
}
/* .hero-actions is only laid out inside .page-hero, so a pair of actions used
   anywhere else needs the same row treatment of its own */
.any-actions {
  margin-top: clamp(24px, 3.6vh, 34px);
  display: flex; align-items: center; gap: 14px 26px; flex-wrap: wrap;
}

/* ==========================================================================
   PHONE FIXES, 2026-08-17. Jake: "fix the industry page mess especially on
   MOBILE." That is a symptom, so qa-mobile.mjs was written first to turn it
   into a defect list measured on every industry page at 390px and 360px.
   Each block below names the defect it closes and the check that proves it.
   ========================================================================== */

/* ---- 1. THE STICKY CHROME WENT SEE-THROUGH OVER THE DARK BAND ------------
   .nav sat at rgba(252,251,253,.82) and .seg-bar at .90, both over a backdrop
   blur. That reads as glass over the light page, which is the intent. The
   industry pages also carry a full-bleed near-black band, and on a phone that
   band is the entire width of the screen, so scrolling it under the header
   turned the header into a grey smear with the band's white headline ghosting
   through it. It is a paint defect, so no DOM check can see it; the evidence
   is a screenshot, reproducible with
   `node shot-mobile.mjs industries/law 390` (the frame where .band-dark is
   passing under the header).

   The menu panel hit this same defect and was fixed with a comment that says
   a translucent surface "is unreadable rather than airy". The header itself
   never got that treatment. It does now.

   .96 alpha was tried first and was not enough, which is worth writing down:
   the band is near-black and its headline is white, so at 4% pass-through the
   band paints 242 and its text paints 252, a ten-level split that the eye
   reads as legible ghost text. The contrast being extreme is exactly why a
   nearly-opaque surface does not help. Opaque is the only value that works.

   The blur goes with it. Under an opaque background a backdrop-filter cannot
   change a pixel, so keeping it would buy a compositing layer on every scroll
   frame for no visual result. Nothing is lost: the frosted effect was only
   ever visible where content passed underneath, which is the case that was
   broken, and over the page's own background (252,251,253) it was already
   indistinguishable from the solid colour. */
.nav, .seg-bar {
  background: #fcfbfd;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}

/* ---- 2. THE SEGMENT PILLS WERE SLICED WITH NO AFFORDANCE -----------------
   .seg-bar-links is overflow-x:auto with the scrollbar hidden, which is the
   right interaction and no signal at all. On a phone the strip is 346px wide
   and up to 585px long, so the third pill was cut mid-word: an industry page
   opened on a phone showed "Corpor" against the right edge. Measured by
   qa-mobile.mjs as `clipped`, on 20 of 20 industry pages.

   Two changes, because the cut needs to look deliberate AND stop landing
   mid-word: a fade at the right edge that says the strip continues, and snap
   points so a pill comes to rest whole. */
.seg-bar-in { position: relative; }
/* A MASK, not a gradient painted on top. An overlay was tried first and barely
   read: it has to fade toward the bar's own colour, and the pills are that
   same near-white, so the only things it could wash out were the pill's hairline
   border and its text. A mask takes the alpha out instead, so the pill's
   background, border and label all dissolve together no matter what colour any
   of them is, and the strip ends in air rather than at a cut line. */
.seg-bar-links {
  /* One value drives both the dissolve and the room left for the last pill to
     clear it. They were written as two numbers first, 62 and 56, and the six
     pixels between them clipped the final pill on 19 of 20 industry pages at
     1440px, where nothing scrolls and nothing should fade. qa-segbar.mjs
     is the check that caught it and is what keeps them tied together. */
  --seg-fade: 62px;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--seg-fade)), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - var(--seg-fade)), transparent);
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--gutter) calc(var(--seg-fade) + 8px);
  padding-inline-end: calc(var(--seg-fade) + 8px);
}
.seg-bar-links a { scroll-snap-align: start; }
/* On a wide screen the pills sit well short of the strip's right edge, so the
   dissolve falls on empty space and shows nothing. Verified rather than
   assumed, at 1440px on all 20 industry pages, by qa-segbar.mjs. */

/* ---- 3. 132px OF PERMANENT CHROME ON AN 844px SCREEN ---------------------
   66px header plus a 66px bar is 15.6% of an iPhone viewport gone before the
   page starts, and it is gone for the whole scroll. The bar's height comes
   from the 44px minimum tap target plus 10px of padding either side; the tap
   target is not negotiable, so the padding is what moves. 56px on phones,
   which holds the 44px target and returns 10px to the content. */
@media (max-width: 700px) {
  .seg-bar-links { padding-block: 6px; }
  .seg-bar-in { min-height: 44px; }
}
/* Every anchor the bar jumps to has to clear both. Two values now, because
   the chrome is two heights: keep them next to the rule that sets it so they
   cannot drift apart the way a hand-kept number does. */
@media (max-width: 700px) {
  #segments, .seg, [id^="seg-"] { scroll-margin-top: 122px; }
  [id^="g-"], [id^="n-"] { scroll-margin-top: 142px; }
}

/* ---- 4. THE EYEBROW SAT UNDER THE 12px PHONE FLOOR -----------------------
   site.css lifted the micro-labels to 11.5px so nothing renders below it. The
   page's own eyebrow, which is the first line a visitor reads on an industry
   page, was left at 11.5px. On a phone that is half a point under the floor
   the same stylesheet set for everything around it. */
@media (max-width: 700px) { .eyebrow { font-size: 12px } }

/* ---- 5. "ANOTHER INDUSTRY" DID NOT READ AS A BUTTON ----------------------
   Jake, twice. It is the escape hatch for every visitor whose industry is not
   one of the nineteen in the menu, so it is the most important item in the
   panel for exactly the people the list failed. It was styled as neither a
   list item nor a control: on desktop a tinted card with a hairline border and
   no affordance, and on mobile plain bold text in a column of plain text.

   Both now carry the site's own action language: an arrow that travels on
   hover, the accent colour on the label, and a surface that separates it from
   the list above it. No markup change, so build_pages.py needs no edit and
   the footer copy of the same link is untouched. */
.nd-foot {
  position: relative;
  padding-right: 52px;
  border-color: var(--accent-line, var(--line-2));
  background: var(--card);
  box-shadow: 0 1px 0 rgba(16, 13, 20, .04);
}
.nd-foot .nd-name { color: var(--accent-deep); font-weight: 600; }
.nd-foot::after {
  content: "→";
  position: absolute; right: 18px; top: 50%; translate: 0 -50%;
  font-size: 17px; line-height: 1; color: var(--accent-deep);
  transition: transform .3s var(--ease);
}
.nd-foot:hover { border-color: var(--accent-deep); }
.nd-foot:hover::after { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) { .nd-foot::after { transition: none } }

/* The mobile menu's version of the same link. A bordered pill with the arrow,
   set apart from the plain rows above it, so a thumb can see it is the thing
   to press when none of the listed industries fit. */
.nav-mob-panel .nm-sub-list a.nm-more {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 8px; padding: 12px 14px;
  border: 1px solid var(--accent-line, var(--line-2)); border-radius: 999px;
  color: var(--accent-deep); font-weight: 600;
  min-height: 44px;
}
.nav-mob-panel .nm-sub-list a.nm-more::after {
  content: "→"; font-size: 16px; line-height: 1; margin-left: 12px;
}
.nav-mob-panel .nm-sub-list a.nm-more:hover { background: var(--paper-2); padding-left: 14px; }
