/*  ==========================================================
  ELECTRIC EULOGY — style.css
  ----------------------------------------------------------
  MADE BY: "CESARE" S.
  PROJECT NAME: ElectricEulogy
  ----------------------------------------------------------
  This file is part of the Electric Eulogy website project.
  ----------------------------------------------------------
  HOW THIS STYLESHEET IS ORGANIZED
  ----------------------------------------------------------
  Sections are marked with "--- NAME ---" comment banners in the same order the matching HTML sections appear in index.html:
  - Ticker, Navigation, Layout, Home, About, Art, Code, Blog, Shop, Modal, Lightbox, footer/misc...

  A dedicated "RESPONSIVE / MOBILE" section at the very end overrides earlier rules with @media queries for tablet and phone screen widths.
========================================================== */

@import url('https://fonts.googleapis.com/css2?family=Poiret+One&family=Rajdhani:wght@500;600;700&family=VT323&family=Kaisei+HarunoUmi&family=Zen+Kaku+Gothic+New:wght@400;500;700&family=Diphylleia&family=Gothic+A1:wght@400;500;600;700&family=Long+Cang&family=Noto+Sans+SC:wght@400;500;600;700&family=Bpmf+Zihi+Kai+Std&family=Noto+Sans+TC:wght@400;500;600;700&family=Bilbo&family=Be+Vietnam+Pro:wght@400;500;600;700&display=swap');

/* ============================================================
   --- LANGUAGE FONT STACKS - Reusable color/font "constants" ---
   ------------------------------------------------------------
   --D (display) and --M (body) are Latin-only (Poiret One & Rajdhani).
   
   js/lang.js sets <html data-lang="..."> as early as possible (an inline snippet in each page's <head>, before first paint) so there's no flash of the wrong font while the page loads. 
   Because literally every rule below this point reaches its font through var(--D)/var(--M) rather than a hardcoded family name, overriding just these two variables per language re-themes the ENTIRE site — 
   nav, headings, buttons, tags, forms, everything — with no other rule anywhere needing to know a language switcher exists.

   English and Spanish are deliberately not listed here: both are plain Latin script and Poiret One/Rajdhani already render Spanish's accented characters (á é í ñ ó ú ü) fine, so the :root defaults apply as-is.

   Each language gets a "thin-elegant" display font (re: Poiret One's deco linework: For headings/nav/buttons/logos) paired with a "high-glyph-coverage" body font (re: Rajdhani's workhorse role: For paragraphs/forms/dense text) —
   rather than defaulting everything to plain Noto Sans, which would read as generic and lose the site's art-deco identity.

   ja/ko/zh-Hans/zh-Hant/vi lean even further into that split than English/Spanish do: --D is a genuine calligraphic face for each of those five, while --M is a clean geometric "metro/modern" UI sans chosen to read as crisp
   and systematic at the small sizes nav tabs/buttons/badges/forms actually render at — so the contrast between "title" and "small print" is much starker for these five than it is for the site's default look.

   Within --D: ja/zh-Hans target a sharp, angular, dry-brush "torn-edge" ink-calligraphy look (bold declarative brushwork with visible texture at the stroke edges) via Yuji Mai and Long Cang — both explicitly described
   by their own designers/Google's listing as "raw," "unrestrained," and "textured" rather than polished. ko/zh-Hant instead use two exact fonts requested by name (Diphylleia, Bpmf Zihi Kai Std) — softer, warmer,
   more rounded/disciplined brush calligraphy, gentle rather than jagged. vi (Bilbo) sits in between: legible and disciplined rather than either extreme. See the per-language comments just below for the reasoning
   behind each individual pick.
============================================================ */

:root {
  --blk:#050508;
  --org:#ff6a00;
  --od:#c44d00;
  --og:#ff6a0044;
  --wht:#e8e0d0;
  --off:#c9bfad;
  --grn:#39ff5a;
  --gd:#1a8c30;
  --pnk:#ff4da6;
  --pur:#b44dff;
  --g2:#111116;
  --yel:#ffd700;
  --tel:#00e5cc;
  --ind:#4b0082;
  --indb:#6610f2;
  --indc:#9b59ff;

  --D:'Poiret One',sans-serif;
  --M:'Rajdhani',sans-serif;
  --D-lh:1.1; /* .htitle's line-height, as a var so a language whose --D face has unusually tall glyphs (deep brush descenders/flourishes) can loosen it without affecting every other language — see html[data-lang="ko"] below. */

  --nh:88px; /* Actual pixel height of <nav> */
  --fh:75px; /* Actual pixel height of <footer> */
}

/* Japanese Fonts */
html[data-lang="ja"] {
  --D:'Kaisei HarunoUmi',serif;
  --M:'Zen Kaku Gothic New',sans-serif;
}

/* --Korean Fonts */
html[data-lang="ko"] {
  --D:'Diphylleia',cursive;
  --M:'Gothic A1',sans-serif;
  --D-lh:1.55;
}

/* Mandarin, Simplified script (mainland China, Singapore) Fonts */
html[data-lang="zh-Hans"] {
  --D:'Long Cang',cursive;
  --M:'Noto Sans SC',sans-serif;
}

/* Mandarin, Traditional script (Taiwan, Hong Kong, Macau) Fonts */
html[data-lang="zh-Hant"] {
  --D:'Bpmf Zihi Kai Std',cursive;
  --M:'Noto Sans TC',sans-serif;
}

/* Vietnamese Fonts */
html[data-lang="vi"] {
  --D:'Bilbo',cursive;
  --M:'Be Vietnam Pro',sans-serif;
}

/* Reset default browser spacing */
* {
  margin:0;
  padding:0;
  box-sizing:border-box;
}

body {
  background:var(--blk);
  color:var(--wht);
  font-family:var(--M);
  font-weight:500;
  overflow-x:hidden; /* Several decorative elements intentionally bleed slightly past the viewport edge; this prevents the annoying horizontal scrollbar! */
}

/* Faint horizontal scanlines over the ENTIRE page, all the time — a subtle old-CRT-monitor texture.
Fixed + pointer-events:none so it never scrolls with the page or blocks clicks on what's underneath. */

body::after {
  content:'';
  position:fixed;
  inset:0;
  background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,.04) 2px,rgba(0,0,0,.04) 4px);
  pointer-events:none;
  z-index:9999;
}

/* ============================================================
   --- TICKER ---
   ------------------------------------------------------------
   The scrolling marquee strip
   .ticker just clips (overflow:hidden) a box pinned to the very top of the viewport; the actual scrolling illusion is entirely the @keyframes tick animation below, which slides .ticker-inner from just off the right edge (padding-left: 100% pushes the text out of view first) 
   to fully off the left edge, then loops 
============================================================ */

.ticker {
  position:fixed;
  top:0;
  left:0;
  width:100%;
  z-index:300;
  background:linear-gradient(90deg,#0a0005,#050010,#0a0005);
  border-bottom:1px solid var(--pnk);
  height:22px;
  overflow:hidden;
}

.ticker-inner {
  display:inline-block;
  white-space:nowrap;
  animation:tick 32s linear infinite;
  font-size:.72rem;
  color:var(--pnk);
  letter-spacing:2px;
  font-weight:600;
  line-height:22px;
  padding-left:100%;
}

@keyframes tick {
  from {
    transform:translateX(0);
  }
  to {
    transform:translateX(-100%);
  }
}

/* ============================================================
   --- NAVIGATION ---
============================================================ */

nav {
  position:fixed;
  top:22px;
  left:0;
  width:100%;
  z-index:200;
  background:rgba(5,5,8,.97);
  border-bottom:2px solid var(--od);
  backdrop-filter:blur(10px);
  display:flex;
  flex-direction:column;
}

nav::after {
  content:'';
  height:1px;
  background:linear-gradient(90deg,transparent,var(--yel),var(--org),var(--yel),transparent);
  opacity:.25;
}

.nlr {
  display:flex;
  align-items:center;
  justify-content:center;
  padding:.5rem 2rem .25rem;
  border-bottom:1px solid rgba(255,215,0,.08);
  position:relative;
}

.nlr::before, .nlr::after {
  content:'◆';
  position:absolute;
  color:var(--yel);
  font-size:.45rem;
  opacity:.35;
  top:50%;
  transform:translateY(-50%);
}

.nlr::before { 
  left:1.5rem; 
}

.nlr::after { 
  right:1.5rem; 
}

.nlogo {
  cursor:pointer;
  display:flex;
  flex-direction:column;
  align-items:center;
  text-decoration:none;
}

.nt {
  text-decoration:none;
  display:inline-block;
}

/* "RGB split" glitch effect on the nav logo text: the real text (.nlt) stays put and fully visible

::before and ::after stack two more copies of the same words directly on top of it in different colors (pink, green), each one only showing a thin horizontal slice via clip-path so it reads as a scan-line glitch rather than a solid duplicate
@keyframes lg1/lg2 keep both slices invisible (opacity:0) almost all the time and only nudge/flash them briefly once per animation loop, which is what makes it look like a glitch "blip" instead of a constant flicker
.htitle below uses the identical trick for the big hero heading

Both pseudo-elements read their text via content:attr(data-text) rather than a hardcoded string — js/main.js writes the current language's site title into .nlt's data-text attribute (and js/render.js does the same for .htitle),
so the glitch always flashes whatever text is actually on screen instead of always flashing the English original underneath a translated title. */

.nlt {
  font-family:var(--D);
  font-size:1.4rem;
  color:var(--org);
  letter-spacing:8px;
  text-transform:uppercase;
  position:relative;
  display:inline-block;
}

.nlt::before {
  content:attr(data-text);
  position:absolute;
  inset:0;
  color:var(--pnk);
  clip-path:polygon(0 30%,100% 30%,100% 50%,0 50%);
  animation:lg1 4s infinite;
  opacity:0;
  font-family:var(--D);
  letter-spacing:8px;
}

.nlt::after {
  content:attr(data-text);
  position:absolute;
  inset:0;
  left:2px;
  color:var(--grn);
  clip-path:polygon(0 55%,100% 55%,100% 75%,0 75%);
  animation:lg2 4s infinite;
  opacity:0;
  font-family:var(--D);
  letter-spacing:8px;
}

@keyframes lg1 {
  0%,85%,100% {
    transform:translate(0);
    opacity:0;
  }
  86% {
    transform:translate(-3px,1px);
    opacity:.7;
  }
  87% {
    transform:translate(3px,-1px);
    opacity:.5;
  }
  88%,94% {
    opacity:0;
  }
  93% {
    transform:translate(-2px,0);
    opacity:.6;
  }
}

@keyframes lg2 {
  0%,85%,100% {
    transform:translate(0);
    opacity:0;
  }
  86% {
    transform:translate(3px,0);
    opacity:.6;
  }
  87% {
    transform:translate(-2px,1px);
    opacity:.4;
  }
  88%,91% {
    opacity:0;
  }
  91% {
    transform:translate(2px,-1px);
    opacity:.5;
  }
}

.lzap {
  display:block;
  text-align:center;
  font-size:.6rem;
  color:var(--od);
  letter-spacing:6px;
  font-weight:600;
  animation:zf 3s infinite;
}

@keyframes zf {
  0%,100% {
    opacity:.6;
  }
  48% {
    opacity:.1;
  }
  90% {
    opacity:.2;
  }
  91% {
    opacity:.8;
  }
  92% {
    opacity:.3;
  }
}

.ntr {
  display:flex;
  align-items:center;
  justify-content:center;
  gap:1px;
  padding:.28rem 1rem .18rem;
  overflow-x:auto;
}

.nt {
  position:relative;
  padding:.35rem 1rem;
  font-size:.7rem;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--off);
  cursor:pointer;
  border:1px solid transparent;
  transition:all .2s;
  white-space:nowrap;
  font-family:var(--D);
}

