/* ericdevlin.co design system
   Type: perfect fourth (1.333) from a 17px base, each step rounded to the 4px
   grid so sizes and spacing answer to the same structure.
   Space: 4px step set. Vertical rhythm is a guide, not a baseline grid: the
   ASCII field, the portrait mask and the product photography all break a strict
   baseline, and a rule nobody can keep is worse than a looser one everybody can.
*/
:root{
  --hue:105;

  /* fallback palette, used only where oklch is unsupported */
  --paper:#E3DD8F;
  --ink:#2B2A1F; --ink-2:#6E6840;
  --hair:#B9B26A; --mid:#7D7746;
  --bright-dim:#A9A25C;

  --ground:var(--paper);
  --inv-ground:var(--ink); --inv-ink:var(--paper);

  --mono:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;
  --grot:"Instrument Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
  --flex:"Roboto Flex",var(--grot);

  /* type scale */
  --t-label:12px;
  --t-body:17px;
  --t-lede:clamp(20px,2.1vw,24px);
  --t-row:clamp(24px,3.4vw,40px);
  --t-head:clamp(32px,5vw,52px);
  --t-display:clamp(40px,7vw,96px);
  --t-metric:clamp(20px,2.6vw,32px);

  /* tracking: three optical steps by size, plus one for mono */
  --tr-s:-.01em;
  --tr-m:-.02em;
  --tr-l:-.035em;
  --tr-mono:.02em;

  /* leading */
  --lh-display:1;
  --lh-head:1.05;
  --lh-lede:1.3;
  --lh-body:1.55;
  --lh-label:1.6;

  /* space: 4px steps. The token name states its value. */
  --s4:4px; --s8:8px; --s12:12px; --s16:16px; --s24:24px;
  --s32:32px; --s40:40px; --s56:56px; --s80:80px;

  --gutter:var(--s24);
  --bleed:calc(-1 * var(--gutter));
  /* Symmetric air around every rule. Section rules get the big gap and draw in
     --ink; rules inside a block get the small one and draw in --hair. */
  --rule-space:var(--s80);
  --rule-space-sm:var(--s40);
  /* the gap under the nav on a page that opens without a hero */
  --page-top:var(--s56);
  --measure:64ch;

  --ease:120ms linear;
  --nav-h:61px;
}
@supports (color: oklch(50% 0 0)){
  :root{
    --paper:oklch(88% 0.10 var(--hue));
    --ink:oklch(26% 0.02 var(--hue));
    --ink-2:oklch(40% 0.045 var(--hue));
    --hair:oklch(74% 0.09 var(--hue));
    --mid:oklch(55% 0.065 var(--hue));
    --bright-dim:oklch(68% 0.085 var(--hue));
  }
  /* The footer inverts, so --inv-ink comes from --paper. Without this it would
     inherit the near-white gallery paper and print white on the dark field. */
  [data-mode="gallery"] footer{
    --inv-ground:oklch(24% 0.012 var(--hue));
    --inv-ink:oklch(90% 0.018 var(--hue));
    --bright-dim:oklch(66% 0.016 var(--hue));
  }
  /* gallery mode: real photography needs quiet walls. Same hue, chroma down. */
  [data-mode="gallery"]{
    --paper:oklch(93% 0.012 var(--hue));
    --ink:oklch(24% 0.008 var(--hue));
    --ink-2:oklch(45% 0.012 var(--hue));
    --hair:oklch(82% 0.014 var(--hue));
    --mid:oklch(58% 0.012 var(--hue));
  }
}
*{margin:0;padding:0;box-sizing:border-box;border-radius:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:var(--nav-h);background:var(--ground)}
@media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}*,*::before,*::after{transition:none !important;animation:none !important}}
body{background:var(--ground);color:var(--ink);font-family:var(--grot);
  font-size:var(--t-body);letter-spacing:var(--tr-s);line-height:var(--lh-head);
  -webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
/* The link idiom is a hairline underline, not a color change; state moves to
   --mid on hover, like every other link on the site. */
.prose a,.fh-txt a,.fh-co a,.wk-beat p a,.meta a.inline{border-bottom:1px solid currentColor}
.prose a:hover,.prose a:focus-visible,
.fh-txt a:hover,.fh-txt a:focus-visible,
.fh-co a:hover,.fh-co a:focus-visible,
.wk-beat p a:hover,.wk-beat p a:focus-visible,
.meta a.inline:hover,.meta a.inline:focus-visible{color:var(--mid)}
img{display:block;max-width:100%;height:auto}

/* ONE gutter for everything. Only rules and hover fills bleed past it. */
.wrap{max-width:1800px;margin:0 auto;padding:0 var(--gutter)}

.skip{position:absolute;left:-9999px;top:0;background:var(--ink);color:var(--inv-ink);padding:var(--s12) var(--s16);font-family:var(--mono);font-size:var(--t-label);z-index:100}
.skip:focus{left:0}
a:focus-visible,summary:focus-visible,button:focus-visible{outline:3px solid var(--ink);outline-offset:3px}

nav{border-bottom:1px solid var(--ink);position:sticky;top:0;background:var(--ground);z-index:50}
.nav-bar{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s24);flex-wrap:wrap;padding-block:var(--s24) var(--s16)}
.nav-links{display:flex;gap:var(--s24);flex-wrap:wrap}
.nav-links a{font-size:var(--t-body);letter-spacing:var(--tr-s);position:relative}
.nav-links a:hover,.nav-links a:focus-visible{color:var(--mid)}
/* State lives on a hairline rising out of the nav's bottom border. The origin
   flips between states, so the line grows up out of the border on the way in and
   keeps going up and out on the way out, instead of retracing its own path. */
