/* ==========================================================================
   Quantum Jump Holdings — Landing Page
   ========================================================================== */

:root{
  /* Site accent — SmartGrid blue. The token keeps its original name
     (--red) from the earlier red-accented design; every accent on the
     page reads from it, EXCEPT QuantumJump's Company column, which uses
     --qj-red below. */
  --red: #00457a;
  --red-dark: #003157;
  --red-soft: #c3d5e2;
  /* QuantumJump's original red — used only by its Company column
     (.company-group--alt). */
  --qj-red: #c0392e;
  --ink: #1a1712;
  --ink-soft: #4a453e;
  --cream: #f4efe6;
  --cream-2: #ece4d6;
  --paper: #fbf9f5;
  --line: rgba(26,23,18,.12);
  --dark-bg: #141210;
  /* Shared brand-accent color for the Company blocks — defaults to the
     site accent (blue), overridden per group company (QuantumJump's
     column sets --qj-red via .company-group--alt) so the two blocks can
     reuse the exact same component classes. */
  --brand-accent: var(--red);

  --ff-serif: "Shippori Mincho", serif;
  --ff-display: "Oswald", sans-serif;
  --ff-script: "Playfair Display", serif;

  --ease: cubic-bezier(.16,.84,.44,1);
  --dur: .8s;

  --header-h: 84px;
}

*,*::before,*::after{ box-sizing: border-box; }

html{
  scroll-behavior: smooth;
  overflow-x: hidden;
  /* Reserve the vertical scrollbar's space so locking the page while a
     modal is open (html.is-modal-open below) doesn't shift the layout
     when the scrollbar disappears. No-op with overlay scrollbars. */
  scrollbar-gutter: stable;
}
/* Page scroll lock while an overlay is open — the exec-message modal, or
   the mobile nav (its fixed panel only covers the top of the screen).
   Applied to <html> (the scroll container) rather than <body>:
   html{overflow-x:hidden} above stops <body>'s overflow from propagating
   to the viewport, so a body-only lock does nothing here. */
html.is-modal-open,
html.is-nav-open{
  overflow: hidden;
}

body{
  margin: 0;
  font-family: var(--ff-serif);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.9;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img{ max-width: 100%; display: block; }
a{ color: inherit; text-decoration: none; }
ul{ list-style: none; margin: 0; padding: 0; }
h1,h2,h3,p{ margin: 0; }

.section-inner{
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 40px;
}

.text-red{ color: var(--red); }

/* ---------- reveal-on-scroll ----------
   The hidden + animated state is scoped to <html class="js"> (set by the
   inline script in <head>). With JS disabled — or if main.js fails to
   run before it wires the reveal observer (see .reveal-ready /
   .reveal-fallback) — .reveal elements keep their natural visible state
   and the page is never blank. */
.js .reveal{
  opacity: 0;
  transform: translateY(36px);
  transition: opacity 1s var(--ease), transform 1s var(--ease);
  transition-delay: calc(var(--d, 0) * 90ms);
}
.reveal.is-visible{
  opacity: 1;
  transform: translateY(0);
}
/* Directional variants — slide in from a side instead of rising from
   below. Used for the two Company brand blocks and their team cards,
   so QuantumJump's content sweeps in from the left and SmartGrid's
   sweeps in from the right, settling at the same resting position. */
.js .reveal--left{
  transform: translateX(-64px);
}
.js .reveal--right{
  transform: translateX(64px);
}
.reveal.reveal--left.is-visible,
.reveal.reveal--right.is-visible{
  transform: translateX(0);
}
/* Failsafe: main.js didn't initialise in time — show everything. */
html.reveal-fallback .reveal{
  opacity: 1 !important;
  transform: none !important;
}

/* ---------- scroll progress ---------- */
.scroll-progress{
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 0%;
  background: linear-gradient(90deg, var(--red), var(--red-dark));
  z-index: 9999;
  transition: width .08s linear;
}

/* ---------- custom cursor ---------- */
.cursor-dot, .cursor-ring{
  position: fixed;
  top: 0; left: 0;
  pointer-events: none;
  z-index: 9998;
  will-change: transform;
}
.cursor-dot{
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--red);
  transform: translate(-50%,-50%);
}
/* The outer element only ever gets a JS-driven translate() (position,
   every frame). Hover growth lives on the inner span instead, as a
   transform: scale() transition — compositor-only, unlike animating
   width/height which forces layout on every step of the transition. */
.cursor-ring{
  width: 34px;
  height: 34px;
}
.cursor-ring__inner{
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(0,69,122,.5);
  transform: scale(1);
  transition: transform .25s var(--ease), border-color .25s var(--ease);
}
.cursor-ring.is-active .cursor-ring__inner{
  transform: scale(1.65);
  border-color: var(--red);
}
@media (hover: none), (pointer: coarse){
  .cursor-dot, .cursor-ring{ display: none; }
}

/* ==========================================================================
   HEADER
   ========================================================================== */
