/* ============================================================
   Project page layout
   Loaded AFTER styles.css, which owns the tokens, .mono, .accent,
   ::selection, the custom cursor and the reduced-motion block.
   This file is shared by every project page — keep it generic.
   ============================================================ */

:root {
  --kanji: 'Noto Serif JP', 'Hiragino Mincho ProN', serif;
  --void: #0d0d0d;              /* the "rich black" from the brand doc */
  --void-text: #f1efe9;
  --sku: var(--accent);         /* overridden per SKU by the switcher */
}

/* ---------- Shell ---------- */
.project {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(96px, 12vw, 150px) var(--pad) clamp(50px, 7vw, 90px);
  display: grid;
  grid-template-columns: minmax(230px, 1fr) 2.1fr;
  gap: clamp(30px, 5vw, 70px);
}

/* ---------- Sticky info column ----------
   align-self: start is load-bearing — a stretched grid item cannot stick.
   Keep the content shorter than the viewport or sticky silently stops. */
.project__aside {
  position: sticky;
  top: clamp(90px, 11vw, 120px);
  align-self: start;
}
.project__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.6rem, 6vw, 4.2rem);
  line-height: 0.92;
  letter-spacing: 0;
  display: flex;
  align-items: baseline;
  gap: 0.34em;
}
/* Brand mark beside the project title — the image counterpart of .ji, for
   projects whose mark is artwork rather than a glyph. height in em rides the
   responsive title size for free. Swapped per product by project.js. */
.project__mark {
  height: 0.72em;     /* ~cap height: a spiky mark needs more than a dense
                         glyph to carry the same weight beside the wordmark */
  width: auto;
  align-self: baseline;
  opacity: 1;
  transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.project__mark.is-swapping { opacity: 0; }

/* Long titles: the .line mask is overflow:hidden, so a word wider than the
   column is silently CLIPPED rather than wrapped. Short names (MA, Anther)
   hide the problem. Any title past ~7 characters needs this. */
.project__title--long { font-size: clamp(1.9rem, 4vw, 2.9rem); }

.project__title .ji {
  font-family: var(--kanji);
  font-size: 0.46em;
  color: var(--sku-ink, var(--sku));
  transition: color 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.project__meta {
  color: var(--muted);
  margin-top: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
}
.project__note {
  margin-top: 22px;
  max-width: 34ch;
  color: #34332b;
  font-size: 1rem;
  line-height: 1.5;
}
.project__back {
  display: inline-block;
  margin-top: 26px;
  padding: 14px 4px;
  margin-left: -4px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  transition: color 0.2s var(--ease);
}

/* ---------- Media column ---------- */
.project__media { min-width: 0; }

.shot { margin: 0 0 clamp(14px, 2vw, 22px); }
/* The intro scales the hero image to 1.06 and settles it back. Nothing paints
   outside (clip-path masks it) but the layout box still overflowed the page by
   a few px at narrow widths. Clipping at the figure keeps the maths honest. */
.shot--hero { overflow: hidden; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--bg-2);
}
/* Two side by side — stops a column of identical portraits from droning on */
.shot-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 2vw, 22px);
  margin-bottom: clamp(14px, 2vw, 22px);
}
.shot-pair .shot { margin: 0; }

.shot figcaption {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-top: 9px;
}

/* Section label inside the media column */
.strip {
  font-family: var(--font-mono);
  /* An <h2> in the markup so project pages have a document outline; these
     two lines keep it looking like the quiet label it is. */
  font-weight: 400;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: clamp(38px, 5vw, 62px) 0 16px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  gap: 16px;
}
.strip:first-child { margin-top: 0; }

/* ---------- SKU switcher band ----------
   Full-bleed, and the ground carries a wash of the live variant. Changing the
   ground is what tells you this is a control rather than more gallery, before
   a single word is read. --sku-wash is set by project.js. */
.sku-band {
  background-color: var(--sku-wash, var(--bg-2));
  padding: clamp(54px, 8vw, 100px) var(--pad);
  margin-top: clamp(40px, 6vw, 80px);
  transition: background-color 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.sku-band__inner { max-width: var(--maxw); margin: 0 auto; }

.sku__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: clamp(20px, 3vw, 32px);
}
.sku__ji {
  font-family: var(--kanji);
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  line-height: 1;
  color: var(--sku-ink, var(--sku));
  flex: none;
  transition: color 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.no-js-sku .sku__ji { display: none; }

.sku__tabs { display: flex; flex-wrap: wrap; gap: 10px; }
/* Deliberately larger than the page's other mono chrome — this one is a control. */
.sku__tab {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 100px;
  padding: 13px 22px;
  cursor: pointer;
  transition: border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1),
              color 0.45s cubic-bezier(0.4, 0, 0.2, 1),
              background-color 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}
