/* ============================================================
   karolisstasiunas.com — cinematic dark
   Midnight navy ground, deep indigo surfaces, electric cyan accent.
   Type: Neue Montreal (licensed, self-hosted — see the @font-face
   block below), falling back to Space Grotesk / Inter until it is.
   ============================================================ */

/* ------------------------------------------------------------------
   NEUE MONTREAL — self-hosted, activate once licensed.

   Neue Montreal is a commercial typeface (Pangram Pangram). It is not
   on Google Fonts and cannot be hot-linked. Once you hold a web licence:
     1. drop the .woff2 files into /assets/fonts/
     2. uncomment this block
   The font stacks below already name it first, so it takes over
   everywhere the moment these faces resolve. The CSP allows self-hosted
   fonts already ('self' in font-src), so nothing else changes.

@font-face{
  font-family:'Neue Montreal';
  src:url('/assets/fonts/NeueMontreal-Regular.woff2') format('woff2');
  font-weight:400;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Neue Montreal';
  src:url('/assets/fonts/NeueMontreal-Medium.woff2') format('woff2');
  font-weight:500;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Neue Montreal';
  src:url('/assets/fonts/NeueMontreal-Bold.woff2') format('woff2');
  font-weight:700;font-style:normal;font-display:swap;
}
------------------------------------------------------------------ */

:root{
  /* --- palette --- */
  --navy:      #0A0F1F;   /* Midnight Navy — the ground */
  --indigo:    #161B3D;   /* Deep Indigo — raised surfaces */
  --indigo-2:  #1E2450;   /* Deep Indigo, lifted — hover */
  --cyan:      #2FE4FF;   /* Electric Cyan — accent, used sparingly */
  --cyan-dim:  #7FEEFF;   /* Cyan, softened — hover on cyan text */
  --off-white: #F4F6FB;   /* Off White — primary text */
  --slate:     #8A94AD;   /* Slate — secondary text */
  --slate-2:   #838DA9;   /* Slate — micro labels (5.8:1 on navy) */
  --danger:    #FF7A85;   /* errors only — never the accent */

  --line:    rgba(244,246,251,.10);
  --line-2:  rgba(244,246,251,.20);
  --cyan-10: rgba(47,228,255,.10);
  --cyan-30: rgba(47,228,255,.30);

  /* --- type ---
     One family by design. Display and body are split only so the
     fallbacks can differ: Space Grotesk holds headline character,
     Inter reads better at paragraph size. Both collapse into
     Neue Montreal once it is installed. */
  --display: 'Neue Montreal', 'Space Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
  --sans:    'Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;

  --wrap: 1140px;
  --gut: 24px;
  --r: 4px;
  --header-h: 68px;
}

*,*::before,*::after{box-sizing:border-box}

html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}

body{
  margin:0;
  background:var(--navy);
  color:var(--off-white);
  font-family:var(--sans);
  font-size:17px;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

img{max-width:100%;height:auto;display:block}

a{color:var(--off-white);text-decoration:none}
a:hover{color:var(--cyan)}

:focus-visible{outline:2px solid var(--cyan);outline-offset:3px;border-radius:2px}

/* A grotesque carries authority through weight and tight tracking rather
   than through serifs, so headings run heavier and tighter than before. */
h1,h2,h3,h4{font-family:var(--display);font-weight:700;line-height:1.06;margin:0;letter-spacing:-.025em}

p{margin:0 0 1.1em}
p:last-child{margin-bottom:0}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--gut)}
.wrap-narrow{max-width:760px;margin:0 auto;padding:0 var(--gut)}

.skip{position:absolute;left:-9999px;top:0}
.skip:focus{left:12px;top:12px;z-index:200;background:var(--cyan);color:var(--navy);padding:10px 16px;border-radius:var(--r);font-weight:600}

/* ---------- utilities ----------
   Real classes rather than inline style="" attributes: the CSP deliberately
   omits 'unsafe-inline' from style-src, which blocks inline styles outright. */
.measure-lg{max-width:820px}
.measure-md{max-width:760px}
.measure-sm{max-width:640px}
.h2-section{font-size:clamp(1.9rem,4.6vw,2.9rem);margin-bottom:22px}
.mt-xl{margin-top:34px}
.mb-xl{margin-bottom:42px}
.field-btn{flex:0 0 auto;align-self:flex-end}
@media (max-width:520px){
  .field-btn{flex:1 1 100%}
  .field-btn .btn{width:100%}
}

