/* GENERATED by tools/build.py — edit the layer files, not this. */


/* ===== tokens ===== */

/* ============================================================
   LAYER 1 · TOKENS
   The only place colour, type and space are defined.
   No hex literal may appear outside this file.
   ============================================================ */

/* --- self-hosted Latin faces ------------------------------- */
@font-face{
  font-family:'General Sans';
  src:url('/assets/fonts/general-sans-variable.woff2') format('woff2-variations');
  font-weight:200 700;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Plex Mono';
  src:url('/assets/fonts/ibm-plex-mono-500.woff2') format('woff2');
  font-weight:500;font-style:normal;font-display:swap;
}

:root{
  /* --- brand: sampled from the SEPIA logo --------------- */
  --blue:#3D5AA6;
  --red:#E01B2E;
  --green:#6DB93F;
  --yellow:#F0CE1A;

  /* --- light theme (default) ---------------------------- */
  --bg:#FFFFFF;
  --bg-2:#FAF7F1;
  --bg-3:#F2EDE4;
  --ink:#141210;          /* warm near-black — never #000 */
  --ink-2:#4B433C;
  --ink-3:#665C54;
  --line:#E4DED4;
  --line-2:#CFC5B6;
  --accent:var(--red);    /* the accent word on light grounds */
  --link:#2F4A8E;
  --field:var(--yellow);  /* the full-bleed finale */
  --on-field:#141210;
  --field-2:#2A4184;      /* second line on the yellow field — 6.19:1 */
  --focus:var(--red);

  /* The inverted panel is a contrast device, so it must stay dark in BOTH
     themes. Deriving it from --ink flips it light in dark mode and strands the
     white text written on it. */
  --panel:#2E2419;        /* warm sepia — the ink #141210 reads as black here */
  --on-panel:#F8F2E8;
  --on-panel-2:rgba(248,242,232,.84);
  --panel-line:rgba(248,242,232,.18);

  /* The hero field and the rail beneath it are the only large dark areas on
     the site, and they are warm sepia by rule — never black. The scrim that
     keeps hero type legible over video is tinted the same sepia, so a missing
     or dark video still reads as brand colour rather than as a black box. */
  --hero-1:#463726;
  --hero-2:#2E2419;
  --hero-3:#241C16;
  --rail-bg:#2A211A;
  /* Four stops, not three. The headline runs to roughly 65% of the viewport
     width, and the old three-stop ramp had already fallen to .30 alpha there —
     enough for white, not for the yellow accent word, which carries the least
     luminance headroom of anything on the site. The fourth stop holds the ramp
     up across the type and only then lets the picture through. */
  --scrim-1:rgba(36,28,22,.84);
  --scrim-2:rgba(36,28,22,.72);
  --scrim-3:rgba(36,28,22,.54);
  --scrim-4:rgba(36,28,22,.28);
  /* the header sits over the top strip at full width, past every horizontal
     stop, so it gets its own vertical scrim */
  --scrim-top:rgba(36,28,22,.52);
  --scrim-mob-2:rgba(36,28,22,.78);
  --scrim-mob-3:rgba(36,28,22,.68);
  --scrim-mob-4:rgba(36,28,22,.54);
  --on-dark:#FFFFFF;
  --on-dark-2:rgba(255,255,255,.86);
  --on-dark-3:rgba(255,255,255,.76);
  --on-dark-line:rgba(255,255,255,.22);

  /* --- type --------------------------------------------- */
  --sans:'General Sans','Noto Sans JP','Hiragino Kaku Gothic ProN','Yu Gothic',Meiryo,system-ui,sans-serif;
  --mono:'Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  --fs-d1:clamp(2.1rem,7vw,6.25rem);
  --fs-d2:clamp(2.1rem,4.4vw,4rem);
  --fs-d3:clamp(1.4rem,2.2vw,1.9rem);
  --fs-d4:1.25rem;
  --fs-lead:clamp(1.06rem,1.5vw,1.375rem);
  --fs-body:1rem;
  --fs-sm:0.9375rem;
  /* The tag is the smallest type on the site and it carries wayfinding — the
     section numbers and the eyebrow above every heading. At .7rem/11.2px with
     .18em tracking, in --accent red, it sat at 4.81:1 on white: legible, but
     with no margin at all over the 4.5:1 floor. 12px buys that margin back
     without changing the label's rank against anything around it. */
  --fs-tag:0.75rem;

  /* --- radius ------------------------------------------- */
  /* One value for every picture on the site, matching the 16px already used by
     the location and comparison cards, so photographs and panels share a corner. */
  --r-img:16px;

  /* --- space -------------------------------------------- */
  --gut:clamp(20px,4vw,56px);
  --maxw:1400px;
  --maxw-text:74ch;
  /* Both sides of a section boundary carry this, so the number is half of the
     gap the reader actually sees: 110px each side read as 220px of empty page
     between two blocks of text. */
  --sect:clamp(48px,5.6vw,88px);
  --sect-sm:clamp(36px,4.4vw,66px);

  /* --- motion ------------------------------------------- */
  --ease:cubic-bezier(.19,1,.22,1);
  --dur:.4s;

  color-scheme:light;
}

/* --- dark theme: warm sepia, never black ------------------ */
:root[data-theme="dark"]{
  --bg:#241C16;
  --bg-2:#2E251C;
  --bg-3:#382D22;
  --ink:#F8F2E8;
  --ink-2:#CDBDAB;
  --ink-3:#AC9C8C;
  --line:#443528;
  --line-2:#584534;
  --accent:var(--yellow);
  --link:#9DB4E8;
  --focus:var(--yellow);
  /* Lifted off the page ground so the panel still reads as raised on sepia. */
  --panel:#3A2F24;
  color-scheme:dark;
}


/* ===== base ===== */

/* ============================================================
   LAYER 2 · BASE — reset, elements, typography
   ============================================================ */

*,*::before,*::after{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto;}}

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--sans);
  font-size:var(--fs-body);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
  transition:background var(--dur) ease,color var(--dur) ease;
}
/* Japanese needs looser leading and relaxed tracking */
html[lang="ja"] body{line-height:1.85;}

img,video,svg{max-width:100%;display:block;}
img,video{height:auto;}
a{color:inherit;text-decoration:none;}
/* Email and phone links always stand alone here — never mid-sentence — so they
   are real tap targets and need the 24px minimum (WCAG 2.5.8), not the 19–20px
   a bare inline link gets from its line box. */
a[href^="mailto:"],a[href^="tel:"]{display:inline-block;padding-block:4px;}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer;}
input,textarea,select{font:inherit;color:inherit;}
ul,ol{margin:0;padding:0;list-style:none;}
h1,h2,h3,h4,p,figure{margin:0;}
hr{border:0;border-top:1px solid var(--line);margin:0;}
::selection{background:var(--yellow);color:var(--ink);}

:focus-visible{outline:3px solid var(--focus);outline-offset:3px;border-radius:2px;}
:focus:not(:focus-visible){outline:none;}

.skip{
  position:absolute;left:-9999px;top:0;z-index:200;
  background:var(--ink);color:var(--bg);padding:14px 22px;font-weight:700;border-radius:0 0 4px 0;
}
.skip:focus{left:0;}

.sr{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* --- containers ------------------------------------------- */
.w{max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gut);}
.w-text{max-width:var(--maxw-text);}

/* A grid item's automatic minimum size is its min-content width, so a `1fr`
   track can never shrink below the widest unbreakable run inside it — and with
   Japanese phrase breaking that run is a whole phrase. min-width:0 lets the
   track shrink and the text wrap instead of pushing the page sideways. */
