/* ============================================================
   Muhammad Ahsan Sheikh — portfolio
   Shared stylesheet
   ============================================================ */

:root{
  --paper:#faf7f2;
  --paper-2:#f3eee5;
  --card:#fffdfa;
  --ink:#17150f;
  --muted:#6d675e;
  --faint:#767065;
  --rule:#e5dfd4;
  --accent:#8a3f2b;        /* sienna */
  --accent-soft:#f0e2db;
  --accent-2:#2f5d62;      /* deep teal */
  --accent-2-soft:#dfeaea;
  /* Dot-grid colour, derived from --rule so it can never drift from the
     hairlines. 1.42:1 against --paper: visible as texture, never as pattern. */
  --dot:color-mix(in srgb,var(--rule) 88%,var(--muted));
  /* Text that sits ON a filled --accent surface. Not a new colour: white in
     light mode, where --accent is dark sienna (7.43:1). In dark mode --accent
     becomes a light salmon and white drops to 2.70:1, so it flips to --paper. */
  --accent-ink:#fff;
  --shadow:0 1px 2px rgba(23,21,15,.04), 0 8px 24px -12px rgba(23,21,15,.10);
  --shadow-lift:0 2px 4px rgba(23,21,15,.05), 0 18px 40px -18px rgba(23,21,15,.20);
  --serif:'Newsreader',Georgia,'Times New Roman',serif;
  --sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --mono:ui-monospace,'SF Mono',Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark){
  :root{
    --paper:#131210; --paper-2:#191713; --card:#1c1a16;
    --ink:#ece7de; --muted:#a49c91; --faint:#8a8279; --rule:#2b2822;
    --accent:#d98a68; --accent-soft:#33241d;
    --accent-2:#78b4b7; --accent-2-soft:#1d2a2b;
    /* LOWER contrast than light, not higher. A light dot on a near-black
       ground is picked up far more readily than a dark dot on cream, so
       matching the light value's 1.42:1 here reads as noise competing with
       body text. Pulled back to 1.25:1 against --paper. */
    --dot:color-mix(in srgb,var(--rule) 92%,var(--paper));
    /* 6.94:1 on the dark --accent, against 2.70:1 for white. */
    --accent-ink:var(--paper);
    --shadow:0 1px 2px rgba(0,0,0,.3), 0 8px 24px -12px rgba(0,0,0,.6);
    --shadow-lift:0 2px 4px rgba(0,0,0,.35), 0 18px 40px -18px rgba(0,0,0,.8);
  }
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  margin:0; color:var(--ink);
  /* Dot grid on the page ground so panels and cards sit ON something rather
     than floating on flat colour. 22px pitch, 1px dot. */
  background-color:var(--paper);
  background-image:radial-gradient(var(--dot) 1px,transparent 1px);
  background-size:22px 22px;
  background-position:-1px -1px;
  font-family:var(--sans); font-size:16.5px; line-height:1.68;
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  position:relative; overflow-x:hidden;
}
/* paper grain */
body::before{
  content:''; position:fixed; inset:0; pointer-events:none; z-index:1; opacity:.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.045'/%3E%3C/svg%3E");
}
main,.topbar,footer{position:relative; z-index:2}

a{color:inherit}
::selection{background:var(--accent); color:var(--accent-ink)}
:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:3px}

.wrap{max-width:760px; margin:0 auto; padding:0 26px}
.wrap-wide{max-width:760px; margin:0 auto; padding:0 26px}

/* ---------------- figures and key terms ----------------
   Every number on the site renders in --mono with tabular figures. This is the
   register the analyzer dashboard uses, and it is what makes a page of prose
   read as measured rather than asserted. .93em because mono sits optically
   larger than Inter at the same px. */
.num{font-family:var(--mono); font-variant-numeric:tabular-nums; font-size:.93em; letter-spacing:-.005em}
/* .hi marks the figure that is the point of its sentence. Two or three per
   paragraph at most, or the emphasis stops meaning anything. */
.num.hi{color:var(--accent); font-weight:500}
/* Colour instead of bold for the term that carries the sentence. Applied to
   the existing <b>, so semantics survive and the weight drops to medium. */
.key{color:var(--accent); font-weight:500}

/* ---------------- stats band ---------------- */
.statband{
  margin:32px 0 0; display:grid; grid-template-columns:repeat(4,1fr);
  background:var(--card); border:1px solid var(--rule); border-radius:10px;
  box-shadow:var(--shadow); overflow:hidden;
}
.stat{padding:18px 18px 16px; border-left:1px solid var(--rule); min-width:0}
.stat:first-child{border-left:none}
.stat .fig{
  display:block; font-family:var(--mono); font-variant-numeric:tabular-nums;
  font-size:clamp(22px,3.4vw,26px); font-weight:500; color:var(--accent);
  letter-spacing:-.03em; line-height:1.08;
}
.stat .lab{
  display:block; margin-top:8px; font-family:var(--mono); font-size:9.5px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--faint); line-height:1.45;
}
@media (max-width:720px){
  .statband{grid-template-columns:1fr 1fr}
  .stat:nth-child(-n+2){border-bottom:1px solid var(--rule)}
  .stat:nth-child(odd){border-left:none}
}

