/* =========================================================================
   LooSolution — theme layer
   Load AFTER css/styles.css.

   THIS FILE IS THE BRAND. Section 1 holds every colour and typeface the
   site uses; section 2 restates them for dark mode. styles.css contains
   no colour values at all any more — only structure, scale and motion.

   Re-branding is a section 1 + 2 edit and nothing else.

   Palette : enterprise navy #003366 with azure #00A3E0 on a cool
             blue-grey page #F4F7FA, navy-black ink #0B1B2B.
   Type    : Plus Jakarta Sans (display) / Inter (body)
             / JetBrains Mono (labels, data, timestamps).
   ========================================================================= */

/* ---------------------------------------------------------------
   1. LIGHT (default) — THE SINGLE SOURCE OF TRUTH

   Every colour and typeface on the site resolves from this block and
   its dark-mode counterpart in section 2. Nothing else in the codebase
   contains a raw hex value except the print stylesheet and the
   standalone favicon (which cannot read page variables).

   To re-brand: change the values here. Nothing else needs editing.

   Palette: enterprise navy. Deep navy dominates; a bright azure carries
   highlights, data and contrasting calls to action.
   --------------------------------------------------------------- */
:root{
  color-scheme: light;

  /* --- 1.1 Typography -------------------------------------------------
     Plus Jakarta Sans for headings — geometric, modern, corporate.
     Inter for body — the most readable workhorse at small sizes.
     JetBrains Mono for labels, eyebrows, data and timestamps.            */
  --display: 'Plus Jakarta Sans', 'Inter', system-ui, -apple-system, sans-serif;
  --body:    'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* --- 1.2 Brand: navy (dominant) -------------------------------------
     --accent-lift is the LIGHTEST stop of the button gradient, so white
     text sits on it — capped at a value that still clears AA (6.98:1).
     --accent      solid fills, buttons, dark panels
     --accent-ink  navy used as TEXT — 12.61:1 on white
     --accent-rgb  channels, for rgba() glows, overlays and washes        */
  --accent:        #003366;
  --accent-lift:   #0F5B9E;
  --accent-deep:   #00284D;
  --accent-ink:    #003366;
  --accent-wash:   #E4EDF6;
  --accent-rgb:    0,51,102;

  /* --- 1.3 Brand: azure (highlights, data, contrasting CTA) -----------
     Azure at full strength is 2.87:1 on white — it fails both text (4.5)
     and non-text (3.0). So the bright value is for FILLS ONLY, where ink
     sits on top of it, and --accent-2-ink carries any azure that has to
     be read as text or drawn as a thin graphic.                          */
  --accent-2:      #00A3E0;
  --accent-2-ink:  #0B6FA4;
  --accent-2-soft: #B8E4F7;
  --accent-2-rgb:  0,163,224;

  /* --- 1.4 Surfaces ---------------------------------------------------
     Three levels: the page is a cool blue-grey, cards lift to white, and
     quiet sections drop a step. Cards read as raised on their own.       */
  --paper:      #F4F7FA;   /* page background          */
  --surface:    #FFFFFF;   /* cards, inputs, panels    */
  --fog:        #EAF0F6;   /* quiet section background */
  --line:       #D5DFEA;   /* hairline borders         */
  --ink:        #0B1B2B;   /* primary text — navy-black, not neutral */
  --ink-2:      #002B52;   /* raised dark surface      */
  --slate:      #556478;   /* secondary text, 5.61:1   */

  /* Shadows and image overlays are mixed from NAVY rather than black.
     This is what makes the drop shadows and the gradient over every
     photo read as blue instead of grey.                                  */
  --ink-rgb:    0,51,102;

  /* --- 1.5 Panels that are dark in BOTH themes ------------------------ */
  --invert:     #002B52;
  --invert-2:   #00325E;
  --quote-end:  #00518C;

  /* --- 1.6 Foreground on coloured/dark ground -------------------------
     --paper flips between themes; these do not. Anything sitting on a
     permanently dark panel must use --on-invert, never --paper.          */
  --on-invert:      #F1F6FB;
  --on-invert-rgb:  241,246,251;
  --on-accent:      #FFFFFF;   /* on navy  — 12.61:1 */
  --on-brass:       #0B1B2B;   /* on azure —  6.07:1 */

  /* --- 1.7 Channel accents --------------------------------------------
     Three tones of the palette rather than three borrowed brand colours,
     so the marketplace cards stay distinguishable by tone. Override these
     three values to restore real brand colours.                          */
  --chan-1:     #0B6FA4;
  --chan-2:     #003366;
  --chan-3:     #4F5E72;

  /* --- 1.8 Elevation ---------------------------------------------------
     Corporate card treatment: a hairline border AND a soft navy shadow at
     rest, lifting on hover. Both tokens are navy-mixed, never grey.      */
  --shadow-card: 0 1px 2px rgba(var(--ink-rgb), .05),
                 0 4px 16px rgba(var(--ink-rgb), .07);
  --shadow-lift: 0 2px 4px rgba(var(--ink-rgb), .07),
                 0 18px 40px rgba(var(--ink-rgb), .14);

  /* --- 1.9 Component odds and ends ------------------------------------ */
  --header-bg:  rgba(244,247,250,.92);
  --ph-ink:     #A9BACD;

  /* --- 1.10 Legacy aliases ---------------------------------------------
     The original stylesheet refers to --red and --mint in ~100 places.
     Rather than rename every rule (and risk missing one), the old names
     point at the current palette. New work should use the names above.   */
  --red:        var(--accent);
  --red-deep:   var(--accent-deep);
  --red-ink:    var(--accent-ink);
  --red-wash:   var(--accent-wash);
  --mint:       var(--accent-2-ink);
  --mint-soft:  var(--accent-2-soft);
}

/* ---------------------------------------------------------------
   2. DARK

   The page becomes deep navy rather than neutral black, so the theme
   still reads as blue. Navy lightens to stay legible as text; the
   button fill lifts so it does not sink into the background.
   --------------------------------------------------------------- */
[data-theme="dark"]{
  color-scheme: dark;

  --accent:        #0F5B9E;   /* lifted so buttons stay visible */
  --accent-lift:   #1A6FB8;
  --accent-deep:   #0A4374;
  --accent-ink:    #6BA9E5;   /* 7.53:1 on the dark page */
  --accent-wash:   #10243A;
  --accent-rgb:    107,169,229;

  --accent-2:      #4FC3F0;
  --accent-2-ink:  #4FC3F0;   /* 9.28:1 — no darkening needed here */
  --accent-2-soft: #B8E4F7;
  --accent-2-rgb:  79,195,240;

  --paper:      #0A1220;
  --surface:    #101B2D;
  --fog:        #0D1626;
  --line:       #1E2C42;
  --ink:        #E8EDF4;
  --ink-2:      #16263C;
  --ink-rgb:    0,0,0;        /* shadows go black on a dark ground */
  --slate:      #93A3B8;

  --invert:     #0E2439;      /* lighter than the page, so inverted
                                 sections still read as raised      */
  --invert-2:   #16304A;
  --quote-end:  #0B3A63;

  --on-invert:      #F1F6FB;
  --on-invert-rgb:  241,246,251;
  --on-accent:      #FFFFFF;
  --on-brass:       #0B1B2B;

  --chan-1:     #4FC3F0;
  --chan-2:     #6BA9E5;
  --chan-3:     #9AAABF;

  --shadow-card: 0 1px 2px rgba(0,0,0,.30),
                 0 4px 16px rgba(0,0,0,.36);
  --shadow-lift: 0 2px 4px rgba(0,0,0,.34),
                 0 18px 40px rgba(0,0,0,.48);

  --header-bg:  rgba(10,18,32,.92);
  --ph-ink:     #35485F;
}

