/* ============================================================================
   MOBILE ONLY.  Nothing in this file can reach desktop.

   It is linked as:

       <link rel="stylesheet" href="mobile.HASH.css" media="(max-width:760px)">

   The media condition lives on the <link>, not inside the file, which is the
   whole point: EVERY rule here is mobile-scoped by construction. You do not
   need to wrap anything in @media, and you cannot forget to. A desktop browser
   parses this file but applies none of it.

   That makes this the safe surface for reworking the phone layout. The rule for
   working here:

     - want to change mobile?            put it in this file
     - need to change desktop too?       that belongs in styles.css, and it is a
                                         deliberate decision, not a side effect

   It loads AFTER styles.css, so on equal specificity these rules win. Prefer
   winning by order rather than by piling on selectors or !important -- a
   specificity war here is how the two files start fighting.

   VERIFY AFTER EVERY CHANGE:

       python3 tools/desktop-guard.py "dist 11.22.00" --check

   That must say DESKTOP IDENTICAL. It compares 2,181 element snapshots at
   1440/1280/1024 against a baseline captured from the released build, and it is
   validated: it catches a shared-rule edit (110 findings on a one-line change)
   and stays silent on a mobile-lane edit.

   The breakpoint is 760px to match the existing mobile lane in styles.css
   (max-width:760px, and the desktop side at min-width:761px). Do not introduce a
   second, different breakpoint -- two disagreeing boundaries is a layout bug
   waiting for a specific screen width.
   ========================================================================== */


/* --------------------------------------------------------------------------
   01 — Anchored content was landing UNDER the fixed nav

   The nav is 70px tall once scrolled (measured, iPhone 15, `nav.scrolled` with
   its 18px padding and the 22px mobile wordmark). Nothing declared a scroll
   offset, so jumping to a section put its heading behind the bar -- "07 —
   Community & Culture" was sliced in half. 84px = the 70px bar plus 14px of air.
   -------------------------------------------------------------------------- */
section[id],
header[id]{ scroll-margin-top:84px }


/* --------------------------------------------------------------------------
   02 — Nav controls: 44px hit areas that cost NO horizontal space

   Measured 25x25 (sound) and 32x32 (menu). Both clear WCAG 2.2 SC 2.5.8
   (24x24, AA) and both fail SC 2.5.5 (44x44, AAA) and Apple's HIG.

   Growing them naively would push the bar wider, and there is no room: at 393px
   the wordmark, sound, "Build With Us" and the burger already fill the row, and
   the existing mobile lane exists specifically because that CTA once wrapped to
   two lines and made the bar 106px tall.

   So the box grows and a matching negative margin gives the space back. The hit
   area becomes 44x44; the LAYOUT footprint is unchanged, so nothing reflows and
   the CTA cannot wrap. The icons inside keep their existing size.

   Note the margins are on BOTH axes. The first version compensated horizontally
   only, so the two icon buttons grew 25->44 and 32->44 vertically with nothing
   giving that height back, and they -- not the CTA -- set the bar to 96px.
   -------------------------------------------------------------------------- */
.menu{ gap:12px }

#sndToggle{
  width:44px; height:44px; padding:0;
  margin:-9px;                                  /* 25 -> 44 is +19 both axes; give it all back */
}

.navtoggle{
  width:44px; height:44px;
  align-items:center; justify-content:center;
  margin:-6px;                                  /* 32 -> 44 is +12 both axes; give it all back */
}

/* The CTA is 122x33. First attempt used min-height:44px and made the whole bar
   96px tall on a Pixel 7 -- taller, when the point was to slim it, and the exact
   failure the existing mobile lane was written to prevent. Same trick as above
   instead: the box grows to a 44px target, the negative margin returns the
   vertical space, so the bar height is unchanged. */
.menu .cta{
  min-height:44px;
  display:inline-flex; align-items:center; justify-content:center;
  margin-top:-6px; margin-bottom:-6px;          /* 33 -> 44 is +11; give back 12 */
}


/* --------------------------------------------------------------------------
   03 — Section rhythm

   `.sec` pads 69px top and bottom on a 659px screen: 21% of the viewport spent
   on air before any content. 48px keeps the sections distinct while returning
   roughly 460px across the page -- most of a screen.
   -------------------------------------------------------------------------- */
.sec{ padding-top:48px; padding-bottom:48px }