/* ---------------- top bar ---------------- */
.topbar{
  position:sticky; top:0; z-index:60;
  background:color-mix(in srgb,var(--paper) 86%,transparent);
  backdrop-filter:saturate(180%) blur(14px);
  -webkit-backdrop-filter:saturate(180%) blur(14px);
  border-bottom:1px solid transparent; transition:border-color .3s ease;
}
.topbar.stuck{border-bottom-color:var(--rule)}
.topbar .wrap-wide{display:flex; justify-content:space-between; align-items:center; height:62px; gap:16px}
.mark{font-family:var(--serif); font-size:1.08rem; text-decoration:none; white-space:nowrap; letter-spacing:.005em}
.mark em{font-style:italic; color:var(--accent)}
.topnav{display:flex; gap:6px; align-items:center}
.topnav a{
  position:relative; color:var(--muted); text-decoration:none; font-size:.855rem;
  padding:6px 11px; border-radius:7px; transition:color .18s, background .18s;
}
.topnav a::after{
  content:''; position:absolute; left:11px; right:11px; bottom:2px; height:1.5px;
  background:var(--accent); transform:scaleX(0); transform-origin:left;
  transition:transform .26s cubic-bezier(.4,0,.2,1);
}
.topnav a:hover{color:var(--ink)}
.topnav a:hover::after{transform:scaleX(1)}
.topnav a.on{color:var(--ink); font-weight:500}
.topnav a.on::after{transform:scaleX(1)}
.topnav a.cta{
  background:var(--accent); color:var(--accent-ink); font-weight:500; margin-left:6px;
}
.topnav a.cta::after{display:none}
.topnav a.cta:hover{opacity:.88; color:var(--accent-ink)}
@media (max-width:640px){
  .topbar .wrap-wide{height:56px}
  .mark{font-size:.98rem}
  .topnav a{padding:6px 8px; font-size:.8rem}
  .topnav a.cta{padding:6px 12px}
}
/* Below ~430px the wordmark and four nav items cannot both fit, and what fell
   off the right edge was the Contact button — the one thing on the bar with a
   job to do. The wordmark goes instead: "About" is the same destination, so
   nothing becomes unreachable. */
@media (max-width:430px){
  .mark{display:none}
  .topbar .wrap-wide{justify-content:flex-end; padding:0 16px}
  .topnav a{padding:6px 7px; font-size:.78rem}
  .topnav a.cta{padding:6px 11px; margin-left:3px}
}

/* ---------------- page head ---------------- */
.pagehead{padding:64px 0 10px}
.eyebrow{
  font-family:var(--mono); font-size:.7rem; letter-spacing:.18em; text-transform:uppercase;
  color:var(--accent); margin:0 0 20px; font-weight:500;
  display:flex; align-items:center; gap:10px;
}
.eyebrow::after{content:''; height:1px; flex:1; background:linear-gradient(90deg,var(--rule),transparent); max-width:120px}
/* Availability reuses .badge rather than inventing a treatment. It sits in the
   eyebrow because it is the first thing a co-op recruiter looks for, and the
   eyebrow is the first line on the page. --accent on --accent-soft is 5.88:1
   light, 5.52:1 dark. */
.eyebrow .avail{margin-left:0; vertical-align:baseline; flex:none}
@media (max-width:430px){
  .eyebrow{flex-wrap:wrap; gap:8px}
  .eyebrow::after{display:none}
}

h1{
  font-family:var(--serif); font-weight:400;
  font-size:clamp(2.4rem,6.8vw,3.4rem); line-height:1.05;
  letter-spacing:-.022em; margin:0 0 22px;
}
h1 em{font-style:italic; color:var(--accent)}
.lede{
  font-family:var(--serif); font-size:clamp(1.16rem,2.9vw,1.4rem);
  line-height:1.52; font-weight:300; margin:0 0 18px; max-width:34ch; color:var(--ink);
}
.lede em{font-style:italic; color:var(--accent)}
p.body{color:var(--muted); margin:0 0 15px; max-width:60ch; font-size:1rem}
p.body strong{color:var(--ink); font-weight:500}

/* ---------------- buttons ---------------- */
.links{display:flex; flex-wrap:wrap; gap:8px; margin-top:28px}
.btn{
  font-size:.86rem; text-decoration:none; color:var(--ink);
  border:1px solid var(--rule); border-radius:100px; padding:7px 16px;
  background:var(--card); transition:all .2s cubic-bezier(.4,0,.2,1); white-space:nowrap;
  display:inline-flex; align-items:center; gap:7px;
}
.btn:hover{border-color:var(--accent); color:var(--accent); transform:translateY(-2px); box-shadow:var(--shadow)}
.btn.primary{background:var(--accent); border-color:var(--accent); color:var(--accent-ink)}
.btn.primary:hover{color:var(--accent-ink); opacity:.9}
.btn svg{width:13px; height:13px; opacity:.65}

