/*
 * ericville26 — Lab landing (section landing / browse pattern)
 * ============================================================
 * Companion to page-lab.php. Everything here is scoped to
 * `.ev26.lab-landing` so it cannot reach any other surface, and every colour
 * resolves through a token — the Lab page used to carry a hardcoded near-black
 * slab behind the projects grid (ericville25's `.projects.inverse`), which
 * fought the real dark theme and made the page ignore the toggle entirely.
 * There is not one literal colour in this file.
 *
 * What this file adds on top of css/v26-components.css, which already supplies
 * .grid, .cell, .shead, .shead-sub, .tag, .btn, .more and .inverse:
 *
 *   .lab-open    the opening block (h1 left, deck baseline-aligned right)
 *   .lab-index   the jump-chip row + entry count
 *   .lab-group   a browse group (section rule, grid, bottom rhythm)
 *   .shead-sub   the sub-group rung (a component; only its rhythm is set here)
 *   .cell.feat   the featured cell, spanning two columns, laid out horizontally
 *   .grid.list   the list variant used by Patents and Resources
 *
 * Borders, deliberately sparse (house rule: a rule earns its place only by
 * separating two things that would otherwise be confused). The page has
 * exactly three kinds of rule: the index row's bottom hairline, one top rule
 * per group via .shead, and the 2px accent bar that wipes in on a live cell.
 * Sub-groups inside Projects are separated by space alone. The chip border is
 * the one exception and it earns it: a chip is a control, and its border is
 * the affordance that says so.
 */

/* ── opening ──────────────────────────────────────────
 * Authored as CORE blocks in the page content (group > paragraph.micro,
 * heading, paragraph.deck) so Eric edits the words in Gutenberg. The layout is
 * here, keyed off the group's className, so the editor stays plain.
 *
 * PLACEMENT FIX (#1445 — Eric: "positioning of description feels off").
 * Two things were wrong, both of them layout rather than copy:
 *
 *   1. The deck was a column away from the thing it describes. Column 1 was
 *      1.25fr — around 620px of the 1120px measure — while the headline itself
 *      is capped at 11ch, so the headline stopped at roughly 230px and the deck
 *      did not begin until 678px. That left a ~430px void between a headline
 *      and its own standfirst, and at that distance they stop reading as one
 *      unit and start reading as two unrelated objects. Column 1 is now sized
 *      to the headline (max-content, still clamped by the 11ch max-width), so
 *      the gap between them is the 56px column gap and nothing else — the deck
 *      hangs off the headline instead of floating in the right-hand third.
 *
 *   2. It was aligned to nothing. `align-items:end` bottoms the deck's BOX
 *      against the headline's BOX, and the two have different line-heights and
 *      different font sizes, so their last baselines missed each other by
 *      ~12px; a hand-tuned `margin-bottom:10px` was then trying to close that
 *      gap for one specific headline. A near-miss is the worst case — the eye
 *      registers the discrepancy without being able to name it, which is what
 *      "feels off" describes. `align-items:last baseline` aligns the two last
 *      baselines exactly, and keeps doing it at any headline length, so the
 *      magic number is gone rather than re-tuned.
 *
 * Still grid 1.25fr-worth of measure overall / gap 56px / padding 74px 0 42px,
 * per the handoff's "Section landing" spec.
 */
.ev26.lab-landing .lab-open{
  display:grid;grid-template-columns:max-content minmax(0,34ch);column-gap:56px;
  justify-content:start;padding:74px 0 42px;align-items:last baseline;margin:0;
}
/* A classic (non-block) theme makes core/group emit an extra
   .wp-block-group__inner-container between the group and its children, so the
   grid had one child and the deck fell under the headline instead of beside
   it. display:contents lifts the real children into the grid without adding a
   wrapper class to content Eric edits, and degrades to the stacked order if it
   is ever unsupported. */
.ev26.lab-landing .lab-open > .wp-block-group__inner-container{display:contents}
/* basetags.css carries `h1:not(.show){display:none}` at (0,1,1) — a real rule,
   not a reset — so a lower-specificity selector renders the headline invisible.
   .ev26.lab-landing .lab-open h1 is (0,3,1) and clears it honestly, without
   bolting a .show class onto content Eric edits. Dies with basetags in Stage 11. */
