/* ===========================================================================
   Boopathi Mahendran · ds.v3.css — shared by every page on www.boopathi.tech
   "Editorial noir": near-black canvas, oversized Geist display type with an
   Instrument Serif italic accent, hairline rules instead of card borders, and
   soft radial spotlights whose hue shifts section by section (--accent).
   Light mode ("paper noir") follows the OS or the toggle.

   VERSIONED FILENAME: /assets/* is cached hard, so never edit this file in
   place after it ships — publish ds.v4.css and update the <link> instead.
   =========================================================================== */

/* ------------------------------------------------------------ tokens */
:root{
  --bg:#faf9f7; --bg-2:#ffffff; --bg-3:#f0efeb;
  --ink:#0b0c0f; --ink-2:#4a4f59; --ink-3:#5c626c;
  --line:#0b0c0f1f; --line-2:#0b0c0f33;
  /* light-mode accents are dark enough for white text on a filled pill (AA) */
  --accent:#5b4ae0; --accent-ink:#4a39cc; --on-accent:#ffffff; --accent-soft:#ece9ff;
  --glow:20%;
  --ok:#186a3f; --warn:#8a5200; --err:#b3261e;
  --c-python:#6d28d9; --c-web:#b45309;
  --code-bg:#0b0d11; --code-ink:#e8eaee; --code-line:#20242b;
  --select:#ded8ff;

  --fd:'Geist','Geist-fb',system-ui,-apple-system,'Segoe UI',sans-serif;
  --fs:'Geist','Geist-fb',system-ui,-apple-system,'Segoe UI',sans-serif;
  --fm:'Geist Mono','GeistMono-fb',ui-monospace,'Cascadia Mono',Consolas,monospace;
  --fe:'Instrument Serif','Serif-fb',Georgia,'Times New Roman',serif;
  --t-xs:.75rem; --t-sm:.875rem; --t-md:1rem; --t-lead:1.15rem;
  --t-h3:1.25rem; --t-h2:clamp(2rem,1.4rem + 2.4vw,3.5rem); --t-h1:clamp(2.2rem,1.4rem + 3.2vw,3.6rem);
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px; --s8:64px; --s9:96px;
  --r-sm:8px; --r:14px; --r-lg:20px; --pill:999px;
  --gut:24px; --measure:68ch;
  --ease:cubic-bezier(.22,1,.36,1);
}
/* dark — declared twice on purpose (OS preference unless light was chosen,
   and the explicit choice). Keep the two blocks identical. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --bg:#08090c; --bg-2:#0f1116; --bg-3:#171a20;
    --ink:#f6f7f8; --ink-2:#a6abb5; --ink-3:#8b919c;
    --line:#ffffff17; --line-2:#ffffff30;
    --accent:#8b7cff; --accent-ink:#a89bff; --on-accent:#08090c; --accent-soft:#191a2e;
    --glow:26%;
    --ok:#4ade80; --warn:#fbbf24; --err:#f87171;
    --c-python:#a78bfa; --c-web:#fbbf24;
    --code-bg:#0b0d11; --code-ink:#e8eaee; --code-line:#20242b;
    --select:#312a63;
  }
}
:root[data-theme="dark"]{
  --bg:#08090c; --bg-2:#0f1116; --bg-3:#171a20;
  --ink:#f6f7f8; --ink-2:#a6abb5; --ink-3:#8b919c;
  --line:#ffffff17; --line-2:#ffffff30;
  --accent:#8b7cff; --accent-ink:#a89bff; --on-accent:#08090c; --accent-soft:#191a2e;
  --glow:26%;
  --ok:#4ade80; --warn:#fbbf24; --err:#f87171;
  --c-python:#a78bfa; --c-web:#fbbf24;
  --code-bg:#0b0d11; --code-ink:#e8eaee; --code-line:#20242b;
  --select:#312a63;
}

/* metric-matched fallbacks so the web-font swap doesn't shift layout */
@font-face{font-family:'Geist-fb';src:local('Segoe UI'),local('Roboto'),local('Arial');size-adjust:101%;ascent-override:94%;descent-override:24%}
@font-face{font-family:'GeistMono-fb';src:local('Consolas'),local('Menlo'),local('Courier New');size-adjust:98%;ascent-override:94%;descent-override:26%}
@font-face{font-family:'Serif-fb';src:local('Georgia'),local('Times New Roman');size-adjust:95%;ascent-override:96%;descent-override:24%}