/* ---------------- section heads ---------------- */
section{padding:60px 0 0}
.shead{display:flex; align-items:baseline; gap:14px; margin-bottom:30px}
.snum{font-family:var(--mono); font-size:.74rem; color:var(--accent); flex:none; letter-spacing:.08em; padding-top:4px}
h2{font-family:var(--serif); font-weight:400; font-size:1.6rem; letter-spacing:-.014em; margin:0; flex:none}
.shead .rule{flex:1; height:1px; background:linear-gradient(90deg,var(--rule),transparent); transform:translateY(-3px)}
/* h2 is flex:none so the trailing rule fills the row. On a narrow screen that
   makes a long heading ("OOH Campaign Performance Analyzer") push past the
   viewport instead of wrapping, so below 620px it is allowed to shrink and the
   rule steps aside. */
@media (max-width:620px){
  .shead{gap:11px}
  .shead h2{flex:1 1 auto; min-width:0}
  .shead .rule{display:none}
}

/* ---------------- portrait ---------------- */
.portrait-wrap{position:relative; flex:none; width:158px}
.portrait{
  width:158px; height:190px; object-fit:cover; border-radius:5px;
  border:1px solid var(--rule); display:block; background:var(--paper-2);
  filter:saturate(.92) contrast(1.02);
}
.portrait-wrap::after{
  content:''; position:absolute; inset:12px -12px -12px 12px; border:1px solid var(--accent);
  border-radius:5px; z-index:-1; opacity:.4;
}
.portrait-ph{
  width:158px; height:190px; border-radius:5px; border:1px dashed var(--rule);
  display:flex; align-items:center; justify-content:center; text-align:center;
  color:var(--muted); font-size:.72rem; padding:14px; background:var(--paper-2); line-height:1.5;
}
.hero-flex{display:flex; gap:38px; align-items:flex-start}
@media (max-width:640px){
  .hero-flex{flex-direction:column-reverse; gap:26px}
  .portrait-wrap,.portrait,.portrait-ph{width:118px}
  .portrait,.portrait-ph{height:142px}
}

/* ---------------- status list ---------------- */
.status{margin:52px 0 0; border-top:1px solid var(--rule)}
.status dl{margin:0; display:grid; grid-template-columns:112px 1fr}
/* Fixed-width label column in the small-caps register: mono, 10px, tracked
   out, --faint. Quiet enough that the row reads as content-with-a-label
   rather than a two-column table. 4.60:1 on --paper. */
.status dt{
  font-family:var(--mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--faint); padding:19px 14px 19px 0; border-bottom:1px solid var(--rule);
  font-weight:500; line-height:1.5;
}
.status dd{margin:0; padding:16px 0; border-bottom:1px solid var(--rule); font-size:.95rem}
.status dd span{color:var(--muted)}
.status dd b{font-weight:500}
/* Dates live at the end of the row, not in the label column. The column stays
   one kind of thing -- a label -- and the date is still there to read.
   --faint on --paper is 4.60:1.

   The markup carries a real space before this element as well as the margin
   here. The margin alone separated it on screen but left the text content as
   "practice.Apr-Jul 2026", which is what you get when you copy the row or
   listen to it. Spacing you can only see is not spacing. */
.stamp{
  font-family:var(--mono); font-size:.71rem; color:var(--faint);
  letter-spacing:.06em; white-space:nowrap; margin-left:7px;
}
.status dd span.stamp{color:var(--faint)}
@media (max-width:540px){
  .status dl{grid-template-columns:1fr}
  .status dt{padding:16px 0 2px; border-bottom:none}
  .status dd{padding:0 0 16px}
}

/* ---------------- cards ---------------- */
.card{
  background:var(--card); border:1px solid var(--rule); border-radius:11px;
  padding:24px 26px; box-shadow:var(--shadow); transition:all .28s cubic-bezier(.4,0,.2,1);
  position:relative; overflow:hidden;
}
.card::before{
  content:''; position:absolute; left:0; top:0; bottom:0; width:2.5px; z-index:2;
  background:linear-gradient(180deg,var(--accent),var(--accent-2));
  transform:scaleY(0); transform-origin:top; transition:transform .34s cubic-bezier(.4,0,.2,1);
}
.card:hover{transform:translateY(-3px); box-shadow:var(--shadow-lift); border-color:color-mix(in srgb,var(--accent) 30%,var(--rule))}
.card:hover::before{transform:scaleY(1)}
.card + .card{margin-top:16px}

/* Header strip. Bleeds to the card edge with negative margins so the card
   reads as a framed panel with a label, not a block of text in whitespace.
   The mono label on the right is the existing .meta. */
.card-top{
  display:flex; justify-content:space-between; align-items:baseline; gap:14px; flex-wrap:wrap;
  margin:-24px -26px 19px; padding:13px 26px;
  background:var(--paper-2); border-bottom:1px solid var(--rule);
}
.card h3{font-family:var(--serif); font-weight:400; font-size:1.3rem; margin:0; letter-spacing:-.012em}
.card h3 a{
  text-decoration:none;
  background-image:linear-gradient(var(--accent),var(--accent));
  background-size:0% 1.5px; background-repeat:no-repeat; background-position:0 100%;
  transition:background-size .3s ease,color .18s;
}
.card h3 a:hover{background-size:100% 1.5px; color:var(--accent)}
/* --muted, not --faint: .meta moved onto the --paper-2 header strip, where
   --faint is 4.25:1 in light mode and fails AA. */