.ev26.lab-landing .lab-open h1{
  display:block;grid-column:1;grid-row:2;max-width:11ch;margin:0;color:var(--ink);
}
.ev26.lab-landing .lab-open .lab-kind{
  grid-column:1;grid-row:1;margin:0 0 18px;
  display:flex;align-items:center;gap:12px;color:var(--accent);
}
/* The kind marker from the article head: a 28px accent rule, then the label. */
.ev26.lab-landing .lab-open .lab-kind::before{
  content:"";width:28px;height:2px;background:var(--accent);flex:0 0 28px;
}
/* No bottom margin: the 10px here was the hand-tuned fudge that `last baseline`
   now makes unnecessary, and leaving it in would reintroduce the same 10px
   miss the fix exists to remove. */
.ev26.lab-landing .lab-open .deck{
  grid-column:2;grid-row:2;max-width:34ch;margin:0;
}

/* ── index row: jump chips + honest count ─────────────
 * Real links, not buttons. Category archives 301 to the home page site-wide
 * (inc/permalinks.php), so a chip pointing at /essay/ would throw the reader
 * off the page — these are in-page anchors to each group instead. No JS: the
 * chips work with scripting off, which is the whole point of doing it this way.
 */
/* STICKY (#1492). The chips are the only navigation this page has, and the page
 * is ~5,500px long — they were useful for the first screen and then gone for
 * the other five. Sticking them keeps "jump to Patents" reachable from
 * anywhere, which is the entire reason the row exists.
 *
 * top:84px is measured against the header, not guessed. .bar is sticky at
 * top:0 and 70px tall AT REST, but by the time this row can stick the page is
 * scrolled, so the header is always in its shrunk pill state: 12px inset + 64px
 * pill = bottom edge at 76px. 84px leaves an 8px gap so the two objects read as
 * two layers rather than one welded stack. (Phone: --hdr-pill-inset drops to
 * 10px and the pill is shorter, so the offset steps down with it below.)
 *
 * z-index 100 is deliberately BELOW the header's 200 — if anything ever does
 * overlap, the chrome wins and the chips pass under it, which is the correct
 * failure. It is above page content so cards scroll under the row, not through.
 *
 * The ground is a translucent tint plus a blur rather than flat var(--bg): the
 * body carries an accent wash gradient behind this row, so an opaque fill would
 * be a visible rectangular patch sliding over it. This matches the header's own
 * material vocabulary, which is what the row is now a peer of. The blur is
 * declared only here (not on a scroll-linked animation), so it costs one
 * backdrop root on one small row — the thing #1432 measured was blur being
 * TRANSITIONED, not blur existing.
 */
/* #1500 — Eric: "the section nav on the Lab page needs to use the same
 * styling as the floating main navigation." It was a flat translucent strip
 * with a bottom hairline; the header pill it sits directly under is a rounded
 * frosted pane with grain and a raised-edge shadow. Same tokens, same
 * material, so the two read as one family of object rather than two
 * different treatments stacked on top of each other. */
.ev26.lab-landing .lab-index{
  position:sticky;top:84px;z-index:100;isolation:isolate;
  display:flex;gap:8px;flex-wrap:wrap;align-items:center;
  margin:0;padding:14px 22px;border:0;border-radius:999px;
  background:color-mix(in srgb,var(--frost) var(--hdr-pill-tint),transparent);
  backdrop-filter:blur(var(--hdr-pill-blur)) saturate(1.7);
  -webkit-backdrop-filter:blur(var(--hdr-pill-blur)) saturate(1.7);
  box-shadow:0 10px 28px -14px color-mix(in srgb,var(--shade) 34%,transparent),
             inset 0 1px 0 color-mix(in srgb,var(--lift) var(--hdr-hi),transparent);
}
.ev26.lab-landing .lab-index::after{
  content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background-image:var(--grain);background-size:var(--hdr-pill-grain-size);background-repeat:repeat;
  mix-blend-mode:var(--hdr-grain-blend);filter:var(--hdr-grain-tone);opacity:var(--hdr-grain);
}
.ev26.lab-landing .lab-chip{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--sans);font-size:var(--t-meta);font-weight:600;color:var(--muted);
  border:1px solid var(--line-strong);border-radius:999px;padding:7px 15px;
  /* #1500 — accessibility fix, take two. The text-shadow scrim alone still
     left the reading depend on whatever happened to be behind the tray at
     any given scroll position. Eric: "just give each item a slightly less
     translucent fill" — each CHIP now carries its own denser frost, so its
     label sits on a near-solid ground of its own rather than borrowing the
     tray's. The tray itself stays at the header's transparency; only the
     controls sitting on it get more opaque, same as a real glass panel would
     put a frosted decal under small print. */
  background:color-mix(in srgb,var(--frost) 65%,transparent);
  text-shadow:var(--hdr-label-scrim);
  transition:color var(--fast) var(--ease),border-color var(--fast) var(--ease),
             background var(--fast) var(--ease),transform .28s var(--spring);
}
/* The count was --faint — the site's lowest-contrast tier, measured at
   3.26:1 even against a near-white ground and well under AA against
   anything busier. --muted clears AA on its own; paired with the scrim
   above it holds regardless of what scrolls underneath. */
