
/* ============================================================
   PURVANG MEHTA: DESIGN SYSTEM (v3, 24 Sep 2026)
   Modelled on cal.com: Cal Sans headings, Cal Sans UI for everything
   else, warm neutral greys, a light grey page with white cards, soft
   ring shadows instead of hard borders, near-black buttons. One blue
   accent (the brand) for focus, links and emphasis.

   RULES
   - Every size is a whole, even number on a 4px grid. No decimals.
   - Type is chosen by ROLE, not by size: a section title is
     var(--ds-type-h1) on every page. The roles and where they apply
     are listed in docs/design-system.md.
   - Sizes step at two widths (768px tablet, 1200px desktop) instead of
     sliding with the window; the steps live here and only here.
   ============================================================ */

:root{
  /* ---- colour: cal.com's official palette (cal.com/brand). Brand = #242424,
     the exact colour of the cal.com logo ("800"). No other hue on the site. ---- */
  --ds-gray-100:       #F7F7F7;
  --ds-gray-200:       #E1E2E3;
  --ds-gray-300:       #C0C2C4;
  --ds-gray-400-brand: #858585;   /* cal's 400: too faint for text (fails AA); borders only */
  --ds-gray-500:       #575757;
  --ds-gray-600:       #424242;
  --ds-gray-700:       #343434;
  --ds-gray-800:       #242424;
  --ds-gray-900:       #101010;

  --ds-brand:          var(--ds-gray-800);  /* logo, links, active states, focus  */
  --ds-ink:            var(--ds-gray-800);  /* headings, primary text             */
  --ds-ink-soft:       var(--ds-gray-500);  /* secondary text, labels, the grey
                                               second voice in a heading (AA)    */
  --ds-ink-hover:      var(--ds-gray-600);  /* primary button hover               */
  --ds-ink-press:      var(--ds-gray-900);  /* primary button pressed             */
  --ds-gray-400:       var(--ds-gray-500);  /* smallest legal text colour         */
  --ds-paper:          #FFFFFF;             /* cards                              */
  --ds-paper-soft:     rgba(255, 255, 255, .64);  /* context voice on a dark panel   */
  --ds-surface:        var(--ds-gray-100);  /* page                               */
  --ds-surface-raised: var(--ds-gray-200);  /* tags, pressed fills                */
  --ds-border:         rgba(34, 42, 53, .10);
  --ds-positive:       rgb(76, 217, 175);
  --ds-negative:       rgb(192, 54, 44);
  --ds-highlight:      #FFF1A8;             /* the highlighter (30 Sep 2026): used only by .ds-highlight */
  /* case-study notes (30 Sep 2026): the pins and notes of ::: annotated only, never the site's UI.
     All three clear WCAG AA (4.5:1) on white, so they work as text as well as fills. */
  --ds-cs-issue:       #B42318;             /* what was wrong in a version  */
  --ds-cs-fix:         #1E7A46;             /* what I changed               */
  --ds-cs-note:        #975A00;             /* a plain note                 */

  /* the accent IS the brand now; the names stay so nothing else has to change */
  --ds-accent:         var(--ds-brand);
  --ds-accent-600:     var(--ds-gray-900);
  --ds-accent-200:     var(--ds-gray-300);
  --ds-accent-100:     var(--ds-gray-200);
  --ds-accent-50:      var(--ds-gray-100);
  --ds-link:           var(--ds-brand);

  /* ---- fonts ---- */
  --ds-font-display: "Cal Sans", "Cal Sans UI", system-ui, sans-serif;
  --ds-font-sans:    "Cal Sans UI", system-ui, sans-serif;
  --ds-font-mono:    ui-monospace, "SF Mono", Menlo, monospace;

  /* ---- type roles: weight size/line family (phone values; steps below) ---- */
  --ds-type-display: 600 40px/44px var(--ds-font-display);  /* hero, case-study + article title */
  --ds-track-display: .015em;  /* letter spacing for the display face (28 Sep 2026): Cal Sans is tight by default */
  --ds-type-h1:      600 32px/36px var(--ds-font-display);  /* every section title, big numbers */
  --ds-type-h2:      600 24px/32px var(--ds-font-display);  /* sub-section heading, pull quote  */
  --ds-type-h3:      600 20px/28px var(--ds-font-display);  /* item name: cards, steps, lessons */
  --ds-type-h4:      600 18px/28px var(--ds-font-sans);     /* small heading inside a card      */
  --ds-type-lead:    400 18px/28px var(--ds-font-sans);     /* line under a title, reading text */
  --ds-type-body:    400 16px/24px var(--ds-font-sans);
  --ds-type-small:   400 14px/20px var(--ds-font-sans);     /* meta, captions, small print      */
  --ds-type-ui:      500 14px/20px var(--ds-font-sans);     /* buttons, nav, links              */
  --ds-type-body-strong: 500 16px/24px var(--ds-font-sans); /* a value in a facts row, a large button label */
  --ds-type-caption: 500 12px/16px var(--ds-font-sans);     /* tags and chips only              */
  --ds-type-label:   500 14px/20px var(--ds-font-sans);     /* a label over a group: "In this article", "Read next", "Role" (28 Sep 2026: 12px read too small) */
  --ds-type-art:     600 96px/96px var(--ds-font-display);  /* the 404 number                   */

  /* ---- layout ---- */
  --ds-container:  1200px;
  --ds-section-y:  64px;                 /* top + bottom of every section */
  --ds-head-gap:   32px;                 /* a section's title row -> its content */
  --ds-gap:        24px;                 /* between cards / columns          */
  --ds-gap-lg:     32px;                 /* between large layout columns     */
  --ds-card-pad:   24px;                 /* inside every card                */
  --ds-panel-pad:  32px;                 /* inside large feature panels      */
  --ds-measure:    66ch;
  --ds-media-max:  960px;
  /* One shape for every project image: case-study images, project and build
     thumbnails, article covers. Deliver 2560 x 1440 (16:9), flat #F7F7F7
     ground, no baked-in corners, shadows or borders (the frame adds those).
     build.py audit_images() lists anything off the standard. */
  --ds-media-ratio: 16 / 9;

  /* ---- spacing (4px grid) ---- */
  --ds-space-1: 4px;   --ds-space-2: 8px;   --ds-space-3: 12px;  --ds-space-4: 16px;
  --ds-space-5: 20px;  --ds-space-6: 24px;  --ds-space-8: 32px;  --ds-space-10: 40px;
  --ds-space-12: 48px; --ds-space-16: 64px; --ds-space-20: 80px; --ds-space-24: 96px; --ds-space-32: 128px;

  /* ---- radius ---- */
  --ds-radius-xs:   4px;
  --ds-radius-sm:   8px;
  --ds-radius-md:   12px;    /* buttons, inputs */
  --ds-radius-lg:   16px;    /* cards           */
  --ds-radius-xl:   24px;    /* large panels    */
  --ds-radius-pill: 1000px;  /* tags, badges    */

  /* ---- elevation (cal.com: a ring plus a soft lift, not a border) ---- */
  --ds-shadow-sm:   0 0 0 1px rgba(34, 42, 53, .08);
  --ds-shadow-card: 0 1px 5px -4px rgba(19, 19, 22, .7), 0 0 0 1px rgba(34, 42, 53, .08), 0 4px 8px 0 rgba(34, 42, 53, .05);
  --ds-shadow-lg:   0 24px 64px rgba(0, 0, 0, .12);
  --ds-shadow-inset-dark: inset 0 2px 0 rgba(255, 255, 255, .15);

  /* ---- motion: one language (25 Sep 2026) ----
     --ds-dur-fast  hover, press, a state flip     --ds-dur  something opens, closes or moves
     --ds-dur-slow  an entrance only.  One curve, --ds-ease, a strong ease-out: it starts at once.
     Transform and opacity only; never ease-in; hover only under @media (hover:hover). */
  --ds-ease: cubic-bezier(.16, 1, .3, 1);
  --ds-ease-quint: cubic-bezier(.22, 1, .36, 1);
  --ds-dur-fast: .15s;  --ds-dur: .3s;  --ds-dur-slow: .6s;

  --ds-icon-size: 16px;
  --ds-media-square: 1 / 1;   /* portraits: headshots, avatars. Product images stay --ds-media-ratio */
}
@media (min-width:768px){:root{
  --ds-type-display: 600 48px/52px var(--ds-font-display);
  --ds-type-h1:      600 40px/44px var(--ds-font-display);
  --ds-type-h2:      600 28px/32px var(--ds-font-display);
  --ds-type-h3:      600 24px/32px var(--ds-font-display);
  --ds-type-art:     600 128px/128px var(--ds-font-display);
  --ds-section-y:    96px;
  --ds-head-gap:     40px;
  --ds-gap:          32px;
  --ds-gap-lg:       48px;
  --ds-card-pad:     32px;
  --ds-panel-pad:    48px;
}}
@media (min-width:1200px){:root{
  --ds-type-display: 600 64px/72px var(--ds-font-display);
  --ds-type-h1:      600 48px/52px var(--ds-font-display);
  --ds-type-h2:      600 32px/36px var(--ds-font-display);
  --ds-type-art:     600 160px/160px var(--ds-font-display);
  --ds-gap-lg:       64px;
  --ds-panel-pad:    64px;
}}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-synthesis:none;
  /* iPhone Safari otherwise enlarges long paragraphs on a scaled page (the résumé sheet is zoomed to fit), so
     bullets grew past their line height and overlapped (29 Sep 2026). Sizes come from the tokens, never the browser. */
  -webkit-text-size-adjust:100%;text-size-adjust:100%}
