/* =====================================================================
   River Tech — works.css (page layer for /works/ and the five /works/<slug>/ pages)
   Sits on top of base.css; uses its tokens and primitives only (docs/components.md).
   Local additions (not in the foundation):
   - .works-row      reference project row: band opens from the centre line, ghost name marquee (index + "Next work")
   - .work-plate     reference detail plate: grey panel with a desktop and a phone capture in thin bezels
   - .work-meta      reference meta list (Client / Category / Scope / URL ↗)
   - .works-veil     paper veil under the fixed header while screenshots pass beneath it (js/works.js)
   js/works.js keeps every name marquee at one speed whatever the length of the name, and drives the veil.
   1 page tokens · 2 index head · 3 rows · 4 row band + ghost · 5 index foot
   6 detail hero · 7 detail info · 8 detail sequence · 9 next work + back · 10 header veil · 11 SP · 12 forced colours
   ===================================================================== */

/* 1. Page tokens + Japanese line breaking ------------------------------ */
.works-page {
  --work-col: min(calc(90% - 136px), var(--w-l)); /* detail column: reference image width (1160 at 1440);
                                        the info block, plates and note all start on this one left edge */
  --row-pad: 40px 120px 40px 50px;      /* reference row padding (top right bottom left) */
  --row-x: 50px;                        /* row text start = left edge of the index grid */
  --work-panel: var(--c-form-line);     /* #dedede: the reference plate grey on paper */
  --icon-ext: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1.5 8.5 8.5 1.5M3 1.5h5.5V7' fill='none' stroke='%23000' stroke-width='1.2'/%3E%3C/svg%3E");
}
.works-nobr { white-space: nowrap; } /* brand names, the client's name and dates never break */
/* Japanese line breaking: Chromium 119+ breaks at phrase boundaries (auto-phrase). Safari and Firefox drop
   that value and keep keep-all: they break only at spaces, after 、。 and at the <wbr> phrase marks in the
   HTML; overflow-wrap is the safety net for a run that still does not fit. text-wrap avoids one-glyph lines. */
.works-page :is(p, h1, h2, h3, dd, figcaption) {
  word-break: keep-all;
  word-break: auto-phrase;
  overflow-wrap: anywhere;
  text-wrap: pretty;
}
/* Bodoni Moda follows the font size on its optical axis, so at 96–128px the hairlines (the W's thin strokes, the
   A's left leg) all but vanish. The 18 cut keeps the stroke contrast of the reference's Didot italic at display
   sizes (about.css does the same for its statement). Small accent words (No., Next work) keep the automatic cut. */
.works-title .accent-word,
.works-row__ghost .accent-word,
.work-seq__bg .accent-word { font-variation-settings: "opsz" 18; }

/* 2. Index head: centred 128/48 "ALL WORKS." (grotesk word + one italic word + an upright full stop, like the
   reference's "ALL PROJECTS."), italic count, JP sub, intro */
.works-index { padding-bottom: var(--space-200); }
.works-head { padding: 168px 5vw 0; text-align: center; } /* 160 + 8: the cap top of "ALL" lands on the reference's ~182 */
.works-title { display: flex; flex-direction: column; align-items: center; }
.works-title__line { position: relative; display: inline-block; }
.works-title__line .rv-mask { padding-inline: .06em .12em; margin-inline: -.06em -.12em; }
/* the italic W's wide side bearing opened a .35em word space; pull it back to the reference's ~.2em */
.works-title .accent-word { margin-left: -.14em; }
/* the reference count is a grotesk italic. The shared font link loads Inter Tight upright only; its italic
   digits and parentheses are a plain slant of the upright ones, so the browser's oblique is used here (13px,
   no letterforms change) instead of a second font file for six glyphs. */
.works-title__count {
  position: absolute;
  top: .6vw;
  left: calc(100% + 1.4vw);
  font-family: var(--ff-latin);
  font-size: var(--fs-small);
  font-style: italic;
  font-weight: 400;
  font-synthesis-style: auto;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}
