/* Varna Rent-a-Car case study
   Hero section — Figma node 25:10758 (Bento Grid).

   The hero is a 1600 x 1200 composition: a 4-column bento on a 30px gutter.
   Everything inside it scales with the viewport instead of needing a breakpoint
   per element. `--u` is one design pixel — a length, since CSS can't divide two
   lengths into a ratio — so a Figma value of 64px is written
   `calc(64 * var(--u))`. Below 760px the bento folds into two columns of the
   same 363px card width, so every card keeps its desktop geometry and only
   `--u` changes. */

:root {
  /* Figma variables */
  --vrac-deep-navy: #060449;
  --vrac-dark-navy: #131073;
  --vrac-dark-blue: #331ad9;
  --vrac-blue: #371bf2;
  --vrac-light-grey: #edebfb;
  --vrac-card-grey: #ededed;
  --vrac-media-grey: #edeafb;
  --vrac-texture: #f4f2fc;
  --vrac-white: #ffffff;

  --font-ui: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  /* Entrances and hovers share one curve: a long exponential ease-out, so
     things arrive quickly and settle slowly. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --hover-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --enter-duration: 1.1s;
  --hover-duration: 0.8s;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--vrac-deep-navy);
  color: var(--vrac-white);
  font-family: var(--font-ui);
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; }

ul { list-style: none; margin: 0; padding: 0; }
p { margin: 0; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Same page frame as the FitForge case study: a capped reading column, with
   `grid-column: full` available to sections that run edge to edge. */
main {
  display: grid;
  grid-template-columns:
    [full-start] minmax(0, 1fr)
    [content-start] minmax(0, 1800px) [content-end]
    minmax(0, 1fr) [full-end];
}

main > * { grid-column: content; }


/* ---------------------------------------------------------------- Hero ---- */

.hero-wrap {
  container-type: inline-size;
}

.hero {
  --u: calc(100cqw / 1600);
  position: relative;
  padding: calc(30 * var(--u));
  background: var(--vrac-deep-navy);
  /* The phone spills past the left gutter; the frame clips it, as in Figma. */
  overflow: clip;
}

.bento {
  display: grid;
  gap: calc(30 * var(--u));
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* Row lines fall at 305 / 566 / 826 in the frame: the left three columns
     split 275 / 491 / 314, the right column 536 / 574, so four rows cover both. */
  grid-template-rows:
    calc(275 * var(--u))
    calc(231 * var(--u))
    calc(230 * var(--u))
    calc(314 * var(--u));
  grid-template-areas:
    "phone car     mark    icons"
    "phone logo    logo    icons"
    "phone logo    logo    mdesign"
    "usps  usps    desktop mdesign";
}

.card {
  position: relative;
  min-width: 0;
  overflow: hidden;
}

/* Wrappers that carry the entrance animation and the hover transform are
   nested rather than combined, so the two never fight over `transform`. */
.phone__enter, .phone__hover,
.car__enter,   .car__hover,
.mark__enter,  .mark__hover,
.logo__enter,
.md__enter,    .md__hover,
.desktop__enter, .desktop__hover {
  width: 100%;
  height: 100%;
}


/* -- Mobile Mockup Container — 25:10759 ------------------------------------ */

.card--phone {
  grid-area: phone;
  background: var(--vrac-light-grey);
  overflow: visible;
  /* Open on the left, so the phone can lean out over the gutter; cut flush on
     the right, as Figma's mask does. */
  clip-path: inset(0 0 0 calc(-30 * var(--u)));
}

/* The export is Figma's 414 x 796 mask box, with the drop shadow baked in.
   Figma starts that box 51px left of the card, but the phone's bezel sits only
   12.5px into the image, so there it ran past the frame edge and was cut off.
   Starting at -30 keeps the whole bezel inside the 30px gutter, 17.5px out. */
.phone {
  position: absolute;
  left: calc(-30 * var(--u));
  top: 0;
  width: calc(414 * var(--u));
  height: calc(796 * var(--u));
}

.phone img {
  width: 100%;
  height: 100%;
}


/* -- Car Image Container — 25:10762 ---------------------------------------- */

.card--car {
  grid-area: car;
  background: var(--vrac-dark-navy);
  /* The car's nose runs past the card, across the gutter and onto the
     logomark card, so this card doesn't clip and sits above its neighbour. */
  overflow: visible;
  z-index: 2;
}

.car {
  position: absolute;
  left: calc(-15.5 * var(--u));
  top: calc(40 * var(--u));
  width: calc(506.464 * var(--u));
  height: calc(261 * var(--u));
}

.car img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* -- Logomark Container — 26:716 ------------------------------------------- */

.card--mark {
  grid-area: mark;
  /* #ededed in Figma, but always covered by the artwork's own blue ground —
     blue here so the zoom-in never flashes grey at the corners. */
  background: var(--vrac-blue);
}

.mark {
  position: absolute;
  left: calc(-215.8 * var(--u));
  top: calc(-105 * var(--u));
  width: calc(777.6 * var(--u));
  height: calc(486 * var(--u));
}

.mark img {
  width: 100%;
  height: 100%;
}


/* -- Icons Container — 25:10760 -------------------------------------------- */

.card--icons {
  grid-area: icons;
  background: var(--vrac-light-grey);
}

/* A 1024px texture turned -28°, centred on (128.9, 422.4) of the card. */
.icons__texture {
  position: absolute;
  left: calc(-383.06 * var(--u));
  top: calc(-89.56 * var(--u));
  width: calc(1024 * var(--u));
  height: calc(1024 * var(--u));
  transform: rotate(-28deg);
  opacity: 0.4;
  background: var(--vrac-texture);
  pointer-events: none;
}

.icons__texture img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.2;
}