body{margin:0;background:var(--ds-surface);color:var(--ds-ink);
  font:var(--ds-type-body);font-optical-sizing:auto}
a{color:inherit}

/* ============================================================
   2. COMPONENTS
   ============================================================ */

/* BUTTONS: one family, modelled on cal.com. Rounded rectangle (12px), 40px tall
   on a pointer, 44px on touch (WCAG 2.5.5 / Apple HIG floor), 14px medium label.
   Primary = near-black with a soft top highlight; secondary = white card with the
   ring shadow. Every state is designed: hover, pressed, keyboard focus, disabled.
   --lg is the one larger size (hero, résumé, About CTA).
   Social / icon links share .ds-icon-btn: a 40px circle in the secondary style.
   A page never restyles a button locally; it only places it. */
.ds-btn{font:var(--ds-type-ui);display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:40px;padding:0 16px;border:0;border-radius:var(--ds-radius-md);
  cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:background-color var(--ds-dur-fast) var(--ds-ease),color var(--ds-dur-fast) var(--ds-ease),
    box-shadow var(--ds-dur-fast) var(--ds-ease),transform var(--ds-dur-fast) var(--ds-ease)}
.ds-btn svg{flex:none;width:16px;height:16px}
.ds-btn--lg{min-height:48px;padding:0 var(--ds-space-6);font:var(--ds-type-body-strong)}
.ds-btn--primary{background:var(--ds-ink);color:var(--ds-paper);box-shadow:var(--ds-shadow-inset-dark)}
.ds-btn--primary:active{background:var(--ds-ink-press);transform:scale(.97)}
.ds-btn--secondary,.ds-icon-btn{background:var(--ds-paper);color:var(--ds-ink);box-shadow:var(--ds-shadow-card)}
.ds-btn--secondary:active,.ds-icon-btn:active{background:var(--ds-surface-raised);transform:scale(.97)}
/* Hover only where there is a pointer: on touch a hover state sticks after the tap. */
@media (hover:hover){.ds-btn--primary:hover{background:var(--ds-ink-hover)}
  .ds-btn--secondary:hover,.ds-icon-btn:hover{background:var(--ds-surface)}}
.ds-btn:focus-visible,.ds-icon-btn:focus-visible{outline:2px solid var(--ds-accent);outline-offset:2px}
.ds-btn:disabled,.ds-btn[aria-disabled="true"]{opacity:.4;cursor:not-allowed;transform:none;pointer-events:none}
.ds-icon-btn{display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:40px;height:40px;padding:0;border:0;border-radius:50%;cursor:pointer;text-decoration:none;
  transition:background-color var(--ds-dur-fast) var(--ds-ease),transform var(--ds-dur-fast) var(--ds-ease)}
.ds-icon-btn svg{width:var(--ds-icon-size);height:var(--ds-icon-size);display:block;fill:currentColor}
@media (max-width:767.98px){
  .ds-btn:not(.ds-btn--lg){min-height:44px}   /* a large button stays 48px on a phone; it was being cut to 44 */
  .ds-icon-btn{width:44px;height:44px}
}

::selection{background:var(--ds-accent);color:var(--ds-paper)}
:focus-visible{outline:2px solid var(--ds-accent);outline-offset:2px}

