/* dt-ux.com — homepage redesign
   Loaded after site.css. Same content and same palette as the replica; what
   changes is the scale, the hierarchy, and how the layout responds.

   Three fixes underneath everything else:
   1. One continuous fluid scale instead of three stepped breakpoints, which is
      what caused content to shrink between 1024 and 1100 on the live site.
   2. A real measure cap, so descriptions stop collapsing to ~30 characters.
   3. One image ratio at every width, so screenshots stop recomposing on resize. */

:root{
  /* Fluid type. Each value grows continuously between 360 and 1600, so there is
     no width at which the page steps down. */
  --t-hero:clamp(2rem, 1.05rem + 4.2vw, 4.25rem);       /* 32 -> 68 */
  --t-sub:clamp(1.25rem, 1.05rem + 0.9vw, 2rem);        /* 20 -> 32 */
  --t-title:clamp(1.375rem, 1.16rem + 0.95vw, 2.125rem);/* 22 -> 34 */
  --t-body:clamp(1rem, 0.96rem + 0.19vw, 1.1875rem);    /* 16 -> 19 */
  --t-label:clamp(0.75rem, 0.72rem + 0.11vw, 0.8125rem);  /* 12 -> 13; an
                        11px floor rendered below the readable minimum on phones */

  --gutter:clamp(20px, 4vw, 56px);  /* capped below 4vw of 1440 so the
                                       content column cannot shrink once
                                       --shell stops growing */
  --shell:1280px;
  --measure:62ch;

  --gap-block:clamp(64px, 8vw, 132px);   /* between work entries */
  --gap-hero:clamp(56px, 7vw, 104px);    /* hero to first entry */
}

body{font-size:var(--t-body);}

/* The warm ground is painted on <main>, but the header sits above it, so it was
   landing on the white body. Painting the canvas the same colour fixes the
   header and also means rubber-band overscroll no longer flashes white.
   overscroll-behavior stops the bounce that let the footer lift off the bottom
   edge. Note: this also disables pull-to-refresh on Android Chrome. */