.ev26.lab-landing .lab-chip b{font-weight:700;font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--muted);transition:color var(--fast) var(--ease)}
.ev26.lab-landing .lab-chip:hover{color:var(--accent);border-color:var(--accent);background:var(--accent-soft);transform:translateY(-1px)}
.ev26.lab-landing .lab-chip:hover b{color:var(--accent)}
.ev26.lab-landing .lab-chip:active{transform:translateY(0) scale(.97);transition-duration:.08s}
.ev26.lab-landing .lab-chip:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
/* The right-hand "N entries · newest first" line was removed in #1447 — it
   described the list rather than helping anyone use it — so .lab-count and its
   responsive override are gone with it. The chips now sit alone on this row. */

/* ── groups ───────────────────────────────────────────
 * basetags.css puts var(--space-xl) margins on every <section>; the rhythm
 * here is owned by the group, so that is reset rather than fought.
 * scroll-margin-top keeps a jumped-to group clear of the sticky glass header —
 * and, since #1492, of the sticky chip row underneath it too. 96px cleared the
 * 76px pill and nothing else, so a chip jump landed its own group heading
 * behind the very row that was clicked. 168px = pill bottom 76 + the chip row's
 * ~84px sticky height + a little air, so the heading arrives just below both.
 */
/* #1500 — same missing reset as .latest-sec in v26-home.css: a bare <section>
 * inheriting basetags.css's legacy breakpoint-dependent horizontal padding
 * (20px below 700px, a larger --page-gutter-l between 700-939px, 0 only at
 * >=940px) instead of the explicit `padding:0` every other landing page's
 * group already carries (.art-group, .shop-group). That's what made the
 * project/essay/patent grids read narrow and misaligned against .lab-open's
 * heading above them. */
.ev26.lab-landing .lab-group{margin:0 0 60px;padding:0;scroll-margin-top:168px}
.ev26.lab-landing .lab-group:last-of-type{margin-bottom:26px}
.ev26.lab-landing .lab-group .grid{margin:0}
/* The index row already draws a hairline directly above the first group, so
   .shead's own top rule would be a second line 34px below the first. */
.ev26.lab-landing .lab-group:first-of-type .shead{border-top:0;padding-top:34px}
/* The heading outline here is h1 > h2 (group) > h3 (sub-group) > h4 (card).
   This file used to restate the group header's type against h2 because the
   component was written against h3; the component now takes both tags from
   --shead-* (see v26-components.css), so there is nothing to say here. */

/* Projects run four-up, not three.
 *
 * Twenty-five made things are a body of work, and a denser grid says that: at
 * three columns they were ten rows of large tiles that read as ten separate
 * decisions. Four columns also buys back ~1,500px of document height, which
 * matters because a page taller than 16,384 device pixels cannot be captured —
 * Chromium stops painting and the last group and the footer come out blank.
 * The column count steps back down as the viewport narrows (see the media
 * queries at the foot of this file).
 */
.ev26.lab-landing #projects .grid{grid-template-columns:repeat(4,1fr)}
.ev26.lab-landing #projects .cell{padding:18px 18px 22px}
.ev26.lab-landing #projects .cell h4{line-height:1.2}
.ev26.lab-landing #projects .cell figure{margin:12px 0 14px}
.ev26.lab-landing #projects .cell .meta{padding-top:0}

/* Sub-group label inside Projects. Four kinds of project is real information
   — it is the range argument — but four full .shead rules in a row turns the
   section into scaffolding. Space and weight carry it instead.
   The type is the sub rung, declared once in v26-components.css against
   .shead-sub (this was .lab-sub, renamed when the rung became a component:
   it is the second level of the section-header system, not a lab feature).
   Only the rhythm is lab's, so only the rhythm is here. The trailing count
   span came off with the rest of the counts (#1450). */
