/* ================================================================
   COMPONENT: PROJECT CARD
   dousanmiao-style: image zoom + overlay arrow on hover.
   ================================================================ */

/* Corner radius for all selected-work cards comes from the global
   --radius-card token (24px desktop, stepped down on tablet/mobile in
   layout.css). The card box, the image (media), and the concentric hover
   frame all derive from it. See DESIGN.md → Surface Radius. */

.project-card {
  display: block;
  text-decoration: none;
  position: relative;
  /* NO transform/box-shadow transition here. `paper-physics.js` writes both
     per frame through its own spring, and `scroll-reveal.js` tweens transform
     on the way in — a CSS transition on either property would be a second
     source of smoothing (DESIGN.md → Motion). It used to be declared here and
     cancelled by an inline `transition: none` that paper-physics wrote on the
     first `mouseenter`, which meant the very first hover of the page eased and
     every hover after it did not. Declaring nothing is the same result, on
     every hover, without the hidden state. */
  will-change: transform;   /* box-shadow is never composited — nothing to hint */
  border-radius: var(--radius-card);
  corner-shape: squircle;   /* Apple continuous corner (ignored where unsupported) */
}

/* Hover frame — expands outward behind the card content. Its radius stays
   concentric with the card (card radius + the outward inset) so the
   expanded frame hugs the card's corners perfectly. */
.project-card::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--radius-card);
  corner-shape: squircle;
  background: var(--surface-alt);
  opacity: 0;
  z-index: -1;
  transition:
    inset var(--dur-normal) var(--ease-out),
    border-radius var(--dur-normal) var(--ease-out),
    opacity var(--dur-normal) var(--ease-out);
}

.project-card:hover::before {
  inset: calc(-1 * var(--sp-4));
  /* concentric: card radius + inset (16) → 24 + 16 = 40 */
  border-radius: calc(var(--radius-card) + var(--sp-4));
  opacity: 1;
}

/* -- Media wrapper ---------------------------------------------- */
.project-card__media {
  position: relative;
  width: 100%;
  border-radius: var(--radius-card);
  corner-shape: squircle;
  overflow: hidden;
  /* On-stock loading plate. This was --gray-100 (#e8e8e8) — a COOL grey
     behind the five biggest rectangles on a warm-paper page, and the first
     frame a visitor sees before the WebP decodes. The paper ramp already
     existed; the plate just never used it. Keep in sync with the case
     cover plate (case.css) and the transition flyer (flyer.css) — the
     flyer crosses the navigation, so a mismatch pops mid-flight. */
  background-color: var(--paper-tint-3);
  transition: box-shadow var(--dur-normal) var(--ease-out);
}

/* THE CARD CARRIES NO TREATMENT OF ITS OWN.
   It used to stack six: a teal `mix-blend-mode: color` grade, a
   pointer-tracking spotlight ring, a dark hover veil, a white circular
   arrow button, the cool plate above, plus paper-physics tilt and image
   parallax. Two of those are paper behaviours and stay (the tilt, and the
   box-shadow on this element). The rest went, for two reasons:

   1. The grade sat at full strength AT REST and dropped to 0.6 on hover,
      so the true colour of the work was suppressed by default and only
      partly restored when you pointed at it. A portfolio's first job is to
      show the work in its own colour. Do not reintroduce a resting tint.
   2. A tile needs chrome to prove it is clickable; a panel of the sheet
      does not — the whole card is the link. The arrow now lives in the
      info row as type, in ink, using the → the page already owns.

   The cursor spotlight is now the NAVBAR PILL ONLY. A pill is UI chrome
   and can carry a UI effect; a sheet of paper cannot. */

/* The card-top crease is defined once, with the other two media plates, in
   `css/layout.css` → "The media crease". */