.meta{
  font-family:var(--mono); font-size:.68rem; color:var(--muted); white-space:nowrap;
  letter-spacing:.11em; text-transform:uppercase; font-variant-numeric:tabular-nums;
}
.card .sub{color:var(--muted); font-size:.96rem; margin:11px 0 14px; max-width:62ch}
.card ul{margin:0; padding-left:0; list-style:none}
.card li{font-size:.925rem; margin-bottom:8px; padding-left:19px; position:relative; color:var(--ink)}
.card li::before{content:''; position:absolute; left:1px; top:.72em; width:9px; height:1px; background:var(--accent); opacity:.65}

/* badges */
.badge{
  font-family:var(--mono); font-size:.62rem; text-transform:uppercase; letter-spacing:.1em;
  border-radius:100px; padding:2.5px 9px; margin-left:9px; vertical-align:2.5px;
  font-weight:500; white-space:nowrap; border:1px solid;
}
.badge.build{color:var(--accent); border-color:var(--accent); background:var(--accent-soft)}
.badge.live{color:var(--accent-2); border-color:var(--accent-2); background:var(--accent-2-soft)}
.badge.pub{color:var(--accent-2); border-color:var(--accent-2); background:var(--accent-2-soft)}

/* ---------------- categorised pill tags ----------------
   Outlined, not filled, and colour-coded so a stack row is scannable by kind
   rather than being one undifferentiated grey block:
     .t-lang  --accent    languages
     .t-data  --accent-2  data stores, libraries, platforms
     .t-viz   --faint     visualisation, and the neutral default
   Borders are the category colour at partial alpha; text is the full value, so
   every pill clears AA on --card and on --paper (4.84:1 worst case). */
.stack{display:flex; flex-wrap:wrap; gap:6px; margin-top:18px}
.stack span{
  font-family:var(--mono); font-size:.7rem; letter-spacing:.02em; white-space:nowrap;
  border:1px solid; border-radius:4px; padding:3px 9px; background:transparent;
  color:var(--faint); border-color:color-mix(in srgb,var(--faint) 38%,transparent);
}
.stack span.t-lang{color:var(--accent); border-color:color-mix(in srgb,var(--accent) 42%,transparent)}
.stack span.t-data{color:var(--accent-2); border-color:color-mix(in srgb,var(--accent-2) 42%,transparent)}
.stack span.t-viz{color:var(--faint); border-color:color-mix(in srgb,var(--faint) 38%,transparent)}

/* ---------------- principles grid ---------------- */
.grid-3{display:grid; grid-template-columns:repeat(3,1fr); gap:14px}
@media (max-width:700px){.grid-3{grid-template-columns:1fr}}
.tile{
  background:var(--card); border:1px solid var(--rule); border-radius:11px; padding:0;
  transition:all .28s cubic-bezier(.4,0,.2,1); overflow:hidden;
}
.tile:hover{transform:translateY(-3px); box-shadow:var(--shadow-lift); border-color:color-mix(in srgb,var(--accent) 28%,var(--rule))}
/* Same header-strip treatment as .card: the numeral becomes a label, not a
   floating superscript. No text-transform — the roman numerals are written
   lowercase on purpose. */
.tile .n{
  display:block; margin:0; padding:10px 20px;
  background:var(--paper-2); border-bottom:1px solid var(--rule);
  font-family:var(--mono); font-size:.7rem; color:var(--accent); letter-spacing:.13em;
}
.tile h4{font-family:var(--serif); font-weight:400; font-size:1.09rem; margin:18px 20px 8px; letter-spacing:-.008em}
.tile p{margin:0 20px 20px; font-size:.895rem; color:var(--muted); line-height:1.6}

/* ---------------- experience panels ----------------
   Framed rather than divided by hairlines. These blocks carry the densest
   figures on the site and were the hardest thing to scan as open rows. */
.job{
  padding:0; background:var(--card); border:1px solid var(--rule); border-radius:11px;
  box-shadow:var(--shadow); margin-bottom:16px; overflow:hidden;
}
.job-top{
  display:grid; grid-template-columns:1fr auto; gap:6px 18px; align-items:baseline;
  padding:14px 24px; background:var(--paper-2); border-bottom:1px solid var(--rule);
}
.job h3{font-family:var(--serif); font-weight:400; font-size:1.24rem; margin:0; letter-spacing:-.01em}
.job .role{color:var(--accent); font-size:.88rem; margin:3px 0 0; font-weight:500}
.job .when{
  font-family:var(--mono); font-size:.68rem; color:var(--muted); white-space:nowrap;
  text-align:right; letter-spacing:.11em; text-transform:uppercase;
  font-variant-numeric:tabular-nums;
}
.job .detail{font-size:.945rem; color:var(--muted); margin:18px 24px 0; max-width:64ch}
.job ul{margin:17px 24px 0; padding-left:0; list-style:none}
.job li{font-size:.925rem; margin-bottom:8px; padding-left:19px; position:relative}
.job li::before{content:''; position:absolute; left:1px; top:.72em; width:9px; height:1px; background:var(--accent); opacity:.65}
.job .stack{margin:18px 24px 0}
.job .facts{margin:20px 24px 0}
.job > :last-child{margin-bottom:22px}
@media (max-width:540px){
  .job-top{grid-template-columns:1fr; padding:13px 18px}
  .job .when{text-align:left}
  .job .detail,.job ul,.job .stack,.job .facts{margin-left:18px; margin-right:18px}
}