.nav-links a::after{content:"";position:absolute;left:50%;bottom:-16px;width:1px;height:12px;
  background:currentColor;transform:translateX(-50%) scaleY(0);transform-origin:50% 0;
  transition:transform .26s cubic-bezier(.4,0,.2,1)}
.nav-links a:hover::after,.nav-links a:focus-visible::after,.nav-links a[aria-current]::after{
  transform:translateX(-50%) scaleY(1);transform-origin:50% 100%;
  transition:transform .3s cubic-bezier(.34,1.4,.64,1)}

/* The wordmark: Roboto Flex, driven per letter by cursor proximity. The resting
   state is set here so it looks right with JS off or on a touch device. */
.wordmark{font-family:var(--flex);font-size:18px;letter-spacing:var(--tr-m);display:inline-flex;
  font-variation-settings:"wght" 700,"wdth" 100,"opsz" 18}
.wordmark i{font-style:normal;display:inline-block;
  font-variation-settings:"wght" 700,"wdth" 100,"opsz" 18;
  transition:font-variation-settings .34s cubic-bezier(.2,.7,.3,1)}
.wordmark .sp{width:.3em}

.meta{font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);color:var(--ink-2);line-height:var(--lh-label)}
.meta b{color:var(--ink);font-weight:400}

/* Two columns: title left, whatever that section has to say on the right. Pulled
   to the bleed and re-padded, so the rule runs edge to edge while the title
   stays on the gutter. */
.sec-head{display:grid;grid-template-columns:1fr 1fr;gap:var(--s24);align-items:start;
  border-top:1px solid var(--ink);padding-top:var(--rule-space);margin-top:var(--rule-space);
  margin-bottom:var(--s32);margin-inline:var(--bleed);padding-inline:var(--gutter)}
.sec-head>.meta{text-align:right}
/* A sec-head divides sections. Opening a page it would sit directly under the
   nav's own border and read as a doubled rule, so drop it there. */
main>section:first-child>.sec-head:first-child{border-top:0;padding-top:0}
/* Pages with no hero need one named gap under the nav, not a pasted number. */
.page-open{margin-top:var(--page-top)}