.icons {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(3, calc(26 * var(--u)));
  gap: calc(62 * var(--u));
  place-content: center;
}

.icon__hover {
  position: relative;
  display: block;
  width: calc(26 * var(--u));
  height: calc(26 * var(--u));
}

.icon__hover > img,
.icon__hover > svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

/* The glyphs that don't fill their 26px frame, placed as in the file. */
.icon__hover > .icon__img--06 { left: calc(2 * var(--u)); top: calc(1 * var(--u));    width: calc(22.614 * var(--u)); height: calc(24 * var(--u)); }
.icon__hover > .icon__img--11 { left: 0;                  top: calc(2.12 * var(--u)); width: calc(26 * var(--u));     height: calc(21.294 * var(--u)); }
.icon__hover > .icon__img--12 { left: calc(2 * var(--u)); top: calc(0.12 * var(--u)); width: calc(22.482 * var(--u)); height: calc(26 * var(--u)); }
.icon__hover > .icon__img--14 { left: calc(1 * var(--u)); top: calc(1 * var(--u));    width: calc(23.451 * var(--u)); height: calc(24 * var(--u)); }


/* -- Logo Container — 25:10764 --------------------------------------------- */

.card--logo {
  grid-area: logo;
  /* The Logo Redesign frame (25:10769) overfills the card in solid blue. */
  background: var(--vrac-blue);
}

/* The lock-up's bounding box, 452 x 86, centred on the card. */
.logo {
  position: absolute;
  left: calc(151.04 * var(--u));
  top: calc(202.12 * var(--u));
  width: calc(452.32 * var(--u));
  height: calc(85.6 * var(--u));
}

.logo__hover { position: relative; width: 100%; height: 100%; }

.logo__hover > * { position: absolute; }

.logo__mark  { left: 0;                       top: 0;                      width: calc(130.062 * var(--u)); height: calc(84.867 * var(--u)); }
.logo__varna { left: calc(155.72 * var(--u)); top: 0;                      width: calc(165.573 * var(--u)); height: calc(39.83 * var(--u)); }
.logo__rent  { left: calc(159.24 * var(--u)); top: calc(44.93 * var(--u)); width: calc(293.084 * var(--u)); height: calc(40.674 * var(--u)); }

.logo__dot {
  top: calc(64.54 * var(--u));
  width: calc(8.255 * var(--u));
  height: calc(8.255 * var(--u));
  background: var(--vrac-white);
}

.logo__dot--1 { left: calc(337.8 * var(--u)); }
.logo__dot--2 { left: calc(286.43 * var(--u)); }


/* -- Mobile Design Container — 25:10761 ------------------------------------ */

/* The card is a window onto the full mobile homepage, offset -974px so its
   "Our Most Popular Options" block (25:11105) shows. Only that block is built;
   the rest of the page is out of frame. */
.card--mdesign {
  grid-area: mdesign;
  background: var(--vrac-white);
  color: var(--vrac-dark-navy);
}

