@charset "UTF-8";
:root{
  --navy:#0b1020; --navy-2:#0f1630; --ink:#141a33;
  --orange:#f6a01a; --orange-2:#ff8a00; --gold:#ffc25c;
  --white:#ffffff; --paper:#f7f8fc; --muted:#6b7280; --line:#e6e8ef;
  --glass:rgba(255,255,255,.06); --shadow:0 20px 60px rgba(8,12,28,.18);
  /* Radii deliberately tight. 18/26px reads consumer-app; corporate sites
     sit nearer 10-16px, and the whole site inherits this one value. */
  --r:12px; --maxw:1440px;
  --grad-orange:linear-gradient(135deg,var(--orange),var(--orange-2));
}
*{box-sizing:border-box;margin:0;padding:0}
/* Base type size. The old clamp resolved to 15px on a 1440px laptop — the most
   common desktop width we get — which put body copy at 15px and the many .8-.9rem
   labels under 13px. Small text is the single loudest "cheap site" signal, and
   every serious industrial/corporate site sits at 17-18px.

   Raising this is safe here in a way it usually isn't: `rem` appears ONLY on
   font-size in this stylesheet — never on padding, margin, gap or width — so
   this grows the text and leaves every box exactly where it was. The two places
   that must not grow with it (the nav links and the nav CTA, both tuned to fit
   on one line down to 1101px) are pinned to px in the design-system layer. */