/* Portrait is a 1-bit dither carried as an alpha mask, not a photo: the fill is
   var(--ink), so it re-colours with the hue roll and costs one small PNG. */
.portrait{width:100%;aspect-ratio:1472/1411;margin-left:auto;background:var(--ink);
  -webkit-mask:url(/img/eric-900.png) center top/contain no-repeat;
  mask:url(/img/eric-900.png) center top/contain no-repeat}
@media (max-width:720px){.portrait{max-width:320px;margin-top:var(--s24);margin-left:0}}
/* The portrait is the tallest thing in About. Rather than zeroing the section gap
   for both columns, it hangs one --rule-space past the grid so its bottom edge
   lands on the next section's rule while the copy keeps its normal air. */
@media (min-width:721px){
  #about .sec-head{align-items:stretch}
  /* The portrait sits inside a column wrapper, so the wrapper is the grid item:
     it stretches to the row and hangs one --rule-space past it, and the portrait
     fills that box with its mask anchored to the bottom. The bottom edge then
     lands on the next section's rule whichever column is taller. Sizing the
     portrait from aspect-ratio instead leaves it short when the copy runs long. */
  #about .sec-head>div:last-child{display:flex;flex-direction:column;
    margin-bottom:calc(-1 * var(--rule-space))}
  #about .portrait{aspect-ratio:auto;flex:1;min-height:0;
    -webkit-mask:url(/img/eric-900.png) center bottom/contain no-repeat;
    mask:url(/img/eric-900.png) center bottom/contain no-repeat}
}

h2.big,.big{font-size:var(--t-head);font-weight:700;letter-spacing:var(--tr-m);line-height:var(--lh-head)}

/* display type pulls its side bearing back onto the gutter line */
.display{font-weight:700;font-size:var(--t-display);letter-spacing:var(--tr-l);line-height:var(--lh-display);margin-left:-.035em}
.lede{font-size:var(--t-lede);line-height:var(--lh-lede);font-weight:500;letter-spacing:var(--tr-m);max-width:34ch}
.prose{max-width:var(--measure)}
.prose p{font-size:var(--t-body);line-height:var(--lh-body)}
.prose p+p{margin-top:var(--s16)}

/* The hero is exactly its content plus one --rule-space top and bottom, matching
   every other rule on the page. The bottom padding also carries the first
   section's top margin, so the ASCII field (inset:0 of this box) runs all the
   way down to the next rule rather than stopping short. */
.hero{display:flex;flex-direction:column;padding-block:var(--rule-space);position:relative;isolation:isolate}
.hero+section .sec-head{margin-top:0}
.hero-field{position:absolute;inset:0;z-index:-1;margin:0;overflow:hidden;
  font-family:var(--mono);font-size:12px;line-height:13px;white-space:pre;
  color:var(--ink-2);opacity:.22;pointer-events:none;user-select:none}
@media (prefers-reduced-motion:reduce){.hero-field{opacity:.16}}
.hero-top{display:grid;grid-template-columns:3fr 2fr;gap:var(--s24);align-items:start;margin-bottom:var(--s24)}
.hero-top .meta:last-child:not(:only-child){text-align:right}
/* eyebrow: the same 9px square the section labels use, so the mark means one thing */
.eyebrow{display:flex;align-items:center;gap:var(--s8)}
.eyebrow::before{content:"";flex:none;width:8px;height:8px;background:var(--ink)}
.hero-sub{margin-top:var(--s40)}

/* index rows: the fill bleeds, the content sits on the gutter. Each row is a
   link to its own case, with one metric carried on the row so a number is
   readable without any interaction. */