/* ---------------------------------------------------------------
   3. Sections that are dark ON PURPOSE in both themes
      (styles.css used --ink here, which now means "text")
   --------------------------------------------------------------- */
.channels,
.contact,
.manifest,
.story,
.net,
.svc-cta{ background: var(--invert); }

.svc-cta{ border-color: var(--invert); }
.statband{ background: var(--invert-2); }

.slide blockquote{
  background: linear-gradient(120deg, var(--invert) 0%, var(--invert-2) 55%, var(--quote-end) 100%);
}

/* ---------------------------------------------------------------
   4. Foreground on surfaces that FLIP between themes.
      These elements sit on var(--ink), which is dark in light mode and
      light in dark mode, so their text must flip with it — var(--paper),
      not var(--on-invert). Panels that are dark in BOTH themes are
      handled in section 3 and keep var(--on-invert).
   --------------------------------------------------------------- */
.skip-link,
.ph-tag{ color: var(--paper); }
.btn-ghost:hover,
.car-btn:hover,
.social a:hover,
.stop.is-active .stop-num{ color: var(--paper); }

.site-header{ background: var(--header-bg); }
.leader-ph{ color: var(--ph-ink); }

/* ---------------------------------------------------------------
   5. Red used as text needs to lift on a dark page
   --------------------------------------------------------------- */
.eyebrow,
.drawer-eyebrow,
.form-title,
.foot-h,
.post-cat,
.lb-cat,
.fact-n,
.proof figcaption,
.err,
.foot-cta strong,
h1 em{ color: var(--red-ink); }

.nav-link:hover,
.acc-btn:hover,
.acc-btn[aria-expanded="true"],
.post h3 a:hover,
.drawer a:hover,
.why-copy a,
.leaders-note a,
.foot-meta a,
.faq-head .sec-sub a,
.contact-list a:hover{ color: var(--red-ink); }

.btn-outline{ color: var(--red-ink); border-color: var(--red-ink); }
.btn-outline:hover{ background: var(--red); border-color: var(--red); color: var(--on-accent); }
.svc-ico{ color: var(--red-ink); }
/* Same accessible navy as .svc-ico — the bright azure fails contrast as a
   thin stroke, so every icon tile uses the -ink stop. */
.sw-ico,
.office-ico{ color: var(--red-ink); }
.logo-loo{ fill: var(--red-ink); }

/* the eyebrow sitting on an inverted background stays mint */
.channels .eyebrow,
.contact .eyebrow{ color: var(--mint-soft); }

/* ---------------------------------------------------------------
   6. The toggle button
   --------------------------------------------------------------- */
.theme-toggle{
  display: grid; place-items: center;
  width: 44px; height: 44px; flex: 0 0 auto;
  background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
  cursor: pointer; color: var(--ink);
  transition: border-color .18s var(--ease), color .18s var(--ease), background .18s var(--ease);
}
.theme-toggle:hover{ border-color: var(--ink); color: var(--red-ink); }
.theme-toggle svg{ width: 19px; height: 19px; }

/* show the sun in dark mode (tap to go light) and the moon in light mode */
.theme-toggle .ic-moon{ display: block; }
.theme-toggle .ic-sun{ display: none; }
[data-theme="dark"] .theme-toggle .ic-moon{ display: none; }
[data-theme="dark"] .theme-toggle .ic-sun{ display: block; }

/* ---------------------------------------------------------------
   7. Header breathing room on small screens
      Three controls plus a logo is tight at 390px, so the wordmark
      drops and the controls shrink rather than wrapping.
   --------------------------------------------------------------- */
@media (max-width: 620px){
  .theme-toggle{ width: 38px; height: 38px; }
  .theme-toggle svg{ width: 17px; height: 17px; }
  .header-actions{ gap: var(--s2); }
  .header-actions .btn-sm{ padding: 9px 12px; font-size: .8rem; }
  .burger{ width: 38px; height: 38px; }
}

/* ---------------------------------------------------------------
   8. Dark-mode refinements
   --------------------------------------------------------------- */
[data-theme="dark"] .hero{
  background:
    radial-gradient(1100px 460px at 12% -8%, rgba(var(--accent-rgb), .16), transparent 62%),
    var(--paper);
}
[data-theme="dark"] .mega,
[data-theme="dark"] .manifest,
[data-theme="dark"] .sw:hover,
[data-theme="dark"] .office:hover,
[data-theme="dark"] .svc:hover{ box-shadow: 0 24px 60px rgba(var(--ink-rgb), .45); }
[data-theme="dark"] .site-header.is-stuck{ box-shadow: 0 6px 24px rgba(var(--ink-rgb), .4); }
[data-theme="dark"] .svc:hover,
[data-theme="dark"] .sw:hover,
[data-theme="dark"] .office:hover,
[data-theme="dark"] .post:hover{ border-color: var(--slate); }
[data-theme="dark"] .field input:focus,
[data-theme="dark"] .field select:focus,
[data-theme="dark"] .field textarea:focus{
  border-color: var(--slate); box-shadow: 0 0 0 3px rgba(var(--on-invert-rgb), .10);
}
[data-theme="dark"] .barcode{ opacity: .65; }

/* The toggle itself must never animate its colour change under
   reduced motion, and the whole page should not cross-fade. */
@media (prefers-reduced-motion: reduce){
  .theme-toggle{ transition: none; }
}

/* =========================================================================
   9. ENHANCED UI LAYER
   Hero pill, gradient CTAs, hero stat row, live manifest.
   Appended here so it sits after every base rule and wins on order.
   ========================================================================= */

/* --- 9.1 Status pill (replaces the plain hero eyebrow) --- */
.pill{
  display:inline-flex; align-items:center; gap:9px;
  padding:8px 16px 8px 12px; margin:0 0 var(--s5);
  background:var(--paper); border:1px solid var(--line); border-radius:999px;
  font-size:var(--t-small); font-weight:500; color:var(--slate);
}
.pill-dot{
  width:8px; height:8px; border-radius:50%; background:var(--mint); flex:0 0 auto;
  box-shadow:0 0 0 0 rgba(var(--accent-2-rgb), .55); animation:pulse 2.4s var(--ease) infinite;
}
@keyframes pulse{
  0%   { box-shadow:0 0 0 0 rgba(var(--accent-2-rgb), .5); }
  70%  { box-shadow:0 0 0 8px rgba(var(--accent-2-rgb), 0); }
  100% { box-shadow:0 0 0 0 rgba(var(--accent-2-rgb), 0); }
}

/* --- 9.2 Buttons: depth without noise --- */
.btn-lg{ padding:16px 28px; font-size:1rem; }

.btn-primary{
  background:linear-gradient(135deg, var(--accent-lift) 0%, var(--accent) 55%, var(--accent-deep) 100%);
  border-color:transparent;
  box-shadow:0 8px 22px rgba(var(--accent-rgb), .26);
}
.btn-primary:hover{
  background:linear-gradient(135deg, var(--red) 0%, var(--red-deep) 100%);
  border-color:transparent;
  box-shadow:0 12px 30px rgba(var(--accent-rgb), .34);
}
.btn-primary:active{ box-shadow:0 4px 12px rgba(var(--accent-rgb), .28); }