/* ---------- micro type ---------- */
.eyebrow{
  font-family:var(--display);
  font-size:.72rem;font-weight:600;letter-spacing:.24em;text-transform:uppercase;
  color:var(--cyan);margin:0 0 18px;
}
.eyebrow-muted{color:var(--slate-2)}
.lede{font-size:1.18rem;line-height:1.7;color:#D3D8E6;letter-spacing:-.005em}
.muted{color:var(--slate)}
.small{font-size:.9rem}

/* ---------- header ---------- */
.site-header{
  position:sticky;top:0;z-index:100;
  background:rgba(10,15,31,.88);
  backdrop-filter:saturate(140%) blur(12px);
  border-bottom:1px solid var(--line);
}
.header-in{
  max-width:var(--wrap);margin:0 auto;padding:0 var(--gut);
  height:var(--header-h);display:flex;align-items:center;justify-content:space-between;gap:20px;
}
.brand{
  font-family:var(--display);font-size:1.02rem;font-weight:700;letter-spacing:-.02em;
  white-space:nowrap;
}
.brand span{color:var(--cyan)}
.nav{display:flex;align-items:center;gap:28px}
.nav a{
  font-size:.86rem;font-weight:500;letter-spacing:.01em;color:#C2C9DB;
}
.nav a:hover,.nav a[aria-current="page"]{color:var(--off-white)}
.nav a[aria-current="page"]{border-bottom:1px solid var(--cyan);padding-bottom:2px}
.nav-cta{
  font-family:var(--display);
  font-size:.78rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  border:1px solid var(--line-2);border-radius:var(--r);padding:9px 16px;color:var(--off-white)!important;
  transition:border-color .18s ease,background .18s ease;
}
.nav-cta:hover{border-color:var(--cyan);background:var(--cyan-10)}

.nav-toggle{
  display:none;background:none;border:1px solid var(--line-2);border-radius:var(--r);
  color:var(--off-white);padding:8px 12px;font-family:var(--display);font-size:.78rem;
  font-weight:600;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;
}

/* ---------- sections ---------- */
section{padding:92px 0}
.section-tight{padding:64px 0}
.rule{border:0;border-top:1px solid var(--line);margin:0}

/* ---------- morph intro (scroll-scrubbed video) ----------
   A tall track scrolled through while the stage stays pinned. Scroll
   progress drives video.currentTime in main.js, so the footage moves only
   as fast as the reader does — on any screen size. Only with
   prefers-reduced-motion does the track collapse to a single screen
   showing the poster frame; that gate lives in main.js. */
/* padding:0 overrides the global section{padding:92px 0}, which would
   otherwise band the footage with 92px of black top and bottom. */
.morph{position:relative;background:#000;padding:0}
/* 800vh, not a smaller number: this clip is 17.856s, well over half again as
   long as the one it replaced, and the pacing that already tested well
   (roughly 44vh of scroll per second of footage — see README) was carried
   forward rather than re-guessed. Less than this risks the same "blows
   through it in one flick" complaint that increasing the track height fixed
   the first time. */
.morph-track{position:relative;height:800vh}
/* The still frame lives here as a CSS background rather than on the video's
   poster attribute: a media query fetches only the size that is needed,
   where a poster swapped in by JS would download both. */
/* top/height are offset by --header-h, not a plain 0/100vh: the sticky
   header sits at z-index:100, above this section, with no z-index of its
   own. Without this offset the top ~68px of every frame renders UNDER the
   header and is invisible there — on this footage that band is exactly
   where the subject's head sits, so it read as the head being swallowed by
   the nav bar. Starting the stage below the header instead means nothing in
   the frame can ever be hidden behind it. */
.morph-stage{
  position:sticky;top:var(--header-h);height:calc(100vh - var(--header-h));overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  background-image:url('/assets/video/morph-poster.jpg');
  background-size:cover;background-position:center;background-color:#000;
}
.morph-video{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;background:transparent;
}
.morph.is-static .morph-video{display:none}
/* Bottom fade: dissolves the black footage into the navy page below, and
   doubles as the scrim the copy sits on. It has to reach up past the text
   (74%) — the cyan line lands on the cyan light-body frame otherwise, and
   cyan on cyan is unreadable. */
.morph-stage::after{
  content:"";position:absolute;inset:auto 0 0 0;height:56vh;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(10,15,31,.55) 34%,rgba(10,15,31,.88) 64%,var(--navy));
}

/* height/width:100% is not decorative — without it this box has no in-flow
   content (every .morph-line child is position:absolute, which contributes
   nothing to auto height), so its intrinsic size collapses to ~0. Every
   .morph-line's top/left percentage was then resolving against that ~0,
   i.e. every percentage value computed to the same 0px regardless of what
   number was written — the lines were only ever landing near-centre because
   .morph-stage's flexbox centring was carrying a zero-size box, not because
   the 74%/88% positioning was doing anything. This is what let the opening
   line sit across the face despite the numbers saying otherwise. */
.morph-copy{position:relative;z-index:2;width:100%;height:100%;text-align:center;padding:0 var(--gut);pointer-events:none}
/* Set in the lower third, not the middle: centred type lands straight across
   the subject's face in the opening frames. */
.morph-line{
  position:absolute;left:50%;top:74%;transform:translate(-50%,-50%) translateY(12px);
  width:min(90vw,780px);margin:0;opacity:0;transition:opacity .5s ease,transform .5s ease;
}
.morph-line.is-on{opacity:1;transform:translate(-50%,-50%)}
/* Only the opening line uses this: at the shared 74% it lands on the mouth
   in the opening portrait frame. Lower, it clears the face and sits on the
   jacket/collar instead. The other two lines stay at 74% — their frames
   (the eye close-up, the energy body) don't have this collision. */
.morph-line--low{top:88%}
.morph-line span{
  display:block;font-family:var(--display);font-weight:700;
  font-size:clamp(1.6rem,4.6vw,3.2rem);line-height:1.08;letter-spacing:-.03em;
  color:var(--off-white);text-shadow:0 2px 40px rgba(0,0,0,.85);
}
.morph-line em{font-style:normal;color:var(--cyan);display:block}

.morph-cue{
  position:absolute;left:50%;bottom:34px;transform:translateX(-50%);z-index:3;
  display:flex;flex-direction:column;align-items:center;gap:10px;
  font-family:var(--display);font-size:.68rem;font-weight:600;letter-spacing:.24em;
  text-transform:uppercase;color:var(--slate);
  transition:opacity .4s ease;
}
.morph-cue.is-gone{opacity:0}
.morph-cue i{display:block;width:1px;height:34px;background:linear-gradient(180deg,var(--cyan),transparent)}

/* No JS, or motion reduced: one screen, poster only, nothing pinned. */
.morph.is-static .morph-track{height:100vh}
.morph.is-static .morph-stage{position:relative}
.morph.is-static .morph-cue{display:none}

/* Phones scrub too — only prefers-reduced-motion (which JS turns into
   .is-static above) collapses the track. The 960px still is what loads
   first at this width, ahead of the video, and it is under a third of the
   weight of the default poster. There is no separate xl poster this time —
   the source master itself is only 1920px wide, so a wide display already
   gets the largest asset that exists; a bigger file would just be the same
   pixels upscaled again before they even reach the browser. */
@media (max-width:760px){
  .morph-stage{background-image:url('/assets/video/morph-poster-sm.jpg')}
}

/* ---------- hero ---------- */
.hero{padding:104px 0 84px;position:relative;overflow:hidden}
/* Cinematic wash: indigo bloom low and wide, a tighter cyan core inside it. */
.hero::before{
  content:"";position:absolute;inset:auto 0 -55% 0;height:90%;
  background:radial-gradient(70% 100% at 50% 100%,rgba(30,36,80,.85),transparent 72%);
  pointer-events:none;
}
.hero::after{
  content:"";position:absolute;inset:auto 0 -35% 0;height:62%;
  background:radial-gradient(42% 100% at 50% 100%,rgba(47,228,255,.12),transparent 70%);
  pointer-events:none;
}
.hero-in{position:relative;z-index:1;max-width:900px}
.hero h1{
  font-size:clamp(2.5rem,7vw,4.7rem);
  line-height:1.02;letter-spacing:-.035em;margin:0 0 28px;
}
.hero h1 em{font-style:normal;color:var(--cyan);display:block}
.hero .lede{max-width:66ch}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--display);font-size:.86rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  padding:14px 26px;border-radius:var(--r);border:1px solid transparent;cursor:pointer;
  transition:background .18s ease,border-color .18s ease,color .18s ease,transform .12s ease;
}
.btn:active{transform:translateY(1px)}
/* Navy on cyan, never white: white on this cyan is 1.5:1 and unreadable. */
.btn-primary{background:var(--cyan);color:var(--navy);border-color:var(--cyan)}
.btn-primary:hover{background:var(--cyan-dim);border-color:var(--cyan-dim);color:var(--navy)}
.btn-outline{background:transparent;color:var(--off-white);border-color:var(--line-2)}
.btn-outline:hover{border-color:var(--cyan);color:var(--off-white);background:var(--cyan-10)}
.btn[disabled]{opacity:.55;cursor:not-allowed}