.ev26.lab-landing .shead-sub{display:flex;align-items:baseline;gap:12px;margin:32px 0 14px}
.ev26.lab-landing .lab-group .shead-sub:first-of-type{margin-top:0}

/* ── cards ────────────────────────────────────────────
 * .cell comes from the components layer. Only the additions are here.
 */
/* THE YEAR SITS WITH THE ENTRY, NOT AT THE FLOOR OF THE CARD (#1492).
 *
 * `margin-top:auto` pinned this row to the bottom of the cell, and the cells in
 * a grid row are all the height of the tallest one — so a card with a short
 * title and no excerpt showed its year 60-100px below the last thing it
 * belonged to, floating on empty ground. That distance is what Eric read as
 * the year being unrelated to the description above it.
 *
 * It was the right rule when the row also held tag pills: two objects ranged to
 * opposite edges need a stable baseline to range against, and the card floor is
 * that baseline. With the pills gone (see page-lab.php) the row is one short
 * year, and a single left-ranged token has nothing to hold the floor for. So it
 * follows the copy instead: 8px under the description, on the same left rag as
 * the title, and the leftover space falls to the bottom of the card where empty
 * space is invisible rather than between two things that belong together.
 *
 * The featured cell keeps the floor (below) — its meta row is still two objects,
 * a date and a "Read" affordance, and its body is a flex column tall enough for
 * the bottom edge to be a real place. */
.ev26.lab-landing .cell .meta{
  margin-top:8px;padding-top:0;display:flex;justify-content:space-between;
  align-items:center;gap:12px;font-size:var(--t-meta);font-weight:500;color:var(--faint);
}
/* Long-text edge case: excerpts vary from one line to a full paragraph, and an
   unclamped one drags its whole grid row taller. Titles are never clamped —
   truncating a title loses information the reader came for. */
.ev26.lab-landing .cell p{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
/* No thumbnail: a quiet well, not a placeholder illustration. The old grey
   wrench placeholder was data-free ink repeated down the page. */
.ev26.lab-landing .cell figure.empty{background:var(--sunken)}

/* ── the grey leans toward the section accent (#1492) ──
 * The components layer runs every card thumbnail at `grayscale(1)` and returns
 * it to full colour on hover, which is the site's whole card language. That is
 * kept — this only decides WHICH grey.
 *
 * A neutral grey belongs to no section. The Lab's ground, its rules, its links
 * and its hover wipe are all --accent, and the images were the one large
 * surface on the page opting out of that, which is what made a wall of 25 of
 * them read as inert plates. A grey that carries a trace of the section hue
 * reads as part of the same object.
 *
 * Done as an overlay pseudo-element on the figure, not as a filter on the img,
 * because a filter cannot say "this hue" — sepia()+hue-rotate() means hardcoding
 * a rotation in degrees, which is a literal colour by another name and would go
 * wrong the moment --accent moves or the theme flips. `mix-blend-mode:color`
 * takes hue and saturation FROM the overlay and lightness from the image
 * underneath, so it is exactly "tint the grey toward the accent" and it follows
 * whatever --accent currently is — green here, and the dark theme's lighter
 * green under [data-theme=dark] — with no second declaration.
 *
 * Held at 13%. 18% was tried first and rendered as a green duotone — a
 * treatment applied TO the photographs rather than a property of the grey they
 * were already in, which is the line the brief draws ("slight", "not a
 * full-color image"). At 13% the cast is legible against the page but the
 * plates still read as black-and-white. On hover it goes to 0 in step with the
 * existing grayscale(0)
 * transition, so the reveal is still a clean return to the real photograph.
 *
 * Not applied to figure.empty — there is no image there to tint, and a coloured
 * pane where a picture is missing would be inventing content. */
.ev26.lab-landing .cell figure{position:relative;isolation:isolate}
.ev26.lab-landing .cell figure:not(.empty)::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:var(--accent);opacity:.13;mix-blend-mode:color;
  transition:opacity var(--slow) var(--ease);
}
.ev26.lab-landing .cell:hover figure:not(.empty)::after{opacity:0}

/* Featured cell — the first thing under the index row. Horizontal: image 46%,
   body beside it, title up at 30px. It sits in its own single-column .grid.lead
   so it reads as a lead item rather than as the biggest tile in a wall. */