.cards > *,.stats > *,.locs > *,.tl > *,.idx > *,.compare > *,
.sect-split > *,.contact-grid > *,.ft-grid > *,.rail-in > *,
.cap-row > *,.legal-grid > *,.svc-car > *,.post > *,.role > *{min-width:0;}

/* --- type scale ------------------------------------------- */
.d1{font-size:var(--fs-d1);font-weight:700;line-height:1.1;letter-spacing:-.022em;}
.d2{font-size:var(--fs-d2);font-weight:700;line-height:1.1;letter-spacing:-.0225em;text-wrap:balance;}
.d3{font-size:var(--fs-d3);font-weight:700;line-height:1.14;letter-spacing:-.02em;}
.d4{font-size:var(--fs-d4);font-weight:700;line-height:1.2;letter-spacing:-.015em;}
/* Japanese display type.
   `word-break: keep-all` plus `display:inline-block` on the accent span stops a
   two-character phrase splitting — but it also makes a long phrase completely
   unbreakable, which pushed several JA pages past the viewport. `line-break:
   strict` gives correct kinsoku line-breaking instead, and `overflow-wrap`
   catches long Latin product names (S/4HANA, One Identity Manager). */
html[lang="ja"] .d1,
html[lang="ja"] .d2,
html[lang="ja"] .d3,
html[lang="ja"] .d4{
  letter-spacing:-.005em;line-height:1.3;
  line-break:strict;overflow-wrap:break-word;
  /* Plain CJK breaking is legal at almost every character, which splits words
     like アナリティクス across lines. auto-phrase breaks on phrase boundaries
     instead; browsers without it drop the declaration and fall back to the
     default, so this only ever improves the result. */
  word-break:auto-phrase;
}
/* text-wrap:balance fights phrase breaking on Japanese — it optimises for even
   line lengths and will happily strand a single character on the last line. */
html[lang="ja"] .d2{text-wrap:pretty;}

.lead{font-size:var(--fs-lead);font-weight:300;line-height:1.4;}
html[lang="ja"] .lead{font-weight:400;line-height:1.8;}

.body-copy{color:var(--ink-2);}
.body-copy p+p{margin-top:1em;}

.tag{
  font-family:var(--mono);font-size:var(--fs-tag);font-weight:500;
  letter-spacing:.18em;text-transform:uppercase;
}
html[lang="ja"] .tag{font-family:var(--sans);letter-spacing:.08em;font-weight:700;}

.acc{color:var(--accent);}
.num{font-variant-numeric:tabular-nums;}


/* ===== components ===== */

/* ============================================================
   LAYER 3 · COMPONENTS
   A component never reaches into a section.
   ============================================================ */

/* --- buttons ---------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;gap:11px;
  font-size:1rem;font-weight:700;padding:16px 28px;border-radius:999px;
  transition:background .22s,color .22s,border-color .22s,transform .22s;
  text-align:left;
}
.btn:hover{transform:translateY(-2px);}
.btn svg{width:15px;height:15px;flex:0 0 auto;}
.btn-fill{background:var(--ink);color:var(--bg);}
.btn-fill:hover{background:var(--accent);color:#fff;}
.btn-out{border:2px solid var(--ink);color:var(--ink);}
.btn-out:hover{background:var(--ink);color:var(--bg);}
.btn-yellow{background:var(--yellow);color:#141210;}
.btn-yellow:hover{background:var(--ink);color:var(--bg);}
.btn-onvid{border:2px solid rgba(255,255,255,.55);color:#fff;}
.btn-onvid:hover{background:#fff;color:#141210;border-color:#fff;}
.btn-ghost{background:rgba(255,255,255,.38);color:var(--on-field);}
.btn-ghost:hover{background:rgba(255,255,255,.7);}

.lnk{
  font-size:1rem;font-weight:700;display:inline-flex;align-items:center;gap:8px;
  border-bottom:2px solid transparent;padding-bottom:2px;transition:border-color .22s;
}
.lnk:hover{border-bottom-color:var(--accent);}

/* --- pills ------------------------------------------------ */
.pills{display:flex;flex-wrap:wrap;gap:9px;}
.pill{
  border:1.5px solid var(--line);background:var(--bg);border-radius:999px;
  padding:9px 17px;font-size:.92rem;font-weight:500;color:var(--ink-2);white-space:nowrap;
}
.pill.key{border-color:var(--accent);color:var(--accent);font-weight:700;}