/* SURFACES: every boxed thing on the site is one of five roles (ROW, the hairline list item, is defined further down). A component
   never sets its own fill, edge, corner, shadow or padding; it is listed here.
   CARD   a unit of content in a grid or list        white, ring shadow, 16px, card padding
   PANEL  one large feature surface per section      24px corners, panel padding
   FRAME  an image / video / artwork container       soft ring, 16px (8px inside a card)
   TAG    a short label                              pill, 12px text, 24px tall      */
.cs-card,.cs-step,.pm-contact-card,.pm-testi-card,.ab-prin-cell,.pm-shelf-card,.cs-gate-card,.pm-wwm-card,.pm-brand-card,.pm-art-card,.pm-art-key,.ds-cta,.ab-tool-card{
  background:var(--ds-paper);border:0;border-radius:var(--ds-radius-lg);
  box-shadow:var(--ds-shadow-card);padding:var(--ds-card-pad)}
.cs-gate-card{border-radius:var(--ds-radius-xl);box-shadow:var(--ds-shadow-card),var(--ds-shadow-lg)}
.ds-cta{border-radius:var(--ds-radius-xl);padding:var(--ds-panel-pad)}  /* PANEL: the closing "what next" */
.pm-contact-card{padding-block:0}  /* CARD holding rows: each row brings its own top and bottom space */
.pm-work-thumb,.cs-more-thumb,.pm-arts-thumb,.pm-art-ph{
  border:0;border-radius:var(--ds-radius-lg);box-shadow:var(--ds-shadow-sm);overflow:hidden}
.pm-shelf-media,.ab-prin-art{border:0;border-radius:var(--ds-radius-sm);overflow:hidden}
.pm-arts-thumb{border-radius:var(--ds-radius-md)}
.cs-chip,.pm-shelf-tag,.pm-art-tags li,.pm-art-chip{display:inline-flex;align-items:center;min-height:24px;
  padding:4px 12px;border:0;border-radius:var(--ds-radius-pill);
  /* 28 Sep 2026: an outlined label in ink, not a grey fill in grey text (that read as disabled). */
  background:var(--ds-paper);box-shadow:inset 0 0 0 1px var(--ds-border);color:var(--ds-ink);font:var(--ds-type-caption)}

/* section title — base component (About Me is the reference styling);
   two-tone: base ink, <span> soft */
/* COLLECTION: every repeating group (cards, steps, facts, stats, lessons) is one
   .ds-collection. It decides its own columns; a block never writes a grid.
   - The build writes the item count as balanced column counts, one per "most that
     fit" (--b2 ... --b5): 5 items with room for 4 become 3 + 2, never 4 + 1.
   - How many fit is read from the collection's OWN width (a container query), not
     the window, so a group beside the case-study sidebar gets the columns it can hold.
   - A short last row stretches to fill the width, so rows never leave a hole.
   Sizes: default items are at least 200px wide (short cards, steps, stats);
   --lg items at least 280px (items carrying a paragraph; the build picks it);
   --sm items at least 140px (short label + value facts). Thresholds are
   n x min + (n-1) x 32px gap. build.py: ds_collection(); doc: section 3. */
.ds-collection{container-type:inline-size;display:flex;flex-wrap:wrap;
  gap:var(--ds-collection-row-gap,var(--ds-gap)) var(--ds-gap)}
.ds-collection--text{--ds-collection-row-gap:var(--ds-space-8)}  /* unboxed items */
.ds-collection>*{--cols:1;box-sizing:border-box;min-width:0;
  flex:1 1 calc((100% - (var(--cols) - 1) * var(--ds-gap)) / var(--cols))}
@container (min-width:432px){.ds-collection>*{--cols:var(--b2,2)}}
@container (min-width:664px){.ds-collection>*{--cols:var(--b3,3)}}
@container (min-width:896px){.ds-collection>*{--cols:var(--b4,4)}}
.ds-collection--sm>*{--cols:var(--b2,2)}
@container (min-width:484px){.ds-collection--sm>*{--cols:var(--b3,3)}}
@container (min-width:656px){.ds-collection--sm>*{--cols:var(--b4,4)}}
@container (min-width:828px){.ds-collection--sm>*{--cols:var(--b5,5)}}
.ds-collection--lg>*{--cols:1}
@container (min-width:592px){.ds-collection--lg>*{--cols:var(--b2,2)}}
@container (min-width:904px){.ds-collection--lg>*{--cols:var(--b3,3)}}

.ds-section-title{font:var(--ds-type-h1);margin:0;color:var(--ds-ink);
  }
.ds-section-title span{color:var(--ds-ink-soft)}







/* ============================================================
   5. LAYOUT & SECTION POLISH (site-wide)
   ============================================================ */



/* ---- About Me v2 (muhid.de/#work layout) — built by runtime-lite ---- */
.pm-about{display:grid;grid-template-columns:minmax(300px,5fr) 7fr;
  gap:var(--ds-space-8) var(--ds-gap-lg);width:100%;align-items:start}
/* section title: type comes from .ds-section-title; layout-only here */
.pm-about-title{grid-column:1/-1}
.pm-polaroid{background:var(--ds-paper);padding:var(--ds-space-4) var(--ds-space-4) var(--ds-space-12);border-radius:var(--ds-radius-xs);
  box-shadow:0 18px 40px rgb(0 0 0/.14),0 2px 8px rgb(0 0 0/.06);
  transform:rotate(-3deg);width:min(330px,92%);margin:12px 0 var(--ds-space-10) 12px}
.pm-polaroid img{width:100%;aspect-ratio:1/1;object-fit:cover;display:block;border-radius:var(--ds-radius-xs)}
.pm-about-facts p{font:var(--ds-type-lead);margin:0;color:var(--ds-ink);}
.pm-about-socslot{margin-top:32px}
.pm-about-socslot>div{display:flex!important;flex-wrap:wrap;gap:8px;
  width:auto!important;height:auto!important;position:relative!important}
.pm-about-sigslot{margin:var(--ds-space-1) 0 var(--ds-space-8)}
.pm-about-head{font:var(--ds-type-h2);margin:0;color:var(--ds-ink-soft)}
.pm-about-head .pm-em{color:var(--ds-ink)}
.pm-about-lede{font:var(--ds-type-lead);margin:24px 0 24px;color:var(--ds-ink-soft);max-width:62ch}
.pm-worklist{list-style:none;margin:0;padding:0;width:100%}
.pm-worklist li{border-bottom:1px solid var(--ds-border)}
.pm-worklist button{display:flex;justify-content:space-between;align-items:center;gap:16px;
  width:100%;padding:var(--ds-space-6) 0;background:none;border:0;cursor:pointer;text-align:left}