.link-arrow{
  display:inline-flex;align-items:center;gap:8px;font-family:var(--display);
  font-size:.84rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--cyan);
  transition:gap .18s ease,color .18s ease;
}
.link-arrow:hover{color:var(--cyan-dim);gap:12px}

/* ---------- signup form ---------- */
.signup{
  margin-top:38px;max-width:620px;
  background:var(--indigo);border:1px solid var(--line);border-radius:6px;padding:26px;
}
.signup .signup-ask{font-size:1rem;color:#D3D8E6;margin:0 0 18px}
.signup-row{display:flex;gap:10px;flex-wrap:wrap}
.signup-row .field{flex:1 1 240px;min-width:0}

label{
  display:block;font-family:var(--display);font-size:.76rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--slate);margin:0 0 7px;
}

input[type="text"],input[type="email"]{
  width:100%;background:var(--navy);border:1px solid var(--line-2);border-radius:var(--r);
  color:var(--off-white);font-family:var(--sans);font-size:1rem;padding:13px 14px;
  transition:border-color .18s ease,box-shadow .18s ease;
}
input[type="text"]::placeholder,input[type="email"]::placeholder{color:var(--slate-2)}
input[type="text"]:focus,input[type="email"]:focus{border-color:var(--cyan);box-shadow:0 0 0 3px var(--cyan-10);outline:none}
input.is-invalid{border-color:var(--danger);background:rgba(255,122,133,.06)}