.btn-ghost{ background:var(--paper); }
.btn-ghost:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink); }

[data-theme="dark"] .btn-primary{ box-shadow:0 8px 26px rgba(var(--accent-rgb), .34); }
[data-theme="dark"] .btn-primary:hover{ box-shadow:0 14px 36px rgba(var(--accent-rgb), .44); }

/* --- 9.3 Hero stat row --- */
.hero-stats{
  display:flex; flex-wrap:wrap; gap:var(--s7);
  margin:var(--s7) 0 0; padding-top:var(--s6);
  border-top:1px solid var(--line);
}
.hero-stats li{ display:flex; flex-direction:column; gap:2px; }
.hs-n{
  font-family:var(--display); font-weight:800; font-size:1.75rem;
  letter-spacing:-.03em; line-height:1;
}
.hs-l{ font-size:var(--t-small); color:var(--slate); }
.hero-note{ margin-top:var(--s5); }

/* --- 9.4 Headline accent
   In light mode this stays a solid red. A gradient into orange would drop
   the lightest stop to ~2.9:1 on white, which fails WCAG AA. On the dark
   page both stops clear 6.5:1, so the gradient is applied there only. --- */
[data-theme="dark"] h1 em{
  background:linear-gradient(100deg, var(--accent-ink) 10%, var(--accent-2) 90%);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}
@supports not (background-clip: text){
  [data-theme="dark"] h1 em{ color:var(--red-ink); -webkit-text-fill-color:var(--red-ink); }
}

/* --- 9.5 Live manifest --- */
.live-dot{
  display:inline-block; width:7px; height:7px; border-radius:50%;
  background:var(--mint); margin-right:8px; vertical-align:middle;
  animation:pulse 2.4s var(--ease) infinite;
}
.live-badge{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px; border-radius:999px;
  border:1px solid rgba(var(--accent-2-rgb), .4); color:var(--mint-soft);
  font-family:var(--mono); font-size:.65rem; letter-spacing:.16em; text-transform:uppercase;
}
.live-badge::before{
  content:""; width:5px; height:5px; border-radius:50%; background:var(--mint-soft);
}

.spark{
  display:flex; align-items:flex-end; gap:4px;
  height:56px; margin:var(--s5) 0 var(--s4);
}
.spark span{
  flex:1; height:var(--h);
  background:linear-gradient(180deg, var(--red) 0%, rgba(var(--accent-rgb), .35) 100%);
  border-radius:2px 2px 0 0;
  transform-origin:bottom; animation:grow .7s var(--ease) backwards;
}
.spark span:nth-child(1){ animation-delay:.05s } .spark span:nth-child(2){ animation-delay:.10s }
.spark span:nth-child(3){ animation-delay:.15s } .spark span:nth-child(4){ animation-delay:.20s }
.spark span:nth-child(5){ animation-delay:.25s } .spark span:nth-child(6){ animation-delay:.30s }
.spark span:nth-child(7){ animation-delay:.35s } .spark span:nth-child(8){ animation-delay:.40s }
.spark span:nth-child(9){ animation-delay:.45s } .spark span:nth-child(10){ animation-delay:.50s }
.spark span:nth-child(11){ animation-delay:.55s } .spark span:nth-child(12){ animation-delay:.60s }
@keyframes grow{ from{ transform:scaleY(0); } to{ transform:scaleY(1); } }

.manifest{
  border:1px solid rgba(var(--on-invert-rgb), .09);
  background:linear-gradient(160deg, var(--invert) 0%, var(--invert-2) 100%);
}
.manifest-foot{ padding-top:var(--s4); border-top:1px solid rgba(var(--on-invert-rgb), .1); }

/* --- 9.6 Hero backdrop: a faint plotting grid, faded out at the edges --- */
.hero{ position:relative; overflow:hidden; }
.hero::before{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background:
    repeating-linear-gradient(90deg, rgba(var(--ink-rgb), .045) 0 1px, transparent 1px 72px),
    repeating-linear-gradient(0deg,  rgba(var(--ink-rgb), .045) 0 1px, transparent 1px 72px);
  mask-image:radial-gradient(900px 520px at 30% 10%, #000, transparent 78%);
}
[data-theme="dark"] .hero::before{
  background:
    repeating-linear-gradient(90deg, rgba(var(--on-invert-rgb), .055) 0 1px, transparent 1px 72px),
    repeating-linear-gradient(0deg,  rgba(var(--on-invert-rgb), .055) 0 1px, transparent 1px 72px);
}
.hero-grid, .trust{ position:relative; z-index:1; }

/* --- 9.7 Card polish --- */
.svc, .post, .proof{ transition:border-color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease); }
.story{ border:1px solid rgba(var(--on-invert-rgb), .08); }
.chan-grid li{ position:relative; }

/* --- 9.8 Responsive --- */
@media (max-width: 900px){
  .hero-stats{ gap:var(--s6); }
  .hs-n{ font-size:1.5rem; }
}
@media (max-width: 620px){
  .btn-lg{ padding:14px 22px; font-size:.95rem; }
  .hero-stats{ gap:var(--s5) var(--s6); }
  .hero::before{ display:none; }
  .spark{ height:44px; }
}

@media (prefers-reduced-motion: reduce){
  .pill-dot, .live-dot{ animation:none; }
  .spark span{ animation:none; }
}

/* =========================================================================
   10. LEADERSHIP CARDS + PROFILE DIALOG
   ========================================================================= */

/* --- 10.1 Cards --- */
.leader-grid > li{ display:flex; }
.leader{
  display:flex; flex-direction:column; gap:5px; width:100%;
  padding:0; background:none; border:0; text-align:left; cursor:pointer;
}
/* Photographs were removed; each person is an initials monogram. The box
   was a 3:4 portrait frame, which left a tall empty rectangle once the
   image went, so it is now a compact circular tile. */
.leader-photo{
  position:relative; display:grid; place-items:center;
  width:84px; height:84px; margin-bottom:var(--s4);
  border-radius:50%; overflow:hidden;
  background:var(--accent-wash); border:1px solid var(--line);
  transition:border-color .22s var(--ease), transform .22s var(--ease),
             box-shadow .22s var(--ease), background .22s var(--ease);
}
.leader-initials{
  font-family:var(--display); font-weight:800; font-size:1.6rem;
  letter-spacing:-.02em; color:var(--accent-ink);
}
.leader:hover .leader-photo{
  border-color:var(--accent); transform:translateY(-3px);
  background:var(--accent); 
  box-shadow:0 12px 28px rgba(var(--ink-rgb), .18);
}
.leader:hover .leader-initials{ color:var(--on-accent); }
.leader:focus-visible .leader-photo{ border-color:var(--accent); }

.leader-n{ font-weight:600; font-size:.98rem; }
.leader-r{ font-size:var(--t-small); color:var(--slate); line-height:1.35; }
.leader-view{
  margin-top:6px; font-size:var(--t-small); font-weight:600; color:var(--red-ink);
  opacity:0; transform:translateY(-3px);
  transition:opacity .22s var(--ease), transform .22s var(--ease);
}
.leader:hover .leader-view,
.leader:focus-visible .leader-view{ opacity:1; transform:none; }