.md {
  position: absolute;
  left: calc(27.015 * var(--u));
  top: calc(31.85 * var(--u));
  width: calc(307.97 * var(--u));
  height: calc(505.25 * var(--u));
}

.md__hover { position: relative; }

.md__heading {
  position: absolute;
  top: 0;
  font-weight: 600;
  font-size: calc(21.612 * var(--u));
  line-height: calc(28.816 * var(--u));
  letter-spacing: calc(-0.5403 * var(--u));
  white-space: nowrap;
}

.md__media {
  position: absolute;
  top: calc(50.61 * var(--u));
  width: 100%;
  height: calc(207.114 * var(--u));
  background: var(--vrac-media-grey);
}

.md__media-clip {
  position: absolute;
  left: calc(2.7015 * var(--u));
  top: calc(6.3035 * var(--u));
  width: calc(302.567 * var(--u));
  height: calc(189.588 * var(--u));
  overflow: hidden;
}

.md__media-clip img {
  position: absolute;
  left: 0;
  top: calc(-13.155 * var(--u));
  width: calc(294.055 * var(--u));
  height: calc(189.588 * var(--u));
  object-fit: cover;
}

.md__info {
  position: absolute;
  top: calc(272.13 * var(--u));
  width: 100%;
  height: calc(211.05 * var(--u));
}

.md__title-row {
  position: absolute;
  top: 0;
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: calc(10.806 * var(--u));
  font-weight: 700;
}

.md__title {
  flex: 1 0 0;
  font-size: calc(18.01 * var(--u));
  line-height: calc(27.015 * var(--u));
  letter-spacing: calc(-0.4502 * var(--u));
}

.md__price {
  flex: none;
  color: var(--vrac-blue);
  font-size: calc(12.607 * var(--u));
  line-height: calc(22.963 * var(--u));
  letter-spacing: calc(-0.3152 * var(--u));
  white-space: nowrap;
}

.md__specs {
  position: absolute;
  top: calc(46.01 * var(--u));
  left: 0;
  display: flex;
  gap: calc(73.5 * var(--u));
}

.md__spec-col {
  display: flex;
  flex-direction: column;
  gap: calc(7.204 * var(--u));
}

.md__spec-col--1 { width: calc(71.14 * var(--u)); }
.md__spec-col--2 { width: calc(103.9 * var(--u)); }

.md__spec {
  display: flex;
  align-items: center;
  gap: calc(8.104 * var(--u));
  height: calc(28 * var(--u));
  font-weight: 500;
  font-size: calc(12.607 * var(--u));
  line-height: calc(27.015 * var(--u));
  white-space: nowrap;
}

.md__spec--seats { gap: calc(9.005 * var(--u)); }
.md__spec--ac    { gap: calc(6.303 * var(--u)); }

.md__spec img, .md__spec svg { flex: none; }

.md__spec--seats img { width: calc(11.848 * var(--u)); height: calc(12.607 * var(--u)); }
.md__spec img[src$="md-doors.svg"] { width: calc(12.607 * var(--u)); height: calc(10.74 * var(--u)); }
.md__gearbox { width: calc(12.607 * var(--u)); height: calc(10.774 * var(--u)); }
.md__spec--ac img { width: calc(14.408 * var(--u)); height: calc(14.408 * var(--u)); }
.md__luggage { width: calc(12.607 * var(--u)); height: calc(10.802 * var(--u)); }

.md__actions {
  position: absolute;
  top: calc(162.43 * var(--u));
  width: 100%;
  display: flex;
  gap: calc(10.806 * var(--u));
}

.md__btn {
  flex: 1 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(48.627 * var(--u));
  font-weight: 700;
  font-size: calc(12.607 * var(--u));
  line-height: calc(29.716 * var(--u));
  white-space: nowrap;
}

.md__btn--primary { background: var(--vrac-dark-navy); color: var(--vrac-white); }
.md__btn--call    { background: var(--vrac-white); }

.md__call {
  display: flex;
  flex-direction: column;
  gap: calc(0.9 * var(--u));
}

.md__call-label {
  display: flex;
  align-items: center;
  gap: calc(7.204 * var(--u));
}

.md__call-label img { width: calc(8.104 * var(--u)); height: calc(11.706 * var(--u)); }
.md__call-line { width: 100%; height: calc(1.801 * var(--u)); }