/* --- header ----------------------------------------------- */
.hdr{position:fixed;top:0;left:0;right:0;z-index:90;transition:background .35s ease;}
.hdr.solid{background:var(--bg);border-bottom:1px solid var(--line);}
.hdr.on-dark:not(.solid){color:#fff;}
.hdr-in{display:flex;align-items:center;gap:20px;height:76px;}

/* --- logo -------------------------------------------------- */
/* The lockup is the company's own artwork (assets/img/brand/), not type: four
   overlapping letters in blue, yellow, green and red over "INNOVATIONS". Two
   files, identical except for that word — it is dark grey, which disappears
   over the hero video and in dark theme, so the second file carries it in the
   warm off-white the theme already uses. The coloured letters never change. */
.logo{display:flex;align-items:center;flex:0 0 auto;}
.logo img{display:block;width:auto;height:42px;transition:height .45s var(--ease);}
.logo .lg-on-dark{display:none;}

.hdr.on-dark:not(.solid) .logo .lg-on-light,
:root[data-theme="dark"] .logo .lg-on-light{display:none;}
.hdr.on-dark:not(.solid) .logo .lg-on-dark,
:root[data-theme="dark"] .logo .lg-on-dark{display:block;}

/* The footer sits on the yellow field in both themes, and the lockup's yellow
   letter is invisible on it — "SEPIA" reads as "S PIA". So the footer carries
   its own file with that one letter darkened to #7A6100, and the theme rules
   above must not reach it. */
.ft .logo img{height:38px;display:block;}

.hdr.compact .logo img{height:32px;}
@media (max-width:520px){.logo img{height:34px;}}

/* The flex item is the <nav> wrapper, not the <ul> inside it — putting the auto
   margin on the list leaves it with no free space to absorb, which is what kept
   the menu pinned beside the logo. */
.hdr-in > nav{margin-left:auto;}
.nav{display:flex;align-items:center;gap:24px;}
.nav > li{position:relative;}
/* 20px / 600 — the size the design system specified for nav all along; the
   built value had drifted to 17px / 500, which read as small print over the
   hero video. The weight matters more than the size here: 500 at this scale
   goes thin against moving footage. */
.nav a,.nav .navbtn{
  font-size:1.375rem;font-weight:600;line-height:1.1;white-space:nowrap;
  padding:8px 0;display:inline-flex;align-items:center;gap:6px;position:relative;
}
.nav a::after{
  content:'';position:absolute;left:0;right:100%;bottom:2px;height:2px;background:var(--accent);
  transition:right .3s var(--ease);
}
.nav a:hover::after,.nav a[aria-current="page"]::after{right:0;}
.nav .navbtn svg{width:11px;height:11px;transition:transform .25s;}
.nav li.open .navbtn svg{transform:rotate(180deg);}

.drop{
  position:absolute;top:100%;left:-18px;min-width:280px;
  background:var(--bg);border:1px solid var(--line);border-radius:8px;
  padding:10px;box-shadow:0 24px 48px -28px rgba(20,18,16,.42);
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .22s,transform .22s,visibility .22s;
}
.nav li.open .drop,.nav li:hover .drop{opacity:1;visibility:visible;transform:none;}
.drop a{display:block;padding:11px 14px;border-radius:5px;font-size:1rem;font-weight:500;color:var(--ink);}
.drop a::after{display:none;}
.drop a:hover{background:var(--bg-2);color:var(--accent);}
.drop a small{display:block;font-size:.82rem;font-weight:400;color:var(--ink-3);margin-top:2px;font-family:var(--sans);letter-spacing:0;}

.hdr-act{display:flex;align-items:center;gap:10px;flex:0 0 auto;}
.hdr.compact .hdr-act{margin-left:auto;}
.langsw{display:flex;border:1.5px solid currentColor;border-radius:999px;overflow:hidden;}
.langsw a{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;padding:9px 12px;
  min-width:46px;min-height:36px;display:inline-flex;align-items:center;justify-content:center;
  white-space:nowrap;opacity:.7;transition:.2s;
}
.langsw a[aria-current="true"]{background:currentColor;opacity:1;}
.langsw a[aria-current="true"] span{color:var(--bg);}
.hdr.on-dark:not(.solid) .langsw a[aria-current="true"] span{color:#141210;}

.tgl{width:58px;height:32px;border-radius:999px;border:1.5px solid currentColor;position:relative;flex:0 0 auto;}
.tgl i{position:absolute;top:3px;left:3px;width:23px;height:23px;border-radius:50%;background:currentColor;transition:transform .34s var(--ease);}
:root[data-theme="dark"] .tgl i{transform:translateX(24px);}
.tgl svg{position:absolute;top:50%;transform:translateY(-50%);width:13px;height:13px;right:9px;opacity:.85;}
:root[data-theme="dark"] .tgl svg{right:auto;left:9px;}

/* The bars stay 22px so the equaliser keeps its proportions; the padding lifts
   the button itself past the 24px target minimum. */
.snd{display:flex;align-items:flex-end;gap:2.5px;height:22px;padding:6px;box-sizing:content-box;flex:0 0 auto;}
.snd b{display:block;width:2.5px;background:currentColor;border-radius:2px;height:5px;}
.snd[aria-pressed="true"] b{animation:eq 1s ease-in-out infinite;}
.snd b:nth-child(1){animation-delay:0s}.snd b:nth-child(2){animation-delay:.15s}
.snd b:nth-child(3){animation-delay:.3s}.snd b:nth-child(4){animation-delay:.45s}
@keyframes eq{0%,100%{height:5px}50%{height:19px}}
.snd[aria-pressed="false"] b:nth-child(1){height:6px}.snd[aria-pressed="false"] b:nth-child(2){height:13px}
.snd[aria-pressed="false"] b:nth-child(3){height:9px}.snd[aria-pressed="false"] b:nth-child(4){height:16px}

.burger{display:none;width:44px;height:44px;align-items:center;justify-content:center;flex:0 0 auto;}
.burger span{display:block;width:20px;height:2px;background:currentColor;position:relative;transition:.3s;}
.burger span::before,.burger span::after{content:'';position:absolute;left:0;width:20px;height:2px;background:currentColor;transition:.3s;}
.burger span::before{top:-6px;}.burger span::after{top:6px;}
.hdr.menu-open .burger span{background:transparent;}
.hdr.menu-open .burger span::before{top:0;transform:rotate(45deg);}
.hdr.menu-open .burger span::after{top:0;transform:rotate(-45deg);}

/* --- footer ----------------------------------------------- */
.ft{background:var(--field);color:var(--on-field);padding-block:var(--sect-sm) 28px;}
/* The finale and the footer share the yellow field, so their two paddings read
   as one empty block — 109px + 72px of plain yellow between the CTA and the
   footer columns. Where the finale is the last thing on the page its own
   spacing is enough, so the footer keeps only a hairline of breathing room.
   Scoped with :has() because the legal pages and 404 have no finale and still
   need the full inset; browsers without :has() simply keep today's spacing. */
main:has(> .finale:last-child) + .ft{padding-top:16px;}
.ft-grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1fr;gap:clamp(22px,4vw,52px);}
.ft h2{font-family:var(--mono);font-size:.64rem;letter-spacing:.16em;text-transform:uppercase;margin-bottom:12px;font-weight:500;color:rgba(20,18,16,.74);}
html[lang="ja"] .ft h2{font-family:var(--sans);letter-spacing:.05em;font-weight:700;}
.ft li{padding:1px 0;}
.ft a,.ft li span{display:inline-block;padding:9px 0;font-size:.95rem;font-weight:500;}
.ft a:hover{text-decoration:underline;}
/* The company's LinkedIn, under the lockup. An outline rather than a bare icon:
   the footer sits on the yellow field, where a small ink glyph on its own reads
   as a stray mark, and the label makes the target the full 44px without a
   tooltip. */
/* `.ft a` above sets display:inline-block and its own padding, and at (0,2,0)
   it outranks a bare `.ft-social` — hence the class is qualified here, or the
   icon and the label stack on top of each other. */
.ft a.ft-social{
  display:inline-flex;align-items:center;gap:9px;margin-top:16px;
  border:1.5px solid rgba(20,18,16,.34);border-radius:999px;
  padding:10px 18px;font-size:.92rem;font-weight:700;transition:background .2s,border-color .2s,color .2s;
}
.ft a.ft-social svg{width:17px;height:17px;flex:0 0 auto;}
.ft a.ft-social:hover{background:var(--on-field);color:var(--field);border-color:var(--on-field);text-decoration:none;}
.ft-bottom{
  margin-top:clamp(26px,3.2vw,44px);padding-top:20px;border-top:1.5px solid rgba(20,18,16,.26);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
}
.ft-bottom span{font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;}
html[lang="ja"] .ft-bottom span{font-family:var(--sans);letter-spacing:.03em;}

/* --- marquee ---------------------------------------------- */
/* The rows carry a 14px rhythm between them, which left the bottom row sitting
   14px off the next section's edge — the chips looked stuck to the boundary.
   The padding gives the marquee its own breathing room without disturbing the
   gap between the two rows. */
.mq{overflow:hidden;padding-bottom:clamp(28px,3.4vw,52px);}
.mq-row{display:flex;gap:14px;width:max-content;margin-bottom:14px;}
.mq-row:last-child{margin-bottom:0;}
.mq-row.a{animation:sl 52s linear infinite;}
.mq-row.b{animation:sr 60s linear infinite;}
.mq:hover .mq-row{animation-play-state:paused;}
@keyframes sl{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@keyframes sr{from{transform:translateX(-50%)}to{transform:translateX(0)}}
.chip{border:1.5px solid var(--line);border-radius:999px;padding:13px 26px;font-size:1.02rem;font-weight:500;white-space:nowrap;}
.chip.hot{background:var(--ink);color:var(--bg);border-color:var(--ink);}

/* --- giant type band -------------------------------------- */
.band{padding-block:clamp(14px,1.7vw,24px);overflow:hidden;border-block:1px solid var(--line);}
.band-row{
  display:flex;gap:.8em;width:max-content;animation:sl 38s linear infinite;
  /* A quarter of the original ~134px. It reads as a running strip of offices
     now rather than a display headline, so the tracking relaxes towards normal
     — the tight -.04em that suited 115px crushes the words at this size. */
  font-size:clamp(1.15rem,2.5vw,2.4rem);font-weight:700;letter-spacing:-.02em;line-height:1;white-space:nowrap;
}
.band:hover .band-row{animation-play-state:paused;}
.band-row em{font-style:normal;color:var(--accent);}

/* --- word roulette ---------------------------------------- */
/* General Sans draws a 1.25em glyph box (ascent 1.01 + descent 0.24) inside a
   1.1 line box, so a window clipped to 1.1em cut the descenders off "Operating"
   and "Governing" and let the next word'"'"'s ink leak in at the top. Each stacked
   word now carries padding for its own overhang and the window grows to match;
   a negative margin gives that height back so the headline'"'"'s leading is
   unchanged. In em, so it scales with the clamped display size — and since the
   step distance JS reads from getBoundingClientRect() includes padding, the
   rotation stays aligned with no change to the script. */
.roul{
  --roul-pad:0.1em;
  display:inline-block;overflow:hidden;vertical-align:bottom;
  height:calc(1.1em + var(--roul-pad) * 2);
  margin-block:calc(var(--roul-pad) * -1);
}
.roul-in{display:flex;flex-direction:column;transition:transform 1.5s var(--ease);}
.roul-in>span{display:block;line-height:1.1;white-space:nowrap;color:var(--yellow);padding-block:var(--roul-pad);}
/* The verb window rotates like the others but stays in the headline's base
   colour: the two-tone rule puts one emphasis phrase per headline, and three
   yellow words in four lines would leave nothing for the accent to emphasise. */
.roul.plain .roul-in>span{color:inherit;}
html[lang="ja"] .roul{height:calc(1.35em + var(--roul-pad) * 2);}
html[lang="ja"] .roul-in>span{line-height:1.35;}

/* --- announcement rail ------------------------------------ */
/* Every announcement is on screen at once. The earlier version rotated one at a
   time behind prev/next, which meant five of the six proof points were invisible
   unless the visitor waited 30 seconds — the opposite of what they are for.
   The 1px grid gap over the line colour draws the rules between cells, so there
   are no borders to double up at the edges. */
/* The band reads on the alternate page ground rather than a dark strip, so the
   proof points sit in the light with the rest of the page. Every colour here is
   a token, so the dark theme swaps the ground to #2E251C and the figures from
   red to yellow without another rule. */
.rail{position:relative;z-index:2;border-top:1px solid var(--line);color:var(--ink);background:var(--bg-2);}
.rail .w{padding-block:22px 32px;}
.rail-k{display:flex;align-items:center;gap:9px;color:var(--accent);white-space:nowrap;margin-bottom:16px;}
.rail-k b{width:8px;height:8px;border-radius:50%;background:var(--accent);flex:0 0 auto;}
.rail-grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:1px;background:var(--line);
  border-block:1px solid var(--line);
}
.ann{background:var(--bg-2);padding:24px 26px 26px;display:flex;flex-direction:column;gap:10px;}
.rail-grid > .ann:nth-child(3n+1){padding-inline-start:0;}

/* Each announcement leads with its figure, so the proof lands before the
   sentence is read. Numerals take the ultralight display weight the design
   system uses for stats; word figures ($15B vs "Palo Alto") cannot carry that
   size without wrapping, so they step down and pick up the label treatment. */
.ann-fig{
  font-size:clamp(2rem,3.1vw,2.9rem);font-weight:300;line-height:1;
  letter-spacing:-.02em;color:var(--accent);
  /* Bottom-aligned inside a numeral-height box so the rule under a short word
     figure lands on the same line as the rule under "$15B" across the row. */
  display:flex;flex-direction:column;justify-content:flex-end;
  min-height:calc(clamp(2rem,3.1vw,2.9rem) + 16px);   /* numeral + the rule below it */
}
.ann-fig.word{
  font-size:var(--fs-d4);font-weight:700;line-height:1.15;
  letter-spacing:.02em;text-transform:uppercase;
}
.ann-fig::after{
  content:"";display:block;width:34px;height:2px;margin-top:14px;
  background:var(--accent);
}
.ann-t{font-size:var(--fs-body);font-weight:500;line-height:1.5;color:var(--ink-2);}

/* --- capability index ------------------------------------- */
.cap-idx{border-top:2px solid var(--ink);}
.cap-row{
  border-bottom:2px solid var(--ink);padding-block:clamp(28px,3.2vw,44px);
  /* The mark column is sized by the mark, not by a share of the row. As a
     fraction it reserved 341px for a 110px number-and-symbol and left the rest
     as a hole, which put the capability headings 341px in from a page whose
     every other block starts at the gutter. `auto` is shared across rows, so
     the six marks still align with each other. */
  display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr);gap:clamp(20px,3vw,40px);
}
.cap-mark{display:flex;align-items:flex-start;gap:16px;}
.cap-mark .n{font-family:var(--mono);font-size:.72rem;color:var(--accent);padding-top:8px;flex:0 0 auto;}
.cap-mark svg{width:clamp(48px,5vw,72px);height:auto;flex:0 0 auto;}
.cap-body h3{margin-bottom:12px;}
.cap-body p{color:var(--ink-2);max-width:58ch;font-size:var(--fs-body);margin-bottom:20px;}

