/* ==========================================================================
   v9 /work pages: the case study template and (section 8) the /work index. Loaded after
   v9-tokens.css and v9.css on /work/* only.
   The page reads like a job file: fold with title + docket, then numbered parts on the shop's
   own grid (Problem, Thinking, Outcome, the work), a drawn figure where it explains the job, and
   the next case. White and ink still switch hard, section by section.
   ========================================================================== */


/* ------------------------------------------------------------ 1. fold */
.cs-fold { padding-bottom: var(--space-6); }
.cs-fold__grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-6);
                 align-items: end; padding: var(--space-5) var(--frame-pad) 0; }
.cs-fold__eyebrow { color: var(--fg-2); margin-bottom: var(--space-3); }
.cs-fold__title { font: 600 clamp(2.75rem, 6.4vw, 6.25rem)/.95 var(--font-text); letter-spacing: -.045em;
                  max-width: 11ch; margin-bottom: var(--space-5); }

/* The docket: the job's facts as a ruled ledger. */
.docket { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 2px solid var(--fg); }
.docket > div { padding: .8rem 1rem .9rem 0; border-bottom: var(--rule) solid var(--line); }
.docket dt { color: var(--fg-2); margin-bottom: .45rem; }
.docket dd { font: 500 1rem/1.35 var(--font-text); }

