/* ==========================================================================
   B VISUAL — home.css
   Page-specific rules for the Home main content only.
   No new font-size declarations — every size comes from applying
   .t-display/.t-head/.t-sub/.t-body/.t-micro in the markup. This file only
   sets colour, spacing, layout and decorative shape.
   No box-shadow. 0px radius on cards/covers, 10px on ui, one pill on the CTA.
   ========================================================================== */

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

.hero {
  position: relative;
  padding-top: calc(var(--nav-h) + var(--s10));
  padding-bottom: var(--s12);
  background-image: var(--surface-plum);
  overflow: hidden;
}

.hero__label { margin-bottom: var(--s6); }

.hero__title { color: var(--paper); }

/* Hollow "IMPOSSIBLE" — outline only.

   NOT -webkit-text-stroke: that strokes every contour in a glyph, so where
   Outfit's bowls and arms overlap their stems (M, P, B, L, E) the seams show
   as stray lines inside the letterforms. Instead the word is painted solid
   and an SVG filter (#bv-outline in index.html) dilates the union silhouette
   and subtracts the original, leaving a clean ring around the outside with
   the counters intact. */
.hero__hollow {
  color: var(--lime);
  filter: url(#bv-outline);
}

/* The ring's colour is the filter's feFlood, not the element's `color` — the
   composite is `out`, so the painted glyph is discarded and only the dilated
   halo survives. Setting it here rather than on the flood-color attribute in
   index.html keeps every colour literal in tokens.css; the attribute stays
   white as the no-CSS fallback. */
.bv-defs #bv-outline feFlood { flood-color: var(--lime); }

/* No filter support: fall back to a solid word rather than an absent one. */
@supports not (filter: url(#bv-outline)) {
  .hero__hollow { filter: none; color: var(--lime); }
}

.bv-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* The line splitter rebuilds this word inside its own mask; the class is
   carried onto the clone, so nothing extra is needed there. */


.hero__sub {
  margin-top: var(--s6);
  color: var(--bone);
}

.hero__actions {
  margin-top: var(--s8);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
}

.hero__scroll-cue {
  position: absolute;
  right: var(--gutter);
  bottom: var(--s6);
  display: flex;
  align-items: center;
  gap: var(--s2);
  color: var(--mute);
}
.hero__scroll-cue i {
  display: block;
  width: 1px;
  height: 28px;
  background: var(--hair);
  position: relative;
  overflow: hidden;
}
.hero__scroll-cue i::after {
  content: "";
  position: absolute;
  left: 0; top: -100%;
  width: 100%; height: 100%;
  background: var(--mint);
  animation: bv-cue-drop 2.4s var(--e-out) infinite;
}
@keyframes bv-cue-drop {
  0%   { transform: translateY(0); }
  60%  { transform: translateY(200%); }
  100% { transform: translateY(200%); }
}
@media (prefers-reduced-motion: reduce) {
  .hero__scroll-cue i::after { animation: none; transform: translateY(100%); }
}

@media (max-width: 720px) {
  .hero { padding-top: calc(var(--nav-h) + var(--s6)); }
  .hero__scroll-cue { display: none; }
}

/* --------------------------------------------------------------------------
   Section heads — shared shape for services / work / process
   -------------------------------------------------------------------------- */

.sec-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s6);
  margin-bottom: var(--s10);
}
.sec-head .label { margin-bottom: var(--s3); }

@media (max-width: 640px) {
  .sec-head { flex-direction: column; align-items: flex-start; gap: var(--s3); }
}

/* --------------------------------------------------------------------------
   Services teaser — list of seven rows
   -------------------------------------------------------------------------- */

.svc-list { border-top: var(--hairline); }

.svc-row {
  display: grid;
  grid-template-columns: 72px 1.1fr 1.4fr auto;
  align-items: center;
  gap: var(--s6);
  padding-block: var(--s5);
  border-bottom: var(--hairline);
  transition: background-color var(--d-ui) var(--e-out);
}
/* :not(.is-lit) — this is the UNLIT hover, which is what shows when svchover.js
   is absent: no JS, touch, or reduced motion. When the row is lit, the lime bar
   is the hover state and this tint must not composite over it (it dragged the
   bar to rgb(209,243,69) instead of true lime).
   Scoped here rather than fought with specificity in shell.css: these two rules
   and the .is-lit inversions tie at (0,3,0)/(0,2,0), and home.css loads after
   shell.css, so source order silently decided it. */