/* ---------------- definition rows ---------------- */
.drows{border-top:1px solid var(--rule); margin:0}
.drow{display:grid; grid-template-columns:158px 1fr; border-bottom:1px solid var(--rule)}
.drow dt{font-size:.79rem; color:var(--accent); padding:15px 14px 15px 0; font-weight:500; letter-spacing:.02em}
.drow dt a{
  text-decoration:none; background-image:linear-gradient(var(--accent),var(--accent));
  background-size:0% 1px; background-repeat:no-repeat; background-position:0 100%;
  transition:background-size .28s ease;
}
.drow dt a:hover{background-size:100% 1px}
.drow dd{margin:0; padding:15px 0; font-size:.925rem; color:var(--ink)}
.drow dd .badge{margin-left:6px}
@media (max-width:540px){
  .drow{grid-template-columns:1fr}
  .drow dt{padding:15px 0 1px}
  .drow dd{padding:0 0 15px}
}
/* .lbl — the same small-caps label column as .status, for rows where the dt is
   genuinely a label rather than a title. Not applied to the Selected work rows
   on the home page: those dt are project names carrying links and badges. */
.drows.lbl .drow{grid-template-columns:186px 1fr}
.drows.lbl dt{
  font-family:var(--mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--faint); font-weight:500; line-height:1.5; padding:17px 16px 17px 0;
}
.drows.lbl dd{padding:16px 0}
@media (max-width:540px){
  .drows.lbl .drow{grid-template-columns:1fr}
  .drows.lbl dt{padding:15px 0 3px}
  .drows.lbl dd{padding:0 0 15px}
}

/* ---------------- callout ---------------- */
.callout{
  border-left:2.5px solid var(--accent); background:var(--paper-2);
  padding:18px 22px; border-radius:0 9px 9px 0; margin:26px 0;
}
.callout p{margin:0; font-family:var(--serif); font-size:1.06rem; font-weight:300; line-height:1.55; color:var(--ink)}
/* --muted for the same reason as .facts dt: --paper-2 ground. */
.callout cite{display:block; margin-top:9px; font-style:normal; font-size:.78rem; color:var(--muted); font-family:var(--sans)}

/* ---------------- closing ---------------- */
.closing{padding:66px 0 26px}
.closing p{font-family:var(--serif); font-size:clamp(1.2rem,3.2vw,1.55rem); line-height:1.45; font-weight:300; margin:0 0 24px; max-width:28ch}
.closing p em{font-style:italic; color:var(--accent)}

footer{
  border-top:1px solid var(--rule); margin-top:40px; padding:24px 0 56px;
  display:flex; justify-content:space-between; gap:14px; flex-wrap:wrap;
  font-size:.8rem; color:var(--faint);
}
footer a{color:var(--muted); text-decoration:none; transition:color .18s}
footer a:hover{color:var(--accent)}
footer nav{display:flex; gap:16px; flex-wrap:wrap}

/* ---------------- live screenshot ---------------- */
.shot{
  margin:18px 0 4px; border:1px solid var(--rule); border-radius:8px; overflow:hidden;
  background:var(--paper-2); position:relative; display:block; line-height:0;
  text-decoration:none;
}
figure.shot{margin-left:0; margin-right:0}
figure.shot img{transition:none}
.shot img{width:100%; height:auto; display:block; transition:transform .5s cubic-bezier(.4,0,.2,1)}
.shot:hover img{transform:scale(1.015)}
.shot figcaption{
  font-family:var(--mono); font-size:.68rem; color:var(--faint); letter-spacing:.06em;
  padding:9px 13px; border-top:1px solid var(--rule); background:var(--card); line-height:1.5;
}

/* ---------------- deal context panel ---------------- */
.facts{
  margin:20px 0 4px; border:1px solid var(--rule); border-radius:10px;
  background:var(--paper-2); overflow:hidden;
}
.facts .fhead{
  font-family:var(--mono); font-size:.66rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--accent); padding:12px 18px; border-bottom:1px solid var(--rule); font-weight:500;
  background:var(--card);
}
.facts dl{margin:0; display:grid; grid-template-columns:repeat(2,1fr)}
.facts .f{padding:13px 18px; border-bottom:1px solid var(--rule)}
.facts .f:nth-child(odd){border-right:1px solid var(--rule)}
/* --muted, not --faint: these cells sit on --paper-2, where --faint is only
   4.25:1 in light mode and fails AA. --muted is 4.84:1 on the same ground. */
.facts dt{
  font-family:var(--mono); font-size:.63rem; color:var(--muted); letter-spacing:.1em;
  text-transform:uppercase; margin-bottom:6px; line-height:1.45;
}
.facts dd{margin:0; font-family:var(--serif); font-size:1.06rem; color:var(--ink); line-height:1.3}
.facts dd small{font-family:var(--sans); font-size:.76rem; color:var(--muted); display:block; margin-top:3px; line-height:1.45}
.facts .note{
  padding:12px 18px; font-size:.78rem; color:var(--muted); line-height:1.55; background:var(--card);
}
.facts .note a{color:var(--accent)}
@media (max-width:560px){
  .facts dl{grid-template-columns:1fr}
  .facts .f:nth-child(odd){border-right:none}
}

