/* AMIN APAC — writing.css
   ============================================================================
   The Writing panel in the workspace, and the "Writing from" block on a member
   profile. Two surfaces, one sheet, because they are one feature and splitting
   them would mean remembering that both exist the next time either changes.

   BORROWS RATHER THAN INVENTS. Spacing is the --s scale, colour is the base
   palette, and the save bar, the buttons and the panel headings are the ones
   workspace.css and dashboard.css already define - this sheet only supplies the
   parts that are genuinely new: the post list, the block editor, and the card
   grid on the profile. Nothing here restyles a component that already exists.

   The one colour decision: a published post is GREEN and a draft is AMBER, and
   the amber is --d-media, the same yellow profile-draft.js uses for its "you
   are seeing unsaved edits" bar. Draft means the same thing on both surfaces,
   so it should not be two different colours.
   ============================================================================ */

/* ==========================================================================
   THE LIST
   ========================================================================== */
.wr-listbar{
  display:flex;flex-wrap:wrap;gap:var(--s4);align-items:center;
  margin-bottom:var(--s7);
}
.wr-count{color:var(--ash);font-size:14px;line-height:20px}

.wr-empty{
  margin:0;padding:var(--s8);max-width:62ch;
  border:1px dashed var(--line);border-radius:12px;
  background:var(--offwhite);
  color:var(--gray);font-size:16px;line-height:25px;
}

.wr-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s3)}

.wr-row{
  display:flex;flex-wrap:wrap;gap:var(--s4);align-items:center;
  justify-content:space-between;
  padding:var(--s5);
  border:1px solid var(--line);border-radius:12px;
  background:var(--white);
}
.wr-row:hover{border-color:var(--lavender)}

.wr-row-main{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);align-items:baseline;min-width:0}
.wr-row-t{
  font-size:17px;font-weight:500;line-height:25px;color:var(--slate);
  /* The title is the only thing here that can be arbitrarily long. Wrapping it
     rather than truncating: a workspace list of nine posts is not a table, and
     an author who cannot read their own headline cannot find the post. */
  flex:1 1 20rem;min-width:0;
}
.wr-row-meta{color:var(--ash);font-size:13px;line-height:20px;flex:0 0 100%}
.wr-row-acts{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}

/* PILLS, NOT THE UNDERLINE WIPE. .btn-ghost inherits .u-line's hover from
   base.css - a currentColor gradient that grows from 0% to 100% width, which
   reads as a rule drawn under the word. That is right for a link inside a
   sentence, which is what .u-line was written for, and wrong for four controls
   sitting in a row at the end of a card: four underlines appearing one after
   another as the cursor crosses them looks like the row is being struck
   through.

   background-image:none is what removes it - the wipe IS a background image,
   so base.css's :hover rule can go on setting background-size and change
   nothing. The pill that replaces it is the same hover the tab switcher uses
   (--pale ground, --plum text), so the page keeps one hover language instead
   of growing a second. */
.wr-row-acts .btn-ghost,
.wr-savebar .btn-ghost{
  background-image:none;
  border-radius:var(--r-pill);
  padding:6px 12px;font-size:14px;
  transition:background-color 160ms var(--ease),color 160ms var(--ease);
}
.wr-row-acts .btn-ghost:hover,
.wr-row-acts .btn-ghost:focus-visible,
.wr-savebar .btn-ghost:hover,
.wr-savebar .btn-ghost:focus-visible{
  background-color:var(--pale);color:var(--plum);
}

/* Destructive, and it should look it - but only on approach. A permanently red
   Delete beside three neutral buttons reads as a warning about the row rather
   than a label on one action. Listed after the pill rule so its red ground wins
   at equal specificity. */
.wr-row-acts .wr-del:hover,
.wr-row-acts .wr-del:focus-visible,
.wr-savebar .wr-del:hover,
.wr-savebar .wr-del:focus-visible{color:var(--red-ink);background-color:var(--red-bg)}

.wr-pill{
  flex:0 0 auto;
  padding:3px 9px;border-radius:999px;
  font-size:11px;font-weight:600;line-height:16px;
  letter-spacing:.06em;text-transform:uppercase;
}
.wr-pill-live{background:#E7F5EB;color:#12633A}
.wr-pill-draft{background:#FDF2DA;color:#7A5406}

/* ==========================================================================
   THE EDITOR
   ========================================================================== */
.wr-edhead{
  display:flex;gap:var(--s4);align-items:center;justify-content:space-between;
  margin-bottom:var(--s7);padding-bottom:var(--s4);
  border-bottom:1px solid var(--line);
}

.wr-fields{display:flex;flex-direction:column;gap:var(--s6);max-width:48rem}
.wr-f{display:flex;flex-direction:column;gap:var(--s2)}
.wr-f2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s6)}