.md__divider {
  position: absolute;
  top: calc(500.3 * var(--u));
  width: 100%;
  height: calc(4.953 * var(--u));
}


/* -- USPs Container — 25:10765 --------------------------------------------- */

.card--usps {
  grid-area: usps;
  background: var(--vrac-dark-navy);
  display: flex;
  align-items: center;
  justify-content: center;
}

.usps {
  display: flex;
  justify-content: space-between;
  width: calc(620 * var(--u));
}

.usp {
  width: calc(172 * var(--u));
  display: flex;
  flex-direction: column;
  gap: calc(20 * var(--u));
}

.usp__icon {
  width: max(36px, calc(64 * var(--u)));
  height: max(36px, calc(64 * var(--u)));
}

.usp__label {
  font-weight: 700;
  font-size: max(12px, calc(20 * var(--u)));
  line-height: 1.4;
}


/* -- Destkop Design Container — 25:10767 ----------------------------------- */

.card--desktop {
  grid-area: desktop;
  background: var(--vrac-card-grey);
}

.desktop {
  position: absolute;
  left: calc(-2 * var(--u));
  top: calc(-16 * var(--u));
  width: calc(366 * var(--u));
  height: calc(330 * var(--u));
}

.desktop img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* ------------------------------------------------------ Hero — motion ---- */

/* Everything starts hidden only once JS has confirmed it will reveal it, and
   `is-ready` is added once the imagery has decoded, so the entrance isn't spent
   on empty boxes. Each card fades in on its own `--d`; its artwork then runs
   the move the annotations ask for, a beat later. */

.js .card { opacity: 0; }

@keyframes cardIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Car — fades and slides right. */
@keyframes carIn {
  from { opacity: 0; transform: translate3d(-18%, 0, 0); }
  to   { opacity: 1; transform: none; }
}

/* Phone — slides left in from beyond the card's clipped right edge. */
@keyframes phoneIn {
  from { transform: translate3d(75%, 0, 0); }
  to   { transform: none; }
}

/* Desktop design and logomark — zoom in, fade in, slight rotation. */
@keyframes zoomTurnIn {
  from { opacity: 0; transform: scale(0.86) rotate(-5deg); }
  to   { opacity: 1; transform: none; }
}

/* Mobile design and logo — zoom in, fade in. */
@keyframes zoomIn {
  from { opacity: 0; transform: scale(0.86); }
  to   { opacity: 1; transform: none; }
}

/* Icons — each slides up and fades in on its own. */
@keyframes iconIn {
  from { opacity: 0; transform: translate3d(0, 70%, 0); }
  to   { opacity: 1; transform: none; }
}

@keyframes riseIn {
  from { opacity: 0; transform: translate3d(0, 12%, 0); }
  to   { opacity: 1; transform: none; }
}

/* Running order. The logo lands last, once the rest of the grid has settled
   around the hole it fills. */
.card--phone   { --d: 0.05s; }
.card--car     { --d: 0.15s; }
.card--mark    { --d: 0.25s; }
.card--icons   { --d: 0.35s; }
.card--desktop { --d: 0.45s; }
.card--usps    { --d: 0.55s; }
.card--mdesign { --d: 0.65s; }
.card--logo    { --d: 1.2s;  }

.bento.is-ready .card {
  animation: cardIn 0.7s ease-out var(--d) both;
}

.bento.is-ready .car__enter     { animation: carIn      var(--enter-duration) var(--ease-out) calc(var(--d) + 0.1s) both; }
.bento.is-ready .phone__enter   { animation: phoneIn    1.3s                  var(--ease-out) calc(var(--d) + 0.1s) both; }
.bento.is-ready .mark__enter    { animation: zoomTurnIn var(--enter-duration) var(--ease-out) calc(var(--d) + 0.1s) both; }
.bento.is-ready .desktop__enter { animation: zoomTurnIn var(--enter-duration) var(--ease-out) calc(var(--d) + 0.1s) both; }
.bento.is-ready .md__enter      { animation: zoomIn     var(--enter-duration) var(--ease-out) calc(var(--d) + 0.1s) both; }
.bento.is-ready .logo__enter    { animation: zoomIn     var(--enter-duration) var(--ease-out) calc(var(--d) + 0.1s) both; }
.bento.is-ready .usps           { animation: riseIn     var(--enter-duration) var(--ease-out) calc(var(--d) + 0.1s) both; }