.rows{list-style:none}
.rows li{border-top:1px solid var(--hair)}
.rows li:last-child{border-bottom:1px solid var(--hair)}
.rows a{display:grid;grid-template-columns:4ch 1fr auto;column-gap:var(--s24);row-gap:var(--s8);
  align-items:baseline;padding:var(--s24) var(--gutter);margin-inline:var(--bleed);
  transition:background var(--ease),color var(--ease)}
.rows .num{grid-column:1;grid-row:1;font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);color:var(--ink-2);line-height:var(--lh-label)}
.rows .cat{grid-column:2;grid-row:1;font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);
  color:var(--ink-2);line-height:var(--lh-label)}
.rows .row-main{grid-column:2;grid-row:2}
.rows .rtitle{display:block;font-size:var(--t-row);font-weight:700;letter-spacing:var(--tr-m);line-height:var(--lh-head)}
.rows .sub{display:block;font-size:var(--t-body);font-weight:400;color:var(--ink-2);
  margin-top:var(--s8);max-width:56ch;line-height:var(--lh-body);letter-spacing:var(--tr-s)}
/* An index whose entries carry no metric drops the third column rather than
   leaving it empty. The arrangement is otherwise identical: number, category,
   title, summary. */
.rows-plain a{grid-template-columns:4ch 1fr}
.rows .row-end{grid-column:3;grid-row:2;display:flex;flex-direction:column;align-items:flex-end;gap:var(--s4);text-align:right}
.rows .row-n{font-size:var(--t-metric);font-weight:700;letter-spacing:var(--tr-m);line-height:1;white-space:nowrap}
.rows .row-l{font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);
  color:var(--ink-2);line-height:var(--lh-body);max-width:22ch}
.rows a:hover,.rows a:focus-visible{background:var(--inv-ground);color:var(--inv-ink)}
.rows a:hover .num,.rows a:hover .sub,.rows a:hover .meta,.rows a:hover .cat,.rows a:hover .row-l,
.rows a:focus-visible .num,.rows a:focus-visible .sub,.rows a:focus-visible .meta,
.rows a:focus-visible .cat,.rows a:focus-visible .row-l{color:var(--bright-dim)}

.pleat{height:64px;background:repeating-linear-gradient(90deg,var(--ink) 0,var(--ink) 1px,transparent 1px,transparent 9px);opacity:.18;margin:var(--rule-space) var(--bleed) 0}

/* metrics: one shared component, everywhere a number is stated */
.wk-metrics{display:flex;gap:var(--s40);flex-wrap:wrap;
  border-top:1px solid var(--hair);padding-top:var(--rule-space-sm);margin-top:var(--rule-space-sm)}
.metric .n{font-size:var(--t-metric);font-weight:700;letter-spacing:var(--tr-m);line-height:1}
.metric .l{font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);
  color:var(--ink-2);margin-top:var(--s8);max-width:26ch;line-height:var(--lh-body)}

/* case study: a plain reading column. A beat label introduces a paragraph, so it
   is a subtitle: body face at 700, here and on /work/. Mono stays on metadata. */
.wk{max-width:76ch}
.wk-case{border-top:1px solid var(--ink);padding-top:var(--rule-space);margin-top:var(--rule-space)}
.wk-case h2{font-size:var(--t-row);font-weight:700;letter-spacing:var(--tr-m);line-height:var(--lh-head);margin-top:var(--s8)}
.wk-beat{margin-top:var(--s40)}
.wk-beat h3{font-size:var(--t-body);font-weight:700;letter-spacing:var(--tr-s);
  color:var(--ink);margin-bottom:var(--s12)}
.wk-beat p{font-size:var(--t-body);line-height:var(--lh-body)}
.wk-beat p+p{margin-top:var(--s16)}
/* previous / next, so a case is never a dead end */
.cs-foot{display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--s16);
  border-top:1px solid var(--ink);padding-top:var(--rule-space-sm);margin-top:var(--rule-space)}
.cs-foot a{font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);color:var(--ink-2);
  transition:color var(--ease)}