.wr-l{font-size:14px;font-weight:500;line-height:20px;color:var(--slate)}
.wr-note{color:var(--ash);font-size:13px;line-height:19px;max-width:56ch}

.wr-fields input,
.wr-fields select,
.wr-fields textarea,
.wr-block textarea,
.wr-block input{
  width:100%;padding:10px 12px;
  border:1px solid var(--line);border-radius:8px;
  background:var(--white);color:var(--slate);
  font:400 15px/23px var(--font,system-ui);
}
.wr-fields textarea,.wr-block textarea{resize:vertical}
.wr-fields input:focus-visible,
.wr-fields select:focus-visible,
.wr-fields textarea:focus-visible,
.wr-block textarea:focus-visible,
.wr-block input:focus-visible{
  outline:2px solid var(--purple-deep);outline-offset:1px;border-color:var(--purple-deep);
}

#wrTitle{font-size:20px;line-height:29px;font-weight:500}

.wr-h{
  margin:var(--s12) 0 var(--s5);
  font-size:12px;font-weight:600;line-height:18px;
  letter-spacing:.08em;text-transform:uppercase;color:var(--ash);
}

/* ---------- blocks ----------
   Each block is a card so the article's structure is visible as structure.

   NO TINTED LEFT EDGE. It was a 3px --lavender rule, on the argument that it
   let you skim the column for headings - but the type is already NAMED at the
   top of every card, in caps, which does that job in words. The stripe was a
   second answer to a question the label had already answered, and a row of
   them read as decoration on a form. */
.wr-blocks{display:flex;flex-direction:column;gap:var(--s3);max-width:48rem}

.wr-block{
  padding:var(--s4);
  border:1px solid var(--line);
  border-radius:10px;background:var(--white);
}
.wr-block:focus-within{border-color:var(--purple-deep);background:var(--offwhite)}

.wr-block-head{
  display:flex;gap:var(--s3);align-items:center;justify-content:space-between;
  margin-bottom:var(--s2);
}
.wr-block-t{
  font-size:11px;font-weight:600;line-height:16px;
  letter-spacing:.07em;text-transform:uppercase;color:var(--ash);
}
.wr-block-acts{display:flex;gap:var(--s1)}
.wr-block-acts button{
  width:26px;height:26px;padding:0;
  border:1px solid var(--line);border-radius:6px;
  background:var(--white);color:var(--gray);
  font-size:13px;line-height:1;cursor:pointer;
}
.wr-block-acts button:hover:not(:disabled){background:var(--pale);border-color:var(--lavender);color:var(--plum)}
.wr-block-acts button:disabled{opacity:.35;cursor:default}
.wr-block-acts button:focus-visible{outline:2px solid var(--purple-deep);outline-offset:1px}

.wr-block .wr-note{margin-top:var(--s2)}
.wr-block input[data-f="who"]{margin-top:var(--s2);font-size:14px}

.wr-add{
  display:flex;flex-wrap:wrap;gap:var(--s2);
  margin-top:var(--s4);max-width:48rem;
}
.wr-add .btn{padding:7px 14px;font-size:14px}