.bento.is-ready .icon {
  animation: iconIn 0.8s var(--ease-out) calc(var(--d) + 0.2s + var(--i) * 0.045s) both;
}

/* Hover repeats each card's own move, a little further. Only where hovering is
   real, and not for anyone who has asked for less motion. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .car__hover,
  .phone__hover,
  .mark__hover,
  .desktop__hover,
  .md__hover,
  .logo__hover,
  .icon__hover {
    transition: transform var(--hover-duration) var(--hover-ease);
  }

  .card--car:hover     .car__hover     { transform: translate3d(4%, 0, 0); }
  /* The export is cut off at the card's right and bottom edges, so moving the
     phone up or left would show that cut. It eases toward the corner instead. */
  .card--phone:hover   .phone__hover   { transform: translate3d(3%, 1.5%, 0); }
  .card--mark:hover    .mark__hover    { transform: scale(1.08) rotate(3deg); }
  .card--desktop:hover .desktop__hover { transform: scale(1.07) rotate(1.5deg); }
  .card--mdesign:hover .md__hover      { transform: scale(1.04); }
  .card--logo:hover    .logo__hover    { transform: scale(1.06); }

  /* A wave down the grid: each icon lifts a touch after the one before. */
  .icon__hover { transition-delay: calc(var(--i) * 0.025s); }
  .card--icons:hover .icon__hover { transform: translate3d(0, -35%, 0); }
}


/* --------------------------------------------------- Hero — two columns ---- */

/* Same 363px cards, stacked two abreast (363 + 30 + 363 = 756 design px), so the
   artwork inside each card keeps its geometry. Three cards are re-cut to make
   the columns meet: icons 536 → 491, mobile design 574 → 574 (275 + 30 + 269),
   desktop design 314 → 269. */
@media (max-width: 759px) {
  .hero {
    --u: calc((100cqw - 32px) / 756);
    padding: 16px;
  }

  .bento {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows:
      calc(491 * var(--u))
      calc(275 * var(--u))
      calc(491 * var(--u))
      calc(275 * var(--u))
      calc(269 * var(--u))
      auto;
    grid-template-areas:
      "logo    logo"
      "phone   car"
      "phone   icons"
      "mark    mdesign"
      "desktop mdesign"
      "usps    usps";
  }

  /* At the right edge of the screen the breakout would run off the page. */
  .card--car { overflow: hidden; }

  /* The three USPs at 0.45 scale would be 9px type; they stack as rows instead. */
  .card--usps { padding: 24px 20px; }

  .usps {
    width: 100%;
    flex-direction: column;
    gap: 16px;
  }

  .usp {
    width: auto;
    flex-direction: row;
    align-items: center;
    gap: 16px;
  }

  .usp__icon { width: 40px; height: 40px; }

  .usp__label { font-size: 16px; }
}


/* ------------------------------------------- Role & Deliverables — 30:4153 ---- */

/* Three 450px columns on a 24px gutter inside 100px of padding — the whole
   1600px frame at the design width, and proportionally narrower below it. */
.roles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px 24px;
  align-items: start;
  padding: clamp(48px, 6.25vw, 100px) clamp(16px, 6.25vw, 100px);
}

.roles__col {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.roles__heading {
  margin: 0;
  font-size: clamp(26px, 2vw, 32px);
  font-weight: 700;
  /* 28px on 32px type in the file: set solid, so the heading's box is no
     taller than its caps and the 24px gap below reads true. */
  line-height: 0.875;
}

.roles__heading--spacer { visibility: hidden; }

.roles__list {
  font-size: clamp(17px, 1.25vw, 20px);
  font-weight: 500;
  line-height: 1.8;
}

/* One column: the spacer would only add dead space, and the third list is
   pulled up under the second so the six deliverables read as one list. */
@media (max-width: 759px) {
  .roles { grid-template-columns: minmax(0, 1fr); }

  .roles__heading--spacer { display: none; }

  .roles__col--more { margin-top: -40px; }
}


/* ----------------------------------------- The Wireframes — 30:4169 ---- */

/* A dark-navy band, full bleed, around content held to the page column. The
   two 755px columns on a 30px gutter are the bento's own grid — two cards and
   a gutter each — so they're sized in the same design pixel, `--u`. */
.wires-wrap {
  grid-column: full;
  background: var(--vrac-dark-navy);
}

.wires-frame {
  max-width: 1800px;
  margin: 0 auto;
  container-type: inline-size;
}

.wires {
  --u: calc(100cqw / 1600);
  display: flex;
  flex-direction: column;
  gap: max(32px, calc(75 * var(--u)));
  padding: max(48px, calc(100 * var(--u))) calc(30 * var(--u));
}

/* 70px of its own padding on the 30px gutter puts the heading on the same
   100px line as Role & Deliverables, at every width. */
.wires__heading {
  margin: 0;
  padding-inline: calc(clamp(16px, 6.25vw, 100px) - 30 * var(--u));
  font-size: clamp(30px, 3vw, 48px);
  font-weight: 700;
  line-height: 1.25;
}

.wires__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(30 * var(--u));
  align-items: start;
}