.nt::after {
  content:'';
  position:absolute;
  bottom:0;
  left:50%;
  width:0;
  height:2px;
  background:linear-gradient(90deg,var(--yel),var(--org),var(--yel));
  transition:all .25s;
  transform:translateX(-50%);
}

.nt:hover, .nt.active {
  color:var(--org);
}

.nt:hover::after, .nt.active::after {
  width:80%; 
}

.nt.active { 
  background:rgba(255,106,0,.06); 
}

.nsep {
  width:1px;
  height:13px;
  background:linear-gradient(180deg,transparent,var(--yel),transparent);
  opacity:.2;
  margin:0 .15rem;
}

/* ============================================================
   --- LANGUAGE SWITCHER ---
   ------------------------------------------------------------
   Built by I18N.renderSwitcher() in js/i18n.js and appended after the last real nav tab (see its hookup in js/main.js).
   ------------------------------------------------------------
============================================================ */

.lswitch {
  position:relative;
  display:inline-flex;
  align-items:center;
}

.lsw-btn {
  display:inline-flex;
  align-items:center;
  gap:.4rem;
  padding:.35rem 1rem;
  font-family:var(--D);
  font-size:.7rem;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--off);
  background:none;
  border:1px solid transparent;
  cursor:pointer;
  transition:all .2s;
  white-space:nowrap;
}

.lsw-btn:hover, .lswitch.open .lsw-btn {
  color:var(--org);
  border-color:rgba(255,106,0,.3);
  background:rgba(255,106,0,.06);
}

.lsw-car {
  font-size:.55rem;
  transition:transform .2s;
  display:inline-block;
}

.lswitch.open .lsw-car {
  transform:rotate(180deg);
}

.lsw-menu {
  /* position:fixed + its top/right are set inline by I18N.renderSwitcher()/setOpen() in js/i18n.js — see the comment above this section for why. min-width/appearance stay here as before. */
  min-width:160px;
  list-style:none;
  background:rgba(8,8,14,.98);
  border:1px solid var(--od);
  box-shadow:0 8px 28px rgba(0,0,0,.55),0 0 18px rgba(255,106,0,.08);
  z-index:9998;
  display:none;
  max-height:60vh;
  overflow-y:auto;
}

.lswitch.open .lsw-menu {
  display:block;
}

.lsw-opt {
  padding:.55rem .95rem;
  font-size:.78rem;
  letter-spacing:1px;
  color:var(--off);
  cursor:pointer;
  transition:all .15s;
  border-bottom:1px solid rgba(255,215,0,.06);
  white-space:nowrap;
}

.lsw-opt:last-child {
  border-bottom:none;
}

.lsw-opt:hover {
  background:rgba(102,16,242,.1);
  color:var(--indc);
}

.lsw-opt.active {
  color:var(--org);
  background:rgba(255,106,0,.07);
}

/* Each option shows its language's own native name (in that language's real font, via a per-option language attribute — see js/lang.js) with the English name underneath, so a visitor can find their language even if they don't recognize the current UI language's script at all. */
.lsw-native {
  display:block;
  font-family:var(--D);
}

.lsw-eng {
  display:block;
  font-size:.62rem;
  color:#777;
  letter-spacing:.5px;
  margin-top:.1rem;
  font-family:'Rajdhani',sans-serif;
}

/* ============================================================
   --- LAYOUT ---
============================================================ */

.wrap { 
  padding-top:calc(22px + var(--nh)); 
}

.page {
  display:block;
}

/* Home is the only page that's centered as a flex column instead of a plain block — everything else (About, Art, Code, Blog, Shop) just flows top-to-bottom like a normal document */
#home {
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
}

section {
  position:relative;
  z-index:1;
  min-height:100vh;
  padding:3rem 2.5rem 4rem;
}

/* ============================================================
   --- SECTION TITLE ---
============================================================ */

.st {
  font-family:var(--D);
  font-size:1.55rem;
  color:var(--org);
  text-shadow:0 0 18px var(--org),0 0 40px var(--od);
  margin-bottom:.45rem;
  letter-spacing:5px;
  text-transform:uppercase;
}

.sdiv {
  width:100%;
  height:18px;
  margin-bottom:2.2rem;
  display:flex;
  align-items:center;
}

.sdiv::before {
  content:'';
  flex:1;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--yel),var(--org),var(--yel),transparent);
  opacity:.55;
}

.sbolt {
  color:var(--yel);
  font-size:.7rem;
  padding:0 .5rem;
  flex-shrink:0;
  animation:bp 2s infinite;
}

@keyframes bp {
  0%,100% {
    opacity:1;
    text-shadow:0 0 6px var(--yel);
  }
  50% {
    opacity:.4;
    text-shadow:none;
  }
}

/* ============================================================
   --- MOTIF PULSE ---
============================================================ */