/* honeypot — visually removed, and never by display:none alone */
.hp{position:absolute!important;left:-9999px!important;top:-9999px!important;width:1px;height:1px;overflow:hidden}

.consent{display:flex;align-items:flex-start;gap:11px;margin:18px 0 0;cursor:pointer}
.consent input[type="checkbox"]{
  appearance:none;-webkit-appearance:none;flex:0 0 auto;
  width:19px;height:19px;margin:2px 0 0;border:1px solid var(--line-2);border-radius:3px;
  background:var(--navy);cursor:pointer;position:relative;transition:background .15s ease,border-color .15s ease;
}
.consent input[type="checkbox"]:checked{background:var(--cyan);border-color:var(--cyan)}
.consent input[type="checkbox"]:checked::after{
  content:"";position:absolute;left:6px;top:2px;width:5px;height:10px;
  border:solid var(--navy);border-width:0 2px 2px 0;transform:rotate(43deg);
}
.consent input.is-invalid{border-color:var(--danger);box-shadow:0 0 0 3px rgba(255,122,133,.22)}
.consent span{font-size:.86rem;line-height:1.55;color:var(--slate);text-transform:none;letter-spacing:0;font-weight:400;font-family:var(--sans)}
.consent a{color:#C2C9DB;text-decoration:underline;text-underline-offset:2px}
.consent a:hover{color:var(--cyan)}

.form-msg{display:none;margin-top:16px;font-size:.9rem;line-height:1.5;border-radius:var(--r);padding:11px 14px}
.form-msg.err{display:block;background:rgba(255,122,133,.10);border:1px solid rgba(255,122,133,.38);color:var(--danger)}
.form-msg.ok{display:block;background:var(--cyan-10);border:1px solid var(--cyan-30);color:var(--cyan)}

/* ---------- self-select strip ---------- */
.self-select{margin-top:44px;font-size:.95rem;color:var(--slate)}
.self-select strong{color:var(--off-white);font-weight:600}
.self-select a{color:var(--off-white);border-bottom:1px solid var(--line-2);padding-bottom:1px}
.self-select a:hover{color:var(--cyan);border-color:var(--cyan)}

/* ---------- story ---------- */
.story-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.35fr);gap:64px;align-items:start}
.pull{
  font-family:var(--display);font-weight:700;
  font-size:clamp(2.2rem,5vw,3.4rem);line-height:1.02;
  letter-spacing:-.04em;margin:0;
}
.pull em{font-style:normal;color:var(--cyan);display:block}
.pull-note{margin-top:20px;font-family:var(--display);font-size:.8rem;letter-spacing:.14em;text-transform:uppercase;color:var(--slate-2)}