.wires__col {
  display: flex;
  flex-direction: column;
  gap: calc(30 * var(--u));
}

.wires__img {
  width: 100%;
  height: auto;
}


/* -- Content Section — 44:13419 -------------------------------------------- */

/* Sized as its own container, so everything inside is in the card's design
   pixel (`--cu`, 1/755 of its width) and keeps its layout whether the card
   sits in the second column or runs the full width of a phone. */
.wires-card {
  position: relative;
  container-type: inline-size;
  aspect-ratio: 755.196 / 998;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* `clip`, not `hidden`: a scroll container loses the automatic minimum
     height, so the aspect ratio would hold even when the text needs more
     room, and the copy would be cut off at the top. */
  overflow: clip;
  isolation: isolate;
  background: var(--vrac-deep-navy);
}

.wires-card > * { --cu: calc(100cqw / 755.196); }

/* The same texture as the Icons card, 1321px square and turned -26.41°. The
   export describes a pale layer at 80% holding the image at 20%, which would
   wash the card out. Figma renders it darker than the navy instead, with deep
   streaks: a colour burn. Measured against the Figma render, the burn at full
   strength matches to within 0.01 per pixel; the exported opacities (80% / 20%)
   leave the streaks too faint. */
.wires-card__texture {
  position: absolute;
  left: calc(-254.12 * var(--cu));
  top: calc(-193.22 * var(--cu));
  width: calc(1321.334 * var(--cu));
  height: calc(1321.334 * var(--cu));
  transform: rotate(-26.41deg);
  background: var(--vrac-texture);
  mix-blend-mode: color-burn;
  pointer-events: none;
}

.wires-card__texture img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A 588px block whose top falls at 468px in the file; anchored from the
   bottom instead, so the minimum type sizes below can't push it out of the
   card. */
.wires-card__content {
  position: relative;
  display: flex;
  flex-direction: column;
  padding:
    0
    max(24px, calc(98.23 * var(--cu)))
    max(32px, calc(99.76 * var(--cu)))
    max(24px, calc(68.97 * var(--cu)));
}

.wires-card__icon {
  width: max(36px, calc(60 * var(--cu)));
  height: auto;
  margin-bottom: max(20px, calc(40 * var(--cu)));
}

.wires-card__heading {
  font-size: max(22px, calc(40 * var(--cu)));
  font-weight: 500;
  line-height: 1.35;
  margin-bottom: max(12px, calc(24 * var(--cu)));
}

.wires-card__copy {
  font-size: max(16px, calc(24 * var(--cu)));
  font-weight: 500;
  line-height: 1.5;
  color: var(--vrac-light-grey);
}

@media (max-width: 759px) {
  .wires { padding: 48px 16px; }

  .wires__heading { padding-inline: calc(clamp(16px, 6.25vw, 100px) - 16px); }

  .wires__grid,
  .wires__col { grid-template-columns: minmax(0, 1fr); gap: 16px; }

  /* Full width the card's own proportions would make it most of a screen
     tall; it takes the height of its text plus room for the texture. */
  .wires-card {
    aspect-ratio: auto;
    padding-top: 160px;
  }
}


/* -------------------------------------------- The Designs — 30:4186 ---- */

/* One column of blocks on the bento's 30px gutter, each 30px from the next:
   a bento of six screens, two text panels, and six page previews. */
.designs-wrap {
  container-type: inline-size;
}

.designs {
  --u: calc(100cqw / 1600);
  display: flex;
  flex-direction: column;
  gap: calc(30 * var(--u));
  padding: 0 calc(30 * var(--u)) calc(30 * var(--u));
}