/* --------------------------------------------------------------------------
   04 — Section 03 was five screens tall

   `.pcard{aspect-ratio:1/1}` is fine in a 4-up desktop grid. Mobile collapses
   that grid to ONE column, so each card becomes a 353x353 square and eight of
   them stack to 2,922px -- 4.4 screens of scrolling for eight items, inside a
   section measuring 3,262px.

   16/10 gives 353x220. Eight cards plus gaps drop to ~1,858px, about 1.6 screens
   returned. The card content needs ~134px (22px padding, the number, h3, two
   lines of copy), so 220px keeps comfortable air and nothing is clipped.
   -------------------------------------------------------------------------- */
.grid-pillars .pcard{ aspect-ratio:16/10 }

/* --------------------------------------------------------------------------
   05 — Nothing acknowledged a finger

   The stylesheet has 75 `:hover` rules and exactly ONE `:active` rule
   (`.btn:active{transform:scale(.97)}`, which covers the contact hold-button).
   On a pointer device the site is alive; on a phone almost nothing responds to
   being pressed. Immediate feedback is most of what separates "app" from
   "document", so every remaining tappable control gets a press state.

   WHY brightness AND NOT transform:scale, which is the idiom used by .btn

   Because these elements already animate `transform`, slowly, for other
   reasons. Measured transition-property / duration on each:

       .sndbtn        opacity                 transform free
       .menu .cta     .4s  (shorthand = ALL)  400ms
       .navtoggle     all
       .film-play     all
       .cc  x8        opacity, transform      1.15s  (the .stagger reveal)
       .navmenu a     transform + delay up to .28s

   A scale on any of those would arrive late or crawl -- 1.15s on the cards, and
   up to .28s LATE on the menu links. `filter` is untouched by every one of these
   elements, so it applies instantly with no transition to override or break.

   THE .cta TRAP -- do not "simplify" the transition below

   `transition:.4s var(--ease)` names no property, so it covers ALL of them,
   filter included. With the shorthand left alone the press measured

       while pressed  brightness(1.219646)   still ramping, never reaches 1.25
       after release  brightness(1.189406)   still lit with the finger gone

   Restating it explicitly keeps the hover fade (background/color/border-color
   are the only properties .menu .cta:hover changes -- there are no :focus rules)
   and makes filter instant. Verified after: 1.25 pressed, none released.

   THE FLIP CARDS ARE SAFE -- this was tested, not assumed

   `filter` on an element with `perspective` can flatten `transform-style:
   preserve-3d`, which would break the card flip. It does not here. Freezing
   .cc-inner mid-rotation and measuring its rendered width, with and without the
   filter:

       rotateY(90deg)   0px    vs  0px     (edge-on collapse, identical)
       rotateY(60deg)   179.1  vs  179.1

   preserve-3d retained, back face still the hit-tested one, and a real tap still
   flips and un-flips exactly as before.

   Geometry impact: zero. Measured with the filter forced permanently ON against
   a 176-element noise floor (the logo marquee, grain layer and hero line move on
   their own between any two snapshots) -- 0 genuine changes.
   -------------------------------------------------------------------------- */
.sndbtn:active,
.navtoggle:active,
.menu .cta:active,
.film-play:active,
.navmenu a:active,
.grid-create .cc:active{ filter:brightness(1.25) }

.menu .cta{
  -webkit-tap-highlight-color:transparent;      /* the only control still showing iOS's default dark box */
  transition: background .4s var(--ease),
              color .4s var(--ease),
              border-color .4s var(--ease),
              filter .09s linear;               /* see THE .cta TRAP above */
}

/* --------------------------------------------------------------------------
   06 — Section 05's rows never responded on a phone

   styles.css wires three effects to .li:hover -- a light sweeping left to
   right, and a 12px slide on the h3 and the p. None of them fire on touch, so
   the section is seven rows of inert text while a desktop visitor gets one that
   wakes up under the cursor.

   main.js nominates whichever row sits in the middle of the screen and toggles
   `.on`. These rules are that hover state. Nothing here declares a transition:
   styles.css already has

       .li    { transition: background .5s var(--ease) }
       .li h3 { transition: transform  .5s var(--ease) }
       .li p  { transition: opacity .5s, transform .5s }

   so the class change animates on the site's own timing, at the site's own
   easing, for free. That is why this is a class toggle rather than a keyframe
   animation -- fewer moving parts and it cannot drift from the desktop look.

   OPACITY IS DELIBERATELY ABSENT. The hover rule also lifts `.li p` from .55 to
   1, but styles.css already does that for touch:

       @media(hover:none){ .li p{opacity:1} }

   An earlier attempt mirrored the hover rule verbatim and animated opacity from
   .55, which UNDID that -- dimming text the original author had deliberately
   fixed. Measured on device at .55 before it was caught. Only the sweep and the
   slide are genuinely missing on touch; leave the opacity alone.

   18px rather than the desktop 12px, and .12 alpha rather than .05: the desktop
   values were tested on a real phone and were invisible. A cursor is a conscious
   act and a whisper is enough; scrolling is not.
   -------------------------------------------------------------------------- */