.pm-worklist strong{font:var(--ds-type-h4);color:var(--ds-ink)}
.pm-worklist button>span{font:var(--ds-type-body);display:inline-flex;align-items:center;gap:12px;
  color:var(--ds-ink-soft);white-space:nowrap}
.pm-worklist svg{width:15px;height:15px;flex:0 0 auto;
  transition:transform var(--ds-dur) var(--ds-ease)}
.pm-worklist li.open svg{transform:rotate(180deg)}
.pm-workbody{max-height:0;overflow:hidden;transition:max-height var(--ds-dur) var(--ds-ease)}
.pm-worklist li.open .pm-workbody{max-height:220px}
.pm-workbody p{font:var(--ds-type-body);margin:0 0 24px;color:var(--ds-ink-soft);}
@media (max-width:900px){
  .pm-about{grid-template-columns:1fr;gap:40px}
  .pm-polaroid{margin:var(--ds-space-2) auto var(--ds-space-8)}
}




/* ============================================================
   6. PROJECT CARDS (muhid case-study pattern)
   soft rounded media card + corner chip; title/description
   caption sits below the card on the page surface.
   ============================================================ */


/* ============================================================
   7. HERO CARD (uxdayshankar pattern, home page)
   hero + client logos live inside one white rounded card
   floating on the gray page surface.
   ============================================================ */
/* the card floats on the gray surface: equal air below the nav (~48px),
   below the card (48px), and inside above the badge */
#pm-hero-wrap{display:flex;flex-direction:column;align-items:center;width:100%;
  position:relative;z-index:1;padding-bottom:48px}
/* hero subhead: step up to the lede size in the type scale (was body 16px) */
.pm-hero-cta{display:flex;gap:12px;justify-content:center;margin-top:32px;flex-wrap:wrap}
.pm-hero-cta .ds-btn{min-width:200px} /* equal widths so the pair reads balanced */
@media (max-width:767.98px){
  #pm-hero-wrap{padding-bottom:24px}
  /* The hero card follows the same 24px gutter as the rest of the page. */
  /* the mobile hero headline is an h2 in the phone variant — give it real
     presence (was 26px) */
  /* the original export locks the hero text block to a fixed 262px on mobile — free it
     so the headline breathes and the CTA row has room */
  /* stack the two pills full-width on mobile so the pair reads balanced */
  .pm-hero-cta{flex-direction:column;align-items:center;flex-wrap:nowrap;width:100%}
  .pm-hero-cta .ds-btn{width:100%;max-width:300px;min-width:0}}


/* ============================================================
   8. VISUAL EXPLORATIONS — dual marquee (reference: uxdayshankar
   "Selected interfaces"): two rows auto-scroll in opposite
   directions; hover pauses.
   ============================================================ */
/* Room for the cards' shadows (28 Sep 2026): the strip clips and masks to its own box, so the shadows need to be
   inside it. Padding above and below, taken back with a negative margin so the page spacing is unchanged. */
