/* ==========================================================================
   insights.css - the field notes: the listing, the reader, and the card the
   hub band on index.html reuses.

   Loaded by insights.html and insights-article.html. content-hub.css loads it
   on index.html for .pcard alone, so a note card is one design wherever it is
   found. Nothing here is declared that base.css already declares: the colours,
   the spacing steps, the radii, the elevations and every button are its.

   ART DIRECTION, since it is the one thing here that is a decision rather than
   a reuse. A blog for an agency network is, by default, a page of stock
   photographs of meetings. This one is a page of MAPS: each note is headed by
   the relief cut of the country it reports on, already on disk for the profile
   page, laid under its own market's ramp colour. It costs nothing, it cannot be
   bought by a competitor, it makes the market the subject of every image, and
   it is the same material the hero plate is made of, so the blog reads as part
   of the site rather than a WordPress theme bolted to the side of it.

   The tint is the CITY'S OWN colour, carried in as --ac. That value already
   paints the member's tile, the panel accent and the map pin, so Tokyo is one
   colour everywhere on this site including here.
   ========================================================================== */


/* ==========================================================================
   01. Page chrome
   ========================================================================== */

/* The insights pages are light from the top, so the header is not the
   transparent-over-a-dark-plate bar index.html uses. It gets a ground and a
   hairline, and its CTA goes back to being the purple primary, which is what
   base.css intends on a light surface. */
/* NOT STICKY, because index.html's is not. Its header is position:absolute over
   the map - it passes once and scrolls away - and a reading page that pins its
   nav while the landing page lets it go reads as two different sites.

   This also retires the z-index that was load-bearing while it pinned. base.css
   gives .site-header a background and nothing else, and immersive-hero.css - the
   sheet index gets its z-index from - is deliberately not loaded here, so a
   STICKY header sat at z-index auto and the note images painted straight over
   it, because mix-blend-mode opens a stacking context. In normal flow the header
   and the content never share space, so there is nothing left to lose to. The
   bug is gone with the position rather than fixed. */
.ins .site-header{
  background:var(--white);
  border-bottom:1px solid var(--line);
}
.ins .site-header .wrap{display:flex;align-items:center;gap:var(--s6)}

/* .ins-nav has moved to base.css - see "The section nav" there. It is on
   profile.html now, which does not load this sheet, so it could no longer live
   in the insights bundle. The name is kept because docs/brief.md and the header
   comments on all six pages refer to it. */


/* --- The contained bar --------------------------------------------------

   index.html's header is a contained pill over the map, and its own CSS gives
   the reason to borrow the geometry: "a wordmark pinned to one edge and an
   action pinned to the other, with eleven hundred pixels of nothing between
   them, reads as unfinished rather than restrained. Inside a frame the same
   emptiness is composed." True here too.

   What is NOT borrowed is the colour, and that is settled rather than chosen:
   the dark pill exists because a full-bleed dark map has to run to the top edge
   and a solid bar would cut the stage off. These pages have no stage.

   There was briefly a second state - flat and full-bleed once pinned - which
   existed only because this header used to be sticky. It is not, so there is
   one state and no scroll machinery behind it.

   901px, the same breakpoint index uses, and for the same reason: below it the
   viewport is too narrow for a contained bar to read as contained. */
@media (min-width:901px){
  .ins .site-header{
    padding-top:var(--s5);
    background:transparent;
    border-bottom:0;
    /* The margin either side of the pill is page, not header. */
    pointer-events:none;
  }
  .ins .site-header .wrap{
    pointer-events:auto;
    background:var(--white);
    /* Fully round at 72 tall, exactly as index reasons it: the action inside is
       43 and sits 14 clear, and concentric corners want outer = inner + gap. */
    border-radius:999px;
    border:1px solid rgb(58 35 100 / .10);
    /* index's shadow, lifted off a dark stage onto a light one: same geometry,
       a third of the opacity, and tinted plum rather than black so it reads as
       depth rather than dirt. */
    box-shadow:0 18px 44px -30px rgb(28 16 54 / .45);
  }
}