/* 100 above, 75 below, and the bento's own 30px top padding after that. The
   file sets it 70px in, where every other heading and panel sits on the
   100px line; it's on that line here. */
.designs__heading {
  margin: 0;
  padding:
    max(48px, calc(100 * var(--u)))
    calc(clamp(16px, 6.25vw, 100px) - 30 * var(--u))
    max(2px, calc(75 * var(--u)));
  font-size: clamp(30px, 3vw, 48px);
  font-weight: 700;
  line-height: 1.25;
}

.designs img { width: 100%; height: auto; }


/* -- Bento Grid — 44:10397 ------------------------------------------------- */

/* Three 493px columns, each a 355 / 755 pair; the middle one upside down. The
   exports are 2x, so the images carry their own proportions. */
.designs-bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: calc(30 * var(--u));
  align-items: start;
}

.designs-bento__col {
  display: flex;
  flex-direction: column;
  gap: calc(30 * var(--u));
}


/* -- Content Sections — 52:16843, 52:16845 --------------------------------- */

/* The same build as the wireframes card, 1540 wide: a container whose
   children measure in its design pixel (`--pu`), copy anchored 100px from the
   bottom so minimum type sizes can grow it rather than overflow it. */
.panel {
  position: relative;
  container-type: inline-size;
  aspect-ratio: 1540 / 535;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: clip; /* not `hidden` — see .wires-card */
  isolation: isolate;
  background: var(--vrac-deep-navy);
}

.panel > * { --pu: calc(100cqw / 1540); }

/* Each texture is a 1082px square of streaks laid over the navy in soft
   light, then faded back into the navy by a gradient that turns with it. The
   blend has to sit on the turned element itself — a transform starts a new
   stacking context, and a blend inside one would only see an empty layer. So
   the image and its fade are two siblings sharing a transform, rather than
   Figma's one group. */
.panel__texture,
.panel__fade {
  position: absolute;
  width: calc(1082 * var(--pu));
  height: calc(1082 * var(--pu));
  pointer-events: none;
}

.panel__texture { mix-blend-mode: soft-light; }

.panel__texture img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Roadblocks: two textures, both flipped and turned -147.61°, centred on
   (192, 426) and (1434.6, 166.6). */
.panel__texture--a, .panel__fade--a,
.panel__texture--b, .panel__fade--b {
  transform: rotate(-147.61deg) scaleY(-1);
}

.panel__texture--a, .panel__fade--a { left: calc(-349 * var(--pu));    top: calc(-115 * var(--pu)); }
.panel__texture--b, .panel__fade--b { left: calc(893.63 * var(--pu));  top: calc(-374.37 * var(--pu)); }

.panel__fade--a { background: linear-gradient(269.53deg, rgba(6, 4, 73, 0) 43.74%, var(--vrac-deep-navy) 99.477%); }
.panel__fade--b { background: linear-gradient(140.86deg, rgba(6, 4, 73, 0) 48.072%, var(--vrac-deep-navy) 79.275%); }

/* Results: one texture turned -32.71°, centred on (1212.6, 303). */
.panel__texture--c, .panel__fade--c {
  left: calc(671.56 * var(--pu));
  top: calc(-237.97 * var(--pu));
  transform: rotate(-32.71deg);
}

.panel__fade--c { background: linear-gradient(269.53deg, rgba(6, 4, 73, 0) 43.74%, var(--vrac-deep-navy) 99.477%); }

.panel__copy {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding:
    0
    max(24px, calc(545 * var(--pu)))
    max(32px, calc(100 * var(--pu)))
    max(24px, calc(69 * var(--pu)));
}

/* Both icons are the stacked-chevron glyph turned on its side, as in the file:
   one flipped and turned -90° (a row of slashes), one turned 90° (›››). */
.panel__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  height: max(30px, calc(60 * var(--pu)));
  margin-bottom: max(20px, calc(40 * var(--pu)));
}

.panel__icon img {
  flex: none;
  width: auto;
  height: auto;
}

.panel__icon--slash    { width: max(61.5px, calc(123 * var(--pu))); }
.panel__icon--chevrons { width: max(48.2px, calc(96.367 * var(--pu))); }

.panel__icon--slash img {
  width: max(30px, calc(60 * var(--pu)));
  transform: rotate(-90deg) scaleY(-1);
}