/* -------------------------------------------------------------- base */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;color-scheme:light dark}
body{position:relative;background-color:var(--bg);color:var(--ink);font-family:var(--fs);font-size:var(--t-md);
  line-height:1.65;min-height:100vh;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:clip}
/* the spotlight layer: two soft accent washes that re-tint as --accent changes */
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:
    radial-gradient(820px 520px at 82% -8%,color-mix(in srgb,var(--accent) var(--glow),transparent),transparent 68%),
    radial-gradient(640px 480px at 4% 34%,color-mix(in srgb,var(--accent) calc(var(--glow) / 2),transparent),transparent 66%);
  transition:background-image .6s linear}
img,svg,video,canvas{max-width:100%;display:block}
img{height:auto}
::selection{background:var(--select);color:var(--ink)}
[id]{scroll-margin-top:96px}
a{color:var(--accent-ink);text-underline-offset:.22em;text-decoration-thickness:1px}
a:hover{text-decoration-thickness:2px}
strong,b{font-weight:600;color:var(--ink)}
h1,h2,h3,h4{font-family:var(--fd);font-weight:600;line-height:1.05;letter-spacing:-.035em;text-wrap:balance;color:var(--ink)}
h1{font-size:var(--t-h1);letter-spacing:-.045em;margin-bottom:var(--s4)}
h2{font-size:var(--t-h2);letter-spacing:-.04em;margin:var(--s7) 0 var(--s4)}
h3{font-size:var(--t-h3);letter-spacing:-.02em;margin:var(--s6) 0 var(--s3)}
h4{font-size:var(--t-md);letter-spacing:-.01em;margin:var(--s5) 0 var(--s2)}
/* the one editorial flourish: an italic serif word inside a headline */
.ser{font-family:var(--fe);font-style:italic;font-weight:400;letter-spacing:-.01em;color:var(--accent-ink)}
p{margin-bottom:var(--s4);max-width:var(--measure)}
ul,ol{margin:0 0 var(--s4) var(--s5);max-width:var(--measure)}
li{margin-bottom:var(--s2)}
li::marker{color:var(--ink-3)}
.stats,.steps ol,.toc ol,.fnav,.tags{max-width:none}
hr{border:0;border-top:1px solid var(--line);margin:var(--s7) 0}
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);
  clip-path:inset(50%);white-space:nowrap;border:0}
.skip-link{position:absolute;left:-9999px;top:8px;z-index:9999;background:var(--accent);color:var(--on-accent);
  padding:10px 18px;border-radius:var(--pill);font-weight:600}
.skip-link:focus{left:8px}
:focus-visible{outline:2px solid var(--accent-ink);outline-offset:3px;border-radius:4px}
:focus:not(:focus-visible){outline:none}
.wrap{max-width:780px;margin:0 auto;padding:0 var(--gut)}
.wrap.wide{max-width:1180px}

/* -------------------------------------------------- nav (hairline bar) */
nav.top{position:sticky;top:0;z-index:50;display:flex;align-items:center;gap:var(--s4);
  padding:var(--s3) var(--gut);border-bottom:1px solid var(--line);
  background:color-mix(in srgb,var(--bg) 78%,transparent);
  -webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3)}
nav.top .brand{display:inline-flex;align-items:center;gap:var(--s3);font-family:var(--fd);font-weight:600;
  font-size:.95rem;letter-spacing:-.02em;color:var(--ink);text-decoration:none;white-space:nowrap;flex:none}
nav.top .brand .d{color:var(--accent-ink);margin-left:calc(var(--s3) * -1)}
.logo{display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;
  border:1px solid var(--line-2);color:var(--ink);font-family:var(--fm);font-weight:500;font-size:.68rem;letter-spacing:.02em}
nav.top .links{display:flex;gap:var(--s1);margin-left:auto}
nav.top .links a{position:relative;font-family:var(--fm);font-size:var(--t-xs);font-weight:400;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-2);text-decoration:none;padding:10px var(--s3);white-space:nowrap;
  transition:color .2s}
/* underline that wipes in from the left */
nav.top .links a::after{content:"";position:absolute;left:var(--s3);right:var(--s3);bottom:4px;height:1px;
  background:var(--accent-ink);transform:scaleX(0);transform-origin:left;transition:transform .3s var(--ease)}
nav.top .links a:hover{color:var(--ink)}
nav.top .links a:hover::after,nav.top .links a[aria-current]::after{transform:scaleX(1)}
nav.top .links a[aria-current]{color:var(--ink)}
.theme-btn{flex:none;display:inline-grid;place-items:center;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--line);background:transparent;color:var(--ink-2);cursor:pointer;transition:color .2s,border-color .2s}
.theme-btn:hover{color:var(--ink);border-color:var(--line-2)}
.theme-btn svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.7}
.theme-btn .lbl{display:none}