/* ==========================================================================
   02. Masthead
   ========================================================================== */

/* ASYMMETRIC, and this is the stated reason the rule in base.css asks for. A
   masthead has no section above it to be separated from - its top padding is
   clearance from the header, which is section-tier work, while its bottom is the
   gap to its own first content block, which is component-tier work. Two
   different jobs, so two different scales. */
.ins-mast{padding:var(--sec) 0 0}
.ins-mast .wrap{padding-top:0;padding-bottom:var(--s10)}
.ins-mast .eyebrow{margin-bottom:var(--s4)}
/* Capped in characters rather than pixels: the line break in the markup is the
   one the display size wants, and a pixel cap would fight it at some widths. */
.ins-mast h1{max-width:18ch}
.ins-mast-deck{
  margin-top:var(--s6);max-width:58ch;
  color:var(--gray);font-size:19px;line-height:29px;
}


/* ==========================================================================
   03. The lead
   One post at full width. Image left, everything else right, which is the
   arrangement a reader scanning a blog index already expects and the one that
   lets the deck run at reading size instead of card size.
   ========================================================================== */

.ins-lead-sec .wrap{padding-bottom:var(--sec)}

.ins-lead{
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
  gap:var(--s10);align-items:center;
  text-decoration:none;
  transition:transform 220ms cubic-bezier(.2,.7,.3,1);
}
.ins-lead:hover{transform:translateY(-2px)}

.ins-lead-media{
  position:relative;display:block;overflow:hidden;
  border-radius:var(--r-lg);aspect-ratio:16/10;
}
.ins-lead-media img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 600ms cubic-bezier(.2,.7,.3,1);
}
.ins-lead:hover .ins-lead-media img{transform:scale(1.03)}

.ins-lead-body{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s4)}
.ins-lead-t{
  color:var(--black);font-size:clamp(28px,2.9vw,40px);font-weight:500;line-height:1.2;
  text-wrap:balance;
}
.ins-lead:hover .ins-lead-t{color:var(--plum)}
.ins-lead-dek{color:var(--gray);font-size:18px;line-height:28px;max-width:46ch}
.ins-lead-go{
  margin-top:var(--s2);
  color:var(--purple);font-size:16px;font-weight:500;
  transition:color 180ms ease-in-out;
}
.ins-lead:hover .ins-lead-go{color:var(--purple-deep)}

@media (max-width:900px){
  .ins-lead{grid-template-columns:1fr;gap:var(--s6)}
  .ins-lead-media{aspect-ratio:16/9}
}


/* ==========================================================================
   04. Controls
   The same two-part split .dir-controls makes: what is in the set on the left,
   which market on the right, the result of both reported underneath.
   ========================================================================== */

/* NOT STICKY. It was, and the reason it was is gone: the applied-filter row
   pinned with it, and that row's whole job was answering "why am I seeing three
   notes" from wherever the reader had scrolled to. With the row removed the bar
   is four controls the reader sets once, and pinning four controls to the top of
   every screen spends 86px of every viewport on something already used.

   Removing it also takes the machinery with it - the measured --hdr-h, the
   font-load re-measure and the scroll listener existed only to position a bar
   that no longer moves. */
/* NO RULES ABOVE OR BELOW. The bar used to be fenced by two --line hairlines,
   which is base.css's stated failure mode written out on this page: a border
   between two blocks reads as a rule across the page, not as a separator, and
   the top one sat a few pixels under .ins-mast's own hairline so the eye got two
   parallel lines doing one job.

   THE PADDING HAD TO CHANGE WITH THEM, because the bottom border was the only
   thing holding the pills off the first card row - at --s2 there were 16px
   between a filter control and a photograph. --s8 below, plus .ins-grid-sec's
   own --s2, is 40px of clear space, which separates the two without drawing
   anything. Nothing is needed above: .ins-lead-sec already closes on a full
   --sec. */