.ev26.lab-landing .grid.lead{grid-template-columns:1fr;margin:0 0 6px}
.ev26.lab-landing .grid.lead .cell.feat{grid-column:auto}
.ev26.lab-landing .cell.feat{grid-column:span 2;flex-direction:row;gap:28px;align-items:stretch}
.ev26.lab-landing .cell.feat figure{margin:0;flex:0 0 46%;aspect-ratio:auto;min-height:250px}
.ev26.lab-landing .cell.feat .body{display:flex;flex-direction:column;flex:1;padding:4px 0;min-width:0}
.ev26.lab-landing .cell.feat h4{
  font-size:var(--t-head);font-weight:600;line-height:1.06;letter-spacing:var(--tr-head);margin:14px 0 10px;
}
.ev26.lab-landing .cell.feat p{font-size:var(--t-body);-webkit-line-clamp:4}
/* The lead cell keeps its meta row at the floor: it is two objects (a date and
   the "Read" affordance) inside a body tall enough for a bottom edge to mean
   something, which is exactly the case the project cards stopped being. */
.ev26.lab-landing .cell.feat .meta{margin-top:auto;padding-top:16px}

/* ── list variant: Essays, Patents, Resources ─────────
 * A patent and a place are one line of fact each, not a picture. Rendering
 * them as image cards is what made the bottom half of the old page repeat
 * itself; a two-column list says the same thing in a fifth of the height.
 *
 * Essays use it too, at a larger size. Two adjacent 3-up image grids — fifteen
 * essays then twenty-five projects — was the monotony the brief names: the two
 * groups looked like one wall. An essay is a piece of thinking, so it leads
 * with its title and standfirst and keeps the picture small; a project is a
 * made thing, so it stays a picture. The rhythm now goes lead card → reading
 * list → visual grid → fact list → place list, four densities instead of one.
 *
 * It is also what keeps the page inside a single screenshot: as 3-up image
 * cards the document ran to 10,147px, past Chromium's 16,384-device-pixel
 * capture ceiling, so the last group and the footer never painted.
 */
.ev26.lab-landing .grid.list{grid-template-columns:1fr 1fr;gap:4px}
.ev26.lab-landing .grid.list .cell{flex-direction:row;align-items:center;gap:18px;padding:15px 20px}
.ev26.lab-landing .grid.list .cell figure{margin:0;flex:0 0 64px;aspect-ratio:1/1;border-radius:var(--r-s)}
.ev26.lab-landing .grid.list .cell .body{flex:1;min-width:0}
.ev26.lab-landing .grid.list .cell h4{margin:0 0 4px}
.ev26.lab-landing .grid.list .cell p{line-height:1.45;margin:0;color:var(--faint);-webkit-line-clamp:2}
/* `.lnk`, `.is-external` and the whole `#resources` block that used them went
   with the Resources section (#1449) and with the "Patent →" label (#1448).
   Nothing on this page renders them any more, so they are deleted rather than
   left behind as CSS describing markup that no longer exists. */

/* ── patent rows ──────────────────────────────────────
 * Patent rows carry no image at all: there is no patent artwork in the library,
 * and seven identical grey placeholder plates were pure noise. The number does
 * the identifying work a thumbnail could not.
 */
/* ONE ROW PER INVENTION, FULL MEASURE (#1492).
 *
 * `.grid.list` is two columns by default; the patents list drops out of that.
 * Two title+numbers pairs on one visual row gave the reader four alternating
 * text blocks and no signal for where one record ended, so "Interspersed
 * message batching" and "Segment creation in a database system" read as one
 * invention with four numbers. Halving the measure also cost the titles ~230px
 * and wrapped most of them to three lines, which is the "cramped" half of the
 * same complaint. Both are the column count, not the type.
 *
 * gap goes to 0 because the rows are separated by a rule now (below) rather
 * than by a 4px void, and the rule wants the rows adjacent to sit on it. */
.ev26.lab-landing .grid.list.plain{grid-template-columns:1fr;gap:0}
/* Asymmetric gap: 18px across (title to number rail), 8px down. The only row
   that wraps is the six-number family, and when it does the numbers belong to
   the title directly above them — 18px of vertical air made them read as a
   stranded second record. */