#industries .list .li.on{
  background:linear-gradient(90deg,rgba(241,232,215,.12),transparent 70%);
}
#industries .list .li.on h3{ transform:translateX(18px) }
#industries .list .li.on p { transform:translateX(18px) }

/* the sweep is the signal; the travel is decoration */
@media (prefers-reduced-motion: reduce){
  #industries .list .li.on h3,
  #industries .list .li.on p { transform:none }
}

/* --------------------------------------------------------------------------
   07 — Section 03's eight pillars were 2.8 screens of stacked column

   Desktop shows the pillars as a 4-across grid. Mobile collapses that to one
   column, so eight cards stack to 1,863px inside a 2,160px section -- 3.3
   screens of scrolling, passing eight items, with nothing to do but scroll.

   A phone has a better idiom for a deck of cards: swipe. The grid becomes a
   horizontal scroll-snap track, which measured

       section 03   2,160px (3.3 screens)  ->  668px (1.0 screens)
       whole page   12,720px               ->  11,228px

   -- roughly 2.3 screens returned from one section, while turning a passive
   scroll into an active gesture. No JS: scroll-snap does all of it.

   84% card width is deliberate. The next card must PEEK, or the section reads
   as having one item and nobody swipes. 4/5 keeps the portrait crop the
   imagery was cut for. Both were picked on a real phone against 78% square,
   66% square and a full-bleed variant.

   overscroll-behavior-x:contain is load-bearing, not decoration: without it a
   hard swipe at the screen edge triggers the browser's back gesture and leaves
   the site.

   THE .stagger TRANSFORM RESET -- do not remove it

   styles.css has these at GLOBAL scope, in this order:

       .stagger.in>*           { opacity:1; transform:none }
       .grid-pillars.stagger>* { transform:translateY(48px); ... }

   Equal specificity, later wins, so the cards NEVER finish their reveal and
   sit permanently 48px low. In a stacked column that reads as spacing and has
   gone unnoticed. Inside this deck, overflow-y:hidden clipped that overhang --
   measured 25px off the description, with the h3 sitting on the edge. Dropping
   the travel keeps the staggered fade and removes the overhang.

   The same bug affects .list and .grid-create, on DESKTOP as well as mobile.
   Not touched here: correcting it would shift three sections up by 48px, which
   is a visual change to a shipped design, not a mobile fix.

   Aspect-ratio here supersedes section 04's 16/10, which existed only to
   shorten the stacked column. 04 is left in place as the fallback if this
   deck is ever removed.
   -------------------------------------------------------------------------- */
.grid-pillars{
  display:flex;
  overflow-x:auto;
  overflow-y:hidden;
  scroll-snap-type:x mandatory;
  overscroll-behavior-x:contain;          /* stops a swipe becoming browser-back */
  -webkit-overflow-scrolling:touch;
  gap:12px;
  scrollbar-width:none;
  grid-template-columns:none;
}
.grid-pillars::-webkit-scrollbar{ display:none }

.grid-pillars .pcard{
  scroll-snap-align:start;
  flex:0 0 84%;                           /* the remaining 16% is the peek */
  aspect-ratio:4/5;
}

.grid-pillars.stagger>*{ transform:none }  /* see THE .stagger TRANSFORM RESET above */