.sku__tab .dot {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--c);
  flex: none;
}
.sku__tab[aria-selected="true"] {
  border-color: var(--c);
  background: var(--c);
  /* Not always white: a light brand colour needs dark text. project.js picks
     whichever of the two actually reads on the active colour. */
  color: var(--sku-on, #fff);
}
.sku__tab:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }

/* Three-up: cord, opened, bottle — the whole variant readable at a glance */
.sku__shots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.8vw, 20px);
}
.sku__shots .shot { margin: 0; }

.sku__panel[hidden] { display: none; }
.sku__panel { animation: skuIn 0.55s cubic-bezier(0.4, 0, 0.2, 1) both; }
@keyframes skuIn { from { opacity: 0; } to { opacity: 1; } }

/* No JS: the switcher is meaningless, so show every variant in sequence */
.no-js-sku .sku__tabs { display: none; }
.no-js-sku .sku__panel[hidden] { display: block; }

/* ---------- Booklet viewer ----------
   Click-through rather than a long scroll, so a booklet still reads like one.
   Generic: any print project can use it. Without JS the fallback below is the
   page — every spread in sequence — so nothing depends on this running. */
.booklet {
  background: var(--bg-2);
  padding: clamp(50px, 8vw, 92px) var(--pad);
  margin-top: clamp(50px, 8vw, 100px);
}
.booklet__inner { max-width: var(--maxw-wide, 1500px); margin: 0 auto; }

/* no-JS / pre-init: the plain sequence */
.booklet__fallback { display: grid; gap: clamp(16px, 2.4vw, 30px); }
.booklet__fallback figure { margin: 0; }
.booklet__fallback img { display: block; width: 100%; height: auto; background: var(--bg); }
.booklet.is-live .booklet__fallback { display: none; }
/* Cover and back are single pages among spreads — at full width they tower.
   Only affects the no-JS fallback; the viewer contains them automatically. */
.booklet__fallback .is-single { width: 58%; margin-inline: auto; }
@media (max-width: 820px) { .booklet__fallback .is-single { width: 100%; } }

/* the viewer itself, built by project.js */
.booklet__stage {
  position: relative;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  /* Height is fixed by the widest page type, so a single cover page is
     contained rather than towering, and the frame never jumps between
     pages. Capped against the viewport so it always fits on screen. */
  aspect-ratio: var(--stage-ratio, 2.59);
  max-height: 74vh;
  touch-action: pan-y;   /* horizontal gestures belong to the page turner */
  /* max-height transfers back through aspect-ratio and shrinks the box's
     WIDTH, so the stage is narrower than this column. Without auto margins a
     block-level box then sits hard left — which read as "not centred" even
     with the spread fully open. */
  margin-inline: auto;
}
.booklet__stage img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  transition: opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
.booklet__stage.is-turning img { opacity: 0; }
/* The section takes focus so Left/Right actually reach their handler;
   without a ring there'd be no sign it had focus. */
.booklet:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: 4px;
}
.booklet:focus:not(:focus-visible) { outline: none; }