.ins-controls-sec .wrap{padding-top:0;padding-bottom:var(--s8)}
.ins-controls{display:flex;align-items:center;gap:var(--s6);flex-wrap:wrap}

/* The chip row and the market <select> that lived here were replaced by the
   toolbar in filter-bar.css - three pill dropdowns, a search field, a count and
   a sort, plus a row of dismissible applied filters. The chips were fine at one
   filter axis and did not survive three: six chips plus ten markets plus eleven
   agencies is fifty-odd controls on a page holding thirteen notes. */

/* ==========================================================================
   05. The note card
   Shared with index.html's hub band. Changing anything here changes both.
   ========================================================================== */

.ins-grid-sec .wrap{padding-top:var(--s2);padding-bottom:var(--sec)}

/* 380, and every digit of it is measured. At the original 320 the 1400 wrap fits
   FOUR tracks and two things broke: 20px titles ran to four lines, and
   .pcard-foot could no longer hold a long member name beside the date, so the
   meta wrapped on SOME cards and not others and the row of card feet came out
   ragged.

   The floor is set by the longest byline in the set. "M2.0 Communications" at
   13px/500 is about 132px; add the 32px tile, two 8px gaps, roughly 128px of
   date and read time, and 48px of card padding and the foot needs a 356px
   track. 360 cleared that at 1440 and failed at 1180, where auto-fill was still
   printing three tracks at 361 and that one card wrapped alone. 380 makes the
   break honest: three tracks down to a 1236px viewport, two below it, and the
   narrowest track anywhere is 380 against a 356 requirement. Below 520 the foot
   stacks on purpose - see the rule at the foot of this block. */
.ins-grid{
  display:grid;gap:var(--s6);
  grid-template-columns:repeat(auto-fill,minmax(380px,1fr));
}

.pcard{
  display:flex;flex-direction:column;
  /* Filled on the same grey the member cards use, for the same reason recorded
     there: a page of outlined boxes draws the grid before it draws the notes. */
  background:var(--haze);border-radius:var(--r-lg);overflow:hidden;
  text-decoration:none;
  transition:background-color 200ms ease-in-out,box-shadow 200ms ease-in-out,
             transform 200ms cubic-bezier(.2,.7,.3,1);
}
.pcard:hover,.pcard:focus-visible{
  background:var(--mist);box-shadow:var(--e-high);transform:translateY(-2px);
}

/* --- the images, untreated -----------------------------------------------

   THE DUOTONE IS GONE (client direction, 2026-08-31), and this note is what was
   here so nobody re-derives it from scratch. The treatment was: a gradient
   ground per market running that market's --ac down into --plum, the photograph
   laid over it in mix-blend-mode:luminosity so it contributed LIGHTNESS ONLY,
   and a hover bloom that swapped the far stop toward the electric end. Every
   colour on a card came from that gradient - the photographs were never in
   colour at all, which is why turning the purple down had to be done to the
   ground and not to the image.

   THREE THINGS WENT WITH IT, because none of them does anything without the
   blend and leaving them would be three pieces of machinery with no mechanism:

     isolation:isolate   existed so the blend resolved against THIS box's ground
                         rather than whatever happened to be painted beneath it.
     the ::before bloom  painted at z-index -1, UNDER the image, which is where
                         it had to be for a luminosity blend to see it. With an
                         opaque image above it, it would never be seen again.
     grayscale(1)        was belt-and-braces on a blend that was already
                         discarding chroma.

   WHAT IT COSTS, recorded because it was the whole argument for the duotone:
   the longitude ramp is no longer visible on these cards. data.js still assigns
   c.color west to east and --ac still colours the kicker, the tags, the reading
   bar and the article's accents - a market's place on the ramp is still on the
   page, it is just not the photograph any more. Cards also no longer share one
   palette, so the grid is as consistent as the photography is.

   THE GROUND STAYS, AS A PLACEHOLDER ONLY. --haze, the same grey .pcard already
   fills with, so a card whose photograph has not decoded yet is a grey plate
   rather than a white hole in the grid. An opaque image covers it the moment
   one arrives. */