.wr-savebar{max-width:48rem}
.wr-saved{color:#12633A;font-size:14px;line-height:20px}
.wr-read{margin-left:auto;color:var(--ash);font-size:13px;line-height:20px}

@media (max-width:720px){
  .wr-f2{grid-template-columns:1fr}
  .wr-row-acts{width:100%}
  .wr-read{margin-left:0;flex:0 0 100%}
}

/* ==========================================================================
   THE PROFILE BLOCK
   Cards are postCardHTML's, so insights.css is doing the work here. This only
   supplies the grid they sit in - three across on a wide profile column, one
   across on a narrow one.
   ========================================================================== */
/* auto-FILL, NOT auto-FIT, and the one letter is the whole bug.

   auto-fit COLLAPSES the tracks it cannot fill and hands their space to the
   survivors. With minmax(15rem, 1fr) as the track, that meant a grid holding
   ONE card gave that card the entire profile column: a 976px card 843px
   tall, 610px of it photograph, against the 435px the identical card is on insights.html. Nine of
   the eleven members had exactly one field note, so nine profiles rendered it
   that way, and it read as a feature rather than as a fault.

   auto-fill KEEPS the empty tracks. One card, three cards or five all render at
   the track width the container actually supports - 312px in a 976px column,
   328 in a 676 one - so the card is the same size on every profile regardless
   of how much the agency has published. A short last row is then just a short
   last row, which is what a listing is supposed to look like.

   TWO GRIDS USE THIS. The field notes block under the profile column, which is
   capped at three by member-profile.js, and the case study cards that
   member-cases.js puts at the head of the work section, which is however many
   the agency has. One rule serves both because they are the same card doing the
   same job, and the only difference between them - a fixed three against an
   open-ended set - is exactly the difference auto-fill absorbs.

   min() on the floor so a card is never wider than its container on a narrow
   screen, which is the one case a bare 15rem minimum overflows.

   ------------------------------------------------------------------------
   AND THE FLOOR IS NOW A THIRD OF THE CONTAINER, NOT A FLAT 15rem (client
   direction, 2026-09-02). Everything above still holds; this only stops
   auto-fill from making tracks nobody asked for.

   THE FAULT A FLAT FLOOR HAS: the number of tracks grows with the container,
   so the cards get NARROWER as the page gets wider. Measured on
   profile-v2.html, where the profile column is full width:

     container 1352  ->  5 tracks x 254px, 3 cards, 549px of reserved empty grid
     container  976  ->  3 tracks x 312px, 3 cards, fills

   Three cards sitting in the left 60% of the section with the work grid
   directly beneath them running the full width - two measures, one section.
   That is what this fixes.

   max(240px, (100% - 2 gaps)/3) makes a track at least a third of the row, so
   auto-fill can never fit a fourth, and the 240px arm takes over on a narrow
   container where a third would be too thin - 2 tracks, then 1, with no media
   query and no viewport assumption. It is the CONTAINER that decides, which
   matters because this grid sits in a full-width column on profile-v2.html and
   a ~1000px one beside the sidebar on profile.html.

   THE ONE-CARD CASE IS STILL SAFE, which is the whole reason auto-fill is here:
   the two empty tracks are still kept, so a single field note renders at one
   third - 437px in a 1352 column, against the 435px the identical card is on
   insights.html. That number is not a coincidence, it is the same card at the
   same size, which is what the note above was asking for. */
/* GAP --s10, tracking insights.css. These are the same .pcard at the same size
   and the card lost its fill there, so the gutter has to do the separating on
   both pages or the same three cards read as one table here and as three cards
   there. The calc has to move with it - it derives the track from the gap, and
   leaving it at --s5 would have printed three tracks that no longer fit. */
.mp-posts{
  display:grid;gap:var(--s10);
  grid-template-columns:repeat(
    auto-fill,
    minmax(max(min(15rem,100%), calc((100% - (2 * var(--s10))) / 3)), 1fr)
  );
}
.mp-writing .source-note{margin-top:var(--s5)}

/* ==========================================================================
   THE CASE STUDY PICKER
   js/dashboard-cases.js only. Everything else in that editor reuses the .wr-*
   set above verbatim - two editors in one workspace that look like two
   different products is worse than one shared set of form styles.

   THE SELECTION IS ORDERED, AND THE ORDER IS THE FEATURE: the first image
   picked is the tile on the public profile that links to the case study. So
   the badge says "Tile" rather than "1" - a number would tell the agency the
   order matters without telling them what it decides.
   ========================================================================== */
.cs-pick-note{max-width:56ch;margin-bottom:var(--s4)}
.cs-pick-note b{color:var(--slate);font-weight:600}

.cs-picker{
  display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  max-width:48rem;
}
.cs-pick{
  position:relative;display:block;padding:0;
  background:var(--offwhite);border:1px solid var(--line);border-radius:var(--r-md);
  overflow:hidden;cursor:pointer;text-align:left;
  transition:border-color 160ms ease,box-shadow 160ms ease;
}
.cs-pick img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover}
/* Unpicked images sit back so the selected ones read as a set at a glance. */
.cs-pick:not(.is-on) img{opacity:.62;transition:opacity 160ms ease}
.cs-pick:hover:not(.is-on) img{opacity:.85}
.cs-pick:hover{border-color:var(--lavender)}
.cs-pick.is-on{border-color:var(--purple-deep);box-shadow:0 0 0 1px var(--purple-deep) inset}
.cs-pick:focus-visible{outline:2px solid var(--purple-deep);outline-offset:2px}