/* ----------------------------------------------------- page headers */
.crumbs{font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.04em;color:var(--ink-3);margin:var(--s7) 0 0}
.crumbs a{color:var(--ink-2);text-decoration:none}
.crumbs a:hover{color:var(--accent-ink);text-decoration:underline}
.crumbs .sep{margin:0 var(--s2);color:var(--ink-3)}
.crumbs span[aria-current]{color:var(--ink)}
article>header,header.hero,.doc-head,.guide main>header,.errpage{padding-top:var(--s6)}
article>header{padding-bottom:var(--s6);border-bottom:1px solid var(--line);margin-bottom:var(--s7)}
article>header h1,.doc-head h1{font-size:clamp(2.2rem,1.3rem + 3.6vw,4rem)}
.eyebrow,.kicker{display:inline-flex;align-items:center;gap:var(--s3);font-family:var(--fm);font-size:var(--t-xs);
  font-weight:400;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-ink);margin-bottom:var(--s4)}
.eyebrow::before,.kicker::before{content:"";width:22px;height:1px;background:currentColor}
.lead{font-size:var(--t-lead);color:var(--ink-2);max-width:var(--measure)}
.kicker+h2{margin-top:0}
.grad{font-family:var(--fe);font-style:italic;font-weight:400;color:var(--accent-ink)}
.byline{margin-top:var(--s5);font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.03em;color:var(--ink-3);
  display:flex;gap:var(--s2) var(--s4);flex-wrap:wrap}
.byline>*+*::before{content:"·";margin-right:var(--s4);color:var(--line-2)}
.byline a{color:var(--ink-2)}
.byline+.tags{margin-top:var(--s4)}
.status{display:inline-flex;align-items:center;gap:var(--s2);font-size:var(--t-sm);font-weight:500;color:var(--ink-2)}
.status::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor;flex:none;
  box-shadow:0 0 0 3px color-mix(in srgb,currentColor 18%,transparent)}
td .status,p .status{white-space:nowrap}
.status.ok{color:var(--ok)}
.status.warn{color:var(--warn)}
.status.obsolete{color:var(--err)}

.toc{border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:var(--s5) 0;margin-bottom:var(--s7)}
.toc h2{font-family:var(--fm);font-size:var(--t-xs);font-weight:400;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3);margin:0 0 var(--s3)}
.toc ol{margin:0;list-style:none;counter-reset:toc;display:grid;gap:0}
.toc li{counter-increment:toc;margin:0}
.toc a{display:flex;gap:var(--s4);align-items:baseline;padding:7px 0;color:var(--ink);text-decoration:none;
  font-size:var(--t-sm);transition:color .2s,padding-left .25s var(--ease)}
.toc a::before{content:counter(toc,decimal-leading-zero);font-family:var(--fm);font-size:var(--t-xs);color:var(--ink-3)}
.toc a:hover{color:var(--accent-ink);padding-left:var(--s2)}

/* ----------------------------------------------------- tables & figures */
main{counter-reset:tbl fig lst}
.tablewrap{overflow-x:auto;margin-bottom:var(--s5)}
.tablewrap table{margin:0}
table{width:100%;border-collapse:collapse;margin-bottom:var(--s5);font-size:var(--t-sm);
  border-top:1px solid var(--line-2);background:none}
caption{caption-side:top;counter-increment:tbl;text-align:left;font-family:var(--fm);font-size:var(--t-xs);
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);padding:0 0 var(--s3)}
caption::before{content:"Table " counter(tbl) " · ";color:var(--accent-ink)}
caption.sr-only::before{content:none}
th,td{padding:12px var(--s4) 12px 0;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
thead th{font-family:var(--fm);font-weight:400;font-size:var(--t-xs);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3)}
td{color:var(--ink-2)}
th[scope="row"]{font-weight:500;color:var(--ink);white-space:nowrap}
table.spec{border-top:0}
table.spec th[scope="row"]{width:36%;font-family:var(--fm);font-weight:400;font-size:var(--t-xs);letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-3)}
table.spec td{color:var(--ink)}
table.spec td small{display:block;font-size:var(--t-xs);color:var(--ink-3)}
table.rev td:first-child{font-family:var(--fm);white-space:nowrap;color:var(--ink-3)}
figure.fig{margin:0 0 var(--s6)}
figure.fig>:not(figcaption){border:1px solid var(--line);border-radius:var(--r);background:var(--bg-2);overflow:hidden}
figure.fig img{width:100%}
figure.fig figcaption{counter-increment:fig;margin-top:var(--s3);font-size:var(--t-sm);color:var(--ink-2);max-width:var(--measure)}
figure.fig figcaption::before{content:"Fig. " counter(fig) " — ";font-family:var(--fm);font-size:var(--t-xs);color:var(--accent-ink)}