.svc-row:hover:not(.is-lit) { background: var(--purple-08); }

.svc-row__num {
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

.svc-row__name { color: var(--paper); }

.svc-row__promise { color: var(--bone); max-width: 46ch; }

.svc-row__arrow {
  justify-self: end;
  width: 40px;
  height: 40px;
  border: var(--hairline);
  border-radius: var(--r-ui);
  display: grid;
  place-items: center;
  color: var(--bone);
  transition: border-color var(--d-ui) var(--e-out), color var(--d-ui) var(--e-out), background-color var(--d-ui) var(--e-out);
  flex: none;
}
.svc-row:hover:not(.is-lit) .svc-row__arrow { border-color: var(--lime); color: var(--lime); }
.svc-row__arrow svg { width: 16px; height: 16px; }

@media (max-width: 900px) {
  .svc-row { grid-template-columns: 48px 1fr; grid-template-areas: "num name" "promise promise"; row-gap: var(--s2); }
  .svc-row__num { grid-area: num; }
  .svc-row__name { grid-area: name; }
  .svc-row__promise { grid-area: promise; }
  .svc-row__arrow { display: none; }
}

/* --------------------------------------------------------------------------
   Work teaser — generated covers
   -------------------------------------------------------------------------- */

.work-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s6);
}
@media (max-width: 900px) {
  .work-grid { grid-template-columns: 1fr; }
}

.work-card { display: block; color: inherit; }

.work-cover {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-flat);
  overflow: hidden;
  background: linear-gradient(155deg, var(--purple) 0%, var(--blue) 100%);
  isolation: isolate;
}

/* Per-card gradient variation — same two brand tones (plus ink-lift as a
   third stop on card 3), different angle/order/weighting per card so the
   covers don't read as one template with swapped icons. */
.work-card:nth-child(2) .work-cover {
  background: linear-gradient(205deg, var(--blue) 0%, var(--purple) 100%);
}
.work-card:nth-child(3) .work-cover {
  background: linear-gradient(55deg, var(--purple) 0%, var(--ink-lift) 55%, var(--blue) 100%);
}

.work-cover__pattern {
  position: absolute;
  inset: -10%;
  opacity: .08;
  background-repeat: repeat;
  background-size: 96px auto;
  transform: rotate(-8deg);
}

.work-cover__accent {
  position: absolute;
  border-radius: 0;
}

/* Per-card variation, applied by index via nth-child on the grid. */
.work-card:nth-child(1) .work-cover__accent {
  width: 46%; aspect-ratio: 1 / 1;
  right: -10%; bottom: -12%;
  background: var(--lime);
  border-radius: 50%;
}
.work-card:nth-child(2) .work-cover__accent {
  width: 62%; height: 3px;
  left: 8%; top: 38%;
  background: var(--mint);
  transform: rotate(-18deg);
}
.work-card:nth-child(2) .work-cover__accent::after {
  content: "";
  position: absolute;
  left: 0; top: -74px;
  width: 100%; height: 3px;
  background: var(--mint);
  opacity: .5;
}
.work-card:nth-child(3) .work-cover__accent {
  width: 0; height: 0;
  right: 14%; top: 12%;
  border-left: 60px solid transparent;
  border-right: 60px solid transparent;
  border-bottom: 96px solid var(--lime);
  background: none;
}

.work-cover__foot {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: var(--s4);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s2);
  background: linear-gradient(0deg, var(--ink-80) 0%, rgba(20,11,48,0) 100%);
}
.work-cover__client { color: var(--paper); }
.work-cover__year { color: var(--bone-64); }

.work-card__meta {
  margin-top: var(--s3);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  color: var(--mute);
}
.work-card__result {
  margin-top: var(--s2);
  color: var(--bone);
}