.cs-pick-n{
  position:absolute;top:var(--s2);left:var(--s2);
  min-width:22px;height:22px;padding:0 7px;
  display:none;align-items:center;justify-content:center;
  background:var(--purple-deep);color:var(--white);
  border-radius:var(--r-pill);
  font-size:11px;font-weight:600;line-height:22px;letter-spacing:.02em;
}
.cs-pick.is-on .cs-pick-n{display:flex}

/* The alt text, as the label. It is already written for every image in data.js
   and it is the only thing that tells one campaign still from another at
   150px - a grid of nine unlabelled thumbnails is a memory test. */
.cs-pick-alt{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  padding:var(--s3);
  color:var(--ash);font-size:12px;line-height:17px;
}
.cs-pick.is-on .cs-pick-alt{color:var(--slate)}

@media (prefers-reduced-motion:reduce){
  .cs-pick,.cs-pick img{transition:none}
}


/* ==========================================================================
   CASE STUDY CARDS AT THE TOP OF THE WORK SECTION
   The cards themselves are postCardHTML's and the grid is .mp-posts, shared
   with the "Writing from" block - the two are the same card and belong in the
   same grid, so neither declares its own.

   Only the space below is new. The photography strip that follows is
   subordinate to the cards: a written-up piece of work is stronger evidence
   than a picture of one, and the gap is what says so.
   ========================================================================== */
.mc-cases{margin-bottom:var(--s8)}

/* THE HEADING ROW, SHARED BY THE TWO BLOCKS THAT HAVE ONE. js/member-cases.js
   wraps the work section's h2 with "Case studies from across AMIN";
   js/member-profile.js wraps the Field notes h2 with "Everything <member> has
   published". Each block opens with both of its facts on one line: what this is,
   and that there is more of it.

   NAMED FOR THE PATTERN, NOT THE SECTION. It shipped as .mc-head, an initialism
   belonging to member-cases.js, and the second block using it would have been
   the work section's class on the writing block - the kind of name that makes a
   reader check whether the wrong stylesheet is winning. Two callers, one
   neutral name.

   align-items:end, not center. The h2 is 26/34 and the button is 14px in a 40px
   pill; centring two boxes of different heights levels their MIDDLES, which
   leaves neither baseline anywhere. Sitting them on a common bottom edge lands
   the button's label within a pixel of the heading's baseline, which is the
   alignment a reader actually sees.

   It wraps, and the button keeps its own line when it does. Below ~760px the
   heading and a 250px pill do not share a row without one of them shrinking,
   and a shrunk pill is a broken pill - white-space:nowrap on .btn means it
   would simply overflow instead.

   SPACE-BETWEEN, NOT margin-left:auto, and the difference only shows once the
   row has broken. Both push the button right while the two fit on one line;
   auto-margin then KEEPS pushing it right on the second line, leaving a lone
   pill hard against the far edge with the heading's text a screenful away to
   the left, which reads as two unrelated things. space-between places a single
   item on a wrapped line at flex-start, so the button drops to sit under the
   start of the heading it belongs to - the correct behaviour at every width
   with no breakpoint to keep in sync with the type scale. */
.blk-head{
  display:flex;align-items:end;justify-content:space-between;flex-wrap:wrap;
  gap:var(--s3) var(--s5);
  /* 24, not base.css's 16 for a bare .profile-block h2. That 16 was set for a
     heading that was text alone; this row is 40px tall because there is a pill
     in it, and a 40px object sitting 16px above a wall of cards reads as
     touching them. 24 is the smallest step that puts air under the button
     without opening a gap the heading has to reach across. */
  margin-bottom:var(--s6);
}
.blk-head h2{margin:0}

/* THE GAP BETWEEN THE TWO CARD BLOCKS, and the reason it is scoped rather than
   set on .profile-block. 56px is base.css's spacing for every profile block,
   and it was chosen for blocks that are a heading and a paragraph. These two
   are heading rows over 500px card grids, and at 56 the distance BETWEEN the
   blocks was only 3.5x the distance WITHIN one - close enough that the last row
   of case cards and the Field notes heading read as one group.

   88 = --s14 + --s8, and the pair now sits at 24 within / 88 between: a 1:3.7
   ratio, which is what makes the two headings read as two blocks rather than
   one long list with a subhead in the middle.

   :has(.blk-head) rather than #workSec, because it is the pattern that needs
   the room, not the section - the Field notes block takes the same rule, and
   only stays quiet because it is :last-child. */