/* ------------------------------------------------------- code & notes */
code{font-family:var(--fm);font-size:.88em;background:var(--bg-3);border:1px solid var(--line);border-radius:5px;
  padding:.1em .4em;color:var(--ink)}
pre{counter-increment:lst;background:var(--code-bg);border:1px solid var(--code-line);border-radius:var(--r);
  margin-bottom:var(--s5);overflow:hidden;color-scheme:dark}
pre::before{content:"Listing " counter(lst);display:block;font-family:var(--fm);font-size:var(--t-xs);color:#8b919c;
  letter-spacing:.1em;text-transform:uppercase;padding:10px var(--s4) 10px 68px;border-bottom:1px solid var(--code-line);
  background:radial-gradient(circle at 20px 50%,#ff6b6b 4px,transparent 5px),radial-gradient(circle at 38px 50%,#fbbf24 4px,transparent 5px),
    radial-gradient(circle at 56px 50%,#4ade80 4px,transparent 5px)}
pre>code{display:block;overflow-x:auto;background:none;border:0;border-radius:0;padding:var(--s4) var(--s5);
  font-size:var(--t-sm);line-height:1.65;color:var(--code-ink)}
.note{border-left:2px solid var(--accent);padding:var(--s2) 0 var(--s2) var(--s5);margin:0 0 var(--s5)}
.note::before{content:"Note";display:block;font-family:var(--fm);font-size:var(--t-xs);font-weight:400;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-ink);margin-bottom:var(--s1)}
.note p:last-child{margin-bottom:0}
.note.warn{border-left-color:var(--warn)}
.note.warn::before{content:"Heads up";color:var(--warn)}
button.copy{font-family:var(--fm);font-size:var(--t-xs);color:var(--ink-2);background:transparent;border:1px solid var(--line-2);
  border-radius:var(--pill);padding:4px 12px;cursor:pointer}
button.copy:hover{color:var(--ink);border-color:var(--ink-3)}
.ds-toast{position:fixed;left:50%;bottom:var(--s5);transform:translateX(-50%);z-index:200;font-size:var(--t-sm);
  background:var(--ink);color:var(--bg);padding:10px 20px;border-radius:var(--pill);max-width:calc(100vw - 32px)}
.ds-toast:not(.show){display:none}

/* ------------------------------------------------ cards, tags, buttons */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:var(--s5);margin:0 0 var(--s6)}
.card{position:relative;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--bg-2);padding:var(--s5);
  transition:border-color .25s,transform .35s var(--ease)}
.card:hover,.card:focus-within{border-color:var(--line-2);transform:translateY(-4px)}
.card h3{margin:0 0 var(--s2);font-size:var(--t-lead)}
.card h3 a{color:var(--ink);text-decoration:none}
.card h3 a::after{content:"";position:absolute;inset:0;border-radius:inherit}
.card:hover h3 a,.card h3 a:focus-visible{color:var(--accent-ink)}
.card p{font-size:var(--t-sm);color:var(--ink-2);margin-bottom:var(--s3)}
.tags{display:flex;gap:6px;flex-wrap:wrap}
.tag,.chip{font-family:var(--fm);font-size:var(--t-xs);color:var(--ink-2);background:transparent;border:1px solid var(--line-2);
  border-radius:var(--pill);padding:2px 10px;white-space:nowrap}
.tag.easy{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 45%,transparent)}
.tag.medium{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 45%,transparent)}
.complexity{display:flex;gap:var(--s5);flex-wrap:wrap;margin:0 0 var(--s5);border-top:1px solid var(--line);padding-top:var(--s4)}
.cx{flex:1;min-width:150px}
.cx span{display:block;font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.cx b{font-family:var(--fd);font-size:1.7rem;font-weight:600;letter-spacing:-.03em;color:var(--accent-ink)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);font-family:var(--fs);font-size:var(--t-sm);
  font-weight:500;text-decoration:none;padding:13px 24px;border-radius:var(--pill);border:1px solid var(--line-2);
  color:var(--ink);background:transparent;cursor:pointer;
  transform:translate(var(--mx,0),var(--my,0));
  transition:transform .3s var(--ease),background .2s,color .2s,border-color .2s}