.works-title__ja {
  display: block;
  margin-top: 32px;
  font-size: var(--fs-kicker);
  font-weight: 400;
  line-height: 1;
  letter-spacing: var(--ls-jp);
}
.works-head__intro {
  max-width: 46em;
  margin: var(--space-24) auto 0;
  font-size: var(--fs-kicker);
  line-height: 1.8;
  color: var(--fg-2);
}

/* 3. Rows: full-bleed list, hairlines between rows (whole row is the link) */
.works-list { margin-top: 96px; border-top: 1px solid var(--line); }
.works-list__item { border-bottom: 1px solid var(--line); }
.works-row {
  position: relative;
  isolation: isolate;
  display: flex;
  justify-content: space-between;
  gap: var(--space-40);
  padding: var(--row-pad);
  overflow: hidden;
  color: var(--fg);
  transition: color var(--d-instant);
}
.works-row__text {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-24);
  min-width: 0;
}
.works-row__no {
  font-family: var(--ff-latin);
  font-size: var(--fs-kicker);
  font-weight: 300;
  line-height: 1;
  letter-spacing: var(--ls-ui);
}
.works-row__of { margin-left: 12px; font-variant-numeric: tabular-nums; }
/* the row heading carries the client and the site name (two lines), so a heading list reads "CSAC 公式サイト" */
.works-row__title { display: block; }
.works-row__client {
  display: block;
  font-family: var(--ff-latin);
  font-size: var(--fs-small);
  line-height: 1.2;
  letter-spacing: var(--ls-ui);
}
.works-row__name { display: block; margin-top: 8px; font-family: var(--ff-latin); }
.works-row__role {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
  margin-top: 18px;
  font-family: var(--ff-latin);
  font-size: var(--fs-small);
  line-height: 1.2;
  letter-spacing: var(--ls-ui);
  color: var(--fg-mute);
  transition: color var(--d-instant);
}
.works-row__role .glyph { transition: background-color var(--d-instant); }
.works-row__desc {
  margin-left: 6px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  font-family: var(--ff-jp);
  letter-spacing: var(--ls-jp);
  transition: border-color var(--d-instant);
}
.works-row__media {
  flex: none;
  align-self: flex-start;
  width: 30%;
  max-width: 320px;
  overflow: hidden;
  border-radius: var(--r-thumb);
  background-color: var(--work-panel);
}
.works-row__media img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  transition: transform var(--d-menu) var(--ease-expo);
}

/* 4. Row band: two halves open from the centre line; the tone-on-tone ghost name fades in behind
   the text and runs only while the row is active. Hover is gated to fine pointers and mirrored on
   keyboard focus; :active gives touch a press state (the band closes again when the tap ends). */