.profile-block:has(.blk-head){margin-bottom:calc(var(--s14) + var(--s8))}

/* Smaller than the base .btn (16px/12-20). This is a utility inside a block,
   not a page-level action, and at full size it out-weighed the h2 beside it. */
.blk-more{font-size:14px;padding:10px 18px}


/* ==========================================================================
   THE TWO CARD GRIDS ON A MEMBER PROFILE
   Scoped to .mp-posts, which is the profile's grid and nowhere else - the
   listing uses .ins-grid and the hub band uses its own. Every rule below is an
   override of the shared .pcard in css/insights.css, and each one exists
   because a card on a MEMBER'S OWN PAGE is in a situation the listing's card
   is not: every card in sight is by the same agency, and the two grids sit one
   above the other where the listing has one.
   ========================================================================== */

/* --- 1. THE TWO BLOCKS' CARDS ARE NOW THE SAME HEIGHT ---------------------

   They were 497px and 520px, and the 23px is exactly one line of dek. Inside a
   grid row the cards already agreed - .pcard-foot has margin-top:auto and the
   row stretches - but the WORK grid and the FIELD NOTES grid are two separate
   grids, so nothing made them agree with each other. The result was two blocks
   of the same card that did not line up, which is the thing that reads as "the
   cards are different" long before anyone finds the line that differs.

   THREE LINES RESERVED, NOT TWO CLAMPED. Counted across all eleven profiles,
   59 cards: 28 deks run to two lines and 31 to three, and none is currently
   truncated. Clamping to two would cut a line off 31 of 59 - more than half the
   deks on the site's member pages, to fix an alignment problem. Reserving three
   costs 28 cards a blank line and truncates nothing.

   min-height on the DEK rather than the body, so it holds the foot down from
   above instead of stretching the card from below - the same mechanism
   .pcard-t's own two-line reserve already uses.

   A CONTAINER QUERY ON THE GRID, NOT insights.css's 840px VIEWPORT RULE, and
   copying that number was a real bug for two measured widths. 840 is where
   .ins-grid - auto-fill minmax(380px,1fr) - reaches two columns. .mp-posts is a
   different grid: its track floor is 15rem, so it reaches two columns at 500px
   of GRID width. Between the two the profile had a multi-column grid with the
   reserve switched off, and the cards went ragged again: measured 475 and 498
   side by side at 839, 448 and 476 at 700.

   500px is that grid's own threshold, derived from its track formula rather
   than observed: below 760 the track floor is a flat 240px, so a second column
   arrives at 2 x 240 + 20 of gap. Container width is also the right QUESTION -
   the reserve exists to line a card up with the card beside it, which is a fact
   about the grid's width and not the window's.

   .pcard-t's own two-line reserve moves onto the same query for the same
   reason; insights.css sets it at the 840 viewport and it was dark in the same
   band.

   IT IS A NAMED CONTAINER, and unnamed it silently did nothing. .pcard already
   declares container-type:inline-size (insights.css, for the eyebrow's stacking
   rule), so an anonymous @container inside a card resolves against the CARD -
   424px at 1440, never 500 - and both reserves stayed dark at every width with
   no error to show for it. The name skips the card and asks the grid. */
.mp-posts{container-type:inline-size;container-name:posts}
@container posts (min-width:500px){
  .mp-posts .pcard-dek{min-height:69px}   /* 3 x 23px line-height */
}

/* --- 2. THE BYLINE COMES OFF ----------------------------------------------

   The foot printed a logo tile and "M2.0 Communications" on every card. On the
   listing that is the card's most useful fact - it is how you tell whose work
   you are looking at in a grid of eleven agencies. On M2.0's own profile it is
   the answer to a question nobody is asking: the page is headed with the name,
   the hero carries the logo, and the two block headings say "Work from M2.0
   Communications" and "Field notes from M2.0 Communications" directly above.
   Printing it six more times is the name nine times on one screen.

   What survives is the date and read time, which is the one thing in that row
   the reader cannot get from anywhere else on the page. With the byline gone it
   has no reason to hang right, so the auto-margin that pushed it away from the
   name is dropped and it sits at the start of the line under the hairline.

   THE HAIRLINE STAYS. It is what separates the card's own words from its
   metadata, and it is the edge that makes a row of cards read as a row - with
   nothing but a floating date the card would end on a shrug. */
