/* ==========================================================================
   The project card — ONE component, two pages
   ==========================================================================
   Client, 2026-09-17, of the services page's security tiles: "treat the cards
   in that section the same as you did the you may also like cards on the
   project pages. They should be the same component."

   They already WERE the same card drawn twice. Measured at 1600 before this
   was written, the two agreed on almost everything — artwork 650 x 396 against
   653 x 397, both at radius 16 in a radius-24 card with 16 of padding, both
   names 40 — and disagreed on four things nobody had decided: the description
   (16 against 18), the card's bottom padding (16 against 48), the body's
   padding (30/0 against 24/8) and the resting hover scale (1.09 against 1.06).
   Four small divergences is what two copies of a component always become.

   THE PROJECT CARD'S VALUES WIN, because that is the one the client has been
   reviewing and the one node 705:82711 describes.

   THE SELECTOR LISTS RIDE ALONGSIDE `.rdk-card`, WHICH IS css/pill.css's
   ARRANGEMENT AND FOR THE SAME REASON: it makes the two literally one rule
   set without churning a generated template and a hand-written page. New
   markup should take the `.rdk-card` classes and needs nothing else. A THIRD
   USER TAKES THE CLASS RATHER THAN EXTENDING THE LIST.

   Linked BEFORE the page stylesheets, so a page can still override what is
   genuinely its own — the services list's own top margin, its `cursor: none`,
   the project list's phone column.
   ========================================================================== */

.rdk-cards,
.rdk-project__more-list,
.rdk-svc-sec__work {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(40 * var(--u));
  margin: 0;
  padding: 0;
  list-style: none;
}

/* THE PAIR IS ONE HEIGHT AND THE SLACK FALLS UNDER THE COPY (client,
   2026-09-17: "the tiles are appearing different heights on device... can we
   just match the heights for the two cards?").

   THE `<li>` ALREADY STRETCHED — grid items do. What did not is the CARD,
   which is the `<a>` INSIDE it at `height: auto`, so it grew only to its own
   content while the li around it was already the row's full height. The brand
   colour is painted on the `<a>`, so a 2-line blurb beside a 3-line one ended
   short by exactly one line.

   `display: grid` ON THE LI, NOT `flex`. A grid item stretches on BOTH axes;
   a flex item stretches only on the cross one, which fixes the height and
   silently makes the card content-WIDTH.

   The card is a flex COLUMN whose children keep their own sizes, so the extra
   height lands after the last one — room between the copy and the foot rather
   than a stretched anything. Node 705:82711 pins every card at 600 for the
   same reason; stretching to the tallest cannot overflow on a longer blurb.

   ONE COLUMN ON A PHONE MAKES THIS A NO-OP, since every card is its own row. */
.rdk-cards > li,
.rdk-project__more-list > li,
.rdk-svc-sec__work > li {
  display: grid;
}

/* `--card-bg` is the client's brand colour, set per card in the markup — the
   same value the index tile and the hero use. `--tile-bg` is the services
   page's own spelling of it, kept so that page's markup did not have to
   change; either name works. */
.rdk-card,
.rdk-project__more-card,
.rdk-svc-work {
  display: flex;
  flex-direction: column;
  padding: calc(16 * var(--u)) calc(16 * var(--u)) calc(48 * var(--u));
  color: var(--rdk-white);
  text-decoration: none;
  background: var(--card-bg, var(--tile-bg, var(--rdk-black-green)));
  border-radius: calc(24 * var(--u));
  overflow: clip;
}

/* 658.02 / 400 off node 705:82711. The master is 1.784, so `cover` trims ~8%
   off the sides — the one-image-per-project rule the hero and tile follow. */
.rdk-card__shot,
.rdk-project__more-shot,
.rdk-svc-work__art {
  position: relative;
  flex: none;
  aspect-ratio: 658.02 / 400;
  margin: 0;
  border-radius: calc(16 * var(--u));
  overflow: clip;
}

/* ITS OWN CLASS, NOT a descendant `img`. That selector is (0,1,1) and beats
   the logo's (0,1,0), so the mark takes the photograph's `width: 100%` — the
   trap `.rdk-footer__mark img` is on record for, and which this card walked
   into once already. A block with two images gives each one a class. */