/* ONE HEIGHT PER ROW, not per card. `--lead` (727) and `--minor` (508) are
   different widths, so they crop to different ratios — but they must share a
   height or the row stops reading as a row and becomes two loose objects.
   The ratio difference is the point; the baseline is what holds it together.

   THE ROW HEIGHT IS SET BY THE TALLEST SUBJECT IN IT, AND THE HEIGHT IS A
   RATIO. At 380 the `--lead` plate was 726×380 = 1.911, and `object-fit:
   cover` against a 1.6 source showed 1675 of the 2000 source px. Pindo's phone
   is 1608 of those, standing 22px below the image's centre — so the device
   cleared the frame by **2.6 CSS px** at the bottom and was visibly standing on
   the card's own edge with no ground under it. 420 is 726 ÷ 1.72, which opens
   the band to 1857 and puts 33px of air above the phone and 23px of table
   below (5.4% of the plate). The other four images are landscape and simply
   show a little more.

   ~1.72 CAME FROM THE ≤768 PLATE, the one step that was always right: 343×200
   never clipped anything. Every other card and cover step held a fixed height
   against a grid-driven width, so the shape drifted as far as 2.93. Divide the
   width by 1.72 rather than picking a height. Keep this in step with
   `.case-cover__media` (550 = 948 ÷ 1.72): the two are the same plate at two
   sizes, and the flight between them is near-uniform only while their ratios
   match — 1.729 vs 1.724 today. */
.project-card--full  .project-card__media { height: 460px; }
.project-card--lead  .project-card__media,
.project-card--minor .project-card__media { height: 420px; }

/* -- The catch-light ------------------------------------------- */
/* THE FOLD IS THE THING THAT MOVES. `--mouse-x` (parallax.js) slides a warm
   highlight along the card's top crease — light travelling across a fold.

   This REPLACED two borrowed gestures. The image used to zoom 1.02 → 1.07
   over 600ms and translate ±7px with the cursor: photo-gallery moves layered
   on an object the rest of the page renders as paper. Paper does not zoom and
   does not slide inside its own frame; it lifts, tilts, and catches light.
   The lift and tilt were already here (`paper-physics.js`), so the hover
   vocabulary is now paper end to end, and it is one device shorter than
   before rather than one longer.

   It also puts the house-mark to work: the crease was the site's signature
   and the only static thing on the card. Now it is the only moving one.

   NOTE — `--mouse-x` is back on the card, having been removed with the border
   spotlight. That is deliberate, and the distinction is what the coordinate
   drives: a ring around a UI tile (wrong material) versus light on a fold
   (the mark itself). Do not use it for anything else here. */
.project-card--full .project-card__media {
  --mouse-x: 50%;
}

/* Scoped to `--full` because the crease is. Light needs a fold to run along;
   on a half card there is nothing under it to catch. The half cards keep the
   tilt and the shadow — still paper, just quieter, which is what a supporting
   card should be. */
.project-card--full .project-card__media::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--rule-box-fine);
  z-index: 3;
  pointer-events: none;
  background: radial-gradient(
    130px 9px at var(--mouse-x) 42%,
    rgba(255, 253, 248, 0.95) 0%,
    rgba(255, 253, 248, 0.35) 45%,
    rgba(255, 253, 248, 0) 100%
  );
  /* Same silhouette as the crease under it, so the light is bounded by the
     drawn edge and fades out where the fold tapers to a hairline. */
  -webkit-mask: var(--rule-silhouette) no-repeat 50% 50% / 100% 100%;
          mask: var(--rule-silhouette) no-repeat 50% 50% / 100% 100%;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.project-card--full:hover .project-card__media::after { opacity: 1; }

/* -- Image ------------------------------------------------------ */
/* The wrapper survives as a plain box: it is the element the flyer measures
   against, and removing it would change the page-transition geometry.
   It carries NO transform and NO `will-change` — a promoted child of a
   rounded-clip parent loses the parent's rounded clip on mobile while the
   layer is live, which is the documented cause of the flyer's corner
   degrading. Nothing here transforms any more, so nothing needs promoting. */
.project-card__img-wrap {
  display: block;
  width: 100%;
  height: 100%;
}