.pcard-media,
.ins-lead-media,
.ins-art-media,
.hub-row-media{
  background:var(--haze);
}

.pcard-media{
  position:relative;display:block;overflow:hidden;
  aspect-ratio:16/10;
}
.pcard-media img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 600ms cubic-bezier(.2,.7,.3,1);
}
.pcard:hover .pcard-media img{transform:scale(1.04)}

/* The scrim, and only the scrim. Bottom-up, so the market label has a ground at
   any crop and the top three quarters of the image are left alone. */
.pcard-tint{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0) 52%);
}

/* The market, set in the mono face the site keeps for coordinates and offsets.
   It is a label on a map, not a caption on a photograph. */
.pcard-place{
  position:absolute;left:var(--s5);bottom:var(--s4);
  color:var(--white);font-family:var(--mono);font-size:12px;
  letter-spacing:.16em;text-transform:uppercase;
  text-shadow:0 1px 6px rgba(0,0,0,.5);
}

.pcard-body{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s6);flex:1}
.pcard-kicker{
  color:var(--gray);font-size:11px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;
}
.pcard-t{
  color:var(--black);font-size:20px;font-weight:500;line-height:27px;
  text-wrap:balance;
  transition:color 180ms ease-in-out;
}
.pcard:hover .pcard-t{color:var(--plum)}
.pcard-dek{
  color:var(--gray);font-size:15px;line-height:23px;
  /* Three lines, then it stops. The deks run to different lengths and a ragged
     row of card feet is the one thing a grid of twelve cannot hide. */
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.pcard-foot{
  display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  margin-top:auto;padding-top:var(--s4);border-top:1px solid var(--line);
}
.pcard-by{color:var(--slate);font-size:13px;font-weight:500}
.pcard-meta{
  margin-left:auto;color:var(--ash);font-size:12px;white-space:nowrap;
}
/* The tile is white against the card's grey, the same correction .member-card
   makes to its tags for the same reason. */
.pcard .tile{flex:none}

@media (max-width:520px){
  .ins-grid{grid-template-columns:1fr}
  .pcard-meta{margin-left:0;width:100%}
}

/* Wide variant: used by the hub band's lead only. */
.pcard-wide .pcard-media{aspect-ratio:16/9}


/* --- show more ----------------------------------------------------------- */
.ins-more-row{display:flex;justify-content:center;margin-top:var(--s10)}
/* Hidden rather than disabled when the set is exhausted: a permanently greyed
   button at the foot of a page reads as something broken. */
.ins-more-row .btn[hidden]{display:none}


/* ==========================================================================
   06. The listing's closer
   It is base.css's .closer, not a copy of it. The grey box, the radius, the
   padding, the centring and the deck's measure all arrive from the one
   declaration index.html's closer already uses, so the two conversion moments
   on this site cannot drift apart. Three things differ and only three:

   1. The band needs its own top padding. base.css sets .closer .wrap's to zero
      because on index.html the directory's own 48px is the single gap above the
      box; here the section above is the grid, and its padding-bottom is doing
      the same job - so this is a no-op that is written down rather than left to
      be rediscovered.
   2. A longer headline. base.css caps .closer h2 at 16ch for "Eleven agencies.
      One conversation."; this one is a sentence and 16ch stacks it seven lines
      deep.
   3. Two actions instead of one, so they need a row.

   NO PALE GROUND. It had one and it was wrong for a reason base.css already
   states at .closer-box: the metrics band is the site's single branded surface
   and a second tinted block halves its weight.
   ========================================================================== */

.ins-closer h2{max-width:26ch}

/* The buttons are siblings in a row, so base.css's .closer .btn margin would
   apply to both and push the row twice. The gap moves to the row.

   --s8, MATCHING base.css's .closer .btn EXACTLY. It was --s7, which meant the
   gap above a closer's action was 28px when the actions were a row and 32px when
   there was one button - two values for one measurement, decided in two sheets,
   and neither of them wrong on its own. base.css argues its 32 out loud beside
   the rule ("a larger button needs the gap above it to grow"); this had no
   argument, so this is the one that moved.

   IT IS ALSO WHY THIS ROW IS WORTH WEARING FOR A SINGLE BUTTON. A bare
   inline-block pill sits in an anonymous line box and carries the strut's
   descender under it - about 7px of space that belongs to no rule and answers to
   nothing. A flex container has no strut, so the gap under the button is the
   gap that was specified. tools.html's closer has one button and uses this. */
.closer-acts{
  display:flex;gap:var(--s4);justify-content:center;flex-wrap:wrap;
  margin-top:var(--s8);
}
.closer-acts .btn{margin-top:0}


/* ==========================================================================
   07. The reader
   ========================================================================== */

/* One hairline in the market's colour, pinned to the top of the viewport.
   Painted with a transform so the compositor owns it, and the script does not
   attach at all under prefers-reduced-motion.

   IT PINS AND THE HEADER DOES NOT, which is the opposite of where it started.
   It was a sibling below a sticky header and lost to it - both pinned to the
   same line and the header, at z-index 100 against its 99, hid it completely.
   Moving it inside the header fixed that by making it ride along. With the
   header no longer pinning, riding it would mean scrolling away after 90px,
   which is no use on an eight-minute note - so it is a sibling again, and this
   time it is the only thing at the top of the viewport and has nothing to lose
   to. The z-index is kept as insurance against a future neighbour, not because
   anything currently competes. */
.ins-progress{
  position:sticky;top:0;z-index:var(--z-header);
  height:2px;background:transparent;pointer-events:none;
}
.ins-progress span{
  display:block;height:100%;background:var(--ac,var(--purple));
  transform:scaleX(0);transform-origin:left center;
  will-change:transform;
}
/* The reading bar is a child of the header now, so it needs no z-index of its
   own and no offset - see .ins-progress. */

.ins-article{--ac:var(--purple)}
.ins-article .wrap{padding-top:var(--s10);padding-bottom:var(--sec)}

/* THE READ IS NARROWER THAN THE PAGE, and this is the rule that decides how the
   whole article scans.

   1400 is the DIRECTORY's width - it exists so three 380px cards fit a row. A
   reader has one column of prose and one 320 aside, so at 1400 the title stopped
   at 20ch, the dek at 56ch and the body at 68ch while the container ran on for
   another 500px of nothing: the header looked pinned to the left edge of a page
   built for something else.

   1080 is measured backwards from the parts, not picked. 1080 - 48 of wrap
   padding = 1032 of content; minus the 320 aside and the 48 gutter leaves a 664
   body track, and .ins-art-body's 68ch measure lands at roughly 600 inside it.
   The prose now fills its track instead of floating in it, and the header's
   ragged right is an ordinary measure rather than a void.

   THE CONTAINER IS CENTRED, THE TEXT IS NOT. Centring the header itself would
   put the title on a different axis to the body column directly beneath it,
   which is the one alignment on this page a reader actually tracks.

   THE RELATED ROW IS NOT IN THIS LIST and is not even in this article any more.
   Its three cards need 3x380 + 2x24 = 1188 and would drop to two tracks at 1032,
   orphaning the third on a row of its own. It lives outside <article> as
   .ins-relband on its own surface - see the note there. */
.ins-crumb,
.ins-art-head,
.ins-art-media,
.ins-art-cols,
.ins-art-cta{max-width:1080px;margin-inline:auto}

.ins-crumb{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s8)}
.ins-crumb a{color:var(--gray);font-size:13px;font-weight:500;text-decoration:none}
.ins-crumb a:hover{color:var(--purple-deep)}
.ins-crumb span{color:var(--line)}

 /* The title is the display size, but capped by CHARACTERS rather than a pixel
   width, so a long one holds three lines instead of running the full 1400 and
   losing the reader between the end of one line and the start of the next. The
   header itself is uncapped - the dek wants a different measure to the title
   and capping their shared parent would give them the same one. */