/* --------------------------------------------------------------------------
   09 — Section 04: the spine goes back in the middle, with a mobile-only image

   DESKTOP shows this as three columns -- six captions, the spine, six captions.
   MOBILE threw the spine above the text (`grid-column:1/-1; order:-1`) and
   dropped the captions into two columns underneath, so the arrangement the
   section is named for only existed above 761px.

   index.html now carries a <picture> whose <source media="(max-width:760px)">
   swaps in a spinal column image. Desktop never fetches it; the phone never
   fetches the 255KB backbone it replaces, so mobile is 89KB LIGHTER, not
   heavier. The wrapper is layout-inert on desktop -- measured identical at
   1440/1280/1024 before this shipped.

   WHY THE COLUMNS ARE SIX FIXED ROWS AND NOT A FLEX STACK

   The two sides do not hold the same amount of text: the left runs 13 lines,
   the right 12. With each column centring its own block, that one-line
   difference split top and bottom and the pairs drifted apart down the column
   -- which reads as "more text on the left" even though the counts are 6 and 6.
   Six fixed rows put row N on the left level with row N on the right no matter
   how many lines each wraps to. Measured drift after: 0,0,0,0,0,0.

   10.5px/.08em is smaller than the shared .cap type (12.5px/.13em) on purpose.
   At the shared size the longest captions ran to three lines and sat within
   7px of the screen edge; at this size they wrap to two and clear both edges by
   20px. Do not raise it without re-measuring that clearance.

   Section 04: 792px -> 633px.
   -------------------------------------------------------------------------- */
.backbone{
  grid-template-columns: 1fr 70px 1fr;
  gap: 0 8px;
  align-items: start;
  min-height: 0;
}

.bb-spine{
  grid-column: auto;          /* was 1 / -1 */
  order: 0;                   /* was -1, which threw it above the captions */
  margin-bottom: 0;
  align-items: flex-start;
}

/* The <picture> is the flex item now, not the <img>. Left to itself it
   shrink-wraps to its content, and its content is an image with no intrinsic
   size until it loads -- so `width:100%` on the img resolved against a
   zero-width parent and the whole box collapsed. Giving the wrapper the width
   breaks that loop and lets the aspect-ratio below reserve the height. */
.bb-spine picture{ display:block; width:100% }

.bb-img{
  max-height: none;           /* was 280px */
  width: 100%;
  height: auto;
  opacity: .85;               /* was .5 -- the chrome is the point here */
  object-fit: contain;

  /* RESERVES THE BOX BEFORE THE IMAGE LOADS -- do not remove.
     A lazy <img> inside <picture> gets NO intrinsic size in WebKit until its
     source resolves, unlike a bare <img> with width/height attributes. Here the
     spine column is taller than the captions (432px vs 362px), so it is the
     image that sets the row height -- and without this the section measured
     563px unloaded and 633px loaded, jolting everything below it by 70px as you
     scrolled toward it. 400/2470 is the asset's own ratio. */
  aspect-ratio: 400 / 2470;
}

/* six fixed rows per side -- this is what keeps the two sides level */
.bb-col{
  display: grid;
  grid-template-rows: repeat(6, 52px);
  gap: 10px;
  padding: 0;
  align-content: start;
}

.bb-col .cap{
  display: flex;
  align-items: center;        /* centre each caption inside its own row */
  min-height: 0;
  white-space: normal;
  max-width: none;
  font-size: 10.5px;
  letter-spacing: .08em;      /* see the note above before changing either */
}

.bb-left  .cap{ justify-content: flex-end;   text-align: right }
.bb-right .cap{ justify-content: flex-start; text-align: left  }

/* --------------------------------------------------------------------------
   10 — The active backbone row lights up as you scroll

   styles.css already dresses an active caption:

       .cap.on                  -- opacity:1; letter-spacing:.16em
       .bb-left  .cap.on::after  -- width:12px   (a line toward the spine)
       .bb-right .cap.on::before -- width:12px

   On a pointer device main.js adds `.on` by cursor proximity. That code returns
   early on touch, and the mobile lane additionally hides the connectors, so on a
   phone none of it ever ran. main.js now picks the row nearest the middle of the
   screen instead, and these rules are what that row wears.

   ROWS, NOT CAPTIONS: the picker sets `.on` on BOTH captions of a pair, so the
   highlight reads as one row crossing the spine rather than two halves lighting
   independently.

   `opacity:1` NEEDS !important. styles.css pins `@media(hover:none){ .cap{
   opacity:.82!important } }` so a phone never gets stranded with dim text it
   cannot brighten. That guarantee stays -- .82 is still the resting state and
   the page is fully readable with this effect disabled -- but the active row has
   to out-rank it, and only !important beats !important.

   .12em rather than desktop's .16em: this lane sets the caption type at 10.5px
   /.08em, so a jump to .16em re-wrapped lines and broke the row alignment.
   -------------------------------------------------------------------------- */