.btn:hover{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.btn.pri{background:var(--accent);color:var(--on-accent);border-color:transparent}
.btn.pri:hover{background:var(--accent-ink);color:var(--on-accent)}
.btn.sec{background:transparent}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.related,.authorbox,.author{border-top:1px solid var(--line-2);padding:var(--s5) 0 0;margin:var(--s7) 0 0}
.related h2,.authorbox h2,.author h2{font-family:var(--fm);font-size:var(--t-xs);font-weight:400;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);margin:0 0 var(--s3)}
.related ul{margin:0 0 0 var(--s5)}
.related li{font-size:var(--t-sm);color:var(--ink-2)}
.authorbox,.author{display:flex;gap:var(--s5);align-items:flex-start;margin-top:var(--s6)}
.authorbox img,.author img{width:64px;height:64px;flex:none;border-radius:50%;object-fit:cover;border:1px solid var(--line-2)}
.authorbox p,.author p{font-size:var(--t-sm);color:var(--ink-2);margin-bottom:var(--s2)}
.authorbox p:last-child,.author p:last-child{margin-bottom:0}
.author .name{font-family:var(--fd);font-size:var(--t-lead);font-weight:600;letter-spacing:-.02em;line-height:1.3}
.author .role{font-size:var(--t-sm);color:var(--ink-3);margin-bottom:var(--s3)}
.actions{display:flex;gap:var(--s3);flex-wrap:wrap;margin-top:var(--s5)}

/* ----------------------------------------------------------- blog index */
[data-cat]{--layer:var(--accent)}
[data-cat="python"],[data-filter="python"]{--layer:var(--c-python)}
[data-cat="web"],[data-filter="web"]{--layer:var(--c-web)}
.sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s4);flex-wrap:wrap;
  border-top:1px solid var(--line);padding-top:var(--s4);margin:var(--s7) 0 var(--s5)}
.sec-head h2{margin:0;font-size:var(--t-h3)}
.filters{display:flex;gap:6px;flex-wrap:wrap}
.pill{display:inline-flex;align-items:center;gap:var(--s2);font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-2);background:transparent;border:1px solid var(--line);border-radius:var(--pill);
  padding:7px 15px;cursor:pointer;transition:background .2s,color .2s,border-color .2s}
.pill:hover{color:var(--ink);border-color:var(--line-2)}
.pill[aria-pressed="true"]{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.pill .n{font-family:var(--fm);font-size:var(--t-xs);opacity:.6}
.posts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5);margin-bottom:var(--s6)}
article.card{padding:0;overflow:hidden;display:flex;flex-direction:column}
article.card .body{display:flex;flex-direction:column;flex:1;padding:var(--s5)}
article.card .meta{display:flex;align-items:center;gap:var(--s2) var(--s3);flex-wrap:wrap;font-size:var(--t-xs);
  color:var(--ink-3);margin-bottom:var(--s3);font-family:var(--fm);letter-spacing:.04em}
article.card .meta .cat{display:inline-flex;align-items:center;gap:6px;color:var(--ink);font-weight:500}
article.card .meta .cat::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--layer)}
article.card h2{font-size:var(--t-h3);margin:0 0 var(--s3)}
article.card h2 a{color:var(--ink);text-decoration:none}
article.card h2 a::after{content:"";position:absolute;inset:0;border-radius:inherit}
article.card:hover h2 a,article.card h2 a:focus-visible{color:var(--accent-ink)}
article.card p{font-size:var(--t-sm);color:var(--ink-2)}
.more{display:inline-flex;align-items:center;gap:var(--s2);margin-top:auto;padding-top:var(--s4);font-family:var(--fm);
  font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--accent-ink);text-decoration:none}
.more .arr{transition:transform .25s var(--ease)}
.card:hover .more .arr{transform:translateX(5px)}
/* card cover: a small code window, always dark like a real editor */
.cover{position:relative;padding:var(--s6) var(--s5) var(--s5);background:var(--code-bg);color-scheme:dark;
  background-image:radial-gradient(420px 200px at 90% 0%,color-mix(in srgb,var(--layer) 32%,transparent),transparent 70%)}
.flag{position:absolute;top:var(--s3);right:var(--s3);font-family:var(--fm);font-size:.68rem;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--on-accent);background:var(--accent);padding:2px 10px;border-radius:var(--pill)}
.win{font-family:var(--fm);font-size:var(--t-xs);line-height:1.8;color:#b4b9c4;background:#12151a;border:1px solid #23272f;
  border-radius:10px;padding:var(--s3) var(--s4)}