/* --- attributed stats ------------------------------------- */
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,3vw,44px);}
.stat{border-left:1.5px solid var(--line);padding-left:clamp(18px,2.2vw,30px);}
.stat b{display:block;font-size:clamp(3rem,6.2vw,5.6rem);font-weight:300;letter-spacing:-.045em;line-height:1;font-variant-numeric:tabular-nums;}
.stat p{margin-top:16px;color:var(--ink-2);font-size:var(--fs-body);font-weight:300;max-width:24ch;}
.stat .who{display:block;margin-top:20px;font-size:.98rem;font-weight:700;}

/* --- cards ------------------------------------------------ */
.cards{display:grid;gap:clamp(18px,2.4vw,28px);}
.cards.c2{grid-template-columns:repeat(2,1fr);}
.cards.c3{grid-template-columns:repeat(3,1fr);}
.cards.c4{grid-template-columns:repeat(4,1fr);}
.card{border-top:2px solid var(--ink);padding-top:22px;}
/* Some cards are links (the engagement tiles the cursor offers as "view case").
   They keep the card look but take a colour and rule shift on hover so the
   promise the cursor makes is visible without one. */
a.card{display:block;color:inherit;transition:border-color .22s,color .22s;}
/* the header is fixed at 76px, so an anchored card has to stop below it */
.card[id]{scroll-margin-top:104px;}
a.card:hover{border-top-color:var(--accent);color:var(--accent);}
a.card:hover p{color:var(--ink-2);}
.card h3{margin-bottom:10px;}
.card p{color:var(--ink-2);font-size:1rem;font-weight:300;line-height:1.45;}
/* Engagement cards name the platforms they were held on. A card is half a
   section wide, and a pill holding a whole phrase — "Cloud identity and access
   management" — has nowhere to go on that column, so inside a card it wraps
   instead of pushing out of one. */
.card .pills{margin-top:16px;}
.card .pills .pill{white-space:normal;}

/* --- comparison ------------------------------------------- */
.compare{display:grid;grid-template-columns:1fr 1fr;gap:clamp(18px,2.6vw,32px);}
.compare-col{border-radius:16px;padding:clamp(24px,3vw,40px);}
.compare-col.old{background:var(--bg-3);}
.compare-col.new{background:var(--panel);color:var(--on-panel);}
.compare-col h3{margin-bottom:22px;padding-bottom:18px;border-bottom:1px solid var(--line-2);}
.compare-col.new h3{border-bottom-color:var(--panel-line);}
.compare-col li{padding:15px 0;border-bottom:1px solid var(--line);font-size:1rem;color:var(--ink-2);}
.compare-col.new li{border-bottom-color:var(--panel-line);color:var(--on-panel-2);}
.compare-col li:last-child{border-bottom:0;}
.compare-col.new .hi{color:var(--yellow);font-weight:700;}