.work-note { margin-top: var(--s8); color: var(--mute); }

/* --------------------------------------------------------------------------
   Process — numbered sequence
   -------------------------------------------------------------------------- */

.process-list {
  border-top: var(--hairline);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 900px) {
  .process-list { grid-template-columns: 1fr; }
}

.process-step {
  padding: var(--s6) var(--s5) var(--s6) 0;
  border-bottom: var(--hairline);
  border-right: var(--hairline);
}
.process-list .process-step:last-child { border-right: 0; }
@media (max-width: 900px) {
  .process-step { border-right: 0; padding-right: 0; }
}

.process-step__num { color: var(--paper); }
.process-step__name { margin-top: var(--s2); color: var(--mute); }
.process-step__desc { margin-top: var(--s3); color: var(--bone); max-width: 34ch; }

/* --------------------------------------------------------------------------
   Global CTA band
   -------------------------------------------------------------------------- */

.cta-band {
  border-top: var(--hairline);
  background-image: var(--surface-plum);
}
.cta-band__title { color: var(--paper); }
.cta-band__sub { margin-top: var(--s5); color: var(--bone); }
.cta-band__actions { margin-top: var(--s8); }

/* --------------------------------------------------------------------------
   Our clients — a muted wordmark marquee, [data-marquee] handles the
   duplication/scroll (site/js/motion.js). Same placeholder company set as
   the Work section; kept deliberately quiet (--mute, no card chrome) so it
   reads as an honest trust-bar sketch, not a claim of polished client logos.
   -------------------------------------------------------------------------- */

.clients .label { margin-bottom: var(--s6); }

.clients__marquee { padding-block: var(--s2); }

.clients__name {
  color: var(--mute);
  font-weight: var(--w-mid);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Small team, big energy
   -------------------------------------------------------------------------- */

.team__grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: var(--s10);
  align-items: end;
}
.team__title { letter-spacing: var(--tr-display); }
.team__body { padding-bottom: var(--s2); }

@media (max-width: 900px) {
  .team__grid { grid-template-columns: 1fr; gap: var(--s5); align-items: start; }
}

/* ==========================================================================
   HERO — layered depth
   Every moving layer is transform/opacity only. The type sits above all of
   them and none of the decoration ever overlaps the reading column, so the
   headline stays legible at every width.
   ========================================================================== */