/* ---------------- published article callout ---------------- */
.press{
  display:block; text-decoration:none; background:var(--card);
  border:1px solid var(--rule); border-left:2.5px solid var(--accent-2);
  border-radius:0 11px 11px 0; padding:0; margin-top:4px; overflow:hidden;
  transition:all .28s cubic-bezier(.4,0,.2,1);
}
.press:hover{transform:translateY(-3px); box-shadow:var(--shadow-lift); border-color:var(--accent-2)}
/* Publication and date become the container's label strip. */
.press .kicker{
  font-family:var(--mono); font-size:.68rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--accent-2); margin:0; font-weight:500;
  padding:12px 26px; background:var(--paper-2); border-bottom:1px solid var(--rule);
  /* .press p below sets a 60ch measure for body copy. The label strip is not
     body copy and must span the full card, so it opts out. */
  max-width:none;
}
.press h3{font-family:var(--serif); font-weight:400; font-size:1.24rem; margin:19px 26px 9px; letter-spacing:-.012em; color:var(--ink)}
.press p{margin:0 26px; font-size:.94rem; color:var(--muted); max-width:60ch}
.press .go{display:inline-block; margin:14px 26px 22px; font-size:.85rem; color:var(--accent-2); font-weight:500}

/* ---------------- 404 ---------------- */
.nf{padding:110px 0 90px; text-align:left}
.nf .code{font-family:var(--mono); font-size:.8rem; letter-spacing:.16em; color:var(--accent); margin:0 0 18px}

/* ---------------- reveal ---------------- */
.rv{opacity:0; transform:translateY(14px); transition:opacity .65s ease, transform .65s cubic-bezier(.4,0,.2,1)}
.rv.in{opacity:1; transform:none}
@media (prefers-reduced-motion:reduce){.rv{opacity:1;transform:none;transition:none}}

/* ---------------- live embedded preview ---------------- */
.preview{
  display:block; position:relative; margin:18px 0 4px; border:1px solid var(--rule);
  border-radius:8px; overflow:hidden; background:#0d1117; text-decoration:none;
}
/* display:block is load-bearing, not decoration. .frame is a <span>, and width
   and height do not apply to an inline box — the iframe and veil inside are
   both absolutely positioned, so the span had no in-flow content and collapsed
   to one line-height (30px), showing a sliver of the dashboard instead of the
   preview. Same reason .cap needs it to sit as a full-width caption bar. */
.preview .frame{display:block; position:relative; width:100%; height:340px; overflow:hidden}
.preview iframe{
  position:absolute; top:0; left:0; width:1440px; height:1020px;
  border:0; transform:scale(.47); transform-origin:top left; pointer-events:none;
}
.preview .veil{position:absolute; inset:0; background:transparent; transition:background .25s}
.preview:hover .veil{background:rgba(255,122,69,.10)}
.preview .open{
  position:absolute; right:12px; bottom:12px; z-index:2;
  font-size:.78rem; font-weight:500; color:#0d1117; background:#ff7a45;
  border-radius:100px; padding:6px 14px; opacity:0; transform:translateY(4px);
  transition:opacity .25s, transform .25s;
}
.preview:hover .open{opacity:1; transform:none}
.preview figcaption, .preview .cap{
  display:block;
  font-family:var(--mono); font-size:.68rem; color:var(--faint); letter-spacing:.06em;
  padding:9px 13px; border-top:1px solid var(--rule); background:var(--card); line-height:1.5;
}
@media (max-width:700px){ .preview .frame{height:230px} .preview iframe{transform:scale(.32)} }

/* ---------------- problem / built rows ---------------- */
.drow dd .pb{display:block; margin-bottom:5px}
.drow dd .pb:last-child{margin-bottom:0}
.drow dd .pb b{color:var(--accent); font-weight:500}
.drow dt .badge{margin-left:8px}

/* Second accent has one job: things a reader can go and verify for themselves.
   Live sites, published writing, external sources. Sienna carries everything else. */
a[target="_blank"]:not(.btn):not(.shot):not(.preview):hover{color:var(--accent-2)}
.facts .note a{color:var(--accent-2)}
.press .go{color:var(--accent-2)}

/* ============================================================
   v2 — progressive disclosure, thread, flagship
   Assembled from the existing tokens. No new colour, typeface,
   shadow or motion type is introduced here.
   ============================================================ */

/* ---------------- skip link ---------------- */
.skip{
  position:absolute; left:-9999px; top:10px; z-index:100;
  background:var(--accent); color:var(--accent-ink);
  padding:10px 18px; border-radius:8px; font-size:.9rem; text-decoration:none;
}
.skip:focus{left:26px}

/* ---------------- disclosure ----------------
   grid-template-rows 0fr -> 1fr animates to the content's REAL height. A
   max-height guess either clips long panels or makes short ones crawl from a
   wrong value. Where the browser cannot animate it, the panel simply appears;
   that is a degradation, not a break. */