.ev26.lab-landing .grid.list.plain .cell{padding:18px 20px;flex-wrap:wrap;align-items:baseline;gap:8px 18px}
.ev26.lab-landing .grid.list.plain .cell p{font-variant-numeric:tabular-nums;margin-top:5px}
/* A hairline between records, and it earns its place by the house rule: these
   are now full-width rows of near-identical shape stacked directly on each
   other, which is precisely the case where two things get confused for one. The
   first row takes none — the section header already draws the line above it.
   `+` rather than `:not(:first-child)` so it is a rule BETWEEN rows, which is
   what it is. */
.ev26.lab-landing .grid.list.plain .cell + .cell{border-top:1px solid var(--line)}
/* The title no longer needs a defensive floor. That 13rem minimum existed to
   stop a six-number family from crushing the title inside a half-width row;
   at full measure the widest family here (six numbers, ~610px) still leaves the
   longest title ~430px, so nothing is competing for space. What the title does
   need is a CEILING — left to the flex default a short title lets the numbers
   drift into the middle of the page instead of ranging against the right edge,
   and long/short titles then range their numbers at different places down the
   list. Capping the body keeps the number rail on one vertical rag. */
.ev26.lab-landing .grid.list.plain .cell .body{flex:1 1 auto;max-width:52ch;min-width:0}
/* The row is a <div> now, because a row can hold several numbers and an anchor
   cannot nest one. That means the CARD is no longer clickable, so the card-level
   affordances have to stop pretending it is: the components layer gives every
   .cell a lift, a paper ground and an accent wipe on hover, all of which promise
   a click target that is not there. The links inside answer for themselves. */
.ev26.lab-landing .grid.list.plain .cell:hover{background:none;box-shadow:none}
.ev26.lab-landing .grid.list.plain .cell:hover::after{transform:scaleX(0)}
.ev26.lab-landing .grid.list.plain .cell:hover h4{color:var(--ink)}
/* One link per patent number. Right-ranged like the label it replaces, but it
   wraps instead of nowrapping — a six-patent design family is six numbers, and
   at 768px they need the second line rather than the overflow. */
.ev26.lab-landing .grid.list.plain .nums{
  margin-left:auto;flex:0 1 auto;display:flex;flex-wrap:wrap;
  justify-content:flex-end;gap:4px 12px;padding-left:16px;
}
/* `.cell.is-wide` is gone with the second column: when every row is already the
   full measure, "make this row span" has nothing left to say. The class is no
   longer emitted by page-lab.php either, so the rule is deleted rather than
   left behind describing markup that does not exist. */
.ev26.lab-landing .grid.list.plain .nums a{
  font-family:var(--sans);font-size:var(--t-meta);font-weight:600;color:var(--accent);
  white-space:nowrap;font-variant-numeric:tabular-nums;
  transition:color var(--fast) var(--ease),border-color var(--fast) var(--ease);
  border-bottom:1px solid transparent;
}
.ev26.lab-landing .grid.list.plain .nums a:hover{border-bottom-color:var(--accent)}
.ev26.lab-landing .grid.list.plain .nums a:focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:2px;
}

/* Essay rows: the reading list. Bigger than a resource row — the title is the
   thing being scanned — and the standfirst gets two full lines. */
.ev26.lab-landing .grid.list.reading{gap:6px}
.ev26.lab-landing .grid.list.reading .cell{align-items:flex-start;gap:20px;padding:18px 20px}
.ev26.lab-landing .grid.list.reading .cell figure{flex:0 0 84px;aspect-ratio:1/1;margin:2px 0 0}
.ev26.lab-landing .grid.list.reading .cell h4{line-height:1.22;margin:0 0 6px}
.ev26.lab-landing .grid.list.reading .cell p{line-height:1.5;color:var(--muted)}
.ev26.lab-landing .grid.list.reading .cell .yr{
  margin-left:auto;flex:0 0 auto;font-size:var(--t-meta);font-weight:600;color:var(--faint);
  white-space:nowrap;padding-top:3px;transition:color var(--fast) var(--ease);
}
.ev26.lab-landing .grid.list.reading .cell:hover .yr{color:var(--accent)}

/* ── closing ──────────────────────────────────────────
 * Navigation, not a newsletter. Six thousand pixels down, the only way out of
 * this page was to scroll back up; the block gives the two real destinations
 * the lab argues for.
 */