.cs-fold__img { margin: 0; position: relative; overflow: hidden; background: var(--bg); }
.cs-fold__img img { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.cs-fold__img figcaption { position: absolute; left: 0; right: 0; bottom: 0; display: flex; justify-content: space-between;
                           padding: .6rem .8rem; background: var(--fg); color: var(--bg); }

@media (max-width: 1023px) {
  .cs-fold__grid { grid-template-columns: 1fr; gap: var(--space-5); }
  .cs-fold__img { max-width: 560px; }
}
@media (max-width: 767px) {
  .docket { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ------------------------------------------------------------ 2. numbered parts */
/* Each part: the number and name in the left column, the copy in the right. */
.cs-part { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); gap: var(--space-2) var(--space-5);
           padding: var(--space-5) var(--frame-pad); border-top: var(--rule) solid var(--line); }
.on-ink .cs-part, .cs-part.on-ink { border-top-color: var(--line); }
.cs-part__h { display: grid; gap: .5rem; align-content: start; }
.cs-part__h .label { color: var(--fg-2); }
.on-ink .cs-part__h .label { color: var(--fg-2); }
.cs-part__name { font: 600 var(--step-2)/1.05 var(--font-text); letter-spacing: -.025em; }
.cs-part__body { display: grid; gap: var(--space-4); }
.cs-copy { font: 400 clamp(1.125rem, 1.6vw, 1.375rem)/1.55 var(--font-text); max-width: 46ch; }

/* a figure inside a part: picture or drawing, its caption under a hairline */
.cs-fig { margin: 0; }
.cs-fig img, .cs-fig svg { display: block; width: 100%; height: auto; }
/* The drawings' generators write white faces (fill="#fff") for parts that hide what is behind
   them; dark only, those faces are the page. Strokes are currentColor already. */
.cs-fig svg [fill="#fff"] { fill: var(--bg); }
.cs-fig figcaption { display: flex; justify-content: space-between; gap: var(--space-2); margin-top: .6rem;
                     padding-top: .6rem; border-top: var(--rule) solid var(--line); color: var(--fg-2); }
.on-ink .cs-fig figcaption { border-top-color: var(--line); color: var(--fg-2); }
.cs-fig--sketch { max-width: 520px; position: relative; overflow: hidden; }
.cs-fig--plan { max-width: 760px; position: relative; }
.cs-fig--badge { max-width: 860px; position: relative; }
.cs-fig--badge figcaption { flex-wrap: wrap; }
.cs-set { color: var(--fg-2); }   /* a one-line note under a gallery ("Mockups, not installs.") */
.cs-legend { display: flex; flex-wrap: wrap; gap: .4rem 1.1rem; }
.cs-legend b { font-weight: 700; margin-right: .35em; color: var(--fg); }

/* the outcome, on ink, as one big statement */
.cs-outcome { font: 600 clamp(1.75rem, 3.6vw, 3.25rem)/1.1 var(--font-text); letter-spacing: -.03em; max-width: 26ch; }

@media (max-width: 767px) {
  .cs-part { grid-template-columns: 1fr; }
}


/* ------------------------------------------------------------ 3. galleries */
.cs-grid { display: grid; gap: var(--space-3); }
.cs-grid--guide { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.cs-grid--use { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.cs-grid--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cs-grid--three img { aspect-ratio: 4 / 3; object-fit: cover; }   /* squares keep theirs: 4:3 only crops the 4:3 */
.cs-grid--three img[width="560"] { aspect-ratio: 1; }
.cs-grid figure { margin: 0; }
.zoom { display: block; position: relative; overflow: hidden; background: var(--bg); cursor: zoom-in; }
.zoom img { width: 100%; height: auto; }
.cs-grid figcaption { margin-top: .5rem; padding-top: .45rem; border-top: var(--rule) solid var(--line); color: var(--fg-2); }
.on-ink .cs-grid figcaption { border-top-color: var(--line); color: var(--fg-2); }
.zoom:focus-visible { outline-offset: 4px; }
@media (hover: hover) {
  .zoom::after { content: "+"; position: absolute; right: .5rem; top: .5rem; display: grid; place-items: center;
                 width: 1.75rem; height: 1.75rem; background: var(--fg); color: var(--bg);
                 font: 500 1rem/1 var(--font-mono); opacity: 0; }
  .on-ink .zoom::after { background: var(--green); color: var(--on-green); }
  .zoom:hover::after, .zoom:focus-visible::after { opacity: 1; }
}
@media (max-width: 1023px) { .cs-grid--guide { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 767px) {
  .cs-grid--guide { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
  .cs-grid--use { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
  .cs-grid--three { grid-template-columns: 1fr; }   /* three across is too small to read a mark on a phone */
}

/* margin spec notes, in Julio's hand (placeholder face until his font exists) */
.hand { font: 400 1.05rem/1.3 var(--font-hand); color: var(--fg-2); rotate: -3deg; transform-origin: left; }
.on-ink .hand { color: var(--fg-2); }
.cs-notes { display: grid; gap: .1rem; justify-self: start; }
/* A green highlighter swipe behind one note per screen (green text is never allowed on white;
   ink on green is). A hard-edged band over the lower part of the letters, like a marker pass. */
.hand--hl { justify-self: start; padding: 0 .2em;
            background: linear-gradient(var(--green), var(--green)) 0 72% / 100% .62em no-repeat; }
@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .hand--hl { animation: hlBand var(--settle) both; animation-timeline: view(); animation-range: entry 100% cover 45%; }
    @keyframes hlBand { from { background-size: 0% .62em; } }
  }
}


/* ------------------------------------------------------------ 4. next case */
.cs-next { display: grid; gap: var(--space-2); padding: var(--space-6) var(--frame-pad); text-decoration: none; }
.cs-next__label { display: flex; justify-content: space-between; color: var(--fg-2); }
.cs-next__title { font: 600 clamp(2.5rem, 6vw, 6rem)/.95 var(--font-text); letter-spacing: -.045em; }
.cs-next__go { justify-self: start; margin-top: var(--space-2); }
.cs-next:hover .cs-next__title, .cs-next:focus-visible .cs-next__title { text-decoration: underline;
  text-decoration-thickness: 3px; text-underline-offset: .12em; }
.cs-next:hover .btn, .cs-next:focus-visible .btn { background: var(--green); color: var(--on-green); }
.cs-next:hover .btn .lamp, .cs-next:focus-visible .btn .lamp { background: var(--on-green); }


/* ------------------------------------------------------------ 5. lightbox */
.lb { width: min(1200px, 100vw - 2rem); max-width: none; max-height: calc(100svh - 2rem); padding: 0;
      border: 0; background: var(--bg); color: var(--fg); }
.lb::backdrop { background: rgba(0, 0, 0, .86); }
.lb__frame { display: grid; grid-template-rows: minmax(0, 1fr) auto; max-height: calc(100svh - 2rem); }
.lb__img { width: 100%; height: 100%; max-height: calc(100svh - 6rem); object-fit: contain; background: var(--bg); }
.lb__bar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
           padding: .6rem .8rem; border-top: var(--rule) solid var(--line); }
.lb__nav { display: flex; align-items: center; gap: .5rem; }
.lb__bar button { padding: .7rem .8rem; cursor: pointer; }
.lb__bar button:hover, .lb__bar button:focus-visible { color: var(--green); }
.lb :focus-visible { outline-color: var(--green); }
@media (prefers-reduced-motion: no-preference) {
  .lb[open] { animation: lbIn var(--t-open) var(--smooth); }
  .lb[open]::backdrop { animation: lbFade var(--t-open) var(--smooth); }
  @keyframes lbIn { from { opacity: 0; translate: 0 12px; } }
  @keyframes lbFade { from { opacity: 0; } }
}


/* ------------------------------------------------------------ 6. motion */
/* Fig. 01's route draws itself as the figure crosses the screen, then the seat lights. */
@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .cs-fig--plan { view-timeline: --plan block; }
    .route__path { stroke-dasharray: 1 1; animation: routeDraw linear both; animation-timeline: --plan;
                   animation-range: cover 22% cover 50%; }
    .route__seat { animation: routeSeat steps(1, end) both; animation-timeline: --plan;
                   animation-range: cover 50% cover 52%; }
    @keyframes routeDraw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
    @keyframes routeSeat { from { opacity: 0; } }
  }
}
.route__hand { font-family: var(--font-hand); font-size: 14px; }

/* AZ Garage Floors Fig. 01: once the whole badge is on screen, the six parts the new mark dropped
   fade back in four hard steps, leaving the three it kept (AZ, the name, one saguaro) standing
   with their green callouts. Opacity only. Static, whole drawing without scroll timelines. */
@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .cs-fig--badge { view-timeline: --badge block; }
    .badge__drop { animation: badgeDrop steps(4, end) both; animation-timeline: --badge;
                   animation-range: contain 8% contain 40%; }
    @keyframes badgeDrop { to { opacity: .22; } }
  }
}

