/* =========================================================================
 * Piece it! — design system
 *
 * 藍染の一反の布を、サイト全体に見立てている。ページの地は生成りからはじまり、
 * 読み進むほど藍が深まり、末尾で留紺・藍墨に至る。ここにあるのは、その布と
 * どのページでも共通の組版・余白・動き。ページ固有の意匠は各 HTML 側に置く。
 * ========================================================================= */

/* ============================================================== tokens == */
:root{
  /* 藍 — 甕をくぐるごとに深くなる伝統色 */
  --kinari:      #F3F1EA;   /* 生成り */
  --shironeri:   #E9E7DD;   /* 白練 */
  --kamenozoki:  #CBD9DD;   /* 甕覗 */
  --mizuasagi:   #9FBECA;   /* 水浅葱 */
  --asagi:       #5B8CA6;   /* 浅葱 */
  --hanada:      #2F6089;   /* 縹 */
  --kon:         #1E3E68;   /* 紺 */
  --tomekon:     #122442;   /* 留紺 */
  --aisumi:      #070E1B;   /* 藍墨 */

  --ink:         #232934;
  --ink-strong:  #12161F;
  --ink-mute:    #5D6675;
  --line:        rgba(18,36,66,.16);
  --line-soft:   rgba(18,36,66,.09);

  --on-dark:         #EDEBE3;
  --on-dark-mute:    rgba(237,235,227,.60);
  --on-dark-line:    rgba(237,235,227,.20);

  --rail-w: 88px;
  --gut: clamp(1.4rem, 4.6vw, 5rem);
  --measure: 34em;

  --ease:  cubic-bezier(.16,1,.3,1);
  --ease-s: cubic-bezier(.4,.14,.2,1);

  --mincho: "Zen Old Mincho", "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", "MS PMincho", serif;
  --gothic: "Zen Kaku Gothic New", "Hiragino Sans", "Yu Gothic", "Noto Sans JP", system-ui, sans-serif;
  --heading: "Hina Mincho", "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", "MS PMincho", serif;

  /* 布の地。ページごとに #cloth を上書きして染めの深さを変える */
  --cloth: linear-gradient(180deg, #F3F1EA 0%, #F3F1EA 100%);
}

/* ================================================================ base == */
*,*::before,*::after{ box-sizing:border-box }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth }
body{
  margin:0;
  position:relative;   /* containing block for #cloth, which spans the document */
  padding-left:var(--rail-w);
  background:var(--kinari);
  color:var(--ink);
  font-family:var(--gothic);
  font-weight:400;
  font-size:clamp(14.5px,.95rem,16px);
  line-height:2.15;
  letter-spacing:.055em;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
img{ max-width:100%; display:block }
a{ color:inherit; text-decoration:none }
h1,h2,h3,h4,p,figure,ul,ol,dl,dd,table{ margin:0 }
ul,ol{ padding:0; list-style:none }
h1,h2,h3,h4{ font-weight:inherit; font-size:inherit }
::selection{ background:var(--kamenozoki); color:var(--ink-strong) }
:focus-visible{ outline:2px solid var(--hanada); outline-offset:4px; border-radius:1px }

.wrap{ width:100%; max-width:1240px; margin-inline:auto; padding-inline:var(--gut) }
.section{ position:relative; padding-block:clamp(6.5rem,13vw,13.5rem); scroll-margin-top:5rem }
.section--tight{ padding-block:clamp(4.5rem,9vw,9rem) }
/* sections that carry their own ground run edge to edge, under the rail */
.bleed{ margin-left:calc(var(--rail-w) * -1); padding-left:var(--rail-w) }
/* one continuous dye ground across several sections: the clip belongs to the
   span, not to each section, so a bloom drifting past its own section's edge
   bleeds straight into the next one instead of being cut off at the seam. */
.dye-span{ position:relative; overflow:hidden }

.skip{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--kon); color:var(--kinari); padding:.9em 1.4em; font-size:.8rem;
}
.skip:focus{ left:var(--gut); top:1rem }