.ev26.lab-landing .lab-close{margin:0 0 20px;padding:48px 44px}
/* Colours restated at real specificity. basetags.css sets `.inverse h2` and
   `.inverse a` to ericville25's accent-light at (0,1,1), which out-ranks the
   component layer's :where(.ev26) .inverse rules and left the heading and both
   buttons the wrong colour on the inverted ground. */
/* 20ch, up from 16ch (#1492). The cap was set for "The made things are half the
   argument."; the new line is longer and broke to three ragged lines, the last
   of which was one word. 20ch sets it in two balanced lines and still keeps the
   closing statement well short of the block's full width, which is the point of
   having a cap at all. */
.ev26.lab-landing .lab-close h2{max-width:20ch;margin:0;color:var(--bg)}
.ev26.lab-landing .lab-close .btn{background:var(--bg);color:var(--ink);border-color:var(--bg)}
.ev26.lab-landing .lab-close .actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:26px}
/* .inverse paints its buttons in --bg on --ink; the ghost needs its border and
   label pulled back onto the inverse ground instead of the page ground. */
.ev26.lab-landing .lab-close .btn.ghost{
  background:transparent;color:var(--bg);
  border-color:color-mix(in oklab,var(--bg) 42%,transparent);
}
.ev26.lab-landing .lab-close .btn.ghost:hover{border-color:var(--bg)}

/* ── empty state ──────────────────────────────────────
 * A group with nothing in it prints one quiet line rather than a bare rule
 * with a hole under it. Real possibility: Resources is a running list Eric
 * curates, and Deep Cuts is three items deep.
 */
.ev26.lab-landing .lab-none{
  font-size:var(--t-meta);color:var(--faint);margin:0;padding:18px 22px 26px;
}

/* ── responsive: 1440 / 1024 / 768 / 375 ──────────────
 * 1440 and 1024 both run three columns — the content column caps at 1120px, so
 * a 1024 viewport only loses gutter. 768 drops to two, 375 to one.
 */
@media (max-width:1000px){
  .ev26.lab-landing .lab-open{grid-template-columns:1fr;padding:58px 0 34px}
  .ev26.lab-landing .lab-open h1{grid-column:1;grid-row:2;max-width:16ch}
  .ev26.lab-landing .lab-open .deck{grid-column:1;grid-row:3;max-width:52ch;margin:20px 0 0}
}
@media (max-width:1200px){
  .ev26.lab-landing #projects .grid{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:900px){
  .ev26.lab-landing .grid,
  .ev26.lab-landing #projects .grid{grid-template-columns:repeat(2,1fr)}
  .ev26.lab-landing .cell.feat{grid-column:span 2}
  .ev26.lab-landing .cell.feat figure{min-height:200px}
  .ev26.lab-landing .cell.feat h4{font-size:var(--t-title)}
  .ev26.lab-landing .lab-group{margin-bottom:48px}
}
/* Lists go single-column at the same step the grids drop to two. Held at 760
   first, which left a 768px tablet running two-up rows so tight that a resource
   row's fixed thumbnail, its nowrap category label and its padding overflowed
   the viewport by 6px — the capture came back 1548px wide instead of 1536. */