.bb-col .cap.on{
  opacity: 1 !important;      /* out-ranks the .82!important resting state */
  letter-spacing: .12em;      /* from .08em; do not raise -- it re-wraps lines */
}

/* Put the connectors back. The mobile lane hides them with display:none because
   nothing on touch could ever grow them; now something can. Width, colour and
   transition all still come from the base rules in styles.css. */
.bb-left  .cap::after,
.bb-right .cap::before{ display: block }

.bb-left  .cap.on::after { width: 10px }   /* 12px on desktop; the gap here is 8px */
.bb-right .cap.on::before{ width: 10px }

/* --------------------------------------------------------------------------
   11 — Own Projects: three logos on one row.

   Stacked, these three 16/9 cards ran 624px — over 90% of a phone screen for three
   logos and nothing else. styles.css collapses the grid to one column below 860px
   (`@media(max-width:860px){.grid-concepts{grid-template-columns:1fr}}`); this puts
   them back on a single row at 94px each, so the block is 94px instead of 624px.

   A plain .grid-concepts beats that media-query rule because both are 0,1,0 and this
   sheet is linked after styles.css — the same source-order convention the rest of this
   file already relies on. No specificity hack needed.

   minmax(0,1fr), not 1fr: a bare 1fr will not shrink below its content's min-content
   width, so three across on a 393px screen would push the row wider than the viewport
   instead of narrowing the cards.

   SQUARE, NOT WIDE. A short wide card flatters wordmarks like LOFT and Vybe and
   starves Evento, whose mark is a near-square stack — at 1/1 all three read evenly.
   That is also why the 52%/62% per-card split above is collapsed to one value here:
   it existed to compensate for a shape this layout no longer has.

   padding drops to 5px because the card is now 94px: the inherited
   clamp(26px,3vw,44px) would leave a 42px hole for the logo.

   Scoped to .grid-concepts, so the twelve .grid-events cards that share .ccard are
   untouched. */
.grid-concepts{
  display:grid;
  grid-template-columns:repeat(3, minmax(0,1fr));
  gap:8px;
  width:84%;
  margin-inline:auto;
}
.grid-concepts .ccard{
  aspect-ratio:1/1;
  width:100%;
  padding:5px;
}
.grid-concepts .ccard .clogo,
.grid-concepts .ccard:nth-child(1) .clogo,
.grid-concepts .ccard:nth-child(2) .clogo{
  width:90%;
  height:90%;
}

/* --------------------------------------------------------------------------
   Stitch section 07 to the founder section.

   .sscrim already fades each section to solid black at 0% and 100%, which should hide
   the join. It does not, because main.js inserts the starfield canvas immediately AFTER
   the scrim (`insertBefore(cv, scrimEl.nextSibling)`) and both sit at z-index 1 — so the
   canvas paints ON TOP of that fade and its stars run right to the section edge. Two
   sections meet with their star fields at full strength and no blend between them, and
   the density step reads as a horizontal band.

   A ::after is the last child, so at the same z-index 1 it paints above the canvas while
   staying under .wrap (z-index 2) — the text is untouched. .sec already carries
   position:relative and overflow:hidden, so it anchors and clips this for free.

   The -1px pulls each gradient a pixel past the boundary so no hairline of un-darkened
   canvas survives rounding at fractional device pixel ratios. */