/* the cloth: one continuous dye running down the light half of the page */
#cloth{
  position:absolute; inset:0; z-index:-2; pointer-events:none;
  background:var(--cloth);
}
/* paper */
#grain{
  position:fixed; inset:0; z-index:120; pointer-events:none;
  background-image:url("paper-grain.png");
  background-size:300px 300px;
  mix-blend-mode:multiply; opacity:.9;
}

/* ================================================================ type == */
.eyebrow{
  font-family:var(--gothic); font-weight:500;
  font-size:.6875rem; line-height:1; letter-spacing:.42em;
  text-transform:uppercase; color:var(--ink-mute); white-space:nowrap;
  display:flex; align-items:center; gap:.9em;
  transition:letter-spacing 1.5s var(--ease), opacity 1.3s var(--ease);
}
.eyebrow::before{
  content:""; width:26px; height:1px; background:currentColor; opacity:.5; flex:none;
}
.eyebrow i{ font-style:normal; letter-spacing:.24em; opacity:.72; font-size:.72rem }
.js [data-reveal] .eyebrow{ letter-spacing:.62em }
.js [data-reveal].is-in .eyebrow{ letter-spacing:.42em }

.h2{
  font-family:var(--heading); font-weight:400;
  font-size:clamp(1.5rem,2.85vw,2.6rem);
  line-height:1.78; letter-spacing:.045em; color:var(--ink-strong);
  font-feature-settings:"palt" 1;
}
.h3{
  font-family:var(--heading); font-weight:400;
  font-size:clamp(1.15rem,1.9vw,1.55rem);
  line-height:1.75; letter-spacing:.05em; color:var(--ink-strong);
  font-feature-settings:"palt" 1;
}
.lead{ max-width:var(--measure); color:var(--ink); text-wrap:pretty }
.lead + .lead{ margin-top:1.6em }
.mute{ color:var(--ink-mute) }
.small{ font-size:.8125rem; line-height:2 }
/* 文節で折り返す — keeps Japanese phrases from splitting mid-word */
.n{ display:inline-block }

.rule{
  height:1px; background:var(--line); transform-origin:left center;
  transition:transform 1.8s var(--ease) .15s;
}
.js [data-reveal] .rule{ transform:scaleX(0) }
.js [data-reveal].is-in .rule{ transform:scaleX(1) }

/* dark grounds */
.on-ink{ color:var(--on-dark) }
.on-ink .h2,.on-ink .h3{ color:var(--on-dark) }
.on-ink .eyebrow{ color:var(--on-dark-mute) }
.on-ink .lead{ color:var(--on-dark) }
.on-ink .mute{ color:var(--on-dark-mute) }
.on-ink .rule{ background:var(--on-dark-line) }

/* ========================================================== components == */
/* ボタン。`.more` の「線が伸びる」しぐさを枠の中に入れたもの ──
   触れるものだと一目で分かる箱を持ちながら、あの動きは残している。 */
.btn{
  display:inline-flex; align-items:center; justify-content:space-between; gap:1.4em;
  padding:1.25em 1.9em;
  border:1px solid var(--line); background:rgba(255,255,255,.34);
  font-size:.6875rem; letter-spacing:.24em; line-height:1.2; text-transform:uppercase;
  color:var(--ink-strong);
  transition:background .5s var(--ease), color .5s var(--ease),
             border-color .5s var(--ease), transform .5s var(--ease);
}
.btn__arrow{ display:inline-flex; align-items:center; gap:.4em; flex:none }
.btn__arrow i{
  display:block; width:14px; height:1px; background:currentColor; opacity:.55;
  transition:width .5s var(--ease), opacity .5s var(--ease);
}
.btn__arrow svg{ display:block; flex:none; opacity:.75; transition:opacity .5s var(--ease) }
.btn:hover,.btn:focus-visible{ background:var(--kon); color:var(--kinari); border-color:var(--kon) }
.btn:hover .btn__arrow i,.btn:focus-visible .btn__arrow i{ width:26px; opacity:1 }
.btn:hover .btn__arrow svg,.btn:focus-visible .btn__arrow svg{ opacity:1 }
.btn:active{ transform:translateY(1px) }