html{background:#fbfaf9;overscroll-behavior-y:none;}
body{background:#fbfaf9;}
/* The warm ground is painted on <main>, so it needs bottom padding or the last
   element sits flush against the edge of the colour. The footer band then butts
   straight up against it. */
main,main.short,main.flush{padding-bottom:clamp(72px,9vw,140px);}
/* when the page ends on a full-bleed band, that band supplies the closing
   space itself - main's own padding would show as a white strip between the
   band and the footer */
main:has(> .ground:last-child){padding-bottom:0;}
/* site.css styles the bare <footer> element as a flex band with its own padding;
   here the padding lives on .inner instead, so reset the element. */
footer.rd-foot{padding:0;display:block;}

.shell{max-width:var(--shell);margin:0 auto;padding:0 var(--gutter);}

/* A full-bleed band. It is a direct child of <main>, so it spans the viewport
   without any 100vw trick, and it carries its own .shell inside for the
   gutters. The hero stays on paper above it. */
.ground{
  padding:clamp(48px,6vw,88px) 0 clamp(64px,8vw,112px);
  margin-top:clamp(24px,3vw,48px);
  border-top:1px solid var(--rule);
}
.ground > .shell > .band:first-child{margin-top:0;}

/* ---------- header ---------- */
.rd-top{
  display:flex;align-items:baseline;justify-content:space-between;gap:20px;
  max-width:var(--shell);margin:0 auto;
  padding:clamp(20px,2.4vw,30px) var(--gutter) 0;
}
.rd-top .mark{font-size:clamp(21px, 1rem + 0.75vw, 26px);}
.rd-top nav a{
  font-family:var(--body);font-weight:500;font-size:clamp(15px,1.1vw,20px);
  color:var(--ink);text-decoration:none;
}
@media (hover:hover){.rd-top nav a:hover{color:var(--muted);}}
/* the nav holds up to three section links; they sit in a row at every width.
   Spacing is margins, not flex gap: an iPhone rendered the links touching
   ("How I workProjectsGet in touch") with gap. Labels never break inside.
   Phones (under 768px) keep only "Get in touch" and the theme switch: the
   first screen already carries "See the work", and three labels plus a switch
   crowd a phone header. The selector hides any link followed by two or more
   siblings, so a single-link nav elsewhere is untouched. */
.rd-top nav{display:flex;align-items:center;}
.rd-top nav > * + *{margin-left:clamp(20px,2.4vw,36px);}
.rd-top nav a{white-space:nowrap;}
@media (max-width:767px){ .rd-top nav a:nth-last-child(n+3){display:none;} }

/* in-page links from the nav and the hero glide to their section; sections
   keep a little air above them when they land at the top */
@media (prefers-reduced-motion:no-preference){ html{scroll-behavior:smooth;} }
main section[id]{scroll-margin-top:clamp(16px,3vw,40px);}
/* js/anchors.js moves focus to the section a link jumps to, for keyboard and
   screen-reader users. A section is not a control, so it draws no ring:
   Safari outlined the whole section after a tap on the table of contents. */
[tabindex="-1"]:focus{outline:none;}

/* ---------- hero ----------
   Compressed from ~780px to ~420px so the first project reaches the fold. The
   avatar moves inline with the eyebrow instead of stacking above the name. */
.rd-hero{padding:clamp(48px,6.5vw,88px) 0 0;}
.rd-id{display:flex;align-items:center;gap:16px;margin:0 0 clamp(24px,3vw,38px);}
/* square box + 50% radius: a true circle, not the 120x100 ellipse that was
   cropping 17% off the top and bottom of the portrait */
.rd-id img{
  width:clamp(56px,5vw,76px);aspect-ratio:1;height:auto;
  border-radius:50%;object-fit:cover;flex:none;
}
.rd-id p{
  margin:0;font-family:var(--data,var(--body));
  font-size:var(--t-label);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);
}
.rd-hero h1{
  font-family:var(--display);font-weight:500;
  font-size:var(--t-hero);line-height:1.08;letter-spacing:-0.02em;
  margin:0;color:var(--ink);text-wrap:balance;
}
/* Set as two deliberate lines: the name, then the role. Left to wrap on its
   own it broke after "Staff". */
.rd-hero h1 .line{display:block;}
.rd-hero h1 .star{color:var(--accent);}
.rd-hero .role{
  font-family:var(--display);font-weight:500;
  font-size:var(--t-sub);line-height:1.25;letter-spacing:-0.01em;
  color:var(--muted);margin:clamp(14px,1.6vw,22px) 0 0;max-width:21.45em;
}

/* ---------- work ---------- */
.rd-work{padding:var(--gap-hero) 0 0;}
.rd-entry{display:block;text-decoration:none;color:inherit;}
.rd-entry + .rd-entry{margin-top:var(--gap-block);}

.rd-head{
  display:grid;gap:clamp(14px,2vw,40px);
  align-items:start;margin:0 0 clamp(20px,2.4vw,32px);
}
/* Split into two columns only once there is room for both to read well. The
   title is capped at 20ch, so the description takes the larger share. */
@media (min-width:1000px){
  .rd-head{grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);}
}
/* Company drops to a small label above the title; the title carries the row. */
.rd-entry .company{
  font-family:var(--body);font-weight:500;font-size:var(--t-label);
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
  margin:0 0 10px;
}
.rd-entry h2{
  font-family:var(--display);font-weight:500;
  font-size:var(--t-title);line-height:1.16;letter-spacing:-0.015em;
  margin:0;color:var(--ink);max-width:12.62em;
}
/* Full ink, capped measure. On the live site this sentence is the faintest text
   in the row despite being the only one that says what the work was. */
.rd-entry .desc{
  font-size:var(--t-body);line-height:1.5;color:var(--ink-2);
  margin:0;max-width:var(--measure);
}
@media (min-width:1000px){
  .rd-entry .desc{padding-top:calc(var(--t-label) + 10px);}
}

/* One ratio at every width, so the screenshot never recomposes on resize.
   2.2:1 rather than 16:9 because these captures carry wide coloured margins;
   the tighter box crops the padding and shows the product larger. */
/* height:auto is load-bearing. The <img height="626"> attribute is a
   presentational hint, which makes the height definite and causes CSS
   aspect-ratio to be ignored entirely. */