.ins-art-t{font-size:clamp(34px,4.2vw,54px);font-weight:500;line-height:1.16;max-width:20ch}
.ins-art-dek{margin-top:var(--s5);max-width:56ch;color:var(--gray);font-size:20px;line-height:31px}

.ins-art-meta{display:flex;align-items:center;gap:var(--s4);margin-top:var(--s8)}
.ins-art-by{display:flex;flex-direction:column;gap:2px}
.ins-art-by b{color:var(--black);font-size:16px;font-weight:500}
.ins-art-by span{color:var(--gray);font-size:14px}

.ins-art-media{
  position:relative;overflow:hidden;
  /* auto, not 0, on the inline axis: the shorthand is declared after the
     1080 centring rule above and would otherwise reset it. */
  margin:var(--s10) auto var(--s12);
  border-radius:var(--r-lg);aspect-ratio:21/9;
}
.ins-art-media img{width:100%;height:100%;object-fit:cover;display:block}
.ins-art-media .pcard-place{left:var(--s8);bottom:var(--s6);font-size:13px}

/* The column and the aside. 1080 is measured, not chosen: the body column wants
   about 68ch to hold the line length the type is set for, and the aside wants
   320 plus a 48 gutter, which is the width at which the two stop fitting. */
.ins-art-cols{
  display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:var(--s12);
  align-items:start;
}
@media (max-width:1080px){
  .ins-art-cols{grid-template-columns:1fr;gap:var(--s10)}
}