.panel__icon--chevrons img {
  width: max(30px, calc(60 * var(--pu)));
  transform: rotate(90deg);
}

.panel__heading {
  margin: 0 0 max(12px, calc(24 * var(--pu)));
  max-width: max(260px, calc(728 * var(--pu)));
  font-size: max(22px, calc(40 * var(--pu)));
  font-weight: 500;
  line-height: 1.35;
}

.panel__body {
  max-width: max(280px, calc(832 * var(--pu)));
  font-size: max(16px, calc(24 * var(--pu)));
  font-weight: 500;
  line-height: 1.5;
  color: var(--vrac-light-grey);
}


/* -- Previews — 30:10609, 30:10146, 52:16844 – 52:16848 -------------------- */

/* A desktop page beside its mobile version, 1140 + 26 + 374. The rest are a
   single page across the full 1540. */
.preview--pair {
  display: grid;
  grid-template-columns: minmax(0, 1140fr) minmax(0, 374fr);
  gap: calc(26 * var(--u));
  align-items: start;
}


@media (max-width: 759px) {
  .designs { gap: 16px; padding: 0 16px 16px; }

  .designs__heading {
    padding: 48px calc(clamp(16px, 6.25vw, 100px) - 16px) 16px;
  }

  /* Three columns of screens would be thumbnails; they stack instead. */
  .designs-bento,
  .preview--pair {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
  }

  .designs-bento__col { gap: 16px; }

  .panel {
    aspect-ratio: auto;
    padding-top: 140px;
  }

  /* The phone page reads at its own width rather than stretched to the
     desktop one. */
  .preview--pair img + img {
    max-width: 374px;
    justify-self: center;
  }
}


/* ------------------------------------------ Conclusion — 2013:8049 ---- */

/* 100px in from the frame on the same line as Role & Deliverables, with 200px
   below to close the page. Type steps down like the text panels'. */
.conclusion {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding:
    clamp(48px, 6.25vw, 100px)
    clamp(16px, 6.25vw, 100px)
    clamp(96px, 12.5vw, 200px);
}

.conclusion__icon {
  width: clamp(40px, 3.75vw, 60px);
  height: auto;
  margin-bottom: clamp(24px, 2.5vw, 40px);
  transform: rotate(90deg);
}

.conclusion__heading {
  margin: 0 0 clamp(12px, 1.5vw, 24px);
  max-width: 798px;
  font-size: clamp(24px, 2.5vw, 40px);
  font-weight: 500;
  line-height: 1.35;
}

.conclusion__body {
  max-width: 832px;
  font-size: clamp(17px, 1.5vw, 24px);
  font-weight: 500;
  line-height: 1.5;
  color: var(--vrac-light-grey);
}


/* ---------------------------------------------------- Section reveals ---- */

/* Everything below the hero fades in and rises as it's scrolled to (the hero
   has its own entrance). Same pattern as the Nordra case study —
   `--reveal-delay` for cascades, `is-visible` added by app.js — with one
   change: the hidden state is keyed to `has-reveals`, which app.js sets only
   once its observer is running, rather than to `.js`. Keyed to `.js`, a
   stale cached app.js from before the reveals existed would hide every
   section and never show them again. Now a script that doesn't run the
   reveals leaves the page as it is.

   The rise is on `translate`, not `transform`, so it composes with transforms
   the elements already carry — the conclusion icon's 90° turn, for one —
   instead of replacing them. */
.has-reveals .reveal {
  opacity: 0;
  translate: 0 28px;
  transition:
    opacity 900ms var(--ease-out),
    translate 900ms var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

.has-reveals .reveal.is-visible {
  opacity: 1;
  translate: none;
}


/* ------------------------------------------------------- Reduced motion ---- */

@media (prefers-reduced-motion: reduce) {
  .js .card { opacity: 1; }

  .bento.is-ready .card,
  .bento.is-ready .car__enter,
  .bento.is-ready .phone__enter,
  .bento.is-ready .mark__enter,
  .bento.is-ready .desktop__enter,
  .bento.is-ready .md__enter,
  .bento.is-ready .logo__enter,
  .bento.is-ready .usps,
  .bento.is-ready .icon {
    animation: none;
  }

  .has-reveals .reveal {
    opacity: 1;
    translate: none;
    transition: none;
  }
}