.hero {
  isolation: isolate;
  /* dvh so the hero settles correctly as mobile browser chrome collapses. */
  min-height: min(100dvh, 62rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.hero__inner { position: relative; z-index: 3; }

/* Grid: a static CSS gradient, drifted by transform. Cheap — no filters. */
/* .particle-field moved to shell.css — the splash uses it too, and it does
   not load home.css. Left here, the canvas fell into normal flow at 18,035px
   tall and dragged the whole page with it. */

.hero__grid {
  position: absolute;
  inset: -12% -5% -20%;
  z-index: 0;
  pointer-events: none;
  opacity: .5;
  background-image:
    linear-gradient(to right, var(--purple-08) 1px, transparent 1px),
    linear-gradient(to bottom, var(--purple-08) 1px, transparent 1px);
  background-size: clamp(48px, 7vw, 96px) clamp(48px, 7vw, 96px);
  -webkit-mask-image: radial-gradient(80% 70% at 30% 30%, #000 0%, transparent 78%);
          mask-image: radial-gradient(80% 70% at 30% 30%, #000 0%, transparent 78%);
}

/* The single restrained acid-lime event on the page. A static radial —
   never an animated filter — nudged by transform only. */
.hero__glow {
  position: absolute;
  z-index: 1;
  right: -14vw;
  top: 6vh;
  width: min(58vw, 720px);
  aspect-ratio: 1;
  pointer-events: none;
  opacity: .16;
  background: radial-gradient(circle at 50% 50%, var(--lime) 0%, rgba(216,255,53,.35) 32%, rgba(216,255,53,0) 68%);
}

.hero__mark {
  position: absolute;
  z-index: 1;
  right: clamp(-6rem, -2vw, 2rem);
  bottom: 8%;
  width: clamp(180px, 26vw, 420px);
  opacity: .10;
  pointer-events: none;
}
.hero__mark img { width: 100%; height: auto; }

.hero__frag {
  position: absolute;
  z-index: 2;
  overflow: hidden;
  border-radius: var(--r-flat);
  border: var(--hairline);
  pointer-events: none;
}
.hero__frag img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero__frag--a { right: 5vw;  top: 16vh; width: clamp(120px, 15vw, 230px); aspect-ratio: 4/3; opacity: .5; }
.hero__frag--b { right: 20vw; bottom: 10vh; width: clamp(100px, 11vw, 170px); aspect-ratio: 3/4; opacity: .38; }

/* Below the point where the type column would collide with the fragments,
   the decoration is dropped entirely rather than shrunk — a cropped frame
   behind a headline is noise, not depth. */
@media (max-width: 1100px) {
  .hero__frag { display: none; }
  .hero__mark { opacity: .07; }
}
@media (max-width: 720px) {
  .hero__glow { right: -30vw; width: 80vw; opacity: .12; }
}

/* ==========================================================================
   SELECTED WORK — carousel cards
   ========================================================================== */

.wcard {
  flex: none;
  width: clamp(15rem, 32vw, 27rem);
  display: block;
  color: inherit;
  scroll-snap-align: center;
}
.wcard__frame {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;                      /* the crop the image scales inside */
  border-radius: var(--r-flat);
  border: var(--hairline);
  background: var(--ink-lift);
}
.wcard__img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transform-origin: 50% 50%;
  will-change: transform;
}
.wcard__meta { margin-top: var(--s3); }
.wcard__num   { color: var(--mute); }
.wcard__title { color: var(--paper); margin-top: var(--s1); }
.wcard__desc  { color: var(--bone); margin-top: var(--s1); max-width: 34ch; }

.wcard:hover .wcard__frame,
.wcard:focus-visible .wcard__frame { border-color: var(--purple); }

/* ==========================================================================
   STATEMENT
   ========================================================================== */

.statement__quote { margin: 0; }
.statement__text { color: var(--paper); max-width: 22ch; margin-top: var(--s5); }

/* Purple, not lime: these sit on every visit to the homepage, and M4 caps the
   accent at three per viewport — purple is explicitly ground and exempt. */
.statement__mark {
  display: block;
  width: clamp(56px, 7vw, 96px);
  height: auto;
  overflow: visible;
}
.statement__mark circle,
.statement__mark path { fill: var(--purple); }
.statement__mark--open  { margin-bottom: var(--s4); }
/* The closing mark is the same artwork rotated — a mirrored pair reads as a
   matched set, and rotating avoids a second path definition. It is decorative
   artwork, not the logo, so rotation is fine here. */
.statement__mark--close {
  transform: rotate(180deg);
  margin-top: var(--s6);
  margin-left: auto;                /* sits under the end of the quotation */
}
@media (max-width: 720px) { .statement__text { max-width: none; } }

/* ==========================================================================
   RIBBON — overlapping frames, mixed ratios
   ========================================================================== */

.ribbon { overflow: clip; }
.ribbon__row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(var(--s3), 3vw, var(--s8));
  padding-inline: var(--gutter);
}
.ribbon__item {
  position: relative;
  margin: 0;
  flex: none;
  width: clamp(8rem, 24vw, 21rem);
}
.ribbon__item img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  border: var(--hairline);
  border-radius: var(--r-flat);
}
.ribbon__item--tall img { aspect-ratio: 3 / 4; }
.ribbon__item--wide { width: clamp(11rem, 34vw, 30rem); }
.ribbon__item--wide img { aspect-ratio: 16 / 10; }
.ribbon__item figcaption { margin-top: var(--s2); color: var(--mute); }

/* Deliberate overlap — editorial, not a card grid. */
.ribbon__item--wide { margin-inline: calc(var(--s5) * -1); z-index: 1; }
/* The negative margin that creates the overlap also drags this caption under
   the neighbouring frame — push the text back to the image's visible edge. */
.ribbon__item--wide figcaption { padding-left: var(--s5); }

@media (max-width: 720px) {
  .ribbon__row { gap: var(--s2); }
  .ribbon__item--wide { margin-inline: calc(var(--s2) * -1); }
}

/* ==========================================================================
   METRICS
   ========================================================================== */

.metrics__grid {
  margin-top: var(--s10);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s6);
  border-top: var(--hairline);
}
.metric { padding-top: var(--s6); border-right: var(--hairline); padding-right: var(--s5); }
.metric:last-child { border-right: 0; }
.metric__num   { color: var(--paper); font-variant-numeric: tabular-nums; }
.metric__label { color: var(--mute); margin-top: var(--s3); }