.pm-gal{--pm-fade:140px;--pm-gal-room:var(--ds-space-8);display:flex;flex-direction:column;gap:20px;width:100%;max-width:var(--ds-container);
  margin-left:auto;margin-right:auto;overflow:hidden;padding-block:var(--pm-gal-room);margin-block:calc(var(--pm-gal-room) * -1);
  -webkit-mask:linear-gradient(90deg,transparent,#000 var(--pm-fade),#000 calc(100% - var(--pm-fade)),transparent);
  mask:linear-gradient(90deg,transparent,#000 var(--pm-fade),#000 calc(100% - var(--pm-fade)),transparent)}
@media (max-width:767.98px){.pm-gal{--pm-fade:36px}}
.pm-gal-track{display:flex;gap:20px;width:max-content;animation:pm-gal-scroll 45s linear infinite}
/* the testimonial marquee pauses on hover (quotes need reading time) */
.pm-testi:hover .pm-gal-track{animation-play-state:paused}
.pm-testi{margin-top:0}
.pm-testi .pm-gal-track{animation-duration:38s;align-items:stretch}
.pm-testi-card{width:min(388px,85vw)!important;min-width:min(388px,85vw)!important;
  max-width:min(388px,85vw)!important;flex:0 0 auto!important;height:auto!important;
  transform:none!important;margin:0!important; /* no staggered offsets: one row, one height */
  align-self:stretch!important;display:flex!important;flex-direction:column!important;
  
  }
/* all cards match the tallest: quote area absorbs the slack */
.pm-testi-card *{min-width:0!important;max-width:100%!important;white-space:normal!important}
@keyframes pm-gal-scroll{to{transform:translateX(-50%)}}
/* Global reduced-motion guard. Covers the hand-built pages AND the leftover
   the original export animations (hero splash, marquee, reveals) that shipped without one.
   Near-instant instead of fully off so state changes still read. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  .pm-gal-track{animation:none!important}
}


/* ---- Mobile layout: one gutter, unframed section headings ---- */
@media (max-width:767.98px){
  :root{--pm-mobile-gutter:24px}

  /* the original export applies a second horizontal inset on several nested wrappers.
     Sections own the gutter; their content wrappers stay flush to it. */

  /* Section titles remain plain, left-aligned content rather than framed blocks. */
  #projects h2,#explorations h2,#testimonials h2,.pm-about-title{
    width:auto!important;margin:0!important;padding:0!important;
    background:transparent!important;border:0!important;text-align:left!important;
  }
  .pm-sec-head{flex-wrap:nowrap!important;align-items:baseline!important;gap:16px!important}
  .pm-sec-head>div:first-child{flex:1 1 auto!important}
}

/* ---- font faces: Cal Sans (headings) + Cal Sans UI (everything else), both
   SIL Open Font License (fonts/OFL-cal-sans.txt), self-hosted from fonts/.
   Cal Sans UI is one variable file: weight 400-700 and an optical-size axis
   that reshapes letters for small text vs large, which is most of the
   cal.com look. Trimmed to the characters the site uses. ---- */
@font-face{font-family:"Cal Sans";src:url(fonts/cal-sans.woff2) format("woff2");
  font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:"Cal Sans UI";src:url(fonts/cal-sans-ui.woff2) format("woff2");
  font-weight:400 700;font-style:normal;font-display:swap}

/* ============================================================
   LEGAL PAGES (terms, privacy-policy)
   Content-driven (content/<slug>.json), rebuilt onto the type
   system. One reading measure, clean h1>h2>h3>h4 hierarchy.
   ============================================================ */
main.legal{background:var(--ds-paper);padding:var(--pm-page-top) var(--ds-space-6) var(--ds-section-y)}
.legal-inner{max-width:720px;margin:0 auto}
.legal-head{margin-bottom:var(--ds-space-12);padding-bottom:var(--ds-space-6);
  border-bottom:1px solid var(--ds-border)}
.legal-title{font:var(--ds-type-h1);margin:0;color:var(--ds-ink);
  }
.legal-updated{font:var(--ds-type-small);margin:var(--ds-space-3) 0 0;color:var(--ds-ink-soft);
  }
.legal-h{color:var(--ds-ink);
  text-wrap:balance}
.legal-h2{font:var(--ds-type-h2);
  margin:var(--ds-space-16) 0 var(--ds-space-5)}
.legal-h2:first-of-type{margin-top:0}
.legal-h3{font:var(--ds-type-h3);
  margin:var(--ds-space-10) 0 var(--ds-space-4)}
.legal-h4{font:var(--ds-type-h4);
  margin:var(--ds-space-6) 0 var(--ds-space-3);color:var(--ds-ink)}
.legal-p{font:var(--ds-type-lead);margin:0 0 var(--ds-space-5);max-width:66ch;color:var(--ds-ink-soft);
  text-wrap:pretty}
.legal-ul{margin:0 0 var(--ds-space-6);padding:0;list-style:none;
  display:flex;flex-direction:column;gap:var(--ds-space-3)}
.legal-ul li{font:var(--ds-type-lead);position:relative;padding-left:var(--ds-space-6);max-width:66ch;
  color:var(--ds-ink-soft);}
.legal-ul li::before{content:"";position:absolute;left:4px;top:.62em;
  width:6px;height:6px;border-radius:50%;background:var(--ds-accent)}
.legal-note{font:var(--ds-type-lead);font-weight:500;margin:var(--ds-space-16) 0 0;padding-top:var(--ds-space-6);
  border-top:1px solid var(--ds-border);max-width:66ch;color:var(--ds-ink);
  }

@media (max-width:760px){
  main.legal{padding:var(--pm-page-top) var(--ds-space-5) var(--ds-section-y)}
  .legal-title{font:var(--ds-type-h1)}
  .legal-h2{font:var(--ds-type-h2);margin-top:var(--ds-space-12)}
  .legal-h3{font:var(--ds-type-h3)}
}

/* ============================================================
   WORK CARDS — shared by the projects page + home 'Selected work'
   ============================================================ */
/* Work page sits on the grey body (no floating white panel); flows into the
   white footer below. Left-aligned editorial header, then the card grid. */
main.work{background:transparent;max-width:calc(var(--ds-container) + var(--ds-space-6)*2);
  margin:0 auto;padding:var(--pm-page-top) var(--ds-space-6) var(--ds-section-y)}
.work-head{max-width:60ch;margin:0 0 var(--ds-head-gap)}
.work-sub{font:var(--ds-type-lead);margin:var(--ds-space-5) 0 0;max-width:52ch;color:var(--ds-ink-soft);
  }
.pm-work-thumb{display:block;overflow:hidden;aspect-ratio:var(--ds-media-ratio);background:var(--ds-paper)}
.pm-work-thumb img{width:100%;height:100%;object-fit:cover;display:block}
/* The case-study cards are the shared product card now (.pm-shelf-* / .pm-case-card, 28 Sep 2026). */
@media (max-width:760px){
  main.work{padding:var(--pm-page-top) var(--ds-space-5) var(--ds-section-y)}
  .work-head{margin-bottom:var(--ds-head-gap)}
}
/* Home 'Selected work' section (same grid, section chrome) */
.pm-work-sec{background:var(--ds-paper);padding:var(--ds-space-24) var(--ds-space-6)}
.pm-work-wrap{max-width:1200px;margin:0 auto}
.pm-work-head{display:flex;align-items:center;justify-content:space-between;
  gap:var(--ds-space-4);margin-bottom:var(--ds-space-10)}
/* consistent title -> content gap across home sections (explorations,
   testimonials). Double-class beats .pm-home-wrap's later `margin:0 auto`. */
.pm-home-wrap.pm-home-head{margin-bottom:var(--ds-space-10)}

/* ---- scroll reveal (progressive enhancement, site-wide) ----
   Only below-fold elements the JS marks get hidden; default is visible, so
   no-JS / reduced-motion / already-in-view users always see everything. */
.pm-reveal{opacity:0;transform:translateY(14px);
  transition:opacity var(--ds-dur-slow) var(--ds-ease),transform var(--ds-dur-slow) var(--ds-ease)}
/* Items of one collection arrive one after another, 60ms apart, so a row reads as a row. */
.ds-collection>.pm-reveal:nth-child(2){transition-delay:60ms}
.ds-collection>.pm-reveal:nth-child(3){transition-delay:120ms}
.ds-collection>.pm-reveal:nth-child(n+4){transition-delay:180ms}
.pm-reveal.is-in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.pm-reveal{opacity:1;transform:none;transition:none}}
.pm-work-viewall{flex:none} /* a .ds-btn--secondary; this class only places it in the head row */
@media (max-width:760px){.pm-work-sec{padding:var(--ds-space-16) var(--ds-space-5)}}

/* ============================================================
   STATIC HOME sections (rebuilt): hero-wrap, section shell,
   socials, signature, testimonial-card internals, 404.
   ============================================================ */
#pm-hero-wrap{min-height:100vh;min-height:100dvh;justify-content:center;padding-top:120px;
  /* FigJam-style dot-grid canvas: reads as a designer's working space.
     Scoped to the hero scene only, so it never bleeds into the sections below. */
  background-color:var(--ds-surface);
  background-image:radial-gradient(rgba(17,17,17,.14) 1.15px, transparent 1.45px);
  background-size:24px 24px;background-position:center top}