/* Ore-Ida Fig. 01: the cap is taken apart in order, the way you would by hand. It stays
   assembled until the whole figure is on screen, then the bill drops, the rope follows, and the
   patch lifts off last, each in four hard steps and overlapping a little so it reads as one
   sequence. Done by the time the figure is centred (measured: top at ~24% of a 900px screen). `contain` is the stretch where the whole
   figure is visible, so the timing holds at any viewport height. Each part carries its own way
   home (--dx, --d) from _dev/drawings/cap-tp.py; the crown never moves. */
@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .cs-fig--cap { view-timeline: --cap block; }
    .cs-fig--cap .part__move { animation: capOpen steps(4, end) both; animation-timeline: --cap; }
    .cs-fig--cap .part--brim .part__move  { animation-range: contain 4% contain 20%; }
    .cs-fig--cap .part--rope .part__move  { animation-range: contain 16% contain 32%; }
    .cs-fig--cap .part--patch .part__move { animation-range: contain 28% contain 46%; }
    @keyframes capOpen { from { transform: translate(var(--dx, 0px), var(--d, 0px)); } }
  }
}


/* ------------------------------------------------------------ 7. pairs and the colourway sequence */
.cs-grid--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 880px; }
.cs-fig--cap { max-width: 760px; position: relative; }

/* Colourways, ported from live (v7 §2). Each is the SIDE view from Julio's own tech pack
   (_dev/oreida/build.py: real vectors, one 3:2 drawing per colourway). They share one camera, so
   stacked in a sticky frame they read as ONE cap changing colour in place. Clicking one opens the
   full sheet (front, back, both sides) in the lightbox. The count is a counter wheel and the
   progress is the ruler, so it speaks the same language as the rest of v9. Every step lands at
   the same three thresholds (22%, 47%, 72% of the sequence). Phones, reduced motion and browsers
   without scroll timelines get the plain 2-up grid. */