.btn--solid{ background:var(--kon); color:var(--kinari); border-color:var(--kon) }
.btn--solid:hover,.btn--solid:focus-visible{ background:var(--tomekon); border-color:var(--tomekon) }
.btn--sm{ padding:1.2em 1.3em; letter-spacing:.16em; gap:1em }
.btn--sm .btn__arrow i{ width:11px }
.btn--sm:hover .btn__arrow i,.btn--sm:focus-visible .btn__arrow i{ width:20px }
.btn--full{ width:100% }

/* 暗い地の上のボタン。.coda はいつでも藍墨なので、いちいち .on-ink を
   付けなくても済むようにここで一緒に見ておく。 */
.on-ink .btn,.coda .btn{ color:var(--on-dark); border-color:var(--on-dark-line); background:rgba(237,235,227,.06) }
.on-ink .btn:hover,.on-ink .btn:focus-visible,
.coda .btn:hover,.coda .btn:focus-visible{ background:var(--kinari); color:var(--tomekon); border-color:var(--kinari) }

.btnrow{ display:flex; flex-wrap:wrap; gap:1rem 1.4rem; align-items:center }

/* 小さな一片 — a label chip */
.chip{
  display:inline-flex; align-items:center;
  font-size:.6875rem; letter-spacing:.16em; line-height:1;
  padding:.72em 1.05em; border:1px solid var(--line); color:var(--ink-mute);
}
.chips{ display:flex; flex-wrap:wrap; gap:.55rem }
.on-ink .chip{ border-color:var(--on-dark-line); color:var(--on-dark-mute) }

/* ============================================================= reveals == */
[data-reveal]{
  transition:opacity 1.5s var(--ease), transform 1.5s var(--ease), filter 1.5s var(--ease);
  transition-delay:var(--d,0s);
}
/* .plate is exempt: it only needs the observer hook. Giving it opacity /
   filter would make it a stacking context and kill the img's blend mode. */
.js [data-reveal]:not(.plate){ opacity:0; transform:translateY(16px); filter:blur(6px) }
.js [data-reveal]:not(.plate).is-in{ opacity:1; transform:none; filter:blur(0) }

.lines{ display:block }
.lines > span{ display:block; overflow:hidden; padding-block:.06em; margin-block:-.06em }
.lines > span > span{
  display:block; transform:translateY(110%);
  transition:transform 1.5s var(--ease); transition-delay:var(--d,0s);
}
.js [data-reveal].is-in .lines > span > span,
html:not(.js) .lines > span > span{ transform:none }

/* “ちょうどいい一片” — pieces fly in from scattered directions and settle
   into place, echoing the hero canvas's own drifting-pieces motif rather
   than sliding up like a plain line */
.lines > span.lines__row--piece{ overflow:visible }
.lines > span.lines__row--piece > .piece-line{ transform:none; transition:none }
.js .piece-quote{
  display:inline-block; opacity:0; transform:translateY(14px); filter:blur(3px);
  transition:opacity 1.1s var(--ease), transform 1.1s var(--ease), filter 1.1s var(--ease);
  transition-delay:var(--d,0s);
}
.js [data-reveal].is-in .piece-quote{ opacity:1; transform:none; filter:blur(0) }
.piece-assemble{ display:inline-block }
.js .piece-assemble .pc{
  display:inline-block; opacity:0;
  transform:translate(var(--px,0),var(--py,0)) rotate(var(--pr,0deg)) scale(.68);
  filter:blur(5px);
  transition:transform 1.5s var(--ease), opacity 1.1s var(--ease), filter 1.2s var(--ease);
  transition-delay:calc(var(--d,0s) + var(--pd,0s));
}
.js [data-reveal].is-in .piece-assemble .pc{
  opacity:1; transform:translate(0,0) rotate(0deg) scale(1); filter:blur(0);
}