/* --- 10.2 Dialog shell --- */
.pmodal[hidden]{ display:none; }
.pmodal{
  position:fixed; inset:0; z-index:160; display:grid; place-items:center;
  padding:var(--s5); overflow-y:auto;
  background:rgba(var(--ink-rgb), .68); backdrop-filter:blur(3px);
  opacity:0; transition:opacity .2s var(--ease);
}
.pmodal.is-open{ opacity:1; }

.pmodal-panel{
  position:relative; width:min(940px,100%); margin:auto;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); overflow:hidden;
  box-shadow:0 40px 90px rgba(var(--ink-rgb), .4);
  transform:translateY(12px) scale(.985);
  transition:transform .28s var(--ease);
}
.pmodal.is-open .pmodal-panel{ transform:none; }

.pmodal-close{
  position:absolute; top:12px; right:12px; z-index:3;
  width:38px; height:38px; border:0; border-radius:50%;
  background:rgba(var(--on-invert-rgb), .16); color:var(--on-invert);
  font-size:1.5rem; line-height:1; cursor:pointer;
  transition:background .18s var(--ease);
}
.pmodal-close:hover{ background:rgba(var(--on-invert-rgb), .3); }

.pm-banner{
  height:104px;
  background:linear-gradient(115deg, var(--accent-lift) 0%, var(--accent) 45%, var(--accent-deep) 100%);
}

/* --- 10.3 Header --- */
.pm-head{
  display:grid; grid-template-columns:auto 1fr auto; align-items:end;
  gap:var(--s5); padding:var(--s4) var(--s7) var(--s5);
}
/* Only the avatar breaks into the banner. The name and role stay below it,
   because dark text on the red banner would fail contrast. */
.pm-avatar{ margin-top:-74px; margin-bottom:-2px; }
.pm-avatar{
  position:relative; display:grid; place-items:center;
  width:112px; height:112px; border-radius:50%; overflow:hidden;
  background:var(--fog); border:4px solid var(--surface);
  box-shadow:0 10px 26px rgba(var(--ink-rgb), .18);
}
.pm-initials{ font-family:var(--display); font-weight:800; font-size:2rem; color:var(--accent-ink); }

.pm-id{ padding-bottom:4px; min-width:0; }
.pm-id h3{ font-size:1.65rem; margin:0 0 4px; }
.pm-role{ margin:0 0 8px; color:var(--red-ink); font-weight:600; font-size:.95rem; }
.pm-meta{ display:flex; flex-wrap:wrap; gap:6px 16px; font-size:var(--t-small); color:var(--slate); }
.pm-meta[hidden]{ display:none; }
.pm-rating{ color:var(--accent-2-ink); font-weight:600; }
[data-theme="dark"] .pm-rating{ color:var(--accent-2-ink); }

.pm-actions{ display:flex; gap:8px; padding-bottom:6px; }

/* --- 10.4 Body --- */
.pm-body{
  display:grid; grid-template-columns:1.35fr 1fr; gap:var(--s7);
  padding:var(--s5) var(--s7) var(--s7);
  border-top:1px solid var(--line);
}
.pm-block{ margin-bottom:var(--s6); }
.pm-block[hidden]{ display:none; }
.pm-block h4{
  margin:0 0 var(--s3);
  font-family:var(--mono); font-size:var(--t-micro); font-weight:500;
  letter-spacing:.18em; text-transform:uppercase; color:var(--red-ink);
}
.pm-block p{ margin:0; color:var(--slate); font-size:.95rem; }

.chips{ display:flex; flex-wrap:wrap; gap:8px; }
.chips li{
  padding:6px 12px; border-radius:999px; font-size:var(--t-small);
  border:1px solid var(--red-ink); color:var(--red-ink); background:var(--red-wash);
}
.chips-alt li{ border-color:rgba(var(--accent-2-rgb), .5); color:var(--mint); background:transparent; }
.chips-quiet li{ border-color:var(--line); color:var(--slate); background:var(--fog); }

/* --- 10.5 In-dialog form --- */
.pm-form{
  align-self:start; padding:var(--s5);
  background:var(--fog); border:1px solid var(--line); border-radius:var(--r-lg);
}
.pm-form-title{
  margin:0 0 var(--s5);
  font-family:var(--mono); font-size:var(--t-micro); letter-spacing:.18em;
  text-transform:uppercase; color:var(--red-ink);
}
.pm-form .field{ margin-bottom:var(--s4); }
.pm-form textarea{ resize:vertical; }

/* --- 10.6 Responsive --- */
@media (max-width: 860px){
  .pm-body{ grid-template-columns:1fr; gap:var(--s6); }
}
@media (max-width: 620px){
  .pmodal{ padding:0; }
  .pmodal-panel{ border-radius:0; min-height:100vh; }
  .pm-head{
    grid-template-columns:1fr; align-items:start;
    gap:var(--s4); padding:var(--s3) var(--s5) var(--s5);
  }
  .pm-avatar{ width:88px; height:88px; margin-top:-58px; }
  .pm-id h3{ font-size:1.35rem; }
  .pm-actions{ padding-bottom:0; }
  .pm-actions .btn{ flex:1; }
  .pm-body{ padding:var(--s5); }
  .pm-banner{ height:88px; }
}

@media (prefers-reduced-motion: reduce){
  .pmodal, .pmodal-panel, .leader-photo, .leader-view{ transition:none; }
}

/* =========================================================================
   11. AMBIENT MOTION
   A cursor-tracked glow behind the page, a spotlight inside cards, and a
   larger animated channel swap in the manifest.
   Driven by --gx/--gy (page) and --mx/--my (per card) from js/ambient.js.
   ========================================================================= */

:root{ --gx:50%; --gy:35%; --mx:50%; --my:50%; }

/* --- 11.1 The glow layer ------------------------------------------------
   Fixed, behind everything, never interactive. Two blobs: one chases the
   cursor, one drifts on a slow loop so the page is never completely still. */
body::before{
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(760px 620px at var(--gx) var(--gy), rgba(var(--accent-rgb), .10), transparent 70%),
    radial-gradient(620px 520px at 12% 88%, rgba(var(--accent-2-rgb), .07), transparent 72%);
  transition:opacity .4s var(--ease);
}
[data-theme="dark"] body::before{
  background:
    radial-gradient(820px 660px at var(--gx) var(--gy), rgba(var(--accent-rgb), .20), transparent 70%),
    radial-gradient(680px 560px at 10% 90%, rgba(var(--accent-2-rgb), .11), transparent 72%),
    radial-gradient(900px 700px at 92% 8%, rgba(var(--accent-2-rgb), .16), transparent 74%);
}

/* Content sits above the glow.
   IMPORTANT: only elements that are statically positioned belong here.
   Adding .pmodal / .lightbox / .drawer / .fab to this list overwrote their
   own `position: fixed` with `relative`, which dropped the profile dialog,
   the story lightbox, the mobile drawer and the floating contact button
   into normal document flow at the bottom of the page instead of
   overlaying it. They already carry their own position and z-index. */
main, .site-footer{ position:relative; z-index:1; }

/* .site-header is deliberately absent above: it is position:sticky with
   z-index:100 in styles.css, and forcing it to relative/1 both unstuck it
   and dropped it below the mobile drawer scrim, making the burger button
   impossible to tap. */