.site-header{
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 500;
  height: var(--header-h);
  display: flex;
  align-items: center;
  transition: transform .5s var(--ease), background-color .4s ease, box-shadow .4s ease;
}
.site-header.is-scrolled{
  /* Solid (near-opaque) instead of backdrop-filter: blur() — the frosted
     look cost a re-composite of the blurred region every scroll frame
     since the content behind a fixed header keeps changing underneath it. */
  background: rgba(251,249,245,.96);
  box-shadow: 0 1px 0 var(--line);
}
.site-header.is-hidden{
  transform: translateY(-100%);
}
.header-inner{
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.logo{
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
}
/* Company-name portion only — the site accent (red in qj-lp, blue in
   sg-lp; both read the same --red token). The group name stays neutral. */
.logo__name{
  color: var(--red);
}
/* Group name after the company name, set off by a thin vertical rule.
   Inherits the logo's current text color so it stays correct in both
   the transparent and scrolled header states. */
.logo__group{
  margin-left: 11px;
  padding-left: 12px;
  border-left: 1px solid currentColor;
  font-weight: 400;
  opacity: .6;
}
/* Two ranges where the group name wraps to a second line under the
   company name (inline divider dropped): 721–925px, where the still-
   horizontal nav crowds a one-line logo, and below 500px, where the
   logo + hamburger no longer fit on one line. */
@media (min-width: 721px) and (max-width: 925px),
       (max-width: 499.98px){
  .logo{
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    line-height: 1.3;
  }
  .logo__group{
    margin-left: 0;
    padding-left: 0;
    border-left: none;
    font-size: 12px;
  }
}
.main-nav ul{
  display: flex;
  gap: 40px;
}
.main-nav a{
  position: relative;
  font-family: var(--ff-display);
  font-size: 13px;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding-bottom: 4px;
}
.main-nav a::after{
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform .35s var(--ease);
}
.main-nav a:hover::after,
.main-nav a.is-active::after{
  transform: scaleX(1);
  transform-origin: left;
}
.main-nav a.is-active{ color: var(--red); }

.nav-toggle{
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
}
.nav-toggle span{
  width: 22px; height: 2px;
  background: var(--ink);
  transition: transform .3s var(--ease), opacity .3s;
}

/* ==========================================================================
   HERO
   ========================================================================== */
.hero{
  position: relative;
  min-height: 100vh;   /* fallback for browsers without svh */
  min-height: 100svh;  /* small viewport height — hero always fits even with mobile browser chrome shown */
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--paper);
}
/* Single-hue "light falling on a wall" wash — no second color, just a soft
   luminance gradient within the paper tone for depth without a hard split. */
.hero-light{
  position: absolute;
  inset: -10%;
  background:
    radial-gradient(60% 55% at 78% 8%, rgba(255,255,255,.9), transparent 60%),
    radial-gradient(50% 60% at 100% 100%, rgba(26,23,18,.05), transparent 65%);
  will-change: transform;
}

.hero-content{
  position: relative;
  z-index: 2;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 40px;
  padding-top: var(--header-h);
}
.hero-title{
  display: flex;
  flex-direction: column;
  margin-bottom: 40px;
}
/* Bold, high-contrast serif (a heavier Playfair Display cut) instead of
   the site's usual condensed Oswald headline — a deliberately more
   editorial, printed feel for this one wordmark. */
.hero-title__iown{
  align-self: flex-start;
  position: relative;
  display: inline-block;
  isolation: isolate;   /* contain the ghosts' multiply blend to the wordmark */
  font-family: var(--ff-script);
  font-weight: 800;
  font-style: normal;
  font-size: clamp(72px, 15vw, 176px);
  line-height: .88;
  letter-spacing: -.01em;
  color: var(--ink);
}
/* "Convergence" intro (ported from the IOWN reference): a cyan and a
   magenta ghost of the word slide in from either side, blurred, and
   focus onto the settled black wordmark. One-shot on load. */
.hero-title__iown-base{
  display: block;
  transform-origin: left center;   /* scaleX in iownFocus expands from the left edge */
  animation: iownFocus 1.5s cubic-bezier(.16,.84,.28,1) both;
}
.hero-title__iown-ghost{
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  opacity: 0;   /* animation fades it in and back out; stays hidden if it never runs */
  mix-blend-mode: multiply;
  pointer-events: none;
}
.hero-title__iown-ghost--l{
  color: #00a9ce;
  animation:
    iownGhostL 1.5s cubic-bezier(.16,.84,.28,1) both,
    iownPulseL 4s ease-in-out 1.1s 1 forwards;
}
.hero-title__iown-ghost--r{
  color: #d14fa0;
  animation:
    iownGhostR 1.5s cubic-bezier(.16,.84,.28,1) both,
    iownPulseR 4s ease-in-out 1.1s 1 forwards;
}
@keyframes iownFocus{
  0%   { opacity: 0; filter: blur(9px); transform: scaleX(1.08); }
  55%  { opacity: 1; }
  100% { opacity: 1; filter: blur(0); transform: scaleX(1); }
}
@keyframes iownGhostL{
  0%   { opacity: 0; transform: translate3d(-14%, 0, 0); filter: blur(11px); }
  30%  { opacity: .85; }
  100% { opacity: 0; transform: none; filter: blur(0); }
}
@keyframes iownGhostR{
  0%   { opacity: 0; transform: translate3d(14%, 0, 0); filter: blur(11px); }
  30%  { opacity: .85; }
  100% { opacity: 0; transform: none; filter: blur(0); }
}
/* After the intro lands, one more gentle chromatic pulse: the ghosts
   ease a little way out, then re-converge for good (plays once). */
@keyframes iownPulseL{
  0%, 75%, 100% { opacity: 0; transform: translate3d(0, 0, 0); filter: blur(0); }
  15%           { opacity: .5; filter: blur(4px); }
  30%           { opacity: .5; transform: translate3d(-3%, 0, 0); filter: blur(4px); }
}
@keyframes iownPulseR{
  0%, 75%, 100% { opacity: 0; transform: translate3d(0, 0, 0); filter: blur(0); }
  15%           { opacity: .5; filter: blur(4px); }
  30%           { opacity: .5; transform: translate3d(3%, 0, 0); filter: blur(4px); }
}
/* "+AI" staggers down and to the right of "IOWN" instead of sitting on
   the same line, giving the composition its diagonal, editorial-page
   read (matches the reference layout's "staircase"). */
