/* ============================================================================
   SANSAN GARMENT & TEXTILE — shared stylesheet (Direction D)
   Brand: Water Blue #325e89 · Gold #ca942f · Navy #16324c
   Type: Gotham (primary) -> Montserrat fallback -> system.
   Content: Sansan Company Profile 2026. Styling: Sansan Brand Guidelines 2024.
   ============================================================================ */
:root{
  --blue:#325e89; --blue-l:#4a77a6; --gold:#ca942f; --navy:#16324c; --navy-2:#1e3a5f;
  /* Gold comes in three values because one cannot serve every background.
     --gold       the brand colour. Logo, borders, glows, accents — anything that is
                  NOT words. Unchanged, and it is what the brand guidelines specify.
     --gold-text  gold WORDS on a light background. #ca942f measures only 2.5-2.7:1
                  there, which fails the 4.5:1 needed for small text; this is 4.81:1
                  on the page and 4.60:1 on the tinted panels.
     --gold-dark  gold WORDS on the dark navy panel. Darkening would make that case
                  WORSE, so it goes the other way. #feba3b cleared desktop but landed at 4.02-4.41
     on the tighter mobile panel, so it is lifted to #fecd72 for margin.
     CSS has color-contrast() for choosing this automatically, but browser support is
     still not dependable, so the choice is made explicitly here. */
  --gold-text:#916a21; --gold-dark:#fecd72;
  /* --gold-ink is what gold TEXT actually uses. It defaults to the light-background
     value and is RE-DECLARED on dark surfaces below. Custom properties inherit, so
     anything inside a dark panel picks the right value automatically — no per-element
     overrides, and no specificity fights when a component moves between contexts.
     This is the closest CSS gets to choosing the colour for you today;
     color-contrast() would do it natively but is not dependably supported yet. */
  --gold-ink:var(--gold-text);
  --ink:#1c2733; --muted:#65707b; --line:#e8ebef; --bg:#fdfdfc; --soft:#f6f8fb;
  /* --muted was #68747f: 4.70:1 on the page but 4.49:1 on the tinted panels, i.e.
     one hundredth under the 4.5 needed for body text. Three shades darker clears
     both (4.96 / 4.75) and is not perceptibly different. */
  --font:"Gotham","Montserrat",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{font-family:var(--font);color:var(--ink);background:var(--bg);line-height:1.68;font-weight:400;-webkit-font-smoothing:antialiased}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
.wrap{max-width:1200px;margin:0 auto;padding:0 36px}

/* ---------- responsive safety net — never bleed past the viewport, never hard-lock a width ---------- */
html{overflow-x:clip}                 /* clips any horizontal overflow to the screen edge; keeps the sticky header working */
body{overflow-wrap:break-word}        /* long words / emails / URLs wrap instead of widening the page on phones */
img,svg,video,iframe,canvas,table{max-width:100%}
/* let grid/flex children shrink below their content so one long word can't blow a column past the row */
.net .r>*,.job>*,.step>*,.fgrid>*,.contact-grid>*,.form .row>*,.impact .grid>*,.stories>*,.comp>*,.dept>*,.pillars>*,.segments>*,.cgrid>*,.mgrid>*,.ostrip>*{min-width:0}

/* ---------- shared type ---------- */
.eyebrow{font-size:.72rem;letter-spacing:.26em;text-transform:uppercase;color:var(--gold-ink);font-weight:600}
h1,h2,h3,h4{color:var(--navy)}
h2{font-weight:300;font-size:clamp(1.9rem,3.6vw,2.9rem);line-height:1.12;letter-spacing:-.015em}
h2 b{font-weight:700}
.lead{color:var(--muted);font-weight:300;font-size:1.08rem;max-width:56ch}
.head{max-width:680px;margin-bottom:8px}
.center{text-align:center;margin-inline:auto}

/* ---------- buttons & links ---------- */
.btn{display:inline-flex;align-items:center;gap:.5rem;font-weight:600;font-size:.9rem;padding:.8rem 1.5rem;border-radius:999px;transition:.2s;cursor:pointer;border:1px solid transparent}
.btn-blue{background:var(--blue);color:#fff}.btn-blue:hover{background:var(--navy)}
.btn-line{border-color:var(--line);color:var(--ink)}.btn-line:hover{border-color:var(--blue);color:var(--blue)}
.btn-ghost{border-color:rgba(255,255,255,.55);color:#fff}.btn-ghost:hover{background:rgba(255,255,255,.12)}
.link{font-weight:600;font-size:.86rem;letter-spacing:.03em;color:var(--blue);display:inline-flex;align-items:center;gap:6px}
.link:hover{gap:10px}

/* ---------- motion ---------- */
.reveal{opacity:0;transform:translateY(26px);transition:.9s cubic-bezier(.2,.7,.2,1)}
.reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}

/* ---------- photo placeholder ---------- */
.ph{position:relative;overflow:hidden;background:linear-gradient(140deg,#eef2f6,#dde5ec);border-radius:16px;display:flex;align-items:flex-end;color:#fff}
.ph .tag{position:relative;z-index:2;padding:20px;font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;background:linear-gradient(transparent,rgba(22,50,76,.6));width:100%}
.ph.plain{align-items:center;justify-content:center;color:#a7b4c2;font-size:.66rem;letter-spacing:.16em;text-transform:uppercase}
.ph.plain svg{width:22px;height:22px;opacity:.6;margin-right:8px}

/* ---------- header ---------- */
header{position:sticky;top:0;z-index:50;background:rgba(253,253,252,.88);backdrop-filter:blur(14px);border-bottom:1px solid var(--line)}
.nav{display:flex;align-items:center;justify-content:space-between;height:80px}
.brand{display:flex;align-items:center;gap:12px;font-weight:900;font-size:1.12rem;letter-spacing:.02em;color:var(--navy)}
.brand svg{width:40px;height:40px}
.brand small{display:block;font-size:.54rem;letter-spacing:.18em;color:var(--gold-ink);font-weight:700}
.menu{display:flex;align-items:center;gap:30px;font-size:.86rem;font-weight:600;color:var(--ink)}
.menu a{position:relative;padding:6px 0}
.menu a:hover{color:var(--blue)}
.menu a.active{color:var(--blue)}
.menu a.active::after{content:"";position:absolute;left:0;right:0;bottom:-2px;height:2px;background:var(--gold)}
.navcta{display:flex;align-items:center;gap:18px}
.lang{font-size:.72rem;letter-spacing:.1em;color:var(--muted);display:inline-flex;align-items:center;gap:6px;font-weight:600}
.lang a{color:var(--muted);padding:2px 1px}
.lang a:hover{color:var(--blue)}
.lang a.on{color:var(--navy);border-bottom:2px solid var(--gold);padding-bottom:1px}
.lang-sep{opacity:.4;font-weight:300}
.lang-mobile{display:none}          /* only ever shown inside the hamburger */
.burger{display:none;background:none;border:0;font-size:1.5rem;color:var(--navy);cursor:pointer}

/* ---------- full-bleed home hero ---------- */
.hero{position:relative;min-height:90vh;display:flex;align-items:center;overflow:hidden;border-bottom:1px solid var(--line)}
.hero .bg{position:absolute;inset:0;z-index:0;background:linear-gradient(140deg,#e3e9ef 0%,#c8d3de 55%,#aebccb 100%)}
.hero .bg .bgvid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  opacity:0;transition:opacity .9s ease}
/* The poster and the video's first frame are different pictures, so the handover was a
   hard cut. Fading in over ~1s hides the swap; app.js adds .on once a frame is ready. */
.hero .bg .bgvid.on{opacity:1}
@media(prefers-reduced-motion:reduce){.hero .bg .bgvid{display:none}} /* fall back to the poster photo */
@media(max-width:980px){.hero .bg .bgvid{display:none}}                /* phones keep the poster */
/* HOME HERO — light wash over the photograph, navy type. Deliberately NOT darkened:
   a heavy overlay makes a busy factory interior look dim rather than dramatic, and
   the readability this hero needs comes from the CHOICE OF PHOTO. See the brief in
   LAUNCH-DAY.md before replacing the image.
   The wash is fitted to the TEXT, not the window: .hero is flex, so the ~690px text
   column sits centred and spans 50% ± 310px at every desktop width. Strong (.88) only
   under that column, .50 at the far left, clear from 50%+800px. Both ramps are
   SMOOTHSTEP curves sampled in 70px steps — a plain linear ramp leaves a visible
   seam where it kinks into the flat part, which the user saw as a hard white edge.
   The old %-based ramp (.98 → clear at 90%) blanked most of the video. Measured over
   a video frame at 1024-1920: eyebrow ≥ 4.98:1, body text ≥ 9.6:1. */
.hero .scrim{position:absolute;inset:0;z-index:1;background:linear-gradient(90deg,rgba(253,253,252,.5) 0,rgba(253,253,252,0.5) calc(50% - 760px),rgba(253,253,252,0.528) calc(50% - 690px),rgba(253,253,252,0.599) calc(50% - 620px),rgba(253,253,252,0.69) calc(50% - 550px),rgba(253,253,252,0.781) calc(50% - 480px),rgba(253,253,252,0.852) calc(50% - 410px),rgba(253,253,252,0.88) calc(50% - 340px),rgba(253,253,252,0.88) calc(50% + 240px),rgba(253,253,252,0.842) calc(50% + 310px),rgba(253,253,252,0.743) calc(50% + 380px),rgba(253,253,252,0.602) calc(50% + 450px),rgba(253,253,252,0.44) calc(50% + 520px),rgba(253,253,252,0.278) calc(50% + 590px),rgba(253,253,252,0.138) calc(50% + 660px),rgba(253,253,252,0.038) calc(50% + 730px),rgba(253,253,252,0) calc(50% + 800px))}
/* The eyebrow stays GOLD but needs its own, deeper value. Brand gold #ca942f tops out
   at 2.70:1 against pure WHITE, so neither a photo nor a scrim can ever make it pass
   here. Even --gold-text (#916a21) only reached 4.14:1 desktop / 3.66:1 phone, because
   the light wash lets some photograph through. #7c571a clears both (5.48 / 4.85) with
   enough margin left over for a different hero image later. It is the one place on the
   homepage that cannot carry the brand value. */
.hero .eyebrow{color:#7c571a}
.hero .wrap{position:relative;z-index:2;padding-top:70px;padding-bottom:70px}
.hero .inner{max-width:620px}
.hero .story{font-weight:300;font-size:1.1rem;color:var(--muted);font-style:italic;margin:20px 0 8px}
.hero h1{font-weight:200;font-size:clamp(2.7rem,6vw,5rem);line-height:1.02;letter-spacing:-.025em;color:var(--navy)}
.hero h1 b{font-weight:700}
.hero p.sub{margin:26px 0 32px;max-width:46ch;color:var(--muted);font-weight:300;font-size:1.08rem}
.hero .cta{display:flex;gap:14px;flex-wrap:wrap}
.hero .segrow{display:flex;gap:26px;margin-top:44px;flex-wrap:wrap}
.hero .segrow a{font-size:.8rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600;color:var(--muted);border-top:2px solid var(--gold);padding-top:10px}
.hero .segrow a:hover{color:var(--blue)}

/* ---------- inner-page hero ---------- */
.phero{position:relative;overflow:hidden;border-bottom:1px solid var(--line);background:linear-gradient(140deg,#e3e9ef,#c8d3de)}
.phero .scrim{position:absolute;inset:0;background:linear-gradient(100deg,rgba(253,253,252,.96) 0%,rgba(253,253,252,.92) 45%,rgba(253,253,252,.80) 62%,rgba(253,253,252,.45) 78%,rgba(253,253,252,0) 94%)}
.phero .wrap{position:relative;z-index:2;padding:84px 36px 70px}
.phero .crumb{font-size:.74rem;letter-spacing:.08em;color:var(--muted);margin-bottom:18px}
.phero .crumb a:hover{color:var(--blue)}
.phero h1{font-weight:200;font-size:clamp(2.3rem,5vw,3.9rem);line-height:1.05;letter-spacing:-.02em;color:var(--navy)}
.phero h1 b{font-weight:700}
.phero p{margin-top:20px;max-width:52ch;color:var(--muted);font-weight:300;font-size:1.08rem}
/* Page-hero small text sits over a photograph at every width. --muted is tuned for a
   white page and measured 1.9-3.3:1 here; gold is worse still (tested 1.2-2.3:1).
   These are the INNER pages, which keep their light scrim — the home hero went dark
   instead, see "HOME HERO" below. */
.phero .crumb,.phero .crumb a,.phero .eyebrow,.phero .wrap > p,
.hero .story,.hero p.sub{color:var(--ink)}

/* ---------- sections ---------- */
.sec{padding:104px 0}
.sec.soft{background:var(--soft);border-block:1px solid var(--line)}
.sec.tight{padding:72px 0}

/* ---------- impact dashboard ---------- */
.impact{background:linear-gradient(180deg,var(--soft),#fff);border-block:1px solid var(--line);padding:46px 0}
.impact .grid{display:grid;grid-template-columns:repeat(6,1fr);gap:18px}
.impact .m{text-align:center}
.impact .m .ic{width:44px;height:44px;margin:0 auto 14px;border-radius:12px;background:#fff;border:1px solid var(--line);display:flex;align-items:center;justify-content:center;color:var(--blue)}
.impact .m b{display:block;font-weight:700;font-size:2.4rem;color:var(--gold-ink);line-height:1}
.impact .m b i{font-style:normal}
.impact .m span{font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}

/* ---------- three pillars ---------- */
.pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:40px;margin-top:44px}
.pillars .p{padding:0}
.pillars .p:last-child{padding-right:0}
.pillars .p .ic{width:40px;height:40px;color:var(--blue);margin-bottom:18px}
.pillars .p h3{font-weight:600;font-size:1.1rem;color:var(--navy);margin-bottom:8px}
.pillars .p p{font-size:.92rem;color:var(--muted);font-weight:300}

/* ---------- segments (garment/textile) ---------- */
.segments{display:grid;grid-template-columns:1fr 1fr;gap:26px;margin-top:52px}
.seg{position:relative;border-radius:22px;overflow:hidden;min-height:380px;display:flex;flex-direction:column;justify-content:flex-end;color:#fff;background:linear-gradient(165deg,#3a6390,var(--navy))}
.seg.textile{background:linear-gradient(165deg,#c99a3e,#9a6f1e)}
.seg .ph2{position:absolute;inset:0;background:linear-gradient(160deg,rgba(255,255,255,.06),rgba(0,0,0,.15))}
.seg .body{position:relative;z-index:2;padding:42px}
.seg .lbl{font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;opacity:.85;font-weight:600}
.seg h3{font-weight:200;font-size:2.6rem;margin:8px 0 14px;letter-spacing:-.01em;color:#fff}
.seg .cap{font-size:2rem;font-weight:700;display:block;margin-bottom:4px}
.seg p{font-weight:300;opacity:.92;font-size:.95rem;max-width:38ch;margin-bottom:22px;min-height:4.8em}/* reserve equal space so both cards' rows line up */
.seg .link{color:#fff}.seg .link:hover{color:#fff}

/* ---------- network list ---------- */
.net{margin-top:52px;border-top:1px solid var(--line)}
/* Capacity gets a full 1fr: it now carries "800,000" plus its unit on one line. */
.net .r{display:grid;grid-template-columns:1fr 1.1fr .5fr 1fr 1.4fr;gap:18px;align-items:center;padding:24px 0;border-bottom:1px solid var(--line)}
.net .r:hover{background:var(--soft)}
.net .r .u{font-weight:700;letter-spacing:.04em;color:var(--blue);font-size:1rem}
.net .r .loc{color:var(--muted);font-size:.9rem;font-weight:300}
/* Lines and Capacity share one treatment — big light figure, small muted unit beside it
   (baseline-aligned, with enough gap that the unit reads as a label rather than a digit). */
.net .r .ln,.net .r .cp{display:flex;align-items:baseline;gap:10px}
.net .r .ln .n,.net .r .cp .n{font-weight:200;font-size:1.8rem;line-height:1;color:var(--navy)}
/* Each figure sits in a fixed-width box, left-aligned so every number starts flush under its
   column header, while the fixed box width keeps the unit labels lined up down the column.
   The gap between a number and its unit therefore varies with the number's length — that is
   the cost of aligning both edges at once; right-aligning the figure would trade the other way.
   Widths are in em (they scale with the smaller figure at ≤1200px) and are sized to the
   longest value: "800,000" measures 3.89em, "17" 1.24em. NOT ch — ch is the width of "0",
   which does not account for the comma. And NOT tabular-nums: it widened "800,000" from
   112px to 137px and overflowed the column. */
.net .r .ln .n,.net .r .cp .n{flex:0 0 auto;text-align:left}
.net .r .ln .n{min-width:1.35em}
.net .r .cp .n{min-width:4.45em}   /* widest measured figure is 4.375em — must exceed it, or that row alone pushes its unit right */
/* Lighter via WEIGHT and letter-spacing, not opacity. These labels carry meaning ("lines",
   "/ month"), and at .66rem they are small text, so they need 4.5:1. --muted on --bg is only
   4.70:1 to begin with — the old opacity:.75 dropped them to 2.95:1, i.e. failing. Fading
   them further is not available; a lighter stroke and more air give the same impression. */
.net .r .unit{font-size:.66rem;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);font-weight:400;white-space:nowrap}
/* "800,000 / MONTH" is the widest cell; between ~1000 and 1200px it outgrew its column and
   pushed into Categories. Give that column more of the row and ease the figure down a step. */
@media(max-width:1200px){
  .net .r{grid-template-columns:.95fr 1fr .5fr 1.15fr 1.25fr;gap:14px}
  .net .r .ln .n,.net .r .cp .n{font-size:1.6rem}
  .net .r .ln,.net .r .cp{gap:8px}
}
.net .r .mn{font-size:.9rem;color:var(--muted);font-weight:400}
.net .r .cat{color:var(--muted);font-size:.85rem;font-weight:300}
.net .r.h{padding:14px 0}
.net .r.h div{font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:600}

/* ---------- overview stat strip ---------- */
.ostrip{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:22px;margin-top:8px}
.ostat{background:#fff;border:1px solid var(--line);border-radius:16px;padding:26px}
.ostat b{display:block;font-weight:700;font-size:2.6rem;color:var(--gold-ink);line-height:1}
.ostat b i{font-style:normal}
.ostat span{font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}

/* ---------- category / capability grid ---------- */
.cgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:44px}
/* auto-fit, not a hard 3, so adding a 4th technology card doesn't leave an orphan on its own row */
.cgrid.three{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.ccard{background:#fff;border:1px solid var(--line);border-radius:14px;padding:24px;transition:.2s}
.ccard:hover{border-color:#d4e0ee;box-shadow:0 20px 40px -30px rgba(27,58,91,.5);transform:translateY(-4px)}
.ccard .ic{width:38px;height:38px;border-radius:10px;background:#eaf1f8;color:var(--blue);display:flex;align-items:center;justify-content:center;margin-bottom:16px}
.ccard h3{font-weight:600;font-size:1.02rem;color:var(--navy);margin-bottom:6px}
.ccard p{font-size:.88rem;color:var(--muted);font-weight:300}

/* ---------- process steps (textile) ---------- */
.steps{margin-top:48px;border-top:1px solid var(--line)}
.step{display:grid;grid-template-columns:60px 1fr auto;gap:28px;align-items:center;padding:26px 0;border-bottom:1px solid var(--line)}
.step .n{font-weight:200;font-size:1.6rem;color:var(--gold-ink)}
.step .t h3{font-weight:600;font-size:1.1rem;color:var(--navy)}
.step .t p{font-size:.9rem;color:var(--muted);font-weight:300}
.step .cap{font-weight:200;font-size:1.5rem;color:var(--navy);white-space:nowrap}
.step .cap small{display:block;font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600}

/* ---------- machinery grid ---------- */
.mgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:44px}
.mcard{border-radius:16px;overflow:hidden;border:1px solid var(--line);background:#fff}
.mcard .ph{height:180px;border-radius:0}
.mcard .b{padding:20px}
.mcard h3{font-weight:600;font-size:1rem;color:var(--navy)}
.mcard p{font-size:.85rem;color:var(--muted);font-weight:300;margin-top:4px}

/* ---------- timeline ---------- */
/* The journey strip holds still in the middle of the screen while it sweeps sideways.
   Pinning is OPT-IN via the .on class, which app.js adds only when it actually applies —
   so with JS off, on phones (where the strip is a vertical list) or under reduced-motion,
   this stays an ordinary horizontally-scrollable strip in normal flow. The track height
   and the sticky offset are set inline by app.js, measured from the real content. */
.tl-track.on{position:relative}
.tl-track.on .tl-stick{position:sticky}
.timeline{display:flex;gap:0;overflow-x:auto;padding:36px 0 12px;margin-top:24px;scroll-behavior:auto}
/* the strip is driven by scroll position, so hide its scrollbar while pinned */
.tl-track.on .timeline{scrollbar-width:none}
.tl-track.on .timeline::-webkit-scrollbar{display:none}
.tl-item{flex:none;width:210px;position:relative;padding:0 16px}
.tl-item::before{content:"";position:absolute;top:8px;left:0;right:0;height:2px;background:var(--line)}
.tl-item .dot{width:15px;height:15px;border-radius:50%;background:var(--gold);border:3px solid #fff;box-shadow:0 0 0 2px var(--gold);position:relative;z-index:2;margin-bottom:18px}
.tl-item .yr{font-weight:200;font-size:1.5rem;color:var(--navy)}
.tl-item .ev{font-size:.85rem;color:var(--muted);font-weight:300}

/* ---------- department grid ---------- */
.dept{display:grid;grid-template-columns:repeat(5,1fr);gap:16px;margin-top:44px}
.dept .d{background:#fff;border:1px solid var(--line);border-radius:14px;padding:24px 14px;display:flex;flex-direction:column;align-items:center;gap:12px;text-align:center;transition:.2s}
.dept .d:hover{border-color:var(--blue);box-shadow:0 16px 32px -22px rgba(27,58,91,.45);transform:translateY(-2px)}
.dept .d .ic{width:46px;height:46px;padding:12px;color:var(--blue);background:#eef4fa;border-radius:50%;box-sizing:border-box;flex:none}
.dept .d span{font-size:.82rem;font-weight:600;color:var(--navy);line-height:1.35}

/* ---------- sustainability band ---------- */
.sus{background:linear-gradient(160deg,#2b5177,var(--navy));border-radius:24px;padding:70px;color:#fff;position:relative;overflow:hidden}
.sus .in{display:grid;grid-template-columns:auto 1fr;gap:66px;align-items:center;position:relative;z-index:2}
.sus .big{font-weight:200;font-size:7rem;line-height:.85;color:#fff}
/* company profile PDF download (Contact page, between the enquiry card and the map) */
.ct-pdf{margin-top:56px}
/* card → map gap matches the VISIBLE gap above the card (enquiry-card outline → card = 56px margin + ~16px
   the enquiry card ends short of the info column), measured 71-74px on desktop */
.ct-pdf + .map iframe{margin-top:72px}
.pdfbox{display:flex;align-items:center;gap:26px;background:var(--soft);border:1px solid var(--line);border-radius:18px;padding:30px 34px}
.pdfbox .pdfico{flex:0 0 auto;width:52px;height:52px;border-radius:14px;background:#fff;border:1px solid var(--line);display:flex;align-items:center;justify-content:center;color:var(--blue)}
.pdfbox .pdfico svg{width:26px;height:26px}
.pdfbox .pdftxt{flex:1 1 auto;min-width:0}
.pdfbox h3{font-weight:600;font-size:1.05rem;color:var(--navy)}
.pdfbox p{font-size:.92rem;color:var(--muted);font-weight:300;margin-top:5px}
.pdfbox .btn{flex:0 0 auto;white-space:nowrap}
@media(max-width:820px){.pdfbox{flex-direction:column;align-items:flex-start;gap:18px;padding:26px 22px}}

/* standards pills on the dark panel — only rendered when the field has content */
.suschips{display:flex;flex-wrap:wrap;gap:9px;margin:24px 0 26px}
.suschips span{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.22);border-radius:999px;padding:7px 15px;font-size:.82rem;font-weight:500;color:#eaf1f8}
.sus .big i{font-style:normal;color:var(--gold-ink);font-weight:600}
.sus .big small{display:block;font-size:.82rem;letter-spacing:.16em;text-transform:uppercase;color:#cdd8e4;font-weight:600;margin-top:14px}
.sus .cs{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:24px}
.sus .cs .c b{color:var(--gold-ink);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;display:block;margin-bottom:4px}
.sus .cs .c span{color:#dbe4ee;font-size:.9rem;font-weight:300}
/* Dark surfaces: gold WORDS go lighter, not darker. .sus is the navy gradient panel,
   .seg the dark segment cards, .ctaband the closing gradient band, footer the navy
   foot. Darkening on these would move contrast the wrong way. */
/* Dark surfaces: re-declare the token and every descendant follows. */
.sus,.ctaband,footer,.impact.on-dark{--gold-ink:var(--gold-dark)}
.seg{--gold-ink:#fff}   /* the seg cards are a lighter blue; no gold clears 4.5 there */
/* Homepage keeps the full brand gold on its light sections — a deliberate choice to
   lead with the brand colour on the page everyone lands on first. It reads 2.5-2.9:1,
   below AA, so it is confined to the eyebrows, the impact numbers and the buyer-region
   headings: short labels that repeat as real text elsewhere, never body copy and never
   the only carrier of a message. Inner pages stay on --gold-text. The dark panels are
   restated below because body.home outranks the plain .sus/.ctaband/footer selectors. */
body.home{--gold-ink:var(--gold)}
body.home .sus,body.home .ctaband,body.home footer,body.home .impact.on-dark{--gold-ink:var(--gold-dark)}
body.home .seg{--gold-ink:#fff}
/* The .seg cards sit on a lighter blue (#3a6390) than the .sus panel, and no gold
   pale enough to clear 4.5:1 there still reads as gold — the ramp tops out at 4.38.
   Those cards are already set in white type, so the eyebrow simply joins it. */
.sus .glow{position:absolute;width:420px;height:420px;border-radius:50%;background:rgba(202,148,47,.25);filter:blur(90px);right:-80px;top:-120px}

/* ---------- compliance pillars (sustainability page) ---------- */
.comp{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;margin-top:44px}
.comp .c{background:#fff;border:1px solid var(--line);border-radius:16px;padding:30px}
.comp .c h3{font-weight:600;font-size:1.15rem;color:var(--navy)}
.comp .c .certs{color:var(--gold-ink);font-size:.74rem;letter-spacing:.08em;text-transform:uppercase;font-weight:600;margin:8px 0 12px}
.comp .c p{font-size:.92rem;color:var(--muted);font-weight:300}
.comp .c .certlogos{display:flex;flex-wrap:wrap;gap:16px;align-items:center;margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.comp .c .certlogos img{height:42px;width:auto;max-width:120px;object-fit:contain;display:block;filter:grayscale(1);opacity:.7;transition:.2s}
.comp .c .certlogos a:hover img,.comp .c .certlogos span:hover img{filter:none;opacity:1}

/* ---------- brands ---------- */
/* buyer logo wall, grouped by continent */
.buyers-group{margin-top:44px}
.buyers-group h4{font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--gold-ink);font-weight:600;margin-bottom:22px;display:inline-block;border-bottom:1px solid var(--gold);padding-bottom:8px}
.buyers-logos{display:flex;flex-wrap:wrap;gap:26px 40px;align-items:center;justify-content:center}
.buyers-logos img{height:46px;width:auto;max-width:150px;object-fit:contain;display:block;filter:grayscale(1);opacity:.62;transition:.2s}
.buyers-logos a:hover img,.buyers-logos span:hover img{filter:none;opacity:1}

.brands{columns:4;column-gap:34px;margin-top:48px}
.brands .g{break-inside:avoid;margin-bottom:28px}
.brands h4{font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--blue);padding-bottom:12px;border-bottom:1px solid var(--gold);margin-bottom:14px}
.brands p{font-size:.9rem;font-weight:300;color:var(--ink);line-height:2}

/* ---------- stories ---------- */
.stories{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;margin-top:48px}
.story-card .ph{height:200px;margin-bottom:18px}
.story-card .k{font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-ink);font-weight:600;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/* Published date sits beside the category. Muted and un-spaced so it reads as
   metadata rather than competing with the gold category label. --muted on --bg
   is 4.70:1, which passes AA — do not lighten it further. */
.story-card .k-date{color:var(--muted);font-weight:400;letter-spacing:.04em;text-transform:none}
.story-card .k-date::before{content:"·";margin-right:8px;opacity:.5}
.story-card h3{font-weight:400;font-size:1.15rem;color:var(--navy);margin:8px 0 6px;letter-spacing:-.01em}
.story-card p{font-size:.9rem;color:var(--muted);font-weight:300}

/* ---------- careers ---------- */
.jobs{margin-top:44px;border-top:1px solid var(--line)}
.job{display:grid;grid-template-columns:1.6fr 1.3fr .9fr auto;gap:18px;align-items:center;padding:22px 0;border-bottom:1px solid var(--line)}
.job .jrole{font-weight:600;font-size:1.05rem;color:var(--navy)}
.job .jloc{font-size:.9rem;color:var(--muted);font-weight:300}
.job .jtype{font-size:.74rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600}
.job .jbtn{padding:.55rem 1.1rem;white-space:nowrap}
@media(max-width:640px){
  .job{grid-template-columns:1fr auto;gap:2px 14px;padding:18px 0}
  .job .jrole{grid-column:1;grid-row:1}
  .job .jloc{grid-column:1;grid-row:2}
  .job .jtype{grid-column:1;grid-row:3;margin-top:3px}
  .job .jbtn{grid-column:2;grid-row:1 / span 3;align-self:center}
}

/* ---------- contact ---------- */
.contact-grid{display:grid;grid-template-columns:1fr 1.1fr;gap:56px;align-items:start}
.cinfo .block{padding:22px 0;border-bottom:1px solid var(--line)}
.cinfo .block:last-child{border-bottom:0}   /* a divider under the last block has nothing to divide — and it crowds the profile-PDF card below */
.cinfo .block h4{font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-ink);margin-bottom:8px}
.cinfo .block p{font-size:.95rem;color:var(--ink);font-weight:300;line-height:1.9}
.cinfo .block a:hover{color:var(--blue)}
.form{background:#fff;border:1px solid var(--line);border-radius:20px;padding:36px;box-shadow:0 24px 60px -44px rgba(27,58,91,.5)}
.form .row{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.field{margin-bottom:16px}
.field label{display:block;font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);font-weight:600;margin-bottom:7px}
.field input,.field textarea,.field select{width:100%;border:1px solid var(--line);border-radius:10px;font-family:var(--font);font-size:.95rem;color:var(--ink);background-color:var(--soft);transition:.2s}
.field input,.field select{height:50px;padding:0 14px}
.field textarea{padding:12px 14px;min-height:120px;resize:vertical}
.field select{appearance:none;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;padding-right:38px;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2368747f' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 14px center}
.field input:focus,.field textarea:focus,.field select:focus{outline:none;border-color:var(--blue);background-color:#fff}
.map .ph{height:260px;border-radius:16px;margin-top:24px}
.map iframe{width:100%;height:380px;border:0;border-radius:16px;display:block;margin-top:24px}
.cinfo .block p + p{margin-top:6px}
.field .req{color:#c0392b;font-weight:600}

/* ---------- cta band ---------- */
/* The CTA band replaces .wrap's gutter padding with its own, so it needs an explicit
   inset or the rounded gradient box runs flush to the screen edges. calc() keeps a
   consistent margin at EVERY width instead of only below a breakpoint. */
.ctaband .wrap{width:calc(100% - 72px);max-width:1128px;margin-left:auto;margin-right:auto;background:linear-gradient(130deg,var(--navy),var(--blue));border-radius:28px;padding:70px;text-align:center;color:#fff;position:relative;overflow:hidden}
.ctaband h2{color:#fff}
.ctaband p{color:#cdd8e4;margin:16px auto 28px;max-width:46ch;font-weight:300}

/* ---------- footer ---------- */
footer{background:var(--navy);color:#aebccb;padding:70px 0 32px;margin-top:20px}
.fgrid{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:36px}
footer h4{color:#fff;font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;margin-bottom:16px}
footer a,footer p{font-size:.9rem;color:#aebccb;line-height:1.95;font-weight:300}
footer a:hover{color:var(--gold)}
.fbrand{color:#fff;font-weight:900;font-size:1.15rem;letter-spacing:.02em;margin-bottom:14px}
.fbrand img{height:38px;width:auto;display:block;margin-bottom:2px}
.fbot{border-top:1px solid rgba(255,255,255,.12);margin-top:46px;padding-top:22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px;font-size:.8rem;color:#8b9cad}  /* #7f92a5 measured 4.11:1 on the navy foot */
/* footer a is .9rem; inside .fbot the link must match the .8rem line it sits on */
.fbot a{font-size:inherit;color:#93a3b4}
.fbot a:hover{color:var(--gold)}
.fsep{margin:0 8px;opacity:.5}

/* ---------- responsive ---------- */
@media(max-width:980px){
  .menu{position:absolute;top:80px;left:0;right:0;flex-direction:column;gap:0;background:#fff;border-bottom:1px solid var(--line);padding:0;max-height:0;overflow:hidden;transition:max-height .3s}
  .menu.open{max-height:80vh;overflow-y:auto}
  .menu a{padding:16px 36px;border-top:1px solid var(--line);width:100%}
  .menu a.active::after{display:none}
  /* The header bar cannot hold logo + switcher + button + burger on a phone: the
     button wrapped to two lines and at 320px the row overflowed. Move the switcher
     into the menu, where it has room and reads as a proper choice. */
  .navcta .lang{display:none}
  .lang-mobile{display:flex;justify-content:center;gap:8px;padding:18px 36px;
    border-top:1px solid var(--line);font-size:.8rem}
  /* pills, not underlines — the desktop rule draws a border-bottom, which follows
     the rounded edge and reads as a stray curve under the active language */
  /* --muted is tuned for the white page; on this panel it measured 4.16:1, so the
     unselected pill gets its own slightly darker grey */
  .lang-mobile a{padding:7px 18px;border-radius:999px;border:1px solid var(--line);
    color:#5c6672;border-bottom-width:1px}
  /* the desktop rule adds padding-bottom:1px under the active language to sit it on
     its gold underline; inside a pill that just drops the text 1px below the other one */
  .lang-mobile a.on{background:var(--navy);border-color:var(--navy);color:#fff;
    border-bottom:1px solid var(--navy);padding-bottom:7px}
  .lang-mobile .lang-sep{display:none}   /* two pills need no divider */
  .navcta .btn{white-space:nowrap}
  .burger{display:block}
  .hero{min-height:auto}
  .hero .wrap{padding-top:56px;padding-bottom:56px}
  .hero .scrim{background:linear-gradient(180deg,rgba(253,253,252,.88),rgba(253,253,252,.96))}
  /* The page-hero scrim fades LEFT-TO-RIGHT, which is right on desktop where the
     text sits in the left third — but on a narrow screen the text spans the full
     width and runs off the end of the fade onto bare photograph. Measured: worst-case
     contrast was 1.00:1 on six of seven pages, i.e. parts of the heading were exactly
     as bright as the image behind them. Switch to a vertical wash, as the home hero
     already does here. .65→.84 measured 6.4:1 worst case — comfortably past the 4.5
     AA threshold, with margin for photos that have not been shot yet, while keeping
     the picture clearly visible. */
  .phero .scrim{background:linear-gradient(180deg,rgba(253,253,252,.65),rgba(253,253,252,.84))}
  /* The scrim fixed the HEADING, but the breadcrumb, eyebrow and intro are painted in
     --muted (#68747f) — a grey chosen for a white page, where it clears AA at 4.70:1.
     Over a photograph, even a scrimmed one, the same grey measured 2.6–2.8:1: the
     heading was legible while everything around it was not. Darkening the small text
     fixes it without pushing the scrim heavier and washing the picture out. Measured
     with --ink: 7.17:1. (#3d4a57 was tried as a softer option and reached only 4.30.) */
  .hero .inner{max-width:none}
  .impact .grid{grid-template-columns:repeat(3,1fr);gap:32px 18px}
  .pillars,.segments,.stories,.contact-grid,.fgrid{grid-template-columns:1fr}
  .pillars .p{padding:0}
  .sus{padding:40px}.sus .in{grid-template-columns:1fr;gap:30px}.sus .big{font-size:4.8rem}
  .net .r{grid-template-columns:1fr 1fr;gap:8px}.net .r .cat,.net .r.h{display:none}
  .ostrip,.cgrid,.cgrid.three,.mgrid,.comp{grid-template-columns:1fr 1fr}
  .dept{grid-template-columns:repeat(2,1fr)}
  .brands{columns:2}
  .form .row{grid-template-columns:1fr}
  .ctaband .wrap{width:calc(100% - 44px);padding:48px 40px;border-radius:22px}
  .step{grid-template-columns:40px 1fr;gap:16px}.step .cap{grid-column:2;white-space:normal}
}
@media(max-width:560px){
  .impact .grid,.ostrip,.cgrid,.cgrid.three,.mgrid,.comp,.brands,.fgrid{grid-template-columns:1fr;columns:1}
  .dept{grid-template-columns:1fr 1fr}
  .phero .wrap,.sec{padding-left:0;padding-right:0}
  .phero .wrap{padding-left:0}
}

/* ---------- article / prose (News, single posts, generic pages) ---------- */
.prose{max-width:760px;margin:0 auto;font-weight:300;color:var(--ink);font-size:1.06rem}
.prose h2{font-weight:400;margin:2em 0 .5em}
.prose h3{font-weight:600;margin:1.6em 0 .4em;color:var(--navy)}
.prose p{margin:0 0 1.2em}
.prose a{color:var(--blue);text-decoration:underline}
.prose img{border-radius:14px;margin:1.6em 0}
.prose ul,.prose ol{margin:0 0 1.2em 1.4em}
.prose li{margin:.4em 0}
.prose blockquote{border-left:3px solid var(--gold);padding-left:20px;margin:1.4em 0;color:var(--muted);font-style:italic}
.postmeta{font-size:.8rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600;margin-top:12px}
.pagenav{display:flex;justify-content:space-between;gap:16px;margin-top:60px;border-top:1px solid var(--line);padding-top:24px}

/* gold emphasis inside the dark sustainability band heading (kept in CSS so it
   survives WordPress' HTML filtering of editable fields) */
.sus h2 b{color:var(--gold-ink)}

/* ---------- footer social icons ---------- */
.social{display:inline-flex;gap:10px;margin-top:14px}
.social a{width:36px;height:36px;border:1px solid rgba(255,255,255,.2);border-radius:9px;display:inline-flex;align-items:center;justify-content:center;color:#aebccb;transition:.2s}
.social a:hover{color:#fff;border-color:var(--gold);background:rgba(255,255,255,.06)}

/* ---------- header logo + nav dropdown ---------- */
.brand .logo-img{height:44px;width:auto;display:block;transition:transform .4s ease}
.brand:hover .logo-img{transform:scale(1.04)}
.brand svg{transition:transform .8s cubic-bezier(.2,.7,.2,1)}
.brand:hover svg{transform:rotate(-12deg)}

/* animated lockup: full wordmark with only the globe animating (wipe on load, pulse on hover) */
.brand.sansan-logo{
  /* ===== SAFE TO EDIT — header logo size (auto-adjusts, no hard lock) =====
     clamp(min, fluid, max): 40px on small phones → up to 48px on laptops,
     scaling smoothly with screen width in between. Change any of the 3 numbers. */
  --sansan-logo-h:clamp(40px,4.8vw,48px);
  position:relative;display:block;height:var(--sansan-logo-h);gap:0}
.sansan-logo .sansan-wordmark{height:var(--sansan-logo-h);width:auto;display:block;max-width:none;
  /* hide the globe baked into the wordmark; the animated globe layer draws it instead */
  clip-path:inset(-5% -2% -5% 24.2%)}
.sansan-logo .sansan-globe{position:absolute;left:0;top:0;height:var(--sansan-logo-h);width:var(--sansan-logo-h);max-width:none}
/* Which animation runs is chosen in Customize > Logo & Loader > "Header logo animation".
   Speed and strength come from CSS variables set in header.php. */
.sansan-logo.anim-pulse .sansan-globe{animation:sansan-pulse var(--sn-wipe-dur,1s) ease-in-out .15s both}
.sansan-logo.anim-pulse:hover .sansan-globe{animation:sansan-pulse var(--sn-pulse-dur,.8s) ease-in-out}
.sansan-logo.anim-heartbeat .sansan-globe{animation:sansan-heartbeat var(--sn-beat-dur,3.4s) cubic-bezier(.4,.6,.35,1) infinite}
.sansan-logo.anim-none .sansan-globe{animation:none}
/* heartbeat: a strong beat then a soft echo, the wordmark never moves */
@keyframes sansan-heartbeat{
  0%{transform:scale(1)}
  8%{transform:scale(var(--sn-beat-scale,1.1))}
  18%{transform:scale(1.005)}
  26%{transform:scale(var(--sn-beat-soft,1.06))}
  38%{transform:scale(1)}
  100%{transform:scale(1)}}
@keyframes sansan-wipe{
  0%  {clip-path:polygon(-25% -25%,125% -25%,125% -49%,-25% -15%)}
  100%{clip-path:polygon(-25% -25%,125% -25%,125% 119%,-25% 153%)}}
@keyframes sansan-pulse{0%{transform:scale(1)}45%{transform:scale(1.06)}100%{transform:scale(1)}}
.menu .has-drop{position:relative}
.menu .has-drop > a::after{display:none}/* no dropdown caret */
.menu .drop{position:absolute;top:100%;left:-14px;background:#fff;border:1px solid var(--line);border-radius:12px;box-shadow:0 22px 44px -26px rgba(27,58,91,.45);padding:8px;min-width:190px;opacity:0;visibility:hidden;transform:translateY(6px);transition:.2s;z-index:60}
.menu .has-drop:hover > .drop,.menu .has-drop:focus-within > .drop{opacity:1;visibility:visible;transform:none}
.menu .drop a{display:block;padding:9px 14px;border-radius:8px;font-size:.86rem;white-space:nowrap;color:var(--ink)}
.menu .drop a:hover{background:var(--soft);color:var(--blue)}
/* Mobile: the submenu starts collapsed and the "Garment" row is a TOGGLE, not a link
   (app.js removes its href below this breakpoint). A chevron marks it as expandable —
   without one, a row that refuses to navigate just reads as broken. */
@media(max-width:980px){
  .menu .has-drop{position:static;width:100%}
  /* display:block is REQUIRED — this <a> is not a flex item (it sits inside .has-drop),
     so while inline its 16px padding is ignored and the row renders 33px shorter */
  .menu .has-drop > a{display:block;width:100%;cursor:pointer;position:relative}
  .menu .has-drop > a::after{
    display:block;content:"";position:absolute;right:36px;top:50%;width:9px;height:9px;
    border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
    transform:translateY(-70%) rotate(45deg);transition:transform .25s ease;
    /* This pseudo-element is ALSO used by .menu a.active::after for the gold
       underline. That rule sets background/left/bottom and this one never reset
       them, so on the active Garment row they combined into a 9px gold square
       stuck to the left edge. Reset them explicitly. */
    background:none;left:auto;bottom:auto
  }
  .menu .has-drop.open > a::after{transform:translateY(-20%) rotate(225deg)}
  /* display:block is REQUIRED — .drop is a <span>, and max-height/overflow are
     ignored on inline elements, so without it the submenu can never collapse. */
  .menu .drop{display:block;position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;background:var(--soft);min-width:0;padding:0;max-height:0;overflow:hidden;transition:max-height .28s ease}
  .menu .has-drop.open > .drop{max-height:300px}
  .menu .drop a{padding:14px 36px 14px 56px;border-top:1px solid var(--line);border-radius:0;width:100%;color:var(--muted);font-weight:500}
}

/* ---------- page loader (light sweep — globe/brandmark only) ---------- */
#sn-loader{position:fixed;inset:0;z-index:9999;background:#fbfaf8;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:30px;transition:opacity .5s ease,visibility .5s ease}
#sn-loader.hide{opacity:0;visibility:hidden;pointer-events:none}
/* ===== SAFE TO EDIT — loader globe size (auto-adjusts, no hard lock) ===== */
.sn-loader-logo{position:relative;width:clamp(84px,24vw,112px);height:clamp(84px,24vw,112px)}
.sn-loader-logo>img,.sn-loader-logo>svg{width:100%;height:100%;display:block}
.sn-loader-sheen{position:absolute;inset:0;overflow:hidden;-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center}
.sn-loader-sheen::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,rgba(255,255,255,0) 30%,rgba(255,255,255,.6) 50%,rgba(255,255,255,0) 70%);animation:sansan-sheen var(--sn-shine-dur,2.6s) cubic-bezier(.65,0,.35,1) infinite}
.sn-loader-label{font-family:var(--font);font-size:12px;font-weight:600;letter-spacing:.34em;padding-left:.34em;background:linear-gradient(90deg,#335e88 42%,#e9f1f8 50%,#335e88 58%);background-size:250% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:sansan-textsweep var(--sn-shine-dur,2.6s) cubic-bezier(.65,0,.35,1) infinite}
@keyframes sansan-sheen{0%{transform:translateX(-135%) skewX(-12deg)}45%{transform:translateX(135%) skewX(-12deg)}100%{transform:translateX(135%) skewX(-12deg)}}
@keyframes sansan-textsweep{0%{background-position:100% 0}45%{background-position:0% 0}100%{background-position:0% 0}}
@media(prefers-reduced-motion:reduce){
  .sn-loader-sheen::after,.sn-loader-label{animation:none}
  .sansan-logo .sansan-globe{animation:none}
  .brand:hover svg,.brand:hover .logo-img,.sansan-logo:hover .sansan-globe{transform:none;animation:none}}

/* ---------- mobile refinements (override inline grids where needed) ---------- */
@media(max-width:820px){
  .wrap{padding:0 22px}
  .sec{padding:62px 0}
  .sec.tight{padding:42px 0}
  .impact{padding:46px 0}
  .impact .grid{grid-template-columns:repeat(2,1fr) !important;gap:28px 16px}
  .ostrip{grid-template-columns:repeat(2,1fr) !important}
  .segments{grid-template-columns:1fr !important}
  .home-about,.contact-grid,.sus .in{grid-template-columns:1fr !important;gap:30px}
  .seg{min-height:340px}
  .sus{padding:34px 24px}
  .ctaband .wrap{width:calc(100% - 32px);padding:44px 24px;border-radius:20px;margin-left:auto;margin-right:auto}
  .phero .wrap{padding:60px 22px 46px}
}
@media(max-width:460px){
  .impact .grid,.ostrip,.cgrid,.cgrid.three,.mgrid,.comp,.divs,.netgrid{grid-template-columns:1fr !important}
  h2{font-size:clamp(1.6rem,7vw,2rem)}
}

/* ---------- careers application form + popup modal ---------- */
.applyform{max-width:720px;margin-top:22px}
.applyform input,.applyform textarea,.applyform select{max-width:100%}
#sn-apply-for{margin-top:14px}

/* the form opens as a popup over the page (dimmed, blurred backdrop) */
.sn-modal{position:fixed;inset:0;z-index:1000;display:none;align-items:flex-start;justify-content:center;padding:5vh 18px;overflow-y:auto}
.sn-modal.open{display:flex}
.sn-modal-backdrop{position:fixed;inset:0;background:rgba(16,32,54,.55);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.sn-modal-dialog{position:relative;z-index:1;background:#fff;width:100%;max-width:640px;margin:auto;border-radius:18px;padding:40px;box-shadow:0 40px 90px -30px rgba(16,32,54,.55);animation:sn-modal-in .28s cubic-bezier(.2,.7,.2,1) both}
.sn-modal-x{position:absolute;top:12px;right:14px;width:40px;height:40px;border:0;border-radius:10px;background:transparent;color:var(--muted);font-size:1.9rem;line-height:1;cursor:pointer;transition:.2s}
.sn-modal-x:hover{background:var(--soft);color:var(--navy)}
/* Freeze the page behind an open popup. position:fixed (with the scroll offset
   written to top: in JS) is what actually stops iOS Safari, which ignores
   overflow:hidden on body. Scroll position is restored on close. */
html.sn-modal-open,body.sn-modal-open{overflow:hidden}
body.sn-modal-open{position:fixed;left:0;right:0;width:100%}
/* browsers without inert support are covered by the Tab handler in app.js */
@keyframes sn-modal-in{0%{opacity:0;transform:translateY(14px) scale(.985)}100%{opacity:1;transform:none}}
@media(max-width:560px){.sn-modal{padding:0}.sn-modal-dialog{min-height:100%;border-radius:0;padding:64px 22px 40px}}
@media(prefers-reduced-motion:reduce){.sn-modal-dialog{animation:none}}

/* ---------- capability chips (laundry / embroidery) ---------- */
.chips{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px}
.chips span{background:#fff;border:1px solid var(--line);border-radius:999px;padding:9px 18px;font-size:.9rem;font-weight:500;color:var(--navy)}

/* ---------- phones: the "Four decades" timeline goes vertical ----------
   As a horizontal scroller each 210px item lands mid-viewport on a 390px
   screen, so every entry is sliced at both edges. Stacked, each one reads
   in full and the page-scroll-linked JS becomes a harmless no-op. */
@media(max-width:640px){
  .timeline{display:block;overflow-x:visible;padding:8px 0 0;margin-top:18px}
  .tl-item{width:auto;padding:0 0 26px 34px}
  .tl-item::before{top:6px;bottom:0;left:9px;right:auto;width:2px;height:auto}
  .tl-item:last-child::before{bottom:auto;height:0}
  .tl-item .dot{position:absolute;left:0;top:0;margin-bottom:0}
  .tl-item .yr{font-size:1.4rem;line-height:1.15}
  .tl-item .ev{margin-top:2px}
}

/* ---------- built-in forms: notices, honeypot, file field ---------- */
/* Honeypot: off-screen rather than display:none — some bots skip hidden inputs. */
.sn-hp{position:absolute!important;left:-9999px!important;width:1px;height:1px;overflow:hidden}
.form-note{border-radius:14px;padding:18px 20px;margin-bottom:22px;font-size:.94rem;line-height:1.55}
.form-note b{display:block;margin-bottom:3px}
.form-note.ok{background:#eef6ef;border:1px solid #cfe4d2;color:#1f5c2c}
.form-note.ok span{color:#3c6b45}
.form-note.err{background:#fdf1ef;border:1px solid #f2d4ce;color:#9c3324}
.form-note.err ul{margin:6px 0 0;padding-left:18px}
.form-note.err li{margin-top:2px}
.form .hint{display:block;margin-top:6px;font-size:.78rem;color:var(--muted);font-weight:300}
/* File field. The native input is laid over the whole box at opacity 0 — Chrome's
   internal layout for input[type=file] can't be centred reliably, so the visible
   "Choose file" pill and filename are ordinary flex children we control. Clicking
   anywhere in the box opens the picker, and the input stays focusable so keyboard
   use and required-field validation still work. */
.filefield{position:relative;display:flex;align-items:center;gap:14px;min-height:52px;padding:0 16px;border:1px dashed var(--line);border-radius:10px;background:#fff;cursor:pointer}
.filefield:hover{border-color:var(--blue)}
.filefield:focus-within{border-color:var(--blue);box-shadow:0 0 0 3px rgba(50,94,137,.12)}
.filefield input[type=file]{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer}
.filefield .filebtn{flex:none;border-radius:999px;padding:9px 18px;background:var(--soft);color:var(--navy);font-weight:600;font-size:.82rem;line-height:1.2}
.filefield:hover .filebtn{background:#e8eef6}
.filefield .filename{min-width:0;color:var(--muted);font-size:.88rem;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.filefield.has-file .filename{color:var(--ink);font-weight:500}
/* z-index:2 lifts this above the transparent file input that covers the box,
   so clicking it clears the file instead of reopening the picker */
.filefield .fileclear{position:relative;z-index:2;margin-left:auto;flex:none;display:none;align-items:center;justify-content:center;width:28px;height:28px;border:0;border-radius:50%;background:none;color:var(--muted);font-size:1.15rem;line-height:1;cursor:pointer;transition:.15s}
.filefield.has-file .fileclear{display:flex}
.filefield .fileclear:hover{background:#fdecea;color:#c0392b}
.filefield .fileclear:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* ---------- contact: enquiry card that opens the popup ---------- */
.encard{background:var(--soft);border:1px solid var(--line);border-radius:18px;padding:38px 34px}
.encard h3{font-weight:600;font-size:1.25rem;color:var(--navy)}
.encard p{color:var(--muted);font-weight:300;font-size:.98rem;margin:10px 0 24px;max-width:44ch}
.encard .alt{font-size:.86rem;margin:18px 0 0}
.encard .alt a{color:var(--blue);font-weight:600}
@media(max-width:820px){.encard{padding:30px 24px}}

/* ---------- phones: keep the caption pills, give them room ----------
   The pill is absolutely positioned bottom-right. On a narrow screen the intro
   wraps to four or five lines and used to run underneath it, so the content
   block reserves space instead of the pill being hidden. */
@media(max-width:820px){
  .phero .wrap{padding-bottom:46px}
  .hero .wrap{padding-bottom:56px}
}

/* Machinery cards were built with an empty photo placeholder that was never wired
   to real images — it renders as a blank grey box. Hide it until photos exist. */
.mcard .ph{height:180px;background-size:cover;background-position:center}
.mcard .ph.plain{height:auto;padding:26px 0;background:var(--soft)}

/* ---------- production network map (Java) ----------
   The outline is generated from real province boundary data; markers are placed
   from each town's true coordinates. NOTE: never put a CSS transform on .jmap-site —
   it would override the transform="translate(x,y)" attribute and stack every marker
   at the origin. Animate opacity here and scale on the halo circle instead. */
/* overflow must stay visible or a tall card gets clipped by the panel */
.jmap{margin-top:40px;position:relative;background:linear-gradient(160deg,#f7f9fb,#eef3f8);border:1px solid var(--line);border-radius:22px;padding:28px 24px 22px}
.jmap svg{width:100%;height:auto;display:block;overflow:visible}
.jmap-island{fill:#dbe5ef;stroke:#b9cadb;stroke-width:1.4;stroke-linejoin:round;transition:fill .4s ease}
.jmap:hover .jmap-island{fill:#d5e1ed}
.jmap-site{cursor:pointer;opacity:0;transition:opacity .5s ease}
.jmap.in .jmap-site{opacity:1}
.jmap-site:focus{outline:none}
.jmap-site:focus-visible .jmap-dot{stroke:var(--navy);stroke-width:3}
.jmap-halo{fill:var(--gold);opacity:.18;transform-origin:center;transform-box:fill-box}
.jmap-dot{fill:var(--gold);stroke:#fff;stroke-width:1.6}
.jmap-lbl{font-size:15px;font-weight:700;fill:var(--navy);letter-spacing:.02em}
.jmap-site.on .jmap-dot,.jmap-site:hover .jmap-dot{fill:var(--blue)}
.jmap-site.on .jmap-halo{fill:var(--blue);opacity:.28}
.jmap.in .jmap-halo{animation:jmap-ping 2.8s ease-out infinite}
.jmap.in .jmap-site:nth-of-type(2) .jmap-halo{animation-delay:.5s}
.jmap.in .jmap-site:nth-of-type(3) .jmap-halo{animation-delay:1s}
.jmap.in .jmap-site:nth-of-type(4) .jmap-halo{animation-delay:1.5s}
@keyframes jmap-ping{0%{transform:scale(.8);opacity:.30}70%{transform:scale(2.4);opacity:0}100%{opacity:0}}

.jmap-tip{position:absolute;pointer-events:none;opacity:0;transform:translateY(6px);transition:opacity .18s ease,transform .18s ease;z-index:5;background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:0 26px 50px -28px rgba(27,58,91,.55);padding:14px 16px;min-width:250px;max-width:310px}
.jmap-tip.show{opacity:1;transform:none}
.jmap-tip h4{font-size:.95rem;color:var(--blue);font-weight:700;letter-spacing:.02em}
.jmap-tip .jloc{font-size:.78rem;color:var(--muted);font-weight:300;margin-bottom:8px}
.jmap-tip .jrow{display:flex;justify-content:space-between;gap:14px;font-size:.82rem;padding:5px 0;border-top:1px solid var(--line);align-items:baseline}
.jmap-tip .jrow .jn{color:var(--navy);font-weight:600}
.jmap-tip .jrow .jl{display:flex;align-items:baseline;gap:7px;min-width:0}
.jmap-tip .jrow .jm{color:var(--muted);font-weight:300;font-size:.72rem;white-space:nowrap}
.jmap-tip .jrow .jc{color:var(--navy);font-weight:700;white-space:nowrap}

.jmap-legend{display:flex;flex-wrap:wrap;gap:10px 22px;margin-top:18px;font-size:.78rem;color:var(--muted);font-weight:300;align-items:center}
.jmap-legend b{color:var(--navy);font-weight:700}
/* Trimmed section padding. These MUST stay below the @media `.sec{padding:62px 0}` rule above —
   that's a shorthand at equal specificity, so an earlier .sec-* rule would lose on small screens. */
/* The visible gap between two sections is this section's padding-bottom PLUS the next
   section's padding-top, so trimming one side alone can only ever get you halfway.
   Both of these therefore also trim the section that follows them. */

/* map → sustainability: was 44+104=148px, now 12+88=100px (about a third off) */
.sec-map{padding-bottom:12px}
.sec-map + .sec{padding-top:88px}


@media(max-width:820px){
  .sec-map{padding-bottom:12px}
  .sec-map + .sec{padding-top:52px}
  .ct-pdf{margin-top:36px}
  .ct-pdf + .map iframe{margin-top:36px}
  .jmap{padding:18px 12px 14px}
  .jmap-lbl{display:none}          /* labels collide at this size — the card names the place */
  .jmap-dot{r:11}
  .jmap-halo{r:26}
  .jmap-tip{position:static;opacity:1;transform:none;display:none;margin-top:14px;min-width:0;max-width:none;box-shadow:none}
  .jmap-tip.show{display:block}
}
@media(prefers-reduced-motion:reduce){
  .jmap-site{opacity:1;transition:none}
  .jmap.in .jmap-halo{animation:none}
}

/* ---------- cookie consent notice ----------
   Only ever rendered when a cookie-based tracker (GA4) is configured AND the
   visitor has not answered yet — see sansan_consent_banner() in functions.php.
   Accept and Decline are given equal visual weight on purpose: a decline button
   that is harder to find is exactly what regulators call a dark pattern. */
.sn-consent{position:fixed;left:16px;right:16px;bottom:16px;z-index:1100;max-width:720px;margin:0 auto;
  background:#fff;color:var(--ink);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 10px 40px rgba(16,32,54,.18);padding:18px 20px;
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  animation:sn-consent-in .35s ease both}
@keyframes sn-consent-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.sn-consent-text{flex:1 1 300px;min-width:0;font-size:.85rem;line-height:1.6;font-weight:300;margin:0}
.sn-consent-text a{color:var(--blue);text-decoration:underline;font-weight:400}
.sn-consent-actions{display:flex;gap:10px;flex-shrink:0}
.sn-consent-btn{font-family:inherit;font-size:.78rem;font-weight:500;letter-spacing:.04em;
  padding:10px 20px;border-radius:999px;border:1px solid var(--blue);background:var(--blue);color:#fff;
  cursor:pointer;transition:background .2s,color .2s}
.sn-consent-btn:hover{background:var(--navy);border-color:var(--navy)}
.sn-consent-btn.ghost{background:transparent;color:var(--ink);border-color:var(--line)}
.sn-consent-btn.ghost:hover{background:var(--soft);color:var(--ink);border-color:var(--muted)}
.sn-consent-btn:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
@media(max-width:560px){
  .sn-consent{padding:16px;gap:14px}
  .sn-consent-actions{width:100%}
  .sn-consent-btn{flex:1}          /* full-width thumb targets rather than two small pills */
}
@media(prefers-reduced-motion:reduce){ .sn-consent{animation:none} }

/* ---------- TranslatePress: suppress its floating switcher ----------
   The theme provides its own EN / ID switcher in the header, so the plugin's
   floating box is a duplicate control — and it parks itself over the hero badge
   in the bottom corner. Belt and braces: the proper off switch is
   TranslatePress ▸ Settings ▸ "Floating language selection" = No, but hiding it
   here means it can never come back if that setting is ever toggled. */
.trp-floating-switcher,
#trp-floater-ls,
.trp-language-switcher.trp-floating-switcher{display:none !important}

/* ---------- news: load-more sentinel ---------- */
.sn-more-sentinel{display:flex;justify-content:center;align-items:center;min-height:64px;margin-top:12px}
.sn-more-spin{width:22px;height:22px;border-radius:50%;border:2px solid var(--line);border-top-color:var(--blue);opacity:0;transition:opacity .2s}
.sn-more-sentinel.loading .sn-more-spin{opacity:1;animation:sn-spin .7s linear infinite}
@keyframes sn-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.sn-more-sentinel.loading .sn-more-spin{animation:none}}

/* ---------- article: link to the other language ---------- */
.sn-altlang{margin:-6px 0 26px;font-size:.85rem}
.sn-altlang a{display:inline-flex;align-items:center;gap:6px;color:var(--blue);font-weight:500;
  border:1px solid var(--line);border-radius:999px;padding:7px 16px;transition:.2s;text-decoration:none}
.sn-altlang a:hover{border-color:var(--blue);background:var(--soft);gap:10px}

/* ---------- FAQ accordion ----------
   Native <details>, so it works without JavaScript, is keyboard accessible, and is
   indexed by search engines at full weight. Collapsed by default keeps the page as
   short as it was — the content is real and readable, just not shouted. */
.sn-faq{max-width:820px;margin:44px auto 0;border-top:1px solid var(--line)}
.sn-faq-item{border-bottom:1px solid var(--line)}
.sn-faq-item summary{list-style:none;cursor:pointer;padding:20px 44px 20px 0;position:relative;
  font-weight:500;font-size:1.02rem;color:var(--navy);line-height:1.5;transition:color .2s}
.sn-faq-item summary::-webkit-details-marker{display:none}
.sn-faq-item summary:hover{color:var(--blue)}
.sn-faq-item summary:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:4px}
/* the +/− is drawn from two bars so it needs no icon font */
.sn-faq-item summary::before,
.sn-faq-item summary::after{content:"";position:absolute;right:8px;top:50%;background:var(--blue);
  transition:transform .25s,opacity .25s}
.sn-faq-item summary::before{width:14px;height:2px;margin-top:-1px}
.sn-faq-item summary::after{width:2px;height:14px;right:14px;margin-top:-7px}
.sn-faq-item[open] summary::after{transform:rotate(90deg);opacity:0}
.sn-faq-item[open] summary{color:var(--blue)}
.sn-faq-a{padding:0 44px 22px 0;color:var(--muted);font-weight:300;font-size:.96rem;line-height:1.75}
.sn-faq-a p{margin:0 0 10px}
.sn-faq-a p:last-child{margin-bottom:0}
@media(prefers-reduced-motion:reduce){.sn-faq-item summary::before,.sn-faq-item summary::after{transition:none}}

/* ---------- specification panel ----------
   Deliberately NOT styled like the FAQ below it: that is a divided list of rows,
   this is a set of separate tiles, so the two read as different kinds of thing.
   Tiles carry their own border with transparent gaps between them — an earlier
   version used a 1px grid gap over a grey container, which looked right until a
   row was part-filled and the leftover cells showed as a grey block. This way any
   number of entries lays out cleanly. */
.sn-specs{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
  gap:14px;max-width:980px;margin:44px auto 0}
.sn-spec-row{background:var(--bg);border:1px solid var(--line);border-radius:14px;
  padding:22px 24px;transition:border-color .2s,transform .2s}
.sn-spec-row:hover{border-color:var(--blue-l);transform:translateY(-2px)}
.sn-specs dt{font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold-ink);font-weight:600;margin:0 0 8px}
.sn-specs dd{margin:0;color:var(--navy);font-weight:300;font-size:1.06rem;line-height:1.5}
@media(max-width:820px){ .sn-specs,.sn-faq{margin-top:30px} }
@media(max-width:640px){
  .sn-specs{grid-template-columns:1fr;gap:10px}
  .sn-spec-row{padding:18px 20px}
}

/* ---------- article → service link ----------
   Sits between the article and the prev/next nav. Matches .prose's 760px column so
   it reads as part of the article rather than a bolted-on advert. */
.sn-related{max-width:760px;margin:38px auto 0;padding:26px;border:1px solid var(--line);
  border-radius:16px;background:var(--soft)}
.sn-related-k{font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;color:var(--gold-ink);
  font-weight:600;margin:0 0 12px}
.sn-related-card{display:block;text-decoration:none}
.sn-related-t{display:block;font-size:1.15rem;font-weight:500;color:var(--navy);line-height:1.35;
  transition:color .2s}
.sn-related-card:hover .sn-related-t{color:var(--blue)}
.sn-related-d{display:block;margin-top:6px;color:var(--muted);font-weight:300;font-size:.95rem;line-height:1.6}
.sn-related-ask{display:inline-flex;align-items:center;gap:6px;margin-top:16px;font-size:.86rem;
  font-weight:600;color:var(--blue);text-decoration:none;transition:gap .2s}
.sn-related-ask:hover{gap:10px}
@media(max-width:640px){ .sn-related{padding:20px;margin-top:28px} }

/* ---------- very small phones ----------
   At 320-414px the CTA was being squeezed until "Get in touch" broke onto two
   lines. Trim its padding and the logo height rather than letting it wrap. */
@media(max-width:430px){
  .navcta .btn{padding:.55rem .85rem !important;font-size:.82rem}
  header{--sansan-logo-h:clamp(34px,10vw,40px)}
  .nav{gap:8px}
}
@media(max-width:340px){
  .navcta .btn{padding:.5rem .7rem !important;font-size:.78rem}
}
