/* ==========================================================================
   Client stories — "case-file cubes" (/usacfo/)

   Three true CSS 3D clay cubes on the sunk band. The camera sits up and to
   the right (perspective-origin), so at rest the front face is square-on and
   undistorted while the lit top face and the shaded right face show. Turning
   a cube rotates it -90deg about Y: the right face — the story — comes round
   square-on, and the back face takes its place as the shaded side.

   Light is the site's one source, top-left: the top face is the lightest, the
   right face the darkest, the cast shadow falls +x +y on the ground. Matte
   fills only; no gloss, no glow.

   Everything is sized from --s, the cube edge, so the faces lay out
   identically at every size. --sr is the resting edge (a share of the cell,
   container query units) and is the stage's layout box; --s is --sr times
   --k, and --k is 1 at rest and the open scale (--open-k, set by the script)
   only while a cube is turned (.is-k). So the 3D body is laid out at the
   size it is SHOWN at: text and strokes raster at their final pixel size
   instead of being scaled up from a smaller box, which is what made the
   turned face soft. The script flips --k with transitions off at the two
   moments the two layouts look identical (scale 1/k == rest size), and
   snaps the opened face to the device-pixel grid (--open-dx/--open-dy).
   Motion: the turn and the open-scale/dim are CSS transitions; the idle
   float, sway, pointer lean and the breathing cast shadow are written by
   stories-cubes.js (transform/opacity only, paused off-screen).
   ========================================================================== */

.cubes {
  --turn: cubic-bezier(.5, .05, .18, 1);
  --fr: calc(var(--s) * .034);              /* face corner — soft clay edge */
  overflow-x: clip;                         /* open scale + shadows never widen the page */
}
.cubes .chapter { margin-bottom: clamp(20px, 3vw, 40px); }
/* Straight after another sunk band (the services stack on /usacfo/), carry
   the well on instead of pressing a second groove into it: no top inset,
   and the doubled padding is taken back. */
.section--sunk + .cubes {
  padding-top: clamp(24px, 4vw, 56px);
  box-shadow: inset 0 -7px 16px -7px rgba(var(--shade), .11);
}
.cubes__hint { max-width: 300px; }

/* ── the wall ─────────────────────────────────────────────────────────── */
.cubes__wall {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(0px, 1.2vw, 20px);
  row-gap: 0;
  position: relative;
}
.cubes__cell {
  position: relative;
  container-type: inline-size;
  --k: 1;
}
.cubes__cell.is-k,
.cubes__wall.is-fit .cubes__cell { --k: var(--open-k, 1); }   /* laid out at the open size */
.cubes__cell.is-open { z-index: 3; }

/* ── stage: one perspective per cube, camera up and to the right ───────── */
.cube-stage {
  --sr: min(82cqi, 400px);                  /* resting edge: the layout box */
  --s: calc(var(--sr) * var(--k));          /* the cube's edge as laid out */
  position: relative;
  width: var(--sr);
  height: var(--sr);
  margin: calc(var(--sr) * .2) auto calc(var(--sr) * .2);
  /* centre the silhouette, not the front face — a whole number of pixels:
     the stage's transforms stay 2D and integer, so the compositor can snap
     the stage to the pixel grid and the faces inside land on whole device
     pixels (a fractional transform here is applied exactly, and a face drawn
     a third of a pixel off the grid is resampled: that was the soft text) */
  translate: calc(var(--sr) * -.06) 0;
  translate: round(calc(var(--sr) * -.06), 1px) 0;
  perspective: calc(var(--s) * 4);
  perspective-origin: calc(50% + var(--s) * 1.05) calc(50% - var(--s) * .92);
  transform: scale(calc(1 / var(--k)));     /* 1 at rest; shows the open layout at rest size */
  transition: transform .95s var(--turn), opacity .7s var(--ease);
}
.cubes__cell.is-snap .cube-stage, .cubes__wall.is-snap .cube-stage { transition: none; }
.cubes__cell.is-open .cube-stage { transform: translate(var(--open-dx, 0px), 0) scale(1); }
.cubes__wall.has-open .cubes__cell:not(.is-open) .cube-stage {
  transform: scale(calc(.93 / var(--k))) translate(0, 2%);
  opacity: .6;
}