.rd-shot{
  width:100%;height:auto;aspect-ratio:2.2/1;
  object-fit:cover;object-position:center center;
  border-radius:14px;background:var(--sink,#f3f1f1);
  transition:transform .5s cubic-bezier(.4,0,.2,1);
}
.rd-media{overflow:hidden;border-radius:14px;}
@media (hover:hover){.rd-entry:hover .rd-shot{transform:scale(1.012);}}
@media (hover:hover){.rd-entry:hover h2{color:var(--accent);}}
.rd-entry h2,.rd-entry .rd-shot{transition:color .2s,transform .5s cubic-bezier(.4,0,.2,1);}

/* ---------- footer ----------
   The footer is the get-in-touch section on every page: css/contact.css. */

/* ---------- touch targets ----------
   Text links default to their line box, which is 16-28px tall. Padding brings
   the hit area to 44px without moving the text off its baseline. */
@media (pointer:coarse), (max-width:768px){
  .rd-top nav a{
    display:inline-block;padding:13px 0;
  }
  .rd-top{align-items:center;}
  .rd-top .mark{display:inline-block;padding:8px 0;}
}

/* ---------- phone ----------
   A 2.2:1 band is only ~160px tall on a 390px screen, too shallow to read as a
   product shot. 3:2 gives the screenshot room without letting it dominate. */
@media (max-width:768px){
  /* 4:3 crops into the wide coloured margins these captures carry, so the
     product itself renders larger on a narrow screen. */
  .rd-shot{aspect-ratio:4/3;object-position:center center;}
  .rd-hero h1{letter-spacing:-0.015em;}
  .rd-id{gap:14px;}
}

@media (prefers-reduced-motion:reduce){
  .rd-shot,.rd-entry h2{transition:none !important;}
}

/* ============================================================
   CASE STUDY / INNER PAGES
   Same fluid scale and column grid as the homepage, so the chrome and the
   rhythm carry across. The replica's fixed 200px + 784px columns are replaced
   by one capped fluid grid that stacks at the same 1000px point the homepage
   splits at.
   ============================================================ */

:root{
  --cs-col:1040px;        /* label + body, centred inside the shell */
  --cs-label:200px;
  --cs-measure:68ch;
}

/* ---------- head ---------- */
.cs,.cs.pad-sbi,.cs.pad-ds{
  padding:clamp(48px,6.5vw,88px) var(--gutter) clamp(64px,8vw,120px);
}
.cs-col{max-width:var(--cs-col);}
.cs-meta{
  font-family:var(--body);font-weight:500;font-size:var(--t-label);
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
h1.cs-title{
  font-size:var(--t-hero);line-height:1.08;letter-spacing:-0.02em;
  margin:clamp(16px,1.8vw,26px) 0 0;text-wrap:balance;
}
.cs-lede{
  font-family:var(--display);font-weight:500;
  font-size:var(--t-sub);line-height:1.3;letter-spacing:-0.01em;
  color:var(--muted);margin:clamp(20px,2.6vw,36px) 0 0;max-width:21.45em;
}

/* ---------- sections ---------- */
/* box-sizing is border-box, so the gutter is added to the cap rather than eaten
   out of it: content still measures --cs-col once there is room. Without the
   padding these sections sat flush against both screen edges on phones. */
.section{
  grid-template-columns:1fr;gap:clamp(10px,1.4vw,18px);
  max-width:calc(var(--cs-col) + 2 * var(--gutter));
  padding:0 var(--gutter);
  margin:0 auto clamp(64px,8vw,132px);
}
@media (min-width:1000px){
  .section{grid-template-columns:var(--cs-label) minmax(0,1fr);gap:16px;}
}
.section > h3{
  font-size:clamp(1.25rem, 1.1rem + 0.7vw, 1.75rem);  /* 20 -> 28 */
  line-height:1.18;letter-spacing:-0.012em;
}
.section .body p{
  font-size:var(--t-body);line-height:1.5;max-width:var(--cs-measure);
}
.section .body h3{font-size:var(--t-title);line-height:1.16;}
.section .body h4,.section .body h4.callout{
  font-size:var(--t-sub);line-height:1.3;
  font-family:var(--display);font-weight:500;color:var(--ink);
}
/* Captions stay sentence case: several are full sentences, and some carry
   meaningful casing ("axe-core", "ChatThread") that uppercasing would destroy.
   The uppercase label treatment is reserved for the eyebrow metadata. */
.section .body .caption,figcaption{
  font-size:var(--t-label);line-height:1.5;letter-spacing:normal;
  text-transform:none;color:var(--muted);
}
.section .body > * + *{margin-top:clamp(40px,4.6vw,72px);}
.section .body > p + p{margin-top:clamp(16px,1.4vw,22px);}
.section .body > * + p.pullquote,
.section .body > p.pullquote + *{margin-top:clamp(40px,4.6vw,72px);}

.pullquote,.section .body p.pullquote{
  font-size:var(--t-title);line-height:1.25;letter-spacing:-0.015em;
  max-width:15.14em;
}

ul.points li{font-size:var(--t-body);line-height:1.5;padding-left:26px;}
ul.points li + li{margin-top:14px;}
ul.points li::before{left:2px;top:calc(0.75em - 3px);}

.cards{gap:clamp(28px,3.4vw,44px) clamp(20px,2.4vw,32px);}
.cards.two .card{padding:clamp(18px,2vw,26px);border-radius:14px;}
.card h4,.section .body .card h4{
  font-family:var(--body);font-weight:500;font-size:var(--t-body);
  line-height:1.4;color:var(--ink);margin:0 0 8px;
}
.section .body .card p{font-size:var(--t-label);line-height:1.55;
  letter-spacing:normal;text-transform:none;}

.stats{gap:clamp(24px,3vw,40px);}
.stats p.stat,.section .body p.stat{font-size:var(--t-title);line-height:1.1;}
.stats p,.section .body .stats p{font-size:var(--t-body);}

.trow{grid-template-columns:1fr;gap:4px;padding:16px 0;}
@media (min-width:1000px){
  .trow{grid-template-columns:1fr 1fr 1fr;gap:0;}
}
.trow p{font-size:var(--t-label);line-height:1.55;letter-spacing:normal;
  text-transform:none;}
.trow.thead p{font-family:var(--body);font-weight:500;font-size:var(--t-body);
  color:var(--ink);}
.trow code{font-size:0.94em;}

blockquote.quote{padding-left:0;}
blockquote.quote h3{font-size:var(--t-sub);line-height:1.3;}
blockquote.quote p{font-size:var(--t-body);padding-left:0;
  letter-spacing:normal;text-transform:none;}
.status{padding-left:0;}
.status h3{font-size:var(--t-title);line-height:1.16;}
.status p{font-size:var(--t-body);line-height:1.5;}

/* ---------- media ----------
   Tied to the same shell so every band shares one grid with the text. */
figure img,.media img{border-radius:14px;}
.media,.mediagroup{
  padding:0 var(--gutter);
  margin:0 auto clamp(64px,8vw,132px);
  gap:clamp(14px,1.8vw,24px);
}
.media-full{max-width:calc(var(--shell) + 0px);}
.media-wide{max-width:calc(var(--cs-col) + 2 * var(--gutter));}
.mediagroup .media{padding:0;margin:0;}
.section .body .media{padding:0;margin:0;}

/* contact page */
.contact{padding-top:clamp(48px,6.5vw,88px);max-width:var(--cs-col);}
.contact h1{font-size:var(--t-hero);line-height:1.08;}
.contact h3{font-size:var(--t-sub);line-height:1.3;max-width:15.14em;}
.contact .label,.contact-row p.label{
  font-size:var(--t-label);letter-spacing:.14em;text-transform:uppercase;
}
.contact-row h4{font-size:var(--t-sub);font-family:var(--display);font-weight:500;}
.contact-linkedin{position:static;display:inline-block;
  margin-top:clamp(36px,4.4vw,56px);font-size:var(--t-sub);
  font-family:var(--display);font-weight:500;}
.credit{display:none;}  /* the black band footer replaces it */

/* ---------- shared across pages ----------
   --cell-pad: the page grid's half gap. The projects grid pads its cells by it,
   and How I work and the footer set their column gap to twice it, so every
   two-column section shares one set of column edges. */
:root{--cell-pad:clamp(20px,2.4vw,36px);}
/* text for screen readers only */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* the mono face: blueprint labels in the hero inspector and on project cells */
@font-face{font-family:'Geist Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url(../fonts/geistmono-400-latin.woff2) format('woff2');}
@font-face{font-family:'Geist Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url(../fonts/geistmono-500-latin.woff2) format('woff2');}