.works-row::before,
.works-row::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  z-index: -2;
  height: calc(50% + 1px);
  background-color: var(--c-band);
  transform: scaleY(0);
  transition: transform var(--d-fast) var(--ease-band);
}
.works-row::before { top: 0; transform-origin: center bottom; }
.works-row::after { bottom: 0; transform-origin: center top; }
.works-row__ghost {
  position: absolute;
  top: 50%;
  inset-inline: 0;
  z-index: -1;
  color: var(--c-line-dark);
  opacity: 0;
  transform: translateY(-50%);
  /* the ghost is cut to the band: it opens and collapses from the same centre line with the same curve, so on
     mouse-out it never shows over the paper row; its opacity also drops at once (fades in slowly on entry) */
  clip-path: inset(50% 0);
  transition: opacity var(--d-instant), clip-path var(--d-fast) var(--ease-band);
  pointer-events: none;
}
.works-row__ghost .marquee__track { animation-play-state: paused; }
.works-row:focus-visible { outline-color: var(--c-accent-on-dark); outline-offset: -4px; }
.works-row:is(:focus-visible, :active) { color: var(--c-white); }
.works-row:is(:focus-visible, :active)::before,
.works-row:is(:focus-visible, :active)::after { transform: scaleY(1); }
.works-row:is(:focus-visible, :active) .works-row__role { color: var(--c-line); }
.works-row:is(:focus-visible, :active) .works-row__desc { border-color: var(--c-mute); }
.works-row:is(:focus-visible, :active) .glyph { background-color: var(--c-accent-on-dark); }
.works-row:focus-visible .works-row__ghost { clip-path: inset(0); opacity: 1; transition-duration: var(--d-base), var(--d-fast); }
.works-row:focus-visible .works-row__media img { transform: scale(1.03); }
html[data-motion="on"] .works-row:focus-visible .works-row__ghost:not(.is-offscreen) .marquee__track { animation-play-state: running; }
@media (hover: hover) and (pointer: fine) {
  .works-row:hover { color: var(--c-white); }
  .works-row:hover::before,
  .works-row:hover::after { transform: scaleY(1); }
  .works-row:hover .works-row__role { color: var(--c-line); }
  .works-row:hover .works-row__desc { border-color: var(--c-mute); }
  .works-row:hover .glyph { background-color: var(--c-accent-on-dark); }
  .works-row:hover .works-row__ghost { clip-path: inset(0); opacity: 1; transition-duration: var(--d-base), var(--d-fast); }
  .works-row:hover .works-row__media img { transform: scale(1.03); }
  html[data-motion="on"] .works-row:hover .works-row__ghost:not(.is-offscreen) .marquee__track { animation-play-state: running; }
  .works-row:active .works-row__media img { transform: scale(1.01); transition-duration: var(--d-instant); }
}

/* 5. Index foot: capture date note, closing line + ring button ------------ */
.works-note {
  padding: 16px var(--row-x) 0;
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--fg-mute);
}
.works-closing { margin-top: var(--space-120); padding-inline: 5vw; text-align: center; }
.works-closing__text { line-height: 1.8; }
.works-closing__btn { margin-top: var(--space-40); }

/* 6. Detail hero: near full-bleed capture (7:4 like the reference), image counter under it */
.work-hero { position: relative; padding-top: calc(var(--header-h) + 2px); } /* 106 / 98: the header probe line stays on paper at the top */
/* capped at the captures' native 1440px so wide screens never upscale them (1420 at the 1440 reference) */
.work-hero > .container--max { max-width: 1440px; }
.work-hero__frame { position: relative; overflow: hidden; border-radius: var(--r-thumb); background-color: var(--work-panel); }
.work-hero__img { width: 100%; height: auto; aspect-ratio: 7 / 4; object-fit: cover; object-position: top center; }
/* --full: the whole 16:10 capture, for a site whose own catch runs to the bottom edge of its first view (Japan
   JDM: the 7:4 crop cut "TO YOUR YARD" through the letters at every width) */
.work-hero__frame--full .work-hero__img { aspect-ratio: 16 / 10; }
/* Header colour over the capture: the transparent dark zone marks the dark part of the capture, shifted 48px
   down because core.js reads the header's bottom edge (104/96) while the logo's centre line sits ~48px higher.
   So the header turns white when the dark image reaches the logo, not 48px before (white logo on paper),
   and turns back when the image has left it. The zone is a sibling of the frame because the frame clips. */
.work-hero__stage { position: relative; }
.work-hero__zone {
  position: absolute;
  top: 48px;
  bottom: -48px;
  inset-inline: 0;
  background-color: transparent;
  pointer-events: none;
}
/* Noguchi: a light top band (the site's own header, 175 of 1440 capture px) above a dark photo. The image is
   scaled by width (16:10 in a 7:4 frame), so the band is a fixed 21.3% of the frame height. */
.work-hero__zone--below-band { top: calc(21.3% + 48px); }
/* the counter sits under the frame's right edge: every capture is different (dark, cream, white, busy
   navigation in the corners), so nothing is laid over the client's screen */
.work-hero__counter { flex-direction: row; justify-content: flex-end; gap: 8px; margin-top: 16px; }

