/* ============================================================
   HOMEPAGE
   ------------------------------------------------------------
   Measured against Figma frame 3:27 "Homepage — Desktop 1440".
   Section order there is fixed: masthead, about, work,
   experience, contact, footer. There is no top nav and no
   full-bleed band in the design; both were removed.

   At a 1440 viewport --pad-x resolves to 58px, so the content
   column is 1324px, matching the Figma frame exactly.
   ============================================================ */

/* ---------- MASTHEAD (4:2) ---------- */
.masthead{
  min-height:min(76svh,700px);
  display:flex;flex-direction:column;justify-content:flex-end;
  padding-top:clamp(90px,14vh,150px);
  padding-bottom:clamp(22px,3.4vh,42px);
}
.wordmark{
  font-size:min(17.8vw,18.9rem);   /* measured on the web build, not the Figma px */
  font-weight:700;
  font-variation-settings:"wdth" 96;
  letter-spacing:-.04em;
  line-height:.84;
  color:var(--blue);
  margin-bottom:clamp(20px,3vw,40px);
}
.wordmark .stop{color:var(--hot)}
/* authored moment: the mark lays down like ink. Gated behind .js so the
   first viewport is never blank when script is blocked or slow. */
/* The wipe clips to the border box, but line-height .84 makes that box
   shorter than the glyphs: the descender of the j in "Ojas" hangs about
   18px below it and was being cut off. Negative vertical insets keep the
   clip purely horizontal so only the wipe direction is constrained. */
.js .wordmark{clip-path:inset(-25% 100% -45% 0)}
body.lit .wordmark{clip-path:inset(-25% 0 -45% 0);transition:clip-path 1.15s var(--ease) .1s}

.mh-foot{
  display:flex;justify-content:space-between;align-items:flex-end;
  gap:24px;flex-wrap:wrap;
  border-top:1.5px solid var(--ink);
  padding-top:16px;
}
.mh-foot p{font-size:clamp(1rem,1.25vw,1.125rem);line-height:1.35;max-width:34ch}
.js .mh-foot p{opacity:0;transform:translateY(10px)}
body.lit .mh-foot p{
  opacity:1;transform:none;
  transition:opacity .7s var(--ease) .72s,transform .7s var(--ease) .72s;
}
body.lit .mh-foot p:last-child{transition-delay:.82s}
.mh-right{display:flex;flex-direction:column;align-items:flex-end;text-align:right}
.avail{display:inline-flex;align-items:center;gap:9px;color:var(--hot-ink);font-weight:600}
.avail .dot{width:8px;height:8px;border-radius:50%;background:var(--hot);flex:none}

/* ---------- ABOUT / STATEMENT (9:43) — drenched ultramarine ---------- */
.statement{
  background:var(--blue);color:var(--paper);
  padding-block:clamp(72px,9.5vw,137px);
}
.st-grid{
  border-top:1.5px solid var(--rule-on-blue);
  padding-top:36px;
  display:grid;grid-template-columns:687fr 565fr;
  column-gap:72px;row-gap:clamp(40px,5vw,64px);
  align-items:start;
}
.st-left{grid-column:1}
.portrait{grid-column:2}
.software{grid-column:1 / -1}
.st-left{display:flex;flex-direction:column;gap:44px}
.st-lead{
  font-size:var(--step-h2);font-weight:700;
  line-height:.98;letter-spacing:-.038em;color:var(--paper);
}
.st-lead em{font-style:normal;color:var(--on-blue-dim)}
.st-body{display:flex;flex-direction:column;gap:24px}
.st-body p:first-child{font-size:var(--step-lead);line-height:1.42;color:var(--paper)}
.st-body p:last-child{font-size:var(--step-body);line-height:1.5;color:var(--on-blue-dim)}

.portrait{display:flex;flex-direction:column;gap:12px}
.portrait img{
  width:100%;aspect-ratio:1/1;object-fit:cover;
  /* the source is 2:3 and the box is square, so cover crops. Anchored to
     the top: centred cuts the cap off entirely, and anything between
     clips its brim. */
  object-position:50% 0%;
  background:rgba(255,255,255,.08);
}
.portrait figcaption{
  border-top:1px solid var(--rule-on-blue);padding-top:12px;
  color:var(--on-blue-dim);
}