@media (max-width: 760px) {
  .metrics__grid { grid-template-columns: 1fr; gap: 0; }
  .metric { border-right: 0; border-bottom: var(--hairline); padding-bottom: var(--s6); }
  .metric:last-child { border-bottom: 0; }
}

/* ==========================================================================
   FEATURED PROJECT
   One block per case study. Adding a second .feature simply stacks; the
   media side alternates so a list does not read as a column of identical
   rows.
   ========================================================================== */

.feature {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(var(--s6), 4vw, var(--s10));
  align-items: center;
  color: inherit;
  border-top: var(--hairline);
  padding-top: var(--s8);
}
.feature + .feature { margin-top: var(--s10); }
.feature:nth-of-type(even) .feature__media { order: 2; }

/* The Explorer shot is PORTRAIT (533x800, 2:3). It was being forced into a
   4/3 landscape box with object-fit: cover, which cropped away most of the
   frame — the car was cut off at the bottom. No forced ratio here: the image
   renders whole, at its own proportion.

   The column is capped instead of the image. A 2:3 photo across the full grid
   column would stand ~1.5x its own width tall and swamp the row, so the figure
   is width-limited and centred; the image then fits inside it complete. */
.feature__media {
  margin: 0;
  overflow: hidden;                /* still the box the hover scale lives in */
  border: var(--hairline);
  border-radius: var(--r-flat);
  background: var(--ink-lift);
  /* Explicit width: as a grid item the figure was shrink-to-fitting, which
     left the image sizing from its height instead of its width and rendering
     narrower than its column. Width drives, height follows the ratio. */
  width: 100%;
  max-width: 30rem;
  margin-inline: auto;
}
.feature__media img {
  width: 100%;
  height: auto;                    /* natural ratio — nothing is cropped */
  display: block;
  transform-origin: 50% 50%;
  transition: transform var(--d-reveal) var(--e-out);
}
.feature:hover .feature__media img,
.feature:focus-visible .feature__media img { transform: scale(1.03); }
.feature:hover .feature__media,
.feature:focus-visible .feature__media { border-color: var(--purple); }

.feature__client { color: var(--mute); }
.feature__title  { color: var(--paper); margin-top: var(--s3); }
.feature__sub    { color: var(--bone); margin-top: var(--s4); max-width: 46ch; }

.feature__stats {
  margin: var(--s8) 0 0;
  display: grid;
  grid-template-columns: repeat(3, auto);
  gap: var(--s6);
  justify-content: start;
  border-top: var(--hairline);
  padding-top: var(--s5);
}
.feature__stats dt { color: var(--mute); }
.feature__stats dd { color: var(--paper); margin: var(--s2) 0 0; font-variant-numeric: tabular-nums; }

.feature__cta {
  margin-top: var(--s7);
  color: var(--lime);
  display: inline-block;
  transition: transform var(--d-ui) var(--e-out);
}
.feature:hover .feature__cta { transform: translateX(6px); }

@media (max-width: 900px) {
  .feature { grid-template-columns: 1fr; gap: var(--s5); padding-top: var(--s6); }
  .feature:nth-of-type(even) .feature__media { order: 0; }
  .feature__media { max-width: none; }   /* full width once stacked */
  .feature__stats { gap: var(--s5); }
}
@media (max-width: 520px) {
  .feature__stats { grid-template-columns: 1fr 1fr; row-gap: var(--s4); }
}