/* 7. Detail info: name, one line, meta list ------------------------------ */
.work-info { padding-top: var(--space-96); } /* + the counter line under the hero = the reference 120 */
.work-wrap { width: var(--work-col); margin-inline: auto; }
.work-title { font-family: var(--ff-latin); }
.work-title .rv-mask { padding-inline-end: .06em; margin-inline-end: -.06em; }
/* balance: a lead that runs past one line splits into two even lines instead of leaving 「ホームページです。」 alone */
.work-lead { max-width: 50em; margin-top: 12px; line-height: 1.8; color: var(--fg-mute); }
.works-page .work-lead { text-wrap: balance; } /* beats the page-wide pretty rule (section 1) */
/* 33px gap + the 15px/1.65 value line = the reference 57px row pitch (36px + 13px/1.65) */
.work-meta { display: flex; flex-direction: column; gap: 33px; max-width: 560px; margin-top: 80px; }
.work-meta__row { display: flex; gap: 16px; }
.work-meta__key {
  flex: none;
  width: 72px;
  padding-top: .2em;
  font-family: var(--ff-latin);
  font-size: var(--fs-label);
  line-height: 1.2;
  color: var(--fg-mute);
}
.work-meta__value { min-width: 0; font-size: var(--fs-kicker); line-height: 1.65; overflow-wrap: anywhere; }
.work-meta__link {
  font-family: var(--ff-latin);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  transition: color var(--d-fast), text-decoration-color var(--d-fast);
}
.work-meta__link::after {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-left: 6px;
  vertical-align: .1em;
  background-color: currentColor;
  -webkit-mask: var(--icon-ext) center / contain no-repeat;
  mask: var(--icon-ext) center / contain no-repeat;
  transition: transform var(--d-fast) var(--ease-cubic);
}
.work-meta__link:focus-visible { color: var(--accent); }
.work-meta__link:focus-visible::after { transform: translate(2px, -2px); }
.work-meta__link:active { color: var(--accent); text-decoration-color: transparent; }
@media (hover: hover) and (pointer: fine) {
  .work-meta__link:hover { color: var(--accent); }
  .work-meta__link:hover::after { transform: translate(2px, -2px); }
}

/* 8. Detail sequence: plates 120px apart, each over a giant name marquee ------------ */
.work-seq { padding-top: 180px; overflow-x: clip; }
.work-seq__list { display: flex; flex-direction: column; gap: 120px; }
.work-seq__item { position: relative; isolation: isolate; }
.work-seq__bg {
  position: absolute;
  top: 50%;
  inset-inline: 0;
  z-index: -1;
  color: var(--fg);
  transform: translateY(-50%);
}
.work-seq__bg .rv-mask { padding-inline-end: .12em; margin-inline-end: -.12em; }
.work-seq__figure { position: relative; width: var(--work-col); margin-inline: auto; }
.work-plate {
  container-type: inline-size;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7.5%;
  aspect-ratio: 1160 / 661;
  border-radius: var(--r-thumb);
  background-color: var(--work-panel);
}
/* desktop 57.4% of the plate, phone matched to its height (1440:900 and 390:844 captures) */
.work-plate__screen {
  --bezel: clamp(2px, .52cqi, 6px);
  flex: none;
  overflow: hidden;
  border: var(--bezel) solid var(--c-line);
  border-radius: calc(var(--r-thumb) + var(--bezel));
  background-color: var(--c-white);
}
.work-plate__screen--desktop { width: calc(57.4cqi + var(--bezel) * 2); }
.work-plate__screen--mobile { width: calc(16.577cqi + var(--bezel) * 2); }
.work-plate__screen img { display: block; width: 100%; height: auto; }
/* a few captures carry a 4px dark edge baked into the site's own hero image: scale it out of the frame */
.work-trim-l img { transform: scale(1.012); transform-origin: right center; }
.work-trim-b img { transform: scale(1.012); transform-origin: center top; }
.work-seq__counter { position: absolute; top: 0; right: -24px; transform: translateX(100%); }
.work-seq__note {
  width: var(--work-col);
  margin: 24px auto 0;
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--fg-mute);
}