/* dye-descending image reveal.
   NB: the clip lives on the img, never on the observed element — a clipped
   element reports an intersectionRatio of 0 and would never reveal itself.
   `darken` drops the cloth's own ground out of the frame, so only the dye
   is left — the stain sits directly on the page rather than in a box. */
.plate{ position:relative; overflow:hidden }
.plate img{ width:100%; height:100%; object-fit:cover; mix-blend-mode:darken }
.js .plate img{
  clip-path:inset(0 0 100% 0); transform:scale(1.09);
  transition:clip-path 1.8s var(--ease) var(--d,0s), transform 2.8s var(--ease) var(--d,0s);
}
.js .plate.is-in img,
.js [data-reveal].is-in .plate img{ clip-path:inset(0 0 0 0); transform:scale(1) }

/* ================================================================ rail == */
.rail{
  position:fixed; top:0; left:0; z-index:90;
  width:var(--rail-w); height:100%;
  display:flex; flex-direction:column; align-items:center;
  padding-block:clamp(1.6rem,4vh,2.6rem);
  pointer-events:none;
}
.rail__mark{ flex:none; color:var(--ink-strong); opacity:.85; transition:color .8s var(--ease) }
/* mid-tone so the rail stays legible over both 生成り and 留紺 */
.rail__track{
  position:relative; flex:1 1 auto; width:1px; margin-block:1.5rem 0;
  background:rgba(116,140,168,.42);
}
/* a plain progress fill — the scroll position speaks for itself,
   it doesn't need to walk through the whole dye scale to do it */
.rail__dye{
  position:absolute; inset:0; width:1px;
  background:var(--kon);
  clip-path:inset(0 0 100% 0);
  transition:background .8s var(--ease);
}
.rail__dye::after{
  content:""; position:absolute; left:50%; width:5px; height:5px;
  transform:translate(-50%,-50%) rotate(45deg);
  top:var(--p,0%); background:var(--kon);
  transition:background .8s var(--ease);
}
body.on-dark .rail__mark{ color:var(--on-dark) }
body.on-dark .rail__dye,
body.on-dark .rail__dye::after{ background:var(--kamenozoki) }

.topbar{ display:none }

/* ============================================================ masthead == */
.masthead{
  position:fixed; top:0; left:var(--rail-w); right:0; z-index:100;
  padding-block:1.55rem;
  transition:padding .6s var(--ease), background .7s var(--ease), backdrop-filter .7s var(--ease);
}
/* header sits on the same 1240 grid as every section, not the viewport edge */
.masthead__inner{
  width:100%; max-width:1240px; margin-inline:auto; padding-inline:var(--gut);
  display:flex; align-items:center; justify-content:space-between; gap:2rem;
}
.masthead::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background:var(--line-soft); opacity:0; transition:opacity .7s var(--ease);
}
/* blur only, no tint — the page ground shifts from 生成り to 留紺 as you read,
   and any fixed colour would show up as a band across it */
.masthead.is-stuck{
  padding-block:1rem;
  backdrop-filter:blur(20px);
  background:linear-gradient(180deg, rgba(255,255,255,.58), rgba(255,255,255,0));
}
.masthead.is-stuck::after{ opacity:1 }
body.on-dark .masthead.is-stuck{
  background:linear-gradient(180deg, rgba(7,14,27,.66), rgba(7,14,27,0));
}
body.on-dark .masthead::after{ background:var(--on-dark-line) }

.brand{ display:inline-flex; align-items:center; gap:.7em; color:var(--ink-strong); transition:color .8s var(--ease) }
.brand svg{ flex:none; overflow:visible }
.brand__name{ font-family:var(--mincho); font-weight:500; font-size:1.06rem; letter-spacing:.015em; line-height:1 }
.brand__sub{
  font-family:var(--gothic); font-size:.625rem; letter-spacing:.28em; text-transform:uppercase;
  color:var(--ink-mute); padding-left:.85em; margin-left:.2em; border-left:1px solid var(--line);
  line-height:1; transition:color .8s var(--ease), border-color .8s var(--ease);
}
body.on-dark .brand{ color:var(--on-dark) }
body.on-dark .brand__sub{ color:var(--on-dark-mute); border-color:var(--on-dark-line) }