.hero-title__plusai{
  display: flex;
  align-items: flex-end;
  gap: clamp(10px, 1.6vw, 20px);
  align-self: flex-end;
  margin-right: clamp(0px, 8vw, 120px);
  margin-top: clamp(-10px, -1vw, -4px);
}
.hero-title__plus{
  font-family: var(--ff-script);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(26px, 5vw, 52px);
  color: var(--ink);
  transform: translateY(-.35em);
}
.hero-title__ai{
  font-family: var(--ff-script);
  font-weight: 800;
  font-style: normal;
  font-size: clamp(72px, 15vw, 176px);
  line-height: .88;
  letter-spacing: -.01em;
  color: var(--ink);
}
.hero-caption{
  max-width: 420px;
  font-family: var(--ff-serif);
  font-size: clamp(16px, 1.8vw, 19px);
  line-height: 2;
  color: var(--ink-soft);
}
.hero-caption strong{ color: var(--red); font-weight: 700; }

.scroll-cue{
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 64px;
  font-family: var(--ff-display);
  font-size: 11px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.scroll-cue i{
  width: 1px;
  height: 34px;
  background: var(--ink-soft);
  position: relative;
  overflow: hidden;
}
.scroll-cue i::after{
  content: "";
  position: absolute;
  top: -100%; left: 0;
  width: 100%; height: 100%;
  background: var(--red);
  animation: scrollcue 1.8s ease-in-out infinite;
}
@keyframes scrollcue{
  0%{ top: -100%; }
  60%{ top: 100%; }
  100%{ top: 100%; }
}

/* ==========================================================================
   TAGS / SHARED
   ========================================================================== */
.tag{
  display: inline-block;
  font-family: var(--ff-display);
  font-size: 12px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: #fff;
  background: var(--brand-accent);
  padding: 7px 18px;
  border-radius: 999px;
  margin-bottom: 28px;
}
.tag--onred{ background: var(--ink); }

/* ==========================================================================
   ABOUT
   ========================================================================== */
.about{
  padding: 160px 0 120px;
  background: var(--paper);
}
.about-grid{
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: 60px;
  margin-bottom: 90px;
}
.about-heading{
  font-size: clamp(28px, 3.2vw, 40px);
  font-weight: 800;
  line-height: 1.5;
  text-align: center;
}
.about-heading__sub{
  font-size: 0.75em;
}
.about-body p{
  font-size: 15px;
  color: var(--ink-soft);
  margin-bottom: 18px;
}
.about-body p:last-child{ margin-bottom: 0; }

.steps{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}
.step-card{
  background: var(--cream);
  border-radius: 18px;
  padding: 40px 32px;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease), background-color .5s var(--ease);
}
.step-card:hover{
  transform: translateY(-10px);
  background: var(--paper);
  box-shadow: 0 24px 48px -20px rgba(26,23,18,.22);
}
.step-card__num{
  display: block;
  font-family: var(--ff-display);
  font-size: 40px;
  font-weight: 600;
  color: var(--red-soft);
  margin-bottom: 6px;
  transition: color .4s ease;
}
.step-card:hover .step-card__num{ color: var(--red); }
.step-card__label{
  font-family: var(--ff-display);
  font-size: 11px;
  letter-spacing: .14em;
  color: var(--ink-soft);
  margin-bottom: 18px;
}
.step-card__title{
  font-size: 24px;
  font-weight: 800;
  margin-bottom: 14px;
  transition: color .4s ease;
}
.step-card:hover .step-card__title{ color: var(--red); }
/* Stays fixed regardless of the hover color above. */
.step-card__title-static{ color: var(--ink); }
.step-card__desc{
  font-size: 14px;
  color: var(--ink-soft);
}

/* ==========================================================================
   SERVICE
   ========================================================================== */
.service{
  position: relative;
  z-index: 0;
  padding: 120px 0;
  /* Cream fallback (matches About before it) — the true cream fill is
     the .section-wipe overlay below, which sweeps in on scroll. */
  background: var(--paper);
  overflow: hidden;
}
/* Section background wipe — sweeps its color in from the left the
   moment the section scrolls into view. z-index:-1 keeps it behind
   both the section's own decorative washes and its real content. */
.section-wipe{
  position: absolute;
  inset: 0;
  z-index: -1;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .9s var(--ease);
  pointer-events: none;
}
.section-wipe.is-visible{ transform: scaleX(1); }
.section-wipe--cream{ background: var(--cream); }
.section-wipe--paper{ background: var(--paper); }
.service-light{
  position: absolute;
  inset: -10%;
  background:
    radial-gradient(55% 60% at 15% 0%, rgba(255,255,255,.7), transparent 62%),
    radial-gradient(50% 55% at 100% 100%, rgba(26,23,18,.04), transparent 60%);
  pointer-events: none;
}
.service-head{
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: end;
  gap: 60px;
  margin-bottom: 56px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 24px;
}
.service-head h2{
  font-family: var(--ff-display);
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 600;
}
.service-head p{
  font-size: 14px;
  color: var(--ink-soft);
  max-width: 480px;
}