/* --- 11.2 Letting the glow through --------------------------------------
   Sections are opaque by default, which would hide the layer entirely.
   In dark mode they become translucent so the glow reads through the page
   the way it does behind frosted glass. Light mode stays opaque, because
   a wash of red under body text costs contrast for very little gain. */
[data-theme="dark"] .hero,
[data-theme="dark"] .quotes,
[data-theme="dark"] .leaders,
[data-theme="dark"] .about,
[data-theme="dark"] .process,
[data-theme="dark"] .faq,
[data-theme="dark"] .site-footer{ background-color:transparent; }

[data-theme="dark"] .solutions,
[data-theme="dark"] .offices,
[data-theme="dark"] .why,
[data-theme="dark"] .stories,
[data-theme="dark"] .insights{ background-color:color-mix(in srgb, var(--surface) 82%, transparent); }

[data-theme="dark"] .channels,
[data-theme="dark"] .contact{ background-color:color-mix(in srgb, var(--invert) 88%, transparent); }

[data-theme="dark"] .statband{ background-color:color-mix(in srgb, var(--invert-2) 92%, transparent); }

/* the hero's own gradient would double up with the glow */
[data-theme="dark"] .hero{ background-image:none; }

/* --- 11.3 Card spotlight ------------------------------------------------
   Drawn as an ::after overlay rather than a ::before behind the card.
   A negative z-index would sit behind the card's own background and never
   be seen. Alpha is kept low so text contrast is unaffected. --- */
.svc, .post, .proof, .story, .form, .pm-form, .manifest{ position:relative; }

.svc::after, .post::after, .proof::after,
.story::after, .form::after, .pm-form::after,
.manifest::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:2;
  border-radius:inherit; opacity:0;
  background:radial-gradient(420px circle at var(--mx) var(--my), rgba(var(--accent-rgb), .09), transparent 62%);
  transition:opacity .3s var(--ease);
}
.svc:hover::after, .post:hover::after, .proof:hover::after,
.form:hover::after, .pm-form:hover::after,
.manifest:hover::after, .story:hover::after{ opacity:1; }

/* on dark panels the highlight has to be light, not red */
.story::after,
.manifest::after{
  background:radial-gradient(420px circle at var(--mx) var(--my), rgba(var(--on-invert-rgb), .13), transparent 60%);
}
[data-theme="dark"] .svc::after,
[data-theme="dark"] .post::after,
[data-theme="dark"] .proof::after,
[data-theme="dark"] .form::after,
[data-theme="dark"] .pm-form::after{
  background:radial-gradient(420px circle at var(--mx) var(--my), rgba(var(--accent-rgb), .13), transparent 62%);
}

/* the story card keeps its own gradient scrim below the spotlight */

/* --- 11.4 The channel readout ------------------------------------------
   Larger, gradient-filled, and it slides up as it swaps rather than just
   fading — the movement is what makes it read as live data. */
.manifest-channel{ align-items:center; }
.channel-rotator{
  font-size:clamp(1.6rem, 1.2rem + 1.1vw, 2.1rem);
  font-weight:800; letter-spacing:-.03em; text-align:right;
  background:linear-gradient(96deg, var(--accent-2-soft) 0%, var(--accent-2) 55%, var(--accent-ink) 100%);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
  transition:opacity .26s var(--ease), transform .26s var(--ease), filter .26s var(--ease);
}
.channel-rotator.is-swapping{
  opacity:0; transform:translateY(-10px); filter:blur(3px);
}
@supports not (background-clip: text){
  .channel-rotator{ color:var(--accent-2); -webkit-text-fill-color:var(--accent-2); }
}

/* --- 11.5 Navigation underline ----------------------------------------- */
.nav-list > li > .nav-link{ position:relative; }
.nav-list > li > .nav-link::before{
  content:""; position:absolute; left:14px; right:14px; bottom:4px; height:2px;
  background:var(--red-ink); border-radius:1px;
  transform:scaleX(0); transform-origin:left; transition:transform .24s var(--ease);
}
.nav-list > li > .nav-link:hover::before,
.nav-list > li > .nav-link[aria-expanded="true"]::before{ transform:scaleX(1); }
.nav-link:hover{ background:transparent; }

/* --- 11.6 Guard rails --------------------------------------------------- */
@media (pointer: coarse){
  body::before{
    background:
      radial-gradient(700px 560px at 78% 8%, rgba(var(--accent-rgb), .10), transparent 70%),
      radial-gradient(560px 460px at 8% 92%, rgba(var(--accent-2-rgb), .06), transparent 72%);
  }
}
@media (prefers-reduced-motion: reduce){
  .channel-rotator, .svc::before, .post::before, .proof::before,
  .story::before, .nav-list > li > .nav-link::before{ transition:none; }
  body::before{ background-position:0 0; }
}

/* --- 11.7 Card surfaces in dark mode -----------------------------------
   In light mode cards are white on grey, so they read as raised. Using
   --paper in dark mode inverts that and the cards sink into the section.
   These lift them back above their background. --- */
[data-theme="dark"] .svc,
[data-theme="dark"] .post,
[data-theme="dark"] .proof,
[data-theme="dark"] .form,
[data-theme="dark"] .pm-form,
[data-theme="dark"] .foot-cta,
[data-theme="dark"] .pill{ background-color:color-mix(in srgb, var(--surface) 94%, transparent); }

[data-theme="dark"] .field input,
[data-theme="dark"] .field select,
[data-theme="dark"] .field textarea{ background-color:color-mix(in srgb, var(--paper) 88%, transparent); }

[data-theme="dark"] .pmodal-panel,
[data-theme="dark"] .lb-panel,
[data-theme="dark"] .mega,
[data-theme="dark"] .drawer{ background-color:var(--surface); }

/* =========================================================================
   12. MARKETPLACE STORY CARDS
   Amazon / eBay / Walmart. The channel names are set in the site's own
   display face rather than reproduced as brand logos — see the note in
   section 12.2.
   ========================================================================= */

.mkt-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s5); }

.mkt{
  position:relative; display:flex; flex-direction:column;
  padding:var(--s7) var(--s6) var(--s6);
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
  transition:border-color .22s var(--ease), transform .22s var(--ease), box-shadow .22s var(--ease);
}
.mkt:hover{
  border-color:var(--ink); transform:translateY(-4px);
  box-shadow:0 22px 46px rgba(var(--ink-rgb), .10);
}
[data-theme="dark"] .mkt{ background-color:color-mix(in srgb, var(--surface) 94%, transparent); }
[data-theme="dark"] .mkt:hover{ border-color:var(--slate); box-shadow:0 22px 46px rgba(var(--ink-rgb), .45); }

/* --- 12.1 Head --- */
.mkt-head{ display:flex; flex-direction:column; gap:var(--s4); margin-bottom:var(--s5); }
.mkt-rule{
  display:block; width:44px; height:3px; border-radius:2px;
  background:var(--mkt-accent, var(--red-ink));
}

/* --- 12.2 Channel wordmark
   Set in Archivo, tightly tracked, with one accent colour each. Reproducing
   the real Amazon, eBay and Walmart logos would mean displaying three
   trademarks you do not own on a page selling your own services — a risk
   that is easy to avoid and costs nothing visually. If you have written
   permission, swap the <span class="mkt-mark"> for an <img> at height:32px. */