.disc{margin-top:16px}
.disc-t{
  font-family:var(--mono); font-size:.72rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--accent); background:none; border:1px solid var(--rule); border-radius:100px;
  padding:9px 16px; cursor:pointer; display:inline-flex; align-items:center; gap:8px;
  min-height:38px; transition:border-color .2s, color .2s, background .2s;
}
.disc-t:hover{border-color:var(--accent); background:var(--accent-soft)}
.disc-t .chev{display:inline-block; transition:transform .2s cubic-bezier(.4,0,.2,1); font-size:.8rem}
.disc-t[aria-expanded="true"] .chev{transform:rotate(180deg)}
.disc-p{display:grid; grid-template-rows:0fr; transition:grid-template-rows .26s cubic-bezier(.4,0,.2,1)}
.disc.on .disc-p{grid-template-rows:1fr}
.disc-p>.disc-in{overflow:hidden; min-height:0}
/* The inner padding lives on a child so it does not fight the 0fr collapse. */
.disc-in>*:first-child{margin-top:20px}
.disc-h{
  font-family:var(--mono); font-size:.66rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--accent); margin:20px 0 7px; font-weight:500;
}
.disc-in p{font-size:.94rem; color:var(--muted); margin:0 0 4px; max-width:64ch}
.disc-in p b,.disc-in li b{color:var(--ink); font-weight:600}
@media (prefers-reduced-motion:reduce){
  .disc-p{transition:none}
  .disc-t .chev{transition:none}
}

/* ---------------- one thread ----------------
   The positioning claim and its proof, adjacent. Three editorial steps, not a
   diagram: the site's voice is typographic and this keeps it that way. */
.thread{display:grid; grid-template-columns:repeat(3,1fr); gap:0; margin-top:4px}
.tstep{padding:0 22px 0 0; position:relative; display:flex; flex-direction:column}
.tstep + .tstep{padding-left:22px; border-left:1px solid var(--rule)}
.tstep .tn{
  font-family:var(--mono); font-size:.7rem; color:var(--accent); letter-spacing:.08em;
  display:block; margin-bottom:9px;
}
.tstep h3{
  font-family:var(--serif); font-weight:400; font-size:1.08rem; margin:0 0 8px;
  letter-spacing:-.01em; line-height:1.25;
}
.tstep p{font-size:.9rem; color:var(--muted); margin:0 0 12px; line-height:1.6}
.tstep .tt{
  font-family:var(--mono); font-size:.63rem; letter-spacing:.11em; text-transform:uppercase;
  color:var(--faint); margin-top:auto;
}
.tstep .tt a{color:var(--accent); text-decoration:none; border-bottom:1px solid transparent}
.tstep .tt a:hover{border-bottom-color:var(--accent)}
@media (max-width:700px){
  .thread{grid-template-columns:1fr; gap:26px}
  .tstep{padding:0 0 0 20px; border-left:1px solid var(--rule)}
  .tstep + .tstep{padding-left:20px}
}

/* ---------------- flagship ----------------
   Dominance comes from image scale, a figure band and position -- not from
   breaking the 760px measure the rest of the site is set to. */
.flag{
  background:var(--card); border:1px solid var(--rule); border-radius:11px;
  box-shadow:var(--shadow); overflow:hidden; position:relative;
}
.flag::before{
  content:''; position:absolute; left:0; top:0; bottom:0; width:3px; z-index:2;
  background:linear-gradient(180deg,var(--accent),var(--accent-2));
}
.flag .fbody{padding:22px 26px 24px}
.flag h3{font-family:var(--serif); font-weight:400; font-size:1.45rem; margin:0; letter-spacing:-.015em}
.flag .lead{font-size:1rem; color:var(--ink); margin:12px 0 0; line-height:1.65; max-width:60ch}
.flag .lead b{font-weight:600}
.flag .shot{margin:0; border:0; border-bottom:1px solid var(--rule); border-radius:0}

/* Project figures. Visually distinct from the hero .statband so a synthetic
   figure can never be mistaken for a paid-work one. */
.figband{
  display:grid; grid-template-columns:repeat(3,1fr); gap:0;
  margin:20px 0 0; border-top:1px solid var(--rule); border-bottom:1px solid var(--rule);
}
.figband .f{padding:14px 16px 13px; border-left:1px solid var(--rule); min-width:0}
.figband .f:first-child{border-left:0; padding-left:0}
.figband .fv{
  font-family:var(--mono); font-size:1.18rem; color:var(--accent); display:block;
  letter-spacing:-.01em; font-variant-numeric:tabular-nums;
}
.figband .fl{font-size:.76rem; color:var(--muted); display:block; margin-top:5px; line-height:1.45}
.synth{
  font-family:var(--mono); font-size:.63rem; letter-spacing:.11em; text-transform:uppercase;
  color:var(--faint); margin:9px 0 0;
}
@media (max-width:620px){
  .figband{grid-template-columns:1fr}
  .figband .f{border-left:0; border-top:1px solid var(--rule); padding-left:0}
  .figband .f:first-child{border-top:0}
}