.ins-art-body{max-width:68ch}
.ins-art-body p{margin-bottom:var(--s6);color:var(--slate);font-size:18px;line-height:31px}
.ins-h2{
  margin:var(--s12) 0 var(--s5);
  font-size:26px;font-weight:500;line-height:34px;
}
.ins-art-body > .ins-h2:first-child{margin-top:0}

.ins-list{margin:0 0 var(--s6);padding-left:0;list-style:none}
.ins-list li{
  position:relative;padding-left:var(--s7);margin-bottom:var(--s4);
  color:var(--slate);font-size:18px;line-height:29px;
}
/* A rule, not a bullet. The list items here are statements rather than items in
   a set, and a short coloured rule marks them without turning the paragraph
   into a shopping list. */
.ins-list li::before{
  content:"";position:absolute;left:0;top:13px;
  width:16px;height:2px;background:var(--ac);
}

/* A TINTED PANEL, NOT A RULE. The pull quote was a 3px --ac border-left with the
   text hung off it, which is the default every CMS ships and which does two
   things badly here: on a 600px measure the rule reads as a nested list marker
   rather than a change of voice - .ins-list li::before is already a short --ac
   rule three paragraphs up - and it gives the quote no ground of its own, so a
   three-line quote sits at exactly the weight of the body copy beside it.

   The tint is mixed FROM --ac rather than taken from --pale, because --ac is the
   market's colour and changes per article; --pale is purple and would be the
   wrong hue on every non-purple market. 6% is the strength at which the panel is
   visible against --surface and still lets --black hold its contrast - anything
   past about 10 and the quote starts competing with the 21:9 plate above it.
   --haze first as the fallback ground: neutral, so a browser without color-mix
   gets a quiet grey panel rather than a wrong-coloured one.

   The inline padding is --s8, one step wider than the block padding, so the
   quote's measure sits inside the paragraphs' measure and the indent does the
   work the border used to. */