.mkt-mark{
  font-family:var(--display); font-weight:800;
  font-size:clamp(1.6rem, 1.3rem + .8vw, 2rem);
  letter-spacing:-.04em; line-height:1; color:var(--mkt-accent, var(--ink));
}
.mkt-mark[data-channel="amazon"]{ --mkt-accent:var(--chan-1); }
.mkt-mark[data-channel="ebay"]  { --mkt-accent:var(--chan-2); }
.mkt-mark[data-channel="walmart"]{ --mkt-accent:var(--chan-3); }
.mkt-head:has(.mkt-mark[data-channel="amazon"]) .mkt-rule{ background:var(--chan-1); }
.mkt-head:has(.mkt-mark[data-channel="ebay"]) .mkt-rule{ background:var(--chan-2); }
.mkt-head:has(.mkt-mark[data-channel="walmart"]) .mkt-rule{ background:var(--chan-3); }


/* --- 12.3 Body --- */
.mkt h3{ font-size:1.2rem; margin-bottom:var(--s3); max-width:22ch; }
.mkt > p{ color:var(--slate); font-size:.95rem; margin-bottom:var(--s5); }

.mkt-points{
  display:grid; gap:10px; margin:0 0 var(--s6);
  padding-top:var(--s5); border-top:1px solid var(--line);
}
.mkt-points li{
  position:relative; padding-left:var(--s5);
  font-size:var(--t-small); color:var(--slate); line-height:1.45;
}
.mkt-points li::before{
  content:""; position:absolute; left:0; top:.55em;
  width:8px; height:8px; border-radius:50%;
  border:2px solid var(--mkt-accent, var(--red-ink)); box-sizing:border-box;
}
.mkt:nth-child(1) .mkt-points li::before{ border-color:var(--chan-1); }
.mkt:nth-child(2) .mkt-points li::before{ border-color:var(--chan-2); }
.mkt:nth-child(3) .mkt-points li::before{ border-color:var(--chan-3); }

/* --- 12.4 Footer link --- */
.mkt-link{
  display:flex; align-items:center; justify-content:space-between; gap:var(--s4);
  width:100%; margin-top:auto; padding:var(--s4) 0 0;
  background:none; border:0; border-top:1px solid var(--line);
  font-family:var(--body); font-weight:600; font-size:var(--t-small);
  text-align:left; cursor:pointer;
  transition:color .18s var(--ease);
}
.mkt-link:hover{ color:var(--red-ink); }
.mkt-arrow{
  display:grid; place-items:center; flex:0 0 auto;
  width:34px; height:34px; border-radius:50%;
  border:1.5px solid var(--line); font-size:.95rem;
  transition:border-color .22s var(--ease), background .22s var(--ease),
             color .22s var(--ease), transform .22s var(--ease);
}
.mkt-link:hover .mkt-arrow{
  border-color:var(--accent); background:var(--accent); color:var(--on-accent); transform:translateX(3px);
}

/* --- 12.5 Brands sub-block --- */
.brands-block{ margin-top:var(--s9); padding-top:var(--s7); border-top:1px solid var(--line); }
.brands-title{
  font-family:var(--mono); font-size:var(--t-micro); font-weight:500;
  letter-spacing:.18em; text-transform:uppercase; color:var(--red-ink);
  margin-bottom:var(--s5);
}

/* --- 12.6 Responsive --- */
@media (max-width: 1080px){
  .mkt-grid{ grid-template-columns:1fr; gap:var(--s4); }
  .mkt h3{ max-width:none; }
}
@media (max-width: 620px){
  .mkt{ padding:var(--s6) var(--s5) var(--s5); }
}

/* =========================================================================
   13. LOGO
   Theme-aware via CSS variables. The mark is inline SVG so it inherits
   these; the standalone favicon.svg carries its own copy because an
   external file cannot read the page's variables.
   ========================================================================= */

/* --- 13.1 Tokens ------------------------------------------------------- */
:root{
  /* The mark now reads entirely from the palette, so it can never drift
     out of step with the site the way the old blue-on-red version did.
     The ribbon carries the pine gradient from .btn-primary; the growth
     arrow is brass, because brass is this system's "data and upside"
     colour and it gives the mark a second tone at small sizes.          */
  --logo-ink:   var(--ink);          /* L, cart, globe, wordmark        */
  --logo-disc:  var(--surface);      /* the well inside each ring       */
  --logo-mint:  var(--accent-2-ink); /* growth arrow — 5.48:1 in light  */
  --logo-r1:    var(--accent-lift);  /* ribbon gradient                 */
  --logo-r2:    var(--accent);
  --logo-r3:    var(--accent-deep);
  --logo-tld:   var(--accent-ink);   /* the ".tech" accent              */
}
[data-theme="dark"]{
  --logo-disc:  var(--paper);
  --logo-mint:  var(--accent-2);     /* 10.29:1 on the dark page        */
  --logo-r1:    var(--accent-2-soft);
  --logo-r2:    var(--accent-ink);
  --logo-r3:    var(--accent);
  --logo-tld:   var(--accent-ink);
}

/* --- 13.2 Layout ------------------------------------------------------- */
.loo-logo{ display:inline-flex; align-items:center; gap:10px; text-decoration:none; }
.loo-mark{ width:64px; height:37px; flex:0 0 auto; overflow:visible; }

.loo-word{ display:flex; flex-direction:column; line-height:1; }
.loo-word-main{
  font-family:var(--display); font-weight:800; font-size:1.02rem;
  letter-spacing:-.025em; color:var(--logo-ink);
}
.loo-word-tld{ color:var(--logo-tld); }
.loo-word-sub{
  font-family:var(--mono); font-size:.5rem; font-weight:500;
  letter-spacing:.22em; text-transform:uppercase;
  color:var(--slate); margin-top:4px;
}

/* --- 13.3 Micro-interactions ------------------------------------------
   The arrow draws itself once on load, then nudges further along its
   path on hover. The rings breathe outward. Same easing curve and
   timing band as the site's buttons and cards. --- */
.loo-arc{
  stroke-dasharray:64; stroke-dashoffset:0;
  animation:loo-draw .9s var(--ease) .15s backwards;
}
@keyframes loo-draw{ from{ stroke-dashoffset:64; } }

.loo-tip{ animation:loo-fade .4s var(--ease) .85s backwards; }
@keyframes loo-fade{ from{ opacity:0; transform:translate(-4px,3px); } }

.loo-arc, .loo-tip{ transition:transform .38s var(--ease); }
.loo-logo:hover .loo-arc,
.loo-logo:hover .loo-tip{ transform:translate(2.5px,-2.5px); }

.loo-ribbon{
  stroke-dasharray:220; stroke-dashoffset:0;
  animation:loo-trace 1.15s var(--ease) backwards;
  transition:transform .38s var(--ease); transform-origin:center; transform-box:fill-box;
}
@keyframes loo-trace{ from{ stroke-dashoffset:220; } }
.loo-logo:hover .loo-ribbon{ transform:scale(1.035); }

.loo-cart, .loo-globe{ transition:opacity .3s var(--ease); }
.loo-logo:focus-visible{ outline:3px solid var(--accent-ink); outline-offset:4px; border-radius:var(--r-md); }

/* --- 13.4 Small screens: drop the sub-line, keep the mark and name --- */
@media (max-width: 620px){
  .loo-mark{ width:50px; height:29px; }
  .loo-word-sub{ display:none; }
  .loo-word-main{ font-size:.88rem; }
  /* The mark plus the full wordmark plus three controls will not fit at
     390px. The header CTA gives way rather than the brand: "Get started"
     still appears in the drawer and on the floating contact button. */
  .header-actions .btn-sm{ display:none; }
}