.seq { padding: 0 var(--frame-pad) var(--space-6); }
.seq__frame { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.seq__frame figure { margin: 0; }
.seq__frame figcaption { margin-top: .5rem; padding-top: .45rem; border-top: var(--rule) solid var(--line); color: var(--fg-2); }
.seq__aside { display: none; }
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    .seq { height: 300vh; padding: 0; view-timeline: --seq block; }
    .seq__stage { --size: min(calc((100svh - var(--header-h) - 8rem) * 1.5), 54vw);
                  position: sticky; top: var(--header-h); height: calc(100svh - var(--header-h));
                  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center;
                  gap: var(--space-6); padding-inline: var(--frame-pad); }
    .seq__frame { position: relative; display: block; width: var(--size); aspect-ratio: 3 / 2; }
    .seq__frame figure { position: absolute; inset: 0; }
    .seq__frame figcaption { display: none; }
    .seq__frame .zoom, .seq__frame img { width: 100%; height: 100%; object-fit: cover; }
    .seq__frame figure:nth-child(n+2) { animation: seqIn linear both; animation-timeline: --seq; }
    .seq__frame figure:nth-child(2) { animation-range: contain 21% contain 23%; }
    .seq__frame figure:nth-child(3) { animation-range: contain 46% contain 48%; }
    .seq__frame figure:nth-child(4) { animation-range: contain 71% contain 73%; }
    @keyframes seqIn { from { opacity: 0; visibility: hidden; } to { opacity: 1; visibility: visible; } }

    .seq__aside { display: grid; gap: var(--space-4); align-content: center; max-width: 26rem; }
    .seq__count { display: flex; font: 600 clamp(6rem, 12vw, 11rem)/1 var(--font-text); letter-spacing: -.04em; }
    .seq__wheel { display: inline-block; height: 1em; overflow: hidden; }
    .seq__wheel > span { display: grid; animation: seqCount linear both; animation-timeline: --seq;
                         animation-range: contain 0% contain 100%; }
    .seq__wheel > span > span { height: 1em; }
    @keyframes seqCount { 0%, 22% { transform: translateY(0); } 22.1%, 47% { transform: translateY(-1em); }
                          47.1%, 72% { transform: translateY(-2em); } 72.1%, 100% { transform: translateY(-3em); } }
    .seq__index { display: grid; gap: .6rem; }
    .seq__index li { opacity: .35; animation: linear both; animation-timeline: --seq; animation-range: contain 0% contain 100%; }
    .seq__index li:nth-child(1) { animation-name: seqI1; }
    .seq__index li:nth-child(2) { animation-name: seqI2; }
    .seq__index li:nth-child(3) { animation-name: seqI3; }
    .seq__index li:nth-child(4) { animation-name: seqI4; }
    @keyframes seqI1 { 0%, 22% { opacity: 1; } 22.1%, 100% { opacity: .35; } }
    @keyframes seqI2 { 0%, 22% { opacity: .35; } 22.1%, 47% { opacity: 1; } 47.1%, 100% { opacity: .35; } }
    @keyframes seqI3 { 0%, 47% { opacity: .35; } 47.1%, 72% { opacity: 1; } 72.1%, 100% { opacity: .35; } }
    @keyframes seqI4 { 0%, 72% { opacity: .35; } 72.1%, 100% { opacity: 1; } }
    .seq .ruler { margin: 0; }
    .seq .ruler__seg { width: 25%; animation: seqStep linear both; animation-timeline: --seq;
                       animation-range: contain 0% contain 100%; }
    @keyframes seqStep { 0%, 22% { transform: none; } 22.1%, 47% { transform: translateX(100%); }
                         47.1%, 72% { transform: translateX(200%); } 72.1%, 100% { transform: translateX(300%); } }
  }
}
@media (max-width: 767px) {
  .cs-grid--pair { gap: var(--space-2); }
  .seq__frame { gap: var(--space-2); }
}


/* ------------------------------------------------------------ 8. the /work index */
/* Fold on white: the one line and the count. Then the index on ink, every project on one grid:
   the two case studies take two columns each and carry their code; the rest are single cells
   that open their frames in the lightbox. Case images run 8:5 across two columns and the rest
   4:5 across one, which puts both at the same height, so any filter leaves the rows level. */
.wi-fold { padding-bottom: var(--space-6); }
.wi-fold__grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-6);
                 align-items: end; padding: var(--space-6) var(--frame-pad) 0; }
.wi-fold__title { font: 600 clamp(2.75rem, 7.2vw, 7rem)/.92 var(--font-text); letter-spacing: -.05em; max-width: 9ch; }
.wi-fold__sub { font: 400 var(--step-1)/1.35 var(--font-text); color: var(--fg-2); margin-bottom: var(--space-4); }
.docket--wi dd { font: 500 var(--step-2)/1 var(--font-mono); letter-spacing: -.02em; }

.wi { padding-bottom: var(--space-7); }
.wi__bar { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-3);
           padding: var(--space-5) var(--frame-pad) var(--space-3); }
.wi__h { color: var(--fg-2); }
.wi__count { color: var(--fg-2); white-space: nowrap; }