.ins-quote{
  margin:var(--s10) 0;
  padding:var(--s7) var(--s8);
  background:var(--haze);
  background:color-mix(in srgb,var(--ac) 6%,var(--surface));
  border-radius:var(--r-lg);
}
.ins-quote blockquote{
  margin:0;color:var(--black);font-size:22px;font-weight:400;line-height:34px;
}
.ins-quote figcaption{
  margin-top:var(--s4);color:var(--gray);font-size:13px;font-weight:500;
  letter-spacing:.08em;text-transform:uppercase;
}

.ins-art-tags{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s10)}

/* --- the aside ----------------------------------------------------------- */
.ins-art-aside{position:sticky;top:calc(var(--s14) + var(--s6))}
@media (max-width:1080px){
  .ins-art-aside{position:static}
}
.ins-aside-card{
  background:var(--haze);border-radius:var(--r-lg);padding:var(--s6);
}
.ins-aside-id{
  display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  column-gap:var(--s4);align-items:center;
  margin-top:var(--s4);text-decoration:none;
}
.ins-aside-id .tile{grid-row:1 / span 2}
.ins-aside-id b{color:var(--black);font-size:17px;font-weight:500;line-height:23px}
.ins-aside-id span{color:var(--gray);font-size:14px}
.ins-aside-id:hover b{color:var(--purple-deep)}
.ins-aside-p{margin-top:var(--s4);color:var(--gray);font-size:15px;line-height:23px}
.ins-aside-acts{display:flex;flex-direction:column;gap:var(--s3);margin-top:var(--s6)}
.ins-aside-acts .btn{text-align:center}
/* .ins-aside-note is gone with the markup that used it - the product line it
   styled now closes the article. See the comment in insights-article.js. */

/* AT 1080 THE ASIDE STOPS BEING AN ASIDE. .ins-art-cols collapses to one column
   here, so the sticky card unpins and lands directly above the closer - two
   boxes, one under the other, carrying the identical primary button. The card
   keeps its identity block and its profile link, which is all it is doing at
   this width; the ask belongs to the closer eight pixels below it. */
@media (max-width:1080px){
  .ins-aside-acts .btn-primary{display:none}
}

/* --- the closer ----------------------------------------------------------

   DARK, and that is the only reason it works this far down the page. The read
   above it is white, the aside card is --haze and the pull quote is a 6% --ac
   tint - a fourth light panel would be the weakest thing on screen at the exact
   point the page is asking for something. --ink gives it the weight, and the
   related row underneath keeps it from touching the dark footer, so the page
   reads light / dark / light / dark rather than closing on one long slab.

   --sec-sm block padding, not --sec: this belongs to the article it closes, and
   the section scale's own note says that is what --sec-sm is for. */
.ins-art-cta{
  margin-top:var(--s14);
  padding:var(--sec-sm) var(--s10);
  background:var(--ink);border-radius:var(--r-lg);
}
.ins-art-cta h2{color:var(--white);max-width:20ch;text-wrap:balance}
.ins-cta-p{
  margin-top:var(--s5);max-width:52ch;
  color:var(--lavender);font-size:17px;line-height:27px;
}
.ins-cta-acts{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:var(--s8)}
@media (max-width:600px){
  .ins-art-cta{padding:var(--sec-sm) var(--s6)}
  .ins-cta-acts .btn{flex:1 1 100%;text-align:center}
}