.cs-foot a:hover,.cs-foot a:focus-visible{color:var(--ink)}

/* fashion: house marque strip, then a house per band on the page's own ground */
.marques{display:flex;gap:clamp(24px,5vw,64px);align-items:baseline;flex-wrap:wrap;list-style:none;
  padding:0 var(--gutter) var(--rule-space-sm);margin:var(--rule-space-sm) var(--bleed) 0;
  border-bottom:1px solid var(--ink)}
.marques li{white-space:nowrap;color:var(--ink);display:flex;align-items:center}
/* Coach and CK are the real marks, inlined as SVG drawn in currentColor so they
   inherit the hue roll. Sizing them here is what keeps them marks rather than
   full-width artwork: the CK outline is 39746 units wide at its natural size. */
.mq-coach svg{height:15px;width:auto;display:block}
/* CK is the wordmark set in Futura and converted to outlines. The font file is
   never served; this is artwork, which the desktop licence covers. */
.mq-ck svg{height:11px;width:auto;display:block}
/* Josefin Sans stands in for Reed Krakoff's Neutraface. */
.mq-they{font-family:Georgia,'Times New Roman',serif;font-size:18px;letter-spacing:.28em}
.mq-reed{font-family:'Josefin Sans',var(--grot);font-weight:700;font-size:19px;letter-spacing:.20em;text-transform:uppercase}
.fh{position:relative}
.fh + .fh{border-top:1px solid var(--hair)}
.fh-in{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,72px);
  padding-block:var(--rule-space);align-items:center}
.fh-right .fh-copy{order:2}
/* Three tiers, deliberately uneven: the role line hugs the house name because it
   labels it, then a clear break before the prose. */
.fh-copy .meta{margin-top:var(--s12)}
.fh-co{font-size:var(--t-body);line-height:var(--lh-body);margin-top:var(--s32);max-width:52ch}
.fh-txt{font-size:var(--t-body);line-height:var(--lh-body);margin-top:var(--s16);max-width:52ch}
/* contain, not cover: these are products, and a cropped handbag is a useless
   photograph. Letterboxing is the correct trade. */
.fh-main{position:relative;margin:0;overflow:hidden}
.fh-main img{width:100%;aspect-ratio:1/1;object-fit:contain;display:block}
/* Hover the outer quarter to page it. The zone darkens and the cursor becomes
   the direction it will move. */
.fh-nav{position:absolute;top:0;bottom:0;width:25%;border:0;padding:0;background:transparent;
  transition:background var(--ease);z-index:2}