.win .bar{display:flex;align-items:center;gap:6px;color:#8b919c;border-bottom:1px solid #23272f;padding-bottom:var(--s2);margin-bottom:var(--s2)}
.win .bar i{width:9px;height:9px;border-radius:50%;background:#3a3f48;flex:none}
.win .bar i:nth-child(1){background:#ff6b6b}.win .bar i:nth-child(2){background:#fbbf24}.win .bar i:nth-child(3){background:#4ade80}
.win .bar span{margin-left:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.win .scr{overflow:hidden}
.win .ln{white-space:pre;overflow:hidden;text-overflow:ellipsis}
.win .k{color:#c4b5ff}.win .f{color:#8b7cff}.win .c{color:#8b919c}.win .ok{color:#4ade80}.win .er{color:#f87171}
.win .q{display:flex;align-items:center;gap:var(--s2);border:1px solid #2c3038;border-radius:var(--pill);padding:2px 10px;margin-bottom:var(--s2);color:#e8eaee}
.win svg{display:inline;vertical-align:-1px}
.win .url{color:#8b919c}
.win .ttl{font-family:var(--fs);color:#a89bff}
.win .bars b{display:block;height:5px;border-radius:3px;background:#2c3038;margin-top:5px}
.win .bars b:last-child{width:66%}
.cur{display:inline-block;width:.55em;height:1em;margin-left:4px;vertical-align:-.15em;background:#8b7cff;border-radius:1px}
@media(min-width:760px){
  .posts .featured,.posts.is-filtered article.card{grid-column:1/-1;display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr)}
  .posts .featured .cover,.posts.is-filtered .cover{display:flex;align-items:center;padding:var(--s6)}
  .posts .featured .cover .win,.posts.is-filtered .cover .win{width:100%}
  .posts .featured h2,.posts.is-filtered article.card h2{font-size:clamp(1.5rem,1.1rem + 1.4vw,2.1rem)}
  .posts .featured .body,.posts.is-filtered .body{padding:var(--s6);justify-content:center}
}
.stats{list-style:none;display:flex;flex-wrap:wrap;gap:0;margin:var(--s6) 0 0;border-top:1px solid var(--line)}
.stats li{display:flex;flex-direction:column;gap:2px;margin:0;padding:var(--s4) var(--s6) var(--s4) 0}
.stats b{font-family:var(--fd);font-size:1.8rem;font-weight:600;letter-spacing:-.04em;line-height:1.1}
.stats span{font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}
.stats a{color:inherit;text-decoration:none}

/* ------------------------------------------------ guide (ESP32 setup) */
.guide{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s6);align-items:start}
.guide>*{min-width:0}
@media(min-width:1024px){
  .guide{grid-template-columns:230px minmax(0,780px);justify-content:center;column-gap:var(--s7)}
  .guide>.steps{position:sticky;top:96px;margin:var(--s6) 0 0;max-height:calc(100vh - 120px);overflow:auto}
}
.steps{border-top:1px solid var(--line);padding:var(--s4) 0;margin-bottom:var(--s6)}
.steps h2{font-family:var(--fm);font-size:var(--t-xs);font-weight:400;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin:0 0 var(--s3)}
.steps .kicker{margin:var(--s4) 0 var(--s2)}
.steps .kicker:first-child{margin-top:0}
.steps ol{margin:0;list-style:none;counter-reset:step}
.steps ul{list-style:none;margin:0}
.steps li{counter-increment:step;margin:0}
.steps a{display:flex;align-items:baseline;gap:var(--s3);padding:7px 0;color:var(--ink);text-decoration:none;
  font-size:var(--t-sm);transition:color .2s,padding-left .25s var(--ease)}
.steps ol a::before{content:counter(step,decimal-leading-zero);font-family:var(--fm);font-size:var(--t-xs);color:var(--ink-3)}
.steps ul a::before{content:"—";color:var(--ink-3)}
.steps a:hover{color:var(--accent-ink);padding-left:var(--s2)}
.steps a[aria-current="true"]{color:var(--accent-ink)}
.steps .done{color:var(--ok);margin-left:auto;font-family:var(--fm);font-size:var(--t-xs)}
.steps .src{font-family:var(--fm);font-size:var(--t-xs);color:var(--ink-3);border-top:1px solid var(--line);padding-top:var(--s3);margin:var(--s4) 0 0;line-height:1.7}
section.step{border-top:1px solid var(--line);padding-top:var(--s5);margin-top:var(--s7)}
section.step>h2{margin-top:0;font-size:clamp(1.5rem,1.1rem + 1.4vw,2.1rem)}
.cmdline{display:flex;align-items:center;gap:var(--s3);border:1px solid var(--code-line);border-radius:var(--r-sm);
  background:var(--code-bg);color-scheme:dark;padding:10px var(--s4);margin:0 0 var(--s4);max-width:100%}
.cmdline .lbl{flex:none;font-family:var(--fm);font-size:var(--t-xs);color:#a89bff}
.cmdline code{flex:1;min-width:0;background:none;border:0;padding:0;overflow-x:auto;white-space:nowrap;
  font-size:var(--t-sm);color:#e8eaee;scrollbar-width:thin}
.cmdline button.copy{flex:none;border-color:#2c3038;color:#c9ced8}
.readout{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);align-items:baseline;font-family:var(--fm);font-size:var(--t-sm);
  border:1px dashed var(--line-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);margin-top:var(--s3)}
.readout .lbl{font-size:var(--t-xs);color:var(--ok)}
a.card{display:block;color:var(--ink);text-decoration:none}
a.card:hover .dc-dl{text-decoration:underline}
.dc-name{display:block;font-family:var(--fd);font-weight:600;letter-spacing:-.02em;margin-bottom:var(--s1)}
.dc-desc{display:block;font-size:var(--t-sm);color:var(--ink-2);margin-bottom:var(--s3)}
.dc-dl{display:block;font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--accent-ink)}
.subpart{border-left:1px solid var(--line-2);padding:0 0 var(--s2) var(--s5);margin-bottom:var(--s5)}
.subpart h3{margin:var(--s2) 0 var(--s1)}
.checklist{list-style:none;margin-left:0}
.checklist li{display:flex;gap:var(--s3);border-top:1px solid var(--line);padding:var(--s3) 0;margin:0}
.checklist li::before{content:"";flex:none;width:16px;height:16px;margin-top:4px;border-radius:4px;border:1px solid var(--accent-ink)}
.ok-mark{color:var(--ok);font-weight:600}
table.ref th[scope="row"]{width:3.5rem;font-family:var(--fm);font-weight:400;color:var(--accent-ink);text-align:left}

/* --------------------------------------- case study (HydroSmart) */
.backlink{font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.06em;margin:var(--s2) 0 0}
.backlink a{color:var(--ink-2);text-decoration:none}
.backlink a:hover{color:var(--accent-ink)}
.doc-head>*{max-width:780px}
main>section{margin-top:var(--s8)}
.features{display:grid;gap:var(--s5);margin:0 0 var(--s6)}
@media(min-width:760px){.features{grid-template-columns:repeat(3,minmax(0,1fr))}}
.feature{border-top:1px solid var(--line-2);padding-top:var(--s4)}
.feature::before{content:"";display:block;width:24px;height:2px;background:var(--accent);margin-bottom:var(--s4)}
.feature h4{margin:0 0 var(--s2)}
.feature p{font-size:var(--t-sm);color:var(--ink-2);margin:0}
.flow{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);list-style:none;margin:0 0 var(--s5);padding:0;max-width:none}
.flow li{margin:0;font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.04em;border:1px solid var(--line-2);
  border-radius:var(--pill);padding:8px 18px;display:flex;align-items:center;gap:var(--s2)}
.flow li:not(:last-child)::after{content:"→";color:var(--accent-ink);margin-left:var(--s3);margin-right:calc(var(--s2) * -1)}
.flow li:last-child{background:var(--accent);color:var(--on-accent);border-color:transparent}
.arch{list-style:none;margin:0;counter-reset:arch;max-width:none;display:grid;gap:0}
.arch>li{counter-increment:arch;display:grid;grid-template-columns:52px minmax(0,1fr);gap:var(--s4);align-items:start;
  border-top:1px solid var(--line);padding:var(--s5) 0;margin:0}
.arch>li::before{content:counter(arch,decimal-leading-zero);font-family:var(--fm);font-size:var(--t-xs);color:var(--accent-ink);
  letter-spacing:.08em;padding-top:4px}
.arch h3{margin:0 0 var(--s1);font-size:var(--t-md)}
.arch p{margin:0;color:var(--ink-2);font-size:var(--t-sm)}
.gallery{display:grid;gap:var(--s6);margin-bottom:var(--s6)}
@media(min-width:760px){.gallery{grid-template-columns:repeat(2,minmax(0,1fr))}.gallery figure.fig:first-child{grid-column:1/-1}}
.gallery picture{display:block;aspect-ratio:16/10;padding:var(--s3)}
.gallery picture img{width:100%;height:100%;object-fit:contain}
.gallery figure.fig:first-child picture{aspect-ratio:2/1}
.gallery figcaption::before{display:none}
.gallery figcaption h3{font-size:var(--t-md);margin:var(--s2) 0 var(--s1)}
.gallery figcaption p{font-size:var(--t-sm);color:var(--ink-2);margin:0}
.cards3{display:grid;gap:var(--s5)}
@media(min-width:760px){.cards3{grid-template-columns:repeat(3,minmax(0,1fr))}}
.cards3>div{border-top:1px solid var(--line-2);padding-top:var(--s4);display:flex;flex-direction:column}
.cards3 h3{margin:0 0 var(--s2)}
.cards3 p{font-size:var(--t-sm);color:var(--ink-2)}
.cards3 .btn{margin-top:auto;align-self:flex-start}

/* ---------------------------------------------------------- 404 page */
.errcode{font-family:var(--fd);font-weight:600;font-size:clamp(5rem,22vw,11rem);line-height:.85;letter-spacing:-.06em;
  color:var(--ink);margin:var(--s4) 0}
.errpage .actions{margin-top:var(--s5)}

/* -------------------------------------------------------------- footer */
footer{margin-top:var(--s9);border-top:1px solid var(--line);padding:var(--s7) 0 var(--s6)}
.fnav,footer.site .fl{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--s2) var(--s5);margin-bottom:var(--s5)}
.fnav a,footer.site .fl a{font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.04em;color:var(--ink-2);text-decoration:none}
.fnav a:hover,footer.site .fl a:hover{color:var(--accent-ink)}
.fbtm,footer.site>div{text-align:center;font-size:var(--t-sm);color:var(--ink-3)}
.footstrip{display:flex;justify-content:center;margin-top:var(--s4)}
.footstrip a{font-family:var(--fm);font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2);
  text-decoration:none;border:1px solid var(--line);border-radius:var(--pill);padding:7px 18px}
.footstrip a:hover{color:var(--ink);border-color:var(--line-2)}

/* --------------------------------------------------------------- mobile */
@media(max-width:760px){
  :root{--gut:16px}
  nav.top{flex-wrap:wrap;gap:var(--s2) var(--s3);padding:var(--s2) var(--gut)}
  nav.top .links{order:3;width:100%;margin:0;overflow-x:auto;scrollbar-width:none;flex-wrap:nowrap;
    -webkit-mask-image:linear-gradient(90deg,#000 88%,transparent);mask-image:linear-gradient(90deg,#000 88%,transparent)}
  nav.top .links::-webkit-scrollbar{display:none}
  nav.top .links a{padding:8px var(--s2)}
  nav.top .links a::after{left:var(--s2);right:var(--s2)}
  .theme-btn{margin-left:auto}
  .posts{grid-template-columns:minmax(0,1fr)}
  .authorbox,.author{flex-direction:column;gap:var(--s4)}
  .complexity{gap:var(--s4)}
}

/* ---------------------------------------------------------------- motion */
/* sections ease in as they scroll into view (CSS only; browsers without
   scroll timelines, and reduced-motion users, simply see everything) */
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline:view()){
    .reveal{animation:ds-rise linear both;animation-timeline:view();animation-range:entry 0% entry 38%}
    .shead::after{animation:ds-rule linear both;animation-timeline:view();animation-range:entry 10% entry 55%}
  }
}
@keyframes ds-rise{from{opacity:.15;transform:translateY(30px)}to{opacity:1;transform:none}}
@keyframes ds-rule{from{transform:scaleX(0)}to{transform:scaleX(1)}}
html.lite .reveal,html.lite .shead::after{animation:none!important}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  html{scroll-behavior:auto}
  body::before{transition:none}
}
@media (forced-colors:active){
  .card,.note,.toc,table,.btn,.pill,nav.top{border:1px solid CanvasText}
  body::before{display:none}
}
@media print{
  nav.top,.theme-btn,.filters,.skip-link,.ds-toast,button.copy,.footstrip{display:none!important}
  body{background:#fff;color:#000}
  body::before{display:none}
  main a[href^="http"]::after{content:" <" attr(href) ">";font-size:.75em}
  .card,.note,table,figure.fig,pre{break-inside:avoid}
}