.nav{ display:flex; align-items:center; gap:clamp(1.1rem,2.4vw,2.4rem) }
.nav a{
  position:relative; font-size:.6875rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--ink-mute); padding-block:.4em; transition:color .5s var(--ease);
}
.nav a::after{
  content:""; position:absolute; left:0; bottom:0; width:100%; height:1px;
  background:currentColor; transform:scaleX(0); transform-origin:right center;
  transition:transform .6s var(--ease);
}
.nav a:hover,.nav a:focus-visible,.nav a.is-current{ color:var(--ink-strong) }
.nav a:hover::after,.nav a:focus-visible::after{ transform:scaleX(1); transform-origin:left center }
.nav a.is-current::after{ transform:scaleX(1); transform-origin:left center; opacity:.4 }
body.on-dark .nav a{ color:var(--on-dark-mute) }
body.on-dark .nav a:hover,
body.on-dark .nav a:focus-visible,
body.on-dark .nav a.is-current{ color:var(--on-dark) }

/* ================================================================ hero == */
.hero{
  position:relative; min-height:100svh;
  display:flex; align-items:center;
  padding-block:clamp(8rem,18vh,12rem) clamp(6rem,12vh,9rem);
  overflow:hidden;
}
.hero--short{ min-height:auto; padding-block:clamp(9rem,20vh,14rem) clamp(5rem,10vh,8rem) }
.hero__canvas{ position:absolute; inset:0; width:100%; height:100%; z-index:-1 }
.hero__scrim{
  position:absolute; inset:0; z-index:-1; pointer-events:none;
  background:
    radial-gradient(58% 46% at 26% 48%,
      rgba(243,241,234,.72) 0%, rgba(243,241,234,.30) 55%, rgba(243,241,234,0) 100%),
    linear-gradient(180deg,
      rgba(243,241,234,.55) 0%, rgba(243,241,234,.16) 22%,
      rgba(243,241,234,.16) 78%, rgba(243,241,234,.60) 100%);
}
.hero__inner{ position:relative }
.hero__title{
  margin-top:clamp(1.8rem,4vh,3rem);
  font-family:var(--heading); font-weight:400;
  font-size:clamp(1.5rem,7.4vw,4.7rem);
  line-height:1.62; letter-spacing:.03em; color:var(--ink-strong);
  font-feature-settings:"palt" 1;
}
.hero__title--sm{ font-size:clamp(1.5rem,5.6vw,3.6rem) }
.hero__title em{ font-style:normal }
.hero__lead{
  margin-top:clamp(2rem,4.5vh,3.2rem); max-width:33em;
  font-size:.9375rem; line-height:2.2; color:var(--ink); opacity:.86;
}
.hero__cue{
  position:absolute; left:var(--gut); bottom:clamp(2rem,5vh,3.4rem);
  display:flex; align-items:center; gap:1rem;
  font-size:.625rem; letter-spacing:.4em; text-transform:uppercase; color:var(--ink-mute);
}
.hero__cue span{ display:block; width:52px; height:1px; background:currentColor; opacity:.45; overflow:hidden; position:relative }
.hero__cue span::after{
  content:""; position:absolute; inset:0; background:var(--hanada);
  animation:cue 3.4s var(--ease-s) infinite;
}
@keyframes cue{ 0%{transform:translateX(-100%)} 55%,100%{transform:translateX(100%)} }

/* ================================================================= duo == */
.duo{ display:grid; gap:clamp(3rem,7vw,7rem); align-items:center }
.duo + .duo{ margin-top:clamp(6rem,13vw,12rem) }
.duo__text .h2{ margin-top:1.7rem }
.duo__text .lead{ margin-top:2rem; max-width:var(--measure) }
/* an opaque backdrop so each plate's `darken` blend always drops out
   against a light ground, whatever is drifting behind it */