.fh-nav:hover,.fh-nav:focus-visible{background:rgba(0,0,0,.28);outline:0}
.fh-prev{left:0;cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M17 5 L8 14 L17 23' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 14 14, w-resize}
.fh-next{right:0;cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M11 5 L20 14 L11 23' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 14 14, e-resize}
.fh-count{position:absolute;right:var(--s12);bottom:var(--s8);z-index:3;font-family:var(--mono);font-size:var(--t-label);
  color:#fff;background:rgba(0,0,0,.55);padding:var(--s4) var(--s8);pointer-events:none}
.fh-thumbs{display:grid;grid-template-columns:repeat(6,1fr);gap:var(--s8);margin-top:var(--s8)}
.fh-thumbs button{padding:0;border:0;background:none;cursor:pointer;opacity:.5;transition:opacity var(--ease)}
.fh-thumbs button:hover,.fh-thumbs button:focus-visible,.fh-thumbs button[aria-current]{opacity:1}
.fh-thumbs img{width:100%;aspect-ratio:1/1;object-fit:contain;display:block}
@media (max-width:820px){.fh-in{grid-template-columns:1fr}.fh-right .fh-copy{order:0}}

footer{background:var(--inv-ground);color:var(--inv-ink);padding-block:var(--s56) var(--s40);margin-top:var(--rule-space)}
/* the pleat is a lead-in to the footer, so it should meet it with no daylight */
main:has(.pleat)+footer{margin-top:0}
/* Placeholders carry the visible labelling, so the real labels go to the screen
   reader only. A placeholder alone is not a label: it vanishes the moment you
   type, and nothing is left to say what the field was. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.foot-form ::placeholder{color:var(--bright-dim);opacity:1}
.foot-rule{height:1px;background:var(--inv-ink);margin:var(--rule-space-sm) 0;margin-inline:var(--bleed)}
.foot-form-row{margin-top:0}
/* Inline validation reserves no space until it has something to say, so the form
   does not jump on first error. */
.foot-form .err{font-size:var(--t-body);letter-spacing:var(--tr-s);color:var(--inv-ink);margin-top:var(--s8)}
.foot-form [aria-invalid="true"]{border-bottom-color:var(--inv-ink);border-bottom-width:2px}
.hp{display:none !important}
.form-note{grid-column:1/-1;font-size:var(--t-body);letter-spacing:var(--tr-s);color:var(--bright-dim);margin:0}
.form-note:empty{display:none}
.foot-form{display:grid;grid-template-columns:1fr 1fr;gap:var(--s16) var(--s24);max-width:56ch}
.foot-form label{display:flex;flex-direction:column;gap:var(--s8)}
.foot-form label.wide{grid-column:1/-1}
.foot-form span{font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);color:var(--bright-dim)}
/* lines, never boxes */
/* Form controls do not inherit font-family, so every one declares it. */
.foot-form input,.foot-form textarea{
  background:transparent;border:0;border-bottom:1px solid var(--bright-dim);
  color:var(--inv-ink);font-family:var(--grot);font-size:var(--t-body);letter-spacing:var(--tr-s);
  padding:var(--s8) 0;resize:vertical}
.foot-form input:focus,.foot-form textarea:focus{outline:0;border-bottom-color:var(--inv-ink)}
.foot-form button{
  justify-self:start;grid-column:1/-1;background:var(--bright-dim);color:var(--ink);
  border:0;font-family:var(--grot);font-size:var(--t-body);letter-spacing:var(--tr-s);
  padding:var(--s12) var(--s24);cursor:pointer;transition:background var(--ease)}
.foot-form button:hover,.foot-form button:focus-visible{background:var(--inv-ink)}
.foot-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s32)}
.foot-col h3{font-size:var(--t-body);letter-spacing:var(--tr-s);color:var(--bright-dim);margin-bottom:var(--s12);font-weight:400}
.foot-col a{display:block;font-size:var(--t-body);letter-spacing:var(--tr-s);line-height:1.6}
.foot-col a:hover{color:var(--bright-dim)}
.foot-bottom{display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--s12);margin-top:var(--s40);
  font-family:var(--mono);font-size:var(--t-label);letter-spacing:var(--tr-mono);color:var(--bright-dim)}
.foot-link{border-bottom:1px solid currentColor}
.foot-link:hover,.foot-link:focus-visible{color:var(--inv-ink)}
footer .meta{color:var(--bright-dim)}

@media(max-width:760px){
  :root{--gutter:var(--s16)}
  .sec-head,.hero-top,.hero-sub{grid-template-columns:1fr;gap:var(--s12)}
  .sec-head .meta,.hero-top .meta:last-child{text-align:left}
  /* Rows stack to one column. The metric drops entirely rather than stacking:
     number, category, title, summary and then a second number is more than a
     phone row can carry, and the metric is the least of them. It is still the
     first thing on the case page the row links to, so nothing is lost. */
  .rows a{grid-template-columns:1fr;row-gap:var(--s4)}
  .rows .num,.rows .cat,.rows .row-main{grid-column:1;grid-row:auto}
  .rows .row-end{display:none}
  .wk-metrics{gap:var(--s24)}
  .foot-grid{grid-template-columns:1fr}
  .foot-form{grid-template-columns:1fr}
}