/* --- location cards --------------------------------------- */
.locs{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(14px,2vw,24px);}
.loc{--loc-pad:clamp(20px,2.4vw,30px);
  background:var(--bg);border:1.5px solid var(--line);border-radius:16px;
  padding:var(--loc-pad);overflow:hidden;}
/* The office photo sits flush to the card edges rather than inset — negative
   margins pull it back out through the card's own padding, and the card's
   overflow clip rounds its top corners. Until a file lands the .fig gradient
   shows, so a missing photo reads as a deliberate block, not a broken image. */
/* `.fig` sets margin:0 further down this file, so this needs the extra class to
   win rather than relying on source order. */
/* square here on purpose: the photo runs to the card's edges, and the card's own
   radius plus overflow clip round it — its own radius would notch the corners */
.loc > .loc-img{margin:calc(-1 * var(--loc-pad)) calc(-1 * var(--loc-pad)) 20px;aspect-ratio:16/10;border-radius:0;}
.loc > .loc-img img{display:block;width:100%;height:100%;object-fit:cover;}
.loc h3{font-size:1.3rem;margin-bottom:4px;}
.loc .zone{font-family:var(--mono);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin-bottom:14px;}
.loc p{color:var(--ink-2);font-size:.95rem;}
.loc .clock{font-family:var(--mono);font-size:1.5rem;margin-top:16px;font-variant-numeric:tabular-nums;letter-spacing:-.02em;}
.loc.on .clock{color:var(--accent);}

/* --- index list (values, why, etc.) ----------------------- */
.idx{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(28px,5vw,72px);}
.idx-item{padding:18px 0;border-top:1px solid var(--line);display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:start;}
/* Same job as .tag, so the same size: an accent-red mono label carrying the
   index number. At .68rem it sat below the floor the tag token was raised to. */
.idx-item .k{font-family:var(--mono);font-size:var(--fs-tag);color:var(--accent);padding-top:5px;}
.idx-item h3{font-size:1.06rem;font-weight:700;margin-bottom:5px;}
.idx-item p{color:var(--ink-2);font-size:var(--fs-body);}

/* --- timeline --------------------------------------------- */
.tl{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,2.4vw,30px);border-top:2px solid var(--ink);}
.tl-node{padding-top:22px;position:relative;}
.tl-node::before{content:'';position:absolute;top:-7px;left:0;width:12px;height:12px;border-radius:50%;background:var(--accent);}
.tl-node .yr{font-family:var(--mono);font-size:.72rem;letter-spacing:.14em;color:var(--ink-3);margin-bottom:8px;}
.tl-node p{font-size:1rem;color:var(--ink-2);}

/* --- form ------------------------------------------------- */
.form{display:grid;gap:20px;}
.field label{display:block;font-size:.94rem;font-weight:700;margin-bottom:7px;}
.field .req{color:var(--accent);}
.field input,.field textarea,.field select{
  width:100%;padding:14px 16px;border:1.5px solid var(--line-2);border-radius:6px;
  background:var(--bg);font-size:1rem;transition:border-color .2s;
}
.field input:focus,.field textarea:focus,.field select:focus{border-color:var(--ink);}
.field textarea{min-height:140px;resize:vertical;}
.field .err{display:none;color:var(--accent);font-size:.88rem;margin-top:6px;font-weight:500;}
.field.invalid input,.field.invalid textarea,.field.invalid select{border-color:var(--accent);}
.field.invalid .err{display:block;}
.check{display:flex;gap:12px;align-items:flex-start;font-size:.94rem;color:var(--ink-2);}
.check input{width:20px;height:20px;flex:0 0 auto;margin-top:2px;}
/* The privacy link sits mid-sentence, so it stays inline — the WCAG 2.5.8
   exception for links in a run of text — and is marked by underline, not size. */
.check a{color:var(--link);text-decoration:underline;text-underline-offset:2px;}
/* The consent box sits outside .field, so it needs its own invalid state or it
   is the one required control that fails silently. */
.check.invalid{color:var(--accent);}
.check.invalid input{outline:2px solid var(--accent);outline-offset:2px;}
.form-summary{display:none;border:1.5px solid var(--accent);border-radius:8px;padding:16px 18px;background:var(--bg-2);}
.form-summary.on{display:block;}
.form-summary h3{color:var(--accent);margin-bottom:8px;font-size:1rem;}
.form-summary a{color:var(--accent);text-decoration:underline;display:block;padding:4px 0;}
/* Shown once the message has been handed to the visitor's mail client. It is
   the counterpart of .form-summary, so it takes the same box — but in ink
   rather than the error accent, and it stays put rather than disappearing on
   the next keystroke. */
.form-sent{border:1.5px solid var(--ink);border-radius:8px;padding:18px 20px;background:var(--bg-2);margin-top:22px;}
.form-sent[hidden]{display:none;}
.form-sent h3{font-size:1.06rem;margin-bottom:8px;}
.form-sent p{color:var(--ink-2);font-size:.98rem;line-height:1.6;}
.form-sent p + p{margin-top:8px;}
.form-sent a{color:var(--link);text-decoration:underline;text-underline-offset:2px;}