.booklet__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  margin-top: clamp(14px, 2vw, 22px);
}
.booklet__count {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.booklet__nav { display: flex; gap: 10px; }
.booklet__btn {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 100px;
  padding: 14px 22px;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.booklet__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.booklet__btn:disabled { opacity: 0.32; cursor: default; }

@media (prefers-reduced-motion: reduce) {
  .booklet__stage img { transition: none; }
}

/* ---------- Statement block ----------
   A full-bleed section for a project's central idea. Treatment is chosen
   per project: MA uses --dark because 間 IS the void, so the page contains
   one. Default is light, so the dark band stays a decision rather than a
   habit repeated on every project. */
.statement {
  background: var(--bg-2);
  color: var(--text);
  padding: clamp(80px, 13vw, 170px) var(--pad);
  margin-top: clamp(50px, 8vw, 100px);
  position: relative;
  overflow: hidden;
}
.statement--dark { background: var(--void); color: var(--void-text); }

.statement__inner {
  max-width: var(--maxw);
  margin: 0 auto;
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(230px, 1fr) 2.1fr;
  gap: clamp(30px, 5vw, 70px);
}
/* Optional oversized glyph cropped off the top-left. MA uses it because the
   packaging's own rule bleeds the hero kanji off the edge; omit it elsewhere
   unless the project has a mark that earns it. */
.statement__mark {
  position: absolute;
  top: -0.34em;
  left: -0.12em;
  font-size: clamp(16rem, 42vw, 40rem);
  line-height: 1;
  color: currentColor;
  opacity: 0.045;
  pointer-events: none;
  user-select: none;
}
.statement__label {
  font-family: var(--font-mono);
  font-weight: 400;   /* also an <h2> — see .strip */
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.statement--dark .statement__label { color: rgba(241, 239, 233, 0.5); }

.statement__body p {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.4rem, 2.7vw, 2.1rem);
  line-height: 1.28;
  max-width: 26ch;
}
.statement__body p + p { margin-top: 1em; }
/* The project's line, in the live accent. Extreme tracking is borrowed from
   MA's packaging but reads as a considered caption anywhere. */
.statement__line {
  margin-top: clamp(30px, 4vw, 48px);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.34em;
  color: var(--sku-ink, var(--sku));
  transition: color 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}


/* ---------- Materials, one quiet line ---------- */
.materials {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(46px, 7vw, 80px) var(--pad) 0;
  color: var(--muted);
  font-size: 0.68rem;
  line-height: 1.8;
}

/* ---------- Next ---------- */
.next {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(60px, 9vw, 110px) var(--pad) clamp(70px, 10vw, 120px);
}
.next a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  border-top: 1px solid var(--line);
  padding-top: 24px;
  transition: color 0.3s var(--ease);
}
.next__t {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.8rem, 5vw, 3.2rem);
  line-height: 1;
  transition: transform 0.4s var(--ease);
}


/* ---------- Intro (project.js) ----------
   Pre-hidden only when JS can bring it back. The head script's 6s failsafe
   strips .js if project.js never arrives. */
/* overflow:hidden is the rise mask. line-height 0.92 makes that box shorter
   than the letters, so pad it down and pull the same back off the margin —
   same fix the hero needed, or the p in "Loopkicks" and "Performance" is cut. */
.project__title .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.18em;
  margin-bottom: -0.18em;
}
/* Load-bearing: transform does nothing on an inline box, so without this the
   pre-hide below and GSAP's yPercent were both silently discarded and the
   title never animated at all. */
.project__title .word { display: inline-block; will-change: transform; }
.js .project__title .word { transform: translateY(110%); }
.js .project__meta,
.js .project__note,
.js .project__back { opacity: 0; }
.js .shot--hero { clip-path: inset(100% 0 0 0); }
.js .shot--hero img { transform: scale(1.06); }

/* ---------- Hover states ----------
   Grouped and capability-gated so nothing sticks after a tap on touch. */
@media (hover: hover) and (pointer: fine) {
  .project__back:hover { color: var(--accent); }
  .sku__tab:hover { border-color: var(--c); }
  .booklet__btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
  .next a:hover { color: var(--accent); }
  .next a:hover .next__t { transform: translateX(10px); }
}

/* ---------- Responsive ---------- */
@media (max-width: 820px) {
  .project, .statement__inner { grid-template-columns: 1fr; }
  /* Sticky needs a tall viewport and a second column to sit beside. */
  .project__aside { position: static; }
  /* Two-up rather than one: a single column here made each switcher image
     ~920px tall on an iPad, roughly 2800px of scroll per panel. */
  .sku__shots { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .shot-pair { grid-template-columns: 1fr; }
  .sku__shots { grid-template-columns: 1fr; }
  /* The --long modifier exists to stop a wide title being clipped by the
     mask in a narrow desktop column. On a phone the title wraps instead, so
     the smaller size buys nothing and just shrinks two of the four pages. */
  .project__title--long { font-size: clamp(2.6rem, 6vw, 4.2rem); }
  /* "Next project →" was wrapping mid-label beside a two-line title. */
  .next a { flex-direction: column; align-items: flex-start; gap: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .sku__panel { animation: none; }
  .sku-band { transition: none; }
  /* Nothing may be left pre-hidden when motion is off. */
  .js .project__title .word { transform: none; }
  .js .project__meta,
  .js .project__note,
  .js .project__back { opacity: 1; }
  .js .shot--hero { clip-path: none; }
  .js .shot--hero img { transform: none; }
  .project__title .ji,
  .project__mark,
  .statement__line,
  .sku__ji,
  .sku__tab { transition: none; }
}