.software{display:flex;flex-direction:column;gap:16px;min-width:0}
.software .software-label{color:var(--on-blue-dim)}
.software-row{
  /* One row at desktop, matching the frame. The column count comes from --n
     on the element, so adding or removing a tool needs no CSS change. Gap is
     34 rather than the frame's 44 because the row now carries more than the
     eight it was drawn with, and 34 keeps the tiles near their designed size
     instead of squeezing them. */
  display:grid;grid-template-columns:repeat(var(--n,8),minmax(0,1fr));
  gap:34px;align-items:start;
}
.software-row img{width:100%;aspect-ratio:1/1;object-fit:contain}

.caps{
  border-top:1.5px solid var(--rule-on-blue);padding-top:18px;
  margin-top:clamp(40px,5vw,64px);color:var(--paper);
}

/* ---------- WORK (6:2) ---------- */
/* The shared .sec rule pads both edges equally, but the Figma frame is
   asymmetric: 72px above the work header, 115px below the grid. Set both
   explicitly. The bottom is then pulled in further than the design, at
   Ojas's request: the ESDC card is a full-bleed block and the designed
   115px here plus Experience's 115px above its rule read as a hole. */
#work{
  padding-top:clamp(40px,5vw,72px);
  padding-bottom:clamp(64px,8vw,115px);
}

.work-head{margin-bottom:clamp(30px,4.4vw,58px)}
.work-head .sec-head{margin-bottom:26px}   /* head to filters is 26 in the frame */
.work-grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:66px 36px;
}
.proj{display:flex;flex-direction:column}
.proj-media{
  display:block;overflow:hidden;background:var(--bone-2);
  aspect-ratio:644/446;
}
.proj-media img{width:100%;height:100%;object-fit:cover}
.proj-body{display:flex;flex-direction:column;gap:12px;padding-top:26px}
.proj-name{
  font-size:var(--step-h3);font-weight:700;line-height:1;letter-spacing:-.035em;
  color:var(--blue);
}
.proj-name .stop{color:var(--hot)}
.proj-line{font-size:var(--step-body);line-height:1.5;color:var(--ink)}
.proj-disc{color:var(--ink-2)}
.proj-links{display:flex;flex-wrap:wrap;gap:30px;align-items:center}
.proj-links a{
  display:inline-flex;align-items:center;gap:7px;
  border-bottom:1.5px solid var(--hot);padding-bottom:3px;
  color:var(--blue);transition:color .2s linear,border-color .2s linear;
  /* the label voice, as in Figma: 13px tracked uppercase */
  font-size:var(--step-label);font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;line-height:1.4;
}
.proj-links .ico{width:14px;height:14px}
.proj-links a:hover{color:var(--hot)}

/* the seventh project is a full-width feature card: the grid is six image
   cards in two columns and a seventh would sit alone beside an empty slot */
.proj--feature{
  grid-column:1 / -1;
  background:var(--blue);color:var(--paper);
  display:grid;grid-template-columns:346px 1fr;gap:72px;align-items:start;
  padding:54px 58px;
  /* no margin-top: the grid's 66px row gap already separates it from the
     cards above, and adding a margin on top of that doubled it to 132px */
}
.proj-figure{
  font-size:clamp(3.5rem,6.7vw,6rem);font-weight:600;
  line-height:.96;letter-spacing:-.035em;color:var(--paper);
}
.proj-figure-label{display:block;margin-top:6px;color:var(--on-blue-dim);
  font-weight:500;letter-spacing:.08em;text-transform:none}
.proj--feature .feature-body{display:flex;flex-direction:column;gap:16px}
.proj--feature .proj-name{
  font-size:clamp(1.9rem,2.8vw,2.5rem);line-height:1.04;letter-spacing:-.03em;
  color:var(--paper);
}
.proj--feature .proj-name .stop{color:var(--on-blue-dim)}
.proj--feature .proj-line{color:var(--paper)}
.proj--feature .proj-disc{color:var(--on-blue-dim);letter-spacing:.08em;text-transform:none;font-weight:500}
.proj--feature .proj-links a{border-bottom-color:var(--rule-on-blue);color:var(--paper)}
.proj--feature .proj-links a:hover{border-bottom-color:var(--paper)}