/* ---------- cards ---------- */
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}
.grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px}

.card{
  background:var(--indigo);border:1px solid var(--line);border-radius:6px;padding:30px;
  display:flex;flex-direction:column;gap:12px;
  transition:border-color .2s ease,background .2s ease,transform .2s ease;
}
.card:hover{border-color:var(--cyan-30);background:var(--indigo-2)}
a.card:hover{transform:translateY(-2px);color:inherit}
.card h3{font-size:1.32rem;letter-spacing:-.025em}
.card p{font-size:.96rem;color:var(--slate);line-height:1.6}
.card .tag{
  font-family:var(--display);
  font-size:.7rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--cyan);
}
.card .card-foot{margin-top:auto;padding-top:10px}

/* ---------- framework list ---------- */
.frameworks{list-style:none;margin:34px 0 0;padding:0;border-top:1px solid var(--line)}
.frameworks li{
  border-bottom:1px solid var(--line);padding:26px 0;
  display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:34px;align-items:baseline;
}
.frameworks h3{font-size:1.26rem}
.frameworks p{color:var(--slate);font-size:.98rem;margin:0}

/* ---------- post list ---------- */
.post-list{list-style:none;margin:0;padding:0}
.post-list li{border-bottom:1px solid var(--line)}
.post-list li:first-child{border-top:1px solid var(--line)}
.post-list a{display:block;padding:28px 0;transition:padding .2s ease}
.post-list a:hover{padding-left:12px}
.post-meta{
  font-family:var(--display);font-size:.73rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--slate-2);margin-bottom:10px;
}
.post-meta .cat{color:var(--cyan)}
.post-list h3{font-size:clamp(1.3rem,3vw,1.7rem);margin-bottom:8px}
.post-list p{color:var(--slate);font-size:.98rem;max-width:70ch;margin:0}

.empty-state{
  border:1px dashed var(--line-2);border-radius:6px;padding:44px 30px;text-align:center;color:var(--slate);
}
.empty-state h3{font-size:1.22rem;color:var(--off-white);margin-bottom:10px}

/* ---------- chips ---------- */
.chips{display:flex;flex-wrap:wrap;gap:10px;margin:0;padding:0;list-style:none}
.chips a{
  display:inline-block;border:1px solid var(--line-2);border-radius:100px;padding:8px 16px;
  font-size:.83rem;color:#C2C9DB;transition:border-color .18s ease,color .18s ease,background .18s ease;
}
.chips a:hover,.chips a[aria-current="page"]{border-color:var(--cyan);color:var(--off-white);background:var(--cyan-10)}