/* --- related -------------------------------------------------------------

   A BAND, NOT THE LAST BLOCK OF THE ARTICLE. It used to be a hairline border-top
   inside the article at the full 1400 while everything above it was centred at
   1080, on the same white ground - so the two edges missed each other by 160px a
   side and it read as a misalignment rather than a wider section.

   The width itself is not negotiable and that is worth stating, because the
   obvious fix is to squeeze the row into 1080 and it does not work: .ins-grid's
   380 floor is MEASURED - the card foot needs 356 to hold the longest byline in
   the set beside the date, and three tracks plus two 24 gutters therefore need
   1188 of content. The reader has 1032. Three cards at 328 would wrap the foot
   on the long-name cards and not the short ones, which is the exact failure the
   note on .ins-grid was written about.

   So the band keeps 1400 and earns it with its own ground instead. --surface-alt
   against the article's --surface, which is the site's stated separator, and the
   hairline goes with it - base.css's note is explicit that a surface change
   makes a border redundant. The page now closes white read / dark closer /
   offwhite band / dark footer.

   PANELS INVERT, per base.css: .pcard is --haze on --surface and takes --white
   here. Hover stays --mist, which still separates from either ground. */
.ins-relband{background:var(--surface-alt);padding:var(--sec) 0}
.ins-relband h2{margin-bottom:var(--s7)}
.ins-relband .pcard{background:var(--white)}

/* --- not found -----------------------------------------------------------
   A 404 is the one state on these pages with no content to push the footer
   down, so the page has to do it itself: body becomes a column, main takes
   the slack, and the footer sits on the fold instead of floating mid-screen.
   js/case.js and js/insights-article.js add .is-404 when they render this
   state; 404.html carries it in the markup, because there it is the whole
   point of the file and a class arriving after first paint would let the
   footer land mid-screen for a frame. */
.ins-404{max-width:48ch;margin:var(--s14) auto;padding:0 var(--s6);text-align:center}
.ins-404 .eyebrow{margin-bottom:var(--s4)}
.ins-404 .lede{margin:var(--s5) 0 var(--s8)}

body.is-404{min-height:100vh;min-height:100dvh;display:flex;flex-direction:column}
/* padding, not margin on the block: main centres its child, so margin only
   fights the centring. The padding is a floor - when the viewport is tall the
   block still sits in the middle of the gap, and when it is short the button
   stops short of the footer's purple edge instead of kissing it. */
body.is-404 > main{
  flex:1 0 auto;display:flex;align-items:center;justify-content:center;
  padding-block:var(--s8);
}
body.is-404 > main > .ins-relband{display:none}
body.is-404 .ins-progress{display:none}
/* main centres it, so the block's own vertical margin only fights the
   centring and pushes the tall footer off the fold. */
body.is-404 .ins-404{margin-block:0}
body.is-404 .site-footer{flex:0 0 auto}


/* ==========================================================================
   08. Motion contract
   The same one both existing pages keep: everything above is a transition or a
   transform, and every one of them is cancelled here rather than being made
   shorter. The reading bar's script checks the same query and does not attach.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  .ins *,.ins *::before,.ins *::after{
    transition-duration:1ms!important;
    animation-duration:1ms!important;
  }
  .pcard:hover,.ins-lead:hover{transform:none}
  .pcard:hover .pcard-media img,
  .ins-lead:hover .ins-lead-media img{transform:none}
  /* The bloom stays. It is a colour change with no movement in it, which is what
     this query asks to keep rather than remove - and dropping it would leave
     these cards with no hover feedback at all once the scale is gone. */
}


/* ==========================================================================
   CASE STUDIES IN THE FEED
   Added when case studies joined the notes listing. One rule: the kicker says
   which of the two kinds of thing the card is, because the card is otherwise
   deliberately identical - same photo, same tint, same city, same byline. They
   belong in one grid, and the reader still has to be able to tell analysis from
   client work before clicking rather than after.

   --d-b2b, not the card's own --ac. Every other element on the card is tinted
   by the member's city colour, so a label tinted the same way would read as
   more of that and disappear. One colour, the same on all 26, is what makes it
   a category rather than a decoration.
   ========================================================================== */
.pcard-kicker-case{color:var(--d-b2b);font-weight:600}