.duo .plate{ aspect-ratio:4/3; background:var(--kinari) }
@media (min-width:900px){
  .duo{ grid-template-columns:minmax(0,1fr) minmax(0,1.08fr) }
  .duo--flip .duo__text{ order:2 }
  .duo--flip .plate{ order:1 }
  .duo .plate{ aspect-ratio:auto; height:clamp(24rem,42vw,34rem) }
}

/* ======================================================= aizome field == *
 * A reusable, image-free indigo-dye ambient background. Drop `.aizome-field`
 * into any `position:relative` container, add a few `.aizome-blob` children
 * (colour / size / position / timing set per-instance via custom properties
 * in `style=`), and it breathes on its own. No asset, no request, and every
 * property is tunable per section without touching this stylesheet.
 * ========================================================================= */
.aizome-field{
  /* no overflow/mask here on purpose: either one clips its own subtree to
     this box's exact edges, and since a field's box == its section's box,
     that clip line would land exactly on every section seam — the one
     place blobs most need to bleed through uninterrupted. `.dye-span`
     alone owns the clip, so a blob drifts and blurs straight across into
     the next section instead of being cut off at this box's edge. */
  position:absolute; inset:0; z-index:0; pointer-events:none;
}
/* paper texture is handled once, globally, by #grain — a per-field hatch
   here would be a second independent pattern per section, and two of those
   meeting at a section seam is exactly what shows up as a visible band */
.aizome-blob{
  position:absolute; left:var(--x,50%); top:var(--y,50%);
  width:var(--size,32vw); height:var(--size,32vw);
  max-width:var(--size-max,440px); max-height:var(--size-max,440px);
  background:radial-gradient(circle, var(--color,var(--hanada)), transparent 72%);
  /* --scroll-o is written every frame by the scroll loop: how close this
     blob's own position is to the middle of the viewport right now. That's
     what makes blooms surface and recede continuously as you scroll instead
     of being cut off at whichever section box they happen to sit in. */
  opacity:calc(var(--o,.55) * var(--scroll-o,1));
  filter:blur(var(--blur,60px));
  mix-blend-mode:var(--blend,multiply);
  border-radius:44% 56% 62% 38% / 48% 42% 58% 52%;
  transform:translate(-50%,-50%);
  /* riding the same --scroll-o: a bloom is smallest and lowest just before
     it surfaces, then blooms out to full size and settles into place as it
     nears the viewport's centre. `scale`/`translate` are standalone transform
     properties, composed *before* `transform`, so this never fights the drift
     keyframes for control of that property. */
  scale:calc(.8 + .2 * var(--scroll-o,1));
  translate:0 calc((1 - var(--scroll-o,1)) * 24px);
  /* a negative delay starts each blob already mid-cycle, so a page that
     loads several blobs at once never shows them pulse in lockstep */
  animation:var(--anim,aizome-drift-1) var(--dur,28s) ease-in-out var(--dir,normal) infinite;
  animation-delay:var(--delay,0s);
  will-change:transform, translate, scale, border-radius;
}
/* one bloom on each side of a section seam is exempted from the --scroll-o
   fade/scale entirely, so there's always at least one full-strength bloom
   bridging every join. */