.service-grid{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
  margin-bottom: 80px;
}
.service-card{
  background: var(--paper);
  border-radius: 18px;
  padding: 40px 20px;
  cursor: pointer;
  transition: background-color .4s ease, transform .4s var(--ease);
  position: relative;
  /* Column layout so the "MORE" affordance can be pinned to the bottom
     (margin-top: auto on it) and line up across all three cards despite
     their different copy lengths. */
  display: flex;
  flex-direction: column;
}
.service-card:hover{
  background: #fff;
  transform: translateY(-4px);
  z-index: 1;
  box-shadow: 0 20px 40px -24px rgba(26,23,18,.25);
}
.service-card:focus-visible{
  outline: 2px solid var(--red);
  outline-offset: 4px;
}
/* Same width as the icon below it, text centered within that width, so
   the number sits centered directly above the icon rather than flush
   with the card's left edge. */
.service-card__num{
  display: block;
  width: 60px;
  text-align: center;
  font-family: var(--ff-display);
  color: var(--ink);
  font-size: 40px;
  font-weight: 600;
  line-height: 1;
  margin-top: -25px;
  margin-bottom: 18px;
}
/* Round icon slot — a rough placeholder until the final custom icons
   are dropped in; swap the inline <svg> per card for the real artwork.
   Now sits beside the title instead of centered above it. */
.service-card__icon{
  flex-shrink: 0;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--cream);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--red);
  transition: background-color .4s ease, transform .4s var(--ease);
}
.service-card__icon svg{
  width: 29px;
  height: 29px;
}
.service-card:hover .service-card__icon{
  background: var(--red);
  color: #fff;
  transform: scale(1.08);
}
.service-card__top{
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 40px;
}
.service-card h3{
  font-size: 16px;
  font-weight: 800;
  line-height: 1.5;
  margin: 0;
}
.service-card__lead{
  font-size: 13px;
  font-weight: 400;
  line-height: 1.7;
  color: var(--ink);
  margin-bottom: 16px;
}
/* Font-size is tuned so a ~23-character catchphrase still fits one line
   at the narrowest 3-column card width (the 1180px breakpoint below
   matches .section-inner's own max-width, so 3-column mode always sees
   the same fixed card width). Longer catchphrases are allowed to wrap —
   balanced across two lines — rather than shrinking the font on every
   card for one outlier. */
.service-card__tagline{
  font-family: var(--ff-script);
  font-style: normal;
  font-weight: 800;
  font-size: 13px;
  text-wrap: balance;
  text-align: center;
  color: var(--red);
  line-height: 1.6;
  margin-bottom: 16px;
}
/* Purely visual now — the whole card (see .service-card[data-exec-trigger]
   above) is the actual click target that opens the shared exec-message
   modal with this card's full description. This is just the affordance
   telling the reader there's more to read. Same pill shape as the
   team-photo "View Message" badge, bottom-pinned and centred across all
   three cards; unlike that badge it stays visible (grey), darkening to
   ink on hover — and starts on ink for coarse pointers (media query at
   the bottom of the file). */
.service-card__more{
  display: inline-block;
  align-self: center;
  margin-top: auto;
  background: #b9b4ac;
  color: #fff;
  font-family: var(--ff-display);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .1em;
  white-space: nowrap;
  padding: 8px 18px;
  border-radius: 999px;
  transition: background-color .3s ease;
}
.service-card:hover .service-card__more{
  background: var(--ink);
}