/* 9. Next work row + back button ----------------------------------------- */
.work-next { padding-top: var(--space-120); padding-bottom: var(--space-200); }
.work-next__list { border-block: 1px solid var(--line); }
/* on a detail page the row text and thumbnail sit on the page column (the plates' edges), not on the
   index grid; the band itself stays full-bleed */
.work-next .works-row { padding-inline: calc((100% - var(--work-col)) / 2); }
.works-row--next .accent-word { margin-right: .1em; }
.work-back { margin-top: var(--space-120); }

/* 10. Header veil: the subpage header is transparent ink type on paper (reference), but these pages scroll
   dark and busy screenshots under it (the phone capture sits right under Home / Works / Service at 1440, the
   logo and burger sit over the plates on phones). A data-theme zone cannot help: the header flips as one, so a
   white header would lose its logo on the paper beside the plate. Instead a paper band, solid behind the
   header type and fading out below it, fades in while a [data-veil] region (the index row list, the plate
   sequence, the next-work row) is under the header (js/works.js adds .is-on), and only while the header is
   ink, so it never sits under a white header (dark hero zone, footer). Titles and text pass under the
   transparent header as in the reference; over a screenshot the image dissolves into the paper instead.
   It is a page element under the header (z-index one below it), not a restyle of the shared header. */
.works-veil {
  --veil-fade: 24px; /* the soft edge starts this far above the header's bottom line and ends as far below it */
  position: fixed;
  top: 0;
  inset-inline: 0;
  z-index: calc(var(--z-header) - 1);
  height: calc(var(--header-h) + var(--veil-fade));
  background-image: linear-gradient(to bottom, var(--c-paper) calc(var(--header-h) - var(--veil-fade)), transparent);
  opacity: 0;
  transition: opacity var(--d-base) var(--ease-cubic);
  pointer-events: none;
}
html[data-header="ink"]:not(.is-menu-open) .works-veil.is-on { opacity: 1; }

/* 11. SP (<=768px) ---------------------------------------------------------- */
@media (max-width: 768px) {
  .works-page { --row-x: 5vw; --work-col: 90%; }
  .works-head { padding-top: 168px; }
  .works-title__ja { margin-top: 24px; }
  .works-list { margin-top: var(--space-96); }
  .works-row { flex-direction: column-reverse; justify-content: flex-start; gap: 5vw; padding: 8vw 5vw; }
  .works-row__text { display: block; }
  .works-row__no { position: absolute; top: 8vw; left: 5vw; max-width: 28%; line-height: 1.5; }
  .works-row__of { display: block; margin: 2px 0 0; }
  .works-row__media { width: 65%; max-width: none; margin: 0 -2vw 0 auto; }
  .works-row__desc { flex-basis: 100%; margin: 4px 0 0; padding-left: 0; border-left: 0; }
  .work-hero__counter { margin-top: 12px; }
  /* the reference keeps its detail rhythm on phones: 120 from the image to the name, the meta list 80 below the
     lead with a 56px row pitch, and 180 down to the first plate */
  .work-info { padding-top: 96px; }
  .work-meta__key { width: 80px; }
  .work-seq__list { gap: 96px; }
  /* the plate fills 90% of the width, so the name behind it showed only 4-20px slivers of letters at the edges,
     which read as stray marks; phones show the plates alone */
  .work-seq__bg { display: none; }
  .work-seq__counter { top: -12px; right: 0; flex-direction: row; gap: 8px; transform: translateY(-100%); }
  .work-next { padding-top: var(--space-120); }
  .work-back { margin-top: var(--space-80); }
}

/* 12. Forced colours: keep the page's own mask glyphs visible; the system backplates the header type itself */
@media (forced-colors: active) {
  .works-veil { display: none; }
  .work-meta__link::after { forced-color-adjust: none; background-color: CanvasText; }
  .work-plate__screen { border-color: CanvasText; }
}