.mp-posts .pcard .tile,
.mp-posts .pcard-by{display:none}
.mp-posts .pcard-meta{margin-left:0}

/* --- 3. HIERARCHY: THE STEPS WERE EVEN WHERE THEY SHOULD BE UNEVEN --------

   .pcard-body is a flex column with a uniform 12px gap, so eyebrow-to-title and
   title-to-dek were the same distance. Even gaps make a card read as three
   separate things stacked; a card reads as ONE thing when the parts that belong
   together sit closer than the parts that do not.

   The eyebrow labels the headline, so it moves to 8px - close enough to belong
   to it. The dek is a second voice explaining the first, so it keeps 12. The
   numbers are small because the type is small; the RATIO is the point.

   The title goes to 21/28 from 20/27. It is the card's one piece of real
   content and at 20px it was five points off a 15px dek, which is not a step a
   reader feels. On the listing 20 is right - a card there is one of eighty-five
   in a scroll - but on a profile there are three, they are the page's evidence,
   and they can carry the extra point. Weight stays 500: it is the site's
   heading weight and .blk-head's h2 above is set at it, so a 600 title would
   out-weigh the heading it sits under.

   21 AND NOT 22, AND THIS WAS MEASURED RATHER THAN PICKED. The titles are
   clamped at two lines, so a size bump is paid for in ellipses. Counted across
   all 59 cards on the eleven profiles: 20/27 truncates 1, 21/28 truncates the
   same 1, 22/29 truncates 4. 22 buys one more point of hierarchy by cutting
   three more headlines that currently finish - and these are the members' own
   headlines, not ours to shorten. 21 is the whole gain for nothing.

   THE TWO-LINE RESERVE MOVES WITH THE LINE-HEIGHT. insights.css reserves 54px
   for 2 x 27; at 28 that is 56, and leaving 54 would let a two-line title in
   one card sit 2px shorter than its neighbour - reintroducing, in miniature,
   the exact raggedness rule 1 exists to remove. */
.mp-posts .pcard-body{gap:0}
.mp-posts .pcard-t{
  margin-top:var(--s2);
  font-size:21px;line-height:28px;
}
.mp-posts .pcard-dek{margin-top:var(--s3)}
/* THE CLAMP TRAVELS WITH THE RESERVE, and reserving without clamping was half
   a fix. insights.css sets .pcard-t's 2-line clamp inside its own 840px media
   query - below that the base clamp is 3 - so between 500 and 840 the profile
   was reserving 56px for a title free to grow to 84. Measured at 700: two
   columns, cards at 448 and 476, the 28px being exactly the third line. Both
   halves belong to the same question, so they sit in the same query. */
@container posts (min-width:500px){
  .mp-posts .pcard-t{-webkit-line-clamp:2;min-height:56px}   /* 2 x 28px */
}

/* THE EXTRA POINT IS GIVEN BACK ON A NARROW CARD, because there it is not free.
   The 21px gain was costed on a 424px card, where it truncates nothing. On a
   300px card - three columns at 1024 - the same point pushes 33 of 59 titles
   past two lines against 26 at 20px, so seven more headlines end in an ellipsis
   to buy hierarchy on a card that has less room for hierarchy in the first
   place.

   400px is insights.css's own narrow-card threshold, already used a few rules
   above it for the eyebrow's stacking. This query is deliberately ANONYMOUS
   where the two above are named: unnamed, it resolves against .pcard, which is
   exactly the box being asked about. */
@container (max-width:400px){
  /* The reserve follows the line-height back down: 2 x 27, not the 56 above,
     so a narrow card does not carry 2px of dead space under its title. */
  .mp-posts .pcard-t{font-size:20px;line-height:27px;min-height:54px}
}