/* ---------- EXPERIENCE (10:43) ---------- */
#experience{background:var(--bone-2)}   /* ground/bone-2 in the frame */
.xp-rows{display:flex;flex-direction:column}
.xp-row{
  border-top:1.5px solid var(--ink);
  padding-block:34px;
  display:grid;grid-template-columns:255px 697px 303px;gap:34px;align-items:start;
}
.xp-when,.xp-where{padding-top:6px;color:var(--ink-2)}
.xp-what{display:flex;flex-direction:column;gap:8px}
.xp-title{font-size:clamp(1.35rem,2vw,1.8125rem);font-weight:700;line-height:1.1;letter-spacing:-.025em;color:var(--ink)}
.xp-body{font-size:var(--step-body);line-height:1.5;color:var(--ink-2)}

/* ---------- CONTACT (11:43) — drenched orange ---------- */
.contact{
  background:var(--hot);color:var(--ink);
  padding-block:clamp(72px,9vw,130px);
}
.contact-lead{
  font-size:var(--step-h2);font-weight:700;line-height:.98;letter-spacing:-.038em;
  color:var(--ink);max-width:760px;
}
.contact-sub{
  padding-top:18px;font-size:var(--step-lead);line-height:1.42;
  color:var(--on-hot-dim);max-width:560px;
}
.contact-list{
  margin-top:66px;border-top:1.5px solid var(--ink);
  display:flex;flex-direction:column;
}
.c-row{
  border-bottom:1.5px solid var(--ink);
  padding-block:26px;
  display:flex;align-items:center;justify-content:space-between;gap:26px;
  transition:padding-left .3s var(--ease);
}
.c-row:hover{padding-left:10px}
.c-name{font-size:clamp(2rem,3.5vw,3.125rem);font-weight:700;line-height:1;letter-spacing:-.035em;color:var(--ink)}
.c-right{display:inline-flex;align-items:center;gap:26px;color:var(--on-hot-dim)}
.c-right .ico{width:32px;height:32px;stroke-width:1.6}

/* ---------- FOOTER (11:67) ---------- */
.footer{background:var(--ink);color:var(--bone);padding-block:clamp(40px,5vw,72px)}
.footer-top{display:flex;justify-content:space-between;gap:26px;flex-wrap:wrap;align-items:flex-end}
.footer-mark{font-size:clamp(1.5rem,3.4vw,2.6rem);font-weight:700;letter-spacing:-.035em;line-height:1;font-variation-settings:"wdth" 94}
.footer-nav{display:flex;gap:clamp(14px,2vw,28px);flex-wrap:wrap}
.footer-nav a{
  font-size:var(--step-label);font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  color:var(--on-ink-72);transition:color .25s linear;
}
.footer-nav a:hover,.footer-nav a:focus-visible{color:var(--hot)}
.footer-bottom{
  margin-top:clamp(28px,3.6vw,48px);padding-top:18px;
  border-top:1px solid var(--rule-on-ink);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  font-size:var(--step-label);letter-spacing:.09em;text-transform:uppercase;
  color:var(--on-ink-62);
}

/* ---------- homepage responsive ---------- */
@media (max-width:1180px){
  .xp-row{grid-template-columns:200px 1fr 220px;gap:24px}
}
/* tablet: the stacked layout made the portrait full-bleed and blew the app
   icons up to ~220px. Sit the portrait and the software row side by side
   instead, both at a sane size. Desktop and phone are untouched. */
@media (min-width:721px) and (max-width:1024px){
  .st-grid{
    grid-template-columns:minmax(0,248px) minmax(0,1fr);
    column-gap:40px;row-gap:44px;
  }
  .st-left{grid-column:1 / -1}
  .portrait{grid-column:1;align-self:start}
  .software{grid-column:2;align-self:start}
  .software-row{
    grid-template-columns:repeat(5,minmax(0,1fr));gap:18px;
    /* five per row so the vendor grouping survives the wrap, capped so the
       tiles cannot grow past the size they are on desktop */
    max-width:calc(5 * 96px + 4 * 18px);
  }
}

@media (max-width:1000px){
  .proj--feature{grid-template-columns:1fr;gap:28px;padding:40px 32px}
  .xp-row{grid-template-columns:1fr;gap:8px}
  .xp-when,.xp-where{padding-top:0}
}
@media (max-width:720px){
  .st-grid{grid-template-columns:1fr;row-gap:40px}
  .st-left,.portrait,.software{grid-column:1}
  .work-grid{grid-template-columns:1fr;gap:46px}
  .mh-right{align-items:flex-start;text-align:left}
  .mh-foot{gap:14px}
  .software-row{grid-template-columns:repeat(5,minmax(0,1fr));gap:14px}
  .c-row{flex-wrap:wrap;gap:6px 14px}
  .c-right{width:100%;justify-content:space-between}
}