@keyframes mpulse {
  0% {
    filter:drop-shadow(0 0 8px #ff6a00)  hue-rotate(0deg);
    opacity:.18;
  }
  25% {
    filter:drop-shadow(0 0 14px #ffd700) hue-rotate(60deg);
    opacity:.26;
  }
  50% {
    filter:drop-shadow(0 0 10px #6610f2) hue-rotate(160deg);
    opacity:.22;
  }
  75% {
    filter:drop-shadow(0 0 14px #ff4da6) hue-rotate(240deg);
    opacity:.28;
  }
  100% {
    filter:drop-shadow(0 0 8px #ff6a00)  hue-rotate(360deg);
    opacity:.18;
  }
}

.drg {
  position:absolute;
  right:1.5rem;
  top:2.5rem;
  pointer-events:none;
  animation:mpulse 8s ease-in-out infinite;
}

.sdeco {
  position:absolute;
  pointer-events:none;
  animation:mpulse 10s ease-in-out infinite;
}

/* Syringe decoration (bottom of the home hero). Pinned near the left edge on desktop, same as the other corner decorations (evil eye top-left, seraphim wings top-right) — but on a phone-width screen there's
  no room for it to read as a "corner" piece, so the mobile override below re-centers it under the tombstone row instead of leaving it clipped against the edge. */
.sdeco-syringe {
  left:2%;
  bottom:12%;
  width:80px;
  height:140px;
}

/* Anatomical heart decoration (bottom-left corner of the About page). Pinned near the left edge on desktop, matching the other corner decorations elsewhere on the site — but on a phone the About column is centered
   full-width (see .abg's mobile override), so a left-pinned corner piece sits right under/behind the bio text instead of reading as a corner accent. The mobile override below (RESPONSIVE section) flips it to the
   right edge instead, same fix as .sdeco-syringe gets on the home page, just mirrored since this one starts on the left rather than needing to move off it entirely. */
.sdeco-heart {
  left:2%;
  bottom:10%;
  width:100px;
  height:120px;
}

.hdrg {
  position:absolute;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%);
  pointer-events:none;
  animation:mpulse 12s ease-in-out infinite;
}

/* ============================================================
   --- ART DECO RULE ---
============================================================ */

.drule {
  display:flex;
  align-items:center;
  gap:.5rem;
  margin:1.2rem 0;
  opacity:.3;
}

.drule::before, .drule::after {
  content:'';
  flex:1;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--yel),transparent);
}

.drule span {
  color:var(--yel);
  font-size:.5rem;
  letter-spacing:4px;
  white-space:nowrap;
  font-family:var(--D);
}

/* ============================================================
   --- FILTER TABS : POIRET ONE ---
============================================================ */

.gf, .bc {
  display:flex;
  gap:3px;
  flex-wrap:wrap;
  margin-bottom:1.8rem;
}

.fb {
  padding:.4rem 1rem;
  font-family:var(--D);
  font-size:.82rem;
  letter-spacing:2px;
  text-transform:uppercase;
  background:#0d0d16;
  border:1px solid #2a2a3a;
  border-bottom:2px solid #2a2a3a;
  color:var(--off);
  cursor:pointer;
  transition:all .2s;
}

.fb.active,
.fb:hover {
  border-color:var(--indb);
  border-bottom-color:var(--yel);
  color:var(--indc);
  background:rgba(102,16,242,.07);
}

/* ============================================================
   --- ANNOUNCEMENTS ---
============================================================ */

.ann {
  display:none;
  width:100%;
  max-width:900px;
  margin-bottom:1.5rem;
  padding:.6rem 1.2rem;
  border:1px solid var(--yel);
  background:linear-gradient(135deg,rgba(255,215,0,.08),rgba(255,106,0,.06));
  font-family:var(--D);
  font-size:.78rem;
  color:var(--yel);
  letter-spacing:2px;
  text-align:center;
}

.ann::before, .ann::after {
  content:'⚡';
  padding:0 .5rem;
  color:var(--org);
}

.ann.on { display:block; }

/* ============================================================
   --- HOME ---
============================================================ */

#home {
  overflow:hidden;
  min-height:calc(100vh - 22px - var(--nh) - var(--fh));
  background:radial-gradient(ellipse at 50% 55%,#1a0510,#0a000f 40%,var(--blk) 80%);
}

.hey {
  font-family:'VT323',monospace;
  font-size:1rem;
  letter-spacing:5px;
  color:var(--pnk);
  text-transform:uppercase;
  margin-bottom:.8rem;
  text-shadow:0 0 12px var(--pnk);
}

.htitle {
  font-family:var(--D);
  font-size:clamp(1.8rem,5.8vw,4.8rem);
  font-weight:400;
  line-height:var(--D-lh,1.1);
  background:linear-gradient(180deg,#fff,#ffe0c0 25%,var(--org) 60%,var(--od));
  background-clip:text;
  -webkit-background-clip:text;
  -webkit-text-fill-color:transparent;
  filter:drop-shadow(0 0 24px var(--org));
  margin-bottom:.6rem;
  letter-spacing:10px;
  position:relative;
  display:inline-block;
  text-transform:uppercase;
  /* #home centers the .htitle BOX via flex, but that only centers the box as a whole — the two lines of text inside it (from home_title's <br/> in js/i18n.js) still default to left-aligned,
     so a shorter second line (e.g. "Eulogy" under "Electric") sits flush against the longer line's left edge instead of centered under it. This matters even more now that home_title is
     per-language: different languages' title text wraps to different-length lines around the same <br/>, so the two lines need to genuinely center against each other, not just the box against the page. */
  text-align:center;
}

/* NOTE ON TIMING: 
This used to run its own tg1/tg2 keyframes on a 5s loop, completely independent of the nav logo's lg1/lg2 loop (4s) above — same "RGB split" trick, different clock, so the two glitches drifted in and out of phase with each other instead of ever reading as one coordinated moment.
Both .nlt and .htitle exist in the DOM from the very start of page load (nav is static markup already in the HTML shell; render.js's initPage() builds #home synchronously before DOMContentLoaded even fires), 
so reusing the EXACT same lg1/lg2 keyframes + 4s duration here — rather than a lookalike tg1/tg2 pair — is what keeps the hero title's glitch flashing in the same instant as the nav's, permanently, with zero drift, instead of just "close" for a few seconds after each page load. */

.htitle::before {
  content:attr(data-text);
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,var(--pnk),#ff0077);
  background-clip:text;
  -webkit-background-clip:text;
  -webkit-text-fill-color:transparent;
  animation:lg1 4s infinite;
  clip-path:polygon(0 20%,100% 20%,100% 40%,0 40%);
  letter-spacing:10px;
  font-family:var(--D);
}

.htitle::after {
  content:attr(data-text);
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,var(--grn),#00cc44);
  background-clip:text;
  -webkit-background-clip:text;
  -webkit-text-fill-color:transparent;
  animation:lg2 4s infinite;
  clip-path:polygon(0 60%,100% 60%,100% 80%,0 80%);
  letter-spacing:10px;
  font-family:var(--D);
}

.hst {
  font-family:var(--D);
  font-size:.95rem;
  background:linear-gradient(90deg,var(--pur),var(--pnk),var(--org),var(--grn),var(--indc),var(--pur));
  background-size:200%;
  background-clip:text;
  -webkit-background-clip:text;
  -webkit-text-fill-color:transparent;
  animation:rb 3s linear infinite;
  letter-spacing:8px;
  margin-bottom:.8rem;
}

@keyframes rb {
  0% {
    background-position:0%;
  }
  100% {
    background-position:200%;
  }
}

.hsub {
  font-size:.85rem;
  color:var(--off);
  max-width:440px;
  line-height:1.9;
  margin-bottom:1.4rem;
  text-align:center;
}

.hdiv {
  display:flex;
  align-items:center;
  gap:.6rem;
  margin:.3rem auto 1.2rem;
  max-width:420px;
  width:100%;
}

.hdiv::before {
  content:'';
  flex:1;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--yel));
}

.hdiv::after {
  content:'';
  flex:1;
  height:1px;
  background:linear-gradient(90deg,var(--yel),transparent);
}

.hdiv span {
  color:var(--yel);
  font-size:.55rem;
  letter-spacing:4px;
  font-family:var(--D);
  opacity:.7;
}

.htags {
  display:flex;
  gap:.5rem;
  flex-wrap:wrap;
  justify-content:center;
  margin-bottom:1.8rem;
}

.tag {
  padding:.25rem .8rem;
  font-size:.68rem;
  letter-spacing:2px;
  text-transform:uppercase;
  border:1px solid;
  font-family:var(--D);
}

.to {
  border-color:var(--org);
  color:var(--org);
}

.tp {
  border-color:var(--pnk);
  color:var(--pnk);
}

.tg {
  border-color:var(--grn);
  color:var(--grn);
}

.tv {
  border-color:var(--pur);
  color:var(--pur);
}

.tt {
  border-color:var(--tel);
  color:var(--tel);
}

.ti {
  border-color:var(--indc);
  color:var(--indc);
}

/* ============================================================
   --- TOMBSTONES ---
   ------------------------------------------------------------
   The rounded-top "tombstone" silhouette for each social link on the home page isn't an image — it's a plain rectangular <a> whose corners are carved away with clip-path: polygon(...)
   Each pair of numbers is one point (x% y%) going clockwise around the shape; the "staircase" of points near the top is what produces the rounded/stepped arch instead of a sharp rectangle corner
   .ts-in repeats a slightly smaller version of the same polygon just inside the border for the double-outline look

   Hovering a tombstone (see initTS() in script.js) draws animated "lightning" on a <canvas> layered on top via .ts-p
============================================================ */

.tsrow {
  display:flex;
  gap:1.2rem;
  flex-wrap:wrap;
  justify-content:center;
}

.ts {
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:flex-end;
  width:86px;
  height:130px;
  padding:.4rem .35rem .5rem;
  background:linear-gradient(180deg,#0e0e1c,#09090f);
  border:1px solid var(--od);
  clip-path:polygon(0% 100%,0% 18%,8% 18%,8% 12%,17% 12%,17% 7%,28% 7%,28% 3%,50% 0%,72% 3%,72% 7%,83% 7%,83% 12%,92% 12%,92% 18%,100% 18%,100% 100%);
  color:var(--off);
  text-align:center;
  cursor:pointer;
  transition:all .25s;
  text-decoration:none;
  gap:.18rem;
  overflow:hidden;
}

.ts-in {
  position:absolute;
  inset:3px;
  clip-path:polygon(0% 100%,0% 19%,8% 19%,8% 13%,17% 13%,17% 8%,28% 8%,28% 4%,50% 1%,72% 4%,72% 8%,83% 8%,83% 13%,92% 13%,92% 19%,100% 19%,100% 100%);
  border:1px solid rgba(255,215,0,.12);
  pointer-events:none;
}

.ts-p {
  position:absolute;
  inset:0;
  pointer-events:none;
}

.ts:hover {
  border-color:var(--org);
  color:var(--org);
  box-shadow:0 0 22px var(--og);
  transform:translateY(-5px);
}

.ts:hover .ts-in { border-color:rgba(255,106,0,.26); }

.ts-deco {
  position:absolute;
  top:21%;
  left:50%;
  transform:translateX(-50%);
  width:70%;
  pointer-events:none;
}

.ts-deco::before {
  content:'';
  display:block;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--yel),transparent);
  opacity:.35;
}