/* ── cast shadow on the ground ─────────────────────────────────────────── */
.cube-ground {
  position: absolute;
  left: calc(50% - var(--s) * .53); top: calc(50% + var(--s) * .3);
  width: calc(var(--s) * 1.3);
  height: calc(var(--s) * .36);
  pointer-events: none;
  transition: opacity 1.1s var(--ease);
}
.cube-ground > span {
  position: absolute; inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(closest-side at 46% 46%, rgba(var(--shade), .30) 0%, rgba(var(--shade), .17) 46%, rgba(var(--shade), .05) 78%, rgba(var(--shade), 0) 100%);
  transform-origin: 40% 40%;
}

/* ── the 3D body ───────────────────────────────────────────────────────── */
.cube-float, .cube {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  /* The containers' own planes cut through the cube; seen from the offset
     camera they would win hit-tests over the faces. Only faces take input. */
  pointer-events: none;
}
.cube__face { pointer-events: auto; }
.cube-float { inset: calc(50% - var(--s) / 2); transform-origin: 50% 50% calc(var(--s) * -.5); }
.cube {
  /* the Z offset is the individual property so the layout flip never
     interpolates it: only the turn is transitioned */
  translate: 0 0 calc(var(--s) * -.5);
  transform: rotateY(0deg);
  transition: transform 1s var(--turn);
}
.cubes__cell.is-open .cube { transform: rotateY(-90deg); }

.cube__face {
  position: absolute; inset: 0;
  margin: 0; padding: 0; border: 0;
  border-radius: var(--fr);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
  color: var(--ink);
  text-align: left;
  font: inherit;
  /* matte clay, a touch lighter at the top; the edges turn away from the
     light — lighter along top/left, settling darker along right/bottom */
  background: linear-gradient(178deg, #fbf8f2 0%, #f4f0e6 58%, #ece6d9 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .75),
    inset 1px 0 0 rgba(255, 255, 255, .45),
    inset -10px 0 16px -12px rgba(var(--shade), .22),
    inset 0 -12px 18px -12px rgba(var(--shade), .22);
}
/* the face's light: one overlay per face, its weight follows the face's
   current orientation (side faces fall into shade) */
.cube__face::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1s var(--turn);
}
.cube__face--front  { transform: translateZ(calc(var(--s) * .5)); }
.cube__face--story  { transform: rotateY(90deg) translateZ(calc(var(--s) * .5)); }
.cube__face--back   { transform: rotateY(180deg) translateZ(calc(var(--s) * .5)); }
.cube__face--left   { transform: rotateY(-90deg) translateZ(calc(var(--s) * .5)); }
.cube__face--top    { transform: rotateX(90deg) translateZ(calc(var(--s) * .5)); }
.cube__face--bottom { transform: rotateX(-90deg) translateZ(calc(var(--s) * .5)); }

/* shade side: darker toward the back edge (local +x is "back" on a right face) */
.cube__face--story::after,
.cube__face--back::after {
  background: linear-gradient(90deg, rgba(var(--shade), .30) 0%, rgba(var(--shade), .46) 100%);
}
.cube__face--story::after { opacity: 1; }
.cubes__cell.is-open .cube__face--story::after { opacity: 0; }
.cubes__cell.is-open .cube__face--back::after { opacity: 1; }
.cube__face--front::after { background: rgba(var(--shade), .16); }
.cubes__cell.is-open .cube__face--front::after { opacity: 1; }