/* ============================================================
   FILTERS: work grid category chips
   ------------------------------------------------------------
   Single select: the options are mutually exclusive, so they are
   radios rather than toggle buttons. State lives on aria-checked,
   which is both the accessibility contract and the styling hook,
   so the two cannot drift apart. "All" is the default.
   Mirrors "Filters" in Figma (node 165:347).
   ============================================================ */
.filters{display:flex;flex-wrap:wrap;align-items:center;gap:12px}

.chip{
  appearance:none;
  font-family:var(--sans);
  color:var(--ink-2);
  background:transparent;
  border:1px solid var(--ink-2);   /* NOT --line/--line-2: both fall under the
                                      3:1 non-text floor on bone (1.40:1 and
                                      1.85:1). --ink-2 gives 6.05:1. */
  border-radius:999px;
  padding:7px 14px;
  cursor:pointer;
  transition:background .18s var(--ease),
             color .18s var(--ease),
             border-color .18s var(--ease);
}
.chip:hover{border-color:var(--ink);color:var(--ink)}
.chip[aria-checked="true"]{
  background:var(--blue);          /* white on blue = 9.07:1 */
  border-color:var(--blue);
  color:var(--paper);
}
.chip:focus-visible{outline:2px solid var(--blue);outline-offset:3px}

.filters-count{margin-left:auto;color:var(--ink-2)}

/* filtered-out cards leave both the layout and the a11y tree */
.work-grid > [hidden]{display:none}

/* ============================================================
   CASE STUDY: shared furniture
   ------------------------------------------------------------
   Measured against the Figma case study frames, not guessed.
   Section order is fixed: back bar / hero / lead band / the idea /
   a closer look / process / palette / next project / footer.
   ESDC is the documented exception: no figures, no palette.
   ============================================================ */

/* --- back bar --- */
.back-bar{
  border-bottom:1px solid var(--line);
  padding-block:20px;
}
.back-bar .bar-inner{display:flex;align-items:center;justify-content:space-between;gap:24px}
.back-bar a{
  display:inline-flex;align-items:center;gap:9px;
  color:var(--ink-2);text-decoration:none;
}
.back-bar a:hover{color:var(--blue)}
.back-bar .bar-mark{color:var(--ink);font-weight:700;font-size:17px;letter-spacing:-.02em}
.back-bar .bar-mark .stop{color:var(--hot)}

/* --- shared section head: 1.5px ink rule, tracked label beneath --- */
.cs-head{
  border-top:1.5px solid var(--ink);
  padding-top:14px;
  margin-bottom:58px;
  color:var(--ink);
}

/* --- hero --- */
.cs-hero{padding-block:120px 90px}
.cs-title{
  font-size:var(--step-case);font-weight:700;
  line-height:.94;letter-spacing:-.038em;color:var(--blue);
  max-width:19ch;
}
.cs-title .stop{color:var(--hot)}
.cs-summary{
  font-size:var(--step-lead);font-weight:400;line-height:1.42;
  color:var(--ink);max-width:780px;
  margin-top:30px;
}
.cs-meta{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:34px;
  border-top:1.5px solid var(--ink);
  margin-top:30px;padding-top:26px;   /* hero gap 30, meta row pad-top 26 */
}
.cs-meta dt{color:var(--ink-2);margin-bottom:7px}
.cs-meta dd{margin:0;color:var(--ink);font-size:var(--step-body);line-height:1.5}

/* --- lead band: full bleed on the dark ground --- */
.lead-band{background:var(--ink);padding-bottom:32px}
.lead-band .band-media{display:block;width:100%}
.lead-band .band-media img{display:block;width:100%;height:auto}
.lead-band .band-foot{
  display:flex;align-items:baseline;justify-content:space-between;gap:34px;
  padding-top:28px;
}
.lead-band .band-caption{color:var(--on-ink-78);max-width:720px;margin:0}
.lead-band .band-link{
  display:inline-flex;align-items:center;gap:8px;
  color:var(--bone);text-decoration:none;white-space:nowrap;
  border-bottom:1px solid var(--rule-on-ink);padding-bottom:3px;
}
.lead-band .band-link:hover{border-bottom-color:var(--bone)}