/* ---------- article ---------- */
.article-head{padding:76px 0 0}
.article-head h1{font-size:clamp(2rem,5.4vw,3.3rem);letter-spacing:-.035em;margin:14px 0 22px}
.article-body{padding:44px 0 92px;font-size:1.08rem;line-height:1.78}
.article-body h2{font-size:clamp(1.5rem,3.4vw,2rem);margin:52px 0 16px}
.article-body h3{font-size:1.2rem;margin:38px 0 12px}
.article-body blockquote{
  margin:38px 0;padding:2px 0 2px 26px;border-left:2px solid var(--cyan);
  font-family:var(--display);font-weight:500;font-size:1.3rem;line-height:1.34;
  letter-spacing:-.02em;color:#E7EAF3;
}
.article-body ul,.article-body ol{margin:0 0 1.2em;padding-left:22px;color:#D3D8E6}
.article-body li{margin-bottom:.5em}
.article-body a{color:var(--cyan);text-decoration:underline;text-underline-offset:3px}
.article-body a:hover{color:var(--cyan-dim)}
.article-body hr{border:0;border-top:1px solid var(--line);margin:48px 0}

/* ---------- legal ---------- */
.legal{padding:76px 0 92px}
.legal h1{font-size:clamp(2rem,5vw,3rem);margin-bottom:14px}
.legal .updated{font-family:var(--display);font-size:.8rem;letter-spacing:.16em;text-transform:uppercase;color:var(--slate-2);margin-bottom:40px}
.legal h2{font-size:1.28rem;margin:44px 0 14px}
.legal h3{font-size:1.04rem;font-weight:700;margin:28px 0 10px}
.legal p,.legal li{color:#CBD1E0;font-size:1rem;line-height:1.72}
.legal ul{padding-left:20px;margin:0 0 1.2em}
.legal li{margin-bottom:.55em}
.legal a{color:var(--cyan);text-decoration:underline;text-underline-offset:3px}
.legal a:hover{color:var(--cyan-dim)}
.legal .callout{
  border:1px solid var(--line-2);border-left:2px solid var(--cyan);border-radius:var(--r);
  padding:18px 22px;margin:0 0 34px;font-size:.95rem;color:var(--slate);
}

/* ---------- CTA band ---------- */
.band{background:var(--indigo);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.band h2{font-size:clamp(1.9rem,4.6vw,2.9rem);margin-bottom:18px}
.band .signup{background:var(--navy)}
.band .signup input[type="text"],.band .signup input[type="email"]{background:var(--indigo-2)}

/* ---------- footer ---------- */
.site-footer{padding:64px 0 40px;border-top:1px solid var(--line);background:var(--navy)}
.footer-grid{display:grid;grid-template-columns:minmax(0,1.4fr) repeat(3,minmax(0,1fr));gap:38px}
.footer-grid h4{
  font-family:var(--display);font-size:.71rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--slate-2);margin:0 0 16px;
}
.footer-grid ul{list-style:none;margin:0;padding:0}
.footer-grid li{margin-bottom:10px}
.footer-grid a{font-size:.92rem;color:#C2C9DB}
.footer-grid a:hover{color:var(--cyan)}
.footer-brand .brand{font-size:1.12rem;display:inline-block;margin-bottom:12px}
.footer-brand p{font-size:.92rem;color:var(--slate);max-width:36ch}
.footer-bottom{
  margin-top:52px;padding-top:24px;border-top:1px solid var(--line);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  font-size:.84rem;color:var(--slate-2);
}
.footer-bottom a{color:var(--slate-2)}
.footer-bottom a:hover{color:var(--cyan)}

/* ---------- reveal ---------- */
.reveal{opacity:0;transform:translateY(14px);transition:opacity .6s ease,transform .6s ease}
.reveal.is-in{opacity:1;transform:none}

/* ---------- responsive ---------- */
@media (max-width:920px){
  .story-grid{grid-template-columns:1fr;gap:34px}
  .grid-3{grid-template-columns:1fr}
  .grid-2{grid-template-columns:1fr}
  .frameworks li{grid-template-columns:1fr;gap:10px}
  .footer-grid{grid-template-columns:1fr 1fr;gap:32px}
}
@media (max-width:760px){
  body{font-size:16px}
  section{padding:66px 0}
  .hero{padding:72px 0 60px}
  /* backdrop-filter: blur() is a known scroll-jank source on mid-range
     mobile GPUs — it has to be recomposited every frame the page scrolls
     under it. It matters everywhere, but it is worst directly over the
     morph section, which is already asking the device to decode and seek
     video on every frame; stacking a live blur on top of that is the more
     likely cause of reported stutter than the video itself. A flat,
     slightly darker fill keeps the header legible without the per-frame
     recomposite cost. */
  .site-header{background:rgba(10,15,31,.97);backdrop-filter:none}
  .nav-toggle{display:block}
  .nav{
    display:none;position:absolute;left:0;right:0;top:var(--header-h);
    flex-direction:column;align-items:stretch;gap:0;
    background:var(--indigo);border-bottom:1px solid var(--line);padding:8px 0;
  }
  .nav.is-open{display:flex}
  .nav a{padding:14px var(--gut);border-bottom:1px solid var(--line)}
  .nav a[aria-current="page"]{border-bottom:1px solid var(--line)}
  .nav-cta{border:0;border-radius:0;text-align:left}
  .nav-cta:hover{background:transparent}
  .signup{padding:20px}
  .footer-grid{grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{transition:none!important;animation:none!important}
  .reveal{opacity:1;transform:none}
}

@media print{
  .site-header,.site-footer,.signup,.band{display:none}
  body{background:#fff;color:#000}
}