/* top: the lit face. Local +y is its front edge. */
.cube__face--top {
  background: linear-gradient(0deg, #fdfbf7 0%, #f7f3eb 100%);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .9), inset 0 0 18px rgba(var(--shade), .05);
}
.cube__face--left { background: #f6f2ea; }
.cube__face--bottom { background: #d9d0bf; }

/* ── front face (the button) ───────────────────────────────────────────── */
.cube__face--front {
  display: flex; flex-direction: column;
  padding: calc(var(--s) * .045);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cube__face--front:focus-visible { outline: none; }
.cubes__cell:not(.is-open) .cube__face--front:focus-visible::before,
.cubes__cell.is-open .cube__face--front:focus-visible ~ .cube__face--story::before {
  content: "";
  position: absolute; inset: calc(var(--s) * .014);
  border-radius: calc(var(--fr) * .8);
  border: 2px solid var(--bronze-bright);
  pointer-events: none;
  z-index: 2;
}

/* the drawing sits in a pressed-in well of its palette block */
.cube__art {
  position: relative;
  display: block;
  flex: 0 0 auto;
  height: calc(var(--s) * .5);
  border-radius: calc(var(--s) * .026);
  background: var(--block);
  box-shadow:
    inset 3px 4px 8px rgba(var(--shade), .16),
    inset 1px 1px 2px rgba(var(--shade), .12),
    inset -1px -1px 1px rgba(255, 255, 255, .45);
  overflow: hidden;
}
.cube__art svg { width: 100%; height: 100%; display: block; }

/* ── the drawings: the site's line language (see stories_cubes.py) ────── */
.cube__art {
  --cx-paper: #FAF7F0;
  --cx-ink: #151513; --cx-dim: rgba(93, 88, 80, .95); --cx-faint: rgba(21, 21, 19, .16);
  --cx-scaf: rgba(21, 21, 19, .085); --cx-ghost: rgba(21, 21, 19, .32);
  --cx-node: rgba(21, 21, 19, .42); --cx-node-dot: rgba(21, 21, 19, .62);
  --cx-bronze: #a8762f; --cx-bronze-2: #b98739;
}
/* a dark block: translucent paper, cream ink, the halo in the paper's own
   composite colour so a label stays legible where a line passes under */
.cube__art--dark {
  --cx-paper: rgba(250, 247, 240, .13);
  --cx-ink: #f3e8d2; --cx-dim: rgba(243, 232, 210, .62); --cx-faint: rgba(243, 232, 210, .2);
  --cx-scaf: rgba(243, 232, 210, .1); --cx-ghost: rgba(243, 232, 210, .4);
  --cx-node: rgba(243, 232, 210, .5); --cx-node-dot: rgba(243, 232, 210, .78);
  --cx-bronze: #d8a24a; --cx-bronze-2: #c99a52;
  --cx-halo: #4b5860;
}
.cx-paper { fill: var(--cx-paper); }
.cx-scaf-l { stroke: var(--cx-scaf); stroke-width: 1; fill: none; }
.cx-line { stroke: var(--cx-ink); stroke-width: 1.2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.cx-one { stroke: var(--cx-bronze); stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.cx-ghost { stroke: var(--cx-ghost); stroke-width: 1; fill: none; stroke-linecap: round; stroke-dasharray: 2 4.5; }
.cx-cross { stroke: var(--cx-ghost); stroke-width: 1.3; fill: none; stroke-linecap: round; }
.cx-tick { stroke: var(--cx-ink); stroke-width: 1.5; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.cx-ring-o { fill: none; stroke: var(--cx-faint); stroke-width: 1; }
.cx-ring { fill: none; stroke: var(--cx-bronze-2); stroke-width: 1.3; }
.cx-dot { fill: var(--cx-bronze); }
.cx-ring-dim { fill: none; stroke: var(--cx-node); stroke-width: 1.1; }
.cx-dot-ink { fill: var(--cx-ink); }
.cx-ring-gh { fill: none; stroke: var(--cx-ghost); stroke-width: 1; }
.cx-dot-gh { fill: var(--cx-ghost); }
.cx-bead { fill: var(--cx-halo, var(--cx-paper)); stroke: var(--cx-bronze-2); stroke-width: 1.3; }
.cx-blk { stroke: var(--cx-ink); stroke-width: 1; stroke-linejoin: round; }
.cx-blk--dark { stroke: none; }
.cx-pulse { fill: var(--cx-bronze); }
.cx-t { font: 300 13px Newsreader, Georgia, serif; letter-spacing: -.01em; fill: var(--cx-ink); }
.cx-t--val { font-size: 30px; letter-spacing: -.03em; }
.cx-c { font: 500 8px Inter, sans-serif; letter-spacing: 1.9px; fill: var(--cx-dim); }
.cx-c--dim { fill: var(--cx-ghost); }
.cx-c--sm { font-size: 7.4px; letter-spacing: 1.5px; }
.cx-halo { paint-order: stroke fill; stroke: var(--cx-halo, var(--cx-paper)); stroke-width: 5px; stroke-linejoin: round; }
.cx-c.cx-halo { stroke-width: 6px; }

/* draw-in: held back once the script runs, released — each mark at its own
   --d after the cube has risen (same clock as the float: 1.05s + stagger) */
.cubes.is-js .cx-draw { stroke-dasharray: 1 2; stroke-dashoffset: 1.001; }
.cubes.is-js .cx-pop { opacity: 0; transform: scale(.55); transform-box: fill-box; transform-origin: center; }
.cubes.is-js .cx-fade { opacity: 0; }
.cubes.is-in .cx-draw {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--dur, .8s) var(--ease) calc(var(--i) * .17s + 1.05s + var(--d, 0s));
}
.cubes.is-in .cx-pop {
  opacity: 1; transform: none;
  transition: opacity .45s var(--ease) calc(var(--i) * .17s + 1.05s + var(--d, 0s)),
              transform .7s var(--ease) calc(var(--i) * .17s + 1.05s + var(--d, 0s));
}
.cubes.is-in .cx-fade { opacity: 1; transition: opacity .6s var(--ease) calc(var(--i) * .17s + 1.05s + var(--d, 0s)); }

.cube__meta {
  flex: 1 1 auto;
  display: flex; flex-direction: column;
  padding: calc(var(--s) * .05) calc(var(--s) * .018) 0;
  min-height: 0;
}
.cube__no {
  display: block;
  font: 500 max(9px, calc(var(--s) * .026))/1 Inter, sans-serif;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--bronze-deep);
}
.cube__title {
  display: block;
  margin-top: calc(var(--s) * .026);
  font-family: Newsreader, Georgia, serif;
  font-weight: 300;
  font-size: calc(var(--s) * .065);
  line-height: 1.12;
  letter-spacing: -.016em;
  color: var(--ink);
  text-wrap: balance;
}
.cube__foot {
  margin-top: auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: calc(var(--s) * .03);
  padding-bottom: calc(var(--s) * .004);
}
.cube__cue, .cube__back {
  display: inline-flex; align-items: center; gap: .6em;
  margin-left: auto;
  font: 500 max(9px, calc(var(--s) * .025))/1 Inter, sans-serif;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
  transition: color .3s var(--ease);
}
.cube__turn-ico { width: 1.45em; height: 1.45em; flex: 0 0 auto; }
.cube__face--front:hover .cube__cue,
.cube__face--front:focus-visible .cube__cue { color: var(--bronze-deep); }

/* metric chip: pressed into the clay, Newsreader numeral + Inter caps */
.cube__chip {
  display: inline-flex; align-items: baseline; gap: .55em;
  padding: calc(var(--s) * .014) calc(var(--s) * .034) calc(var(--s) * .016);
  border-radius: 999px;
  background: linear-gradient(178deg, #e9e3d5 0%, #f0ebdf 100%);
  box-shadow: var(--clay-in);
  white-space: nowrap;
}
.cube__chip-val {
  font: 300 calc(var(--s) * .052)/1 Newsreader, Georgia, serif;
  letter-spacing: -.02em;
  color: var(--bronze-deep);
  font-variant-numeric: lining-nums;
}
.cube__chip-lab {
  font: 500 max(9px, calc(var(--s) * .024))/1 Inter, sans-serif;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ── story face ────────────────────────────────────────────────────────── */
.cube__face--story {
  padding: calc(var(--s) * .07) calc(var(--s) * .075) calc(var(--s) * .06);
  cursor: pointer;
}
.cube__story {
  opacity: 0;
  transition: opacity .45s var(--ease);
}
.cubes__cell.is-open .cube__story { opacity: 1; transition: opacity .6s var(--ease) .32s; }
.cube__story-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0;
}
.cube__story-title {
  margin-top: calc(var(--s) * .03);
  font-family: Newsreader, Georgia, serif;
  font-weight: 400;
  font-size: calc(var(--s) * .05);
  line-height: 1.16;
  letter-spacing: -.014em;
  color: var(--ink);
}
.cube__story-text {
  margin-top: calc(var(--s) * .028);
  font-family: Newsreader, Georgia, serif;
  font-weight: 300;
  font-size: calc(var(--s) * .046 * var(--cm, 1));
  line-height: 1.5;
  letter-spacing: -.003em;
  color: #2c2924;
  text-wrap: pretty;
  hyphens: manual;
}
/* when even the fitted size cannot hold the story, the face scrolls — the
   text is never clipped. A soft fade marks that there is more. */
.cube__face--story[data-scroll] {
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--shade), .35) transparent;
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - var(--s) * .1), transparent);
          mask-image: linear-gradient(180deg, #000 calc(100% - var(--s) * .1), transparent);
}
.cube__face--story[data-scroll][data-end] { -webkit-mask-image: none; mask-image: none; }

/* ── entry: the cubes rise from below and settle, one after another ───── */
.cubes.is-js .cubes__cell {
  opacity: 0;
  transform: translate3d(0, 110px, 0);
}
.cubes.is-js .cube-ground { opacity: 0; }
.cubes.is-in .cubes__cell {
  opacity: 1;
  transform: none;
  transition:
    transform 1.25s cubic-bezier(.2, 1.18, .34, 1) calc(var(--i) * .17s),
    opacity .8s var(--ease) calc(var(--i) * .17s);
}
.cubes.is-in .cube-ground {
  opacity: 1;
  transition: opacity 1.2s var(--ease) calc(var(--i) * .17s + .45s);
}

/* ── responsive ────────────────────────────────────────────────────────── */
/* 780–1099: two and one, the third centred under the pair */
@media (max-width: 1099px) {
  .cubes__wall { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 12px; }
  .cubes__cell:nth-child(3):last-child { grid-column: 1 / -1; justify-self: center; width: calc(50% - 6px); }
  .cube-stage { margin-bottom: calc(var(--sr) * .12); }
}
/* 600–779: two columns would shrink the story type, so the cubes stagger
   down one column instead — left, right, left — each at a reading size */
@media (max-width: 779px) {
  .cubes__wall { grid-template-columns: minmax(0, 1fr); }
  .cubes__cell:nth-child(3):last-child { grid-column: auto; width: 100%; }
  .cube-stage {
    --sr: min(62cqi, 400px);
    margin: calc(var(--sr) * .14) auto calc(var(--sr) * .08) calc(var(--sr) * .06);
  }
  .cubes__cell:nth-child(even) .cube-stage { margin-left: auto; margin-right: calc(var(--sr) * .14); }
}
/* <600: one stack, near full width */
@media (max-width: 599px) {
  .cube-stage {
    --sr: min(92cqi, 420px);
    margin: calc(var(--sr) * .17) auto calc(var(--sr) * .2);
    translate: calc(var(--sr) * -.045) 0;
    translate: round(calc(var(--sr) * -.045), 1px) 0;
    perspective-origin: calc(50% + var(--s) * .85) calc(50% - var(--s) * .9);
  }
  .cubes__cell:nth-child(even) .cube-stage { margin-left: auto; margin-right: auto; }
  .cube__story-text { font-size: calc(var(--s) * .05 * var(--cm, 1)); }
  .cube__story-title { font-size: calc(var(--s) * .056); }
  .cube__no, .cube__cue, .cube__back, .cube__chip-lab { font-size: max(9.5px, calc(var(--s) * .028)); }
  .cubes .chapter__row > p { max-width: 40ch; }
}
/* small cubes (narrow phones): a shorter drawing well leaves the title room,
   and the drawing's type and lines step up as it scales down */
@container (max-width: 300px) {
  .cube__art { height: calc(var(--s) * .44); }
}
@container (max-width: 360px) {
  .cx-t { font-size: 14.5px; }
  .cx-t--val { font-size: 33px; }
  .cx-c { font-size: 9.4px; letter-spacing: 2px; }
  .cx-c--sm { font-size: 8.6px; letter-spacing: 1.5px; }
  .cx-line { stroke-width: 1.45; }
  .cx-one { stroke-width: 2.4; }
  .cx-tick { stroke-width: 1.8; }
}

/* container units unsupported: size from the viewport instead */
@supports not (container-type: inline-size) {
  .cube-stage { --sr: min(24vw, 400px); }
  @media (max-width: 1099px) { .cube-stage { --sr: min(36vw, 400px); } }
  @media (max-width: 599px)  { .cube-stage { --sr: 76vw; } }
}

/* ── reduced motion: static cubes, the turn is an instant swap ─────────── */
@media (prefers-reduced-motion: reduce) {
  .cubes.is-js .cubes__cell, .cubes.is-in .cubes__cell { opacity: 1; transform: none; transition: none; }
  .cubes.is-js .cube-ground { opacity: 1; }
  .cube, .cube-stage, .cube__face::after, .cube__story,
  .cubes__cell.is-open .cube__story { transition: none !important; }
}

@media print {
  .cubes__wall { display: block; }
  .cube-stage, .cube-float, .cube { position: static; inset: auto; transform: none !important; width: auto; height: auto; perspective: none; translate: none; }
  .cube__face { position: static; transform: none !important; box-shadow: none; }
  .cube__face--back, .cube__face--left, .cube__face--top, .cube__face--bottom, .cube-ground { display: none; }
  .cube__story { opacity: 1 !important; }
}