@media (max-width:900px){
  .ev26.lab-landing .grid.list{grid-template-columns:1fr}
}
@media (max-width:600px){
  .ev26.lab-landing .lab-open{padding:40px 0 28px}
  .ev26.lab-landing .lab-open h1{max-width:none}
  /* #1500 — Eric: hide the counts so the 3 chips are more likely to sit on
     one row on a phone. "Projects 22" is meaningfully wider than "Projects"
     alone; dropping the count everywhere it's the widest part of each chip
     is what actually buys back a row, not a padding trim. The count is
     still real information, just not phone-critical the way the label — the
     thing that makes the chip a working jump link — is. */
  .ev26.lab-landing .lab-chip b{display:none}
  /* Projects stay two-up on a phone. One made thing per screen turns a
     twenty-five item collection into a scroll with no end in sight.
     ── #1457: why these tracks are minmax(0,1fr) and not 1fr ──
     `1fr` is shorthand for `minmax(auto,1fr)`, and that `auto` floor is the
     grid item's MIN-CONTENT, not zero. A track can therefore refuse to shrink
     to its share of the row, and when both tracks refuse, the grid's own
     content box (247px inside the 375 viewport) is simply overrun: the tracks
     measured 159.4 + 8 + 157.7 = 325 inside a 247px box, the right-hand cell
     landed at right=389, and the whole document scrolled 14px sideways on
     every phone. Same failure mode as #1414 in the header — a row of items
     that individually will not shrink, pushing past the viewport together.
     What set the floor was the .meta row: one non-wrapping flex line of year
     + tag pills, whose min-content is year + gap + widest pill ≈ 134px. So
     the floor is lifted in three places at once, because removing only one of
     them just moves the overflow to the next inflexible thing:
       1. minmax(0,1fr) + min-width:0 — the track and the cell may now reach
          their real half-measure (119.5px) instead of being propped open.
       2. .meta wraps — the tags drop under the year rather than demanding a
          134px line, which is what was propping the track open.
       3. the pill is capped at the cell's measure and may break — a pill is
          the last thing in the chain and the only one that can still be wider
          than the card it sits in (a single long tag word). Capped, a long
          tag wraps inside its own pill instead of hanging out of the card.
     Nothing here is a viewport-keyed magic number: at any width where the
     content does fit, every one of these rules is inert. Verified
     scrollWidth === clientWidth === 375 on /lab/, light and dark, with no
     element spilling its cell, and 768/1024/1440 unchanged. */
  .ev26.lab-landing .grid,
  .ev26.lab-landing .grid.list{grid-template-columns:minmax(0,1fr)}
  .ev26.lab-landing #projects .grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ev26.lab-landing .cell{min-width:0}
  .ev26.lab-landing #projects .cell{padding:12px 12px 16px}
  .ev26.lab-landing #projects .cell h4{font-size:var(--t-body)}
  /* Points 2 and 3 of the note above (the wrapping .meta row, and the capped
     breakable .tag pill) are gone with the tag pills themselves in #1492: the
     134px min-content line that was propping the track open WAS the pill row,
     so removing the pills removes the cause rather than the symptom. Point 1 —
     minmax(0,1fr) plus min-width:0 — stays, because it is the load-bearing one:
     it is what lets the tracks reach their real half-measure at all, and it has
     to keep holding for any future inflexible child. */
  /* The chip row sticks lower on a phone only because the pill does: the header
     drops to --hdr-pill-inset:10px there, so the offset steps down with it.
     #1500 — Eric: the tray's border-radius looked "clunky and not purposeful."
     999px is correct for the desktop tray because it is reliably one row —
     a stadium shape reads as a pill exactly because it IS pill-shaped (height
     ≈ 2×radius). On a phone the three chips wrap to two rows (measured
     346×111 at 390px, Patents dropping to its own second row), so the same
     999px keeps trying to draw a full stadium curve on a box that is now
     closer to a rounded rectangle — the blobby, oversized corners in the
     screenshot. --r-l is the theme's own "large panel" radius, used nowhere
     near a pill context, and is what every other multi-row surface on this
     page (the cards themselves) already reads as "rounded, on purpose." */
  .ev26.lab-landing .lab-index{top:80px;border-radius:var(--r-l)}
  /* On a phone the reading row's 84px thumbnail took 28% of the usable width
     and squeezed titles into five-line columns. The title is what is being
     scanned here, so the picture steps aside. It stays in the DOM — the alt
     text is still part of the page's information. */
  .ev26.lab-landing .grid.list.reading .cell figure{display:none}
  .ev26.lab-landing .grid.list.reading .cell{padding:16px 16px}
  /* A phone has no room for a title, a facts line and a right-ranged column of
     numbers on one row, so the numbers drop under the title and range left with
     it rather than squeezing the title into a four-line column. */
  .ev26.lab-landing .grid.list.plain .cell{flex-direction:column;align-items:flex-start;gap:10px}
  .ev26.lab-landing .grid.list.plain .nums{margin-left:0;padding-left:0;justify-content:flex-start}
  /* Stacked, the featured cell is just a card with a bigger title. */
  .ev26.lab-landing .cell.feat{grid-column:span 1;flex-direction:column;gap:0}
  .ev26.lab-landing .cell.feat figure{flex:none;aspect-ratio:4/3;min-height:0;margin:14px 0 16px}
  .ev26.lab-landing .cell.feat h4{margin-top:0}
  .ev26.lab-landing .cell.feat p{font-size:var(--t-meta)}
  .ev26.lab-landing .lab-close{padding:40px 28px}
  .ev26.lab-landing .lab-close .actions .btn{flex:1 1 100%;justify-content:center}
}