/* ---------------- pull quote (the published piece) ---------------- */
.pullq{
  font-family:var(--serif); font-style:italic; font-size:1.12rem; line-height:1.55;
  color:var(--ink); margin:16px 0 14px; padding-left:18px;
  border-left:2px solid var(--accent-2);
}
.masthead{
  font-family:var(--mono); font-size:.66rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--accent-2); margin:0 0 2px;
}

/* ---------------- how I work ---------------- */
.howrow{border-top:1px solid var(--rule); padding:16px 0 15px}
.howrow:last-child{border-bottom:1px solid var(--rule)}
.howrow .hk{
  font-family:var(--serif); font-size:1.05rem; margin:0 0 7px; font-weight:400;
  letter-spacing:-.01em;
}
.howrow .hv{font-size:.9rem; color:var(--muted); margin:0 0 7px; line-height:1.6}
.howrow .he{font-family:var(--mono); font-size:.68rem; letter-spacing:.07em; color:var(--faint)}
.howrow .he a{color:var(--accent); text-decoration:none; border-bottom:1px solid transparent}
.howrow .he a:hover{border-bottom-color:var(--accent)}

/* ---------------- experience "led to" ---------------- */
.ledto{
  font-family:var(--mono); font-size:.68rem; letter-spacing:.07em; color:var(--faint);
  margin:12px 0 0;
}
.ledto a{color:var(--accent); text-decoration:none; border-bottom:1px solid transparent}
.ledto a:hover{border-bottom-color:var(--accent)}

/* ---------------- case study ---------------- */
.csnote{font-size:.9rem; color:var(--muted); margin:14px 0 0; line-height:1.65; max-width:64ch}
.evid{width:100%; border-collapse:collapse; font-size:.9rem; margin-top:6px}
.evid caption{
  font-family:var(--mono); font-size:.66rem; letter-spacing:.11em; text-transform:uppercase;
  color:var(--faint); text-align:left; padding-bottom:10px; line-height:1.6;
}
.evid th,.evid td{padding:9px 0; border-bottom:1px solid var(--rule); text-align:left; vertical-align:top}
.evid td:last-child{text-align:right; font-family:var(--mono); font-variant-numeric:tabular-nums; white-space:nowrap}
.evid th{font-weight:500; color:var(--muted); font-size:.82rem}
.evidwrap{overflow-x:auto}
.pipe{
  font-family:var(--mono); font-size:.76rem; line-height:2; color:var(--muted);
  background:var(--paper-2); border:1px solid var(--rule); border-radius:9px;
  padding:16px 18px; margin:16px 0 0; overflow-x:auto; white-space:pre;
}

/* ---------------- positioning line ----------------
   The claim the site is organised around. Promoted from body size, where the
   audit found it styled as a caption. */
.posline{
  font-family:var(--serif); font-weight:400; font-size:clamp(1.42rem,3.1vw,1.95rem);
  line-height:1.22; letter-spacing:-.018em; color:var(--ink);
  margin:20px 0 0; max-width:41ch;
}
.posline em{font-style:italic; color:var(--accent)}
.statnote{
  font-family:var(--mono); font-size:.65rem; letter-spacing:.07em; color:var(--faint);
  margin:9px 0 0;
}

/* ---------------- credibility row ----------------
   A variant of .statband where two tiles carry an employer rather than a
   figure. A number without an employer beside it is a trivia question; "CAD
   19.5M" means something once "KPMG, Deal Advisory" sits next to it. */
.stat.who .fig{
  font-family:var(--serif); font-size:clamp(19px,2.8vw,22px); font-weight:400;
  color:var(--ink); letter-spacing:-.015em;
}
.stat.who .lab{color:var(--muted)}

/* ---------------- project entry ----------------
   One system, three scales. The entry is not a card: it is a block of page, so
   the largest one reads as the most important without being labelled. */
.entry{margin-top:4px}
.entry .lede-q{
  font-family:var(--serif); font-size:clamp(1.06rem,2.2vw,1.22rem); line-height:1.5;
  color:var(--ink); margin:0 0 18px; max-width:56ch; letter-spacing:-.008em;
}
.entry .lede-q b{font-weight:500}
.entry .proof{
  font-family:var(--mono); font-size:.7rem; letter-spacing:.07em; color:var(--faint);
  margin:14px 0 0; line-height:1.9;
}
.entry .proof b{color:var(--accent); font-weight:500}
.entry .links{margin-top:18px}

/* The published piece uses the publication itself as its artifact. */
.press.artifact{margin:0 0 4px}
.press.artifact:hover{transform:none; box-shadow:var(--shadow)}

/* ---------------- where I've worked ---------------- */
.wrow{
  display:grid; grid-template-columns:1fr auto; gap:6px 18px; align-items:baseline;
  padding:15px 0; border-top:1px solid var(--rule);
}
.wrow:last-of-type{border-bottom:1px solid var(--rule)}
.wrow .wc{font-family:var(--serif); font-size:1.04rem; letter-spacing:-.01em}
.wrow .ww{font-family:var(--mono); font-size:.68rem; letter-spacing:.08em; color:var(--faint); white-space:nowrap}
.wrow .wd{grid-column:1/-1; font-size:.9rem; color:var(--muted); margin:0; line-height:1.6}
