* { box-sizing: border-box; }
body{margin:0;-webkit-font-smoothing:antialiased;text-wrap:pretty;background:#07070a;color:#f3efe4;font-family:'General Sans',-apple-system,sans-serif;line-height:1.5;overflow-x:hidden}
a{color:#f6cf4c;text-decoration:none;cursor:pointer}
a:hover{color:#ffe28a}
::selection{background:#e4b315;color:#07070a}
:focus-visible{outline:2px solid #e4b315;outline-offset:3px;border-radius:2px}
button{font:inherit;cursor:pointer}
input,select,textarea{font-family:inherit}

/* Every button/link in this site sets its own background/color inline, which always wins over
   a:hover's color rule above (inline style beats an external-stylesheet selector regardless of
   :hover) — so none of them showed any hover feedback. filter isn't set inline anywhere, so it
   layers on top of whatever inline colors a given button uses without a specificity fight, and
   it changes brightness rather than size/position, which keeps buttons layout-stable on press. */
a,button{transition:filter 120ms ease-out}
a:hover,button:hover{filter:brightness(1.15)}
a:active,button:active{filter:brightness(0.88)}
.market-cell:hover,.market-cell:active,.mobile-menu a:hover,.mobile-menu a:active{filter:none}

/* Primary CTAs ([data-magnetic="true"]) used to follow the cursor on mousemove (see app.js
   history) — replaced with a scale-down on click only (hover still just gets the brightness
   shift from the rule above). Scale is reserved for the actual press, not the hover, so it
   reads as "this button just got pushed" rather than a hover-triggered pop. */
[data-magnetic="true"]{transition:filter 120ms ease-out,transform 150ms cubic-bezier(0.34,1.56,0.64,1)}
[data-magnetic="true"]:active{transform:scale(0.96)}

@keyframes fadeUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}
@keyframes pulseRing{0%{transform:scale(.6);opacity:.7}100%{transform:scale(1.8);opacity:0}}
@keyframes checkDraw{from{stroke-dashoffset:64}to{stroke-dashoffset:0}}
.reveal:not(.in-view){opacity:0;transform:translateY(16px)}
.reveal.in-view{animation:fadeUp 650ms cubic-bezier(0.16,1,0.3,1) both}
/* A fill-mode:both animation keeps "holding" transform even after it finishes, which silently
   blocks any :hover{transform:...} rule on the same element (a held animation value beats a
   normal-cascade rule regardless of specificity) — and hardcoding transform:none in its place
   would just trade that for a specificity fight against .market-cell:hover instead. Once the
   entrance animation ends, JS swaps to .settled, which turns the animation off and leaves
   transform undeclared for the resting state — .reveal:not(.in-view) no longer matches once
   .in-view is present, so nothing is left competing with a later :hover rule. */
.reveal.in-view.settled{animation:none;opacity:1}
.pulse-ring{animation:2.2s cubic-bezier(0.32,0.72,0,1) 0s infinite normal none running pulseRing}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:0.001ms !important;animation-iteration-count:1 !important;transition-duration:0.001ms !important;scroll-behavior:auto !important}
  [data-magnetic]{transform:none !important}
  .reveal{opacity:1 !important;transform:none !important}
}

.nav-cta{display:none}
.mobile-menu{display:none}
.mobile-menu.open{display:block;animation:fadeUp 220ms cubic-bezier(0.16,1,0.3,1) both}
.mobile-menu a:hover,.mobile-menu a:focus-visible{background:rgba(255,255,255,0.06)}
@media (min-width:900px){ [data-nav-links]{display:flex !important} .two-col-40{flex-direction:row !important} .two-col-40 > div{flex:1} .nav-cta{display:flex !important} .mobile-menu-btn{display:none !important} .mobile-menu{display:none !important} }
@media (min-width:1024px){ #equation-grid{display:grid !important;grid-template-columns:repeat(3,1fr) !important} #process-grid{grid-template-columns:0.85fr 1.15fr !important} #contact-layout{grid-template-columns:1fr 1fr !important} }
/* Hero photos are cropped sideways by cover, toward the centre, and both the home
   and services subjects stand in the right third — so narrow viewports threw the
   officer away and showed empty background.

   The cutoff is 1280px, not the 1024px used elsewhere in this file, because it is
   set by the photo rather than by layout. Measuring the visible slice of the home
   hero with centre framing: at 1024px it spans 25-75% of the image, at 1200px
   22-78%, and the officer starts at 72% — a sliver at best. Only at 1280px
   (20-80%) is he properly in frame. iPad landscape is 1024px and sat inside the
   broken range.

   !important because the fallback position is set inline on the element. */
@media (max-width:1279px){
  [data-hero-image]{background-position:var(--hero-x-narrow,center) top !important}
}

@media (max-width:1023px){
  #process-grid{grid-template-columns:1fr !important;gap:32px !important}
  #process-grid > div:first-child{position:static !important}
}
@media (max-width:1023px){
  [data-cards="storefront"]{grid-template-columns:1fr !important}
  .svc-detail-groups{grid-template-columns:1fr !important}
  /* data-grid marks a grid that collapses to one column on small screens.
     This was once a list of section ids, so a grid in a section nobody had
     listed kept its desktop columns on a phone — which is what had happened to
     every grid on the assessment page. Marking the element is the whole point
     of the attribute; matching the attribute is what makes it work. */
  [data-grid]{grid-template-columns:1fr !important}
  #credentials-grid{grid-template-columns:1fr !important}
  #contact-layout{grid-template-columns:1fr !important;gap:40px !important}
  .stats-grid{grid-template-columns:1fr !important}
  [data-two-col]{grid-template-columns:1fr !important}
  [data-choice-grid]{grid-template-columns:1fr 1fr !important}
  [data-hide-mobile]{display:none !important}
}

/* The stats panel carries its own 24px gutter on top of the hero section's
   20px. Stacked one-per-row on a phone that left it at 77% of the screen and
   667px tall, which reads as a bar rather than a panel. The section gutter
   alone is enough at this width; the vertical padding is untouched. */
/* Matches the width at which .stats-grid above collapses to one column. */
@media (max-width:1023px){
  /* The hero section is a column flex container with align-items:center, so a
     child with no width of its own shrinks to fit its widest text. This panel
     had no width of its own: it was held open by the caption that used to sit
     under it, and when that line was deleted the panel collapsed to 221px and
     centred itself. Stretching gives it a width that does not depend on what
     text happens to be inside it, and the section's own 20px gutter is then
     enough without the wrapper adding a second one. */
  .stats-wrap{align-self:stretch;width:100%;padding-left:0 !important;padding-right:0 !important}
}

/* production-ready stand-in for design-tool image-slot placeholders */
.img-slot{position:relative;width:100%;height:100%;background:
    radial-gradient(60% 60% at 30% 20%, rgba(228,179,21,0.10), transparent 60%),
    radial-gradient(50% 50% at 80% 80%, rgba(228,179,21,0.06), transparent 60%),
    #0d0e12;
  overflow:hidden}
.img-slot::after{content:'';position:absolute;inset:0;
  background-image:repeating-linear-gradient(135deg, rgba(255,255,255,0.025) 0 2px, transparent 2px 14px);}

[data-screen]{display:none}
[data-screen].is-active{display:block}

.day-pill{flex:1;min-height:44px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;text-align:center;border:1px solid rgba(255,255,255,0.36);border-radius:8px;padding:11px 4px;font-size:11.5px;font-family:'JetBrains Mono',monospace;cursor:pointer;transition:0.24s cubic-bezier(0.32,0.72,0,1);background:transparent;color:rgba(243,239,228,0.58)}
.day-pill:hover{border-color:rgba(228,179,21,0.5);color:#f3efe4}
.day-pill.selected{background:#e4b315;color:#07070a;border-color:#e4b315;font-weight:600}

.choice-card{cursor:pointer;border:1px solid rgba(255,255,255,0.09);background:rgba(255,255,255,0.02);border-radius:14px;padding:16px;transition:0.24s cubic-bezier(0.32,0.72,0,1)}
.choice-card:hover{border-color:rgba(228,179,21,0.35);background:rgba(228,179,21,0.04)}
.choice-card.selected{border-color:#e4b315;background:rgba(228,179,21,0.08)}

/* Sector cards. These were 150px label tiles — icon pinned top, name pinned
   bottom, seven across in one row. They now follow the reference grid: a tinted
   icon plate, the name, one line of what the sector actually is, and a quiet
   link. Height is content-driven rather than fixed, and .market-blurb takes the
   spare space so every "Learn more" sits on a shared baseline across a row. */
.market-cell{background:rgba(255,255,255,0.02);border:1px solid rgba(255,255,255,0.09);border-radius:16px;padding:28px;display:flex;flex-direction:column;cursor:pointer;transition:border-color 0.3s,background 0.3s,transform 0.4s cubic-bezier(0.32,0.72,0,1)}
.market-cell:hover{border-color:rgba(228,179,21,0.5);background:rgba(228,179,21,0.05);transform:translateY(-4px)}
.market-cell svg{stroke:rgba(243,239,228,0.5);transition:stroke 0.3s}
.market-cell:hover svg{stroke:#f6cf4c}
.market-icon{width:40px;height:40px;border-radius:12px;background:rgba(228,179,21,0.08);border:1px solid rgba(228,179,21,0.22);display:flex;align-items:center;justify-content:center;flex:0 0 auto;margin-bottom:20px;transition:background 0.3s,border-color 0.3s}
.market-cell:hover .market-icon{background:rgba(228,179,21,0.14);border-color:rgba(228,179,21,0.45)}
.market-title{font-family:'Clash Display','General Sans',sans-serif;font-weight:600;font-size:17px;color:#f3efe4;margin:0 0 9px;letter-spacing:-0.005em}
.market-blurb{font-size:14px;color:rgba(243,239,228,0.58);line-height:1.6;margin:0 0 20px;flex:1}
.market-more{font-family:'JetBrains Mono',monospace;font-size:11px;color:#f6cf4c;letter-spacing:0.06em;text-transform:uppercase}
/* The seventh sector shares the last row with a photograph rather than
   stretching across it. The first column is sized to match the card columns
   above exactly — calc((100% - 60px)/3) against a 30px gap — so the residential
   card lines up with the grid rather than sitting 10px wider, which an fr-based
   split would have done. The photo is decorative: it carries no information,
   links nowhere, and is hidden from assistive tech rather than given a label it
   does not deserve. */
.market-figure{position:relative;overflow:hidden;border-radius:16px;border:1px solid rgba(255,255,255,0.09);background-size:cover;background-position:62% center;min-height:220px;
  filter:grayscale(0.30) brightness(0.92) contrast(1.08)}
/* Same tone-match the sector images use. Reusing those measured values rather
   than picking new ones: an earlier pass elsewhere in this file darkened an
   image to 14 luminance steps above the page background and made it invisible,
   and this photo is decorative — it should sit behind the cards it shares a row
   with, not outshine them. */
.market-figure::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(7,7,10,0.08),rgba(7,7,10,0.30)),
             linear-gradient(90deg,rgba(228,179,21,0.08),transparent 55%)}


.buyer-toggle{cursor:pointer;flex:1;text-align:center;border:1px solid rgba(255,255,255,0.09);background:rgba(255,255,255,0.02);border-radius:14px;padding:16px;font-weight:600;color:#f3efe4;transition:0.24s}
.buyer-toggle:hover{border-color:rgba(228,179,21,0.35);background:rgba(228,179,21,0.04)}
.buyer-toggle.selected{border-color:#e4b315;background:rgba(228,179,21,0.08)}

.field-input{height:44px;width:100%;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.36);border-radius:10px;color:#f3efe4;padding:0 12px;font-size:15px;box-sizing:border-box;transition:border-color 150ms ease-out}
.field-input:focus{border-color:#e4b315}
.field-input[aria-invalid="true"]{border-color:#e8a33d}
.field-error{display:flex;align-items:flex-start;gap:6px;font-size:12px;color:#e8a33d;margin:6px 0 0;line-height:1.4}
.field-error::before{content:"⚠";flex-shrink:0;font-size:11px;line-height:1.5}

/* Sector banners carried over from the previous WordPress site. They are bright,
   dated stock at 1200x350, and sit badly next to the commissioned photography
   elsewhere, so they are desaturated and darkened with a slight brand tint to
   settle them into the palette. Shown at native aspect: at 350px tall there is
   no headroom to upscale into a hero without going soft. */
.industry-banner,.industry-card-img,.industry-feature-img{position:relative;overflow:hidden}
.industry-banner{border-radius:20px}
.industry-banner img{width:100%;display:block}
/* Card images crop from the same wide source, so they take 16:9 rather than the
   4:3 the service cards use — a 3.4:1 strip squeezed into 4:3 loses most of the
   frame and leaves an unreadable detail.

   The height comes from percentage padding rather than aspect-ratio. As a flex
   child with no explicit height, an empty box sizing purely off aspect-ratio
   collapses to zero height in WebKit, so the image area vanished in Safari and
   the cards rendered as text only. Percentage padding resolves against the
   element's own width, which is definite in every engine. 56.25% is 9/16. */
/* Geometry is also set inline on the element itself. The hero renders entirely
   from inline styles and was never affected by this, while the cards depended on
   this file for their size — so a stale cached stylesheet left them as divs with
   a background image and no dimensions, i.e. invisible. Keeping the sizing inline
   means the image survives whatever happens to this file; what is left here is
   only the cosmetic treatment, which degrades harmlessly. */
.industry-card-img{height:0;padding-top:56.25%;flex:0 0 auto;background-size:cover;background-position:center}
/* The residential card spans the whole grid rather than taking a third of it,
   so its image fills a column instead of a fixed 16:9 strip. Same tone-matching
   as the card images above; only the geometry differs. */
.industry-feature-img{min-height:320px;background-size:cover;background-position:center 38%}
/* Tone-matching these stock images must not cost their legibility. An earlier
   pass stacked brightness(0.62) under an overlay reaching 0.7 opacity, which
   landed the result 14 luminance steps above the page background — effectively
   invisible on any display dimmer than the one it was checked on. Measured:
   untreated 107, that version 24, this one 78. Still clearly darker than the
   source and still in palette, with margin to actually be seen. */
.industry-banner img,.industry-card-img,.industry-feature-img{filter:grayscale(0.30) brightness(0.92) contrast(1.08)}
.industry-banner::after,.industry-card-img::after,.industry-feature-img::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(7,7,10,0.08),rgba(7,7,10,0.30)),
             linear-gradient(90deg,rgba(228,179,21,0.08),transparent 55%)}

details summary::-webkit-details-marker{display:none}

/* Container */
.tc-chat-widget {
  position: fixed;
  bottom: 28px;
  right: 28px;
  z-index: 9999;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* Floating Action Button */
.tc-chat-toggle-btn {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: #25D366;
  color: #FFFFFF;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
  transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}

.tc-chat-toggle-btn:hover {
  transform: scale(1.06);
  background-color: #20BA5A;
  box-shadow: 0 6px 24px rgba(37, 211, 102, 0.35);
}

/* Tactical Chat Modal */
.tc-chat-modal {
  position: absolute;
  bottom: 70px;
  right: 0;
  width: 340px;
  background: #0D1117;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.6);
  display: flex;
  flex-direction: column;
  transition: opacity 0.25s ease, transform 0.25s ease;
  transform-origin: bottom right;
}

/* Header */
.tc-chat-header {
  background: #161B22;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.tc-avatar-wrapper {
  position: relative;
}

.tc-avatar {
  width: 36px;
  height: 36px;
  background: #D4AF37;
  color: #0D1117;
  font-weight: 700;
  font-size: 13px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tc-status-indicator {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 10px;
  height: 10px;
  background: #25D366;
  border: 2px solid #161B22;
  border-radius: 50%;
}

.tc-header-info {
  display: flex;
  flex-direction: column;
}

.tc-title {
  color: #F0F6FC;
  font-size: 14px;
  font-weight: 600;
}

.tc-subtitle {
  color: #8B949E;
  font-size: 11px;
}

.tc-online-text {
  color: #25D366;
}

/* Chat Body */
.tc-chat-body {
  padding: 16px;
  background: #090D13;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tc-message.incoming {
  background: #161B22;
  border: 1px solid rgba(255, 255, 255, 0.06);
  color: #C9D1D9;
  padding: 12px;
  border-radius: 10px 10px 10px 2px;
  font-size: 13px;
  line-height: 1.45;
}

.tc-message p {
  margin: 0;
}

.tc-timestamp {
  display: block;
  font-size: 10px;
  color: #6E7681;
  margin-top: 6px;
  text-align: right;
}

/* Prompt Chips */
.tc-prompt-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tc-chip {
  background: rgba(212, 175, 55, 0.1);
  border: 1px solid rgba(212, 175, 55, 0.3);
  color: #E6C265;
  font-size: 11px;
  font-weight: 500;
  padding: 6px 10px;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.tc-chip:hover {
  background: rgba(212, 175, 55, 0.2);
  border-color: #D4AF37;
}

/* Chat Footer / Form */
.tc-chat-footer {
  padding: 12px;
  background: #161B22;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  align-items: center;
  gap: 8px;
}

.tc-chat-footer input {
  flex: 1;
  background: #090D13;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 13px;
  color: #F0F6FC;
  outline: none;
}

.tc-chat-footer input:focus {
  border-color: #D4AF37;
}

.tc-send-btn {
  background: #25D366;
  border: none;
  border-radius: 8px;
  width: 36px;
  height: 36px;
  color: #FFFFFF;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.2s ease;
}

.tc-send-btn:hover {
  background-color: #20BA5A;
}

/* Visibility Utilities */
.tc-hidden {
  display: none !important;
}

@media (max-width: 480px) {
  .tc-chat-modal {
    width: calc(100vw - 32px);
    right: -12px;
  }
}