.aizome-blob--bridge{
  opacity:var(--o,.55);
  scale:1;
  translate:0;
}
@keyframes aizome-drift-1{
  0%,100%{ transform:translate(-50%,-50%) scale(1); border-radius:44% 56% 62% 38% / 48% 42% 58% 52% }
  33%{ transform:translate(calc(-50% + 6%),calc(-50% + 5%)) scale(1.12); border-radius:58% 42% 46% 54% / 40% 58% 42% 60% }
  67%{ transform:translate(calc(-50% - 3%),calc(-50% + 7%)) scale(0.92); border-radius:38% 62% 54% 46% / 56% 44% 60% 40% }
}
@keyframes aizome-drift-2{
  0%,100%{ transform:translate(-50%,-50%) scale(1); border-radius:50% 50% 42% 58% / 58% 42% 50% 50% }
  50%{ transform:translate(calc(-50% - 7%),calc(-50% - 6%)) scale(1.16); border-radius:40% 60% 58% 42% / 46% 54% 44% 56% }
}
@keyframes aizome-drift-3{
  0%,100%{ transform:translate(-50%,-50%) scale(1); border-radius:56% 44% 40% 60% / 44% 56% 46% 54% }
  40%{ transform:translate(calc(-50% + 5%),calc(-50% - 4%)) scale(0.9); border-radius:42% 58% 56% 44% / 58% 40% 54% 46% }
  75%{ transform:translate(calc(-50% - 4%),calc(-50% + 3%)) scale(1.1); border-radius:60% 40% 44% 56% / 42% 58% 48% 52% }
}

/* ================================================================ coda == */
.coda{
  position:relative; background:var(--aisumi); color:var(--on-dark);
  padding-block:clamp(7rem,15vw,14rem);
  text-align:center; overflow:hidden;
}
.coda--tight{ padding-block:clamp(5rem,10vw,9rem) }
.coda__mark{ display:inline-flex; color:var(--kamenozoki); opacity:.9 }
.coda__word{
  margin-top:clamp(1.6rem,3.5vw,2.6rem);
  font-family:var(--mincho); font-weight:400;
  font-size:clamp(2.8rem,8.5vw,7rem); line-height:1.1; letter-spacing:.005em;
  color:var(--on-dark);
}
.coda__tag{
  margin-top:clamp(1.8rem,4vw,3rem);
  font-family:var(--heading); font-size:clamp(.9375rem,1.5vw,1.25rem);
  letter-spacing:.13em; color:rgba(237,235,227,.78); line-height:2.1;
}
.coda__act{ margin-top:clamp(2.6rem,5vw,4rem); display:flex; justify-content:center; flex-wrap:wrap; gap:1rem 1.4rem }

/* ============================================================== footer == */
.foot{
  background:var(--aisumi); color:var(--on-dark-mute);
  border-top:1px solid rgba(237,235,227,.10);
  margin-left:calc(var(--rail-w) * -1);
  padding-left:var(--rail-w);
  font-size:.6875rem; letter-spacing:.22em;
}
.foot__inner{
  width:100%; max-width:1240px; margin-inline:auto;
  padding:2.4rem var(--gut);
  display:flex; flex-wrap:wrap; gap:1rem 2rem; align-items:center; justify-content:space-between;
}
.foot a{ transition:color .5s var(--ease) }
.foot a:hover{ color:var(--on-dark) }
.foot__mark{ display:inline-flex; opacity:.55 }
.foot__nav{ display:flex; flex-wrap:wrap; gap:1rem 1.8rem; text-transform:uppercase }
.foot__top{ display:inline-flex; align-items:center; gap:.7em; text-transform:uppercase }
.foot__top svg{ transition:transform .6s var(--ease) }
.foot__top:hover svg{ transform:translateY(-4px) }

/* =========================================================== responsive == */
@media (max-width:959px){
  :root{ --rail-w:0px }
  .rail{ display:none }
  .nav{ display:none }
  .topbar{
    display:block; position:fixed; top:0; left:0; right:0; height:2px; z-index:110;
    background:var(--line-soft);
  }
  .topbar i{
    display:block; height:100%; width:var(--pw,0%);
    background:var(--kon);
  }
  .aizome-blob{ opacity:calc(var(--o,.55) * var(--scroll-o,1) * .75) }
}

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto }
  *,*::before,*::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .js [data-reveal]:not(.plate){ opacity:1; transform:none; filter:none }
  .js .plate img{ clip-path:none; transform:none }
  .js .piece-quote,.js .piece-assemble .pc{ opacity:1; transform:none; filter:none }
}