/* Below ~44px the cart and globe become noise. Hide them and let the
   loop read as a clean double-O. */
.loo-mark.is-compact .loo-detail{ display:none; }

@media (prefers-reduced-motion: reduce){
  .loo-arc, .loo-tip, .loo-ribbon{ animation:none; }
  .loo-arc, .loo-tip, .loo-ribbon{ transition:none; }
}

/* ---------------------------------------------------------------
   14. ENTERPRISE TREATMENT

   Three things the navy brief asks for that are not just token values:
   a resting shadow on cards, a blue gradient over imagery, and a
   contrasting CTA button. Each is built from the tokens above.
   --------------------------------------------------------------- */

/* --- 14.1 Cards: hairline border AND a soft navy shadow at rest ------
   The previous theme was deliberately flat. Corporate cards read as
   physical objects, so they carry elevation before you touch them and
   lift further on hover.                                              */
.svc, .mkt, .post, .form, .proof, .lb-panel, .pmodal-panel{
  box-shadow: var(--shadow-card);
}
.svc:hover, .mkt:hover, .post:hover{
  box-shadow: var(--shadow-lift);
  border-color: rgba(var(--accent-rgb), .45);
  transform: translateY(-4px);
}
.svc, .mkt, .post{
  transition: transform .22s var(--ease),
              box-shadow .22s var(--ease),
              border-color .22s var(--ease);
}

/* --- 14.2 Blue gradient over imagery ---------------------------------
   Photographs get a navy scrim that deepens toward the bottom, so text
   over them stays readable and the imagery joins the palette instead of
   fighting it.                                                         */
.post-media::after, .about-media .net::after{
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(
    180deg,
    rgba(var(--accent-rgb), .00) 40%,
    rgba(var(--accent-rgb), .42) 100%);
  pointer-events: none;
}
.post-media{ position: relative; overflow: hidden; }

/* Images warm slightly on hover rather than simply scaling. */
.post-media img{ transition: transform .5s var(--ease), filter .5s var(--ease); }
.post:hover .post-media img{ transform: scale(1.04); filter: saturate(1.08); }

/* --- 14.3 Contrasting CTA -------------------------------------------
   Navy on navy has no urgency. .btn-accent puts bright azure against the
   dark sections, with ink on top at 6.07:1. Add the class alongside
   .btn to any call to action that needs to win the page.               */
.btn-accent{
  background: var(--accent-2);
  color: var(--on-brass);
  border-color: var(--accent-2);
  box-shadow: 0 8px 22px rgba(var(--accent-2-rgb), .30);
}
.btn-accent:hover{
  background: var(--accent-2-soft);
  border-color: var(--accent-2-soft);
  color: var(--accent-deep);
  box-shadow: 0 12px 30px rgba(var(--accent-2-rgb), .40);
  transform: translateY(-2px);
}
.btn-accent:active{ transform: translateY(0); }

/* --- 14.4 Section headings get a short navy rule --------------------- */
.section-head .eyebrow::before{
  content: '';
  display: inline-block;
  width: 22px; height: 2px;
  margin-right: 10px;
  vertical-align: middle;
  background: var(--accent-2);
}

@media (prefers-reduced-motion: reduce){
  .svc, .mkt, .post, .btn-accent{ transition: none; }
  .svc:hover, .mkt:hover, .post:hover, .btn-accent:hover{ transform: none; }
  .post:hover .post-media img{ transform: none; }
}

/* ---------------------------------------------------------------
   15. CHANNELS SECTION — ambient depth

   The section was a flat navy fill behind a bordered table. It now gets
   two very soft radial washes and a faint grid, so the cards sit on a
   surface with depth instead of a plain rectangle. Both layers are
   painted gradients, not blurs — no filter cost.
   --------------------------------------------------------------- */
.channels{ position: relative; overflow: hidden; }

.channels::before{
  content: ''; position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(760px 420px at 12% 0%,  rgba(var(--accent-2-rgb), .13), transparent 62%),
    radial-gradient(620px 380px at 92% 8%,  rgba(var(--accent-rgb),   .30), transparent 66%);
}

/* Faint grid, fading out before it reaches the lower edge so it never
   competes with the cards. */
.channels::after{
  content: ''; position: absolute; inset: 0; z-index: 0;
  pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(to right,  rgba(var(--on-invert-rgb), .05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--on-invert-rgb), .05) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 72%);
          mask-image: linear-gradient(180deg, #000 0%, transparent 72%);
}

.channels > .shell{ position: relative; z-index: 1; }

/* The heading carries the section; let it run larger and tighter here. */
.chan-title{
  font-size: clamp(2.2rem, 1.3rem + 3.2vw, 3.9rem);
  line-height: 1.04;
  letter-spacing: -.03em;
  max-width: 18ch;
}
.channels .sec-sub{
  max-width: 56ch;
  color: rgba(var(--on-invert-rgb), .72);
}

/* Keyboard focus must be visible on a dark ground. */
.chan:focus-visible,
.chan:focus-within{
  outline: 3px solid var(--accent-2);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce){
  .chan{ transition: none; }
  .chan:hover, .chan:focus-within{ transform: none; }
  .chan:hover .chan-mark{ transform: none; }
  .chan::before{ transition: none; }
}

/* ---------------------------------------------------------------
   16. MARKETPLACE ECOSYSTEM

   Desktop shows a connected network: LooSolution at the centre, twelve
   channels around it, thin curved links between. Below 1024px the whole
   diagram is hidden and the existing .chan-grid takes over — a network
   diagram squeezed onto a phone is unreadable, so it is not attempted.

   Everything is one inline SVG on a fixed viewBox, so proportions and
   type sizes scale exactly with no per-breakpoint tuning.
   --------------------------------------------------------------- */
.eco{
  position: relative;
  margin-top: var(--s7);
  display: none;                    /* desktop-only, enabled at 1024px */
}
.eco-svg{ position: relative; z-index: 1; display: block; width: 100%; height: auto; }

/* Star field. A canvas rather than DOM nodes: ~60 particles cost one
   element instead of sixty, and the whole thing stops when scrolled away. */
.eco-stars{
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}

/* --- connection lines ------------------------------------------------ */
.eco-line{
  fill: none;
  stroke: rgba(var(--on-invert-rgb), .16);
  stroke-width: 1;
  stroke-dasharray: 4 7;
  transition: stroke .3s var(--ease), stroke-width .3s var(--ease);
}
.eco-line.is-lit{
  stroke: rgba(var(--accent-2-rgb), .75);
  stroke-width: 1.6;
}

/* Motes travelling out along each link. Staggered so only two or three
   are ever in flight — the effect should register as depth, not traffic. */
.eco-mote{
  fill: var(--accent-2);
  opacity: 0;
  offset-rotate: 0deg;
}