/* ==========================================================================
   FIELD NOTES ARE A LIST, NOT A SECOND GRID OF CARDS (2026-09-02)

   THE PAGE ENDED ON THE SAME OBJECT TWICE. Measured: "Work from <member>" and
   "Field notes from <member>" were both exactly 564px, both three .pcards, both
   under a .blk-head with a purple pill whose labels rhymed - "Case studies in
   the listing" over "Field notes in the listing". 1,128px of six identical
   cards. They are the page's two DIFFERENT kinds of proof - what they made, and
   what they think - and a reader skimming the silhouette could not tell them
   apart.

   THE PICTURES WERE THE WEAKEST PART OF IT, and that is what made this cheap.
   All three note cards render the SAME FILE: manila.jpg three times on M2.0,
   auckland.jpg three times on Harper, melbourne.jpg three times on DPR - a city
   stock photograph standing in for "a post from here". The case cards above
   carry three genuinely different images of the actual work. So the block was
   spending 265px per card, three times over, on one repeated photograph, to
   look exactly like the block that had real ones.

   Dropping to a list changes the register at the end of the page, ends the
   duplication, and takes about 250px off every profile - and the only content
   lost is a photograph printed three times.

   The kicker, the headline, the dek and the date all stay: everything the card
   said in words, the row still says.

   SCOPED TO body.pf-v, WHICH profile-v2.html CARRIES AND profile.html DOES NOT.
   writing.css is loaded by both, so unscoped these rules silently restyled the
   old page's Field notes block too - measured, its card images had gone. The
   old page is not part of this change and its column is a different width; the
   same rules there are an untested layout nobody asked for. Every selector
   below carries the scope for that reason. */

/* THE PICTURE IS BACK, ON THE LEFT, AT ROW SCALE (client direction,
   2026-09-02, after the list shipped).

   It is NOT a reversal of the note above. Everything that note argues against
   still holds: two blocks of three cards was the page ending on the same
   object twice, and a 265px-tall photograph printed three times was the
   weakest part of it. What comes back is a thumbnail in a row - a different
   object at a different scale doing a different job.

   WHAT A LEFT THUMB IS FOR, AND IT IS NOT INFORMATION. At 220px it is a
   rhythm device: it gives each row a fixed left edge and a consistent height,
   which is what stops three stacked text blocks reading as one long paragraph
   - the job the hairline was doing alone. The silhouette stays a LIST, so the
   duplication the note above solved stays solved: nobody will confuse this
   block with the three-up card grid above it.

   THE REPETITION IS STILL THERE AND IT IS STILL THE REAL PROBLEM. All three
   rows are manila.jpg, and stacking them vertically is the arrangement that
   exposes sameness most - the eye compares adjacent things. Two mitigations,
   neither of them a fix: the thumb is roughly a fifth of the area the card
   image had, so the repeat costs proportionally less; and frameFor() in
   js/insights-data.js already gives rows 2 and 3 a real crop (--pz 1.75 with
   pan), so at this size the three read as three framings rather than three
   copies. The fix is still three photographs, per the note in
   js/insights-data.js: give each post a `photo`.

   --r-md, NOT --r-lg. base.css's radius token comment states the rule -
   "--r-lg for full cards, --r-md for compact rows" - and 24px on a 220px box
   is a card's corner on a row's picture. */
body.pf-v .mp-writing .pcard{
  display:grid;
  /* One clamp rather than a breakpoint. 220 at 1730 down to 96 on a phone,
     where a 96px thumb still leaves the headline about 230px and the row stays
     a row instead of becoming a card again. */
  grid-template-columns:clamp(96px, 15vw, 220px) minmax(0,1fr);
  column-gap:clamp(20px, 2.4vw, 40px);
  align-items:start;
}
body.pf-v .mp-writing .pcard-media{
  border-radius:var(--r-md);
  /* Level with the kicker, not centred on the row: the row's top edge is what
     the eye tracks down a list, and a picture floating in the middle of one
     puts a second, competing alignment beside it. */
  align-self:start;
}

body.pf-v .mp-writing .mp-posts{
  grid-template-columns:1fr;
  gap:0;
}

/* A rule per row, and one above the first. It is the list's structure - without
   it three rows of mixed type sizes read as one paragraph block - and it is the
   same hairline the card foot used to draw, moved from inside the card to
   between the rows. */
body.pf-v .mp-writing .pcard{
  border-top:1px solid var(--line);
  padding:var(--s5) 0;
}

/* THE DATE MOVES TO ITS OWN COLUMN. In the card it sat under a hairline at the
   foot, which is where a card's metadata goes; in a row that would put it below
   the dek and give every entry a fourth line for six words. Beside the headline
   it is scannable down the right edge, which is what a list of dated things
   wants. auto, not a fixed track: "21 Aug 2026 - 5 min read" sets its own width
   and every row agrees because the strings are the same shape. */