.pm-home-sec{padding:var(--ds-space-24) var(--ds-space-6);background:var(--ds-paper)}
.pm-home-sec--gray{background:var(--ds-surface)}
#about-me.pm-home-sec{background:var(--ds-surface)}
.pm-home-wrap{max-width:var(--ds-container);margin:0 auto}
.ds-section-title span,.pm-about-title span,
#explorations h2 span,#testimonials h2 span{color:var(--ds-ink-soft)}
.pm-about-socslot>div{gap:12px!important}
.pm-sig{display:block;height:60px;width:auto;opacity:.92}
/* testimonial card internals (static; equal heights via flex stretch, no JS) */
.pm-testi-head{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.pm-testi-av{width:46px;height:46px;border-radius:50%;object-fit:cover;flex:0 0 auto}
.pm-testi-who{min-width:0}
.pm-testi-name{font:var(--ds-type-body);font-weight:600;margin:0;color:var(--ds-ink);}
.pm-testi-role{font:var(--ds-type-small);margin:2px 0 0;color:var(--ds-ink-soft);}
.pm-testi-quote{font:var(--ds-type-body);margin:0;flex:1 1 auto;color:var(--ds-ink-soft);}
.pm-testi-card{justify-content:flex-start!important}
/* 404 */
.pm-404{min-height:68vh;display:flex;align-items:center;justify-content:center;
  padding:var(--ds-space-32) var(--ds-space-6) var(--ds-space-24);text-align:center}
.pm-404-inner{max-width:520px}
.pm-404-big{font:var(--ds-type-art);margin:0;color:var(--ds-ink);
  }
.pm-404-title{font:var(--ds-type-h1);margin:8px 0 0;color:var(--ds-ink);}
.pm-404-sub{font:var(--ds-type-lead);margin:var(--ds-space-3) 0 var(--ds-space-6);color:var(--ds-ink-soft);}
.pm-404-btn{display:inline-flex}
@media (max-width:767.98px){.pm-home-sec{padding:var(--ds-space-16) var(--ds-space-5)}}

/* DOTS: the home page's dot field, as one utility (25 Sep 2026). Any full-bleed surface that needs
   texture (the NDA gate, the Work with me hero) adds .ds-dots; never re-type the gradient. */
.ds-dots{background-color:var(--ds-surface);
  background-image:radial-gradient(rgba(17,17,17,.14) 1.15px, transparent 1.45px);
  background-size:24px 24px;background-position:center top}

/* ICON BADGE: the line icon at the head of a card (25 Sep 2026). Just the icon, 24px, in ink: the grey
   circle it first sat in added a shape without a meaning (his call, the same evening). Not a button. */
.ds-icon-badge{display:inline-flex;align-items:center;justify-content:center;flex:none;width:24px;height:24px;
  color:var(--ds-ink)}
.ds-icon-badge svg{width:24px;height:24px;display:block}
/* MARK: a service's real logo beside a link that opens it (cal.com, Topmate, LinkedIn...). Drawn by
   ds_mark(); a brand mark keeps its owner's shape and colour, so no fill, radius or border here. */
.ds-mark{display:block;flex:none;width:24px;height:24px;object-fit:contain}


/* DOT: the full stop from the logo as a mark (25 Sep 2026). 8px, brand ink. --live is the positive
   green and breathes (Open to new projects, the gate's Waiting for approval). The menu's 4px
   current-page mark is the same shape. One motif, three jobs; never a new mascot. */
.ds-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--ds-brand);flex:none}
.ds-dot--live{background:var(--ds-positive);animation:ds-pulse 1.6s var(--ds-ease) infinite}
@keyframes ds-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.8)}}
@media (prefers-reduced-motion:reduce){.ds-dot--live{animation:none}}

/* LINK: every link inside running text (25 Sep 2026). A hairline at rest; on hover the ink line draws
   in from the left. Listed here like the surfaces; a page never underlines a link on its own. */
.ds-link,.pm-sec-lede a,.pm-art-body a,.legal-p a,.legal-ul a,.legal-note a,.pm-contact-value a,
.cs-gate-sub a,.cs-gate-ask a,.pm-arts-empty a,.pm-wwm-v a,.cs-body p a{
  color:var(--ds-ink);text-decoration:none;
  background-image:linear-gradient(currentColor,currentColor),linear-gradient(var(--ds-border),var(--ds-border));
  background-size:0 1px,100% 1px;background-position:0 100%,0 100%;background-repeat:no-repeat;
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
  transition:background-size var(--ds-dur) var(--ds-ease)}
@media (hover:hover){
  .ds-link:hover,.pm-sec-lede a:hover,.pm-art-body a:hover,.legal-p a:hover,.legal-ul a:hover,.legal-note a:hover,
  .pm-contact-value a:hover,.cs-gate-sub a:hover,.cs-gate-ask a:hover,.pm-arts-empty a:hover,.pm-wwm-v a:hover,
  .cs-body p a:hover{background-size:100% 1px,100% 1px}}

/* HIGHLIGHT: a highlighter stroke over one phrase (30 Sep 2026, his ask). The only colour outside the greys, and
   it is a human annotation, not decoration: at most one phrase in view, the words stay ink (the point is
   dark). It draws in from the left like the LINK line, but only after its container has arrived (the
   --ds-dur-slow delay), inside a hand-drawn edge (the mask), tilted a degree. One line only (nowrap).
   What turns it on belongs to the context, e.g. `.pm-note.in .ds-highlight::before` for the home cards. */
.ds-highlight{position:relative;isolation:isolate;white-space:nowrap;font-weight:600}
.ds-highlight::before{content:"";position:absolute;z-index:-1;left:-.16em;right:-.2em;top:-.08em;bottom:-.2em;
  background-image:linear-gradient(var(--ds-highlight),var(--ds-highlight));background-repeat:no-repeat;background-size:0 100%;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20' preserveAspectRatio='none'%3E%3Cpath d='M2.5 4.2C20 2.8 38 3.9 56 3.1C72 2.4 86 3.3 97.6 2.2L99.2 9.6C98.4 12.8 99.4 15.6 97.9 18.4C80 17.3 62 18.6 44 17.8C28 17.1 14 18.5 1.6 17.6L.8 10.8C1.9 8.2.6 6.4 2.5 4.2Z'/%3E%3C/svg%3E") 0 0/100% 100% no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20' preserveAspectRatio='none'%3E%3Cpath d='M2.5 4.2C20 2.8 38 3.9 56 3.1C72 2.4 86 3.3 97.6 2.2L99.2 9.6C98.4 12.8 99.4 15.6 97.9 18.4C80 17.3 62 18.6 44 17.8C28 17.1 14 18.5 1.6 17.6L.8 10.8C1.9 8.2.6 6.4 2.5 4.2Z'/%3E%3C/svg%3E") 0 0/100% 100% no-repeat;
  transform:rotate(-1deg);
  transition:background-size var(--ds-dur-slow) var(--ds-ease) var(--ds-dur-slow)}
@media (prefers-reduced-motion:reduce){.ds-highlight::before{transition:none}}