/* --- central platform ------------------------------------------------ */
.eco-hub-bg{
  fill: color-mix(in srgb, var(--on-invert) 9%, var(--invert));
  stroke: rgba(var(--accent-2-rgb), .38);
  stroke-width: 1;
}
.eco-hub-ring{
  fill: none;
  stroke: rgba(var(--accent-2-rgb), .30);
  stroke-width: 1;
  transform-origin: 560px 330px;
}
.eco-hub-eyebrow{
  fill: var(--accent-2-soft);
  font-family: var(--mono); font-size: 10px;
  letter-spacing: .18em; text-anchor: middle;
}
.eco-hub-name{
  fill: var(--on-invert);
  font-family: var(--display); font-weight: 800;
  font-size: 26px; letter-spacing: -.02em; text-anchor: middle;
}
.eco-hub-sub{
  fill: rgba(var(--on-invert-rgb), .62);
  font-family: var(--body); font-size: 11.5px; text-anchor: middle;
}

/* --- channel cards --------------------------------------------------- */
.eco-card{ cursor: default; }
.eco-card-bg{
  /* Opaque mix rather than real transparency, so the connection lines do
     not show through the card and muddy the wordmark. */
  fill: color-mix(in srgb, var(--on-invert) 5%, var(--invert));
  stroke: rgba(var(--on-invert-rgb), .12);
  stroke-width: 1;
  transition: fill .22s var(--ease), stroke .22s var(--ease);
}
.eco-card-name{
  fill: var(--on-invert);
  font-family: var(--display); font-weight: 700;
  font-size: 14px; letter-spacing: -.01em; text-anchor: middle;
  transition: fill .22s var(--ease);
}
.eco-card-kind{
  /* Was 52% / 8.5px: measured 4.27:1 on the light panel (under AA) and
     rendered at 7.2px once the SVG scales down at 1024px. */
  fill: rgba(var(--on-invert-rgb), .62);
  font-family: var(--mono); font-size: 9.5px;
  letter-spacing: .09em; text-anchor: middle;
  text-transform: uppercase;
}
.eco-card{ transition: transform .22s var(--ease); transform-box: fill-box; transform-origin: center; }
.eco-card:hover, .eco-card:focus-visible{ transform: translateY(-4px); }
.eco-card:hover .eco-card-bg,
.eco-card:focus-visible .eco-card-bg{
  fill: color-mix(in srgb, var(--on-invert) 10%, var(--invert));
  stroke: rgba(var(--accent-2-rgb), .55);
}
.eco-card:focus{ outline: none; }
.eco-card:focus-visible .eco-card-bg{ stroke: var(--accent-2); stroke-width: 2; }

/* --- flow strip ------------------------------------------------------ */
.eco-flow{
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: var(--s4);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid rgba(var(--on-invert-rgb), .12);
}
.eco-flow li{
  display: flex; align-items: baseline; gap: var(--s3);
  font-family: var(--display); font-weight: 600; font-size: .95rem;
  color: rgba(var(--on-invert-rgb), .88);
}
.eco-flow-k{
  font-family: var(--mono); font-size: var(--t-micro);
  color: var(--accent-2); font-weight: 400;
}

@media (min-width: 1024px){
  .eco{ display: block; }
  .channels .chan-grid{ display: none; }   /* diagram replaces the grid */
}

/* Between 1024 and 1200 the SVG renders below 1:1, shrinking every glyph.
   Nudge the two smallest sizes up so nothing drops under ~9px on screen. */
@media (min-width: 1024px) and (max-width: 1199px){
  .eco-card-kind{ font-size: 11px; }
  .eco-card-name{ font-size: 15.5px; }
  .eco-hub-sub{ font-size: 13px; }
}

@media (max-width: 700px){
  .eco-flow{ grid-template-columns: repeat(2, 1fr); gap: var(--s3); }
  .eco-flow li{ font-size: .875rem; }
}

/* --- motion ----------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference){
  .eco-mote{
    animation: ecoTravel 7s linear infinite;
  }
  @keyframes ecoTravel{
    0%        { offset-distance: 0%;   opacity: 0; }
    12%       { opacity: .9; }
    82%       { opacity: .9; }
    100%      { offset-distance: 100%; opacity: 0; }
  }
  .eco-hub-ring{ animation: ecoPulse 4.5s var(--ease) infinite; }
  .eco-hub-ring2{ animation-delay: 2.25s; }
  @keyframes ecoPulse{
    0%   { transform: scale(.86); opacity: .55; }
    70%  { transform: scale(1.22); opacity: 0; }
    100% { transform: scale(1.22); opacity: 0; }
  }
}
@media (prefers-reduced-motion: reduce){
  .eco-mote{ display: none; }
  .eco-card{ transition: none; }
  .eco-card:hover, .eco-card:focus-visible{ transform: none; }
}

/* ---------------------------------------------------------------
   17. MARKETPLACE LOGOS

   Cards are generated by js/marketplaces.js. A card renders its wordmark
   first and swaps in a real logo once one loads from images/marketplaces/,
   so a missing file degrades to text rather than a broken image.
   --------------------------------------------------------------- */

/* --- backing plate ---------------------------------------------------
   Brand logos arrive in every possible colour. Dark artwork would vanish
   on a navy card, so the script measures each file's brightness and adds
   this plate only when one is needed. Colours are never altered — no
   filters, no monochrome conversion. */
.eco-card-plate{
  fill: #FFFFFF;
  fill-opacity: .94;
  stroke: rgba(var(--on-invert-rgb), .18);
  stroke-width: 1;
  transition: fill-opacity .22s var(--ease);
}
.eco-card:hover .eco-card-plate,
.eco-card:focus-visible .eco-card-plate{ fill-opacity: 1; }

.eco-card-logo{
  transition: transform .22s var(--ease), opacity .22s var(--ease);
  transform-box: fill-box;
  transform-origin: center;
  opacity: .94;
}
.eco-card:hover .eco-card-logo,
.eco-card:focus-visible .eco-card-logo{
  transform: scale(1.05);
  opacity: 1;
}

/* Once a logo is present the wordmark becomes the supporting label. */
.eco-card.has-logo .eco-card-name{ font-size: 12.5px; font-weight: 600; }
.eco-card.has-logo .eco-card-kind{ font-size: 8.5px; }

/* --- grid cards (tablet and mobile) --------------------------------- */
.chan-logo{
  flex: 0 0 auto;
  width: 46px; height: 46px;
  object-fit: contain;          /* never stretch, whatever the ratio */
  object-position: center;
  border-radius: 9px;
  padding: 5px;
  background: rgba(var(--on-invert-rgb), .06);
  border: 1px solid rgba(var(--on-invert-rgb), .14);
  transition: transform .22s var(--ease), border-color .22s var(--ease),
              background .22s var(--ease);
}
.chan-logo.on-plate{
  background: #FFFFFF;
  border-color: rgba(var(--on-invert-rgb), .2);
}
.chan:hover .chan-logo{
  transform: scale(1.05);
  border-color: rgba(var(--accent-2-rgb), .5);
}

/* --- no-JS fallback -------------------------------------------------- */
.chan-grid-fallback{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--s3);
  margin-top: var(--s7);
}
.chan-grid-fallback li{
  padding: var(--s4);
  border: 1px solid rgba(var(--on-invert-rgb), .12);
  border-radius: var(--r-lg);
  background: rgba(var(--on-invert-rgb), .035);
  font-family: var(--display); font-weight: 700;
  color: var(--on-invert);
}

@media (max-width: 700px){
  .chan-logo{ width: 40px; height: 40px; padding: 4px; }
}

@media (prefers-reduced-motion: reduce){
  .eco-card-logo, .chan-logo{ transition: none; }
  .eco-card:hover .eco-card-logo,
  .chan:hover .chan-logo{ transform: none; }
}