/* ESDC: an ultramarine panel INSIDE the dark band, not a blue section.
   The frame is ground/ink with 32px below, wrapping a signal/blue panel
   padded 96/58 with a 40px gap. No federal artifact can be shown. */
.lead-band--statement .statement-panel{
  background:var(--blue);
  padding-block:clamp(56px,6.7vw,96px);
}
.lead-band--statement .statement-line{
  font-size:var(--step-h3);font-weight:600;line-height:1.04;
  letter-spacing:-.025em;color:var(--paper);max-width:24ch;margin:0;
}
.lead-band--statement .statement-note{
  color:var(--on-blue-dim);max-width:60ch;margin:40px 0 0;   /* frame gap 40 */
}

/* --- the idea --- */
.cs-idea{padding-block:115px 64px}
.idea-grid{display:flex;gap:72px;align-items:flex-start}
.idea-lead{
  flex:0 0 620px;max-width:620px;margin:0;
  font-size:var(--step-h2);font-weight:700;
  line-height:.98;letter-spacing:-.038em;color:var(--ink);
}
.idea-body{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:22px}
.idea-body p{margin:0;color:var(--ink-2)}
.idea-body p:first-child{color:var(--ink)}   /* first para carries full weight */

/* --- a closer look --- */
.cs-figures{padding-block:32px 115px}
.cs-figures .cs-head{margin-bottom:58px}
.cs-figure{margin:0}
.cs-figure + .cs-figure{margin-top:58px}
.cs-figure img{
  display:block;width:100%;height:auto;
  background:var(--bone-2);   /* holds the space while the image loads */
}
.cs-figure figcaption{color:var(--ink-2);padding-top:15px}

/* --- process --- */
.cs-process{
  padding-block:115px;
  background:var(--bone-2);   /* ground/bone-2 in the frame, on every case study */
}
.process-slots{display:flex;flex-direction:column}
.process-slot{
  display:flex;gap:34px;align-items:flex-start;
  border-top:1px solid var(--line);
  padding-block:34px;margin:0;
}
.process-slot dt{flex:0 0 255px;color:var(--ink)}
.process-slot dd{flex:1 1 0;min-width:0;margin:0;color:var(--ink-2)}

/* --- palette --- */
.cs-palette{padding-block:115px}

@media (max-width:900px){
      }
.swatch-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:34px}
.swatch{margin:0}
.swatch .chip-fill{
  display:block;aspect-ratio:303/132;border:1px solid var(--line);
}
.swatch .name{display:block;color:var(--ink);padding-top:14px}
.swatch .hex{display:block;color:var(--ink-2);padding-top:4px;text-transform:uppercase}

/* --- next project --- */
.next-project{padding-block:46px 110px}
.next-project .cs-head{margin-bottom:22px}   /* frame gap is 22 here, not 58 */
.next-row{
  display:flex;align-items:center;justify-content:space-between;gap:34px;
  color:var(--blue);text-decoration:none;
}
.next-row .next-name{
  font-size:var(--step-h3);font-weight:700;
  line-height:1;letter-spacing:-.03em;margin:0;
  color:var(--blue);
}
.next-row .ico{width:40px;height:40px;flex:none;transition:transform .3s var(--ease)}
.next-row:hover{color:var(--hot)}
.next-row:hover .ico{transform:translateX(10px)}

/* Hover wipes the orange across the name from the left. Two backgrounds
   clipped to the glyphs, the hot one growing from 0 to full width, so a
   single animatable property carries the whole effect.

   Guarded: background-clip:text needs color:transparent, and without
   support that would hide the name completely. Outside the @supports the
   name stays blue and the row just recolours on hover, as before. The
   full stop keeps its own colour and is orange throughout. */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .next-row .next-name{
    background-image:linear-gradient(var(--hot),var(--hot)),
                     linear-gradient(var(--blue),var(--blue));
    background-repeat:no-repeat;
    background-position:left center,left center;
    background-size:0% 100%,100% 100%;
    -webkit-background-clip:text;
            background-clip:text;
    color:transparent;
    transition:background-size .55s var(--ease);
  }
  .next-row:hover .next-name,
  .next-row:focus-visible .next-name{
    background-size:100% 100%,100% 100%;
  }
}
@media (prefers-reduced-motion:reduce){
  .next-row .next-name{transition:none}
}