html{scroll-behavior:smooth;font-size:clamp(16px,0.25vw + 13.4px,18px)}
body{font-family:'Manrope',system-ui,sans-serif;color:#1a1f33;background:#fff;overflow-x:hidden;line-height:1.6}
h1,h2,h3,h4{font-family:'Sora',sans-serif;line-height:1.08;letter-spacing:-.02em}
img{max-width:100%;display:block}
[hidden]{display:none!important}
a{color:inherit;text-decoration:none}
.muted{color:var(--muted)}
/* 96px top and bottom put ~200px of white between every two sections, which
   read as the page having lost its content. Corporate layouts sit nearer
   64-72px a side; still airy, but the sections stay related to each other. */
.section{max-width:var(--maxw);margin:0 auto;padding:clamp(48px,5vw,72px) 24px}
.section.dark{max-width:100%;background:var(--navy);color:#fff;padding:clamp(56px,5.6vw,84px) 0}
.section.dark .prod-acc{max-width:var(--maxw);margin-left:auto;margin-right:auto;padding:0 24px}
.eyebrow{color:var(--orange);font-weight:800;letter-spacing:.22em;font-size:.78rem;text-transform:uppercase;margin-bottom:20px}
.eyebrow.center{text-align:center}
.section-title{font-size:clamp(1.9rem,3vw,3.2rem);font-weight:800;color:#0c1330;margin-bottom:42px}
.section-title.center{text-align:center}
.section-title.light{color:#fff}
.center{text-align:center}

.empty-note{max-width:440px;margin:10px auto 0;padding:42px 32px;text-align:center;
  border:1px dashed var(--line);border-radius:18px;background:var(--paper)}
.empty-note .empty-note-ic{display:inline-flex;align-items:center;justify-content:center;
  width:56px;height:56px;border-radius:50%;background:rgba(246,160,26,.12);font-size:1.6rem;margin-bottom:16px}
.empty-note p{margin:0;color:var(--muted);font-size:.95rem;line-height:1.6}
.empty-note a{color:var(--orange-ink);font-weight:700}

.btn{display:inline-flex;align-items:center;gap:8px;font-family:'Sora';font-weight:700;
  font-size:.95rem;padding:14px 26px;border-radius:50px;border:1px solid transparent;cursor:pointer;
  transition:.25s ease;position:relative;overflow:hidden}
.btn-primary{background:var(--grad-orange);color:#1a1200;box-shadow:0 12px 30px rgba(246,160,26,.35)}
.btn-primary:hover{transform:translateY(-3px) scale(1.05);box-shadow:0 22px 50px rgba(246,160,26,.6);animation:btnPulse .6s ease-out}
.btn-ghost{background:rgba(255,255,255,.08);color:#fff;border:1px solid rgba(255,255,255,.35);backdrop-filter:blur(8px)}
.btn-ghost:hover{background:rgba(255,255,255,.16)}
.btn-dark{background:var(--navy);color:#fff}.btn-dark:hover{background:#1a2348}
.btn-line{background:#fff;border:1px solid var(--line);color:#0c1330}.btn-line:hover{border-color:var(--orange);color:var(--orange)}
.btn-primary:active{transform:translateY(-1px) scale(0.98)}
.btn:active{opacity:.95}
.btn-lg{padding:18px 38px;font-size:1.05rem}.btn-sm{padding:9px 18px;font-size:.85rem}
.btn-block{width:100%;justify-content:center;margin-top:8px}

#loader{position:fixed;inset:0;z-index:9999;display:grid;place-items:center;overflow:hidden;
  background:radial-gradient(110% 120% at 78% 8%,#fff7e6 0%,#fbf7ef 46%,#f3ecdd 100%);
  transition:opacity .3s ease,visibility .3s}
#loader.done{opacity:0;visibility:hidden}

#loader.instant{display:none!important;animation:none!important;transition:none!important}
.intro-atmos{position:absolute;inset:0;pointer-events:none}
.intro-atmos::before{content:"";position:absolute;width:70vw;height:70vw;top:-22vw;right:-18vw;
  background:radial-gradient(circle,rgba(247,171,9,.30),rgba(247,171,9,0) 62%);filter:blur(8px)}
.intro-scene{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center}
.intro-stage{position:relative;aspect-ratio:940/532;width:min(74vw,560px)}
.intro-stage .il{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;opacity:0;user-select:none}
.il-sun{transform-origin:18.49% 58.7%}
.il-x{transform-origin:79.24% 68.7%}
.intro-tag{font-family:'Sora',sans-serif;font-weight:800;letter-spacing:-.02em;
  font-size:clamp(1.05rem,3.2vw,1.8rem);color:#16233f;margin-top:12px;opacity:0;text-align:center}
.intro-tag b{color:#f7ab09}
@keyframes ilTextIn{from{opacity:0;transform:translateY(18px) scale(.98)}to{opacity:1;transform:none}}
@keyframes ilArrowIn{from{opacity:0;transform:translate(-26%,40%) rotate(-12deg)}to{opacity:1;transform:none}}
@keyframes ilXIn{0%{opacity:0;transform:scale(.3) rotate(-18deg)}70%{opacity:1;transform:scale(1.14)}100%{opacity:1;transform:scale(1)}}
@keyframes ilSunIn{from{opacity:0;transform:scale(.2) rotate(-160deg)}to{opacity:1;transform:scale(1) rotate(0)}}
@keyframes ilTagIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes ilSpin{to{transform:rotate(360deg)}}
/* The intro is an opaque full-screen overlay, so NOTHING counts as painted
   until it fades — its total runtime is the page's FCP and LCP, one for one.
   The choreography is kept but compressed ~2.5x (was ~2.25s + .6s fade, which
   pinned LCP at ~2.75s and capped Lighthouse Performance at 76). */
#loader.go .il-text {animation:ilTextIn .3s .04s both}
#loader.go .il-arrow{animation:ilArrowIn .34s .16s cubic-bezier(.34,1.56,.64,1) both}
#loader.go .il-x    {animation:ilXIn .3s .32s cubic-bezier(.34,1.56,.64,1) both}
#loader.go .il-sun  {animation:ilSunIn .38s .42s cubic-bezier(.22,1,.36,1) both, ilSpin 18s .8s linear infinite}
#loader.go .intro-tag{animation:ilTagIn .26s .66s both}

@media (prefers-reduced-motion: reduce){
  #loader .il,#loader .intro-tag{opacity:1!important;animation:none!important}
  .il-sun{animation:none!important}
}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(246,160,26,.5)}70%{box-shadow:0 0 0 22px rgba(246,160,26,0)}100%{box-shadow:0 0 0 0 rgba(246,160,26,0)}}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes streak{0%{left:-30%}100%{left:100%}}
@keyframes load{0%{transform:translateX(-120%)}100%{transform:translateX(320%)}}
@keyframes fadeUp{to{opacity:1;transform:translateY(0)}}
@keyframes btnPulse{0%{box-shadow:0 22px 50px rgba(246,160,26,.6)}100%{box-shadow:0 22px 50px rgba(246,160,26,.3)}}
@keyframes arrowSlide{0%{transform:translateX(0)}50%{transform:translateX(4px)}100%{transform:translateX(0)}}

#scroll-progress{position:fixed;top:0;left:0;height:3px;width:0;background:var(--grad-orange);z-index:9998}

#navbar{position:fixed;top:0;left:0;right:0;z-index:1000;transition:.35s;background:#fff;border-bottom:1px solid #edeff4}
#navbar.scrolled{background:rgba(255,255,255,.94);backdrop-filter:blur(16px);box-shadow:0 6px 24px rgba(16,24,52,.10);border-bottom-color:transparent}
.nav-inner{max-width:1440px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;
  padding:14px 26px;gap:20px}
.brand{display:flex;align-items:center;gap:10px}
.nav-links{display:flex;gap:clamp(12px,1.55vw,28px);align-items:center;flex-wrap:nowrap}
.nav-links a{color:#0c1330;font-weight:600;font-size:clamp(.84rem,.95vw,.95rem);position:relative;padding:6px 0}
.nav-links a::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:0;background:var(--orange);transition:.3s}
.nav-links a:hover::after,.nav-links a.active::after{width:100%}
.nav-links a.active{color:var(--orange)}

/* Download is a conversion point, not another section link — give it a quiet
   outlined pill so it reads as an action without competing with the CTA. The
   underline sweep the other links use is suppressed inside the border. */
/* Solid, not outlined. An outlined pill sat at the same visual weight as the
   plain links beside it and got skipped; filled, it is the second thing the eye
   lands on after the orange CTA without shouting over it. */
.nav-links a.nav-link--download{
  position:relative;display:inline-flex;align-items:center;gap:8px;
  border:0;border-radius:999px;padding:8px 17px;overflow:hidden;
  background:var(--navy-2);color:#fff;font-weight:700;
  box-shadow:0 2px 6px rgba(8,12,28,.16);
  transition:background .25s var(--ease),box-shadow .25s var(--ease),transform .25s var(--ease)}
.nav-links a.nav-link--download::after{display:none}

/* The tray-and-arrow mark, drawn as a mask so it inherits the link colour and
   stays crisp at any zoom. */
.nav-links a.nav-link--download > svg,
.nav-links a.nav-link--download::before{
  content:"";width:13px;height:13px;flex:none;background:currentColor;
  -webkit-mask:var(--dl-ic) center/contain no-repeat;
          mask:var(--dl-ic) center/contain no-repeat}
.nav-links a.nav-link--download{
  --dl-ic:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 3v10m0 0 4-4m-4 4-4-4' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/><path d='M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'/></svg>")}

/* Warm wash sweeps in from the left behind the label rather than the whole
   background snapping colour. */
.nav-links a.nav-link--download > span,
.nav-links a.nav-link--download{z-index:0}
.nav-links a.nav-link--download > i.dl-fill{
  position:absolute;inset:0;z-index:-1;background:var(--grad-orange);
  transform:scaleX(0);transform-origin:left;transition:transform .38s var(--ease)}
.nav-links a.nav-link--download:hover > i.dl-fill,
.nav-links a.nav-link--download.active > i.dl-fill{transform:scaleX(1)}

.nav-links a.nav-link--download:hover,
.nav-links a.nav-link--download:focus-visible,
.nav-links a.nav-link--download.active{
  /* The wash does the colour change by sweeping across, so the base stays put —
     a background swap underneath it would fight the sweep for the same pixels. */
  color:#1a1200;box-shadow:0 6px 16px rgba(246,160,26,.34);transform:translateY(-1px)}

/* Arrow drops out of the tray and returns from above — the download gesture. */
@keyframes dl-drop{
  0%  {transform:translateY(0);opacity:1}
  40% {transform:translateY(6px);opacity:0}
  41% {transform:translateY(-7px);opacity:0}
  100%{transform:translateY(0);opacity:1}
}
.nav-links a.nav-link--download:hover::before,
.nav-links a.nav-link--download:focus-visible::before{
  animation:dl-drop .62s var(--ease)}

/* Idle attention cue. The movement occupies the first eighth of a 5s cycle and
   the arrow is still for the rest — enough to catch peripheral vision, not
   enough to nag while someone is reading the page. */
@keyframes dl-idle{
  0%,88%,100%{transform:translateY(0)}
  92%{transform:translateY(2.5px)}
  96%{transform:translateY(0)}
}
.nav-links a.nav-link--download::before{animation:dl-idle 5s var(--ease) infinite}
.nav-links a.nav-link--download:hover::before{animation:dl-drop .62s var(--ease)}

@media(prefers-reduced-motion:reduce){
  .nav-links a.nav-link--download::before,
  .nav-links a.nav-link--download:hover::before{animation:none}
  .nav-links a.nav-link--download > i.dl-fill{transition:none}
}
@media(max-width:1100px){
  /* In the drawer it is a plain row again, like every other link. */
  .nav-links a.nav-link--download{border:0;border-radius:0;padding:14px 0;background:none;overflow:visible}
  .nav-links a.nav-link--download::before{display:none}
  .nav-links a.nav-link--download > i.dl-fill{display:none}
}
.nav-right{display:flex;align-items:center;gap:clamp(8px,.9vw,16px);flex:0 0 auto}

.nav-cta{font-size:clamp(.8rem,.9vw,.9rem);padding:11px 12px 11px clamp(14px,1.4vw,22px);letter-spacing:.015em;gap:10px;white-space:nowrap;
  box-shadow:0 10px 24px rgba(246,160,26,.32),inset 0 1px 0 rgba(255,255,255,.42),inset 0 -1px 0 rgba(160,90,0,.18)}
.nav-cta span{position:relative;z-index:1}
.nav-cta .cta-arr{position:relative;display:inline-grid;place-items:center;
  width:22px;height:22px;border-radius:50%;
  background:rgba(255,255,255,.22);
  transition:transform .28s cubic-bezier(.34,1.56,.64,1),background .25s ease}
.nav-cta .cta-arr::after{content:"";width:7px;height:7px;
  border-top:2px solid #1a1200;border-right:2px solid #1a1200;
  transform:translateX(-1px) rotate(45deg)}
.nav-cta:hover .cta-arr{background:rgba(255,255,255,.4);transform:translateX(3px)}
.lang-switch{position:relative}
.lang-btn{background:transparent;border:0;color:#0c1330;font-weight:700;display:flex;gap:6px;align-items:center;cursor:pointer;font-family:'Sora'}
.lang-menu{position:absolute;top:100%;right:0;margin-top:10px;background:#fff;border-radius:12px;box-shadow:var(--shadow);
  padding:8px;min-width:150px;z-index:1001;opacity:0;visibility:hidden;transform:translateY(6px);
  transition:opacity .18s ease,transform .18s ease,visibility .18s}
.lang-menu::before{content:"";position:absolute;top:-12px;left:0;right:0;height:12px}
.lang-switch:hover .lang-menu,.lang-switch:focus-within .lang-menu{opacity:1;visibility:visible;transform:none}
.lang-menu a{display:flex;align-items:center;gap:9px;padding:9px 14px;border-radius:8px;color:#1a1f33;font-weight:600}
.lang-menu a:hover,.lang-menu a.on{background:var(--paper);color:var(--orange)}
.lang-flag{display:inline-flex;align-items:center;line-height:1}
.lang-flag-img{width:24px;height:16px;object-fit:cover;border-radius:3px;display:block;
  box-shadow:0 0 0 1px rgba(0,0,0,.1);background:#eee}
.lang-code{font-size:.85rem;letter-spacing:.03em}
/* 44x44 minimum tap target (WCAG 2.5.8); the bars stay 26px wide.
   Negative margin keeps the enlarged hit area from shifting the layout. */
.hamburger{display:none;flex-direction:column;align-items:center;justify-content:center;
  gap:5px;width:44px;height:44px;margin-right:-9px;background:none;border:0;cursor:pointer}
.hamburger span{width:26px;height:2px;background:#0c1330;border-radius:2px;transition:.3s}

.flash{max-width:var(--maxw);margin:90px auto 0;background:#e8fbef;border:1px solid #b7ebc6;color:#137a3a;
  padding:14px 20px;border-radius:12px;font-weight:600;text-align:center}

.hero{position:relative;min-height:100vh;display:flex;align-items:center;color:#fff;overflow:hidden}
.hero-bg{position:absolute;inset:0;z-index:0}
.hero-bg video,.hero-photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.hero-photo{z-index:-1}
.hero-overlay{position:absolute;inset:0;background:
  linear-gradient(105deg,rgba(8,10,20,.92) 18%,rgba(20,12,4,.55) 55%,rgba(246,160,26,.18) 100%)}
.hero-particles{position:absolute;inset:0}
.hero-particles span{position:absolute;width:3px;height:3px;border-radius:50%;background:rgba(255,200,120,.8);
  animation:float 7s linear infinite}
@keyframes float{0%{transform:translateY(0);opacity:0}10%{opacity:1}100%{transform:translateY(-120px);opacity:0}}
.hero-content{position:relative;z-index:2;max-width:var(--maxw);margin:0 auto;padding:0 26px;width:100%}
.badge{display:inline-block;border:1px solid rgba(246,160,26,.5);color:var(--gold);border-radius:50px;
  padding:8px 18px;font-size:.78rem;font-weight:800;letter-spacing:.18em;text-transform:uppercase;background:rgba(246,160,26,.08)}
.hero h1{font-size:clamp(2.6rem,6vw,7rem);font-weight:800;margin:22px 0 18px}
.hero h1 .line{display:block}
.hero h1 .accent{background:var(--grad-orange);-webkit-background-clip:text;background-clip:text;color:transparent}
.hero-sub{max-width:560px;font-size:1.15rem;color:rgba(255,255,255,.82);margin-bottom:34px}
.hero-btns{display:flex;gap:16px;flex-wrap:wrap}

.ach-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.ach-card{display:flex;align-items:center;gap:18px;padding:26px 28px;border-radius:var(--r);
  border:1px solid var(--line);background:linear-gradient(120deg,#fff,#fff7ec);box-shadow:0 8px 24px rgba(20,26,51,.05)}
.ach-card strong{display:block;font-family:'Sora';font-size:1.9rem;color:#0c1330}
.ach-card span{font-size:.78rem;letter-spacing:.12em;color:var(--muted);font-weight:700}
.ach-icon{width:48px;height:48px;border-radius:13px;background:linear-gradient(160deg,#1a2348,#0c1330);
  display:grid;place-items:center;flex:0 0 auto;position:relative}
.ach-icon::after{content:"";width:20px;height:20px;background:var(--orange);
  -webkit-mask:center/contain no-repeat;mask:center/contain no-repeat}
.ic-grid::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Crect x='3' y='3' width='7' height='7' rx='1'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1'/%3E%3C/svg%3E")}
.ic-bolt::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M13 2 4 14h6l-1 8 9-12h-6z'/%3E%3C/svg%3E")}
.ic-users::after,.ic-team::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Ccircle cx='9' cy='8' r='4'/%3E%3Cpath d='M1 21c0-4 4-6 8-6s8 2 8 6'/%3E%3C/svg%3E")}
.ic-factory::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M3 21V9l6 4V9l6 4V9l6 4v8z'/%3E%3C/svg%3E")}
.ic-chip::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Crect x='6' y='6' width='12' height='12' rx='2'/%3E%3C/svg%3E")}

/* ── Product showcase — cinematic expanding accordion ──────────────────
   Panels auto-cycle; the active one widens and its photo slowly pushes in
   (Ken Burns), so the section reads as a living reel rather than a grid.
   Hover takes over from the timer. Collapses to a stacked list on mobile. */
.prod-acc{display:flex;gap:14px;height:min(560px,72vh);margin-top:38px}
.pa-panel{position:relative;flex:1 1 0;min-width:0;border-radius:20px;overflow:hidden;cursor:pointer;
  text-decoration:none;color:inherit;background:#070b18;
  transition:flex-grow .8s cubic-bezier(.34,.01,.2,1),box-shadow .5s ease}
.pa-panel.on{flex-grow:4.6;box-shadow:0 34px 70px -26px rgba(0,0,0,.75)}
/* Gradient hairline that only lights up on the open panel. */
.pa-panel::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1.5px;z-index:5;pointer-events:none;
  background:linear-gradient(140deg,rgba(246,160,26,.75),rgba(255,255,255,.06) 45%,rgba(246,160,26,.5));
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;
  opacity:0;transition:opacity .6s ease}
.pa-panel.on::after{opacity:1}

.pa-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;
  transform:scale(1.06);transition:transform .8s ease,filter .6s ease;filter:saturate(.95) brightness(.8)}
.pa-panel:hover .pa-img{filter:saturate(1.05) brightness(.92)}
.pa-panel.on .pa-img,.pa-panel.on:hover .pa-img{filter:saturate(1.08) brightness(1);animation:paKen 7s ease-out forwards}
@keyframes paKen{from{transform:scale(1.02)}to{transform:scale(1.13)}}
/* Collapsed panels keep a scrim so the vertical label stays readable; the open
   one only darkens near the bottom, under the caption. */
.pa-panel::before{content:"";position:absolute;inset:0;z-index:1;transition:background .6s ease;
  background:linear-gradient(180deg,rgba(6,10,26,.24) 0%,rgba(5,8,20,.78) 100%)}
.pa-panel.on::before{background:linear-gradient(180deg,rgba(6,10,26,.05) 0%,rgba(6,10,26,.1) 42%,rgba(5,8,20,.9) 100%)}

.pa-num{position:absolute;top:18px;left:0;right:0;z-index:4;text-align:center;font-family:'Sora';font-weight:800;
  font-size:.82rem;color:rgba(255,255,255,.55);transition:color .5s ease}
.pa-panel.on .pa-num{color:var(--orange);text-align:left;padding-left:30px}
.pa-tag{position:absolute;top:44px;left:30px;z-index:4;background:var(--orange);color:#1a1200;font-weight:800;
  font-size:.72rem;letter-spacing:.1em;padding:5px 11px;border-radius:999px;
  opacity:0;transform:translateY(-6px);transition:opacity .4s .2s ease,transform .4s .2s ease}
.pa-panel.on .pa-tag{opacity:1;transform:none}

/* Vertical name, shown only while the panel is collapsed. */
.pa-vert{position:absolute;left:0;right:0;bottom:26px;z-index:4;display:flex;justify-content:center;
  opacity:1;transition:opacity .35s ease}
.pa-panel.on .pa-vert{opacity:0;pointer-events:none}
.pa-vert span{writing-mode:vertical-rl;transform:rotate(180deg);font-family:'Sora';font-weight:800;font-size:1rem;
  letter-spacing:.06em;color:#fff;white-space:nowrap;text-shadow:0 2px 12px rgba(0,0,0,.6)}

/* Caption, revealed only on the open panel. nowrap stops the text reflowing
   mid-transition while the panel is still widening. */
.pa-info{position:absolute;left:30px;right:30px;bottom:28px;z-index:4;white-space:nowrap;
  opacity:0;transform:translateY(16px);transition:opacity .5s .18s ease,transform .5s .18s ease}
.pa-panel.on .pa-info{opacity:1;transform:none}
.pa-info h3{font-family:'Sora';font-size:1.5rem;color:#fff;margin:0 0 5px;letter-spacing:-.01em}
.pa-sub{display:block;font-size:.78rem;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.6);margin-bottom:13px}
.pa-chips{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:15px}
.pa-chips span{background:rgba(255,255,255,.1);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.18);
  color:rgba(255,255,255,.85);font-size:.72rem;font-weight:600;padding:5px 12px;border-radius:999px}
.pa-cta{display:inline-flex;align-items:center;gap:7px;color:var(--orange);font-weight:700;font-size:.88rem}
.pa-cta i{font-style:normal;transition:transform .3s ease}
.pa-panel.on:hover .pa-cta i{transform:translateX(6px)}

.pa-prog{position:absolute;left:0;bottom:0;height:3px;width:0;z-index:6;
  background:linear-gradient(90deg,var(--orange),var(--gold,#ffc25c))}
.pa-panel.on .pa-prog{animation:paProg 5s linear}
.prod-acc:hover .pa-panel.on .pa-prog{animation-play-state:paused}
@keyframes paProg{from{width:0}to{width:100%}}

@media(max-width:900px){
  /* Sideways panels can't shrink far enough to stay legible — stack them. */
  .prod-acc{flex-direction:column;height:auto;gap:16px}
  .pa-panel,.pa-panel.on{flex:none;height:230px}
  .pa-panel::after{opacity:1}
  .pa-panel::before,.pa-panel.on::before{background:linear-gradient(180deg,rgba(6,10,26,.1) 0%,rgba(5,8,20,.92) 100%)}
  .pa-img{filter:saturate(1.05) brightness(.95);animation:none;transform:none}
  .pa-panel.on .pa-img{animation:none;transform:none}
  .pa-vert{display:none}
  .pa-num{text-align:left;padding-left:24px;color:var(--orange)}
  .pa-panel.on .pa-num{padding-left:24px}
  .pa-tag{opacity:1;transform:none;top:40px;left:24px}
  .pa-info{opacity:1;transform:none;white-space:normal;left:24px;right:24px;bottom:22px}
  .pa-info h3{font-size:1.25rem}
  .pa-chips{display:none}
  .pa-prog,.pa-panel.on .pa-prog{display:none}
}

.war-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:18px}

.marquee{overflow:hidden;-webkit-mask:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.marquee-track{display:flex;gap:70px;align-items:center;width:max-content;animation:scroll 70s linear infinite;
  will-change:transform;backface-visibility:hidden;transform:translateZ(0)}
.marquee:hover .marquee-track{animation-play-state:paused}
.client-chip{white-space:nowrap;padding:16px 30px;border:1px solid var(--line);border-radius:50px;
  font-family:'Sora';font-weight:700;color:#0c1330;font-size:.9rem;box-shadow:0 6px 18px rgba(20,26,51,.05)}

@keyframes scroll{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}

.about-split{display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:center}
.about-img img{border-radius:var(--r);box-shadow:var(--shadow)}
.about-txt .section-title{font-size:clamp(1.7rem,2.5vw,2.6rem);margin-bottom:18px}
.about-txt .rich-text{margin-bottom:26px}
.about-txt > .btn{margin-top:6px}

.cta-band{background:var(--navy);color:#fff;text-align:center;padding:90px 24px;position:relative;overflow:hidden}
.cta-band::before{content:"";position:absolute;top:-40%;left:50%;width:600px;height:600px;transform:translateX(-50%);
  background:radial-gradient(circle,rgba(246,160,26,.25),transparent 60%)}
.cta-band h2{font-size:clamp(1.9rem,3vw,3.4rem);position:relative}
.cta-band p{max-width:620px;margin:16px auto 30px;color:rgba(255,255,255,.78);position:relative}

#site-footer{background:var(--navy);color:rgba(255,255,255,.8);padding:70px 24px 30px}
.footer-grid{max-width:var(--maxw);margin:0 auto;display:grid;grid-template-columns:1.4fr 1fr 1.2fr;gap:40px}
#site-footer h3{color:var(--orange);font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;margin-bottom:16px}
#site-footer a{display:block;color:rgba(255,255,255,.75);padding:5px 0;transition:.2s}
#site-footer a:hover{color:var(--orange)}
.footer-brand{margin-bottom:14px}
#site-footer .btn{margin:16px 0}
.socials{display:flex;gap:10px}
.socials a{width:34px;height:34px;border-radius:50%;background:rgba(255,255,255,.08);display:grid;place-items:center;color:#fff;font-size:.8rem}
.socials a:hover{background:var(--orange);color:#1a1200}
.footer-bottom{max-width:var(--maxw);margin:40px auto 0;padding-top:20px;border-top:1px solid rgba(255,255,255,.08);
  text-align:center;font-size:.82rem;color:rgba(255,255,255,.5)}

.footer-contact .foot-office{margin-bottom:13px}
.footer-contact .fo-name{display:block;color:#fff;font-weight:700;font-size:.9rem;margin-bottom:2px}
.footer-contact a{font-size:.82rem;padding:2px 0;word-break:break-word}

#cookie-banner{position:fixed;bottom:18px;left:18px;right:18px;max-width:680px;margin:0 auto;z-index:900;
  background:rgba(12,19,48,.96);backdrop-filter:blur(10px);color:#fff;padding:16px 20px;border-radius:14px;
  display:flex;gap:16px;align-items:center;justify-content:space-between;box-shadow:var(--shadow);
  transform:translateY(160%);transition:.5s}
#cookie-banner.show{transform:translateY(0)}
#cookie-banner a{color:var(--orange)}

.page-hero{min-height:42vh;background-size:cover;background-position:center;display:flex;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;color:#fff;position:relative;padding:120px 24px 60px}
.page-hero.short{min-height:42vh}
.page-hero::before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(8,12,28,.85),rgba(8,12,28,.6))}
.page-hero h1{font-size:clamp(2.2rem,3.7vw,4rem);position:relative}
.page-hero p{position:relative;color:rgba(255,255,255,.8);margin-top:10px}
.row-btns{display:flex;gap:14px;margin-top:24px;flex-wrap:wrap}
.detail-top{display:grid;grid-template-columns:1fr 1fr;gap:46px;align-items:start;position:relative;padding-bottom:48px}
.detail-left{display:flex;flex-direction:column;gap:14px}
/* Product photos used to be forced into a fixed 4:3 box — first cropped to fill
   it, then fitted inside it with a blurred copy padding the gaps. Both showed
   the customer something other than the photo. The box now takes the photo's
   own shape, so the picture is complete and fills its frame with nothing added
   around it. The slider only swaps the img's src, so it re-sizes with each
   slide rather than depending on a fixed height. */
.detail-video{position:relative;border-radius:var(--r);overflow:hidden;background:#0b1124}
.detail-video img,.detail-video video{position:relative;width:100%;height:auto;display:block}

/* This is a tabindex="0" slider — it must keep a visible focus ring.
   (`outline:none` here previously made it unreachable for keyboard users.) */
.detail-video.is-slider:focus{outline:none}
.detail-video.is-slider #pmain{transition:opacity .25s ease}
.detail-video.is-slider #pmain.swapping{opacity:.25}

@media(min-width:981px){
  .detail-left{position:sticky;top:88px}
}

.psl-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:3;width:44px;height:44px;
  border:0;border-radius:50%;background:rgba(8,12,28,.55);color:#fff;font-size:1.9rem;line-height:1;
  display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .18s,transform .18s;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.psl-arrow:hover{background:var(--orange)}
.psl-prev{left:12px}.psl-prev:hover{transform:translateY(-50%) translateX(-2px)}
.psl-next{right:12px}.psl-next:hover{transform:translateY(-50%) translateX(2px)}
.psl-counter{position:absolute;top:12px;right:12px;z-index:3;background:rgba(8,12,28,.6);color:#fff;
  font-size:.78rem;font-weight:600;padding:4px 11px;border-radius:20px;letter-spacing:.04em}
.psl-counter b{font-weight:800;color:#fff}
.vid-note{position:absolute;bottom:14px;left:14px;background:rgba(0,0,0,.6);color:#fff;font-size:.78rem;padding:5px 10px;border-radius:6px}

.detail-video.has-video{cursor:pointer}
.vid-play{position:absolute;inset:0;margin:auto;width:74px;height:74px;border:0;border-radius:50%;background:rgba(246,160,26,.94);color:#fff;font-size:1.55rem;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 10px 30px rgba(0,0,0,.4);transition:transform .18s,background .18s}
.vid-play .vid-play-ic{margin-left:5px;line-height:1}
.detail-video.has-video:hover .vid-play{transform:scale(1.09);background:#f6a01a}
.btn .btn-play{font-size:.82em}
.vid-modal{position:fixed;inset:0;z-index:1200;display:none;align-items:center;justify-content:center;background:rgba(6,9,20,.88);padding:24px}
.vid-modal.on{display:flex}
.vid-modal-inner{width:min(980px,100%);aspect-ratio:16/9;background:#000;border-radius:14px;overflow:hidden;box-shadow:0 30px 90px rgba(0,0,0,.55)}
.vid-modal-inner video{width:100%;height:100%;display:block;object-fit:contain;background:#000}
.vid-modal-close{position:absolute;top:18px;right:22px;width:46px;height:46px;border:0;border-radius:50%;background:rgba(255,255,255,.16);color:#fff;font-size:1.9rem;line-height:1;cursor:pointer;transition:background .18s}
.vid-modal-close:hover{background:rgba(255,255,255,.3)}
.detail-body h2{font-size:2rem;color:#0c1330}.detail-body h3{margin:24px 0 12px;color:#0c1330}
.spec{list-style:none}
.spec li{display:flex;gap:20px;justify-content:space-between;align-items:baseline;
  padding:10px 2px;border-bottom:1px dashed var(--line);font-size:.9rem;line-height:1.45}
.spec li b{flex:0 0 44%;color:#0c1330;font-weight:600}
.spec li>span{flex:1 1 auto;text-align:right;color:#41496a}

.rich-text .ds-title{margin:22px 0 8px;font-size:1.06rem;font-weight:700;color:#0c1330}
.rich-text .ds-list{list-style:none;padding:0;margin:0}
.rich-text .ds-list li{padding:9px 2px;border-bottom:1px dashed var(--line);font-size:.9rem;line-height:1.5;color:#41496a}
.rich-text .ds-list li strong{color:#0c1330;font-weight:600;margin-right:4px}

.hero-badge{display:inline-block;vertical-align:middle;font-size:.85rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;background:var(--orange);color:#1a1200;padding:6px 14px;border-radius:999px;margin-left:14px}
.badge-upcoming{display:inline-block;vertical-align:middle;font-size:.72rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;background:var(--orange);color:#1a1200;padding:4px 10px;border-radius:999px;margin-left:10px;transform:translateY(-2px)}

.detail-body{position:relative;z-index:1}

.tabs{margin-top:26px}
.tab-heads{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.th{padding:9px 14px;border:1px solid var(--line);background:#fff;border-radius:8px;cursor:pointer;font-size:.82rem;font-weight:600}
.th.on{background:var(--orange);border-color:var(--orange);color:#1a1200}
.tp{display:none}.tp.on{display:block}
.tab-ic{width:56px;height:56px;margin:0 0 14px;color:var(--orange)}
.tab-ic svg{width:100%;height:100%;display:block}

/* Draws the eye to the brochure download without being distracting — a slow
   breathing ring, paused on hover/focus and for anyone who prefers reduced motion. */
.btn-brochure{animation:pulse 2.8s ease-in-out infinite}
.btn-brochure:hover,.btn-brochure:focus-visible{animation-play-state:paused}
@media(prefers-reduced-motion:reduce){ .btn-brochure{animation:none} }

/* Body-copy paragraphs read better with a straight right edge, especially in
   the two-column product/about layouts — bullet lists keep their own alignment.
   Card copy is deliberately NOT justified: a card column is only a few words
   wide, and justifying that opens rivers of whitespace between words. */
/* Was text-align:justify. CSS justification has no hyphenation dictionary to
   fall back on here, so it pads the word gaps instead — and these paragraphs are
   long, technical and full of unbreakable terms like "1P-HSAT", which opened
   visible rivers of white space down the column. Ragged-right reads better and
   is what the rest of the site already uses. */
.rich-text p{text-align:start}
.icon-card p{text-align:left}
/* Frames take the picture's shape. A fixed height plus object-fit:contain
   is the combination that leaves grey margins beside every photo — the
   frame is one shape, the photo another, and the difference has to go
   somewhere. Letting the height follow the image removes the gap at
   source; the grids align to the start so uneven tiles read as a
   deliberate row rather than a broken one. */
.mini-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;align-items:start}
.mini-card{border:1px solid var(--line);border-radius:16px;overflow:hidden;transition:.3s}
.mini-card figcaption{text-align:center;font-weight:700;padding:10px 12px;color:#0c1330;font-size:.9rem;line-height:1.4}
.mini-card img{height:auto;width:100%;display:block;background:#f4f6fa}
.mini-card span{display:block;padding:18px 16px;font-family:'Sora';font-weight:700;font-size:1.05rem;color:#0c1330}
.mini-card:hover{transform:translateY(-4px);box-shadow:var(--shadow);border-color:rgba(12,19,48,.16)}

/* Shared "image + title + optional text + bullet points" card grid — used by
   Our Strengths (in-house capabilities) and Quality Approval (process cards).
   .str-card reuses the .mini-card shell; this just adds the body/caption. */
.str-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
/* No fixed height. There is no object-fit here, so the browser default `fill`
   applied: a 475x300 source forced into 449x170 was stretched 1.67x sideways,
   which is why the machinery and the people in these cards looked flattened.
   The card bottoms are kept level by the flex column below, not by cropping
   the photograph. */
.str-card img{width:100%;height:auto}
.str-card-body{padding:22px 20px}
.str-card-body h3,.str-card-body h4{color:#0c1330;font-size:1.05rem;margin:0 0 8px}
.str-card-body p{font-size:.88rem;color:var(--muted);margin:0 0 10px}
@media(max-width:980px){ .str-grid{grid-template-columns:repeat(2,1fr)} }
@media(max-width:600px){ .str-grid{grid-template-columns:1fr} }
.map-link{color:var(--orange);font-weight:700;font-size:.9rem}

/* align-items:start — each card ends under its own content. Stretching them
   to the tallest card left a block of empty white under the shorter ones
   once the image frame started following each poster's shape. */
.expo-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;align-items:stretch}
.expo-card{display:block;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:#fff;transition:.35s;color:inherit;text-decoration:none}

.exhibition-hero{min-height:42vh}
.exh-crumb{position:relative;margin-top:14px;font-size:.8rem;letter-spacing:.04em;text-transform:uppercase;color:rgba(255,255,255,.7);font-weight:700}
.exh-crumb a{color:rgba(255,255,255,.9);text-decoration:none}
.exh-crumb a:hover{color:var(--gold)}
.exh-crumb span{margin:0 6px;color:rgba(255,255,255,.45)}
.exh-layout{display:grid;grid-template-columns:1fr 340px;gap:34px;align-items:start;max-width:var(--maxw);margin:0 auto}
.exh-main{min-width:0;border:1px solid var(--line);border-radius:18px;overflow:hidden;background:#fff;box-shadow:var(--shadow)}
.exh-poster{background:#0b1124;text-align:center;padding:16px}
.exh-poster img{display:inline-block;width:auto;max-width:100%;max-height:460px;vertical-align:middle;border-radius:8px}
.exh-detail{padding:26px 30px 32px}
.exh-when{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;font-size:.86rem;color:var(--muted);font-weight:600;margin-bottom:14px}
.exh-tag{display:inline-block;font-size:.72rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:4px 11px;border-radius:50px}
.exh-tag.up{background:rgba(246,160,26,.15);color:#b4730a}
.exh-tag.past{background:#eef1f5;color:#6b7280}
.exh-title{font-family:'Sora';font-size:clamp(1.5rem,3.4vw,2.1rem);color:#0c1330;line-height:1.2;margin-bottom:14px}
.exh-body{color:#374151;line-height:1.8;font-size:1rem;white-space:pre-line}
.exh-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:22px;align-items:start}
.exh-gallery img{width:100%;height:auto;display:block;background:#f4f6fa;border-radius:var(--r-sm,8px);border:1px solid var(--line)}
.exh-gallery.docs img{height:auto}
/* The heights here used to force 1200x800 exhibition photos into 138x200
   portrait boxes and 848x1200 certificate scans into 169x200 — with no
   object-fit, so both were simply squashed. The grid still goes two-up on a
   phone; each photo just keeps its own shape. */
@media(max-width:600px){ .exh-gallery{grid-template-columns:repeat(2,1fr)} }
/* Facility/lab photo gallery: the caption is a real HTML <figcaption> below the
   photo (consistent font/position every time), so a mild top-anchored crop hides
   any leftover baked-in text along the bottom edge of an older source photo
   instead of showing it half-cut-off at an inconsistent size. */
.exh-gallery.facility{align-items:start}
.exh-gallery.facility figure{margin:0}
.exh-gallery.facility img{width:100%;height:auto;display:block;border-radius:var(--r-sm,8px);border:1px solid var(--line);background:#f4f6fa}
.exh-gallery.facility figcaption{text-align:center;margin-top:10px;font-weight:700;font-size:.86rem;color:#0c1330;line-height:1.4}
.exh-zoom{cursor:pointer}

.exh-lightbox{position:fixed;inset:0;z-index:3000;display:none;align-items:center;justify-content:center;background:rgba(8,12,28,.82);padding:24px;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.exh-lightbox.on{display:flex;animation:exhLbFade .2s ease}
@keyframes exhLbFade{from{opacity:0}to{opacity:1}}
.exh-lb-box{position:relative;background:transparent;padding:0;border-radius:14px;box-shadow:0 30px 80px rgba(0,0,0,.55);max-width:min(900px,92vw);max-height:90vh;animation:exhLbPop .22s cubic-bezier(.2,.8,.3,1.1)}
@keyframes exhLbPop{from{transform:scale(.85);opacity:0}to{transform:scale(1);opacity:1}}
.exh-lb-box .exh-lb-img{display:block;width:auto;height:auto;max-width:100%;max-height:90vh;border-radius:14px}
.exh-lb-close{position:absolute;top:-16px;right:-16px;width:42px;height:42px;border:none;border-radius:50%;background:var(--orange,#f6a01a);color:#1a1200;font-size:1.5rem;line-height:1;cursor:pointer;box-shadow:0 6px 18px rgba(0,0,0,.35);transition:transform .15s;z-index:3}
.exh-lb-close:hover{transform:scale(1.12)}

.exh-lb-nav{position:absolute;top:50%;transform:translateY(-50%);width:50px;height:50px;border:none;border-radius:50%;
  background:rgba(255,255,255,.14);color:#fff;font-size:2rem;line-height:1;cursor:pointer;display:grid;place-items:center;
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);transition:.18s;z-index:3}
.exh-lb-prev{left:20px}.exh-lb-next{right:20px}
.exh-lb-nav:hover{background:var(--orange,#f6a01a);color:#1a1200;transform:translateY(-50%) scale(1.1)}
@media(max-width:600px){ .exh-lb-close{top:-12px;right:-12px;width:38px;height:38px} .exh-lb-nav{width:42px;height:42px;font-size:1.6rem} .exh-lb-prev{left:8px}.exh-lb-next{right:8px} }

.exh-side{position:sticky;top:96px;border:1px solid var(--line);border-radius:18px;background:#fff;box-shadow:var(--shadow);overflow:hidden}
.exh-side-title{font-family:'Sora';text-align:center;color:var(--orange);font-size:1.15rem;padding:18px 18px 6px;border-bottom:2px solid rgba(246,160,26,.18)}
.exh-list{list-style:none;margin:0;padding:8px;max-height:72vh;overflow:auto}
.exh-list li{margin:0}
.exh-list a{display:flex;align-items:flex-start;gap:9px;padding:11px 12px;border-radius:10px;text-decoration:none;
  color:#334155;font-size:.86rem;font-weight:600;line-height:1.4;transition:.18s}
.exh-list a:hover{background:#f7f8fb;color:#0c1330}
.exh-list a .exh-arrow{color:var(--orange);font-weight:800;flex:0 0 auto;margin-top:1px}
.exh-list a.on{background:linear-gradient(135deg,rgba(246,160,26,.16),rgba(246,160,26,.06));color:#0c1330;
  box-shadow:inset 0 0 0 1px rgba(246,160,26,.45)}
@media(max-width:880px){
  .exh-layout{grid-template-columns:1fr}
  .exh-side{position:static;order:2}
  .exh-list{max-height:none}
}
.expo-card:hover{transform:translateY(-5px);box-shadow:var(--shadow)}
/* One frame for every card. Sizing each to its own artwork (asset_ratio) made
   a row of three end at three different heights the moment two posters had
   different proportions, and the grid read as broken.
   4/5 because that is the shape the event posters are actually made in. The
   artwork is contained rather than cropped — these are posters carrying dates
   and booth numbers, so cutting their edges would cut real information — and a
   blurred copy fills whatever is left, so there are no empty bars either. */
.expo-img{position:relative;overflow:hidden;background:#0c1330;aspect-ratio:4/5}
/* ── Deferred card artwork ─────────────────────────────────────────── */
/* These photographs are painted from a --bimg custom property set in a style
   attribute. A custom property is not fetched until something actually uses it,
   so gating the background on .bg-on — added by the observer in main.js once the
   card is within 600px of the viewport — turns an eager download into a lazy one.
   There is no loading="lazy" for a CSS background, and /exhibitions was pulling
   all 27 event photos (~1.9MB) before the visitor had scrolled a pixel.
   .modal-banner is deliberately left ungated: it sits inside a display:none
   dialog, which browsers already skip. */
/* Both layers stay gated on .bg-on so the lazy-loading above still holds. */
.expo-img.bg-on::before{content:"";position:absolute;inset:0;background:var(--bimg) center/cover no-repeat;
  filter:blur(22px) brightness(.55);transform:scale(1.15)}
.expo-img.bg-on::after{content:"";position:absolute;inset:0;background:var(--bimg) center/contain no-repeat}
/* The card is a flex column and the body grows into whatever height the row
   settles on, so a one-line title no longer leaves its card 24px shorter than
   its neighbours. margin-top:auto pins "View details" to the bottom edge of
   every card instead of floating it under the last line of text. */
.expo-card{display:flex;flex-direction:column}
.expo-body{display:flex;flex-direction:column;flex:1}
.expo-body .link-btn{margin-top:auto;padding-top:10px;align-self:flex-start}
.expo-body{padding:22px}.expo-body h3{font-size:1.15rem;color:#0c1330;margin-bottom:12px}
.expo-body p{font-size:.86rem;color:var(--muted);margin:4px 0}
.link-btn{background:none;border:0;color:var(--orange);font-weight:700;cursor:pointer;margin-top:10px;font-size:.9rem}

.blog-chip{display:inline-flex;align-items:center;gap:5px;font-size:.72rem;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;padding:5px 11px;border-radius:50px;background:rgba(246,160,26,.16);color:#b4730a}
.blog-excerpt{font-size:.88rem;color:var(--muted);line-height:1.65;margin:0 0 16px}
.blog-readmore{margin-top:auto;align-self:flex-start;display:inline-flex;align-items:center;gap:6px;
  font-size:.8rem;font-weight:700;color:#0c1330;text-decoration:none;border:1px solid var(--line);
  border-radius:8px;padding:8px 14px;transition:.2s}
.blog-readmore:hover{background:var(--orange);border-color:var(--orange);color:#fff}
.blog-readmore span{color:var(--orange);transition:.2s}
.blog-readmore:hover span{color:#fff;transform:translate(2px,-2px)}

.blog-list-hero{min-height:42vh}
.blog-feature{display:grid;grid-template-columns:1.05fr .95fr;gap:0;max-width:var(--maxw);margin:0 auto 34px;
  border:1px solid var(--line);border-radius:20px;overflow:hidden;background:#fff;box-shadow:var(--shadow);
  text-decoration:none;color:inherit;transition:.35s}
.blog-feature:hover{transform:translateY(-4px);box-shadow:0 24px 60px rgba(8,12,28,.16)}
/* Was a contained photo sitting on a blurred, darkened, 1.15x-scaled copy of
   itself — so a banner headline in the artwork appeared twice, once sharp and
   once as a blur bleeding off both edges. The frame now takes the picture's own
   aspect-ratio (passed in from pages/blog.php), which makes `cover` an exact
   fit: whole photo, no crop, no filler. Same frame as .expo-img and .he-img. */
.blog-feature-img{position:relative;overflow:hidden;background:#eef1f6}
.blog-feature-img.bg-on::after{content:"";position:absolute;inset:0;background:var(--bimg) center/cover no-repeat}
/* Warm near-black on the orange, not white: white on --orange measures 2.11:1
   and this chip is the first thing read on the featured post. */
.blog-feature-img .featured-chip{position:absolute;top:16px;left:16px;z-index:2;background:var(--orange);color:#241700}
.blog-feature-body{padding:34px 38px;display:flex;flex-direction:column;justify-content:center}
.blog-feature-body h3{font-family:'Sora';font-size:clamp(1.3rem,2.4vw,1.85rem);line-height:1.25;color:#0c1330;margin:14px 0 12px}
.blog-feature-meta{display:flex;flex-wrap:wrap;gap:8px 18px;font-size:.8rem;color:var(--muted);font-weight:600;margin:0 0 18px}
@media(max-width:820px){ .blog-feature{grid-template-columns:1fr} .blog-feature-img{min-height:220px} .blog-feature-body{padding:26px 24px} }

.blog-grid{align-items:stretch}
.blog-card{display:flex;flex-direction:column}
.blog-card .blog-card-img{position:relative;display:block;overflow:hidden;background:#eef1f6}
.blog-card .blog-card-img.bg-on::after{content:"";position:absolute;inset:0;background:var(--bimg) center/cover no-repeat}
.blog-card .blog-card-img .blog-chip{position:absolute;top:12px;left:12px;z-index:2;background:rgba(12,19,48,.78);color:#fff;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.blog-card .expo-body{display:flex;flex-direction:column;flex:1;padding:22px}
.blog-card-meta{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:.78rem;color:var(--muted);font-weight:700;margin:0 0 9px}
.blog-card-meta .blog-date,.blog-card-meta .blog-rt{display:inline-flex;align-items:center;gap:5px;margin:0}
.blog-card .expo-body h3{font-size:1.05rem;line-height:1.38;color:#0c1330;margin:0 0 10px}
.blog-card .expo-body h3 a{color:inherit;text-decoration:none}
.blog-card .expo-body h3 a:hover{color:var(--orange)}

.blog-hero{min-height:42vh}
.blogd-layout{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:34px;align-items:start;max-width:var(--maxw);margin:0 auto}

.blogd-card{min-width:0;background:#f7f8fa;border:1px solid var(--line);border-radius:16px;overflow:hidden}
.blogd-img{background:#eef1f5;padding:14px;position:relative;overflow:hidden}
.blogd-img img{position:relative;z-index:1;display:block;width:100%;border-radius:10px;cursor:zoom-in}
.blogd-content{padding:10px 30px 32px}
.blogd-date{display:flex;align-items:center;gap:7px;font-size:.82rem;color:var(--muted);font-weight:600;margin:8px 0 12px}
.blogd-date .bd-ic{color:var(--orange)}
.blogd-title{font-family:'Sora';font-size:clamp(1.4rem,3vw,1.9rem);line-height:1.28;color:#0c1330;margin:0 0 18px}
.blogd-body{color:#5b6675;line-height:1.85;font-size:1rem}
.blogd-body p{margin:0 0 14px}
.blogd-body h2,.blogd-body h3{font-family:'Sora';color:#0c1330;line-height:1.3;margin:24px 0 10px}
.blogd-body h2{font-size:1.4rem}.blogd-body h3{font-size:1.2rem}
.blogd-body ul,.blogd-body ol{margin:0 0 16px;padding-left:22px}
.blogd-body li{margin:7px 0}
.blogd-body strong{color:#2b3445}
.blogd-body a{color:var(--orange);text-decoration:underline;text-underline-offset:2px}
.blogd-body blockquote{margin:18px 0;padding:12px 20px;border-left:4px solid var(--orange);background:#fff;border-radius:0 10px 10px 0;font-style:italic;color:#4b5563}
.blogd-body img{max-width:100%;border-radius:10px;margin:12px 0}

.blogd-share{display:flex;align-items:center;gap:10px;margin-top:26px;padding-top:18px;border-top:1px solid var(--line)}
.blogd-share .bs-label{font-weight:800;color:#0c1330;font-size:.9rem;margin-right:4px}
.blogd-share a{width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;border-radius:50%;
  color:#fff;text-decoration:none;transition:transform .18s,filter .18s}
.blogd-share a svg{width:17px;height:17px}
.blogd-share a:hover{transform:translateY(-2px);filter:brightness(1.08)}
.blogd-share .bs-fb{background:#1877f2}.blogd-share .bs-x{background:#0c1330}
.blogd-share .bs-in{background:#0a66c2}
.blogd-share .bs-ig{background:radial-gradient(circle at 30% 107%,#fdf497 0%,#fdf497 5%,#fd5949 45%,#d6249f 60%,#285AEB 90%)}
.blogd-back{display:flex;flex-wrap:wrap;gap:12px;margin-top:22px}

.blogd-side{position:sticky;top:96px;background:#f4f5f7;border:1px solid var(--line);border-radius:16px;padding:18px 14px;overflow:hidden}
.blogd-side-t{font-family:'Sora';text-align:center;color:#0c1330;font-size:1.15rem;margin:4px 0 12px;position:relative}
.blogd-side-t::after{content:"";display:block;width:46px;height:3px;background:var(--orange);border-radius:3px;margin:8px auto 0}
@media(max-width:980px){ .blogd-layout{grid-template-columns:1fr} .blogd-side{position:static} }
@media(max-width:600px){ .blogd-content{padding:10px 18px 26px} }

.blog-recent{list-style:none;margin:0;padding:8px;max-height:none;overflow:visible}
.blog-recent li{margin:0;border-bottom:1px solid #f1f3f7}
.blog-recent li:last-child{border-bottom:0}
.blog-recent a{display:flex;gap:12px;padding:12px 10px;border-radius:12px;text-decoration:none;transition:.18s}
.blog-recent a:hover{background:#f7f8fb}
.blog-recent .br-thumb{flex:0 0 60px;width:60px;height:60px;border-radius:10px;background:#0b1124 center/cover no-repeat}
.blog-recent .br-meta{display:flex;flex-direction:column;min-width:0;justify-content:center}
.blog-recent .br-date{font-size:.78rem;color:var(--muted);font-weight:600;margin-bottom:3px}
.blog-recent .br-title{font-size:.83rem;font-weight:700;color:#0c1330;line-height:1.35}
.blog-recent a:hover .br-title{color:var(--orange)}

.modal{position:fixed;inset:0;z-index:2000;background:rgba(6,8,16,.8);backdrop-filter:blur(6px);
  display:none;align-items:flex-start;justify-content:center;padding:40px 18px;overflow-y:auto}
.modal.open{display:flex;animation:fade .3s}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal-card{background:#fff;border-radius:20px;max-width:760px;width:100%;overflow:hidden;box-shadow:var(--shadow);position:relative}
.modal-x{position:absolute;top:14px;right:14px;width:36px;height:36px;border-radius:50%;border:0;background:rgba(0,0,0,.4);
  color:#fff;font-size:1.4rem;cursor:pointer;z-index:2}
.modal-banner{height:280px;position:relative;overflow:hidden;background:#eef1f6}
.modal-banner::after{content:"";position:absolute;inset:0;background:var(--bimg) center/contain no-repeat}
.modal-content{padding:30px}.modal-content h2{color:#0c1330;font-size:1.6rem;margin-bottom:8px}

.form-card{max-width:760px;margin:0 auto;background:#fff;border:1px solid var(--line);border-radius:20px;
  padding:38px;box-shadow:var(--shadow)}
.form-card.wide{max-width:880px}
.form-captcha{margin:18px 0 4px}
.captcha-box{background:#f7f8fb;border:1px solid var(--line);border-radius:12px;padding:14px 16px}
.captcha-q{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin:0}
.captcha-label{font-family:'Manrope';font-weight:600;color:#0c1330;font-size:.95rem}
.captcha-q input{flex:0 0 130px;width:130px;margin:0;padding:10px 12px;border:1px solid var(--line);
  border-radius:8px;font-size:1rem}

.thanks-card{max-width:680px;margin:0 auto;background:#fff;border:1px solid var(--line);
  border-radius:24px;padding:48px 40px;box-shadow:var(--shadow);text-align:center;
  position:relative;overflow:hidden}
.thanks-card::before{content:"";position:absolute;inset:auto -10% -80% -10%;height:240px;
  background:radial-gradient(ellipse at center,rgba(246,160,26,.18),transparent 70%);pointer-events:none}
.thanks-card .ty-tick{display:flex;justify-content:center;margin-bottom:14px}
.thanks-card .ty-ring{stroke-dasharray:226;stroke-dashoffset:226;animation:tyRing .7s cubic-bezier(.6,0,.2,1) .1s forwards}
.thanks-card .ty-check{stroke-dasharray:70;stroke-dashoffset:70;animation:tyCheck .45s cubic-bezier(.6,0,.2,1) .65s forwards}
.thanks-card .eyebrow{margin-top:6px}
.thanks-card .ty-title{color:#0c1330;font-size:clamp(1.6rem,3.6vw,2.2rem);margin:8px auto 14px;max-width:520px;line-height:1.2}
.thanks-card .ty-body{max-width:520px;margin:0 auto 26px;font-size:1rem;line-height:1.6}
.thanks-card .ty-buttons{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;position:relative;z-index:1}
@keyframes tyRing{to{stroke-dashoffset:0}}
@keyframes tyCheck{to{stroke-dashoffset:0}}

/* Thank-you popup — the .thanks-card shown as a centred modal after a form submit.
   Reuses the .modal shell (backdrop + close JS) and all .thanks-card inner styles. */
.ty-modal .thanks-card{max-width:540px;margin:auto;animation:tyPop .42s cubic-bezier(.2,.8,.25,1)}
.ty-modal .modal-x{background:rgba(12,19,48,.5)}
.ty-modal .modal-x:hover{background:rgba(12,19,48,.78)}
@keyframes tyPop{from{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:none}}
@media(max-width:600px){ .ty-modal .thanks-card{padding:40px 22px} }

/* Brochure download — lead-capture modal (reuses the .modal shell + .form-card inputs) */
.brochure-modal .modal-card{max-width:460px}
.brochure-modal.open .modal-card{animation:tyPop .42s cubic-bezier(.2,.8,.25,1)}
.brochure-modal .bro-head{text-align:center}
.brochure-modal .bro-ic{font-size:2.4rem;line-height:1;display:block;margin-bottom:8px}
.brochure-modal .bro-head h2{color:#0c1330;font-size:1.45rem;margin-bottom:6px}
.brochure-modal .bro-head p{margin:0 auto;max-width:340px;font-size:.92rem}
.brochure-modal .form-card{box-shadow:none;border:0;padding:0;margin:0;max-width:none;border-radius:0;background:none}

.form-card h2{color:#0c1330;font-size:1.7rem;margin-bottom:6px}
.form-card label{display:block;font-size:.82rem;font-weight:700;color:#0c1330;margin:16px 0 6px}
.form-card input,.form-card select,.form-card textarea{width:100%;padding:12px 14px;border:1px solid var(--line);
  border-radius:10px;font-family:inherit;font-size:.95rem;transition:.2s;background:#fff}
.form-card input:focus,.form-card textarea:focus,.form-card select:focus{outline:none;border-color:var(--orange);
  box-shadow:0 0 0 3px rgba(246,160,26,.15)}

/* International phone: country-code dropdown + national number, styled as one field */
.iti{display:flex;gap:8px;align-items:stretch}
.iti .iti-cc{flex:0 0 auto;width:auto;max-width:46%}
.iti .iti-num{flex:1 1 auto;min-width:0}
.iti.iti-bad .iti-num{border-color:#dc2626;box-shadow:0 0 0 3px rgba(220,38,38,.14)}

.form-card label.has-err input,.form-card label.has-err select,.form-card label.has-err textarea,
.captcha-box.has-err input{border-color:#dc2626;box-shadow:0 0 0 3px rgba(220,38,38,.14)}
.form-card .has-err,.captcha-box.has-err{position:relative}
.err-msg{display:block;color:#dc2626;font-size:.76rem;font-weight:600;margin-top:5px;animation:fade .2s}
.g-recaptcha.has-err{outline:2px solid #dc2626;outline-offset:3px;border-radius:4px}
.checks.has-err legend{color:#dc2626}
.checks.has-err .chk{border-color:rgba(220,38,38,.4)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.checks{border:0;margin:16px 0}.checks legend{font-size:.82rem;font-weight:700;color:#0c1330;margin-bottom:8px}
.chk{display:flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:10px;padding:12px;
  font-weight:600;font-size:.88rem;margin-bottom:10px;cursor:pointer}
.chk input{width:auto}

.feature-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.feature-grid-3{grid-template-columns:repeat(3,1fr)}
.feature-card{border:1px solid var(--line);border-radius:16px;padding:28px 22px;text-align:center;background:#fff;transition:.3s}
.feature-card:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.feature-card .fic{display:inline-grid;place-items:center;width:54px;height:54px;border-radius:14px;
  background:var(--grad-orange);font-size:1.4rem;margin-bottom:16px}
.feature-card b{display:block;color:#0c1330;margin-bottom:8px}
.feature-card p{font-size:.85rem;color:var(--muted)}
.office-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.office-card{border:1px solid var(--line);border-radius:16px;padding:24px;background:#fff}
.office-card .oic{display:inline-grid;place-items:center;width:42px;height:42px;border-radius:11px;
  background:linear-gradient(160deg,#1a2348,#0c1330);margin-bottom:14px}
.office-card h4{color:#0c1330;margin-bottom:10px}.office-card p{font-size:.83rem;color:var(--muted);margin:5px 0}
.narrow{max-width:840px}.legal h2{color:#0c1330;margin:26px 0 10px;font-size:1.4rem}

/* ===== Imprint / Impressum page ===== */
.imprint{max-width:1040px}
.imprint-lead{text-align:center;max-width:640px;margin:0 auto 34px;color:var(--muted);font-size:1rem}
.imprint-card{border:1px solid var(--line);border-radius:18px;padding:32px 30px;background:#fff;
  transition:transform .3s,box-shadow .3s;position:relative;overflow:hidden}
.imprint-card::before{content:"";position:absolute;inset:0 auto 0 0;width:4px;background:var(--grad-orange);opacity:0;transition:.3s}
.imprint-card:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.imprint-card:hover::before{opacity:1}
.imprint-card.span{grid-column:1/-1}
/* single-card variant: all sections stacked inside one card */
.imprint-card.single{padding:14px 36px}
.imprint-row{display:flex;gap:22px;align-items:flex-start;padding:28px 0;border-bottom:1px solid var(--line)}
.imprint-row:last-child{border-bottom:0}
.imprint-row .imc{margin-bottom:0;flex:0 0 auto}
.imprint-row-body{flex:1 1 auto;min-width:0}
.imprint-row-body h2{margin-top:4px}
@media(max-width:600px){ .imprint-card.single{padding:10px 22px} .imprint-row{gap:16px;padding:22px 0} }
.imprint-card .imc{display:inline-grid;place-items:center;width:54px;height:54px;border-radius:15px;
  background:var(--grad-orange);font-size:1.4rem;margin-bottom:18px;box-shadow:0 10px 24px rgba(246,160,26,.28)}
.imprint-card h2{color:#0c1330;font-size:1.22rem;margin:0 0 14px}
.imprint-card .rich-text{font-size:.95rem;line-height:1.8;color:#3a4055}
.imprint-card .rich-text p{margin:0 0 12px}.imprint-card .rich-text p:last-child{margin-bottom:0}
.imprint-card .rich-text strong{color:#0c1330;font-size:1.05rem;font-weight:700}
.imprint-card .rich-text a{color:var(--orange-2);font-weight:600}
.imprint-card .rich-text a:hover{text-decoration:underline}
@media(max-width:760px){ .imprint-card{padding:26px 22px} }

.reveal{opacity:0;transform:translateY(34px) scale(.97);filter:blur(6px);
  transition:opacity .7s ease,transform .7s ease,filter .7s ease}
.reveal.in{opacity:1;transform:none;filter:blur(0)}

/* Above-the-fold content must never wait for JavaScript to become visible.
   The scroll-reveal observer only runs once main.js has downloaded and parsed,
   so hero copy sat at opacity:0 until then — the browser recorded the hero
   subtitle's largest-contentful-paint at ~5.4s on a throttled phone instead of
   ~0.5s. Inside the hero the same entrance runs as a plain CSS animation, so it
   still animates but paints on the first frame. main.js may later add .in to
   these elements; that is a no-op because they are already in the end state. */
.hero .reveal,.page-hero .reveal{opacity:1;transform:none;filter:none;
  animation:heroReveal .7s cubic-bezier(.2,.7,.2,1) both}
.hero .reveal.d1,.page-hero .reveal.d1{animation-delay:.08s}
.hero .reveal.d2,.page-hero .reveal.d2{animation-delay:.16s}
.hero .reveal.d3,.page-hero .reveal.d3{animation-delay:.24s}
.hero .reveal.d4,.page-hero .reveal.d4{animation-delay:.32s}
@keyframes heroReveal{
  from{opacity:0;transform:translateY(34px) scale(.97);filter:blur(6px)}
  to{opacity:1;transform:none;filter:blur(0)}
}
@media (prefers-reduced-motion: reduce){
  .hero .reveal,.page-hero .reveal{animation:none}
}

@media(max-width:980px){
  .nav-links{position:fixed;top:0;right:-100%;height:100vh;height:100dvh;width:78%;max-width:340px;flex-direction:column;
    background:rgba(8,12,28,.98);backdrop-filter:blur(20px);padding:100px 30px 48px;gap:8px;transition:right .4s;z-index:999;
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
  .nav-links.open{right:0}

  body.nav-open{overflow:hidden}
  .nav-links a{font-size:1.1rem;padding:14px 0;color:rgba(255,255,255,.92)}
  .hamburger{display:flex}.nav-cta{display:none}
  .ach-grid,.war-grid,.feature-grid,.office-grid,.expo-grid,.mini-grid{grid-template-columns:1fr 1fr}
  .about-split,.detail-top{grid-template-columns:1fr}
  /* Collapsing to one column is not enough on its own: a grid item defaults to
     min-width:auto, so it refuses to shrink below its own min-content and drags
     the track — and the page — wider than the viewport. On /quality that pushed
     the document to 525px inside a 390px screen (a nested auto-fit grid with a
     240px minimum was the widest child). Letting the items shrink is what
     actually stops the sideways scroll. */
  .about-split>*,.detail-top>*{min-width:0}
  .section{padding:64px 20px}
}
@media(max-width:600px){
  .ach-grid,.war-grid,.feature-grid,.office-grid,.expo-grid,.mini-grid,.grid2{grid-template-columns:1fr}
  .hero h1{font-size:3rem}.hero-btns{flex-direction:column}.btn{width:100%;justify-content:center}
}

:root{
  --r-lg:16px; --r-sm:8px;
  --shadow-sm:0 6px 18px rgba(16,24,52,.08);
  --shadow-md:0 18px 44px rgba(16,24,52,.12);
  --shadow-lg:0 34px 80px rgba(8,12,28,.22);
  --ring:0 0 0 3px rgba(246,160,26,.22);
}
::selection{background:rgba(246,160,26,.28)}
body{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a,button{outline:none}
/* Keyboard focus. The ring must clear 3:1 against the page (WCAG 2.4.11),
   so it is drawn with a solid outline in the text-safe orange — the old
   rgba(246,160,26,.22) glow measured ~1.2:1 on white. `outline` follows the
   element's own border-radius, so pills and circles keep their shape. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:3px solid var(--orange-ink);outline-offset:3px;box-shadow:var(--ring)}
/* On dark surfaces the same orange is too low-contrast — switch to gold. */
.section.dark :focus-visible,#site-footer :focus-visible,.hero :focus-visible,
.page-hero :focus-visible,.nav-links.open :focus-visible,.modal :focus-visible{
  outline-color:var(--gold)}
.eyebrow{display:inline-flex;align-items:center;gap:8px}
.eyebrow::before{content:"";width:26px;height:2px;background:var(--grad-orange);border-radius:2px;display:inline-block}
.eyebrow.center{display:flex;justify-content:center}
.section-title{position:relative}
.lead{font-size:1.12rem;color:var(--muted);max-width:680px;line-height:1.7}
.lead.center{margin-left:auto;margin-right:auto;text-align:center}

.btn-primary{position:relative}
.btn-primary::after{content:"";position:absolute;top:0;left:-120%;width:60%;height:100%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);transform:skewX(-18deg);transition:.6s}
.btn-primary:hover::after{left:140%}
.btn-ghost{transition:.25s}
.btn-ghost:hover{transform:translateY(-2px)}

.hero-sky{position:absolute;inset:0;z-index:0;
  background:linear-gradient(180deg,#05070f 0%,#0b1226 30%,#1c2f57 58%,#7c4a2c 84%,#e0913f 100%)}
.hero-stars{position:absolute;inset:0;z-index:0;
  background-image:radial-gradient(1.4px 1.4px at 20% 22%,rgba(255,255,255,.8),transparent),
    radial-gradient(1.2px 1.2px at 64% 14%,rgba(255,255,255,.7),transparent),
    radial-gradient(1.6px 1.6px at 82% 30%,rgba(255,255,255,.65),transparent),
    radial-gradient(1.1px 1.1px at 38% 9%,rgba(255,255,255,.6),transparent),
    radial-gradient(1.3px 1.3px at 9% 40%,rgba(255,255,255,.5),transparent);
  opacity:.55}
.hero-sun{position:absolute;z-index:1;width:120px;height:120px;border-radius:50%;
  background:radial-gradient(circle,#fff7df 0%,#ffd470 42%,#f6a01a 66%,rgba(246,160,26,0) 72%);
  box-shadow:0 0 120px 50px rgba(246,160,26,.45);
  animation:sunArc 17s ease-in-out infinite alternate;will-change:left,top}
@keyframes sunArc{0%{left:3%;top:60%;opacity:.55}16%{opacity:1}50%{left:46%;top:9%}100%{left:90%;top:58%;opacity:.7}}
.hero-rig{position:absolute;left:0;right:0;bottom:9%;z-index:1;height:38%;
  display:flex;align-items:flex-end;justify-content:center;gap:clamp(14px,3.4vw,46px);
  padding:0 5%;perspective:1200px}
.hero-ground{position:absolute;left:0;right:0;bottom:0;height:30%;z-index:1;
  background:linear-gradient(180deg,rgba(120,74,40,0),rgba(10,8,5,.55));
  -webkit-mask:linear-gradient(180deg,transparent,#000 60%);mask:linear-gradient(180deg,transparent,#000 60%)}
.tracker{position:relative;width:clamp(58px,8vw,118px);aspect-ratio:1/.66;transform-style:preserve-3d}
.t-panel{position:absolute;inset:0;border-radius:5px;border:1px solid #0a1830;transform-origin:center;
  background-color:#13305c;background-image:
    linear-gradient(118deg,rgba(255,255,255,.22),rgba(255,255,255,0) 46%),
    repeating-linear-gradient(90deg,#0a1c3a 0 1px,transparent 1px 25%),
    repeating-linear-gradient(0deg,#0a1c3a 0 1px,transparent 1px 50%);
  box-shadow:0 14px 26px rgba(0,0,0,.4);animation:track 17s ease-in-out infinite alternate;will-change:transform}
.t-panel::after{content:"";position:absolute;left:-1px;right:-1px;bottom:-7px;height:7px;border-radius:0 0 4px 4px;
  background:#28344d;transform:rotateX(-90deg);transform-origin:top}
.t-post{position:absolute;left:50%;bottom:-30%;width:5px;height:38%;transform:translateX(-50%);
  background:linear-gradient(#9aa6ba,#566076);border-radius:2px;z-index:-1}
.tracker:nth-child(2) .t-panel{animation-delay:-.5s}
.tracker:nth-child(3) .t-panel{animation-delay:-1s}
.tracker:nth-child(4) .t-panel{animation-delay:-1.5s}
.tracker:nth-child(5) .t-panel{animation-delay:-2s}
.tracker:nth-child(6) .t-panel{animation-delay:-2.5s}
.tracker:nth-child(7) .t-panel{animation-delay:-3s}
@keyframes track{0%{transform:rotateX(6deg) rotateY(36deg)}100%{transform:rotateX(6deg) rotateY(-36deg)}}
.hero-overlay{z-index:2;background:
  linear-gradient(100deg,rgba(6,9,18,.94) 16%,rgba(12,17,38,.62) 52%,rgba(246,160,26,.10) 100%)}
.hero-particles{z-index:2}
.hero-content{z-index:3}
.hero .badge{backdrop-filter:blur(4px)}
.scroll-cue{position:absolute;left:50%;bottom:26px;z-index:3;transform:translateX(-50%);
  width:26px;height:42px;border:2px solid rgba(255,255,255,.4);border-radius:14px;display:grid;justify-items:center}
.scroll-cue::before{content:"";width:4px;height:8px;border-radius:2px;background:var(--gold);margin-top:7px;
  animation:cue 1.6s ease-in-out infinite}
@keyframes cue{0%,100%{transform:translateY(0);opacity:1}60%{transform:translateY(12px);opacity:.2}}

.ach-card{transition:.3s}
.ach-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md);border-color:rgba(12,19,48,.16)}
.ach-icon{box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}/* no hover zoom — scaling inside a clipped box crops the photo's edges. */
.about-img{position:relative}
.about-img::before{content:"";position:absolute;inset:-14px -14px auto auto;width:60%;height:60%;border-radius:var(--r);
  background:var(--grad-orange);opacity:.18;filter:blur(30px);z-index:-1}
.stat-band{background:var(--navy);color:#fff;padding:70px 24px;position:relative;overflow:hidden}
.stat-band::before{content:"";position:absolute;inset:0;background:
  radial-gradient(60% 120% at 12% 0%,rgba(246,160,26,.16),transparent 60%)}

.stat-band.has-bg{background-size:cover;background-position:center;background-repeat:no-repeat}
.stat-band.has-bg::before{background:
  radial-gradient(60% 120% at 12% 0%,rgba(246,160,26,.22),transparent 60%),
  linear-gradient(0deg,rgba(8,12,28,.86),rgba(8,12,28,.74))}
.stat-inner{max-width:var(--maxw);margin:0 auto;display:grid;grid-template-columns:repeat(4,1fr);gap:28px;position:relative}
.qwar-inner{grid-template-columns:repeat(5,1fr)}
@media(max-width:980px){ .qwar-inner{grid-template-columns:repeat(3,1fr)} }
@media(max-width:600px){ .qwar-inner{grid-template-columns:repeat(2,1fr)} }

/* Promise cards: as few as 2 today, more if an admin adds them later — size
   columns to the content instead of reserving a fixed 3-up grid that leaves
   a card-sized hole when there's an even/short count.
   Needs BOTH classes in the selector: plain `.qpromise-grid` has the same
   specificity as the `.icon-grid{repeat(3,1fr)}` rule further down the file,
   so the later one won and the two cards were squeezed into a 3-up track with
   dead space beside them. */
.icon-grid.qpromise-grid{grid-template-columns:repeat(auto-fit,minmax(240px,1fr));max-width:640px}

/* Branded stand-in for a project with no photo yet (see project_placeholder_html()) —
   shared by the Projects listing card and the project detail page's main figure.
   Deliberately calm: one flat navy plate, a large faint watermark icon anchored in
   the corner (not a floating badge competing with the text), plain text — no pills,
   no gradients-on-gradients. Reads as "no photo yet", not "we're trying too hard". */
/* 706 of the 774 projects have no cover photo, so this is the dominant look of
   the grid rather than a rare fallback — and sitting beside real aerial shots
   of solar farms, the old flat navy plate with a drafting grid read as a photo
   that had failed to load.

   So it now draws what the photographs show: rows of modules running back to a
   lit horizon. Entirely CSS gradients on one empty span — no image request, and
   nothing to load for the ~700 cards that use it. */
.proj-ph{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;
  text-align:center;padding:22px;color:#fff;overflow:hidden;
  background:radial-gradient(54% 40% at 80% 60%,rgba(246,160,26,.3),transparent 66%),
             linear-gradient(180deg,#0b1330 0%,#122045 52%,#1b2c58 64%,#0d1636 100%)}
/* Low sun sitting just above the horizon line. */
.proj-ph::before{content:"";position:absolute;z-index:0;left:82%;top:57%;width:42px;height:42px;
  margin:-21px 0 0 -21px;border-radius:50%;pointer-events:none;opacity:.9;
  background:radial-gradient(circle,#ffe1a8 0%,#f6a01a 52%,rgba(246,160,26,0) 72%)}
/* The horizon itself — a lit edge that separates sky from array. */
.proj-ph::after{content:"";position:absolute;z-index:0;left:0;right:0;top:64%;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,216,155,.42) 34%,rgba(255,216,155,.8) 74%,transparent);
  box-shadow:0 0 20px 7px rgba(246,160,26,.16)}
/* The array. A flat plane of stripes laid down in perspective: the stripes
   converge as they recede, which is what gives the rows their depth. Masked
   away at the top so they dissolve into haze at the horizon instead of ending
   on a hard line. */
.proj-ph-field{position:absolute;z-index:0;left:-34%;right:-34%;top:64%;bottom:0;pointer-events:none;
  transform:perspective(200px) rotateX(66deg);transform-origin:50% 0;
  background-image:repeating-linear-gradient(90deg,rgba(178,210,255,.34) 0 11px,rgba(178,210,255,0) 11px 27px),
                   repeating-linear-gradient(0deg,rgba(255,255,255,.055) 0 1px,transparent 1px 17px);
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 24%,#000 100%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 24%,#000 100%);
  transition:transform .65s cubic-bezier(.2,.7,.2,1),filter .65s ease}
/* Hovering tips the rows, the way a tracker turns to follow the sun. */
.pj-card:hover .proj-ph-field,.pd-figure--ph:hover .proj-ph-field{
  transform:perspective(200px) rotateX(61deg) skewX(-5deg);filter:brightness(1.28)}
/* Fixed-tilt and seasonal MMS sites get wider, cooler rows than trackers, so a
   screen of photo-less cards varies with the portfolio instead of repeating. */
.proj-ph--fixed .proj-ph-field{
  background-image:repeating-linear-gradient(90deg,rgba(150,226,214,.3) 0 15px,rgba(150,226,214,0) 15px 34px),
                   repeating-linear-gradient(0deg,rgba(255,255,255,.05) 0 1px,transparent 1px 21px)}
@media(prefers-reduced-motion:reduce){
  .proj-ph-field,.pj-card:hover .proj-ph-field,.pd-figure--ph:hover .proj-ph-field{transition:none}
}
.proj-ph-mw{position:relative;z-index:1;font-family:'Sora',sans-serif;font-weight:800;
  font-size:2rem;line-height:1;letter-spacing:-.02em;color:#fff;text-shadow:0 2px 18px rgba(0,0,0,.45)}
/* Short rule under the capacity, so the number reads as a heading with a
   caption instead of two unrelated centred lines. */
.proj-ph-mw::after{content:"";display:block;width:32px;height:3px;border-radius:2px;
  margin:11px auto 0;background:var(--grad-sun,linear-gradient(135deg,#ffc25c,#f6a01a))}
.proj-ph-type{position:relative;z-index:1;font-family:var(--font-mono,ui-monospace,monospace);
  font-size:.72rem;font-weight:700;letter-spacing:.15em;text-transform:uppercase;max-width:92%;
  color:#ffd9a0;background:rgba(8,12,28,.5);border:1px solid rgba(246,160,26,.34);
  padding:4px 10px;border-radius:5px}
/* Pinned to the floor so the capacity + type stay optically centred in the plate. */
.proj-ph-brand{position:absolute;z-index:1;left:0;right:0;bottom:14px;margin:0;
  font-size:.64rem;font-weight:800;letter-spacing:.34em;color:rgba(255,255,255,.32)}
.proj-ph-hero .proj-ph-mw{font-size:3.1rem}
.proj-ph-hero .proj-ph-mw::after{width:46px;margin-top:15px}
.proj-ph-hero .proj-ph-type{font-size:.78rem;padding:6px 14px}
.proj-ph-hero .proj-ph-brand{font-size:.78rem;bottom:20px}
.stat-inner .st strong{font-family:'Sora';font-size:2.6rem;display:block;color:#fff;line-height:1}
.stat-inner .st b{color:var(--gold)}
.stat-inner .st span{font-size:.78rem;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.6);font-weight:700}

.icon-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.icon-card{padding:30px 26px;border-radius:var(--r);border:1px solid var(--line);background:#fff;transition:.3s}
.icon-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md)}
.icon-card .ic{width:54px;height:54px;border-radius:14px;display:grid;place-items:center;font-size:1.5rem;
  background:linear-gradient(160deg,#1a2348,#0c1330);color:var(--gold);margin-bottom:16px}
.icon-card .ic svg{width:26px;height:26px;display:block}

.why-grid{grid-template-columns:repeat(4,1fr)}
.why-grid .icon-card{padding:24px 20px}
.why-grid .icon-card h3{font-size:1rem}
.why-grid .icon-card p{font-size:.84rem}
@media(max-width:980px){.why-grid{grid-template-columns:repeat(2,1fr)}}
.icon-card h2,.icon-card h3{color:#0c1330;font-size:1.12rem;margin-bottom:8px}
.icon-card p{font-size:.9rem;color:var(--muted)}
.icon-card.dark{background:linear-gradient(160deg,#10193a,#0a1026);border-color:rgba(255,255,255,.08)}
.icon-card.dark h4{color:#fff}.icon-card.dark p{color:rgba(255,255,255,.7)}

.timeline{position:relative;max-width:820px;margin:0 auto;padding-left:34px}/* The rail is drawn per item, from this dot down to the next one, rather than
   as one bar down the whole container. A container-height bar kept running past
   the final dot into the section's bottom padding, leaving a line dangling into
   empty space; segments simply stop at the last milestone. */

.cta-band .btn{position:relative;z-index:1}

.reveal{transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1),filter .7s cubic-bezier(.2,.7,.2,1)}
.reveal.d1{transition-delay:.08s}.reveal.d2{transition-delay:.16s}.reveal.d3{transition-delay:.24s}.reveal.d4{transition-delay:.32s}

.map-embed{border:0;width:100%;height:340px;border-radius:var(--r);box-shadow:var(--shadow-md);display:block}

/* Leaflet ships its zoom buttons at 26px, which measures 29x27 on a phone —
   well under the 44px a finger needs, and they sit in the corner of a map that
   pans under the same touch. Only enlarged on touch pointers so the desktop
   control keeps its compact proportions. */
/* Leaflet's stylesheet is appended at scroll time, so it lands AFTER this one.
   Its own touch rule is `.leaflet-touch .leaflet-bar a{width:30px}` — the same
   (0,2,1) specificity, so it would win on source order. Adding .map-embed to
   the container (Leaflet puts .leaflet-touch on that same element) makes this
   (0,3,1) and settles it without !important. */
@media (pointer:coarse){
  .map-embed.leaflet-touch .leaflet-bar a,
  .map-embed.leaflet-touch .leaflet-bar a:hover{
    width:44px;height:44px;line-height:44px;font-size:1.35rem}
  .map-embed.leaflet-touch .leaflet-bar a:first-child{border-top-left-radius:8px;border-top-right-radius:8px}
  .map-embed.leaflet-touch .leaflet-bar a:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}
}

@media(max-width:980px){
  .stat-inner,.steps,.icon-grid{grid-template-columns:1fr 1fr}
  .hero-rig{bottom:6%;gap:14px}
  .tracker:nth-child(n+6){display:none}
}
@media(max-width:600px){
  .stat-inner,.steps,.icon-grid{grid-template-columns:1fr}
  .section{padding:72px 20px}
  .tracker:nth-child(n+4){display:none}
}

@media(prefers-reduced-motion:reduce){
  .hero-sun,.t-panel,.marquee-track,.scroll-cue::before{animation:none!important}
  .t-panel{transform:rotateX(6deg) rotateY(-14deg)}
  html{scroll-behavior:auto}
}

.brand-logo{height:40px;width:auto;display:block;object-fit:contain;filter:drop-shadow(0 2px 8px rgba(0,0,0,.35))}
.footer-brand{display:block}
.footer-brand .brand-logo{height:52px;margin-bottom:6px}

.socials a:hover{transform:translateY(-3px)}

.wa-float{position:fixed;right:18px;bottom:18px;z-index:950;width:56px;height:56px;border-radius:50%;
  background:#25d366;display:grid;place-items:center;color:#fff;box-shadow:0 12px 30px rgba(37,211,102,.45);
  transition:.3s;animation:waPulse 2.6s infinite}
.wa-float svg{width:30px;height:30px}
.wa-float:hover{transform:scale(1.08)}
@keyframes waPulse{0%{box-shadow:0 0 0 0 rgba(37,211,102,.5),0 12px 30px rgba(37,211,102,.45)}
  70%{box-shadow:0 0 0 16px rgba(37,211,102,0),0 12px 30px rgba(37,211,102,.45)}100%{box-shadow:0 0 0 0 rgba(37,211,102,0),0 12px 30px rgba(37,211,102,.45)}}

.video-wrap{position:relative;max-width:1000px;margin:0 auto;aspect-ratio:16/9;border-radius:var(--r);
  overflow:hidden;box-shadow:var(--shadow-lg);background:#05070f}
.video-wrap iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

.client-chip.logo{padding:0;background:none;display:flex;align-items:center;justify-content:center;
  min-width:auto;height:clamp(96px,13vw,150px);border:0;border-radius:0;box-shadow:none;transition:transform .3s ease}
.client-chip.logo:hover{transform:scale(1.06)}

/* Fluid logo size: 150px on desktop, scales down to 96px on phones — object-fit:contain
   so nothing is ever cropped, only letter-boxed, at every screen width. */
.client-chip.logo img{max-height:clamp(96px,13vw,150px);max-width:min(68vw,280px);width:auto;
  object-fit:contain;display:block;filter:saturate(1.08)}

.feat-list{list-style:none;margin:18px 0 0;display:grid;gap:10px}
.feat-list li{position:relative;padding-left:30px;color:#2a3150;font-size:.92rem}
.feat-list li::before{content:"✓";position:absolute;left:0;top:0;width:20px;height:20px;border-radius:50%;
  background:var(--grad-orange);color:#1a1200;font-size:.78rem;font-weight:800;display:grid;place-items:center}
.feat-list.plain li{padding-left:0}
.feat-list.plain li::before{content:none}

@media(max-width:600px){ .wa-float{width:50px;height:50px} .wa-float svg{width:26px;height:26px} }

.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;
  background:#0e1530}

.vmodal{position:fixed;inset:0;z-index:3000;background:rgba(4,6,12,.88);backdrop-filter:blur(8px);
  display:none;align-items:center;justify-content:center;padding:24px}
.vmodal.open{display:flex;animation:fade .3s}
.vmodal-card{position:relative;width:100%;max-width:1000px}
.vmodal-x{position:absolute;top:-46px;right:0;width:40px;height:40px;border-radius:50%;border:0;
  background:rgba(255,255,255,.16);color:#fff;font-size:1.5rem;cursor:pointer;transition:.2s}
.vmodal-x:hover{background:var(--orange);color:#1a1200}

.expo-pop{position:fixed;right:24px;bottom:92px;z-index:945;width:340px;max-width:calc(100vw - 36px);
  max-height:calc(100vh - 110px);max-height:calc(100dvh - 110px);display:flex;flex-direction:column;
  background:#fff;border-radius:18px;overflow:hidden;box-shadow:var(--shadow-lg);border:1px solid var(--line);
  transform:translateY(30px) scale(.96);opacity:0;transition:.5s cubic-bezier(.2,.7,.2,1);pointer-events:none}
.expo-pop.show{transform:translateY(0) scale(1);opacity:1;pointer-events:auto}
.expo-pop-img{line-height:0;flex:0 0 auto}
.expo-pop-img img{width:100%;height:auto;max-height:46vh;object-fit:contain;display:block}
.expo-pop-x{position:absolute;top:12px;right:12px;width:40px;height:40px;border-radius:50%;border:2px solid #fff;
  background:#0c1330;color:#fff;font-size:1.55rem;line-height:1;display:grid;place-items:center;
  cursor:pointer;z-index:6;box-shadow:0 4px 16px rgba(0,0,0,.5);transition:.2s}
.expo-pop-x:hover{background:var(--orange);color:#1a1200;transform:rotate(90deg)}
.expo-pop-body{padding:18px;overflow-y:auto;flex:1 1 auto;min-height:0}
.expo-pop-body .badge{display:inline-block;color:#a35d00;border:1px solid rgba(246,160,26,.4);
  background:rgba(246,160,26,.08);margin-bottom:10px;font-size:.72rem;padding:5px 12px}
.expo-pop-body .badge.live{color:#dc2626;border-color:rgba(220,38,38,.45);background:rgba(220,38,38,.1);
  display:inline-flex;align-items:center;gap:6px;font-weight:800}
.expo-pop.is-live{border:2px solid rgba(220,38,38,.55)}
.expo-pop-body h3{font-size:1.05rem;color:#0c1330;margin:0 0 8px;line-height:1.25;font-family:'Sora'}
.expo-pop-body p{font-size:.82rem;color:var(--muted);margin-bottom:13px;line-height:1.5}

body.expo-pop-open .wa-float,
body.expo-pop-open #sc-chat-launch{opacity:0;transform:scale(.4);pointer-events:none;transition:.25s ease}
@media(max-width:600px){
  .expo-pop{left:12px;right:12px;width:auto;bottom:14px;max-height:calc(100vh - 28px);max-height:calc(100dvh - 28px)}
  .expo-pop-img img{max-height:40vh}
  .expo-pop-body{padding:15px 16px}
  .wa-float{bottom:24px}

  #cookie-banner{flex-direction:column;align-items:stretch;text-align:center;gap:10px;padding:14px 16px;left:10px;right:10px;bottom:10px}
  #cookie-banner .btn{width:100%;justify-content:center}

  body.has-cookie .wa-float{bottom:152px}

  body.has-cookie .expo-pop{bottom:150px;max-height:calc(100vh - 164px);max-height:calc(100dvh - 164px)}
}

.sec-logo{height:48px;width:auto;display:block;margin-bottom:18px}

.cert-label{text-align:center;font-size:.78rem;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);font-weight:800;margin:42px 0 20px}
.cert-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;margin-top:0}
.cert{position:relative;display:flex;align-items:center;gap:15px;padding:18px 20px;border:1px solid var(--line);border-radius:16px;
  background:#fff;box-shadow:var(--shadow-sm);transition:transform .35s ease,box-shadow .35s ease,border-color .35s ease;
  text-decoration:none;color:inherit;overflow:hidden;cursor:pointer}
.cert::after{content:"";position:absolute;top:0;left:-60%;width:45%;height:100%;
  background:linear-gradient(115deg,rgba(255,255,255,0) 0%,rgba(255,255,255,.55) 50%,rgba(255,255,255,0) 100%);
  transform:skewX(-18deg);transition:left .75s ease;pointer-events:none}
.cert:hover{transform:translateY(-4px);box-shadow:var(--shadow-md);border-color:rgba(12,19,48,.16)}
.cert:hover::after{left:130%}
.cert-seal{width:60px;height:60px;flex:0 0 auto;border-radius:50%;display:flex;flex-direction:column;align-items:center;
  justify-content:center;background:radial-gradient(circle at 50% 32%,#22335f,#0b1430);position:relative;
  box-shadow:0 10px 22px rgba(12,19,48,.32);transition:transform .4s cubic-bezier(.2,.8,.3,1.3)}
.cert:hover .cert-seal{transform:scale(1.08) rotate(-4deg)}
.cert-seal::before{content:"";position:absolute;inset:4px;border:1.5px dashed rgba(246,160,26,.6);border-radius:50%;
  transition:transform 6s linear}
.cert:hover .cert-seal::before{transform:rotate(180deg)}
.cert-seal b{font-family:'Sora';font-weight:800;font-size:.95rem;color:var(--gold);line-height:1;letter-spacing:.02em}
.cert-seal i{font-style:normal;font-size:.64rem;color:rgba(255,255,255,.72);font-weight:700;letter-spacing:.05em;margin-top:2px}
.cert-zoom-ic{position:absolute;right:-3px;bottom:-3px;width:22px;height:22px;border-radius:50%;
  background:var(--orange,#f6a01a);display:flex;align-items:center;justify-content:center;font-size:.78rem;
  box-shadow:0 3px 8px rgba(12,19,48,.4);opacity:0;transform:scale(.5);transition:opacity .25s ease,transform .25s ease}
.cert:hover .cert-zoom-ic{opacity:1;transform:scale(1)}
.cert-txt b{display:block;color:#0c1330;font-family:'Sora';font-size:.96rem;line-height:1.2}
.cert-txt span{font-size:.76rem;color:var(--muted)}
@media(max-width:980px){.cert-row{grid-template-columns:1fr 1fr}}
@media(max-width:600px){.cert-row{grid-template-columns:1fr}}

#site-footer .footer-brand .brand-logo{height:50px}
#site-footer .btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;padding:15px 32px;width:auto;text-align:center;color:#1a1200}
#site-footer .btn-primary{margin:18px 0;box-shadow:0 12px 28px rgba(246,160,26,.38)}
/* Brochure + Impressum sit as a pair. The rule above paints every footer button
   dark for the orange primary, which would leave the ghost variant near-black on
   a translucent dark panel — so the secondary re-claims white here. */
#site-footer .footer-cta{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin:18px 0}
#site-footer .footer-cta .btn{margin:0}
#site-footer .btn-ghost{color:#fff;padding:15px 26px}
#site-footer .btn-ghost:hover{color:#fff;border-color:rgba(246,160,26,.75)}
.socials{display:flex;gap:12px;margin-top:4px;flex-wrap:wrap}
.socials a{width:44px;height:44px;border-radius:12px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.12);color:#fff;transition:.25s}
#site-footer .socials a{display:grid;place-items:center;padding:0;line-height:0}
.socials a svg{width:19px;height:19px}
.socials a:hover{transform:translateY(-3px)}
.socials a[aria-label="LinkedIn"]:hover{background:#0a66c2;border-color:#0a66c2}
.socials a[aria-label="YouTube"]:hover{background:#ff0000;border-color:#ff0000}
.socials a[aria-label="X (Twitter)"]:hover{background:#0b0b0b;border-color:#333}
.socials a[aria-label="Facebook"]:hover{background:#1877f2;border-color:#1877f2}
.socials a[aria-label="WhatsApp"]:hover{background:#25d366;border-color:#25d366}

/* Top-aligned, not centred. With align-items:center the copy floated to the
   middle of whatever height the photo happened to be, so the heading started
   ~100px below the top of the image and no two rows lined up the same way.
   Starting both columns on one line is what makes the row read as deliberate. */
/* minmax(0,1fr), not 1fr: a plain 1fr keeps a min-content floor, so a long
   unbreakable word in the copy widened the text column and squeezed the photo.
   That is why the frames measured 563px wide on one row and 717px on the next
   even though both rows asked for equal halves. */
.prod-showcase{position:relative;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:56px;align-items:start;
  margin-bottom:92px;padding-top:34px}
/* The eyebrow's cap-height sits a couple of px below the photo's hard top edge;
   this pulls it up so the two read as flush rather than nearly-flush. */
.psc-body{padding-top:2px}
.prod-showcase:last-child{margin-bottom:0}
.prod-showcase.flip .psc-media{order:2}
.psc-index{position:absolute;top:-20px;left:-6px;font-family:'Sora';font-weight:800;font-size:6.5rem;line-height:1;
  color:transparent;-webkit-text-stroke:2px rgba(246,160,26,.22);z-index:0;pointer-events:none;user-select:none}
.prod-showcase.flip .psc-index{left:auto;right:-6px}
/* Letting each box take its photo's own shape did show every picture whole,
   but it also made all seven frames a different size — measured 563x559,
   717x711, 563x595, 688x702 … so the left and right halves of the page never
   lined up and the column looked accidental. One square frame for all of them.
   1/1 rather than 4:3 because the product photography actually is square: the
   masters are 732x773 and 783x777, within 5% of it.
   The photo fills that frame (cover), it is not fitted inside it. Fitting left
   a strip of filler down both sides of every near-square photo — the exact
   gap-beside-the-picture this box has been through twice already. At 5% off
   a 732x773 master the crop is invisible; a visible bar is not. */
.psc-media{position:relative;border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-lg);z-index:1;
  border:1px solid var(--line);aspect-ratio:1/1;background:#eef1f6}
.psc-media img,.psc-media video{position:relative;z-index:1;width:100%;height:100%;display:block;object-fit:cover}
.psc-media::before{content:"";position:absolute;left:0;top:0;width:6px;height:100%;background:var(--grad-orange);z-index:2}
.psc-media .ribbon{position:absolute;top:16px;left:22px;background:var(--grad-orange);color:#1a1200;font-family:'Sora';
  font-weight:800;font-size:.72rem;letter-spacing:.12em;padding:6px 12px;border-radius:8px;box-shadow:var(--shadow-sm);z-index:3}
.psc-body{position:relative;z-index:1}
.psc-body .eyebrow{margin-bottom:6px}
.psc-body h2{font-size:2.4rem;color:#0c1330;margin:4px 0 14px}
.chips{display:flex;gap:9px;flex-wrap:wrap;margin:20px 0 26px}
.chips span{font-size:.78rem;font-weight:700;color:#0c1330;background:#fff;border:1px solid var(--line);
  padding:8px 14px;border-radius:50px;transition:.2s}
.chips span::before{content:"✓";color:var(--orange);font-weight:800;margin-right:6px}
.prod-showcase:hover .chips span{border-color:rgba(246,160,26,.45)}
@media(max-width:980px){
  .prod-showcase{grid-template-columns:1fr;gap:26px;margin-bottom:62px}
  .prod-showcase.flip .psc-media{order:0}
  .psc-index{font-size:4.4rem;top:-4px}
  .psc-body h2{font-size:2rem}
}

.brand-badge{display:inline-flex;align-items:center;background:#fff;border-radius:14px;padding:8px 16px;
  box-shadow:0 8px 22px rgba(0,0,0,.22);transition:.25s}
.brand-badge .brand-logo{height:40px;width:auto;display:block;filter:none}
.brand:hover .brand-badge{transform:translateY(-1px);box-shadow:0 12px 28px rgba(0,0,0,.3)}

#navbar .brand-badge{background:transparent;padding:0;border-radius:0;box-shadow:none}

#navbar .brand-badge .brand-logo{height:56px}
#navbar .brand:hover .brand-badge{box-shadow:none;transform:translateY(-1px)}
#site-footer .brand-badge{padding:12px 22px;margin-bottom:6px}
#site-footer .brand-badge .brand-logo{height:48px}
@media(max-width:600px){ .brand-badge{padding:6px 12px} .brand-badge .brand-logo{height:38px} #navbar .brand-badge .brand-logo{height:42px} }

.war-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:18px}
.war-tile{position:relative;min-height:240px;border-radius:20px;overflow:hidden;
  --accent:246,160,26;
  background:
    radial-gradient(135% 105% at 16% 12%, rgba(var(--accent),.26) 0%, rgba(var(--accent),0) 46%),
    radial-gradient(120% 120% at 100% 108%, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 42%),
    linear-gradient(158deg, #1b2a55 0%, #0e1630 58%, #090e20 100%);
  border:1px solid rgba(255,255,255,.07);
  display:flex;flex-direction:column;justify-content:flex-end;padding:24px 22px;color:#fff;
  box-shadow:var(--shadow-md);transition:.35s}

.war-tile::before{content:"";position:absolute;inset:0;z-index:0;opacity:.55;
  background:repeating-linear-gradient(122deg,rgba(255,255,255,.05) 0 1px,transparent 1px 26px),
            repeating-linear-gradient(32deg,rgba(255,255,255,.035) 0 1px,transparent 1px 26px)}

.war-tile::after{content:"";position:absolute;inset:0;z-index:0;opacity:0;transition:opacity .35s;
  background:radial-gradient(120% 90% at 18% 10%, rgba(var(--accent),.3) 0%, rgba(var(--accent),0) 55%)}
.war-tile:hover::after{opacity:1}

.war-grid .war-tile:nth-child(2){--accent:56,189,208}
.war-grid .war-tile:nth-child(3){--accent:96,150,255}
.war-grid .war-tile:nth-child(4){--accent:74,201,126}
.war-grid .war-tile:nth-child(5){--accent:255,194,92}

.war-tile.hl{--accent:255,200,110;
  background:
    radial-gradient(135% 105% at 16% 12%, rgba(255,214,150,.5) 0%, rgba(255,175,65,0) 52%),
    linear-gradient(158deg, #f49a1d 0%, #c0600d 56%, #3f1e05 100%)}
.war-tile:hover{transform:translateY(-6px);box-shadow:var(--shadow-lg)}
.war-tile>*{position:relative;z-index:1}

.war-tile.has-photo{background-size:cover;background-position:center}
.war-tile.has-photo::before{opacity:1;background:linear-gradient(180deg,rgba(13,28,58,.5) 0%,rgba(11,21,48,.85) 58%,rgba(8,12,28,.95) 100%)}
.war-tile.has-photo::after{display:none}
.wt-ic{width:54px;height:54px;border-radius:50%;background:rgba(255,255,255,.18);border:1px solid rgba(255,255,255,.25);
  display:grid;place-items:center;font-size:1.45rem;margin-bottom:auto;backdrop-filter:blur(4px)}
.war-tile strong{font-family:'Sora';font-weight:800;font-size:2.9rem;line-height:1;color:#fff;margin-top:18px;display:block}
.war-tile strong sub{font-size:1.05rem;color:var(--gold);vertical-align:baseline}
.wt-label{display:block;margin-top:8px;font-size:.78rem;letter-spacing:.1em;color:rgba(255,255,255,.82);font-weight:700}
@media(max-width:1100px){.war-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:680px){.war-grid{grid-template-columns:repeat(2,1fr)}}

/* Two-word labels ("About Us") were breaking onto a second line and pushing the
   header taller once the bar got tight — never let a nav label wrap, and don't
   let the items shrink below their text. */
.nav-item{position:relative;display:flex;align-items:center;flex:0 0 auto}
.nav-item>a{display:inline-flex;align-items:center;gap:7px;white-space:nowrap}
.nav-links>a{white-space:nowrap}
.nav-caret{width:7px;height:7px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg) translateY(-2px);opacity:.55;transition:transform .25s ease,opacity .25s ease}
.has-drop:hover .nav-caret,.has-drop:focus-within .nav-caret{transform:rotate(225deg) translateY(2px);opacity:1}
.nav-drop{position:absolute;top:100%;left:50%;transform:translateX(-50%) translateY(14px);min-width:236px;
  background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
  padding:8px;opacity:0;visibility:hidden;transition:opacity .22s ease,transform .22s ease,visibility .22s;z-index:1001}
.nav-drop::before{content:"";position:absolute;top:-14px;left:0;right:0;height:14px}
/* Opens on hover, and for keyboard users when the section link is focus-VISIBLE
   or focus has moved inside the panel.

   Deliberately not :focus-within on the whole item. A mouse click leaves :focus
   sitting on the link, which pinned that panel open after the click — so moving
   the pointer to another section opened a second panel while the first was
   still up, and the two overlapped. :focus-visible is not set by a click, so
   the click case now closes as soon as the pointer leaves. */
.has-drop:hover .nav-drop,
.nav-item.has-drop>a:focus-visible~.nav-drop,
.nav-drop:focus-within{opacity:1;visibility:visible;transform:translateX(-50%) translateY(8px)}
.nav-drop a{display:block;padding:10px 14px;border-radius:9px;color:#1a1f33;font-weight:600;font-size:.9rem;white-space:nowrap;padding-bottom:10px}
.nav-drop a::after{display:none}
.nav-drop a:hover{background:var(--paper);color:var(--orange)}

@media(max-width:980px){
  .nav-links{align-items:stretch}
  .nav-item{flex-direction:column;align-items:flex-start;width:100%}
  .nav-item>a{width:100%}
  .nav-caret{display:none}
  .nav-drop{position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;background:transparent;
    min-width:0;padding:2px 0 8px 16px;margin:2px 0 6px;border-left:2px solid rgba(246,160,26,.45)}
  .nav-drop::before{display:none}
  .nav-drop a{color:rgba(255,255,255,.72);font-size:1rem;padding:9px 0}
  .nav-drop a:hover{background:transparent;color:var(--orange)}
}

.pm-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.pm-grid .icon-card{position:relative}
.pm-grid .icon-card .ic{font-size:1.6rem}
.pm-step{position:absolute;top:24px;right:26px;font-family:'Sora';font-weight:800;font-size:1.7rem;color:rgba(246,160,26,.22)}
.pm-grid .feat-list li{font-size:.95rem}

.pm-card-body ul{list-style:none;margin:14px 0 0;padding:0;display:grid;gap:10px}
.pm-card-body li{position:relative;padding-left:30px;color:#2a3150;font-size:.95rem;line-height:1.5}
.pm-card-body li::before{content:"✓";position:absolute;left:0;top:1px;width:20px;height:20px;border-radius:50%;background:var(--grad-orange);color:#1a1200;font-size:.78rem;font-weight:800;display:grid;place-items:center}
.pm-card-body p{color:#2a3150;font-size:.95rem;line-height:1.6;margin:8px 0}
.pm-card-body a{color:var(--orange);font-weight:700}
.pm-intro p{margin:0}
@media(max-width:760px){ .pm-grid{grid-template-columns:1fr} }

.portfolio-head{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap;margin-bottom:32px}
.portfolio-head .eyebrow,.portfolio-head .section-title{text-align:left}
.portfolio-more{white-space:nowrap}
.portfolio-wrap{position:relative}
.portfolio-track{display:flex;gap:24px;overflow-x:auto;scroll-snap-type:x mandatory;padding:6px 2px 18px;
  scrollbar-width:none;-ms-overflow-style:none}
.portfolio-track::-webkit-scrollbar{display:none}
.pf-card{flex:0 0 360px;max-width:360px;height:430px;border-radius:20px;overflow:hidden;position:relative;
  display:block;text-decoration:none;cursor:pointer;
  background:#0c1330;scroll-snap-align:start;box-shadow:0 18px 40px rgba(8,12,28,.18);transition:transform .3s ease,box-shadow .3s ease}
.pf-card:hover{transform:translateY(-4px);box-shadow:0 24px 50px rgba(8,12,28,.28)}
.pf-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* Neutral, not near-black: these frames now show the whole photo, so the
   surround is visible and a dark slab would read as heavy bars. */
.he-img,.modal-banner,.expo-pop-img,.war-tile.has-photo{background-color:#eef1f6}
.expo-img{background-color:#dfe4ee}
.pf-card::after{content:"";position:absolute;inset:0;z-index:0;background:linear-gradient(180deg,rgba(8,12,28,0) 28%,rgba(8,12,28,.88) 100%)}
.pf-overlay{position:absolute;left:0;right:0;bottom:0;padding:24px;z-index:1;color:#fff}
.pf-mw{display:inline-block;background:var(--orange);color:#1a1200;font-family:'Sora';font-weight:800;
  font-size:1rem;padding:4px 13px;border-radius:30px;margin-bottom:12px}
.pf-name{font-family:'Sora';font-weight:800;font-size:1.3rem;margin:0 0 6px;line-height:1.2;color:#fff}
.pf-type{display:block;font-size:.85rem;color:#f6a01a;font-weight:700}
.pf-loc{display:block;font-size:.85rem;opacity:.9;margin-top:4px}
.pf-arrow{position:absolute;top:50%;transform:translateY(-50%);width:46px;height:46px;border-radius:50%;border:0;
  background:#fff;box-shadow:0 8px 24px rgba(8,12,28,.22);font-size:1.7rem;line-height:1;color:#0c1330;cursor:pointer;
  z-index:3;display:flex;align-items:center;justify-content:center;transition:.2s}
.pf-prev{left:-12px}.pf-next{right:-12px}
.pf-arrow:hover{background:var(--orange);color:#1a1200}

.home-expo .portfolio-head{margin-bottom:30px}
.he-wrap{position:relative}
/* stretch, not flex-start: the row is as tall as its tallest card either way,
   so leaving the others at their natural height just parks white space under
   each one. Stretching makes every card the same height and the row read as a
   deliberate set. */
.he-track{display:flex;align-items:stretch;gap:28px;overflow-x:auto;scroll-snap-type:x mandatory;padding:6px 2px 20px;
  scrollbar-width:none;-ms-overflow-style:none}
.he-track::-webkit-scrollbar{display:none}
.he-card{flex:0 0 calc((100% - 56px)/3);scroll-snap-align:start;display:flex;flex-direction:column;background:#fff;
  border:1px solid var(--line);border-radius:20px;overflow:hidden;text-decoration:none;
  box-shadow:0 10px 30px rgba(20,26,51,.07);transition:.3s}
.he-card:hover{transform:translateY(-6px);box-shadow:var(--shadow)}
/* Frame follows the artwork, same as the exhibition cards. */
.he-img{position:relative;overflow:hidden;background:#eef1f6}
.he-img.bg-on::after{content:"";position:absolute;inset:0;background:var(--bimg) center/cover no-repeat}
.he-body{padding:26px}
.he-date{font-size:.9rem;font-weight:700;color:var(--orange)}
.he-body h3{font-family:'Sora';font-weight:800;color:#0c1330;font-size:1.3rem;margin:10px 0 10px;line-height:1.3}
.he-venue{font-size:.98rem;color:var(--muted);margin:0}
@media(max-width:900px){ .he-card{flex-basis:calc((100% - 28px)/2)} }
@media(max-width:600px){ .he-card{flex-basis:86%}  .pf-card{flex-basis:290px;max-width:290px;height:390px} .pf-arrow{display:none} }

.job-accordion{max-width:860px;margin:0 auto;display:flex;flex-direction:column;gap:14px}
.job-item{border:1px solid var(--line);border-radius:16px;background:#fff;overflow:hidden;transition:box-shadow .3s ease,border-color .3s ease}
.job-item[open]{border-color:rgba(246,160,26,.5);box-shadow:var(--shadow-md)}
.job-item summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:18px;padding:20px 24px}
.job-item summary::-webkit-details-marker{display:none}
.job-item summary::after{display:none}
.job-info{display:flex;flex-direction:column;gap:4px}
.job-title{font-family:'Sora';font-weight:700;color:#0c1330;font-size:1.1rem}
.job-loc{font-weight:700;color:var(--orange);font-size:.76rem;letter-spacing:.06em}
.job-toggle{position:relative;flex:0 0 26px;width:26px;height:26px;border-radius:50%;border:1px solid var(--line);transition:.3s}
.job-toggle::before,.job-toggle::after{content:"";position:absolute;left:50%;top:50%;background:var(--orange);border-radius:2px}
.job-toggle::before{width:11px;height:2px;transform:translate(-50%,-50%)}
.job-toggle::after{width:2px;height:11px;transform:translate(-50%,-50%);transition:transform .3s}
.job-item[open] .job-toggle{background:var(--grad-orange);border-color:transparent}
.job-item[open] .job-toggle::before,.job-item[open] .job-toggle::after{background:#1a1200}
.job-item[open] .job-toggle::after{transform:translate(-50%,-50%) scaleY(0)}
.job-body{padding:0 24px 22px;color:var(--muted);line-height:1.65}
.job-body p{margin-bottom:14px}

.expo-tag{display:inline-block;font-size:.72rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:4px 11px;border-radius:50px;margin-bottom:10px}
.expo-tag.up{background:rgba(246,160,26,.15);color:#b4730a}
.expo-tag.past{background:#eef1f5;color:#6b7280}
.expo-tag.press{background:rgba(43,95,176,.13);color:#2b5fb0}
.expo-tag.live,.exh-tag.live{background:rgba(220,38,38,.12);color:#dc2626;display:inline-flex;align-items:center;gap:6px}
/* Pulsing red dot used by every "LIVE NOW" tag/badge */
.live-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#dc2626;box-shadow:0 0 0 0 rgba(220,38,38,.6);animation:livePulse 1.4s infinite}
@keyframes livePulse{0%{box-shadow:0 0 0 0 rgba(220,38,38,.55)}70%{box-shadow:0 0 0 7px rgba(220,38,38,0)}100%{box-shadow:0 0 0 0 rgba(220,38,38,0)}}
@media (prefers-reduced-motion:reduce){.live-dot{animation:none}}

html{overflow-x:hidden}

@media(max-width:860px){ .footer-grid{grid-template-columns:1fr 1fr;gap:32px} }
@media(max-width:540px){ .footer-grid{grid-template-columns:1fr;gap:26px} }

.hero h1,.section-title,.page-hero h1{overflow-wrap:break-word;word-break:break-word}
@media(max-width:600px){
  .hero h1{font-size:clamp(2.05rem,8.4vw,3rem)}
  .nav-inner{padding:12px 18px}
}

.rich-text p{margin:0 0 10px}
.rich-text p:last-child{margin-bottom:0}
.rich-text ul,.rich-text ol{margin:8px 0 10px 20px;padding:0}
.rich-text li{margin:4px 0;line-height:1.55}
.rich-text a{color:var(--orange);font-weight:700}
.rich-text strong,.rich-text b{font-weight:800}

[dir="rtl"]{text-align:right}
[dir="rtl"] body,html[lang="ar"]{font-family:'Manrope','Segoe UI',Tahoma,sans-serif}

[dir="rtl"] .blogd-body ul,[dir="rtl"] .blogd-body ol{padding-left:0;padding-right:22px}
[dir="rtl"] .blogd-date,[dir="rtl"] .blogd-share{flex-direction:row-reverse;justify-content:flex-end}
[dir="rtl"] .blog-feature-meta,[dir="rtl"] .blog-card-meta{flex-direction:row-reverse;justify-content:flex-end}

[dir="rtl"] .lang-menu{right:auto;left:0}

[dir="rtl"] .exh-crumb span{margin:0 6px}

[dir="rtl"] .brand,[dir="rtl"] #loader,[dir="rtl"] .lang-code{direction:ltr}

[dir="rtl"] .blog-readmore span{transform:scaleX(-1)}

/* ═════════════════════════════════════════════════════════════════════
   POLISH LAYER
   Appended last so it refines the rules above through the cascade rather
   than restructuring them. Order: tokens → a11y → motion → type → depth
   → mobile → utilities → print.
   ═════════════════════════════════════════════════════════════════════ */

/* ── Tokens ────────────────────────────────────────────────────────── */
:root{
  /* --orange on white measures 2.1:1 — unusable for text (AA needs 4.5:1).
     This is the text-safe shade at 5.2:1. Keep --orange for fills, bars,
     icons and anything on a dark surface, where it already clears 8.9:1. */
  --orange-ink:#a05c00;
  --muted:#5f6879;                              /* was #6b7280 — 4.8:1 → 5.6:1 */
  --tx-1:#0c1330; --tx-2:#3a4155; --tx-3:#525b70;
  --sf-1:#f7f8fc; --sf-2:#eef1f6;
  --measure:68ch;                               /* comfortable reading width */

  /* Two-layer elevation: a tight contact shadow plus a soft ambient one.
     Flat single-layer shadows are the main thing that reads as "amateur".
     --shadow keeps its name so the ~20 existing users upgrade for free. */
  --shadow-xs:0 1px 2px rgba(16,24,52,.06),0 1px 1px rgba(16,24,52,.04);
  --shadow-sm:0 2px 4px rgba(16,24,52,.05),0 6px 16px rgba(16,24,52,.07);
  --shadow-md:0 4px 10px rgba(16,24,52,.06),0 18px 40px rgba(16,24,52,.10);
  --shadow-lg:0 4px 10px rgba(8,12,28,.06),0 18px 40px rgba(8,12,28,.10);
  --shadow:var(--shadow-md);
  --ring:0 0 0 5px rgba(246,160,26,.28);

  /* One motion vocabulary — durations previously ranged .15s–.7s ad-hoc. */
  --t-fast:.18s; --t-base:.28s; --t-slow:.5s;
  --ease:cubic-bezier(.2,.7,.2,1);
  --nav-h:96px;
}

/* ── Accessibility ─────────────────────────────────────────────────── */
/* Anchor targets must clear the fixed navbar, otherwise smooth-scrolling to
   #products or #tabs parks the heading underneath it. */
[id]{scroll-margin-top:var(--nav-h)}

.skip-link{position:absolute;left:-9999px;top:0;z-index:10001}
.skip-link:focus{left:12px;top:12px;background:#fff;color:var(--tx-1);
  padding:12px 18px;border-radius:var(--r-sm);box-shadow:var(--shadow-lg);font-weight:700}
#main:focus{outline:none}

/* Touch targets — WCAG 2.5.8 asks for 44x44 CSS px. */
.lang-btn{min-height:44px;padding:8px 10px;margin-right:-6px}
.modal-x,.blogd-share a{width:44px;height:44px}
@media(max-width:600px){
  .exh-lb-close,.exh-lb-nav{width:44px;height:44px}
}

/* ── Motion ────────────────────────────────────────────────────────── */
/* The existing reduced-motion blocks cover the intro loader, hero sun and
   marquee only. The scroll-reveal system (52+ blocks sliding 34px) and every
   hover lift were still animating for users who asked us not to. */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  .reveal{opacity:1!important;transform:none!important;filter:none!important}
  .hero-particles,.wa-float,.live-dot{animation:none!important}
}

/* ── Typography ────────────────────────────────────────────────────── */
/* line-height:1.08 is a display value; it was applied to every heading level,
   so a wrapping card h4 came out visibly cramped. Scale leading with size. */
h3{line-height:1.25}
h4{line-height:1.35;letter-spacing:-.005em}
h5,h6{line-height:1.4;letter-spacing:0}
h1,h2,h3{text-wrap:balance}

/* Long-form copy had no measure and ran to ~110ch in the wide content
   columns; 65–75ch is the readable range. */
.blogd-body,.exh-body,.imprint-card .rich-text,.job-body,.legal p,.legal li{
  max-width:var(--measure)}
.blogd-body{line-height:1.75}

/* ── Contrast ──────────────────────────────────────────────────────── */
/* Small orange text on light backgrounds — see --orange-ink above. */
.eyebrow,.map-link,.link-btn,.he-date,.job-loc,.rich-text a,.blogd-body a,.pm-card-body a,.imprint-card .rich-text a{color:var(--orange-ink)}
/* …but on dark surfaces the bright brand orange is correct and passes. */
.section.dark .eyebrow,.hero .eyebrow,.stat-band .eyebrow,.war-tile .eyebrow,
#site-footer .eyebrow,.page-hero .eyebrow{color:var(--orange)}

.exh-tag.up,.expo-tag.up,.blog-chip{background:rgba(246,160,26,.18);color:var(--orange-ink)}
.exh-tag.past,.expo-tag.past{background:var(--sf-2);color:#4b5468}

/* Page heroes sit on admin-uploaded photos of unknown brightness, so the
   scrim has to carry the text on its own — strengthened top and bottom. */
.page-hero::before{background:
  linear-gradient(180deg,rgba(8,12,28,.72) 0%,rgba(8,12,28,.55) 42%,rgba(8,12,28,.88) 100%),
  radial-gradient(120% 90% at 50% 100%,rgba(8,12,28,.5),transparent 70%)}
.page-hero p{color:rgba(255,255,255,.92);max-width:62ch;margin-inline:auto}

/* ── Depth & interaction ───────────────────────────────────────────── */
/* Card hover lifts ranged -3px to -6px across six near-identical components;
   one lift and one elevation step reads as a single designed system. */
.icon-card:hover,.feature-card:hover,.office-card:hover,.imprint-card:hover,
.mini-card:hover,.expo-card:hover,.he-card:hover,.cert:hover,.str-card:hover{
  transform:translateY(-4px);box-shadow:var(--shadow-lg)}

/* Inputs got a colour change on focus but no ring, so the focused field was
   easy to lose on a long form. */
.form-card input:focus,.form-card textarea:focus,.form-card select:focus{
  box-shadow:var(--ring)}

/* ── Mobile ────────────────────────────────────────────────────────── */
/* The desktop nav ran to 981px but stopped fitting around 1024 (iPad
   landscape), and body{overflow-x:hidden} silently clipped the overflow.
   Only the drawer moves up to 1100px — the grid rules stay at 980. */
@media(max-width:1100px){
  .nav-links{position:fixed;top:0;right:-100%;height:100vh;height:100dvh;width:78%;
    max-width:340px;flex-direction:column;background:rgba(8,12,28,.98);
    backdrop-filter:blur(20px);padding:100px 30px 48px;gap:8px;z-index:999;
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
    transition:right .4s var(--ease),visibility .4s}
  .nav-links.open{right:0}
  /* Off-screen links stayed in the tab order on every phone page. */
  .nav-links:not(.open){visibility:hidden}
  .nav-links a{font-size:1.1rem;padding:14px 0;color:rgba(255,255,255,.92)}
  .hamburger{display:flex}
  .nav-cta{display:none}
  body.nav-open{overflow:hidden}

  /* ── Drawer: collapsible sections ──────────────────────────────────
     Every sub-menu used to render open, so the drawer was one ~30-link
     scroll (Products alone contributes seven). Collapsed, the whole site
     fits on one screen as nine tappable rows. */
  .nav-links{padding:88px 22px 30px;gap:2px}
  /* Divider sits on the row, not the label — on the label it stopped short of
     the chevron and read as an unfinished underline. */
  .nav-item.has-drop{position:relative;display:block;width:100%;
    border-bottom:1px solid rgba(255,255,255,.07)}
  .nav-item.has-drop > a{width:auto;max-width:calc(100% - 48px);padding:13px 0;font-weight:700}
  .nav-links > a{border-bottom:1px solid rgba(255,255,255,.07)}
  .nav-links > a:last-of-type{border-bottom:0}
  /* The sliding underline is a desktop hover affordance; in the drawer it
     doubled up with the active bar below. */
  .nav-links a::after{display:none}

  /* The toggle sits on the row's right edge, clear of the label's tap area. */
  .nav-sub{position:absolute;top:4px;right:-6px;width:44px;height:44px;padding:0;
    background:transparent;border:0;cursor:pointer;display:grid;place-items:center;
    -webkit-tap-highlight-color:transparent}
  .nav-sub::before{content:"";width:8px;height:8px;border-right:2px solid rgba(255,255,255,.6);
    border-bottom:2px solid rgba(255,255,255,.6);transform:rotate(45deg) translate(-2px,-2px);
    transition:transform .3s var(--ease),border-color .3s}
  .nav-item.is-open > .nav-sub::before{transform:rotate(225deg) translate(-2px,-2px);
    border-color:var(--orange,#f6a01a)}
  .nav-sub:focus-visible{outline:2px solid var(--orange,#f6a01a);outline-offset:-6px;border-radius:10px}

  /* max-height rather than the 0fr grid trick: that needs an extra wrapper
     element inside .nav-drop, which the desktop mega-menu grid also targets. */
  .nav-drop,.nav-drop.nav-mega{
    max-height:0;overflow:hidden;opacity:.4;padding:0;
    transition:max-height .34s var(--ease),opacity .3s ease}
  .nav-item.is-open > .nav-drop{max-height:640px;opacity:1;padding:4px 0 10px}
  .nav-drop a,.nav-drop.nav-mega a.nmi{
    padding:9px 0 9px 14px;font-size:.98rem;position:relative;
    border-left:2px solid rgba(246,160,26,.28)}
  .nav-drop a:hover,.nav-drop a:focus-visible{border-left-color:var(--orange,#f6a01a)}

  /* Items fan in behind the drawer as it slides. Scoped to .open so they are
     never left invisible if the drawer never opens. */
  .nav-links > *{opacity:0;transform:translateX(16px);
    transition:opacity .3s ease,transform .35s var(--ease)}
  .nav-links.open > *{opacity:1;transform:none}
  .nav-links.open > *:nth-child(1){transition-delay:.05s}
  .nav-links.open > *:nth-child(2){transition-delay:.09s}
  .nav-links.open > *:nth-child(3){transition-delay:.13s}
  .nav-links.open > *:nth-child(4){transition-delay:.17s}
  .nav-links.open > *:nth-child(5){transition-delay:.21s}
  .nav-links.open > *:nth-child(6){transition-delay:.25s}
  .nav-links.open > *:nth-child(7){transition-delay:.29s}
  .nav-links.open > *:nth-child(8){transition-delay:.33s}
  .nav-links.open > *:nth-child(n+9){transition-delay:.37s}

  /* Current section: a bar on the rail rather than a full-width fill, which
     would fight the orange CTA at the foot of the drawer. */
  .nav-links a.active{color:#fff}
  .nav-item.has-drop > a.active,.nav-links > a.active{
    box-shadow:inset 3px 0 0 var(--orange,#f6a01a);padding-left:12px}

  .nav-drawer-cta{display:inline-flex;margin-top:22px;width:100%;justify-content:center;
    padding:15px 22px;font-size:1rem}
}
/* Desktop keeps the hover mega-menu — the drawer-only controls stay hidden. */
@media(min-width:1101px){
  .nav-sub{display:none}
  .nav-drawer-cta{display:none}
}
@media(prefers-reduced-motion:reduce){
  .nav-links > *{transition:none!important;opacity:1;transform:none}
  .nav-drop,.nav-drop.nav-mega{transition:none}
}

/* .war-grid is redeclared after the 600px collapse rule, which killed it —
   phones were getting two 46px-number tiles side by side in ~150px. */
@media(max-width:600px){
  .war-grid{grid-template-columns:1fr}
  .war-tile{min-height:190px}
  .war-tile strong{font-size:2.2rem}
}

/* ── Utilities ─────────────────────────────────────────────────────── */
/* Full-bleed tint for alternating section rhythm — breaks up long runs of
   identical white slabs without touching the max-width-capped .section. */
.section.tint{position:relative;z-index:0}
.section.tint::before{content:"";position:absolute;top:0;bottom:0;left:50%;
  transform:translateX(-50%);width:100vw;background:var(--sf-1);z-index:-1}
/* Replaces inline style="padding-top:0" / "padding-bottom:0". */
.section.tight{padding-top:0}
.section.flush-b{padding-bottom:0}

/* ── Chrome ────────────────────────────────────────────────────────── */
html{scrollbar-color:rgba(246,160,26,.55) transparent}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(12,19,48,.22);border-radius:8px;
  border:3px solid #fff;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:rgba(246,160,26,.6);background-clip:padding-box;
  border:3px solid #fff}

/* ── Component fit & finish ────────────────────────────────────────── */
/* auto-fit with a 1fr max stretched 3 certificates to ~450px each around a
   60px seal. Capping the track keeps trust content dense and centred. */
.cert-row{grid-template-columns:repeat(auto-fit,minmax(240px,320px));justify-content:center}

/* .short was byte-identical to the base rule, so the quote page asked for a
   shorter hero and got none — it now sits closer to the fold. */
.page-hero.short{min-height:32vh;padding:104px 24px 44px}

/* Five full-width checkboxes stacked down an 880px column read as an
   unfinished form. The .chk labels are direct children of the fieldset
   (with the legend first), so flex-wrap lays them out without needing a
   wrapper element — and the legend is forced onto its own row. */
.checks{display:flex;flex-wrap:wrap;gap:10px}
.checks legend{width:100%;float:left}
.checks .chk{flex:1 1 210px;margin:0}

/* ═════════════════════════════════════════════════════════════════════
   SIGNATURE THEME — "Engineered Light"
   The visual identity: engineering precision (blueprint grid, corner
   brackets, monospace spec labels, tabular figures) lit by solar warmth
   (radial glow, gradient accents). Decoration only — no layout is moved,
   so every existing page picks this up without markup changes.
   ═════════════════════════════════════════════════════════════════════ */

:root{
  --font-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --grad-sun:linear-gradient(135deg,var(--gold) 0%,var(--orange) 45%,var(--orange-2) 100%);
  --grad-ink:linear-gradient(140deg,#0c1330 0%,#16204a 55%,#0b1020 100%);
}

/* ── Atmosphere ────────────────────────────────────────────────────── */
/* The warm top-of-section glow was removed on purpose. It was anchored hard
   at each section's top edge, so wherever two light sections stacked the
   previous one ended fully transparent and the next one began at ~10% orange
   — a visible horizontal seam repeating down every page. Any top-anchored
   gradient has a non-zero value at y=0 and therefore reproduces that step, so
   the fix is to drop it rather than re-tune it. Light sections now share one
   continuous surface; the alternating .tint bands still provide the rhythm. */

.section.tint::before{background-color:var(--sf-1)}

/* Dark sections become a lit mesh instead of flat navy. */
.section.dark{
  background-image:
    radial-gradient(58% 44% at 82% 6%,rgba(246,160,26,.20),transparent 66%),
    radial-gradient(50% 40% at 6% 96%,rgba(96,150,255,.14),transparent 70%),
    var(--grad-ink);
  background-size:auto,auto,auto}
.stat-band{background-color:#0b1020;background-image:none}
/* CTA band stays a clean flat panel — the drafting grid competes with the
   headline and the orange glow behind the button. */
.cta-band{background-color:#0b1020;background-image:none}

/* ── Spec label (eyebrow) ──────────────────────────────────────────── */
/* Reads like a drawing callout: mono, tracked, with the gradient rule it
   already had. Small-caps sizing keeps it quiet next to the title.
   Letter-spacing is intentionally modest here — a monospace font already has
   wide, boxy characters, so the .22em the sans-serif original used reads as
   an oversized gap between every letter once combined with mono, especially
   on long eyebrows like "About Sunchaser Structures Service". */
.eyebrow{font-family:var(--font-mono);font-weight:600;font-size:.78rem;
  letter-spacing:.13em;gap:8px}
.eyebrow::before{width:22px;height:2px;border-radius:0}
.section.dark .eyebrow,.hero .eyebrow{color:var(--gold)}

/* ── Section titles ────────────────────────────────────────────────── */
/* Tighter, heavier display setting plus a gradient rule beneath — the
   single most repeated element on the site, so it defines the feel. */
.section-title{letter-spacing:-.035em;font-weight:800;padding-bottom:20px;margin-bottom:34px}
.section-title::after{
  content:"";position:absolute;left:0;bottom:0;width:64px;height:4px;border-radius:4px;
  background:var(--grad-sun);box-shadow:0 0 18px rgba(246,160,26,.55)}
.section-title.center::after{left:50%;transform:translateX(-50%)}
.section-title.light::after{box-shadow:0 0 22px rgba(246,160,26,.8)}

/* Hero headline: the accent line burns in the solar gradient. */
.hero h1 .accent{background:var(--grad-sun);-webkit-background-clip:text;
  background-clip:text;color:transparent}
.hero h1{letter-spacing:-.04em}
.hero-content{position:relative}
.hero .btn-primary,.hero .btn-primary:hover{box-shadow:none}

/* ── Signature card ────────────────────────────────────────────────── */
/* Three ownable details: a gradient edge that ignites on hover, an
   engineering corner bracket, and a warm glow in the lifted shadow. */
.icon-card,.feature-card,.mini-card,.expo-card,.office-card,.he-card,
.imprint-card,.cert,.str-card,.ach-card,.form-card{position:relative;overflow:hidden}

/* Visible at rest as a short brand tick, then it runs the full width on hover.
   A hover-only accent would be invisible in the static view and on every touch
   device, which is where most of this traffic lands. */
.icon-card::before,.feature-card::before,.expo-card::before,.office-card::before,
.he-card::before,.str-card::before,.ach-card::before{
  content:"";position:absolute;top:0;left:0;right:0;height:2px;
  background:var(--line);transform:scaleX(1);transform-origin:left;
  transition:background .3s var(--ease);z-index:2}
.icon-card:hover::before,.feature-card:hover::before,.expo-card:hover::before,
.office-card:hover::before,.he-card:hover::before,.str-card:hover::before,
.ach-card:hover::before{background:var(--orange)}

/* The office chips were switched to the solar gradient to match the other icon
   chips. Both are back on navy now — six identical orange tiles on the contact
   page was the loudest orange on the site, and it made the offices read as
   decoration rather than as the six real places this company operates from. */

.icon-card:hover,.feature-card:hover,.office-card:hover,.imprint-card:hover,
.mini-card:hover,.expo-card:hover,.he-card:hover,.cert:hover,.str-card:hover,
.ach-card:hover{
  /* A coloured ring on hover reads as a consumer UI. Cards lift with a plain
     shadow; the brand shows in content, not in a glow around every box. */
  box-shadow:0 4px 10px rgba(8,12,28,.06),0 18px 40px rgba(8,12,28,.10)}

/* Icon chips stay on the navy gradient defined further up, with the gold mark
   inside it. A wall of eight orange tiles was the first thing the eye hit on
   the homepage, and a halo glowing out of each one is a consumer-app device.
   The orange now appears in the icon, not around it. */

/* ── Numbers ───────────────────────────────────────────────────────── */
/* Stats are the proof points on a manufacturer's site — set them in
   tabular figures so counting animations don't jitter, and let the big
   ones carry the solar gradient. */
.ach-card strong,.stat-inner .st strong,.war-tile strong,.counter{
  font-variant-numeric:tabular-nums;letter-spacing:-.03em}
.stat-inner .st strong{background:var(--grad-sun);-webkit-background-clip:text;
  background-clip:text;color:transparent}
/* stat_value_html() wraps the unit in <b>, which carries its own gold colour.
   That would paint over the clipped gradient and split the number in two —
   inherit the transparent fill so the whole figure reads as one gradient. */
.stat-inner .st strong b{color:inherit}
.stat-inner .st span{font-family:var(--font-mono);font-size:.78rem;letter-spacing:.2em}

/* ── Buttons ───────────────────────────────────────────────────────── */
.btn{letter-spacing:-.01em}
.btn-primary{box-shadow:0 2px 0 rgba(160,90,0,.35),0 12px 30px rgba(246,160,26,.38),
  inset 0 1px 0 rgba(255,255,255,.45)}
.btn-primary:hover{box-shadow:0 2px 0 rgba(160,90,0,.35),0 20px 46px rgba(246,160,26,.55),
  inset 0 1px 0 rgba(255,255,255,.55)}
.btn-dark{background:var(--grad-ink);box-shadow:var(--shadow-sm)}
.btn-dark:hover{box-shadow:var(--shadow-md);transform:translateY(-2px)}
.btn-line{transition:.25s var(--ease)}
.btn-line:hover{border-color:var(--orange);
  box-shadow:0 0 0 3px rgba(246,160,26,.14),var(--shadow-sm);transform:translateY(-2px)}

/* ── Navbar ────────────────────────────────────────────────────────── */
/* The underline becomes a gradient and the scrolled state gets a warm
   hairline, so the chrome matches the rest of the identity. */
.nav-links a::after{background:var(--grad-sun);height:3px;border-radius:3px}
#navbar.scrolled{border-bottom:1px solid rgba(246,160,26,.18)}
.nav-links a.active{color:var(--orange-ink)}

/* ── Dark-surface readability ──────────────────────────────────────── */
/* The mesh sits behind everything; make sure nothing gets lost in it. */
.section.dark .prod-acc,.cta-band .cta-inner,.stat-band .stat-inner{position:relative;z-index:1}

/* ── Footer ────────────────────────────────────────────────────────── */
/* Same own-background technique as the sections — the floating WhatsApp and
   chat buttons live in the footer, so no stacking context is introduced. */
#site-footer{background-color:#0b1020;background-image:var(--grad-ink)}

/* ── Motion & small screens ────────────────────────────────────────── */
@media(max-width:600px){
  /* The ambient glows are sized for desktop; scale them down so they don't
     wash out a phone screen. */
  .section:not(.dark)::after{height:200px}
  .hero-content::before{width:340px;height:340px}
  .section-title{padding-bottom:16px;margin-bottom:26px}
  .section-title::after{width:48px;height:3px}
}
@media(prefers-reduced-motion:reduce){
  .icon-card::before,.feature-card::before,.expo-card::before,.office-card::before,
  .he-card::before,.str-card::before,.ach-card::before{transition:none}
}

@media print{
  #navbar,#site-footer,.cta-band,.wa-float,#sc-chat-launch,.skip-link,
  #scroll-progress,#loader,.expo-pop{display:none!important}
  .reveal{opacity:1!important;transform:none!important;filter:none!important}
  .section{padding:18px 0!important}
  .section::after,.section.dark::after,.hero-content::before{display:none!important}
  .section-title::after{box-shadow:none}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:.75em;color:#555}
  body{color:#000}
}

/* ═════════════════════════════════════════════════════════════════════
   3D MOTION LAYER — "Tracker Tilt"
   The product physically tilts to follow the sun, so the interface does
   the same: every card leans toward the pointer and catches a warm
   highlight where the "sun" is standing. Built entirely on the existing
   Engineered Light tokens (--grad-sun, --orange, --navy) — no new palette.
   Additive only: nothing here moves layout, so every page inherits the
   depth without a markup change.
   ═════════════════════════════════════════════════════════════════════ */

:root{
  --t3d-lift:-8px;      /* how far a hovered card rises */
  --t3d-pop:26px;       /* how far it pushes toward the viewer */
  --t3d-persp:1000px;
}

/* ── Scroll reveal in 3D ───────────────────────────────────────────── */
/* Was a flat rise; now each block swings up on its X axis like a panel
   rotating into alignment. Hero blocks keep their own keyframe intro —
   `.hero .reveal` outranks this single-class selector, so they're left
   alone without needing an override. */
.reveal{
  transform:perspective(1400px) translate3d(0,36px,-70px) rotateX(7deg) scale(.975);
}
.reveal.in{transform:none}

/* Narrow screens get a flat slide instead of the tilt.
   The perspective + rotateX projects a tall section WIDER than its layout box
   (the edge nearest the viewer is magnified), so a correctly-sized 390px
   section painted at ~427px. Every not-yet-revealed section below the fold sat
   in that state, so phones had a permanent sideways scroll and the page jittered
   as sections animated in. A plain translate cannot change the box width. */
@media(max-width:980px){
  .reveal{transform:translateY(28px)}
  .reveal.in{transform:none}
}

/* ── Card tilt ─────────────────────────────────────────────────────── */
/* Selectors are body-qualified (0,2,1) on purpose. Nearly every card here
   is also a `.reveal`, and several pages ship their own inline <style>
   with rules like `.pj-card:hover{transform:...}` that render AFTER this
   file. Those are all (0,2,0), so at equal weight whichever comes last
   would flatten the tilt. The extra `body` outranks them either way.

   Pointer-driven only: --rx/--ry are written by the tilt engine in
   main.js. Gated to fine pointers so a phone never freezes mid-tilt
   after a tap. */
@media (hover:hover) and (pointer:fine){
  body .tilt3d{
    transition:transform .55s cubic-bezier(.2,.7,.2,1),
               box-shadow .45s cubic-bezier(.2,.7,.2,1);
  }
  /* will-change only while tilting — leaving it on permanently would hand
     a compositor layer to all 774 project cards at once. */
  body .tilt3d.tilting{
    will-change:transform;
    transition:transform .12s linear, box-shadow .45s cubic-bezier(.2,.7,.2,1);
    transform:perspective(var(--t3d-persp))
              rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
              translate3d(0,var(--t3d-lift),var(--t3d-pop));
    /* Depth only. The hairline used to be rgba(246,160,26,.34), which drew a
       lit orange ring round every card the cursor touched. */
    box-shadow:
      0 2px 6px rgba(8,12,28,.06),
      0 18px 32px -18px rgba(8,12,28,.28),
      0 46px 80px -40px rgba(8,12,28,.42),
      0 0 0 1px rgba(8,12,28,.08);
  }

  /* Icon chip counter-parallaxes so the card reads as layered glass
     rather than one flat plane pivoting. */
  .ic,.fic,.oic,.dl-ic{transition:transform .5s cubic-bezier(.2,.7,.2,1)}
  body .tilt3d.tilting .ic,body .tilt3d.tilting .fic,
  body .tilt3d.tilting .oic,body .tilt3d.tilting .dl-ic{
    transform:translate3d(var(--icx,0px),var(--icy,0px),0)}
}

/* ── Hero depth ────────────────────────────────────────────────────── */
/* --hx/--hy come from the pointer; the headline sits nearest the viewer
   and the supporting copy trails it, which is what sells the depth. */
@media (hover:hover) and (pointer:fine){
  .hero-content{
    transform:perspective(1200px)
              rotateX(calc(var(--hy,0) * -1.6deg)) rotateY(calc(var(--hx,0) * 1.6deg));
    transition:transform .9s cubic-bezier(.2,.7,.2,1);
    transform-style:preserve-3d;
  }
  .hero-content h1{transform:translateZ(46px)}
  .hero-content .eyebrow{transform:translateZ(28px)}
  .hero-content p,.hero-content .hero-cta{transform:translateZ(18px)}
}

/* ── Buttons ───────────────────────────────────────────────────────── */
/* A real press: the button sinks along Z instead of only changing colour. */
.btn{transition:transform .22s cubic-bezier(.2,.7,.2,1),box-shadow .22s,background .22s,color .22s,border-color .22s}
.btn:active{transform:perspective(600px) translate3d(0,1px,-6px) scale(.985)}
.btn-primary:hover,.btn-dark:hover{transform:perspective(600px) translate3d(0,-3px,12px)}

/* ── Numbers ───────────────────────────────────────────────────────── */
.stat-inner .st{transition:transform .5s cubic-bezier(.2,.7,.2,1)}
.stat-inner .st:hover{transform:perspective(800px) translate3d(0,-5px,20px)}

/* ── Opt-outs ──────────────────────────────────────────────────────── */
/* Surfaces that already move or overlay stay flat — a tilting marquee or
   lightbox reads as a bug, not an effect. */
.clients-marquee .tilt3d,.lb-wrap .tilt3d,.modal .tilt3d{transform:none!important}

@media (prefers-reduced-motion:reduce){
  .tilt3d,.tilt3d.tilting,.hero-content,.btn:active,
  .btn-primary:hover,.btn-dark:hover,.stat-inner .st:hover{
    transform:none!important;transition:none!important}
  /* Cards carry their own hover translate from earlier rules (and from
     page-level inline <style>, e.g. .pj-card). The tilt engine bails out
     entirely under reduce-motion, so those cards never get .tilt3d and the
     rule above can't reach them — flatten them by name so "reduce motion"
     means one thing everywhere. !important beats the un-flagged page rules
     regardless of their specificity or source order. */
  .icon-card,.feature-card,.mini-card,.expo-card,.office-card,.he-card,.cert,
  .str-card,.ach-card,.imprint-card,.pj-card,.pf-card,.dl-card,.blog-card{
    transform:none!important}
  .reveal{transform:translateY(20px)!important}
  .reveal.in{transform:none!important}
}

/* ── Products mega-menu ────────────────────────────────────────────── */
/* Benchmarked against the tracker majors (Array, Nextracker): products are
   chosen by sight, so the Products dropdown shows artwork and a one-line
   descriptor instead of a 236px column of names. Only the Products menu
   gets this — header.php flags it by checking whether the first child
   carries an image, so a text-only section menu is unaffected. */
.nav-drop.nav-mega{
  min-width:min(680px,88vw);padding:12px;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px;
}
/* Overrides .nav-drop a, which is display:block + nowrap. */
.nav-drop.nav-mega a.nmi{
  display:flex;align-items:center;gap:13px;padding:9px 10px;border-radius:12px;
  white-space:normal;font-weight:600;
}
.nav-drop.nav-mega a.nmi:hover{background:var(--sf-1,#f7f8fc)}
.nav-mega .nmi img{
  width:66px;height:46px;flex:none;object-fit:cover;border-radius:9px;
  background:#0c1330;box-shadow:0 4px 12px -6px rgba(8,12,28,.5);
}
.nav-mega .nmi-tx{display:block;min-width:0}
.nav-mega .nmi-tx b{display:block;font-size:.9rem;line-height:1.25;color:#1a1f33}
.nav-mega .nmi-tx span{
  display:block;margin-top:2px;font-size:.75rem;font-weight:500;line-height:1.35;
  color:var(--muted,#6b7280);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.nav-mega .nmi:hover .nmi-tx b{color:var(--orange-ink,#a05a00)}

/* In the mobile drawer the dropdown is a flat stacked list, so the grid and
   the thumbnails would only add noise and vertical scroll. */
@media(max-width:1100px){
  .nav-drop.nav-mega{display:block;min-width:0;padding:0}
  .nav-mega .nmi img{display:none}
  .nav-drop.nav-mega a.nmi{padding:9px 0}
  .nav-mega .nmi-tx b{color:rgba(255,255,255,.72);font-size:1rem;font-weight:600}
  .nav-mega .nmi-tx span{display:none}
  .nav-drop.nav-mega a.nmi:hover{background:transparent}
  .nav-mega .nmi:hover .nmi-tx b{color:var(--orange)}
}

/* The base .nav-drop centres itself on its parent link, which is right for a
   236px list but pushes the ~680px mega-menu off the left edge of the screen
   (Products sits well left of centre). Anchor the wide one to the item's left
   edge instead so it always opens into the page. */
.nav-drop.nav-mega{left:0;transform:translateX(0) translateY(14px)}
.has-drop:hover .nav-drop.nav-mega,
.nav-item.has-drop>a:focus-visible~.nav-drop.nav-mega,
.nav-drop.nav-mega:focus-within{transform:translateX(0) translateY(8px)}
@media(max-width:1100px){
  .nav-drop.nav-mega,
  .has-drop:hover .nav-drop.nav-mega,
  .has-drop:focus-within .nav-drop.nav-mega{transform:none}
}

/* Only one panel may be open at a time. Even with the :focus-visible fix above,
   a keyboard user who tabs to a section and then moves the mouse would leave
   two panels up — while the pointer is anywhere over the nav, the hovered
   section wins and the others close.

   The :not(:focus-within) on the panel is what keeps this safe: a panel that
   currently holds keyboard focus is never force-hidden, so focus can't end up
   parked on something invisible. Desktop only — below 1101px the drawer lays
   these out statically and a sticky touch :hover would collapse the accordion. */
@media(min-width:1101px){
  .nav-links:hover .nav-item.has-drop:not(:hover) .nav-drop:not(:focus-within){
    opacity:0;visibility:hidden;transform:translateX(-50%) translateY(14px)}
  .nav-links:hover .nav-item.has-drop:not(:hover) .nav-drop.nav-mega:not(:focus-within){
    transform:translateX(0) translateY(14px)}

  /* The 680px panels (About Us, Quality) sit late in the bar, so anchoring them
     to their own item pushed them past the right edge — 35px at 1280, 124px at
     1101 — and because an ancestor clips instead of scrolling, the last column's
     text was silently cut off rather than producing a scrollbar.

     These two centre on the nav bar instead of on their item: .has-wide goes
     static so the panel resolves against .nav-links, and the width is capped to
     the viewport. The narrow panels keep item-anchored positioning. */
  .nav-links{position:relative}
  .nav-item.has-wide{position:static}
  .nav-drop.nav-mega.cols-2{left:50%;right:auto;
    transform:translateX(-50%) translateY(14px);
    max-width:min(680px,calc(100vw - 32px))}
  .has-drop:hover .nav-drop.nav-mega.cols-2,
  .nav-item.has-drop>a:focus-visible~.nav-drop.nav-mega.cols-2,
  .nav-drop.nav-mega.cols-2:focus-within{transform:translateX(-50%) translateY(8px)}
  .nav-links:hover .nav-item.has-drop:not(:hover) .nav-drop.nav-mega.cols-2:not(:focus-within){
    transform:translateX(-50%) translateY(14px)}
}

/* Wide menus stay two-up; Projects/Media (2-3 links) go single column so the
   panel is sized to its content instead of leaving half of it blank. */
.nav-drop.nav-mega.cols-1{min-width:min(340px,88vw);grid-template-columns:minmax(0,1fr)}
.nav-drop.nav-mega.cols-2{min-width:min(680px,88vw);grid-template-columns:repeat(2,minmax(0,1fr))}
/* Product subtitles are short spec lines, but page descriptions run longer —
   clamp to two lines rather than truncating mid-word on one. */
.nav-mega .nmi-tx span{
  white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;text-overflow:ellipsis;
}
@media(max-width:1100px){
  .nav-drop.nav-mega.cols-1,.nav-drop.nav-mega.cols-2{min-width:0;grid-template-columns:1fr}
}

/* ═════════════════════════════════════════════════════════════════════
   DESIGN SYSTEM LAYER
   Appended last, so it settles the cascade rather than rewriting the rules
   above. Everything here was measured, not guessed: contrast ratios come
   from a real-DOM WCAG probe run across 13 routes, and the type floor from
   counting the 71 distinct font sizes this stylesheet had grown.
   Order: scales → nav lock → contrast → shared components.
   ═════════════════════════════════════════════════════════════════════ */

/* ── Scales ────────────────────────────────────────────────────────── */
:root{
  /* One 4px spacing scale. The stylesheet had 108 distinct padding values and
     36 distinct gaps, so no two components agreed on any measurement. */
  --s-1:4px;  --s-2:8px;   --s-3:12px; --s-4:16px; --s-5:20px;  --s-6:24px;
  --s-7:32px; --s-8:40px;  --s-9:48px; --s-10:64px; --s-11:80px; --s-12:96px;
  --r-pill:999px;

  /* Text-safe accent. --orange measures 2.1:1 on white, so it may fill a shape
     or paint an icon but must never BE the text. --orange-ink is the 5.2:1
     stand-in for light surfaces; --gold clears 8.9:1 on the navy. */
  --accent-on-light:var(--orange-ink);
  --accent-on-dark:var(--gold);
}

/* ── Nav locked to px ──────────────────────────────────────────────── */
/* The nav row was tuned to survive on ONE line from 1101px up, verified at
   seven widths. It sizes in rem, so raising the root would have quietly put
   it back onto two lines. Pinning to px keeps the rendered size identical to
   what was measured and decouples it from the base-size change. */
.nav-links a{font-size:clamp(12.6px,.95vw,14.3px)}
.nav-cta{font-size:clamp(12px,.9vw,13.5px)}

/* ── Contrast ──────────────────────────────────────────────────────── */
/* Every rule below is a measured AA failure on the rendered page. */

/* The active nav item was --orange on the always-white navbar: 2.11:1. */
.nav-links a.active{color:var(--accent-on-light)}
/* …except the Download pill, whose active state is dark ink on the orange
   wash that sweeps in behind it. That pairing already clears 8:1. */
.nav-links a.nav-link--download.active{color:#1a1200}

/* Small orange caps on a light surface — 2.11:1 wherever the orange is the
   text itself. The equivalents inside pages/projects.php's own <style> are
   fixed there, because a page-local block outranks this file. */
.blog-chip{color:var(--accent-on-light)}

/* ── Shared components ─────────────────────────────────────────────── */
/* .pj-stage is authored inside pages/projects.php's own <style>, but the
   homepage portfolio carousel uses the same class — so on the homepage the
   badge rendered with no styling at all: default dark text sitting on a dark
   photo, 1.12:1. The component belongs to the stylesheet, not to one page. */
.pj-stage{position:absolute;top:12px;left:12px;z-index:2;
  font-size:.78rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;
  padding:6px 11px;border-radius:var(--r-pill);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.pj-stage.completed{background:rgba(21,128,61,.94);color:#fff}
.pj-stage.upcoming{background:rgba(246,160,26,.96);color:#1a1300}

/* ── Orange discipline ─────────────────────────────────────────────── */
/* The brief was "professional, not a cheap company", and the thing working
   against it was orange used as atmosphere: every primary button sat in a
   30-50px orange halo, every icon chip glowed, the section rule glowed, and
   the navbar carried a warm hairline. Coloured shadows are the clearest
   consumer-app signal there is — light does not take on the colour of the
   object casting it.
   Orange keeps every job where it MEANS something: the primary action, the
   active nav item, the rule under a section title, the focus ring, progress,
   and the brand mark. It stops being the lighting. */

/* Primary action: real elevation in ink, plus a darker seam under the fill so
   the button still reads as a raised surface rather than a flat rectangle. */
.btn-primary,
#site-footer .btn-primary{
  box-shadow:0 1px 0 rgba(120,68,0,.32),0 2px 4px rgba(16,24,52,.10),0 8px 20px rgba(16,24,52,.12),
    inset 0 1px 0 rgba(255,255,255,.38)}
.btn-primary:hover{
  box-shadow:0 1px 0 rgba(120,68,0,.32),0 4px 10px rgba(16,24,52,.12),0 14px 32px rgba(16,24,52,.18),
    inset 0 1px 0 rgba(255,255,255,.48);
  /* was translateY(-3px) scale(1.05) + a pulse keyframe — buttons that grow and
     throb belong to app onboarding, not to a manufacturer's quote button. */
  transform:translateY(-2px) scale(1);
  animation:none}
.btn-primary:active{transform:translateY(0) scale(1)}

/* Secondary outline button: the border already carries the accent. */
.btn-line:hover{box-shadow:var(--shadow-sm)}

/* The rule under every section title — the most repeated element on the site. */
.section-title::after,
.section-title.light::after{box-shadow:none}

/* Navbar hairline goes neutral; the active underline is the accent here. */
#navbar.scrolled{border-bottom:1px solid var(--line)}

/* The Download pill's own lift, in ink rather than orange. */
.nav-links a.nav-link--download:hover,
.nav-links a.nav-link--download:focus-visible,
.nav-links a.nav-link--download.active{box-shadow:0 4px 12px rgba(16,24,52,.20)}

/* ── Muted text on dark surfaces ───────────────────────────────────── */
/* --muted is tuned for white backgrounds, where it clears 5.6:1. The footer
   tagline, the dark section intros and the CTA band all reuse .muted on navy,
   where the same grey collapses to 3.4:1 — the footer sentence about the
   company was effectively unreadable. This is the dark-surface equivalent,
   at 8.7:1 on --navy. (A contrast probe misses these: the surfaces paint a
   gradient, so there is no flat colour to resolve them against.) */
#site-footer .muted,
#site-footer .rich-text,
.section.dark .muted,
.cta-band .muted,
.cta-band p,
.stat-band .muted{color:#a8b0c0}

/* ── Photo rules the rest of the site already follows ──────────────── */
/* The product accordion still had two zoom effects stacked on it: a resting
   scale(1.06) on every panel photo plus a 7s Ken-Burns push to scale(1.13) on
   the open one. The open product was therefore never shown whole — it was a
   permanently magnified crop that kept magnifying. The panel is a true
   background layer under a scrim, so `cover` is legitimate here; the zoom
   is not. */
.pa-img,
.pa-panel.on .pa-img,
.pa-panel.on:hover .pa-img{animation:none;transform:none}

/* Six of the seven products were 62px slivers — at that width a cover crop
   lands on one uniform region of the photograph, so panels rendered as flat
   washes of teal or grey and communicated nothing. Every collapsed panel now
   holds a readable minimum, and the open one takes a smaller share so the
   other six have room. */
.pa-panel{min-width:104px;border-radius:var(--r)}
.pa-panel.on{flex-grow:3.2}

/* ── Portfolio carousel ────────────────────────────────────────────── */
/* The fixed 360px card left a ~28px strip of the next card showing, and the
   strip cut through the title overlay — so the peek rendered as a column of
   half-letters ("50MW RAGHUVIR GR") that reads as a rendering fault. Four
   cards now divide the track exactly; the overlay's own 24px padding means
   any remaining sliver is photograph only. */
.pf-card{flex:0 0 calc((100% - 72px) / 4);max-width:none}
@media(max-width:1100px){ .pf-card{flex:0 0 calc((100% - 48px) / 3)} }
@media(max-width:860px){  .pf-card{flex:0 0 calc((100% - 24px) / 2)} }
@media(max-width:600px){  .pf-card{flex:0 0 calc(100% - 22px);max-width:none} }

/* MACHINES rendered as an empty rounded box — .ic-chip's mask was a bare
   rectangle with nothing in it, so it read as a failed image. And HAPPY
   CUSTOMERS and TEAM STRENGTH shared one single-person glyph, so two of six
   tiles carried the same icon. A press and a group, so all six differ. */
.ic-chip::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M4 3h16v4H4zM7 7h10v3H7zM3 20h18v1.5H3zM10 10h4v10h-4z'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M4 3h16v4H4zM7 7h10v3H7zM3 20h18v1.5H3zM10 10h4v10h-4z'/%3E%3C/svg%3E")}
.ic-team::after{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Ccircle cx='8' cy='8' r='3.4'/%3E%3Ccircle cx='17' cy='9' r='2.7'/%3E%3Cpath d='M1 20c0-3.5 3.2-5.4 7-5.4s7 1.9 7 5.4zM16 14.8c3.1.2 5.6 1.9 5.6 5.2h-4.3c0-2-.5-3.7-1.3-5.2z'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Ccircle cx='8' cy='8' r='3.4'/%3E%3Ccircle cx='17' cy='9' r='2.7'/%3E%3Cpath d='M1 20c0-3.5 3.2-5.4 7-5.4s7 1.9 7 5.4zM16 14.8c3.1.2 5.6 1.9 5.6 5.2h-4.3c0-2-.5-3.7-1.3-5.2z'/%3E%3C/svg%3E")}

/* ── Ambient orange washes ─────────────────────────────────────────── */
/* Three full-bleed orange blooms — a 600px radial behind the closing CTA, a
   30px-blurred slab beside the About photo, and one under the thank-you card.
   Together with the halos these were what made the site glow orange. The dark
   bands keep their own depth from --grad-ink; they do not need tinting. */
.cta-band::before,
.about-img::before,
.thanks-card::before{display:none}

/* ── Warranty tiles ────────────────────────────────────────────────── */
/* Five tiles carried a navy base with a low-opacity accent bloom in the corner
   (teal, blue, green, gold) and the sixth was a solid orange gradient card.
   The set therefore read as "four of a kind plus one that went wrong" rather
   than as a highlighted item. The highlight now works the way the others do —
   same navy body, its accent simply turned up — so it leads the row without
   leaving it. */
.war-tile.hl{
  background:
    radial-gradient(135% 105% at 16% 12%, rgba(246,160,26,.42) 0%, rgba(246,160,26,0) 52%),
    radial-gradient(120% 120% at 100% 108%, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 42%),
    linear-gradient(158deg, #1b2a55 0%, #0e1630 58%, #090e20 100%);
  border-color:rgba(246,160,26,.32)}

/* ── Vertical rhythm ───────────────────────────────────────────────── */
/* A 390px phone was being given 72px of section padding — the same as a
   1440px desktop, and MORE than the 64px a 980px tablet got — while having
   44% less screen height to spend. With every grid also collapsing to one
   column, that put ~144px of empty band between each pair of sections and
   made the homepage 13,031px tall on a phone against 7,885px on a laptop.
   Padding now shrinks as the screen does, which is the whole point of it. */
@media(max-width:980px){ .section{padding:56px 20px} }
@media(max-width:600px){ .section{padding:40px 18px} }

/* Two sections on the same surface, stacked, paid for their padding twice —
   which is the 151px of dead white between the homepage exhibition cards and
   the About photo, and the hole punched through the middle of About's one
   continuous band. Adjacent siblings on the same surface share the seam. */
.section:not(.dark):not(.tint) + .section:not(.dark):not(.tint){padding-top:0}

/* The closing CTA and the footer are both navy and ran together as one
   184px slab of undifferentiated dark with no seam between them. */
.cta-band + #site-footer{border-top:1px solid rgba(255,255,255,.09)}

/* ── Products listing ──────────────────────────────────────────────── */
/* The rows were `align-items:start` against the intent documented eight lines
   below them in this same file ("sit in an align-items:center grid"), so a
   tall near-square photo beside a shorter text column left 223-409px of white
   under every block — on AgriChase the Learn More button was followed by
   409px of nothing while the photo carried on. Centring the row splits that
   difference above and below, where it reads as editorial spacing, and a
   slightly narrower photo track stops a square image dictating the height. */
.prod-showcase{align-items:center;grid-template-columns:minmax(0,.88fr) minmax(0,1.12fr)}
/* .flip moves the photo to the right-hand column but the track widths stayed
   put, so the photo was 563px wide on one row and 717px on the next — the two
   sides of the page never matched. Mirroring the tracks keeps the photo on the
   narrow one whichever side it sits. */
.prod-showcase.flip{grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr)}
/* Re-stated after the two rules above: they are unconditional and declared
   later than the ≤980px block near .prod-showcase's own definition, so without
   this the listing stayed two columns on phones. */
@media(max-width:980px){
  .prod-showcase,.prod-showcase.flip{grid-template-columns:1fr}
}

/* Spec rows drew a full-width dashed rule under a phrase that stopped at
   246-530px, so each line was a short label trailed by ~1000px of naked
   dotted line, and the values started at seven different x-positions. Two
   columns of aligned label/value pairs — the same shape .spec li already
   uses ten lines above. Airavat's 16 rows become 8x2. */
.rich-text .ds-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:56px;max-width:1120px}
.rich-text .ds-list li{display:grid;grid-template-columns:minmax(0,42%) minmax(0,1fr);
  gap:10px;align-items:baseline}
.rich-text .ds-list li strong{margin-right:0}
@media(max-width:900px){ .rich-text .ds-list{grid-template-columns:minmax(0,1fr)} }

/* auto-fit resolved to five columns at 1440px, so a six-product "More
   Products" grid stranded one card alone in row two with four empty slots
   beside it — on every product page. Six divides by three. */
.mini-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
@media(max-width:900px){ .mini-grid{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media(max-width:600px){ .mini-grid{grid-template-columns:minmax(0,1fr)} }

/* ── Interface icons ───────────────────────────────────────────────── */
/* Inline SVG from ui_icon(). Sized in em and painted in currentColor, so an
   icon always matches the text it sits beside — which is the whole reason for
   replacing the OS emoji that used to hold these positions. */
.ui-ic{width:1.05em;height:1.05em;flex:none;display:inline-block;
  vertical-align:-.16em;margin-right:.45em;opacity:.85}
a .ui-ic,.map-link .ui-ic{opacity:1}
.office-card .ui-ic,.pj-loc .ui-ic,.pf-loc .ui-ic,.he-venue .ui-ic,.job-loc .ui-ic{color:var(--orange-ink)}
.section.dark .ui-ic,#site-footer .ui-ic,.hero .ui-ic,.pf-overlay .ui-ic{color:var(--gold)}

/* The office chip holds a real building mark now rather than an emoji. */
.office-card .oic{display:grid;place-items:center}
.office-card .oic .ui-ic{width:22px;height:22px;margin:0;opacity:1;color:var(--gold)}

/* Impressum section markers are numbers now — set them as figures, on the
   same navy chip the rest of the site uses, without the orange halo. */
.imprint-card .imc{background:linear-gradient(160deg,#1a2348,#0c1330);color:var(--gold);
  font-family:'Sora',sans-serif;font-weight:800;font-size:1.15rem;box-shadow:none;
  display:grid;place-items:center;font-variant-numeric:tabular-nums}

/* ── Card bottoms line up, whatever shape the photo is ─────────────── */
/* Now that every picture keeps its own aspect-ratio, photo heights inside a
   row differ — which is correct, but it left the product names sitting at
   six different heights across the More Products grid. The grid stretches its
   cards to a common height and the label is pushed to the bottom of each, so
   the eye reads one straight line of names even though the pictures above
   them are not the same shape. Same treatment for the strength/quality
   cards, which share this shell. */
.mini-grid,.str-grid{align-items:stretch}
.mini-card,.str-card{display:flex;flex-direction:column}
.mini-card span,.mini-card figcaption{margin-top:auto}
.str-card-body{margin-top:auto}

/* ── Portfolio card with no photograph ─────────────────────────────── */
/* Same branded placeholder the Projects grid uses, so a card never borrows an
   unrelated site's photo to fill itself. The card's own bottom scrim would
   darken the artwork it is meant to sit on, so it is dropped here — the
   placeholder ships its own contrast. */
.pf-card--ph .proj-ph{position:absolute;inset:0;width:100%;height:100%;border-radius:inherit}
.pf-card--ph::after{display:none}
.pf-card--ph .pf-overlay{background:linear-gradient(180deg,rgba(8,12,28,0) 0%,rgba(8,12,28,.86) 62%)}