body.pf-v .mp-writing .pcard-body{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  column-gap:clamp(24px, 4vw, 72px);
  align-items:start;
  gap:0 clamp(24px, 4vw, 72px);
  padding:0;
}
body.pf-v .mp-writing .pcard-kicker,
body.pf-v .mp-writing .pcard-t,
body.pf-v .mp-writing .pcard-dek{grid-column:1}
body.pf-v .mp-writing .pcard-foot{
  grid-column:2;grid-row:1 / span 3;
  margin:0;padding:0;border-top:0;
  /* The kicker's own line, so the date sits level with the eyebrow rather than
     with the middle of the headline. */
  align-self:start;
}

/* THE CARD RESERVES ARE RELEASED. .pcard-t's two-line clamp and .pcard-dek's
   three-line min-height exist to make cards in a GRID ROW end at the same
   height - see the note further up this file. In a single column there is
   nothing beside a row to line it up with, so the reserve is pure dead space:
   it would put 69px under every dek whether the dek needs two lines or three.
   The clamp goes with it - a list has room for a third line where a card did
   not. */
body.pf-v .mp-writing .pcard-t{
  -webkit-line-clamp:3;
  min-height:0;
  margin-top:var(--s2);
}
body.pf-v .mp-writing .pcard-dek{min-height:0}

/* A MEASURE, because a full-width row has none. The card gave these a 424px
   column and the grid did the limiting; across a 1352px row the dek was running
   to about 130 characters, which is roughly twice a comfortable line and the
   reason a list of rows can read worse than the cards it replaced. base.css
   already caps .profile-block p at 66ch for the same reason - this is that rule
   reaching content it cannot select.

   The headline gets a tighter one than the dek: it is set 6px larger, so the
   same character count is a longer line, and a headline that needs 70
   characters is a sentence. */
/* CORRECTED 2026-09-02: 76ch did not buy 76 characters. `ch` is the advance of
   the "0" glyph, and this font's zero is wide - 10.32px against a ~7.5px
   average advance for running lowercase, so 1ch buys about 1.4 characters of
   prose. Measured on this page, the 76ch cap above was still letting the dek
   run to 105 characters, which is why the note above could set a cap and the
   line could still read long. 52ch is the same intent in a figure that
   measures: ~72 characters, inside the 45-75 the note was aiming at. .pcard-t
   keeps a proportionally tighter one for the reason its own note gives. */
body.pf-v .mp-writing .pcard-t{max-width:32ch}
body.pf-v .mp-writing .pcard-dek{max-width:52ch}

/* NARROW: the date comes off its column and sits under the dek. Below about
   640px there is no room for a second column that a six-word string can hold
   open, and the alternative - letting it squeeze - wraps "5 min read" onto its
   own line beside a headline. */
@media (max-width:640px){
  body.pf-v .mp-writing .pcard-body{grid-template-columns:minmax(0,1fr)}
  body.pf-v .mp-writing .pcard-foot{
    grid-column:1;grid-row:auto;
    margin-top:var(--s3);
  }
}


/* TOUCH TARGETS ON THE PROFILE (2026-09-02). Measured across 12 widths: the
   page's small buttons render 35px tall - .blk-more at 14px/10-18 in the two
   block headings, and the sticky bar's "Visit website" at the same scale. The
   base .btn is 43px and fine; these are the two size overrides.

   35px clears WCAG 2.5.8's 24px minimum, so this is not a failure - it is the
   difference between passing and being comfortable. 44px is the figure both
   Apple's and Google's guidance settle on, and these two buttons are the ones a
   thumb reaches for while the page is moving under it.

   pointer:coarse ONLY. A mouse hits 35px without thinking, and growing every
   small button on the desktop layout would change type rhythm that was set
   deliberately. This asks about the input device, not the window size - a
   touch laptop at 1440 gets the bigger target and a narrow desktop window does
   not.

   PROMOTED TO base.css SECTION 16 (2026-09-02, same day). The note above said
   this should probably live in base and was held back only because the other
   pages had not been reviewed. They have been - 28 pages at 390px under a real
   touch context - so the rule now covers every .btn on the site along with the
   inputs, the toggles and the two 10px map targets. Nothing is left here: a
   body.pf-v copy of a rule base.css already applies to .btn is exactly the
   drift this file argues against everywhere else. See section 16 for the
   measurements and for what is deliberately exempt. */