.project-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

/* -- Info ------------------------------------------------------- */
.project-card__info { padding-top: var(--sp-4); }

/* NO DESTINATION MARK ON THE CARD.
   There were two attempts and both are gone. First a white circular arrow
   floating over the image on hover — chrome restating what the card already
   was, and invisible on touch. Then a `→` in the title row (`.project-card__go`
   in a `.project-card__head` flex row) — present at rest, which fixed touch
   but put a fifth object in a five-card grid and read as clutter.

   The card needs no mark: it is a link end to end, and the page already says
   so three ways — the cursor state (`data-cursor="viewing"`), the hover frame
   that expands behind it, and the paper tilt. Keyboard gets the focus ring.
   **Do not add a third arrow.** If a destination cue is ever genuinely needed,
   it belongs in the description's last line as words, not as a glyph.

   `.is-unlinked` (Clover Agent, no case page yet) therefore needs no rule of
   its own any more — nothing about the card promises navigation. Keep the
   class in the markup as the marker for *why* that one is not an `<a>`; when
   `work/clover-agent.html` exists, make it an `<a href>`, restore
   `data-cursor="viewing"`, and drop the class. */

.project-card__title {
  font-family: var(--type-h4-font);
  font-size: var(--type-h4-size);
  line-height: var(--type-h4-line);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin-bottom: var(--sp-1);
}

.project-card__desc {
  font-family: var(--type-body1-font);
  font-size: var(--type-body1-size);
  line-height: var(--type-body1-line);
  color: var(--text-secondary);
}

/* -- Responsive ------------------------------------------------- */
@media (max-width: 1024px) {
  /* THE TALLEST PLATE ON THE SITE IS ALSO THE ONE WITH THE MOST ROOM TO FILL.
     Every span resets to one column here, so all five cards are the FULL 879
     — but the heights had stayed at their desktop-ish 360/300, which made
     these plates 2.44:1 and **2.93:1**, the hardest letterbox anywhere on the
     site. Pindo's phone lost 65px off its top and 77px off its bottom, in CSS
     px: worse at a tablet than it had been at a desktop, because the plate got
     wider while the height stood still.

     A wider plate needs a taller plate to keep the same shape. 510 is 879 ÷
     1.72, the shape every other step now takes; `--full` sits at 560 so it
     still outranks its row-mates by roughly the same step it does on a desktop
     (460 vs 420), which is the only rank signal left once the spans collapse
     and all five cards share one width. Mobile needed nothing — 343×200 is
     1.715, and it is where the 1.72 came from: the one plate on the site whose
     shape was never stretched, because its width and height were set together. */
  .project-card--full  .project-card__media { height: 560px; }
  .project-card--lead  .project-card__media,
  .project-card--minor .project-card__media { height: 510px; }

  /* Hover frame expands to the MIDDLE of the side spacing — half the side
     padding (--gutter-inner = 40px → 20px) so it sits centred in the gap.
     Radius stays concentric: card radius (20) + inset (20) = 40. */
  .project-card:hover::before {
    inset: calc(var(--gutter-inner) / -2);
    border-radius: calc(var(--radius-card) + var(--gutter-inner) / 2);
  }
}
@media (max-width: 768px) {
  .project-card--full  .project-card__media,
  .project-card--lead  .project-card__media,
  .project-card--minor .project-card__media {
    height: 200px;   /* radius comes from --radius-card (16px on mobile) */
  }

  /* Half the side spacing (--gutter = 16px → 8px), centred in the gutter.
     Concentric radius: card radius (16) + inset (8) = 24. */
  .project-card:hover::before {
    inset: calc(var(--gutter) / -2);
    border-radius: calc(var(--radius-card) + var(--gutter) / 2);
  }

  .project-card__info {
    padding-top: 10px;
  }

  .project-card__title {
    font-size: 17px;
    line-height: 22px;
    margin-bottom: 2px;
  }

}