/* ROW: the fifth surface (25 Sep 2026): one item of a hairline-divided list (a question, a fact).
   No fill, no box padding; 56px tall when closed, and the whole row is the control. As a <details>
   it opens in --ds-dur (browsers without interpolate-size open at once), and name= makes the list
   an accordion: one open at a time. */
.ds-rows{border-top:1px solid var(--ds-border)}
.ds-row{border-bottom:1px solid var(--ds-border);interpolate-size:allow-keywords}
.ds-row>summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;
  gap:var(--ds-space-4);min-height:56px;padding:var(--ds-space-3) 0;font:var(--ds-type-h4);color:var(--ds-ink)}
.ds-row>summary::-webkit-details-marker{display:none}
.ds-row>summary:focus-visible{outline:2px solid var(--ds-accent);outline-offset:2px;border-radius:var(--ds-radius-sm)}
.ds-row-icon{flex:none;width:20px;height:20px;color:var(--ds-ink-soft);transition:transform var(--ds-dur) var(--ds-ease),color var(--ds-dur-fast) var(--ds-ease)}
.ds-row[open]>summary .ds-row-icon{transform:rotate(45deg)}
@media (hover:hover){.ds-row>summary:hover .ds-row-icon{color:var(--ds-ink)}}
.ds-row::details-content{height:0;overflow:hidden;
  transition:height var(--ds-dur) var(--ds-ease),content-visibility var(--ds-dur) allow-discrete}
.ds-row[open]::details-content{height:auto}
.ds-row-body{font:var(--ds-type-body);color:var(--ds-ink-soft);margin:0;padding:0 0 var(--ds-space-5);max-width:var(--ds-measure)}
@media (prefers-reduced-motion:reduce){.ds-row::details-content,.ds-row-icon{transition:none}}

/* FRAME, square: a portrait (the headshot, an avatar). Sits after every FRAME ratio rule on purpose, so it
   wins by order. Product images keep --ds-media-ratio. (25 Sep 2026) */
.ds-frame--square{aspect-ratio:var(--ds-media-square)}

/* ACTIONS: a row of buttons under a title or a lede (25 Sep 2026). 12px between buttons, one head gap
   above. Any page that places two buttons uses this; never a page-level flex row. */
.ds-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ds-space-3);margin-top:var(--ds-head-gap)}

/* ICON: one set, Lucide, the one cal.com uses (25 Sep 2026). Drawn by ds_icon() in build.py from icons/:
   24 grid, 2px stroke, round caps and joins, currentColor. 16px beside text or in a button, 20px in a
   40px circle or at a card's head, 12px in a tag. A brand mark (a social logo, the Figma mark) is not an
   icon and keeps its owner's drawing. Never hand-draw a path. */
.ds-icon{display:block;flex:none}

/* BAND: a full-width section with its own tone (25 Sep 2026). Sections alternate white and grey so the eye
   sees where one ends; the home page did this by hand (.pm-home-sec), any page does it with .ds-band. */
.ds-band{background:var(--ds-paper);padding-block:var(--ds-section-y)}
.ds-band--surface{background:var(--ds-surface)}

/* BENTO: a services or features grid where size shows importance (25 Sep 2026). The first tile is the lead
   (two rows tall beside two stacked tiles from 1024px; full width on a tablet); each tile is mostly picture
   with a short title and one line. Tiles are CARDs and stretch to their row. */
.ds-bento{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--ds-gap)}
.ds-bento>*{display:flex;flex-direction:column}
@media (min-width:768px){.ds-bento{grid-template-columns:repeat(2,minmax(0,1fr))}.ds-bento>:first-child{grid-column:1 / -1}}
@media (min-width:1024px){.ds-bento{grid-template-columns:minmax(0,3fr) minmax(0,2fr);grid-auto-rows:1fr}
  .ds-bento>:first-child{grid-column:auto;grid-row:span 2}}

/* DARK: the ink surface (25 Sep 2026), used by the footer so every page has a clear end. Text is paper, the
   context voice is paper-soft; buttons invert: primary is a paper fill, secondary a hairline outline. */
.ds-dark{background:var(--ds-ink);color:var(--ds-paper)}
.ds-dark .ds-btn--primary{background:var(--ds-paper);color:var(--ds-ink);box-shadow:none}
.ds-dark .ds-btn--secondary,.ds-dark .ds-icon-btn{background:transparent;color:var(--ds-paper);box-shadow:inset 0 0 0 1px var(--ds-ink-soft)}
@media (hover:hover){
  .ds-dark .ds-btn--primary:hover{background:var(--ds-surface-raised)}
  .ds-dark .ds-btn--secondary:hover,.ds-dark .ds-icon-btn:hover{background:var(--ds-gray-700)}}
.ds-dark .ds-btn:focus-visible,.ds-dark .ds-icon-btn:focus-visible,.ds-dark a:focus-visible{outline-color:var(--ds-paper)}

/* BENTO, row: three tiles of one size in one row from 1024px, so the whole section fits one laptop screen
   (his call, 25 Sep 2026: a lead tile two rows tall ran past the viewport). */
@media (min-width:1024px){.ds-bento--row{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:auto}
  .ds-bento--row>:first-child{grid-row:auto;grid-column:auto}}

/* CLOSING PANEL (ds-cta, 28 Sep 2026): the one "what next" on the site, at the end of every article and of
   About. Words and buttons on the left; a device picture on the right, anchored left so the device runs
   off the panel's edge on purpose. On a phone the picture sits on top. build.py: ds_cta(). */
.ds-cta-title{font:var(--ds-type-h2);margin:0;color:var(--ds-ink)}
.ds-cta-title span{color:var(--ds-ink-soft)}
.ds-cta-text{font:var(--ds-type-lead);margin:var(--ds-space-2) 0 0;color:var(--ds-ink-soft)}
.ds-cta-list{list-style:none;margin:var(--ds-space-5) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--ds-space-2)}
.ds-cta-list li{font:var(--ds-type-small);color:var(--ds-ink-soft)}
.ds-cta-list strong{font-weight:500;color:var(--ds-ink)}
.ds-cta .ds-actions{margin-top:var(--ds-space-6)}
.ds-cta .ds-btn{display:inline-flex;align-items:center;gap:var(--ds-space-2)}
.ds-cta--pic{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);align-items:stretch;padding:0;overflow:hidden}
.ds-cta--pic .ds-cta-copy{padding:var(--ds-panel-pad);align-self:center}
.ds-cta-pic{display:block;width:100%;height:100%;min-height:100%;object-fit:cover;object-position:0 50%;aspect-ratio:4/3}
@media (max-width:767.98px){.ds-cta--pic{display:flex;flex-direction:column}
  .ds-cta-pic{order:-1;height:auto;min-height:0;aspect-ratio:16/9;object-position:50% 50%}}