.rdk-card__img,
.rdk-project__more-img,
.rdk-svc-work__shot {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

/* `--card-logo-w` IS THE CARD'S OWN DESIGNED WIDTH, measured against this
   figure's 662 — NOT `--logo-w`, which is measured against the work index
   tile's 982.418 artwork. No single number or factor serves both boxes; node
   705:82711's eight run 160 to 400, a 2.5x spread.

   THE 70% CLAMP IS A GUARD AGAINST A MISSING VALUE AND MUST NEVER BIND ON A
   DESIGNED ONE. The node's widest is 400 in 662 = 60.4%. It was 46% once,
   invisible while an old 0.6718 factor held every mark under 34%, and it
   began truncating silently the moment that went. Keep it slack enough that
   it can only ever fire on a mistake.

   `--logo-w` is the fallback for a card with no designed figure.

   A SHARE OF THE FIGURE, NOT A LENGTH IN DESIGN UNITS (client, 2026-09-18:
   "on mobile the logos on the additional project tiles are too small, should
   stay the same proportionally as desktop"). It was `--card-logo-w * --u`, and
   `--u` is 100vw/1600 — so on a 390 phone the mark shrank to a quarter of its
   design value while the FIGURE it sits in did not, because that is a grid
   column and stays most of the screen. Measured: Datascan's 280 drew 21% of
   its figure against the designed 42%, i.e. half. The collapsing-unit trap
   this file records against the client grid and the label rows, on a mark this
   time.

   THE DIVISOR IS 660, the figure's RENDERED width at `--u: 1`, not the node's
   662 — so the percentage reproduces the desktop exactly rather than to within
   0.3%. Verified: 400 -> 60.6% and 260 -> 39.4%, the same two numbers the
   `--u` version drew.

   It is also strictly better on the desktop, where it was already correct by
   coincidence: the percentage tracks whatever the grid column actually gives
   the figure, where the old form assumed it was always 660 design units. */
.rdk-card__logo,
.rdk-project__more-logo,
.rdk-svc-work__logo {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: calc(var(--card-logo-w, var(--logo-w, 280)) * 0.1515%);
  max-width: 70%;
  height: auto;
}

/* THE COPY IS INSET FURTHER THAN THE ARTWORK (client, 2026-09-18: "inset the
   copy on those tiles like we did elsewhere").

   "Elsewhere" is the blog card, which gives its body `padding-inline: 16u`
   (12px on a phone) so the words clear the card edge by more than the picture
   does. The relationship is what carries over, not the number: there the card
   has no padding of its own and the artwork is flush, so 16 of body padding
   IS 16 of inset; here the card already pays 16, so 16 more puts the copy at
   32 against the artwork's 16 — the same 16 further in.

   It was 8, which at this size reads as flush rather than as a decision.

   PLUS 8px ON ALL SIDES SINCE 2026-09-18 (client), which is the same addition
   tablet portrait was given on 2026-09-17 and desktop never got. It is added
   in px, not in design units, for the reason that block already records: it is
   a fixed breathing space around the copy, not a proportion of the frame.

   IT DOES NOT CLOSE THE RIGHT-HAND RAG, AND IT WAS NOT KEPT ON THAT BASIS.
   It was reached for as a fix for one — `pretty` (inherited from body) pulls a
   word off the first line to save a stub last line, which on a short two-line
   blurb leaves the first line ~100 short. `auto` and `balance` were measured
   against that and neither helped either.

   Nor does a narrower box: measured over all eight blurbs, 619 -> 603 improved
   six of them by exactly 16 (the box shrinking, same break) and tipped a word
   onto line 2 for the two that sat on a word boundary — MetroPCS 5 -> 56 slack,
   Radiant 9 -> 52. MEAN SLACK WENT 44.6 -> 44.4, i.e. it redistributes the
   problem rather than solving it. That is the knife-edge the services pills
   already record ("solve against 524u, not 530"): any measure is lucky for
   some strings and unlucky for others, so DO NOT retune this number chasing a
   rag. The lever is copy length — the two worst, Secureworks (81 chars, 125)
   and nuHarbor (78, 84), are the two shortest.

   The 8px is kept for the INSET itself: copy 40 in against the artwork's 16,
   the relationship tablet portrait already had. */
.rdk-card__body,
.rdk-project__more-body,
.rdk-svc-work__body {
  padding: calc(24 * var(--u) + 8px)
           calc(16 * var(--u) + 8px)
           calc(8 * var(--u) + 8px);
}

/* Heading/L. The node's -1.2 on 40 is -3%; the ladder's rung is -2.27%. */
.rdk-card__name,
.rdk-project__more-name,
.rdk-svc-work__name {
  margin: 0 0 calc(12.198 * var(--u));
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(40 * var(--du));
  line-height: 1;
  letter-spacing: -0.0227em;
}

/* The node says 1.4; the body scale says 1.5 for every step but the lede, and
   that scale exists precisely to stop a per-frame number like this one.

   THERE IS NO `max-width` ANY MORE, AND DESKTOP WAS THE LAST BREAKPOINT
   HOLDING ONE (client, 2026-09-18: "the copy needs to go to the edges. The
   extra space on the right looks bad"). It was `467 * --u`, which is 467 in a
   628 content box — so the copy broke ~161 short of the inset it was given and
   read as a ragged right edge rather than as a measure.

   The phone and tablet-portrait blocks below had ALREADY been given
   `max-width: none` for this exact complaint, the tablet one in as many words
   ("It's breaking too early causing a weird gap"). Both were written as
   overrides of this cap; with the cap gone they would be overriding nothing,
   so they are deleted and their reasoning is recorded here.

   The measure is now the body's own padding box — 596 at a 1600 window, i.e.
   33em, which the 32u inset is what actually sets. Inset the COPY if it ever
   wants to be narrower; do not put a second number back here, or the two
   disagree and only one of them is visible in the layout. */
.rdk-card__desc,
.rdk-project__more-desc,
.rdk-svc-work__desc {
  margin: 0;
  font-size: var(--rdk-body-m);
  line-height: 1.5;
  opacity: 0.9;
}

/* THE ARTWORK OPENS UP UNDER THE POINTER, exactly as the work index tile
   does. The image is an element GSAP never touches — the entrances animate
   the card and the list — so CSS keeps `scale` here; put it on an element
   GSAP transforms and the inline `scale: none` it writes wins outright. */
.rdk-card .rdk-card__img,
.rdk-project__more-card .rdk-project__more-img,
.rdk-svc-work .rdk-svc-work__shot {
  scale: 1.06;
  transition: scale 2.4s cubic-bezier(0.22, 1, 0.36, 1);
}

@media (hover: hover) and (pointer: fine) {
  .rdk-card:hover .rdk-card__img,
  .rdk-card:focus-visible .rdk-card__img,
  .rdk-project__more-card:hover .rdk-project__more-img,
  .rdk-project__more-card:focus-visible .rdk-project__more-img,
  .rdk-svc-work:hover .rdk-svc-work__shot,
  .rdk-svc-work:focus-visible .rdk-svc-work__shot {
    scale: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rdk-card__img,
  .rdk-project__more-img,
  .rdk-svc-work__shot {
    transition: none;
  }
}

@media (max-width: 767px) {
  .rdk-cards,
  .rdk-project__more-list,
  .rdk-svc-sec__work {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
  }

  .rdk-card,
  .rdk-project__more-card,
  .rdk-svc-work {
    padding: 12px 12px 32px;
    border-radius: 20px;
  }

  .rdk-card__shot,
  .rdk-project__more-shot,
  .rdk-svc-work__art { border-radius: 12px; }

  /* The blog card's own phone value, and the same relationship: the card pays
     12 and the copy 12 more, so it sits 24 in against the artwork's 12. */
  .rdk-card__body,
  .rdk-project__more-body,
  .rdk-svc-work__body { padding: 20px 12px 0; }

  .rdk-card__name,
  .rdk-project__more-name,
  .rdk-svc-work__name { font-size: 32px; letter-spacing: -0.73px; }
}

/* --------------------------------------------------------------------------
   TABLET PORTRAIT
   --------------------------------------------------------------------------
   THESE TWO WERE STRANDED IN css/project.css AND THE SERVICES CARD NEVER GOT
   THEM (client, 2026-09-17: "the project tiles dont match the project page
   tiles like I asked. The text is too narrow and the padding doesnt match").
   Correct, and the extraction is what exposed it: they were written for the
   project page before the component existed, scoped to its own selectors, so
   sharing the desktop rules moved most of the card across and left its tablet
   treatment behind. Measured at 820 — body padding 12.3/4.1/4.1 against the
   project's 20.3/12.1/12.1, and the description capped at 239 in a 346 card
   against the project's full 307.

   WHEN A COMPONENT IS EXTRACTED, ITS BREAKPOINT RULES COME WITH IT. The
   desktop block is the obvious half and the easy one to stop at.

   The measure: `467 * --u` is 239 inside a 347 card, so the copy wrapped
   ~108px short of the edge (client, earlier: "the copy needs to go edge to
   edge. It's breaking too early causing a weird gap").

   The padding: 8px ON TOP of the component's own, not replacing it, so the
   card keeps its proportions underneath — 12.3 / 4.1 / 4.1 at 820 becomes
   20.3 / 12.1 / 12.1 (client: "can we inset the text a little bit so its not
   so close to the edge and image. Maybe 8 additional pixels on all sides?").
   -------------------------------------------------------------------------- */
@media (min-width: 768px) and (orientation: portrait) {
  .rdk-card__body,
  .rdk-project__more-body,
  .rdk-svc-work__body {
    padding: calc(24 * var(--u) + 8px)
             calc(8 * var(--u) + 8px)
             calc(8 * var(--u) + 8px);
  }
}