/* --- responsive --- */
@media (max-width:1100px){
  .idea-grid{gap:46px}
  .idea-lead{flex-basis:46%}
}
@media (max-width:900px){
  .cs-hero{padding-block:72px 56px}
  .cs-meta{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:28px;margin-top:48px}
  .idea-grid{flex-direction:column;gap:32px}
  .idea-lead{flex:0 0 auto;max-width:none}
  .cs-idea,.cs-process{padding-block:72px}
  .cs-palette{padding-block:72px}
  .cs-figures{padding-block:24px 72px}
  .process-slot{flex-direction:column;gap:12px;padding-block:26px}
  .process-slot dt{flex:0 0 auto}
  .swatch-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .lead-band .band-foot{flex-direction:column;align-items:flex-start;gap:16px}
  .cs-head{margin-bottom:40px}
}

/* --- tiled body sections (Figma 64:234, 65:258, 66:247, 66:270) ----------
   Dungeon Party's body sections are an editorial grid, not a stack of
   full-width figures. A row holds one to four tiles whose widths come
   straight from the frame and are carried as fr weights, so the designed
   proportions hold at any viewport. Within-row gap is 37; the section is a
   flex column on 58, which is what separates rows, groups and the intro. */
.cs-tiles{
  padding-block:32px;
  display:flex;flex-direction:column;gap:58px;align-items:flex-start;
}
.cs-tiles > *{width:100%}
/* .cs-head carries margin-bottom:58px for the block sections. Inside this
   flex column the 58px gap already does that job, so the margin has to go
   or the head sits 116px from the intro instead of the designed 58. */
.cs-tiles > .cs-head{margin-bottom:0}
.cs-tiles:has(+ .cs-process){padding-bottom:115px}

.cs-section-intro{
  font-size:var(--step-lead);line-height:1.42;color:var(--ink);
  max-width:900px;margin:0;
}

.tile-row{display:grid;grid-template-columns:var(--cols);gap:37px;align-items:start}
.tile{margin:0;min-width:0}
.tile-media{display:block;overflow:hidden;background:var(--bone-2)}
.tile-media img{display:block;width:100%;height:auto}
/* a tile whose designed box crops the source, e.g. the player rail strip */
.tile-media[data-crop]{aspect-ratio:var(--ar)}
.tile-media[data-crop] img{height:100%;object-fit:cover;object-position:var(--crop)}

.tile figcaption{
  border-top:1px solid var(--line);
  padding-top:14px;
  color:var(--ink-2);
  display:flex;gap:24px;align-items:baseline;justify-content:space-between;
}
.tile-link{
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  color:var(--blue);border-bottom:1.5px solid var(--hot);padding-bottom:3px;
}
.tile-link:hover{color:var(--hot)}
.tile-link .ico{width:14px;height:14px}

.tile-group{display:flex;flex-direction:column;gap:16px}
.tile-group .group-label{color:var(--ink)}

/* the prose block that closes "What playtesting changed" */
.tile-prose{display:flex;flex-direction:column;gap:22px}
.tile-prose p{margin:0;color:var(--ink-2)}

@media (max-width:900px){
  .cs-tiles{padding-block:24px;gap:40px}
  /* below tablet the designed proportions stop being readable: collapse any
     row of three or more to two columns, and the rest to one */
  .tile-row{grid-template-columns:1fr !important;gap:28px}
  .tile-group{gap:12px}
}
@media (min-width:901px) and (max-width:1100px){
  .tile-row{gap:26px}
}

/* slots reused outside Process (ESDC "The constraints") */
.cs-slots{padding-block:32px 115px}
@media (max-width:900px){
  .cs-slots{padding-block:24px 72px}
  .gallery-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:24px}
}

/* slash separators in the capability run and the feature card disciplines */
.caps .sep,.proj-disc .sep{opacity:.5;margin-inline:.62em}

/* --- video lead band (Dungeon Party) ------------------------------------
   Same dark band as an image lead, but the media is a click-to-load
   facade: a locally served poster over the video's own 16:9 box. The
   designed image wrap is 1440x818, which is 1.760; 16:9 is 1.778, so the
   8px difference is taken rather than letterbox the trailer. */
.video{
  position:relative;aspect-ratio:16/9;overflow:hidden;background:var(--ink);
}
.video img{display:block;width:100%;height:100%;object-fit:cover}
.video iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