/* The filter: one row of plates. Pressed = green plate, ink type (15.2:1). */
.wi__filter { display: flex; flex-wrap: wrap; gap: .4rem; justify-self: center; }
.wi__filter[hidden] { display: none; }
.wi__filter button { display: inline-flex; align-items: center; gap: .6em; padding: .7em .85em;
                     text-transform: inherit; letter-spacing: inherit;
                     border: var(--rule) solid var(--line); cursor: pointer;
                     transition: background-color 160ms var(--lock), border-color 160ms var(--lock), color 160ms var(--lock); }
.wi__n { color: var(--fg-2); transition: color 160ms var(--lock); }
.wi__filter button:hover { border-color: var(--fg); }
.wi__filter button[aria-pressed="true"] { background: var(--green); border-color: var(--green); color: var(--on-green); }
.wi__filter button[aria-pressed="true"] .wi__n { color: var(--on-green); }

.wi__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5) var(--space-3);
            padding: var(--space-4) var(--frame-pad) 0; border-top: var(--rule) solid var(--line);
            margin: 0 var(--frame-pad); padding-inline: 0; list-style: none; }
.wi__item[hidden], .wi__item > .zoom[hidden] { display: none; }   /* .zoom sets display; the extra frames are for the lightbox only */
.wi__item--case { grid-column: span 2; }

.wt { display: flex; flex-direction: column; gap: var(--space-1); height: 100%; color: var(--fg); text-decoration: none; }
.wt__meta { display: flex; justify-content: space-between; gap: var(--space-2); color: var(--fg-2); }
.wt__img { position: relative; display: block; aspect-ratio: 4 / 5; overflow: hidden; background: var(--bg); margin-top: .25rem; }
.wt--case .wt__img { aspect-ratio: 8 / 5; }
.wt__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wt__img--high img { object-position: 50% 18%; }   /* the flag's lettering runs top down: keep its top */
.wt__name { font: 600 var(--step-1)/1.15 var(--font-text); letter-spacing: -.015em; margin-top: var(--space-1); }
.wt--case .wt__name { font-size: var(--step-2); letter-spacing: -.02em; }
.wt__foot { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); margin-top: auto; }
.wt__title { font: 400 var(--step-1)/1.25 var(--font-text); color: var(--fg-2); }
.wt__n { color: var(--fg-2); }
.wt__go { flex: 0 0 auto; padding: .7em .85em; border: var(--rule) solid var(--line);
          transition: background-color 160ms var(--lock), border-color 160ms var(--lock), color 160ms var(--lock); }
.wt:hover .wt__title, .wt:focus-visible .wt__title { color: var(--fg); }
.wt:hover .wt__go, .wt:focus-visible .wt__go { background: var(--green); border-color: var(--green); color: var(--on-green); }
.wt:focus-visible { outline-offset: 8px; }

@media (max-width: 1023px) {
  .wi-fold__grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .wi__bar { grid-template-columns: 1fr auto; }
  .wi__filter { grid-column: 1 / -1; grid-row: 2; justify-self: start; }
  .wi__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Phones: the filter becomes one swipeable row, the case studies stay full width and the rest
   pair up, so ten projects cost five screens, not ten. */
@media (max-width: 767px) {
  .wi-fold__grid { padding-top: var(--space-5); }
  .docket--wi { grid-template-columns: repeat(3, minmax(0, 1fr)); }   /* three short facts fit one row */
  .wi__filter { flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
                margin-inline: calc(-1 * var(--frame-pad)); padding-inline: var(--frame-pad); max-width: 100vw; }
  .wi__filter::-webkit-scrollbar { display: none; }
  .wi__filter button { flex: 0 0 auto; }
  .wi__grid { gap: var(--space-4) var(--space-2); }
  .wt--case .wt__img { aspect-ratio: 5 / 4; }
  .wt--case .wt__foot { flex-wrap: wrap; }
  .wt__name { font-size: var(--step-0); }
  .wt--case .wt__name { font-size: var(--step-2); }
  .wt__meta > span:only-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .wt__go { padding: .6em .7em; }
}

/* Filtering re-lays the grid through a view transition: the cells that stay slide to their new
   places, the ones that leave or arrive fade. Each cell gets its name from v9-case.js. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-group(*) { animation-duration: 380ms; animation-timing-function: var(--smooth); }
  ::view-transition-old(*), ::view-transition-new(*) { animation-duration: 220ms; }
}