/* PRODUCT CARD (28 Sep 2026): one card for everything the site shows as a product: Personal builds and the
   case studies. The device mockup on top, name, tag, up to three lines, the button on the floor. Moved here
   from the Builds page so the Work grids share it. */
/* The card is the collection's item: it takes the collection's column width and stretches to the row. */
.pm-shelf-card{display:flex;flex-direction:column;height:auto;
  
  }

/* The image is taken OUT of the height calculation. Left in normal flow, an <img> at
   width:100% reports its own intrinsic ratio as the box height, which is how a square
   photo once dictated the height of the whole card. */
.pm-shelf-media{position:relative;margin:0 0 20px;overflow:hidden;
  background:var(--ds-surface);aspect-ratio:var(--ds-media-ratio)}
.pm-shelf-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* One flex column per card, and the button row is pushed to the floor. With cards of
   equal height and copy of unequal length, that is what puts every CTA on the same
   line across the row instead of wherever its paragraph happened to end. */
/* No horizontal padding of its own. It had 8px, which put every line of text on a
   different left edge from the photograph directly above it, at both breakpoints. The
   card's own padding is the only inset now, so image, title, copy and button share one
   edge. */
.pm-shelf-body-col{display:flex;flex-direction:column;flex:1}

/* Name, then the tag on its own line (25 Sep 2026): beside the name it wrapped under long names only, so three
   cards in a row showed the tag in three places. */
.pm-shelf-titlerow{display:flex;flex-direction:column;align-items:flex-start;gap:var(--ds-space-2)}
.pm-shelf-name{font:var(--ds-type-h3);margin:0;
  color:var(--ds-ink)}
/* Beside the name, not above it: above reads as a category heading and sorts the page
   into two classes of thing, which is the one thing this label must not do. */
/* Optically centred on the title's first line. Its own box is a touch shorter than
   the line it sits in, so it needs a hair of offset, not the eyeballed 4px that had
   it sitting visibly low once the title stepped down a size. */
.pm-shelf-tag{font:var(--ds-type-caption);flex:none;
  white-space:nowrap}

/* One block of copy, not a pull-quote followed by a paragraph explaining it. Two
   text weights in a card this size split the reader's attention between them and
   neither got read. */
.pm-shelf-body{font:var(--ds-type-body);margin:16px 0 0;color:var(--ds-ink-soft);
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;line-clamp:3;overflow:hidden}
/* Three lines at most (28 Sep 2026). The copy in builds.json is written to fit three lines on a phone;
   the clamp is only the safety net for a future entry that runs long. */


.pm-shelf-links{display:flex;flex-wrap:wrap;gap:var(--ds-space-2);margin-top:auto;padding-top:var(--ds-space-6)}
/* Back to the page's ink. Accent made it the loudest thing on a card whose job is to
   show a photograph, and a blue button on two cards side by side read as two warnings.
   Size carries the emphasis instead: it spans the card, which is the same full-width
   behaviour the design system's own buttons already have. */
/* Side by side, sharing the width equally; a single button still spans the card (28 Sep 2026). */
.pm-shelf-links{display:flex;gap:var(--ds-space-3)}
.pm-shelf-more{font:var(--ds-type-ui);margin:var(--ds-space-3) 0 0}
.pm-shelf-more a{display:inline-flex;align-items:center;gap:var(--ds-space-1)}
.pm-shelf-links .ds-btn{display:flex;flex:1 1 0;min-width:0}
.pm-shelf-media{display:block}
/* A little tighter than the default card (28 Sep 2026): the picture is the point, so it gets the room. */
.pm-shelf-card{padding:var(--ds-space-6)}
.pm-shelf-media{margin-bottom:var(--ds-space-5)}
.pm-case-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--ds-gap)}
@media (max-width:767.98px){.pm-case-grid{grid-template-columns:minmax(0,1fr)}.pm-shelf-card{padding:var(--ds-space-5)}}
.pm-case-card{text-decoration:none;color:inherit;transition:transform var(--ds-dur) var(--ds-ease)}
.pm-case-card .pm-shelf-media img{transition:transform var(--ds-dur-slow) var(--ds-ease)}
.pm-case-card .pm-shelf-body{display:-webkit-box}
@media (hover:hover){.pm-case-card:hover{transform:translateY(-4px)}.pm-case-card:hover .pm-shelf-media img{transform:scale(1.03)}}
@media (prefers-reduced-motion:reduce){.pm-case-card,.pm-case-card .pm-shelf-media img{transition:none}.pm-case-card:hover{transform:none}}
/* The whole card opens the case study through the button's link, stretched over it; the store marks sit above that
   link as links of their own (1 Oct 2026). */
.pm-case-card{position:relative}
.pm-case-link::after{content:"";position:absolute;inset:0;border-radius:inherit}
.pm-shelf-tagrow{display:flex;align-items:center;gap:var(--ds-space-2)}
.pm-case-stores{display:inline-flex;align-items:center;gap:var(--ds-space-1)}
.pm-case-store{position:relative;z-index:1;display:inline-flex;padding:var(--ds-space-1);border-radius:var(--ds-radius-sm)}
/* A store link is a 44px tap target (the site's rule) that still looks 28px: the extra is padding the row doesn't see. */
a.pm-case-store{padding:var(--ds-space-3);margin:calc(var(--ds-space-2) * -1)}
.pm-case-store .ds-mark{display:block;width:var(--ds-space-5);height:var(--ds-space-5)}
a.pm-case-store:hover{background:var(--ds-surface)}

/* DISPLAY TRACKING (28 Sep 2026, his call: titles felt cramped). Everything set in Cal Sans gets a touch of space.
   The type tokens are font shorthands, which can't carry letter-spacing, so it is applied here once. */
h1,h2,h3,.ds-section-title,.pm-hero-title,.pm-beat,.pm-footer-cta,.pm-about-head,.pm-shelf-name,.pm-art-title,
.pm-art-h1,.ds-cta-title,.pm-art-stat-v,.ab-tool-k,.pm-wwm-k,.pm-cv-name,.pm-cv-dlgtitle,.pm-brand-sample{
  letter-spacing:var(--ds-track-display)}