.ts-deco::after {
  content:'◆';
  display:block;
  text-align:center;
  color:var(--yel);
  font-size:.26rem;
  opacity:.45;
  margin-top:1px;
}

.ts-rip {
  font-family:var(--D);
  font-size:.42rem;
  letter-spacing:3px;
  color:var(--yel);
  opacity:.8;
  display:block;
  margin-bottom:.04rem;
}

.ts-icon {
  width:34px;
  height:38px;
  flex-shrink:0;
}

.ts-icon svg {
  width:100%;
  height:100%;
}

/* A custom uploaded icon (socialIcons[].img in content.js) instead of the default drawn SVG — 34x38 */
.ts-icon img {
  width:100%;
  height:100%;
  object-fit:contain;
}

.ts-name {
  font-family:var(--D);
  font-size:.58rem;
  letter-spacing:2.5px;
  line-height:1;
  text-transform:uppercase;
}

/* ============================================================
   --- ART ---
============================================================ */

#art {
  background:var(--blk);
}

/* auto-fill + minmax(210px,1fr) is what makes this grid responsive without a single @media query: the browser fits as many 210px-or-wider columns as will comfortably reach across the current screen width, then stretches them evenly to fill any leftover space
- On a phone that's usually 1 column, on a tablet 2-3, on a wide desktop monitor 5+ — all from this one rule

See the RESPONSIVE section near the end of this file for how the minimum column width itself is narrowed further on very small screens */

.gg {
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
  gap:1rem;
}

/* Each art-piece card only pops out with a real image (rArt() adds the "has-img" class in that case — see script.js) get the pointer cursor and the "View Full Size" hover hint below; 
a card that's still just showing the 🖼 placeholder isn't clickable, so it shouldn't look clickable either!

The click itself (open the full-size lightbox) is wired up in script.js via a single delegated listener on #art-grid rather than an onclick on every card
display:flex + flex-direction:column (matching the same fix already used on .pc/.bc2/.sc for the Code/Blog/Shop grids) so .ac-info can flex:1 and absorb any leftover height itself — see the comment on .ac-info below for why this matters */
.ac {
  position:relative;
  overflow:hidden;
  background:var(--g2);
  border:1px solid #252530;
  transition:border-color .3s,box-shadow .3s;
  display:flex;
  flex-direction:column;
}

.ac.has-img {
  cursor:pointer;
}

.ac:hover {
  border-color:var(--indb);
  box-shadow:0 0 22px rgba(102,16,242,.35);
}