/* --- custom cursor ---------------------------------------- */
.cur{
  position:fixed;top:0;left:0;z-index:200;pointer-events:none;
  width:14px;height:14px;border-radius:999px;background:var(--yellow);
  display:grid;place-items:center;overflow:hidden;
  transition:width .32s var(--ease),height .32s var(--ease),background .25s;
}
.cur span{font-size:.9rem;font-weight:700;color:#141210;white-space:nowrap;opacity:0;transition:opacity .2s;}
.cur.big{width:118px;height:44px;}
.cur.big span{opacity:1;}
.cur.onfield{background:#141210;}
.cur.onfield span{color:var(--yellow);}
@media (hover:none),(pointer:coarse){.cur{display:none;}}

/* --- figures ----------------------------------------------
   Photography is square-cornered by rule — the cards are rounded, the pictures
   are not, so an image always reads as a window rather than a component.

   The warm gradient is not decoration: it is the placeholder. Assets are
   generated one at a time, so every slot has to look deliberate while its file
   is still missing. js/main.js drops any <picture> whose image fails to load,
   leaving this ground exposed instead of a broken-image icon. */
.fig{
  position:relative;margin:0;overflow:hidden;border-radius:var(--r-img);
  background:
    radial-gradient(72% 60% at 28% 26%,rgba(240,206,26,.20),transparent 64%),
    radial-gradient(60% 55% at 78% 76%,rgba(61,90,166,.30),transparent 62%),
    linear-gradient(140deg,var(--hero-1) 0%,var(--hero-2) 58%,var(--hero-3) 100%);
}
.fig img{display:block;width:100%;height:100%;object-fit:cover;}
.fig figcaption{
  font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);padding-top:12px;
}
html[lang="ja"] .fig figcaption{font-family:var(--sans);letter-spacing:.06em;}

/* aspect ratios — the slot reserves its space before the file arrives, so a
   late-loading image never shifts the page */
.fig.r219{aspect-ratio:21/9;}
.fig.r169{aspect-ratio:16/9;}
.fig.r1610{aspect-ratio:16/10;}
.fig.r32{aspect-ratio:3/2;}
.fig.r43{aspect-ratio:4/3;}
.fig.r11{aspect-ratio:1/1;}
.fig-cap{aspect-ratio:auto;background:none;}
.fig-cap > .fig{margin-bottom:0;}

/* full-bleed banner: escapes .w without a horizontal scrollbar */
.banner{margin-block:clamp(28px,4vw,56px);}
@media (max-width:620px){
  /* 21:9 is a letterbox on a phone — crop to something you can actually see */
  .fig.r219{aspect-ratio:16/10;}
}

/* --- reveal (added by JS; no-JS renders everything) -------- */
.js .rv{opacity:0;transform:translateY(22px);}
.js .rv.in{opacity:1;transform:none;transition:opacity .75s var(--ease),transform .75s var(--ease);}


/* ===== sections ===== */

/* ============================================================
   LAYER 4 · SECTIONS — composed of components
   ============================================================ */

.sect{padding-block:var(--sect);}
.sect-sm{padding-block:var(--sect-sm);}
.sect-alt{background:var(--bg-2);border-block:1px solid var(--line);}

/* Where the ground changes, a section's padding is the tinted band breathing
   around its own contents and both sides earn their space. Where it does not —
   two plain sections running on the same white — there is no band, and the two
   paddings simply add up into a void: the media strip on the IAM page sat 144px
   clear of the section under it with nothing in between. Same ground, so the
   boundary keeps one step instead of two. Same reasoning as `.statement + .sect`
   below, generalised. */
.sect:not(.sect-alt) + .sect:not(.sect-alt),
.sect:not(.sect-alt) + .sect-sm:not(.sect-alt),
.sect-sm:not(.sect-alt) + .sect:not(.sect-alt),
.sect-sm:not(.sect-alt) + .sect-sm:not(.sect-alt){padding-top:clamp(20px,2.4vw,34px);}
/* The same boundary, one step earlier: the page hero already closes with a rule
   and a full measure of padding, so the band under it opens with the short step
   too. A tinted section still takes its own, for the reason above. */
.hero-page + .sect:not(.sect-alt),
.hero-page + .sect-sm:not(.sect-alt){padding-top:clamp(20px,2.4vw,34px);}

.sect-hd{margin-bottom:clamp(26px,3.1vw,46px);}
.sect-hd .tag{color:var(--accent);display:block;margin-bottom:16px;}
/* One step down from --fs-d2. A section heading, the closing statement and the
   finale were all rendering at the same 64px, which left the page with no
   hierarchy between "here is point 01" and "here is what the company is" — the
   two loudest lines on the page were the least and most important. The max-width
   grows in step so the measure the 15ch cap produced at the larger size is
   preserved and the heading still wraps into the same tight block. */
.sect-hd .d2,
/* Not every section heading sits in a .sect-hd — the two-column sections put the
   heading in the first column of the split instead, and those were left at the
   full 64px while their neighbours stepped down, which is the hierarchy problem
   above still live on the same page. Same role, same size. */
.sect-split > .d2{font-size:clamp(1.9rem,3.4vw,3rem);max-width:20ch;}
.sect-hd.wide .d2{max-width:28ch;}
.sect-split{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(24px,5vw,72px);align-items:start;}
/* Image on one side, words on the other. A picture this size sitting alone
   across the full width says nothing; halved and paired with a line of copy it
   carries an idea — and the type stays on the page ground, where it is legible,
   rather than fighting a busy photograph for contrast. */
.sect-split.media{grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;}
.sect-split.media .fig{align-self:stretch;}
.sect-split.media .lead{color:var(--ink-2);margin:14px 0 0;}
.sect-split.media .lnk{margin-top:22px;display:inline-block;}
.sect-split .lead{color:var(--ink-2);margin-bottom:16px;}

/* --- hero: video (home only) ------------------------------ */
.hero-video{position:relative;min-height:100svh;display:flex;align-items:center;overflow:hidden;background:var(--hero-3);}
.hero-video video,.hero-video .vid-fallback{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
/* The gradient is the no-video state, and it follows the <video> in the DOM, so
   it paints over it. Lift the video above it and fade the gradient out once the
   file is actually playing — if the video never loads, nothing changes and the
   gradient stays, which is the whole point of it. */
/* The hero is a dark field with white and yellow type on it, and the scrim was
   measured against dark footage. Bright footage — a daylit office — puts white
   type on near-white pixels and the headline stops being readable. Darkening
   the video here rather than in the file keeps the source untouched and lets
   any clip, light or dark, sit under the same type. */
/* This montage swings from near-white transitions to near-black interiors, and
   a flat brightness cut can only serve one end: set low enough for the white
   frames, the dark scenes disappear entirely. Reducing contrast first lifts the
   shadows and pulls the highlights toward each other, so the whole clip lands
   in a band the scrim can cover — white maps to ~150 (the ceiling the yellow
   accent can tolerate) while black lifts from 16 to ~39 and stays visible. */
.hero-video video{z-index:1;filter:contrast(.7) brightness(.69) saturate(.98);}
.hero-video .vid-fallback{z-index:0;transition:opacity .6s ease;}
.hero-video.has-video .vid-fallback{opacity:0;}
.hero-video .vid-fallback{
  background:
    radial-gradient(60% 50% at 26% 30%,rgba(240,206,26,.26),transparent 62%),
    radial-gradient(60% 55% at 76% 74%,rgba(61,90,166,.44),transparent 62%),
    linear-gradient(140deg,var(--hero-1) 0%,var(--hero-2) 58%,var(--hero-3) 100%);
}
/* Two scrims, because the type sits in two directions. The horizontal ramp
   protects the headline and lead; the vertical one protects the header, which
   spans the full width and so runs past every horizontal stop. Both are the
   same warm sepia, so a missing video still reads as brand colour. */
.hero-video::after{
  content:'';position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(180deg,var(--scrim-top) 0,transparent 190px),
    linear-gradient(90deg,var(--scrim-1) 0%,var(--scrim-2) 40%,var(--scrim-3) 70%,var(--scrim-4) 100%);
}
.hero-video .hero-in{position:relative;z-index:2;width:100%;padding-block:120px 40px;color:var(--on-dark);}

/* The roulette windows must stay `white-space:nowrap` — the rotation reads each
   word's height from getBoundingClientRect(), so a wrapped slot would break the
   step distance. That makes the widest word set the width, and it cannot reflow.
   Japanese runs full-width: 「アイデンティティを、」 is 10em against 7.5em for the
   longest English slot ("cloud platforms"), so once --fs-d1 hits its 2.1rem floor
   the JA headline overshot the gutter and was silently clipped by the root's
   overflow-x — 16px lost at 375px, 71px (two whole characters) at 320px.
   Cap the JA hero on viewport width so the widest slot always lands inside the
   gutter. min() keeps --fs-d1 in charge everywhere above ~400px, so this is a
   no-op on tablet and desktop and needs no breakpoint. */
html[lang="ja"] .hero-video .d1{font-size:min(var(--fs-d1),calc(9.2vw - 4px));}
/* Insurance against a bright frame drifting under a letterform: too soft to
   read as a drop shadow, enough to hold the edge apart from the picture. */
.hero-video h1,.hero-video .lead{text-shadow:0 1px 20px rgba(20,16,12,.5);}
.hero-video h1{margin-bottom:26px;max-width:15ch;}
.hero-video .lead{color:var(--on-dark-2);max-width:44ch;margin-bottom:32px;}
.hero-cta{display:flex;gap:12px;flex-wrap:wrap;}

/* --- hero: standard page ---------------------------------- */
.hero-page{padding-block:clamp(120px,13vw,190px) var(--sect-sm);border-bottom:1px solid var(--line);}
.hero-page .tag{color:var(--accent);display:block;margin-bottom:18px;}
.hero-page h1{max-width:17ch;margin-bottom:22px;}
.hero-page .lead{color:var(--ink-2);max-width:56ch;}
.hero-page .hero-cta{margin-top:32px;}

/* --- statement -------------------------------------------- */
.statement{padding-block:clamp(56px,7vw,112px);}
.statement h2{font-size:var(--fs-d2);font-weight:700;line-height:1.18;letter-spacing:-.0225em;}
/* These two headings carry the display size without the .d1–.d4 classes, so
   they need the Japanese phrase-breaking treatment spelled out (see base). */
html[lang="ja"] .statement h2{
  letter-spacing:-.005em;line-height:1.45;
  line-break:strict;word-break:auto-phrase;overflow-wrap:break-word;text-wrap:pretty;
}
.statement .sub{margin-top:26px;color:var(--ink-2);max-width:56ch;}
/* The statement carries its own generous padding, and the section after it adds
   its own on top — 124px + 72px left 196px of empty page between two blocks of
   text. The statement's space is enough on its own, so whatever follows starts
   flush against it. */
.statement + .sect,
.statement + .sect-sm{padding-top:0;}
/* …unless the statement carries its own ground. Then the page colour changes at
   the boundary, and a following section with no top padding drops its eyebrow
   11px under that change — it reads as a section that has fallen into the one
   above it rather than as a new one. */
.statement.sect-alt + .sect,
.statement.sect-alt + .sect-sm{padding-top:var(--sect-sm);}

/* --- finale ----------------------------------------------- */
.finale{background:var(--field);color:var(--on-field);padding-block:clamp(60px,7.6vw,116px);}
.finale h2{font-size:var(--fs-d2);font-weight:700;line-height:1.18;letter-spacing:-.0225em;max-width:22ch;}
html[lang="ja"] .finale h2{
  letter-spacing:-.005em;line-height:1.45;
  line-break:strict;word-break:auto-phrase;overflow-wrap:break-word;text-wrap:pretty;
}
.finale .alt{color:var(--field-2);}
.finale .lead{margin-top:20px;max-width:52ch;}
.finale .hero-cta{margin-top:clamp(28px,3.4vw,46px);}

/* --- work grid -------------------------------------------- */
/* Four engagements, all four on screen. This was a horizontal scroller, which
   put half the cards off the right edge and depended on a scrollbar to admit
   they existed. No rules between them — the spacing separates them, and the
   cards are links, so a rule would read as a divider rather than as structure. */
.work-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(26px,3.2vw,48px);}
.work-grid .card{border-top:0;padding-top:0;}

/* --- services carousel ------------------------------------ */
/* All six capabilities on screen, two across and three down. This was a
   carousel showing one at a time behind 06 ← / 02 → paging, which meant five of
   the six were invisible — on the page whose whole job is to say what the
   company does. Each keeps the mark the carousel used to swap in for it. */
.svc-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(30px,3.6vw,56px);margin-top:30px;}
.svc-item{display:flex;flex-direction:column;align-items:flex-start;gap:12px;
  border-top:1.5px solid var(--line);padding-top:24px;}