.video-play{display:block;position:absolute;inset:0;cursor:pointer}
.video-btn{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:clamp(64px,7vw,96px);aspect-ratio:1;border-radius:50%;
  background:var(--hot);display:grid;place-items:center;
  transition:transform .28s var(--ease),background .2s linear;
}
.video-btn svg{width:42%;height:42%;fill:var(--paper)}
.video-play:hover .video-btn{transform:translate(-50%,-50%) scale(1.07)}
.video-play:focus-visible{outline:3px solid var(--hot);outline-offset:-6px}
@media (prefers-reduced-motion:reduce){.video-btn{transition:none}}

/* ============================================================
   MOTION
   ------------------------------------------------------------
   Everything interactive gets a transition, and arrows move in
   the direction they point. Durations come from tokens so the
   whole site shares one feel. The reduced-motion block in
   layout.css collapses all of it.
   ============================================================ */

/* --- colour and border changes --- */
.back-bar a,
.tile-link,
.next-row,
.c-row,
.c-right,
.footer-nav a,
.proj-links a,
.lead-band .band-link{
  transition:color var(--dur-quick) linear,
             border-color var(--dur-quick) linear,
             background-color var(--dur-quick) linear;
}
.c-row{
  transition:padding-left var(--dur-base) var(--ease),
             color var(--dur-quick) linear;
}

/* --- arrows travel the way they point --- */
.ico{transition:transform var(--dur-base) var(--ease)}
.back-bar a:hover .ico,
.back-bar a:focus-visible .ico{transform:translateX(-4px)}          /* points west */
.proj-links a:hover .ico,
.tile-link:hover .ico,
.lead-band .band-link:hover .ico{transform:translate(3px,-3px)}      /* north-east */
.c-row:hover .ico,
.c-row:focus-visible .ico{transform:translate(4px,-4px)}
.next-row .ico{transition:transform var(--dur-base) var(--ease)}     /* east, set above */

/* --- project card: the image lifts slightly under the whole card --- */
.proj-media img{transition:transform var(--dur-slow) var(--ease)}
.proj:hover .proj-media img,
.proj:focus-within .proj-media img{transform:scale(1.03)}

/* --- press feedback, so a tap registers --- */
.chip,.video-play{transition:transform var(--dur-quick) var(--ease),
                             background var(--dur-quick) linear,
                             color var(--dur-quick) linear,
                             border-color var(--dur-quick) linear}
.chip:active{transform:scale(.97)}

/* --- the orange wipe, shared by the Next project name and the card titles --- */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .proj-name a{
    background-image:linear-gradient(var(--hot),var(--hot)),
                     linear-gradient(var(--blue),var(--blue));
    background-repeat:no-repeat;
    background-position:left center,left center;
    background-size:0% 100%,100% 100%;
    -webkit-background-clip:text;
            background-clip:text;
    color:transparent;
    transition:background-size .55s var(--ease);
  }
  .proj:hover .proj-name a,
  .proj-name a:focus-visible{background-size:100% 100%,100% 100%}

  /* The feature card sits on signal/blue, so its base layer has to be
     paper, not blue. With the shared rule it was painting blue on blue
     and the title vanished at rest. White, wiping to orange on hover. */
  .proj--feature .proj-name a{
    background-image:linear-gradient(var(--hot),var(--hot)),
                     linear-gradient(var(--paper),var(--paper));
  }
}

/* ============================================================
   SCROLL REVEAL
   ------------------------------------------------------------
   Restored: this was lost when the homepage CSS was rebuilt, and
   the reduced-motion block still referenced it. Per
   data/tokens.json this is animation-timeline, not an observer,
   because the observer version left images hidden on fast
   scrolls. Content is visible by default and the animation is
   layered on top, so an unsupported browser shows everything.
   ============================================================ */
@keyframes wipe-up{from{clip-path:inset(0 0 100% 0)}to{clip-path:inset(0 0 0 0)}}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .proj-media,
    .cs-figure img,
    .tile-media,
    .lead-band .band-media{
      animation:wipe-up linear both;
      animation-timeline:view();
      /* Was entry 4% to 54%. For a 446px card in an 870px viewport that is
         roughly 658px of scrolling before the image is fully unclipped,
         which reads as the page lagging behind the scroll. 5% to 28% is
         about 300px: the wipe still registers, but the image is whole
         almost as soon as it is properly on screen. */
      animation-range:entry 5% entry 28%;
    }
  }
}

/* the scale figure holds its width while the digits change */
.figure-value{font-variant-numeric:tabular-nums}