#structure::after,
.founder::after{
  content:"";
  position:absolute;
  left:0; right:0;
  height:190px;
  z-index:1;
  pointer-events:none;
}
#structure::after{
  bottom:-1px;
  background:linear-gradient(0deg,   #050505 0%, rgba(5,5,5,.86) 42%, rgba(5,5,5,0) 100%);
}
.founder::after{
  top:-1px;
  background:linear-gradient(180deg, #050505 0%, rgba(5,5,5,.86) 42%, rgba(5,5,5,0) 100%);
}

/* --------------------------------------------------------------------------
   12 — Section 07's six entries become a deck, exactly like section 03's pillars.

   Same geometry as .grid-pillars: 84% width so the next card peeks, 4/5 portrait,
   x-mandatory snap, and overscroll-behavior-x:contain so a swipe cannot turn into
   browser-back. The .on treatment mirrors .pcard:hover one-for-one -- border lifts,
   image scales to 1.09 and loses its grayscale, scrim drops to .85 -- so a swipe here
   feels identical to a swipe in section 03.

   .ei is the deck container. On desktop it is the orbital diagram's stage
   (aspect-ratio:1.8/1, container-type:inline-size, the six labels absolutely placed
   around the rings), so all of that has to be unwound here. Its other children --
   .ei-art, .ei-bloom, .ei-nucleus -- are already display:none on mobile, so the six
   .ei-cat are the only flex items.

   IMAGE URLS LIVE IN THIS FILE, not styles.css, so a desktop browser never learns the
   URLs and never fetches them. The inline background-image on each card resolves to an
   undefined variable on desktop, which is simply invalid and paints nothing.
   -------------------------------------------------------------------------- */
:root{
  --s-studio:url(assets/img/struct-01.a9d11066.webp);
  --s-ips:url(assets/img/struct-02.e4dffca1.webp);
  --s-implementation:url(assets/img/struct-03.38b03d19.webp);
  --s-investments:url(assets/img/struct-04.ede0865a.webp);
  --s-media:url(assets/img/struct-05.096d84ab.webp);
  --s-lab:url(assets/img/struct-06.dcd4770d.webp);
}

.ei{
  display:flex;
  overflow-x:auto;
  overflow-y:hidden;
  scroll-snap-type:x mandatory;
  overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
  gap:12px;
  scrollbar-width:none;
  aspect-ratio:auto;
  container-type:normal;
  width:auto;
}
.ei::-webkit-scrollbar{ display:none }

.ei-cat[data-c]{
  position:relative;
  flex:0 0 84%;                      /* the remaining 16% is the peek */
  scroll-snap-align:start;
  aspect-ratio:4/5;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  padding:22px;
  overflow:hidden;
  background:#0b0a0c;
  border:1px solid var(--hair);      /* replaces the stacked list's border-top */
  transition:border-color .5s var(--ease);
}
.ei-cat[data-c]:last-of-type{ border-bottom:1px solid var(--hair) }

.ei-cat .ei-img{
  position:absolute; inset:0; z-index:0;
  background-size:cover; background-position:center;
  filter:grayscale(.12);
  transform:scale(1.02);
  transition:transform .85s var(--ease), filter .6s;
}
.ei-cat .ei-scrim{
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(0deg,rgba(5,5,5,.92),rgba(5,5,5,.2) 52%,rgba(5,5,5,.42));
  transition:opacity .5s;
}

/* the label sits over the image, bottom-aligned, like .pcard's text */
.ei-cat[data-c] .ei-label{
  position:relative; z-index:2;
  left:auto; top:auto; transform:none;
  width:auto; align-items:flex-start; text-align:left;
}
.ei-cat .ei-num  { opacity:.9 }
.ei-cat .ei-sub  { opacity:.92 }

/* .on mirrors .pcard:hover exactly */
.ei-cat.on            { border-color:rgba(241,232,215,.5) }
.ei-cat.on .ei-img    { transform:scale(1.09); filter:grayscale(0) }
.ei-cat.on .ei-scrim  { opacity:.85 }

/* --------------------------------------------------------------------------
   Section 07's card text, retyped to match section 03.

   Both sections already used Satoshi; what made them read as different faces was the
   treatment, inherited from the orbital diagram where these six were labels floating
   around an SVG rather than card copy:

       was                                   now (section 03's values)
       title 16.5px w500  ls 1.65px          19px w500  ls normal
       body  13.5px w300  ls 0.27px          13px w400  ls normal
       num          w400  ls 3.883px              w400  ls 2.2px

   The body going 300 -> 400 is the change that does most of the work; light weight at
   13px over photography was the thinnest text on the page.

   COLOUR IS A DELIBERATE STEP BRIGHTER than the rest of the site. These cards carry
   full-bleed imagery behind their text, unlike section 03's, so champagne at .92 sat
   too close to the photograph. Opacity is dropped entirely rather than dimmed — the
   scrim below already does that job, and doing it twice was what made the copy murky.

   The all-caps titles are untouched: that is literal text in the HTML, not a
   text-transform, so changing it would mean rewriting copy. */
.ei-cat .ei-num{
  letter-spacing:2.2px;
  color:#FDFAF4;
  opacity:1;
}
.ei-cat .ei-title{
  letter-spacing:normal;
  font-size:19px;
  font-weight:500;
  color:#FDFAF4;
}
.ei-cat .ei-sub{
  letter-spacing:normal;
  font-size:13px;
  font-weight:400;
  line-height:19.5px;
  color:#D8D3C9;
  opacity:1;
}