.ac-img {
  width:100%;
  aspect-ratio:1;
  background:linear-gradient(135deg,#1a0a2e,#0f0018,#1a0010);
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:2.5rem;
  overflow:hidden;
  position:relative;
}

.ac-img img {
  width:100%;
  height:100%;
  object-fit:cover;
}

.ac-img::after {
  content:'';
  position:absolute;
  inset:0;
  background:linear-gradient(135deg,transparent 30%,rgba(255,255,255,.05) 50%,transparent 70%);
  transform:translateX(-100%);
  transition:transform .4s;
}

.ac:hover .ac-img::after {
  transform:translateX(100%);
}

/* "View Full Size" hint overlay — sits on top of the image, invisible until hover, and never intercepts the click itself (pointer-events:none) since the click handling lives on the card/grid in script.js, not on this element */
.ac-expand {
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:.4rem;
  background:rgba(5,5,8,.55);
  color:var(--wht);
  font-family:var(--D);
  font-size:.68rem;
  letter-spacing:2px;
  text-transform:uppercase;
  text-align:center;
  opacity:0;
  transition:opacity .25s;
  pointer-events:none;
  z-index:2;
}

.ac.has-img:hover .ac-expand {
  opacity:1;
}

/* ============================================================
   --- INFO PANEL ---
============================================================ */

/* flex:1 so this panel itself stretches to fill whatever extra height the grid row imposes (rows are as tall as their tallest card, and titles/descriptions here vary a lot in how many lines they wrap to)
Without this, .ac-info only ever grew as tall as its own text, so cards with a short title+description sat inside a taller grid-stretched .ac card and left a bare gap of the card's plain background showing below the info panel — 
a stray-looking "bar" that only appeared under the shorter cards in a row, never the tallest one setting that row's height */
.ac-info {
  padding:.65rem .8rem .7rem;
  background:linear-gradient(180deg,#0d0d18,#0a0a12);
  border-top:1px solid rgba(255,215,0,.35);
  position:relative;
  flex:1;
}

.ac-info::before {
  content:'◆';
  position:absolute;
  top:-6px;
  left:50%;
  transform:translateX(-50%);
  font-size:.3rem;
  color:var(--yel);
  background:var(--g2);
  padding:0 4px;
}

.ac-title {
  font-family:var(--D);
  font-size:.95rem;
  color:#fff;
  margin-bottom:.15rem;
  letter-spacing:2px;
  text-transform:uppercase;
}

.ac-meta {
  font-family:var(--D);
  font-size:.58rem;
  color:var(--indc);
  letter-spacing:2px;
  text-transform:uppercase;
  opacity:.8;
}

.cbadge {
  position:absolute;
  top:.5rem;
  right:.5rem;
  background:#000;
  color:#ff4da6;
  font-family:var(--D);
  font-size:.6rem;
  padding:.22rem .6rem;
  letter-spacing:2px;
  text-transform:uppercase;
  border:1px solid #ff4da6;
  text-shadow:0 0 8px #ff4da6;
  z-index:10;
  pointer-events:none;
}

/* "See the full portfolio elsewhere" callout, filled in by rArtCTA() in script.js (which pulls the actual URLs from SOCIAL_LINKS so they're only ever edited in one place)
Sits between the section divider and the filter buttons — reuses the same outlined-panel language as the About page's The Vitrinepanel, just in the Art page's own indigo/gold palette instead of introducing a new look */
.art-cta {
  width:100%;
  max-width:900px;
  margin:0 auto 1.6rem;
  padding:.75rem 1.1rem;
  border:1px solid var(--indb);
  background:linear-gradient(135deg,rgba(75,0,130,.15),rgba(102,16,242,.07));
  font-size:.8rem;
  color:var(--off);
  line-height:1.7;
  text-align:center;
}

.art-cta a {
  color:var(--indc);
  font-family:var(--D);
  letter-spacing:1px;
  text-decoration:none;
  border-bottom:1px solid var(--indb);
  padding-bottom:1px;
  transition:all .2s;
}

.art-cta a:hover {
  color:#fff;
  border-color:var(--indc);
  text-shadow:0 0 10px var(--indc);
}

/* ============================================================
   --- CODE ---
============================================================ */

#programming { 
  background:linear-gradient(180deg,var(--blk),#05050f); 
}

.pg {
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
  gap:1rem;
}

.pc {
  background:var(--g2);
  border:1px solid #252530;
  overflow:hidden;
  transition:all .3s;
  position:relative;
  display:flex;
  flex-direction:column;
}

.pc::before {
  content:'';
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:2px;
  background:linear-gradient(90deg,transparent,var(--indb),var(--pur),var(--indb),transparent);
  opacity:0;
  transition:opacity .3s;
}

.pc:hover {
  border-color:var(--indb);
  box-shadow:0 0 22px rgba(75,0,130,.4);
}

.pc:hover::before { 
  opacity:.7; 
}

.pc-body {
  padding:1.2rem;
  flex:1;
}

.pc-foot {
  padding:.65rem 1.2rem;
  background:linear-gradient(135deg,rgba(75,0,130,.18),rgba(102,16,242,.1),rgba(57,255,90,.05));
  border-top:2px solid rgba(102,16,242,.3);
  flex-shrink:0;
}

.pc-title {
  font-family:var(--D);
  font-size:.88rem;
  color:var(--indc);
  margin-bottom:.45rem;
  letter-spacing:2px;
}

.pc-desc {
  font-size:.78rem;
  color:var(--off);
  line-height:1.6;
  margin-bottom:.9rem;
}

.tts {
  display:flex;
  gap:.4rem;
  flex-wrap:wrap;
}

.tt2 {
  font-size:.68rem;
  padding:.22rem .5rem;
  border:1px solid var(--gd);
  color:var(--grn);
  letter-spacing:1px;
  background:rgba(57,255,90,.05);
  font-family:var(--M);
  font-weight:600;
}

.plinks {
  display:flex;
  gap:.8rem;
  flex-wrap:wrap;
  align-items:center;
}

.pl {
  font-size:.72rem;
  color:var(--org);
  text-decoration:none;
  letter-spacing:1px;
  border-bottom:1px solid var(--od);
  padding-bottom:1px;
  transition:all .2s;
  font-family:var(--D);
}

.pl:hover {
  color:var(--wht);
  border-color:var(--wht);
}

/* "More Info ↭" button — opens the Project Info Modal (see openProjectModal() in script.js) with the full description plus a button for every link that project has: GitHub, Steam, itch.io, Pastebin, a related blog post, a live demo, and/or custom "other" links
Sits alongside the quick GitHub/Live Demo text links above; margin-left:auto pushes it to the right end of the row when there's room, and lets it wrap to its own line on narrow cards otherwise */
.pl-more {
  font-family:var(--D);
  font-size:.68rem;
  letter-spacing:1.5px;
  text-transform:uppercase;
  padding:.32rem .75rem;
  border:1px solid var(--indb);
  color:var(--indc);
  background:rgba(102,16,242,.08);
  cursor:pointer;
  transition:all .2s;
  margin-left:auto;
}

.pl-more:hover {
  background:var(--indb);
  color:#fff;
  box-shadow:0 0 12px rgba(75,0,130,.5);
}

/* ============================================================
   --- BLOG ---
============================================================ */

#blog { 
  background:var(--blk); 
}

.bg {
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
  gap:1rem;
}

.bc2 {
  background:var(--g2);
  border:1px solid #252530;
  overflow:hidden;
  transition:all .3s;
  cursor:pointer;
  position:relative;
  display:flex;
  flex-direction:column;
}

.bc2::before {
  content:'';
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:2px;
  background:linear-gradient(90deg,transparent,var(--yel),var(--pnk),var(--yel),transparent);
  opacity:0;
  transition:opacity .3s;
}

.bc2:hover {
  border-color:var(--pnk);
  box-shadow:0 0 22px #ff4da622;
}

.bc2:hover::before {
  opacity:.5; 
}

.bch {
  padding:.42rem .9rem;
  font-size:.68rem;
  letter-spacing:2px;
  text-transform:uppercase;
  font-family:var(--D);
  flex-shrink:0;
}

.cg {
  background:#0d0018;
  color:var(--indc);
  border-bottom:2px solid var(--indb);
}

.ca {
  background:#12000a;
  color:var(--pnk);
  border-bottom:2px solid var(--pnk);
}

.cv {
  background:#001208;
  color:var(--grn);
  border-bottom:2px solid var(--grn);
}

.cu {
  background:#120600;
  color:var(--org);
  border-bottom:2px solid var(--org);
}

.bcb {
  padding:.9rem;
  flex:1;
}

.bcf {
  padding:.55rem .9rem;
  background:linear-gradient(135deg,rgba(255,77,166,.1),rgba(75,0,130,.12),rgba(255,106,0,.06));
  border-top:2px solid rgba(255,215,0,.18);
  font-size:.68rem;
  color:var(--off);
  display:flex;
  justify-content:space-between;
  font-weight:600;
  flex-shrink:0;
}

.brm {
  color:var(--org);
  letter-spacing:1px;
  font-family:var(--D);
}

.bc2-title {
  font-family:var(--D);
  font-size:.88rem;
  color:var(--wht);
  margin-bottom:.28rem;
  line-height:1.4;
  letter-spacing:1px;
}

.bc2-date {
  font-size:.72rem;
  color:var(--off);
  margin-bottom:.4rem;
  font-weight:600;
}

.bc2-ex {
  font-size:.75rem;
  color:#9a8a90;
  line-height:1.6;
}

.bc2-thumb {
  width:100%;
  aspect-ratio:16/7;
  overflow:hidden;
  background:#0a0010;
  flex-shrink:0;
}

.bc2-thumb img {
  width:100%;
  height:100%;
  object-fit:cover;
  opacity:.85;
}

/* ============================================================
   --- BLOG POSTS ---
============================================================ */

#blog-post { background:var(--blk); }

.pb {
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  color:var(--org);
  font-size:.78rem;
  cursor:pointer;
  border:1px solid var(--od);
  padding:.3rem .85rem;
  margin-bottom:1.8rem;
  transition:all .2s;
  letter-spacing:1px;
  font-family:var(--D);
}

.pb:hover {
  background:var(--org);
  color:var(--blk);
}

.pt {
  font-family:var(--D);
  font-size:1.4rem;
  color:var(--org);
  margin-bottom:.45rem;
  line-height:1.3;
  text-shadow:0 0 15px var(--od);
  letter-spacing:3px;
}

.pm {
  font-size:.72rem;
  color:var(--off);
  margin-bottom:1.8rem;
  display:flex;
  gap:1rem;
  font-weight:600;
}

/* Everything below styles the HTML that parseBody() (see script.js, right above openPost()) generates from a post's bracket-tag body markup
headings, paragraphs, bold/italic, quotes, lists, the divider and inline links all get a look here that matches the rest of the site instead of falling back to plain browser defaults

.pbw is centered on its own (max-width + auto margins) rather than as part of a shared wrapper with the title/meta above it —
the back link, category badge, title and meta line stay left-aligned with the rest of the site's layout, and only the body copy reads as a centered column, so it doesn't drift out from under a left-aligned title on wide screens */
.pbw {
  max-width:720px;
  margin:0 auto;
}

.pbw p {
  font-size:.86rem;
  line-height:1.9;
  color:var(--off);
  margin-bottom:1.1rem;
}

.pbw strong {
  color:#fff;
  font-weight:700;
}

.pbw em {
  color:var(--indc);
  font-style:italic;
}

.pbw a {
  color:var(--indc);
  text-decoration:none;
  border-bottom:1px solid var(--indb);
  transition:all .2s;
}

.pbw a:hover {
  color:#fff;
  border-color:var(--indc);
  text-shadow:0 0 8px var(--indc);
}

/* [h2] — large section heading within a post; same bright gradient-text treatment as the page-level .st titles, just sized down to fit inline with body copy instead of a whole section top */
.pbw h2.pb-h2 {
  font-family:var(--D);
  font-size:1.25rem;
  letter-spacing:3px;
  text-transform:uppercase;
  margin:1.8rem 0 .6rem;
  background:linear-gradient(90deg,#fff,#ffe0c0 45%,var(--org));
  background-clip:text;
  -webkit-background-clip:text;
  -webkit-text-fill-color:transparent;
  text-shadow:0 0 20px rgba(255,106,0,.3);
}

/* [h3] — medium subheading, solid glowing orange */
.pbw h3.pb-h3 {
  font-family:var(--D);
  color:var(--org);
  font-size:1.05rem;
  margin:1.5rem 0 .5rem;
  letter-spacing:2px;
  text-shadow:0 0 10px rgba(255,106,0,.3);
}
 
/* [h4] — small label-style heading, indigo, uppercase — same register as the About page's "◆ Skills"/"◆ Interests" labels */
.pbw h4.pb-h4 {
  font-family:var(--D);
  color:var(--indc);
  font-size:.8rem;
  letter-spacing:3px;
  text-transform:uppercase;
  margin:1.3rem 0 .4rem;
  text-shadow:0 0 8px rgba(102,16,242,.4);
}

/* [quote]...[/quote] — pull-quote block */
.pbw blockquote.pb-quote {
  margin:1.4rem 0;
  padding:.85rem 1.3rem;
  border-left:3px solid var(--org);
  background:linear-gradient(135deg,rgba(255,106,0,.07),rgba(75,0,130,.06));
  color:var(--wht);
  font-size:.92rem;
  font-style:italic;
  line-height:1.85;
}

/* [list][li]...[/li][/list] — bulleted list, ⚡ bullets instead of the browser's default disc so it stays on-theme */
.pbw ul.pb-list {
  list-style:none;
  margin:1rem 0 1.3rem;
  padding-left:0;
}

.pbw ul.pb-list li {
  position:relative;
  padding-left:1.5rem;
  margin-bottom:.55rem;
  font-size:.86rem;
  line-height:1.75;
  color:var(--off);
}

.pbw ul.pb-list li::before {
  content:'⚡';
  position:absolute;
  left:0;
  top:0;
  color:var(--yel);
  font-size:.68rem;
}

/* [hr] renders as a real .drule — the same "◆ · · · ◆" divider used to separate sections everywhere else on the site — so a post's own internal section breaks look identical to the site's, not a separate one-off rule invented just for blog posts */
.pbw .drule {
  margin:1.8rem 0;
}

.pbw img {
  max-width:100%;
  border:1px solid rgba(255,106,0,.25);
  margin:1.2rem 0;
  box-shadow:0 0 24px rgba(255,106,0,.12);
}

/* ============================================================
   --- SHOP ---
============================================================ */

#shop {
  background:linear-gradient(180deg,var(--blk),#0a0005); 
}

.sg {
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(220px,1fr));
  gap:1rem;
}

.sc {
  background:var(--g2);
  border:1px solid #252530;
  transition:all .3s;
  overflow:hidden;
  position:relative;
  display:flex;
  flex-direction:column;
}

.sc::before {
  content:'';
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:2px;
  background:linear-gradient(90deg,transparent,var(--yel),var(--org),var(--yel),transparent);
  opacity:0;
  transition:opacity .3s;
}

.sc:hover {
  border-color:var(--pnk);
  box-shadow:0 0 22px #ff4da622;
}

.sc:hover::before {
  opacity:.5; 
}

/* Product thumbnail
Like .ac-img on the Art page, clicking it (when it holds a real photo, not just the emoji placeholder — rShop() adds the "has-img" class in that case, see script.js) opens the full-size lightbox — 
wired up via a delegated click listener on #shop-grid in script.js so it doesn't interfere with the buy/order buttons underneath */
.sc-img {
  width:100%;
  aspect-ratio:1;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:2.8rem;
  position:relative;
  overflow:hidden;
}

.sc-img.has-img {
  cursor:pointer;
}

.sc-img img {
  width:100%;
  height:100%;
  object-fit:cover;
}

/* Same hover hint as .ac-expand on the Art page */
.sc-expand {
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:.4rem;
  background:rgba(5,5,8,.55);
  color:var(--wht);
  font-family:var(--D);
  font-size:.62rem;
  letter-spacing:1.5px;
  text-transform:uppercase;
  text-align:center;
  opacity:0;
  transition:opacity .25s;
  pointer-events:none;
  z-index:2;
}

.sc-img.has-img:hover .sc-expand {
  opacity:1;
}

.sc-img::before {
  content:'';
  position:absolute;
  inset:0;
  background:linear-gradient(135deg,rgba(75,0,130,.12),rgba(102,16,242,.1),rgba(57,255,90,.06));
  animation:holo 3s ease infinite alternate;
  z-index:1;
}

@keyframes holo {
  0% {
    opacity:0;
  }
  100% {
    opacity:1;
  }
}

.sa {
  background:linear-gradient(135deg,#150008,#0a001a); 
}

.sc2 {
  background:linear-gradient(135deg,#001015,#000d1a); 
}

.sp {
  background:linear-gradient(135deg,#120010,#080015); 
}

.sco {
  background:linear-gradient(135deg,#100800,#180a00); 
}

.spo {
  background:linear-gradient(135deg,#001a10,#0a1500); 
}

/* ============================================================
   --- SHOP INFO PANEL ---
============================================================ */

.sc-info {
  padding:.7rem .8rem .75rem;
  background:linear-gradient(180deg,#0d0d18,#0a0a12);
  border-top:1px solid rgba(255,215,0,.35);
  position:relative;
  flex:1;
  display:flex;
  flex-direction:column;
}

.sc-info::before {
  content:'◆';
  position:absolute;
  top:-6px;
  left:50%;
  transform:translateX(-50%);
  font-size:.3rem;
  color:var(--yel);
  background:var(--g2);
  padding:0 4px;
}

.sc-title {
  font-family:var(--D);
  font-size:.88rem;
  color:var(--wht);
  margin-bottom:.15rem;
  letter-spacing:1.5px;
  text-transform:uppercase;
}

.sc-type {
  font-family:var(--D);
  font-size:.58rem;
  color:var(--indc);
  letter-spacing:2px;
  text-transform:uppercase;
  margin-bottom:.45rem;
  opacity:.8;
}

.sc-price {
  font-family:var(--D);
  font-size:1.05rem;
  margin-bottom:.6rem;
  background:linear-gradient(90deg,#fff,var(--org),#ffaa00);
  background-clip:text;
  -webkit-background-clip:text;
  -webkit-text-fill-color:transparent;
  letter-spacing:2px;
}

.sc-btns {
  display:flex;
  flex-direction:column;
  gap:.35rem;
  margin-top:auto;
}

.sbn {
  width:100%;
  padding:.4rem;
  font-family:var(--D);
  font-size:.65rem;
  letter-spacing:2px;
  text-transform:uppercase;
  background:rgba(255,106,0,.1);
  border:1px solid var(--org);
  color:var(--org);
  cursor:pointer;
  transition:all .2s;
  text-decoration:none;
  display:block;
  text-align:center;
}

.sbn:hover {
  background:var(--org);
  color:var(--blk);
}

/* The "Request/Order" button on a shop listing, swapped in by rShop() (script.js) in place of the normal .sbn button when SITE_SETTINGS.commissionsOpen is false — muted/greyed instead of the usual orange, and inert */
.sbn-closed,
.sbn-closed:hover {
  background:rgba(255,255,255,.03);
  border-color:#555;
  color:#777;
  cursor:not-allowed;
}

.sbn-etsy {
  border-color:#f1641e;
  color:#f1641e;
  background:rgba(241,100,30,.08);
}

.sbn-etsy:hover {
  background:#f1641e;
  color:#fff;
}

.sbn-gumroad {
  border-color:#36a9ae;
  color:#36a9ae;
  background:rgba(54,169,174,.08);
}

.sbn-gumroad:hover {
  background:#36a9ae;
  color:#fff;
}

.sbn-inprnt {
  border-color:var(--indc);
  color:var(--indc);
  background:rgba(102,16,242,.08);
}

.sbn-inprnt:hover {
  background:var(--indb);
  color:#fff;
}

.cs {
  display:inline-flex;
  align-items:center;
  gap:.55rem;
  padding:.38rem 1.1rem;
  margin-bottom:1.8rem;
  background:rgba(57,255,90,.04);
  border:1px solid var(--grn);
  color:var(--grn);
  font-size:.75rem;
  letter-spacing:2px;
  font-family:var(--M);
  font-weight:600;
}

/* Commissions-closed state — toggled by init() (script.js) reading SITE_SETTINGS.commissionsOpen; swaps the whole pill from the default green "open" look to a muted red so it reads as closed at a glance, dot included */
.cs.closed {
  background:rgba(255,68,68,.05);
  border-color:#f44;
  color:#f44;
}

.sdot {
  width:7px;
  height:7px;
  border-radius:50%;
  background:var(--grn);
  animation:pls 1.5s infinite;
}

.cs.closed .sdot {
  background:#f44;
  animation:none;
  opacity:.7;
}

@keyframes pls {
  0%,100% {
    opacity:1;
  }
  50% {
    opacity:.3;
  }
}

/* ============================================================
   --- SHOP PAYMENT ---
============================================================ */

.prow {
  display:flex;
  gap:.5rem;
  flex-wrap:wrap;
  margin-top:1.3rem;
}

.pb2 {
  padding:.38rem .8rem;
  font-size:.68rem;
  font-family:var(--M);
  font-weight:600;
  cursor:pointer;
  transition:all .2s;
  text-decoration:none;
  display:inline-flex;
  align-items:center;
  gap:.35rem;
  letter-spacing:1px;
}

.pk {
  background:#29abe0;
  border:1px solid #29abe0;
  color:#fff;
}

.pbmc {
  background:#ff813f;
  border:1px solid #ff813f;
  color:#fff;
}

.ppp {
  background:#003087;
  border:1px solid #009cde;
  color:#fff;
}

.pst {
  background:#6772e5;
  border:1px solid #6772e5;
  color:#fff;
}

.psq {
  background:#28c840;
  border:1px solid #28c840;
  color:#000;
}

.pb2:hover {
  filter:brightness(1.2);
  transform:translateY(-1px);
}

/* ============================================================
   --- MODAL ---
   ------------------------------------------------------------
   Full-screen dark backdrop (.mo, "modal overlay") with a centered content box (.md, "modal dialog") inside it.
   Hidden by default (display:none) and only shown once JS adds the "open" class — see om()/cm() in script.js. The same open/close pattern is reused for the image lightbox just below.
============================================================ */

.mo {
  position:fixed;
  inset:0;
  background:rgba(0,0,0,.88);
  z-index:500;
  display:none;
  align-items:center;
  justify-content:center;
  padding:1rem;
}

.mo.open {
   display:flex;
}

.md {
  background:var(--g2);
  border:1px solid var(--org);
  max-width:560px;
  width:100%;
  max-height:90vh;
  overflow-y:auto;
}

.md::before {
  content:'';
  display:block;
  height:2px;
  background:linear-gradient(90deg,transparent,var(--yel),var(--org),var(--yel),transparent);
}

.mdh {
  padding:.9rem 1.1rem;
  background:linear-gradient(135deg,rgba(255,106,0,.13),rgba(75,0,130,.1));
  border-bottom:1px solid rgba(255,215,0,.13);
  display:flex;
  justify-content:space-between;
  align-items:center;
}

.mdt {
  font-family:var(--D);
  font-size:.92rem;
  color:var(--org);
  letter-spacing:3px;
}

.mdc {
  background:none;
  border:none;
  color:var(--off);
  font-size:1.2rem;
  cursor:pointer;
}

.mdc:hover {
   color:var(--org);
}

.mdb { 
  padding:1.3rem; 
}

.fg { 
  margin-bottom:.9rem; 
}

.fl {
  display:block;
  font-size:.72rem;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--off);
  margin-bottom:.3rem;
  font-family:var(--M);
  font-weight:700;
}

.fi,
.fta,
.fsl {
  width:100%;
  background:#0a0a12;
  border:1px solid #2a2a3a;
  color:var(--wht);
  font-family:var(--M);
  font-size:.82rem;
  font-weight:500;
  padding:.45rem .62rem;
  transition:border-color .2s;
}

.fi:focus,
.fta:focus,
.fsl:focus {
  outline:none;
  border-color:var(--indb);
  box-shadow:0 0 8px rgba(102,16,242,.3);
}

.fta {
  resize:vertical;
  min-height:78px;
}

.frow {
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:.75rem;
}

.fsub {
  width:100%;
  padding:.62rem;
  font-family:var(--D);
  font-size:.82rem;
  letter-spacing:3px;
  background:var(--org);
  border:none;
  color:var(--blk);
  cursor:pointer;
  transition:all .2s;
  margin-top:.45rem;
}

.fsub:hover {
  background:#ffaa00;
  box-shadow:0 0 20px var(--og);
}

.fsub:disabled,
.fsub:disabled:hover {
  background:#555;
  color:#999;
  cursor:not-allowed;
  box-shadow:none;
}

.fn {
  font-size:.72rem;
  color:var(--off);
  margin-top:.45rem;
  opacity:.85;
}

/* Order-submission result text — swapped in on top of/instead of the default .fn note once submitOrder() (script.js) succeeds or fails */
.fn-ok {
  color:var(--grn);
  opacity:1;
}

.fn-err {
  color:#ff6a6a;
  opacity:1;
}

/* ============================================================
   --- MODAL : MODE CHOICE ---
   ------------------------------------------------------------
   Shown instead of the form when a shop item's order.mode is 'choice' (see om() in script.js) — two stacked buttons offering "go to an external site" vs "fill out the custom form here", styled as alternates of each other so neither option visually outranks the other.
============================================================ */

.choice-row {
  display:flex;
  flex-direction:column;
  gap:.7rem;
  margin-top:.2rem;
}

.choice-btn {
  width:100%;
  padding:.85rem 1rem;
  font-family:var(--D);
  font-size:.78rem;
  letter-spacing:2px;
  text-transform:uppercase;
  background:rgba(102,16,242,.08);
  border:1px solid var(--indb);
  color:var(--indc);
  cursor:pointer;
  transition:all .2s;
  text-align:center;
  text-decoration:none;
  display:block;
}

.choice-btn:hover {
  background:var(--indb);
  color:#fff;
  box-shadow:0 0 16px rgba(102,16,242,.4);
}

.choice-btn.cb-alt {
  background:rgba(255,106,0,.08);
  border-color:var(--org);
  color:var(--org);
}

.choice-btn.cb-alt:hover {
  background:var(--org);
  color:var(--blk);
  box-shadow:0 0 16px var(--og);
}

/* ============================================================
   --- IMAGE LIGHTBOX ---
   ------------------------------------------------------------
   Full-size image viewer, opened by clicking any gallery/shop thumbnail that has a real photo (see openLightbox() in script.js)
   Same fixed-overlay pattern as .mo/.md above, just simplified: no dialog box, the image itself IS the content, sized to fit the screen with object-fit-style containment (max-width/max-height + auto margins) so it never gets cropped or overflows on any device.
============================================================ */

.lb {
  position:fixed;
  inset:0;
  z-index:600; /* above .mo (500) so a lightbox opened from inside a modal — e.g. a reference image — still wins */
  background:rgba(0,0,0,.94);
  display:none;
  align-items:center;
  justify-content:center;
  padding:2rem 1rem;
}

.lb.open {
  display:flex;
  flex-direction:column;
}

.lb-img {
  max-width:min(92vw,1100px);
  max-height:80vh;
  width:auto;
  height:auto;
  object-fit:contain;
  border:1px solid var(--org);
  box-shadow:0 0 40px rgba(255,106,0,.25);
}

.lb-cap {
  margin-top:1rem;
  font-family:var(--D);
  font-size:.95rem;
  letter-spacing:2px;
  text-align:center;
  max-width:92vw;
  color:var(--org);
  text-shadow:0 0 10px var(--org),0 0 26px var(--od),0 0 46px rgba(255,106,0,.35);
}

.lb-desc {
  margin-top:.5rem;
  font-family:var(--M);
  font-weight:600;
  font-size:.82rem;
  letter-spacing:.5px;
  line-height:1.75;
  text-align:center;
  max-width:600px;
  color:var(--indc);
  text-shadow:0 0 8px var(--indc),0 0 22px var(--indb),0 0 40px rgba(102,16,242,.3);
}

.lb-close {
  position:fixed;
  top:1.1rem;
  right:1.2rem;
  width:42px;
  height:42px;
  background:rgba(5,5,8,.85);
  border:1px solid var(--org);
  color:var(--wht);
  font-size:1.2rem;
  cursor:pointer;
  transition:all .2s;
  z-index:601;
}

.lb-close:hover {
  background:var(--org);
  color:var(--blk);
  box-shadow:0 0 16px var(--og);
}

/* ============================================================
   --- MODAL : PROJECT INFO ---
   ------------------------------------------------------------
   Reuses the .mo/.md overlay+dialog pattern from the order modal above
   #pmTech/#pmDesc are plain text; #pmLinks is the row of per-platform buttons built by openProjectModal() in script.js
============================================================ */

.pm-desc {
  font-size:.86rem;
  line-height:1.85;
  color:var(--off);
  margin-bottom:1.4rem;
}

.plinkrow {
  display:flex;
  flex-wrap:wrap;
  gap:.55rem;
}

/* Base look shared by every link button; each platform below only overrides the border/text color and (on hover) the fill, the same "outlined until hovered" treatment used by the shop's storefront buttons (.sbn-etsy etc.) and the payment buttons in the order modal */
.plink {
  display:inline-flex;
  align-items:center;
  gap:.4rem;
  padding:.42rem .9rem;
  font-family:var(--D);
  font-size:.72rem;
  letter-spacing:1.5px;
  text-transform:uppercase;
  text-decoration:none;
  border:1px solid;
  transition:all .2s;
  background:rgba(255,255,255,.02);
}

.plink:hover {
  color:var(--blk)!important;
  box-shadow:0 0 14px currentColor;
}

.plink-gh {
  border-color:#e8e0d0;
  color:#e8e0d0;
}

.plink-gh:hover {
  background:#e8e0d0;
}

.plink-live {
  border-color:var(--tel);
  color:var(--tel);
}

.plink-live:hover {
  background:var(--tel);
}

.plink-steam {
  border-color:#66c0f4;
  color:#66c0f4;
}

.plink-steam:hover {
  background:#66c0f4;
}

.plink-itch {
  border-color:#fa5c5c;
  color:#fa5c5c;
}

.plink-itch:hover {
  background:#fa5c5c;
}

.plink-pastebin {
  border-color:#02a7e1;
  color:#02a7e1;
}

.plink-pastebin:hover {
  background:#02a7e1;
}

.plink-blog {
  border-color:var(--pnk);
  color:var(--pnk);
}

.plink-blog:hover {
  background:var(--pnk);
}

.plink-other {
  border-color:var(--indc);
  color:var(--indc);
}

.plink-other:hover {
  background:var(--indb);
  border-color:var(--indb);
}

/* ============================================================
   --- ABOUT ---
============================================================ */

#about {
  background:linear-gradient(180deg,var(--blk),#05000a);
  display:flex;
  flex-direction:column;
  align-items:center;
}

#about .st,
#about .sdiv {
  width:100%;
  max-width:900px;
}

/* Photo + name sit to the left, bio/skills to the right, side by side, on anything roomy enough (tablet and up)
On phones this row layout gets switched to a stacked column instead — see the RESPONSIVE section near the end of this file */
.abg {
  display:flex;
  flex-direction:row;
  align-items:center;
  max-width:860px;
  margin:0 auto;
  width:100%;
}

.abg-header {
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
  margin-bottom:1.8rem;
  margin-right: 4%;
}

.abg-body {
  width:100%;
}

/* ============================================================
   --- ABOUT DECO SPHERE : PHOTO ---
   ------------------------------------------------------------
   200px fixed circular frame around the profile photo (or the SVG placeholder sphere when no photo is set — see ABOUT_INFO.photo in script.js)
   Shrunk down for small screens in the RESPONSIVE section so it never crowds out the text next to/below it
============================================================ */

.aph {
  position:relative;
  width:200px;
  height:200px;
  flex-shrink:0;
  display:grid;
  margin-bottom:1.1rem;
}

.aph img {
  position:absolute;
  inset:5.25%;
  width:89.5%;
  height:89.5%;
  object-fit:cover;
  border-radius:50%;
  z-index:2;
}

.aph-bg,
.aph-fg {
  grid-area:1/1;
  width:200px;
  height:200px;
}

.aph-bg { 
  z-index:1; 
}

.aph-fg {
  z-index:3;
  pointer-events:none;
}

.an {
  font-family:var(--D);
  font-size:1.25rem;
  color:var(--org);
  margin-bottom:.28rem;
  text-shadow:0 0 15px var(--od);
  letter-spacing:4px;
  text-align:center;
}

.ah {
  font-size:.85rem;
  color:var(--pnk);
  margin-bottom:.6rem;
  letter-spacing:3px;
  font-family:var(--M);
  font-weight:700;
  text-align:center;
}

.abio {
  font-size:.86rem;
  line-height:1.9;
  color:var(--off);
  margin-bottom:1.4rem;
}

.asl {
  font-family:var(--D);
  font-size:.88rem;
  font-weight:700;
  color:var(--indc);
  letter-spacing:3px;
  margin-bottom:.65rem;
  text-transform:uppercase;
  text-shadow:0 0 12px rgba(102,16,242,.5);
  -webkit-text-stroke:.5px var(--indb);
}

.skgs {
  display:flex;
  flex-wrap:wrap;
  gap:.38rem;
  margin-bottom:1.3rem;
}

.skt {
  padding:.25rem .7rem;
  font-size:.72rem;
  border:1px solid var(--indb);
  color:var(--indc);
  letter-spacing:1px;
  background:rgba(75,0,130,.08);
  font-family:var(--M);
  font-weight:600;
}

.int {
  font-size:.84rem;
  color:var(--off);
  line-height:2.1;
}

/* ============================================================
   --- THE VITRINE PANEL ---
============================================================ */

.tl-panel {
  margin-top:1.5rem;
  padding:1rem 1.2rem;
  border:1px solid var(--indb);
  background:linear-gradient(135deg,rgba(75,0,130,.15),rgba(102,16,242,.08));
  position:relative;
}

.tl-panel::before {
  content:'';
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:2px;
  background:linear-gradient(90deg,transparent,var(--indb),var(--pur),var(--indb),transparent);
}

.tl-title {
  font-family:var(--D);
  font-size:.78rem;
  color:var(--indc);
  letter-spacing:3px;
  margin-bottom:.35rem;
  text-transform:uppercase;
}

.tl-desc {
  font-size:.74rem;
  color:var(--off);
  margin-bottom:.7rem;
  line-height:1.6;
}

.tl-btn {
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  padding:.38rem 1rem;
  font-family:var(--D);
  font-size:.68rem;
  letter-spacing:2px;
  text-transform:uppercase;
  border:1px solid var(--indc);
  color:var(--indc);
  text-decoration:none;
  transition:all .2s;
  background:rgba(102,16,242,.1);
}

.tl-btn:hover {
  background:var(--indb);
  color:#fff;
  box-shadow:0 0 14px rgba(75,0,130,.5);
}

footer {
  position:relative;
  z-index:1;
  padding:1.4rem 2rem;
  border-top:1px solid rgba(255,215,0,.08);
  text-align:center;
  font-family:var(--D);
  font-size:.68rem;
  color:#666;
  letter-spacing:4px;
}

footer::before {
  content:'';
  display:block;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--yel),var(--org),var(--yel),transparent);
  opacity:.18;
  margin-bottom:.9rem;
}

#particles {
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  pointer-events:none;
  z-index:0;
}

::-webkit-scrollbar { 
  width:3px; 
}

::-webkit-scrollbar-track { 
  background:var(--blk); 
}

::-webkit-scrollbar-thumb {
  background:var(--indb);
}

/* ============================================================
   RESPONSIVE / MOBILE
   ------------------------------------------------------------
   Everything above this point is written "desktop-first" — it looks right on a wide screen and mostly holds up reasonably well down to tablet width already (grids use auto-fill/minmax, the hero title uses clamp(), etc.)
   The rules in this section are the exceptions: places where fixed pixel sizes, side-by-side layouts, or generous letter-spacing stop fitting comfortably as the screen narrows

   Because these rules are declared LAST in the file, normal CSS cascade order means they automatically win over the desktop rules above whenever their @media condition matches — nothing above needs to change or "know about" these overrides

   Three breakpoints, narrowing progressively:
     900px  — small laptop / tablet landscape
     640px  — large phone / tablet portrait
     420px  — small phone
============================================================ */

/* ---------- ≤900px : tablets & small laptops ---------- */
@media (max-width: 900px) {
  /* Section side padding was tuned for a wide desktop viewport; shrink it so content doesn't feel squeezed against the edges */
  section {
    padding:2.4rem 1.4rem 3rem;
  }

  /* Stack the About page's photo+name column above the bio instead of beside it — side-by-side stops having room once the bio text column would otherwise get squeezed under ~300px wide */
  .abg {
    flex-direction:column;
  }

  .abg-header {
    margin-right:0;
  }
 
  /* Gallery/shop/code/blog grids: allow narrower columns than the desktop minimum so 2 columns keep fitting instead of collapsing straight to 1 the moment the viewport drops below ~900px */
  .gg,
  .sg {
    grid-template-columns:repeat(auto-fill,minmax(165px,1fr));
  }

  .pg,
  .bg {
    grid-template-columns:repeat(auto-fill,minmax(230px,1fr));
  }
}

/* ---------- ≤640px : phones ---------- */
@media (max-width: 640px) {
  section {
    padding:2rem 1.1rem 2.6rem;
  }

  /* --- Nav: let tabs wrap onto a second line instead of relying on horizontal scrolling, and shrink them so more fit per line --- */
  .ntr {
    flex-wrap:wrap;
    padding:.3rem .5rem .3rem;
  }

  .nt {
    padding:.3rem .7rem;
    font-size:.64rem;
  }

  .lsw-btn {
    padding:.3rem .7rem;
    font-size:.64rem;
  }

  /* .lsw-menu's position is computed inline by js/i18n.js on open (see the LANGUAGE SWITCHER
     section above) and already keeps it on-screen on narrow widths, so no override is needed here. */

  .nlt {
    font-size:1.1rem;
    letter-spacing:5px;
  }

  .nlt::before,
  .nlt::after {
    letter-spacing:5px;
  }

  .lzap {
    font-size:.5rem;
    letter-spacing:3px;
  }

  .ticker-inner {
    font-size:.62rem;
    letter-spacing:1px;
  }

  /* Home hero: tighten letter-spacing so the title/tagline don't force horizontal overflow on narrow phones, and let the subtitle use the full width instead of a fixed max-width */
  .htitle {
    letter-spacing:4px;
  }

  .htitle::before,
  .htitle::after {
    letter-spacing:4px;
  }

  .hst {
    letter-spacing:4px;
    font-size:.8rem;
  }

  .hey {
    letter-spacing:3px;
  }

  .hsub {
    max-width:100%;
  }

  .htags {
    gap:.35rem;
  }

  .tag {
    font-size:.6rem;
    padding:.22rem .6rem;
  }

  /* Syringe: centered horizontally instead of pinned to the left edge, where it's mostly clipped off-screen on a narrow phone (see .sdeco-syringe's desktop position above) */
  .sdeco-syringe {
    left:50%;
    transform:translateX(-50%);
  }

  /* Tombstones: shrink so 3-4 fit per row on a phone instead of 2, and tighten the gap between them */
  .tsrow {
    gap:.7rem;
  }

  .ts {
    width:72px;
    height:112px;
  }

  .ts-name {
    font-size:.5rem;
  }

  /* Section titles a touch smaller so they don't wrap awkwardly */
  .st {
    font-size:1.25rem;
    letter-spacing:3px;
  }

  /* Gallery/shop/code/blog grids: one comfortable column on most phones, still allowing two if the screen is wide enough */
  .gg,
  .sg {
    grid-template-columns:repeat(auto-fill,minmax(135px,1fr));
    gap:.7rem;
  }

  .pg,
  .bg {
    grid-template-columns:1fr;
  }

  /* About: shrink the photo sphere so it doesn't dominate a narrow screen; both the background/foreground SVG layers and the photo itself are sized off this same box */
  .aph,
  .aph-bg,
  .aph-fg {
    width:150px;
    height:150px;
  }

  /* Anatomical heart: flip from the left edge to the right edge — on a phone the About column is centered full-width (see .abg above), so the left-pinned desktop position (.sdeco-heart) sits right behind/under
     the bio text instead of reading as a corner accent. Moving it to the opposite corner keeps it clear of the centered text column. */
  .sdeco-heart {
    left:auto;
    right:2%;
  }

  /* Modal / order form: two-column rows (Name+Email, Budget+ Deadline) don't have room side by side on a phone — stack them */
  .frow {
    grid-template-columns:1fr;
    gap:0;
  }

  .md {
    max-width:100%;
  }

  .mdb {
    padding:1rem;
  }

  /* Lightbox: smaller close button, image sized to leave room for the caption without needing to scroll */
  .lb-close {
    top:.7rem;
    right:.7rem;
    width:36px;
    height:36px;
    font-size:1rem;
  }

  .lb-img {
    max-height:70vh;
  }

  footer {
    padding:1.1rem 1rem;
    font-size:.6rem;
    letter-spacing:2px;
  }
}

/* ---------- ≤420px : small phones ---------- */
@media (max-width: 420px) {
  .nlt {
    font-size:.95rem;
    letter-spacing:3px;
  }

  .nlt::before,
  .nlt::after {
    letter-spacing:3px;
  }

  .htitle {
    letter-spacing:2px;
  }

  .htitle::before,
  .htitle::after {
    letter-spacing:2px;
  }

  .ts {
    width:64px;
    height:100px;
  }

  .gg,
  .sg {
    grid-template-columns:repeat(auto-fill,minmax(115px,1fr));
  }

  .aph,
  .aph-bg,
  .aph-fg {
    width:120px;
    height:120px;
  }
}

/* ---------- short viewports (landscape phones, small-height windows) ----------
   #home centers its content vertically with justify-content:center, which looks great as long as the hero (title + tagline + tags + tombstone row) is shorter than the viewport
   On a short/wide viewport — a phone in landscape, or just a short browser window — that content can be taller than the available height, and a centered overflow expands equally in both directions,
   pushing the top of the hero up behind the fixed ticker/nav instead of simply scrolling into view below them
   Switching to flex-start (plus a little top padding) here means short viewports get a normal top-anchored, scrollable page instead of that overlap

   900px (not 700px) is the real threshold: #home now sizes itself to 100vh minus the fixed nav/ticker AND the footer (see the #home rule above), so the hero has noticeably less
   room to work with than a flat 100vh would suggest — real content stops fitting without scrolling somewhere around ~860-870px of viewport height, not 700px. */

@media (max-height: 900px) {
  #home {
    justify-content:flex-start;
    padding-top:1.5rem;
  }
}