.svc-ic{width:52px;height:52px;flex:0 0 auto;}
.svc-ic .disc{fill:var(--yellow);}
.svc-ic .cut{fill:var(--bg-2);}      /* the ground, so the mark reads in both themes */
.svc-item h3{letter-spacing:-.02em;}
.svc-item p{color:var(--ink-2);font-size:1.01rem;line-height:1.6;max-width:46ch;}
.svc-item .pills{margin-top:2px;}
@keyframes fadeUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

/* --- legal / long-form ------------------------------------ */
.legal{padding-block:clamp(120px,13vw,190px) var(--sect);}
.legal-grid{display:grid;grid-template-columns:minmax(0,220px) minmax(0,1fr);gap:clamp(28px,5vw,72px);align-items:start;}
.legal-toc{position:sticky;top:100px;}
.legal-toc li a{display:block;padding:7px 0;font-size:.94rem;color:var(--ink-2);}
.legal-toc li a:hover{color:var(--accent);}
.legal-body{max-width:72ch;}
.legal-body h2{font-size:1.5rem;font-weight:700;margin:44px 0 14px;letter-spacing:-.015em;}
.legal-body h2:first-child{margin-top:0;}
.legal-body p{margin-bottom:14px;color:var(--ink-2);font-size:1.0625rem;line-height:1.72;}
.legal-body ul{margin:0 0 14px 0;}
.legal-body ul li{padding:5px 0 5px 22px;position:relative;color:var(--ink-2);font-size:1.0625rem;line-height:1.72;}
.legal-body ul li::before{content:'';position:absolute;left:6px;top:15px;width:5px;height:5px;border-radius:50%;background:var(--accent);}
.legal-meta{font-family:var(--mono);font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);margin-bottom:32px;}

/* --- 404 -------------------------------------------------- */
.nf{min-height:70svh;display:grid;place-items:center;text-align:center;padding-block:var(--sect);}
.nf h1{max-width:16ch;margin-inline:auto;margin-bottom:20px;}
.nf .lead{color:var(--ink-2);max-width:48ch;margin-inline:auto;margin-bottom:36px;}
.nf-links{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;}
.nf-links a{border:1.5px solid var(--line-2);border-radius:999px;padding:11px 20px;font-weight:500;transition:.2s;}
.nf-links a:hover{border-color:var(--ink);background:var(--ink);color:var(--bg);}


/* ===== pages ===== */

/* ============================================================
   LAYER 5 · PAGES — page-specific overrides only.
   If a rule here would help another page, it belongs in
   components or sections instead.
   ============================================================ */

/* --- home ------------------------------------------------- */
[data-page="home"] .statement h2{max-width:26ch;}

/* --- contact ---------------------------------------------- */
[data-page="contact"] .contact-grid{
  display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  gap:clamp(28px,5vw,72px);align-items:start;
}
[data-page="contact"] .direct li{padding:14px 0;border-top:1px solid var(--line);}
[data-page="contact"] .direct .who{font-weight:700;display:block;margin-bottom:3px;}
[data-page="contact"] .direct a{color:var(--link);text-decoration:underline;}
@media (max-width:1080px){
  [data-page="contact"] .contact-grid{grid-template-columns:1fr;}
}

/* --- insights --------------------------------------------- */
/* Three tracks: label, mark, words. The mark used to sit inside the text column
   at the full 1098px, which made a flat saffron circle the largest object on a
   page whose actual content is a headline and two lines of summary — the
   announcement read as a caption to its own decoration. These are marks, not
   photographs; at 84px the circle, star, arc and bars are legible as devices and
   the headline is what the eye lands on. */
[data-page="insights"] .post{
  display:grid;grid-template-columns:minmax(0,104px) 84px minmax(0,1fr);
  gap:clamp(14px,2.4vw,32px);padding:22px 0;border-top:1px solid var(--line);align-items:center;
}
[data-page="insights"] .post > .post-mark{width:84px;height:84px;border-radius:12px;}
[data-page="insights"] .post .meta{font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);}
[data-page="insights"] .post h3{margin-bottom:8px;}
[data-page="insights"] .post p{color:var(--ink-2);font-size:1rem;font-weight:300;max-width:62ch;}
@media (max-width:620px){
  /* The mark holds the left edge and spans both rows; the label sits above the
     headline rather than beside it. minmax(0,1fr), not 1fr: a bare 1fr track
     floors at min-content, and with Japanese phrase breaking min-content is a
     whole phrase — wide enough to push the track past a 320px screen. */
  [data-page="insights"] .post{grid-template-columns:56px minmax(0,1fr);gap:6px 16px;align-items:start;}
  [data-page="insights"] .post > .post-mark{grid-column:1;grid-row:1 / span 2;width:56px;height:56px;}
  [data-page="insights"] .post .meta{grid-column:2;grid-row:1;}
  [data-page="insights"] .post > div:last-child{grid-column:2;grid-row:2;}
}