.partners{
  border-radius: 18px;
  padding: 32px 0;
  background: var(--paper);
}
.partners__title{
  text-align: center;
  font-family: var(--ff-display);
  font-size: 12px;
  font-weight: 700;   /* Oswald's heaviest — 800 was silently clamped to this anyway */
  letter-spacing: .14em;
  color: var(--ink);
  margin-bottom: 22px;
}
.marquee{
  overflow: hidden;
  display: flex;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee + .marquee{ margin-top: 18px; }
.marquee__track{
  display: flex;
  flex-shrink: 0;
  gap: 64px;
  padding: 0 32px;
  animation: marquee 26s linear infinite;
}
.marquee__track span{
  font-family: var(--ff-display);
  font-size: 15px;
  letter-spacing: .08em;
  color: var(--ink-soft);
  opacity: .55;
  white-space: nowrap;
}
@keyframes marquee{
  from{ transform: translateX(0); }
  to{ transform: translateX(-100%); }
}
/* Same ticker, cloned once per company inside the Company section:
   pulled up directly under the dark stats bar (its old 100px bottom gap
   moves here, below the ticker) so the executive photos stay put. The
   section is already on paper, so drop the card fill. The list is split
   across two rows (see the two .marquee blocks in the markup); both
   scroll the same way and .marquee + .marquee sets the gap between them. */
.partners--company{
  background: none;
  margin-bottom: 100px;
}

/* ==========================================================================
   COMPANY
   ========================================================================== */
.company{
  position: relative;
  z-index: 0;
  padding: 120px 0 140px;
  /* Cream fallback (matches Service before it) — true paper fill sweeps
     in via .section-wipe on scroll. */
  background: var(--cream);
  /* First Company block is SmartGrid — brand accent = the site blue.
     The second block (.company-group--alt below) overrides this to
     QuantumJump's red. */
  --brand-accent: var(--red);
}

.company-brand{
  margin: 4px 0 22px;
}
/* Tighten the gaps between the tag / brand info / stats bar specifically
   within Company — the 28px base tag spacing is shared site-wide, so
   it's narrowed here rather than globally. */
.company .tag{
  margin-bottom: 16px;
}
.company-brand__inner{
  padding: 32px 40px 40px;
}
.company-brand__row{
  display: flex;
  align-items: center;
  gap: 24px;
}
.company-brand__logo{
  flex-shrink: 0;
  width: 72px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.company-brand__logo img{
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
/* inline-block so the rule below hugs the text's own rendered width
   and always ends exactly at the last character ("プ"), whatever the
   font size or viewport. */
.company-brand__name-jp{
  display: inline-block;
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
  padding-bottom: 8px;
  border-bottom: 3px solid var(--brand-accent);
  margin-bottom: 10px;
}
.company-brand__name-en{
  font-family: var(--ff-display);
  font-size: 15px;
  letter-spacing: .1em;
  color: var(--brand-accent);
}

/* Second (group-company) block: logo + name are grouped as one unit
   and pushed to the right, lining up under the right-aligned tag. */
.company-brand--right .company-brand__inner{
  display: flex;
  justify-content: flex-end;
}
.company-group__tag-row{
  display: flex;
  justify-content: flex-end;
}
/* Second Company block is QuantumJump — the one place on the page that
   keeps the original red accent (everything else, including the first
   Company block, is the site blue). */
.company-group--alt{
  --brand-accent: var(--qj-red);
}
.company-group{
  padding-top: 90px;
}

.stats{
  position: relative;
  background: var(--dark-bg);
  color: #fff;
  /* Small bottom gap only — the partner ticker sits right under the bar
     now, then a larger gap (.partners--company) before the team grid. */
  margin: 22px 0 40px;
  overflow: hidden;
}
.stats__bg{
  position: absolute;
  inset: -20% -10%;
  background: radial-gradient(60% 70% at 25% 15%, rgba(255,255,255,.06), transparent 60%);
}
.stats-inner{
  position: relative;
  max-width: 1180px;
  margin: 0 auto;
  padding: 64px 40px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}
.stat{
  border-left: 1px solid rgba(255,255,255,.15);
  padding-left: 24px;
}
.stat__num{
  display: inline-flex;
  align-items: flex-end;
  min-height: 88px;
  font-family: var(--ff-display);
  font-size: clamp(38px, 4.5vw, 56px);
  font-weight: 600;
  color: var(--brand-accent);
}
.stat__num::after{
  content: attr(data-suffix);
  font-size: .5em;
  margin-left: 4px;
  /* 年 / 名 / 万 — regular weight (the digits stay at 600), same muted
     colour as the label below. */
  font-weight: 400;
  color: rgba(255,255,255,.6);
}
.stat__label{
  margin-top: 10px;
  font-size: 11px;
  letter-spacing: .06em;
  color: rgba(255,255,255,.6);
  line-height: 1.7;
}
/* Small extra detail line under the years-of-history label (founding
   date) — same color as .stat__label, just below it. */
.stat__meta{
  margin-top: 6px;
  font-size: 11px;
  color: rgba(255,255,255,.6);
}
/* White, to stand out from the muted grey of the label text around it. */
.stat__meta-date{ color: #fff; }
/* Corporate Advisor stat — a short list of firm names standing in for
   the usual big count-up number. Deliberately not styled like .stat__num
   (no count-up here, per the brief). min-height + flex-end bottom-aligns
   the list (and, below, the number in the other stats) so every
   .stat__label lands at the same height regardless of which kind of
   value sits above it. */
.stat__list{
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 88px;
}
.stat__list p{
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: #fff;
}

.team{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 34px;
  max-width: 828px;
  margin: 0 auto;
}
.team-card__photo{
  aspect-ratio: 3/4;
  border-radius: 12px;
  background: linear-gradient(150deg, var(--cream-2), var(--cream));
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin-bottom: 18px;
  position: relative;
  /* Natural cast shadow, offset to the bottom-right — plain black/neutral
     for every card regardless of which company group it's in. */
  box-shadow: 12px 18px 32px -14px rgba(0,0,0,.3);
}
/* Fallback initial, visible only while the photo below hasn't loaded. */
.team-card__initial{
  font-family: var(--ff-display);
  font-size: 64px;
  font-weight: 600;
  color: rgba(26,23,18,.18);
}
/* Fixed aspect-ratio box + cover crops any source photo — different
   original sizes all end up framed identically. */
.team-card__photo-img{
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center top;
  transition: transform .6s var(--ease);
}
.team-card__photo:hover .team-card__photo-img{
  transform: scale(1.08);
}
.team-card__name{
  font-size: 15px;
  font-weight: 700;
  color: var(--brand-accent);
  margin-bottom: 4px;
}
.team-card__role{
  font-size: 12px;
  color: var(--ink-soft);
}

/* Photos wired to the executive-message modal get a pointer affordance and
   a small badge that fades in on hover/focus so the interaction is discoverable. */
.team-card__photo--message{
  cursor: pointer;
}
.team-card__message-badge{
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translate(-50%, 8px);
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(20,18,16,.72);
  backdrop-filter: blur(4px);
  color: #fff;
  font-family: var(--ff-display);
  font-size: 11px;
  letter-spacing: .1em;
  white-space: nowrap;
  opacity: 0;
  transition: opacity .35s var(--ease), transform .35s var(--ease);
  pointer-events: none;
}
.team-card__photo--message:hover .team-card__message-badge,
.team-card__photo--message:focus-visible .team-card__message-badge{
  opacity: 1;
  transform: translate(-50%, 0);
}
.team-card__photo--message:focus-visible{
  outline: 2px solid var(--red);
  outline-offset: 3px;
}
/* QuantumJump's Company column keeps its red accent — match the focus
   ring to it too. */
.company-group--alt .team-card__photo--message:focus-visible{
  outline-color: var(--qj-red);
}

/* ==========================================================================
   EXECUTIVE MESSAGE MODAL
   ========================================================================== */
.exec-modal{
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  /* visibility (delayed to after the fade) takes the closed modal — and
     its close button — out of the tab order and the a11y tree. */
  visibility: hidden;
  pointer-events: none;
  transition: opacity .35s var(--ease), visibility 0s linear .35s;
}
.exec-modal.is-open{
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .35s var(--ease);
}
.exec-modal__backdrop{
  position: absolute;
  inset: 0;
  background: rgba(20,18,16,.6);
  backdrop-filter: blur(6px);
}
.exec-modal__panel{
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 720px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  /* The panel itself no longer scrolls — only .exec-modal__scroll does —
     so the close button (absolute, below) stays pinned top-right however
     far the content is scrolled. overflow:hidden clips the scroll area
     to the rounded corners. */
  overflow: hidden;
  background: var(--paper);
  border-radius: 20px;
  box-shadow: 0 40px 80px -20px rgba(0,0,0,.4);
  transform: translateY(24px) scale(.97);
  opacity: 0;
  transition: transform .45s var(--ease), opacity .4s var(--ease);
}
.exec-modal.is-open .exec-modal__panel{
  transform: translateY(0) scale(1);
  opacity: 1;
}
.exec-modal__scroll{
  min-height: 0;
  overflow-y: auto;
  /* Keep the panel's scroll from chaining out to the page. */
  overscroll-behavior: contain;
  padding: 48px;
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 36px;
}
/* JS makes this focusable (tabindex 0) only when the content overflows,
   so keyboard users can scroll a long message with the arrow keys. */
.exec-modal__scroll:focus-visible{
  outline: 2px solid var(--red);
  outline-offset: -3px;
}
/* No photo to show (e.g. a Service card's full description rather than
   a person) — collapse to a single, text-only column. */
.exec-modal__panel--no-photo{
  max-width: 560px;
}
.exec-modal__panel--no-photo .exec-modal__scroll{
  grid-template-columns: 1fr;
}
.exec-modal__panel--no-photo .exec-modal__photo{ display: none; }
.exec-modal__close{
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 1;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  /* 50% translucent so text scrolling behind stays visible through it.
     The base is darker than --cream by exactly the amount that makes it
     composite back to --cream over the --paper panel (C = 2*cream - paper). */
  background: rgba(237, 229, 215, .5);
  color: var(--ink);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .3s ease, transform .3s var(--ease);
}
.exec-modal__close:hover{
  background: var(--red);
  color: #fff;
  transform: rotate(90deg);
}
.exec-modal__photo{
  width: 100%;
  aspect-ratio: 3/4;
  border-radius: 14px;
  background-size: cover;
  background-position: center top;
  align-self: start;
}
.exec-modal__body{
  display: flex;
  flex-direction: column;
}
/* Service popups only — icon + business-unit name at the top, in place
   of the photo + trailing signature used for people. */
.exec-modal__header{
  display: none;
  align-items: center;
  gap: 16px;
  margin-bottom: 26px;
}
.exec-modal__icon{
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--red);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.exec-modal__icon svg{
  width: 24px;
  height: 24px;
}
.exec-modal__heading{
  font-size: 17px;
  font-weight: 700;
  line-height: 1.5;
}
.exec-modal__messages p{
  font-size: 14.5px;
  line-height: 2.1;
  color: var(--ink-soft);
  margin: 0 0 20px;
}
.exec-modal__messages p:last-child{ margin-bottom: 28px; }
.exec-modal__signature{
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: .04em;
}

@media (max-width: 640px){
  .exec-modal__panel{
    max-height: 90vh;
  }
  .exec-modal__scroll{
    grid-template-columns: 1fr;
    padding: 32px 24px;
  }
  .exec-modal__photo{ max-width: 180px; margin: 0 auto; }
  /* The circular close button sits top-right of the panel — give
     text-only popups (Service card descriptions) extra headroom so
     the heading doesn't run underneath it. */
  .exec-modal__panel--no-photo .exec-modal__scroll{
    padding-top: 64px;
  }
}

/* ==========================================================================
   ACCESS
   ========================================================================== */
.access{
  position: relative;
  z-index: 0;
  /* Paper fallback (matches Company before it) — true cream fill sweeps
     in via .section-wipe on scroll. Three dark blocks back to back
     (Company's stats bar, Access itself before, Footer) felt heavy, so
     cream keeps the page's light/dark rhythm alternating into the red
     Recruit section that follows. */
  background: var(--paper);
  color: var(--ink);
  padding: 120px 0;
}
.access .tag{ margin-bottom: 44px; }
.access .section-inner{ max-width: 980px; }
.access-grid{
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 56px;
  align-items: start;
}
.access__eyebrow{
  font-family: var(--ff-serif);
  font-size: 13px;
  letter-spacing: .12em;
  color: var(--ink-soft);
  margin-bottom: 32px;
}
.access__entry{ margin-bottom: 26px; }
.access__entry-name{
  font-size: 17px;
  font-weight: 700;
  margin-bottom: 6px;
}
.access__entry-phone{
  font-size: 14px;
  color: var(--ink-soft);
}
/* Privacy mark badge + policy link — small and quiet, sitting right
   under the phone number like a standard footer-style credential
   rather than competing with the company name for attention. */
.access__pmark{
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}
.access__pmark img{
  flex-shrink: 0;
  width: 60px;
  height: auto;
}
.access__pmark a{
  font-size: 12px;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color .3s ease;
}
.access__pmark a:hover{ color: var(--ink); }
.access__hq{ margin-top: 40px; }
/* Matches the footer's "本社" label treatment exactly (same word, same
   role — a category label sitting right above an address). */
.access__hq-label{
  font-family: var(--ff-display);
  font-size: 13px;
  letter-spacing: .1em;
  color: var(--ink);
  margin-bottom: 8px;
}
.access__hq-address{
  font-size: 15px;
  line-height: 1.8;
}

.access-map{
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  aspect-ratio: 16/12;
  max-width: 420px;
  background: var(--paper);
  box-shadow: 0 20px 50px -20px rgba(26,23,18,.25);
}
.access-map iframe{
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.access-map__link{
  position: absolute;
  z-index: 1;
  top: 16px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: #fff;
  color: var(--ink);
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 8px 20px rgba(0,0,0,.3);
  transition: transform .3s var(--ease);
}
.access-map__link:hover{ transform: translateY(-2px); }

@media (max-width: 900px){
  .access-grid{ grid-template-columns: 1fr; }
  .access-map{ aspect-ratio: 16/11; max-width: none; }
}

/* ==========================================================================
   RECRUIT
   ========================================================================== */
.recruit{
  position: relative;
  background: var(--red);
  color: #fff;
  padding: 140px 0 120px;
  overflow: hidden;
  text-align: center;
}
.recruit-light{
  position: absolute;
  inset: -15%;
  background: radial-gradient(65% 60% at 20% 0%, rgba(255,255,255,.14), transparent 60%);
}
.recruit-inner{
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.tag--onred{ background: rgba(255,255,255,.15); }
.recruit-copy{
  max-width: 640px;
  font-size: 14px;
  line-height: 2;
  color: rgba(255,255,255,.85);
  margin-bottom: 32px;
}
/* Mirrors the Hero's "IOWN＋AI" three-line wordmark (same recurring
   phrase, same stacked layout) — solid white here instead of Hero's
   watercolor-gradient treatment, since that's a one-off Hero moment
   and this sits on the solid red Recruit background. */
.recruit-title{
  display: flex;
  align-items: baseline;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(8px, 1.2vw, 16px);
  margin-bottom: 14px;
}
/* Same heavy Playfair Display as the Hero's "IOWN＋AI" (800/normal for
   IOWN and AI, 400/normal for the "+") — kept on one centered line
   rather than Hero's staggered 3-line layout, since Recruit's whole
   block (tag, copy, title, sub, button) is already a symmetric,
   centered composition; breaking just this one line into a 3-line
   stack would read as off-balance against everything around it. */
.recruit-title__iown{
  font-family: var(--ff-script);
  font-weight: 800;
  font-style: normal;
  font-size: clamp(48px, 9vw, 120px);
  line-height: .9;
  letter-spacing: -.01em;
  color: #fff;
}
.recruit-title__plusai{
  display: flex;
  align-items: baseline;
  gap: clamp(8px, 1.2vw, 16px);
}
.recruit-title__plus{
  font-family: var(--ff-script);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(26px, 4.4vw, 56px);
  color: #fff;
}
.recruit-title__ai{
  font-family: var(--ff-script);
  font-weight: 800;
  font-style: normal;
  font-size: clamp(48px, 9vw, 120px);
  line-height: .9;
  letter-spacing: -.01em;
  color: #fff;
}
.recruit-sub{
  font-size: 17px;
  color: rgba(255,255,255,.85);
  margin-bottom: 48px;
}
.recruit-sub strong{ color: #fff; font-weight: 700; }

.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 160px;
  padding: 18px 40px;
  border-radius: 999px;
  font-family: var(--ff-display);
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
/* Slow ambient "breathing" — the fill's own alpha eases down and back
   (not opacity, which would fade the white label too) so the red
   Recruit background shows faintly through at the dim point while
   "View" stays fully legible white throughout. Independent of the
   magnetic hover-follow (data-magnetic in main.js, which only ever
   touches transform) so the two don't fight. */
.btn--dark{
  background: rgba(26,23,18,1);
  color: #fff;
  animation: btnBreathe 2s ease-in-out infinite;
}
@keyframes btnBreathe{
  0%, 100%{ background-color: rgba(26,23,18,1); }
  50%{ background-color: rgba(26,23,18,.5); }
}
.btn--dark:hover{
  box-shadow: 0 14px 30px -10px rgba(0,0,0,.5);
}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.site-footer{
  background: var(--dark-bg);
  color: rgba(255,255,255,.6);
  padding: 32px 0;
  text-align: center;
}
.site-footer__copy{
  font-size: 11px;
  letter-spacing: .04em;
}

/* ==========================================================================
   TO TOP
   ========================================================================== */
.to-top{
  position: fixed;
  right: 28px;
  bottom: 28px;
  width: 48px; height: 48px;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
  transition: opacity .4s var(--ease), transform .4s var(--ease), background-color .3s;
  z-index: 400;
}
.to-top.is-visible{
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.to-top:hover{ background: var(--red); }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
/* Service cards: 3 columns above 1180px (unchanged — that's exactly
   .section-inner's own max-width, so 3-column mode always sees the same
   fixed column width, which is what lets the tagline use one flat
   font-size instead of a viewport clamp). Below that, 2 columns with
   card 03 dropping to its own centered row — and below ~820px, 2
   columns no longer leaves enough width per card for the one-line
   tagline, so it drops further to a single column. */
@media (max-width: 1180px){
  .service-grid{ grid-template-columns: repeat(2, 1fr); }
  .service-card:nth-child(3){
    grid-column: 1 / -1;
    justify-self: center;
    width: 100%;
    max-width: calc(50% - 14px);
  }
}

@media (max-width: 820px){
  .service-grid{ grid-template-columns: 1fr; }
  .service-card:nth-child(3){
    grid-column: auto;
    justify-self: stretch;
    max-width: none;
  }
}

/* Between 534px and 820px, stretching the single column out to the
   (increasingly wide) full container looked bloated well before the
   viewport was actually narrow. Pin it to the width it would be at
   533px (485px, once .section-inner's padding drops to 24px at
   ≤720px: 533 - 48) and center it, background showing on either side.
   Below 533px this stops applying and the grid goes back to filling
   the full width, shrinking with the viewport as usual. */
@media (max-width: 820px) and (min-width: 534px){
  /* margin-left/right only — a shorthand "margin: 0 auto" here would
     also zero out the base rule's margin-bottom, which is exactly what
     was pinning card 03 to the Partners panel below it with no gap. */
  .service-grid{ max-width: 485px; margin-left: auto; margin-right: auto; }
}

/* About US's 3 step cards get the exact same 3-tier treatment as the
   Service cards above, for consistent behavior between the site's two
   3-card grids: 3 columns above 1180px, 2 columns (card 03 centered on
   its own row) down to 820px, then 1 column — pinned to its 533px width
   between 534–820px so it doesn't stretch bloated, fully fluid again
   at ≤533px. */
@media (max-width: 1180px){
  .steps{ grid-template-columns: repeat(2, 1fr); }
  .step-card:nth-child(3){
    grid-column: 1 / -1;
    justify-self: center;
    width: 100%;
    max-width: calc(50% - 14px);
  }
}

@media (max-width: 820px){
  .steps{ grid-template-columns: 1fr; }
  .step-card:nth-child(3){
    grid-column: auto;
    justify-self: stretch;
    max-width: none;
  }
}

@media (max-width: 820px) and (min-width: 534px){
  .steps{ max-width: 485px; margin-left: auto; margin-right: auto; }
}

@media (max-width: 980px){
  .about-grid{ grid-template-columns: 1fr; }
  .service-head{ grid-template-columns: 1fr; }
  .stats-inner{ grid-template-columns: repeat(2, 1fr); row-gap: 40px; }
  /* 1-column layout kicks in here — 243px (75% of the previous 324px)
     is a good size at ~768px, but a fixed px cap doesn't keep shrinking
     on narrower phones, so it ends up taking a much bigger *share* of
     the screen at 375–425px even though the pixel size is unchanged.
     min() with a vw term lets it keep scaling down below ~517px
     viewport width while staying at the fixed 243px above that. */
  .team{ grid-template-columns: 1fr; max-width: min(243px, 47vw); }
  /* Single-column layout below this breakpoint — the left/right
     slide-in reads as a misplaced photo rather than an entrance
     effect here, so skip the directional motion for team cards. */
  .team-card.reveal,
  .team-card.reveal--left,
  .team-card.reveal--right{
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@media (max-width: 720px){
  .section-inner{ padding: 0 24px; }
  .header-inner{ padding: 0 24px; }
  .main-nav{
    position: fixed;
    top: var(--header-h); left: 0; right: 0;
    background: var(--paper);
    border-top: 1px solid var(--line);
    transform: translateY(-140%);
    transition: transform .4s var(--ease);
  }
  .main-nav.is-open{ transform: translateY(0); }
  .main-nav ul{ flex-direction: column; padding: 24px; gap: 20px; }
  .nav-toggle{ display: flex; }
  /* Open menu → the three bars morph into an ✕. Bars are 2px tall and
     5px apart, so the outer two travel 7px to meet in the middle. */
  .main-nav.is-open ~ .nav-toggle span:nth-child(1){
    transform: translateY(7px) rotate(45deg);
  }
  .main-nav.is-open ~ .nav-toggle span:nth-child(2){ opacity: 0; }
  .main-nav.is-open ~ .nav-toggle span:nth-child(3){
    transform: translateY(-7px) rotate(-45deg);
  }
  .company-brand__inner{ padding: 24px; }
  .company-brand__row{ gap: 16px; }
  .company-brand__logo{ width: 52px; height: 52px; }
  .company-brand__name-jp{ font-size: 17px; }
}

/* Touch/coarse-pointer devices can't hover, so hints that only appear on
   hover (the team-photo message badge, the Service card MORE button)
   would otherwise be easy to miss as clickable. Show them in their
   "revealed" state from the start instead. */
@media (hover: none), (pointer: coarse){
  .team-card__message-badge{
    opacity: 1;
    transform: translate(-50%, 0);
  }
  .service-card__more{
    background: var(--ink);
  }
}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal{ opacity: 1; transform: none; }
  .section-wipe{ transform: scaleX(1); }
  /* IOWN wordmark: skip the convergence, just show the settled word. */
  .hero-title__iown-base{ animation: none; opacity: 1; filter: none; transform: none; }
  .hero-title__iown-ghost{ display: none; }

  /* The infinite marquee is the only way to see every partner name,
     so keep it scrolling even under reduced motion instead of
     freezing it mid-list. */
  .marquee__track{
    animation-duration: 26s !important;
    animation-iteration-count: infinite !important;
  }
}