/* --- careers ---------------------------------------------- */
[data-page="careers"] .role{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:20px;
  padding:22px 0;border-top:1px solid var(--line);align-items:center;
}
[data-page="careers"] .role .where{font-family:var(--mono);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);margin-top:5px;}
[data-page="careers"] .empty{
  border:1.5px dashed var(--line-2);border-radius:12px;padding:clamp(24px,3vw,40px);text-align:center;
}
@media (max-width:620px){
  [data-page="careers"] .role{grid-template-columns:minmax(0,1fr);align-items:start;}
}


/* ===== utilities ===== */

/* ============================================================
   LAYER 5 · RESPONSIVE + UTILITIES — last layer, wins on purpose
   ============================================================ */

.mt-0{margin-top:0!important;}
.mt-1{margin-top:12px;}
.mt-2{margin-top:24px;}
.mt-3{margin-top:40px;}
.mb-2{margin-bottom:24px;}
.center{text-align:center;}
.hide{display:none!important;}

/* The nav grows leftward into the gap after the logo, and that gap is what runs
   out first. Below ~1160px there is no longer room for the full 22px, so it
   steps back to 20px rather than colliding with the language switch. */
@media (max-width:1160px){
  .nav a,.nav .navbtn{font-size:1.25rem;}
}

/* Japanese runs ~30% wider at the same size — 770px of nav against 664px — so
   it needs its own ladder, one step ahead of the Latin one. It also reads
   optically larger at a given pixel size, so 20px JA sits beside 22px Latin
   without looking smaller. */
@media (min-width:1241px){
  html[lang="ja"] .nav a,html[lang="ja"] .nav .navbtn{font-size:1.25rem;}
}
@media (max-width:1240px){
  html[lang="ja"] .nav{gap:18px;}
  html[lang="ja"] .nav a,html[lang="ja"] .nav .navbtn{font-size:1.125rem;}
}
@media (max-width:1160px){
  html[lang="ja"] .nav a,html[lang="ja"] .nav .navbtn{font-size:1.0625rem;}
}

/* ---------- ≤1080px ---------- */
@media (max-width:1080px){
  /* .sect-split.media is two classes, so it outranks a bare .sect-split however
     late this layer comes — without matching that specificity the image/text
     band stayed two columns on a phone and pushed the page 39px wide. */
  .sect-split,.sect-split.media,.legal-grid{grid-template-columns:1fr;}
  .legal-toc{position:static;}
  .cards.c3,.cards.c4{grid-template-columns:repeat(2,1fr);}
  .locs{grid-template-columns:repeat(2,1fr);}
  .stats{grid-template-columns:1fr;}
  .stat{border-left:0;border-top:1.5px solid var(--line);padding-left:0;padding-top:20px;}
  .compare{grid-template-columns:1fr;}
  .tl{grid-template-columns:repeat(2,1fr);row-gap:30px;}
  .ft-grid{grid-template-columns:1fr 1fr;}
  .cap-row{grid-template-columns:1fr;gap:18px;}
  /* The lockup is the widest fixed item in the header, and below 1080 it has to
     share the row with a horizontal nav — Japanese labels run ~30% longer than
     English. Shrinking it is what keeps the nav on one line. */
  .logo img{height:36px;}
  html[lang="ja"] .nav{gap:18px;}
  html[lang="ja"] .nav a,html[lang="ja"] .nav .navbtn{font-size:1rem;}
}

/* ---------- ≤860px : nav becomes a drawer ---------- */
@media (max-width:860px){
  .nav{
    position:fixed;inset:76px 0 auto 0;flex-direction:column;align-items:stretch;gap:0;
    background:var(--bg);color:var(--ink);border-top:1px solid var(--line);
    padding:8px var(--gut) 28px;max-height:calc(100svh - 76px);overflow-y:auto;
    transform:translateY(-8px);opacity:0;visibility:hidden;
    transition:opacity .25s,transform .25s,visibility .25s;
  }
  .hdr.menu-open .nav{opacity:1;visibility:visible;transform:none;}
  .nav > li{border-bottom:1px solid var(--line);}
  .nav a,.nav .navbtn{padding:17px 0;font-size:1.08rem;width:100%;justify-content:space-between;}
  .nav a::after{display:none;}
  .drop{
    position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;
    background:transparent;padding:0 0 14px 0;min-width:0;display:none;
  }
  .nav li.open .drop{display:block;}
  .drop a{padding:12px 0 12px 16px;font-size:1rem;}
  .drop a small{display:none;}
  .burger{display:flex;}
  .hdr .tgl,.hdr .snd{display:none;}
  .hdr-act{margin-left:auto;}
  /* Touch targets: the accessibility floor is 44px, and these three sat at
     29-38px — fine for a cursor, not for a thumb. Padding rather than height so
     the type does not move. */
  .lnk{padding-block:9px;}
  .langsw a{min-height:44px;}
  /* two announcements per row, and the first of each pair loses its inset */
  .rail-grid{grid-template-columns:repeat(2,1fr);}
  .rail-grid > .ann:nth-child(3n+1){padding-inline-start:26px;}
  .rail-grid > .ann:nth-child(2n+1){padding-inline-start:0;}
  .ann-fig::after{margin-top:11px;}
  .idx{grid-template-columns:1fr;}
  .ft-grid{grid-template-columns:1fr;}
  .band-row{font-size:clamp(1.02rem,3.6vw,1.6rem);}
}

/* On a phone the headline spans nearly the full width, so it runs past every
   stop of the desktop ramp, and `cover` crops the video to its bright middle
   instead of its darker edge. There is no picture area left to protect at this
   size, so the ramp flattens out and stays strong the whole way across. */
@media (max-width:860px){
  .hero-video::after{
    background:
      linear-gradient(180deg,var(--scrim-top) 0,transparent 190px),
      linear-gradient(90deg,var(--scrim-1) 0%,var(--scrim-mob-2) 40%,var(--scrim-mob-3) 70%,var(--scrim-mob-4) 100%);
  }
}

/* ---------- ≤620px ---------- */
@media (max-width:620px){
  .cards.c2,.cards.c3,.cards.c4,.work-grid{grid-template-columns:1fr;}
  .svc-grid{grid-template-columns:1fr;}
  .rail-grid{grid-template-columns:1fr;}
  .rail-grid > .ann{padding-inline:0 !important;padding-block:16px 18px;}
  .locs{grid-template-columns:1fr;}
  .tl{grid-template-columns:1fr;}
  .hero-cta .btn{width:100%;justify-content:center;}
  .statement h2,.finale h2{font-size:clamp(1.7rem,7.2vw,2.3rem);}
  .sect-hd .d2{max-width:none;}
  /* Pills hold whole phrases — "Identity governance and administration" is
     wider than a small phone, so below 620 they wrap rather than push the row. */
  .pill,.chip{white-space:normal;overflow-wrap:break-word;}
}

/* ---------- ≤400px : narrow phones ---------- */
@media (max-width:400px){
  /* Lockup, language switch and burger have to share ~280px of usable width. */
  .hdr-in{gap:10px;}
  .logo img{height:30px;}
  .langsw a{min-width:44px;padding:9px 8px;}
  .burger{width:44px;}
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  .mq-row,.band-row,.snd b{animation:none!important;}
  .js .rv{opacity:1;transform:none;}
  .cur{display:none;}
}

/* ---------- print ---------- */
@media print{
  .hdr,.ft,.cur,.rail,.mq,.band,.hero-cta{display:none!important;}
  body{background:#fff;color:#000;font-size:11pt;}
  .sect,.legal{padding-block:0;}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;}
}
