/* ==========================================================================
   Ignition — Ádám Zsolt, real estate agent
   Extracted from index.html so browsers can cache it between visits.
   Color tokens mirror brand/palette.css; that file is the brand source of
   truth, this one is what the page actually loads.
   ========================================================================== */

:root{
  --color-bg:#0A0B15;         /* Background — Ink (was Paper; the page is dark throughout now) */
  --color-frame:#0A0B15;      /* page mat — the body gradient below is what actually paints it */
  --color-surface:rgba(255,255,255,0.06); /* Secondary — glass mist, was pale Mist */
  --color-text:#FFFFFF;       /* Text — White (was Graphite; every surface is dark now) */
  --color-primary:#14161A;    /* Primary — Graphite (mobile drawer, skip-link — still darker than the page) */
  --color-accent:#2F5DFF;     /* Accent (bold tint) — Cobalt — badges, rings, glow, emphasis */
  --color-accent-text:#A9C2FF;/* Accent (text-safe tint) — Periwinkle, was the on-dark-only tint, now the default everywhere */
  --btn-primary-bg:#FFFFFF;   /* was Graphite/White; flipped — a dark pill would vanish on a dark page */
  --btn-primary-text:#14161A;
  --on-primary:#FFFFFF;
  --border:rgba(255,255,255,0.14);        /* was dark-on-light; every surface is dark now */
  --border-on-primary:rgba(255,255,255,0.16);
  --ease-out:cubic-bezier(.16,1,.3,1); /* stronger than CSS ease-out — used for reveals and press feedback */

  /* Shared frosted-glass card system — used by every card (listings, services,
     the Why Me card, the contact card) instead of a flat white or flat dark
     fill, so cards float visibly on the page's own dark gradient. */
  --glass-bg:rgba(255,255,255,0.055);
  --glass-bg-strong:rgba(255,255,255,0.09);
  --glass-border:rgba(255,255,255,0.14);
  --glass-border-top:rgba(255,255,255,0.28);
}
/* Committed brand direction, v8: one continuous dark, glossy-blue field runs
   the full length of the page — not just the hero and footer bookends — with
   frosted glass cards floating on top. Not a viewer dark-mode toggle; colors
   are painted explicitly throughout. */

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
html{background:#0A0B15;scroll-behavior:smooth;}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto;}}
body{
  margin:0;
  overflow-x:hidden;
  background:
    radial-gradient(900px 620px at 14% -4%, rgba(75,118,255,0.26), transparent 60%),
    radial-gradient(1000px 720px at 88% 22%, rgba(47,93,255,0.18), transparent 55%),
    radial-gradient(900px 680px at 12% 48%, rgba(47,93,255,0.15), transparent 55%),
    radial-gradient(1000px 720px at 88% 72%, rgba(75,118,255,0.16), transparent 55%),
    radial-gradient(900px 680px at 16% 96%, rgba(47,93,255,0.14), transparent 55%),
    linear-gradient(180deg,#1B2138 0%,#0E1020 26%,#0A0B15 55%,#08090F 100%);
  color:var(--color-text);
  font-family:"Work Sans", ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3{font-family:"Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif;text-wrap:balance;margin:0;}
code,.mono{font-family:"IBM Plex Mono", ui-monospace, Menlo, monospace;}
a{color:inherit;}
.wrap{max-width:1120px;margin:0 auto;padding:0 2rem;}

/* Skip link — first thing in the tab order, invisible until it has focus.
   Without it a keyboard visitor tabs the whole nav on every section jump. */
.skip-link{
  position:absolute;left:-9999px;top:0;z-index:400;
  background:var(--color-primary);color:#fff;text-decoration:none;
  font-family:"Work Sans",sans-serif;font-weight:600;font-size:0.85rem;
  padding:0.7rem 1.2rem;border-radius:0 0 10px 0;
}
.skip-link:focus{left:0;}

/* One visible focus treatment for everything, rather than per-component.
   Periwinkle by default now — every surface on the page is dark. */
:focus-visible{outline:2px solid var(--color-accent-text);outline-offset:2px;border-radius:2px;}
@media (max-width:640px){.wrap{padding:0 1.2rem;}}

/* Full-bleed on the blue field — no more boxed white page card. */
.reveal{opacity:0;transform:translateY(18px);transition:opacity .55s var(--ease-out), transform .55s var(--ease-out);}
.reveal.is-visible{opacity:1;transform:none;}

/* Grid/list children get their own hidden state and a per-item stagger,
   layered on top of the section-level .reveal above — a row arrives as
   a cascade rather than one flat block. Card art and copy stay put;
   only opacity/transform move, so nothing reflows while it plays. */
.reveal .listings-grid > *, .reveal .services-grid > *, .reveal .why-list > .why-item, .reveal .timeline > .tl-item{
  opacity:0;transform:translateY(14px);
  transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
.reveal.is-visible .listings-grid > *, .reveal.is-visible .services-grid > *, .reveal.is-visible .why-list > .why-item, .reveal.is-visible .timeline > .tl-item{
  opacity:1;transform:none;
}
.listings-grid > *:nth-child(1), .services-grid > *:nth-child(1), .why-list > .why-item:nth-child(1){transition-delay:0ms;}
.listings-grid > *:nth-child(2), .services-grid > *:nth-child(2), .why-list > .why-item:nth-child(2){transition-delay:70ms;}
.listings-grid > *:nth-child(3), .services-grid > *:nth-child(3), .why-list > .why-item:nth-child(3){transition-delay:140ms;}
.why-list > .why-item:nth-child(4){transition-delay:210ms;}

/* The process timeline shares one delay value per step — via a custom
   property, not a repeated transition-delay — because the reveal touches
   three separate elements per step (the row, the node, the glowing rail
   segment below it) that all need to move in lockstep. */
.timeline > .tl-item:nth-child(1){--tl-delay:0ms;}
.timeline > .tl-item:nth-child(2){--tl-delay:90ms;}
.timeline > .tl-item:nth-child(3){--tl-delay:180ms;}
.timeline > .tl-item:nth-child(4){--tl-delay:270ms;}
.timeline > .tl-item:nth-child(5){--tl-delay:360ms;}
.timeline > .tl-item:nth-child(6){--tl-delay:450ms;}
.timeline > .tl-item:nth-child(7){--tl-delay:540ms;}
.reveal .timeline > .tl-item{transition-delay:var(--tl-delay,0ms);}

/* ---------- nav ---------- */
.nav{
  display:flex;align-items:center;justify-content:space-between;
  padding:1.4rem 2rem;
  max-width:1120px;margin:0 auto;
}
.brand-lockup{display:flex;align-items:center;gap:0.55rem;}
.brand-lockup img{height:28px;width:auto;display:block;}
.nav-links{
  display:flex;align-items:center;gap:0.1rem;
  padding:0.3rem;border-radius:999px;
  background:var(--glass-bg);
  backdrop-filter:blur(20px) saturate(180%); -webkit-backdrop-filter:blur(20px) saturate(180%);
  border:1px solid var(--glass-border);border-top-color:var(--glass-border-top);
}
@media (prefers-reduced-transparency:reduce){.nav-links{background:#14161A;backdrop-filter:none;-webkit-backdrop-filter:none;}}
.nav-links a{
  font-size:0.86rem;font-weight:500;text-decoration:none;color:var(--color-text);opacity:0.72;
  padding:0.5rem 1rem;border-radius:999px;
  transition:background .2s var(--ease-out), opacity .15s ease, color .15s ease;
}
.nav-links a:hover, .nav-links a:focus-visible{opacity:1;color:var(--color-accent-text);background:rgba(255,255,255,0.09);}
@media (max-width:760px){.nav-links{display:none;}}
.btn-pill{
  display:inline-block;background:var(--btn-primary-bg);color:var(--btn-primary-text);
  font-family:"Work Sans",sans-serif;font-weight:600;font-size:0.85rem;
  padding:0.68rem 1.35rem;border-radius:999px;text-decoration:none;
  transition:background .15s ease, transform 120ms var(--ease-out);
}
.btn-pill:hover, .btn-pill:focus-visible{background:var(--color-accent-text);}
.btn-pill:active{transform:scale(0.97);}
.nav-actions{display:flex;align-items:center;gap:0.9rem;}
.lang-toggle{display:flex;align-items:center;gap:1px;padding:3px;border-radius:999px;border:1px solid var(--border);}
.lang-btn{
  font-family:"IBM Plex Mono",monospace;font-size:0.7rem;font-weight:500;letter-spacing:0.03em;
  padding:0.36rem 0.6rem;border-radius:999px;border:none;background:transparent;color:var(--color-text);opacity:0.62;
  cursor:pointer;transition:background .15s ease,opacity .15s ease,color .15s ease;
}
.lang-btn:hover, .lang-btn:focus-visible{opacity:0.9;}
.lang-btn.active{background:var(--color-accent);color:#fff;opacity:1;}
@media (max-width:400px){.lang-btn{padding:0.36rem 0.5rem;}}
@media (max-width:400px){.btn-pill{padding:0.6rem 1rem;font-size:0.8rem;}}
@media (max-width:400px){.brand-lockup img{height:24px;}}

/* ---------- mobile nav toggle + drawer ---------- */
.nav-toggle{
  display:none;flex-direction:column;justify-content:center;align-items:center;gap:5px;
  width:38px;height:38px;flex:none;background:transparent;border:none;padding:0;cursor:pointer;
}
.nav-toggle .bar{
  display:block;width:20px;height:1.6px;border-radius:2px;background:#fff;
  transition:transform .25s ease, opacity .2s ease, background .25s ease;
}
.nav-toggle.is-open .bar:nth-child(1){transform:translateY(6.6px) rotate(45deg);}
.nav-toggle.is-open .bar:nth-child(2){opacity:0;}
.nav-toggle.is-open .bar:nth-child(3){transform:translateY(-6.6px) rotate(-45deg);}
@media (max-width:760px){.nav-toggle{display:flex;}}

.mobile-nav{
  display:none;flex-direction:column;
  background:#14161A;
  padding:0.4rem 2rem 1.3rem;
}
.mobile-nav a{
  padding:0.85rem 0;font-size:1rem;font-weight:500;text-decoration:none;
  color:#fff;opacity:0.82;border-top:1px solid rgba(255,255,255,0.12);
}
.mobile-nav a:first-child{border-top:none;}
.mobile-nav a:hover, .mobile-nav a:active, .mobile-nav a:focus-visible{opacity:1;color:#A9C2FF;}
.nav-bar.menu-open .mobile-nav{display:flex;}
@media (max-width:640px){.mobile-nav{padding:0.4rem 1.2rem 1.3rem;}}
@media (min-width:761px){.mobile-nav{display:none !important;}}

/* ---------- fixed top bar: stays visible while scrolling ---------- */
html{scroll-padding-top:5.2rem;}
.nav-bar{
  position:fixed;top:0;left:0;right:0;z-index:200;
  padding-top:env(safe-area-inset-top);
  transition:background .25s ease, box-shadow .25s ease, backdrop-filter .25s ease;
}
.nav-bar .nav-links a{color:#fff;opacity:0.78;}
.nav-bar .nav-links a:hover, .nav-bar .nav-links a:focus-visible{opacity:1;color:#A9C2FF;}
.nav-bar .lang-toggle{border-color:rgba(255,255,255,0.28);}
.nav-bar .lang-btn{color:#fff;}
.nav-bar .btn-pill{background:#fff;color:#14161A;}
.nav-bar .btn-pill:hover, .nav-bar .btn-pill:focus-visible{background:#A9C2FF;}
/* The page is one continuous dark field now, so the bar doesn't flip to a
   light theme once scrolled — it just gains a frosted backing for legibility
   over whatever glass card happens to scroll underneath it. */
.nav-bar.scrolled{
  background:rgba(8,9,16,0.68);
  backdrop-filter:blur(14px) saturate(160%); -webkit-backdrop-filter:blur(14px) saturate(160%);
  box-shadow:0 1px 0 rgba(255,255,255,0.08), 0 8px 24px rgba(4,6,16,0.35);
}
@media (max-width:640px){.nav-bar .nav{padding:1.1rem 1.2rem;}}

/* ---------- hero stage: full-bleed 3D loop is the first thing on the page ---------- */
.hero-stage{
  position:relative;
  overflow:hidden;
  min-height:100svh;
  background:radial-gradient(circle at 50% 45%, #1B2138 0%, #0E1020 62%, #0A0B15 100%);
}
.key-stage{position:absolute;inset:0;display:flex;align-items:flex-start;justify-content:center;padding-top:13vh;pointer-events:none;}
.key-composite{position:relative;width:min(30vmin,220px);}
.key-glow-wrap{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:160%;height:160%;
}
.key-glow-ambient{
  width:100%;height:100%;border-radius:50%;
  background:radial-gradient(circle, rgba(47,93,255,0.55) 0%, rgba(47,93,255,0.22) 45%, rgba(47,93,255,0) 72%);
  filter:blur(6px);
  animation:keyGlowIntro 2.6s ease-out both, keyGlowPulse 6s ease-in-out 2.6s infinite;
}
.key-art{
  position:relative;width:100%;
  animation:keyIntro 2.6s cubic-bezier(.22,.85,.28,1) both, keyFloat 8s ease-in-out 2.6s infinite;
}
.key-art img{display:block;width:100%;height:auto;filter:drop-shadow(0 18px 30px rgba(5,8,20,0.55));}
@keyframes keyFloat{
  0%,100%{transform:translateY(0) rotate(-2deg);}
  50%{transform:translateY(-14px) rotate(2deg);}
}
@keyframes keyGlowPulse{
  0%,100%{opacity:0.55;transform:scale(1);}
  50%{opacity:0.85;transform:scale(1.08);}
}
@keyframes keyIntro{
  0%,44%{transform:translateY(52px) rotate(-70deg) scale(0.8);}
  70%{transform:translateY(8px) rotate(14deg) scale(1.05);}
  86%{transform:translateY(-6px) rotate(-8deg) scale(0.98);}
  100%{transform:translateY(0) rotate(-2deg) scale(1);}
}
@keyframes keyGlowIntro{
  0%,44%{opacity:0;transform:scale(0.6);}
  72%{opacity:0.9;transform:scale(1.15);}
  100%{opacity:0.55;transform:scale(1);}
}
/* The rest of the token set now matches the page-wide default; only the
   arrow badge's border stays a touch stronger against the busy key art. */
.hero-stage.on-dark{ --border:rgba(255,255,255,0.22); }
.hero-content{position:relative;z-index:1;min-height:100svh;display:flex;flex-direction:column;}
.hero-center{
  flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;gap:0.9rem;padding:6rem 1.5rem 4.5rem;max-width:34rem;margin:0 auto;
}
.hero-logo{height:56px;width:auto;filter:drop-shadow(0 0 26px rgba(47,93,255,0.55));}
.hero-name{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:800;
  font-size:clamp(2.1rem,5.4vw,3.6rem);color:#fff;letter-spacing:-0.01em;line-height:1.03;
}
.hero-kicker{
  font-family:"IBM Plex Mono",monospace;font-size:0.72rem;letter-spacing:0.12em;text-transform:uppercase;
  color:var(--color-accent-text);opacity:0.95;margin:-0.3rem 0 0;
}
.hero-tagline{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:600;
  font-size:clamp(1.15rem,2.6vw,1.55rem);color:rgba(255,255,255,0.92);line-height:1.28;margin:0.3rem 0 0;
}
.hero-tagline em{font-style:normal;color:var(--color-accent-text);}
.hero-sub{max-width:30ch;font-size:0.9rem;line-height:1.6;color:rgba(255,255,255,0.66);margin:0;}
.hero-cta{display:flex;align-items:center;gap:1rem;margin-top:0.5rem;}
.hero-cta-label{display:inline-block;font-family:"Work Sans",sans-serif;font-weight:600;font-size:0.88rem;color:#fff;text-decoration:none;border-bottom:1.5px solid rgba(255,255,255,0.35);padding-bottom:2px;transition:border-color .15s ease, color .15s ease, transform 100ms var(--ease-out);}
.hero-cta-label:hover, .hero-cta-label:focus-visible{border-color:var(--color-accent-text);color:var(--color-accent-text);}
.hero-cta-label:active{transform:scale(0.97);}
.arrow-badge{
  flex:none;width:52px;height:52px;border-radius:50%;
  border:1.3px solid var(--border);
  display:flex;align-items:center;justify-content:center;
  text-decoration:none;
  transition:border-color .15s ease, transform 120ms var(--ease-out);
}
.arrow-badge:hover, .arrow-badge:focus-visible{border-color:var(--color-accent);transform:scale(1.06);}
.arrow-badge:active{transform:scale(0.94);}
.arrow-badge svg{width:18px;height:18px;}
.arrow-badge svg line, .arrow-badge svg polyline{stroke:var(--color-text);}
@media (max-width:640px){
  .hero-center{padding:5.2rem 1.2rem 3rem;}
}

.model-caption{
  margin:1.2rem auto 0;
  font-family:"IBM Plex Mono",monospace;
  font-size:0.78rem;
  line-height:1.6;
  color:var(--color-text);
  opacity:0.55;
  max-width:48ch;
}

/* ---------- pillars strip ----------
   Two glass layers stacked, not one flat band: the strip itself is a big,
   softly-blurred panel (thin material, per Apple's "bigger surfaces read
   thicker" rule it still gets the deeper of the two shadows because it's
   the one lifting off the busiest part of the background gradient), and
   each icon badge is a small, tighter, more-blurred chip sitting on top
   of it — the same weight relationship the rest of the page already uses
   between a card and the controls inside it. */
.pillars{padding:2.8rem 2rem;position:relative;z-index:2;}
@media (max-width:640px){.pillars{padding:2rem 1.2rem;}}
.pillars .wrap{
  display:grid;grid-template-columns:repeat(4,1fr);gap:0;
  max-width:1120px;padding:0;
  background:var(--glass-bg-strong);
  backdrop-filter:blur(28px) saturate(180%); -webkit-backdrop-filter:blur(28px) saturate(180%);
  border:1px solid var(--glass-border);border-top-color:var(--glass-border-top);
  border-radius:18px;
  box-shadow:0 20px 44px -24px rgba(3,5,18,0.55), inset 0 1px 0 rgba(255,255,255,0.05);
}
@media (max-width:760px){.pillars .wrap{grid-template-columns:1fr 1fr;}}
@media (prefers-reduced-transparency:reduce){.pillars .wrap{background:#161A28;backdrop-filter:none;-webkit-backdrop-filter:none;}}
.pillar{
  position:relative;border-left:1px solid var(--glass-border);
  padding:1.7rem 1.5rem;
  transition:background .25s var(--ease-out);
}
.pillar:first-child{border-left:none;border-radius:18px 0 0 18px;}
.pillar:last-child{border-radius:0 18px 18px 0;}
.pillar:hover{background:rgba(255,255,255,0.035);}
@media (max-width:760px){
  .pillar:nth-child(odd){border-left:none;}
  .pillar:nth-child(-n+2){border-bottom:1px solid var(--glass-border);}
  .pillar:first-child{border-radius:18px 0 0 0;}
  .pillar:nth-child(2){border-radius:0 18px 0 0;}
  .pillar:nth-child(3){border-radius:0 0 0 18px;}
  .pillar:last-child{border-radius:0 0 18px 0;}
}
.pillar-icon{
  display:flex;align-items:center;justify-content:center;
  width:1.75rem;height:1.75rem;margin-bottom:0.85rem;
  border-radius:8px;color:var(--color-accent-text);
  background:rgba(255,255,255,0.07);
  border:1px solid var(--glass-border);
  box-shadow:0 4px 10px -6px rgba(3,5,18,0.6);
}
.pillar-icon svg{width:13px;height:13px;}
.pillar .word{font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.02rem;margin-bottom:0.35rem;}
.pillar p{margin:0;font-size:0.85rem;line-height:1.55;opacity:0.62;max-width:22ch;}

/* ---------- section shell ---------- */
section.doc{padding:5rem 0;max-width:1120px;margin:0 auto;}
section.doc + section.doc{border-top:1px solid var(--border);}
@media (max-width:640px){section.doc{padding:3.4rem 0;}}
.section-kicker{
  font-family:"IBM Plex Mono",monospace;font-size:0.72rem;letter-spacing:0.12em;
  text-transform:uppercase;color:var(--color-accent-text);margin:0 0 0.8rem;
}
section.doc h2{font-size:clamp(1.6rem,3vw,2rem);font-weight:700;margin-bottom:0.6rem;max-width:20ch;}
section.doc > .wrap > p.note{max-width:40rem;line-height:1.6;opacity:0.7;margin:0 0 2.6rem;font-size:0.98rem;}

/* ---------- legal / privacy page ---------- */
.legal-first{padding-top:9.5rem;}
@media (max-width:640px){.legal-first{padding-top:7.6rem;}}
.legal h1{font-size:clamp(1.9rem,4vw,2.6rem);font-weight:700;margin:0 0 0.6rem;max-width:20ch;}
.legal .legal-updated{font-family:"IBM Plex Mono",monospace;font-size:0.78rem;opacity:0.5;margin:0 0 2.6rem;}
.legal h2{font-size:clamp(1.15rem,2vw,1.35rem);font-weight:700;margin:2.4rem 0 0.7rem;max-width:32ch;}
.legal > div:first-of-type h2{margin-top:0;}
.legal p{margin:0 0 1rem;font-size:0.96rem;line-height:1.7;opacity:0.78;max-width:62ch;}
.legal ul{margin:0 0 1.2rem;padding-left:1.25rem;max-width:62ch;}
.legal li{font-size:0.96rem;line-height:1.7;opacity:0.78;margin-bottom:0.5rem;}
.legal strong{opacity:1;font-weight:600;}
.legal a{color:var(--color-accent-text);text-decoration:underline;text-underline-offset:2px;}
.legal a:hover, .legal a:focus-visible{color:#fff;}

/* ---------- process timeline ----------
   Each step is its own hoverable glass row rather than plain text, the
   node is a glowing glass badge that pops in on reveal, and a second,
   brighter rail segment fades in behind each step in step with the same
   reveal — so the path visibly lights up as you scroll down it, instead
   of the whole list just sitting there fully drawn from the start. */
.timeline{list-style:none;margin:0;padding:0;max-width:44rem;}
.tl-item{
  display:grid;grid-template-columns:2.3rem 1fr;column-gap:1.2rem;position:relative;
  padding:0.9rem 1rem;margin:0 -1rem 0.4rem;border-radius:14px;
  border:1px solid transparent;
  transition:background .25s var(--ease-out), border-color .25s var(--ease-out);
}
.tl-item:last-child{margin-bottom:0;}
.tl-item:hover{background:var(--glass-bg);border-color:var(--glass-border);}

/* base rail — always present, dim */
.tl-item:not(:last-child)::after{
  content:"";position:absolute;left:2.15rem;top:3.3rem;bottom:-1.1rem;width:1.5px;
  background:var(--border);
}
/* glow rail — fades in on reveal, same delay as the row and its node */
.tl-item:not(:last-child)::before{
  content:"";position:absolute;left:2.15rem;top:3.3rem;bottom:-1.1rem;width:1.5px;
  background:linear-gradient(to bottom, var(--color-accent-text), rgba(169,194,255,0.1));
  box-shadow:0 0 8px rgba(169,194,255,0.55);
  opacity:0;transition:opacity .6s var(--ease-out);transition-delay:var(--tl-delay,0ms);
}
.reveal.is-visible .tl-item::before{opacity:1;}

.tl-item .node{
  width:2.15rem;height:2.15rem;border-radius:50%;
  background:var(--glass-bg-strong);border:1.5px solid rgba(169,194,255,0.55);color:var(--color-accent-text);
  font-family:"IBM Plex Mono",monospace;font-size:0.72rem;font-weight:600;
  display:flex;align-items:center;justify-content:center;z-index:1;
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  transform:scale(0.7);box-shadow:0 0 0 rgba(47,93,255,0);
  transition:transform .5s var(--ease-out), box-shadow .5s var(--ease-out), border-color .2s ease;
  transition-delay:var(--tl-delay,0ms);
}
.reveal.is-visible .tl-item .node{
  transform:scale(1);
  box-shadow:0 0 20px rgba(47,93,255,0.45), 0 0 4px rgba(169,194,255,0.65);
}
.tl-item:hover .node{border-color:var(--color-accent-text);}
/* the last step reads as the finish line: a solid badge instead of an outline */
.tl-item:last-child .node{background:var(--color-accent);border-color:var(--color-accent);color:#fff;}
.reveal.is-visible .tl-item:last-child .node{box-shadow:0 0 24px rgba(47,93,255,0.6), 0 0 6px rgba(47,93,255,0.8);}

.tl-item h3{font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.02rem;margin:0.15rem 0 0.3rem;}
.tl-item p{margin:0;font-size:0.88rem;line-height:1.55;opacity:0.7;}

/* ---------- why me ---------- */
.why-grid{display:grid;grid-template-columns:272px 1fr;gap:3.2rem;align-items:start;}
@media (max-width:820px){.why-grid{grid-template-columns:1fr;}}
/* Frosted glass, like every other card now — was its own separate ink
   gradient when it needed to stand out against a light page; against the
   page's own dark gradient that would just disappear. */
.why-card{
  position:sticky;top:1.6rem;isolation:isolate;overflow:hidden;
  background:var(--glass-bg);
  backdrop-filter:blur(24px) saturate(180%); -webkit-backdrop-filter:blur(24px) saturate(180%);
  border:1px solid var(--glass-border);border-top-color:var(--glass-border-top);
  box-shadow:0 16px 40px rgba(4,6,16,0.35);
  border-radius:20px;text-align:center;
}
@media (prefers-reduced-transparency:reduce){
  .why-card{background:#14161A;backdrop-filter:none;-webkit-backdrop-filter:none;}
}
@media (max-width:820px){.why-card{position:relative;}}
.why-card .photo{
  display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;object-position:top center;
}
.why-card-body{padding:1.8rem 1.6rem 2.3rem;}
.why-card .signature{
  display:block;width:60%;max-width:150px;height:auto;margin:0 auto;
  filter:drop-shadow(0 0 14px rgba(47,93,255,0.4));
}
.why-card .who-name{font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.05rem;color:#fff;margin-top:0.6rem;}
.why-card .who-role{
  font-family:"IBM Plex Mono",monospace;font-size:0.68rem;letter-spacing:0.1em;text-transform:uppercase;
  color:#A9C2FF;margin-top:0.35rem;
}
.why-list{display:flex;flex-direction:column;}
.why-item{
  display:grid;grid-template-columns:auto 1fr;gap:1.3rem;align-items:start;
  padding:1.7rem 0;border-top:1px solid var(--border);
}
.why-item:first-child{border-top:none;padding-top:0;}
.why-num{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:800;line-height:0.9;
  font-size:clamp(2.2rem,4.6vw,3.1rem);color:var(--color-accent-text);opacity:0.4;
}
.why-item h3{font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.05rem;margin:0.3rem 0 0.4rem;}
.why-item p{margin:0;font-size:0.9rem;line-height:1.58;opacity:0.68;max-width:36rem;}

/* ---------- services ---------- */
.services-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.7rem;}
@media (max-width:820px){.services-grid{grid-template-columns:1fr;}}
/* Dark glass instead of a plain white card: a frosted panel floating on
   the page mat, in the same Ink family as the hero and the Why Me card,
   rather than a fourth flat white surface in a row. Bigger radius + a
   softer, wider shadow than the first pass — that one read as a blocky
   rectangle rather than a rounded, floating panel. */
.service-card{
  position:relative;
  background:var(--glass-bg);
  backdrop-filter:blur(24px) saturate(180%);
  -webkit-backdrop-filter:blur(24px) saturate(180%);
  border-radius:28px;padding:2.3rem 2rem 2.1rem;
  border:1px solid var(--glass-border);
  border-top-color:var(--glass-border-top);
  box-shadow:0 26px 54px -28px rgba(3,5,18,0.62);
  transition:transform .35s var(--ease-out), background .35s var(--ease-out), box-shadow .35s var(--ease-out);
}
.service-card:hover{
  transform:translateY(-4px);
  background:var(--glass-bg-strong);
  box-shadow:0 34px 64px -26px rgba(3,5,18,0.68);
}
@media (prefers-reduced-transparency:reduce){
  .service-card{background:#14161A;backdrop-filter:none;-webkit-backdrop-filter:none;}
}
.service-card .svc-num{
  display:inline-flex;align-items:center;justify-content:center;
  width:2.15rem;height:2.15rem;margin-bottom:1.15rem;
  border-radius:11px;color:var(--color-accent-text);
  background:rgba(255,255,255,0.07);
  border:1px solid var(--glass-border);
  font-family:"IBM Plex Mono",monospace;font-size:0.78rem;letter-spacing:0.05em;
}
.service-card h3{font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.2rem;margin:0 0 0.7rem;}
.service-card p{margin:0 0 1.6rem;font-size:0.94rem;line-height:1.62;opacity:0.68;}
/* CTA text turned into a glass pill, matching the nav links and language
   toggle instead of sitting as bare underlined text. */
.service-card a{
  display:inline-flex;align-items:center;gap:0.35rem;
  font-size:0.86rem;font-weight:600;color:#fff;text-decoration:none;
  background:rgba(255,255,255,0.09);
  border:1px solid var(--glass-border);border-top-color:var(--glass-border-top);
  padding:0.62rem 1.2rem;border-radius:999px;
  transition:background .2s var(--ease-out), color .2s ease, border-color .2s ease, transform 100ms var(--ease-out);
}
.service-card a:hover, .service-card a:focus-visible{background:var(--color-accent-text);color:#0A0B15;border-color:var(--color-accent-text);}
.service-card a:active{transform:scale(0.96);}


/* ---------- listings ---------- */
/* Rendered from data/listings.json — see assets/js/app.js, listings module. */
.listings-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem;}
@media (max-width:900px){.listings-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:600px){.listings-grid{grid-template-columns:1fr;}}

.listings-loading{grid-column:1/-1;margin:0;font-size:0.9rem;opacity:0.55;}

.listing-card{
  position:relative;display:flex;flex-direction:column;
  background:var(--glass-bg);border-radius:18px;overflow:hidden;
  backdrop-filter:blur(24px) saturate(180%); -webkit-backdrop-filter:blur(24px) saturate(180%);
  border:1px solid var(--glass-border);border-top-color:var(--glass-border-top);
  box-shadow:0 16px 40px rgba(4,6,16,0.3);
  transition:box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
@media (prefers-reduced-transparency:reduce){
  .listing-card{background:#14161A;backdrop-filter:none;-webkit-backdrop-filter:none;}
}
.listing-card:hover, .listing-card:focus-within{
  box-shadow:0 20px 48px rgba(4,6,16,0.4);
  border-color:rgba(255,255,255,0.22);
  transform:translateY(-2px);
}
.listing-media{position:relative;display:block;background:var(--color-surface);}
.listing-media img{
  display:block;width:100%;height:auto;aspect-ratio:3/2;object-fit:cover;
}

/* Status pill — sits on the artwork, reads on any image behind it. */
.listing-status{
  position:absolute;top:0.85rem;left:0.85rem;
  font-family:"IBM Plex Mono",monospace;font-size:0.62rem;font-weight:500;
  letter-spacing:0.1em;text-transform:uppercase;
  padding:0.34rem 0.62rem;border-radius:999px;
  background:rgba(255,255,255,0.94);color:var(--color-accent-text);
  box-shadow:0 1px 3px rgba(10,11,21,0.25);
}
.listing-status[data-status="sold"]{background:#14161A;color:#fff;}
.listing-status[data-status="reserved"]{background:#F0B429;color:#14161A;}
.listing-status[data-status="for-rent"]{background:var(--color-accent);color:#fff;}

/* When a listing has no photo the pill has no artwork to sit on, so it
   becomes a normal inline chip at the top of the card body instead. */
.listing-status.is-inline{
  position:static;align-self:flex-start;margin:0 0 0.7rem;
  box-shadow:none;background:var(--color-surface);border:1px solid var(--border);
}
.listing-status.is-inline[data-status="sold"]{background:#14161A;color:#fff;border-color:#14161A;}
.listing-status.is-inline[data-status="reserved"]{background:#F0B429;color:#14161A;border-color:#F0B429;}
.listing-status.is-inline[data-status="for-rent"]{background:var(--color-accent);color:#fff;border-color:var(--color-accent);}

/* Sample-data ribbon. Anything carrying "demo": true in listings.json gets
   this, so a placeholder can never be mistaken for real inventory. Remove
   the flag from the data — not this rule — when an entry becomes real. */
.listing-card.is-demo::after{
  content:attr(data-demo-label);
  position:absolute;top:0.85rem;right:0.85rem;z-index:2;
  font-family:"IBM Plex Mono",monospace;font-size:0.6rem;font-weight:500;
  letter-spacing:0.14em;text-transform:uppercase;
  padding:0.34rem 0.6rem;border-radius:6px;
  background:repeating-linear-gradient(-45deg,#14161A,#14161A 6px,#242833 6px,#242833 12px);
  color:#fff;border:1px solid rgba(255,255,255,0.28);
}

.listing-body{padding:1.25rem 1.3rem 1.4rem;display:flex;flex-direction:column;flex:1;}
.listing-location{
  font-family:"IBM Plex Mono",monospace;font-size:0.66rem;letter-spacing:0.09em;
  text-transform:uppercase;color:var(--color-accent-text);opacity:0.8;margin:0 0 0.5rem;
}
.listing-card h3{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:700;
  font-size:1.05rem;line-height:1.3;margin:0 0 0.7rem;
}
.listing-price{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:800;
  font-size:1.28rem;letter-spacing:-0.01em;margin:0 0 0.15rem;
}
.listing-price .per{font-size:0.78rem;font-weight:600;opacity:0.5;}
.listing-price.is-poa{font-size:1rem;font-weight:700;opacity:0.6;}

.listing-specs{
  display:flex;flex-wrap:wrap;gap:0.4rem 1.1rem;margin:0.75rem 0 0;padding:0;list-style:none;
}
.listing-specs li{font-size:0.84rem;opacity:0.68;display:flex;align-items:baseline;gap:0.32rem;}
.listing-specs .spec-v{font-weight:600;opacity:1;}

.listing-features{display:flex;flex-wrap:wrap;gap:0.35rem;margin:0.95rem 0 0;padding:0;list-style:none;}
.listing-features li{
  font-size:0.72rem;padding:0.26rem 0.55rem;border-radius:999px;
  background:var(--color-surface);border:1px solid var(--border);opacity:0.85;
}

.listing-cta{
  margin-top:auto;padding-top:1.15rem;
  font-size:0.84rem;font-weight:600;color:var(--color-accent-text);text-decoration:none;
  align-self:flex-start;display:inline-block;
  border-bottom:1.5px solid rgba(169,194,255,0.35);padding-bottom:1px;
  transition:border-color .15s ease, transform 100ms var(--ease-out);
}
.listing-cta:hover, .listing-cta:focus-visible{border-color:var(--color-accent-text);}
.listing-cta:active{transform:scale(0.97);}

/* Empty state — what the section shows when listings.json holds nothing.
   A section that vanishes reads as a broken page; this reads as a start. */
.listings-empty{
  grid-column:1/-1;
  border:1.5px dashed var(--border);border-radius:20px;
  padding:3.2rem 2rem;text-align:center;background:var(--color-surface);
}
.listings-empty h3{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:700;
  font-size:1.2rem;margin:0 0 0.6rem;
}
.listings-empty p{margin:0 auto 1.6rem;max-width:38ch;font-size:0.92rem;line-height:1.6;opacity:0.68;}
.listings-empty .btn-pill{font-size:0.84rem;}

/* Load failure. Distinct from empty: one means "none yet", the other means
   "something is wrong" — collapsing them would hide a broken deploy. */
.listings-error{
  grid-column:1/-1;margin:0;padding:1.5rem;border-radius:14px;
  background:var(--color-surface);border:1px solid var(--border);
  font-size:0.9rem;line-height:1.6;opacity:0.75;
}
@media (prefers-reduced-motion:reduce){*{transition:none !important;animation:none !important;} .reveal, .reveal .listings-grid > *, .reveal .services-grid > *, .reveal .why-list > .why-item, .reveal .timeline > .tl-item{opacity:1 !important;transform:none !important;}}

/* ---------- footer ---------- */
/* No flat background of its own — the footer just continues the page's
   own dark gradient instead of sitting on it as a separately-colored
   block, so the whole page reads as one continuous surface. */
footer{border-top:1px solid var(--border);color:rgba(255,255,255,0.62);padding:3.4rem 0 0;font-size:0.9rem;}
footer .footer-top{
  display:grid;grid-template-columns:1fr 1fr;gap:2rem 4rem;align-items:start;
  padding-bottom:2.6rem;border-bottom:1px solid rgba(255,255,255,0.14);
}
@media (max-width:900px){footer .footer-top{grid-template-columns:1fr;}}
footer .footer-brand{display:flex;align-items:center;gap:0.6rem;margin-bottom:1.1rem;}
footer .footer-brand img{height:22px;width:auto;}
footer .footer-brand span{font-family:"Bricolage Grotesque",sans-serif;font-weight:700;color:#fff;font-size:1rem;}
footer h2{color:#fff;font-size:clamp(1.5rem,3vw,2.1rem);font-weight:700;max-width:16ch;margin:0 0 0.7rem;}
footer .footer-top > div:first-child p{margin:0;max-width:34rem;line-height:1.6;font-size:0.94rem;}
footer .footer-signature{display:block;height:46px;width:auto;margin:1.4rem 0 0;opacity:0.94;}
.footer-social{margin-top:1.8rem;}
.footer-social p{margin:0 0 0.9rem;font-size:0.86rem;line-height:1.55;color:rgba(255,255,255,0.6);max-width:28rem;}
.social-links{display:flex;gap:0.7rem;}
.social-icon{
  width:40px;height:40px;border-radius:50%;color:rgba(255,255,255,0.85);
  display:flex;align-items:center;justify-content:center;
  border:1.3px solid rgba(255,255,255,0.2);
  transition:border-color .15s ease, background .15s ease, color .15s ease, transform 120ms var(--ease-out);
}
.social-icon:active{transform:scale(0.93);}
.social-icon svg{width:16px;height:16px;}
.social-icon:hover, .social-icon:focus-visible{border-color:#A9C2FF;color:#A9C2FF;background:rgba(169,194,255,0.08);}
footer .footer-links{display:flex;flex-wrap:wrap;gap:0.5rem 1.3rem;}
footer .footer-links a{font-size:0.86rem;text-decoration:none;color:rgba(255,255,255,0.72);}
footer .footer-links a:hover, footer .footer-links a:focus-visible{color:#fff;}
footer .footer-bottom{
  display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:0.7rem 1.5rem;
  padding:1.4rem 0;font-size:0.78rem;color:rgba(255,255,255,0.45);
}

/* ---------- contact form ---------- */
.contact-card{
  background:var(--glass-bg);
  backdrop-filter:blur(24px) saturate(180%); -webkit-backdrop-filter:blur(24px) saturate(180%);
  border:1px solid var(--glass-border);border-top-color:var(--glass-border-top);
  border-radius:20px;
  padding:1.7rem 1.7rem 1.9rem;
}
@media (prefers-reduced-transparency:reduce){
  .contact-card{background:#14161A;backdrop-filter:none;-webkit-backdrop-filter:none;}
}
.contact-row{display:flex;gap:0.9rem;}
@media (max-width:520px){.contact-row{flex-direction:column;gap:0;}}
.contact-field{margin-bottom:1.05rem;flex:1;min-width:0;}
.contact-field label{
  display:block;font-family:"IBM Plex Mono",monospace;font-size:0.68rem;
  letter-spacing:0.09em;text-transform:uppercase;color:rgba(255,255,255,0.42);
  margin-bottom:0.5rem;
}
.contact-field label .optional{text-transform:none;letter-spacing:0;opacity:0.7;font-family:"Work Sans",sans-serif;font-size:0.72rem;}
.contact-field input, .contact-field textarea{
  width:100%;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.14);
  border-radius:12px;padding:0.72rem 0.85rem;color:#fff;
  font-family:"Work Sans",sans-serif;font-size:16px;
  transition:border-color .15s ease, background .15s ease;
}
.contact-field input::placeholder, .contact-field textarea::placeholder{color:rgba(255,255,255,0.3);}
.contact-field input:focus, .contact-field textarea:focus{
  outline:none;border-color:#A9C2FF;background:rgba(255,255,255,0.09);
}
.contact-field textarea{resize:vertical;min-height:92px;line-height:1.5;font-family:"Work Sans",sans-serif;}
.contact-submit{
  display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;
  width:100%;background:#fff;color:#14161A;border:none;cursor:pointer;
  font-family:"Work Sans",sans-serif;font-weight:600;font-size:0.9rem;
  padding:0.8rem 1.35rem;border-radius:999px;
  transition:background .15s ease, transform 120ms var(--ease-out);
}
.contact-submit:hover, .contact-submit:focus-visible{background:#A9C2FF;}
.contact-submit:active{transform:scale(0.97);}
.contact-note{margin:0.85rem 0 0;font-size:0.76rem;line-height:1.5;color:rgba(255,255,255,0.4);}
.contact-note.is-success{color:#A9C2FF;}
.contact-note.is-error{color:#FFB4A9;}

/* Honeypot. Kept out of sight without display:none — some bots skip hidden
   fields, and a field they never fill in catches nothing. */
.hp-field{
  position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;
}

.contact-consent{
  display:flex;align-items:flex-start;gap:0.6rem;margin:0.2rem 0 1.15rem;
}
.contact-consent input[type="checkbox"]{
  flex:none;margin:0.15rem 0 0;width:16px;height:16px;
  accent-color:var(--color-accent);cursor:pointer;
}
.contact-consent label{
  font-size:0.76rem;line-height:1.5;color:rgba(255,255,255,0.5);cursor:pointer;
}
.contact-consent.is-invalid label{color:#FFB4A9;}

/* Field-level error marking, set by the submit handler. */
.contact-field.is-invalid input,
.contact-field.is-invalid textarea{border-color:#FF8A75;}

.contact-submit{position:relative;}
.contact-submit:disabled{cursor:default;opacity:0.65;}
.contact-submit .cs-spinner{
  display:none;flex:none;width:14px;height:14px;border-radius:50%;
  border:2px solid rgba(20,22,26,0.25);border-top-color:#14161A;
  animation:csSpin .7s linear infinite;
}
.contact-submit.is-busy .cs-spinner{display:block;}
@keyframes csSpin{to{transform:rotate(360deg);}}

/* Sent. The form is replaced by this rather than sitting there inviting a
   second identical submission. */
.contact-sent{text-align:center;padding:1.2rem 0.4rem 0.6rem;}
.contact-sent .tick{
  width:46px;height:46px;border-radius:50%;margin:0 auto 1rem;
  display:flex;align-items:center;justify-content:center;
  background:rgba(169,194,255,0.14);border:1.5px solid #A9C2FF;
}
.contact-sent .tick svg{width:20px;height:20px;stroke:#A9C2FF;fill:none;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;}
.contact-sent h3{
  font-family:"Bricolage Grotesque",sans-serif;font-weight:700;
  font-size:1.1rem;color:#fff;margin:0 0 0.5rem;
}
.contact-sent p{margin:0;font-size:0.86rem;line-height:1.6;color:rgba(255,255,255,0.6);}

/* ---------- footer contact details ---------- */
.footer-contact{list-style:none;margin:1.5rem 0 0;padding:0;display:grid;gap:0.75rem;}
.footer-contact li{display:flex;flex-wrap:wrap;align-items:baseline;gap:0.3rem 0.75rem;}
.footer-contact .fc-label{
  font-family:"IBM Plex Mono",monospace;font-size:0.63rem;letter-spacing:0.1em;
  text-transform:uppercase;color:rgba(255,255,255,0.38);min-width:8.5rem;
}
.footer-contact a{color:#fff;text-decoration:none;border-bottom:1px solid rgba(255,255,255,0.24);}
.footer-contact a:hover, .footer-contact a:focus-visible{color:#A9C2FF;border-color:#A9C2FF;}

/* ================================================================
   INTRO — "unlock the site"
   A cobalt lock screen with nothing on it but a keyhole. The key
   flies in, seats, turns 90 deg, the lock clicks, the panel splits
   like a door, and the key rises into its resting hero pose.

   Geometry notes (measured from the 700x646 key artwork):
     - the shaft axis sits at -37deg in the raw art, so rotate(-53deg)
       stands the key upright, bow up / tip down;
     - the tip (the knob at the end of the shaft) is at 3.571% 81.114%
       of the art box — that is the transform-origin, so every rotation
       pivots around the point sitting in the keyhole;
     - the last keyframe lands on a net -2deg, exactly where .key-art
       rests, so the hand-off to the hero key is seamless.
   JS measures the real hero key and feeds --lk-* so the hand-off is
   pixel-accurate at any viewport size. Never runs without JS or under
   prefers-reduced-motion — see the guard script below.
   ================================================================ */
:root{ --lk-dur:3.2s; }

/* No background of its own — the two door halves cover the viewport
   while they are closed, and anything painted here would sit between
   them and the page, so the doors would open onto it instead of the
   site. */
.lk-overlay{
  position:fixed;inset:0;z-index:9999;overflow:hidden;display:none;
  -webkit-tap-highlight-color:transparent;
}
html.lk-lock .lk-overlay{display:block;}
html.lk-lock{overscroll-behavior:none;}

/* The blue panel, split down the middle so it can open like a door.
   Each half holds a full-viewport-wide face, so the gradient and the
   keyhole line up seamlessly across the seam. */
.lk-doors{position:absolute;inset:0;z-index:1;}
.lk-door{position:absolute;top:0;bottom:0;width:50%;overflow:hidden;will-change:transform;}
.lk-door--l{left:0;}
/* The right half overlaps the seam by 1px and pulls its face back by
   the same 1px, so both faces still span the viewport exactly — the
   halves stay pixel-aligned and the subpixel hairline goes away. */
.lk-door--r{right:0;width:calc(50% + 1px);}
.lk-door-face{
  position:absolute;top:0;height:100%;width:200%;
  background:radial-gradient(112% 78% at 50% 46%,
    #4B76FF 0%, #2F5DFF 30%, #2049D8 55%, #14309B 78%, #0E2064 100%);
}
.lk-door--l .lk-door-face{left:0;}
.lk-door--r .lk-door-face{right:0;width:calc(200% - 2px);}

/* the keyhole itself: one path — circle over a tapered slot */
.lk-kh{
  position:absolute;left:50%;top:var(--lk-kh-top, 48%);
  width:calc(var(--lk-kh-d, 64px) * 1.0769);
  height:calc(var(--lk-kh-d, 64px) * 1.8846);
  transform:translate(-50%,-50%);
  overflow:visible;
  /* hidden until JS has measured and lk-run starts lkKhIn, otherwise
     it paints at the fallback size for a frame and then jumps */
  opacity:0;
}
.lk-kh path{fill:#05070E;stroke:rgba(255,255,255,0.20);stroke-width:0.55;}

/* thin light seam that flares along the split as the door gives */
.lk-seam{
  position:absolute;left:50%;top:0;bottom:0;width:2px;margin-left:-1px;z-index:2;
  background:linear-gradient(to bottom,
    rgba(169,194,255,0) 0%, rgba(226,236,255,0.95) 48%, rgba(169,194,255,0) 100%);
  opacity:0;pointer-events:none;
}

/* the click: a burst of light out of the keyhole */
.lk-flash{
  position:absolute;left:50%;top:var(--lk-hole-y, 50%);
  width:calc(var(--lk-kh-d, 64px) * 7);
  height:calc(var(--lk-kh-d, 64px) * 7);
  border-radius:50%;z-index:2;
  transform:translate(-50%,-50%) scale(.12);
  background:radial-gradient(circle,
    rgba(255,255,255,0.98) 0%, rgba(214,229,255,0.85) 8%,
    rgba(120,160,255,0.45) 20%, rgba(47,93,255,0.18) 38%,
    rgba(47,93,255,0) 60%);
  opacity:0;pointer-events:none;
}

/* The key. left/top/width are written by JS to sit exactly on top of
   the hero key, so transform:none == the hero key resting position. */
.lk-key{position:absolute;z-index:3;}
.lk-glow-wrap{
  position:absolute;top:50%;left:50%;
  width:160%;height:160%;
  transform:translate(-50%,-50%) translate(0px,0px) scale(1);
}
.lk-glow{
  width:100%;height:100%;border-radius:50%;opacity:0;
  background:radial-gradient(circle, rgba(47,93,255,0.55) 0%, rgba(47,93,255,0.22) 45%, rgba(47,93,255,0) 72%);
  filter:blur(6px);
}
.lk-key-art{
  position:relative;width:100%;
  transform-origin:3.571% 81.114%;
  will-change:transform;
}
.lk-key-art img{display:block;width:100%;height:auto;filter:drop-shadow(0 18px 30px rgba(5,8,20,0.55));}

@keyframes lkKey{
  /* sweeping in from off-screen, low and to the right */
  0%{
    opacity:0;
    transform:translate(calc(var(--lk-tx,0px) + 54vw), calc(var(--lk-ty,0px) + 26vh)) rotate(-62deg) scale(calc(var(--lk-s,1) * .42)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.22,.62,.36,1);
  }
  4%{ opacity:1; }
  16%{
    transform:translate(calc(var(--lk-tx,0px) + 24vw), calc(var(--lk-ty,0px) - 4vh)) rotate(-26deg) scale(calc(var(--lk-s,1) * .82)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.3,0,.18,1);
  }
  /* poised over the keyhole, upright */
  29.5%{
    transform:translate(var(--lk-tx,0px), calc(var(--lk-ty,0px) - var(--lk-d,220px) * .40)) rotate(0deg) scale(calc(var(--lk-s,1) * 1.05)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.4,0,.55,1);
  }
  36%{
    transform:translate(var(--lk-tx,0px), calc(var(--lk-ty,0px) - var(--lk-d,220px) * .34)) rotate(0deg) scale(calc(var(--lk-s,1) * 1.03)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.6,0,.3,1);
  }
  /* pushed home, with a small recoil as it seats */
  44.5%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(0deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.2,.8,.3,1);
  }
  47.5%{
    transform:translate(var(--lk-tx,0px), calc(var(--lk-ty,0px) - var(--lk-d,220px) * .014)) rotate(0deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.4,0,.4,1);
  }
  50.5%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(0deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.35,0,.65,1);
  }
  /* wind-up against the tumblers, then the turn */
  55.5%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(-9deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:linear;
  }
  58.5%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(-9deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.66,0,.16,1);
  }
  68%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(97deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.3,0,.35,1);
  }
  /* the click — overshoot, snap back, settle */
  71%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(87deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.35,0,.3,1);
  }
  74%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(90deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.5,0,.2,1);
  }
  76%{
    transform:translate(var(--lk-tx,0px), var(--lk-ty,0px)) rotate(90deg) scale(var(--lk-s,1)) rotate(-53deg);
    animation-timing-function:cubic-bezier(.34,.02,.2,1);
  }
  /* Withdraw and settle into the hero pose — net -2deg, translate ~0.
     This lands by 92% so the key is already home and out of the way
     before the hero copy fades in underneath it. */
  92%,100%{
    opacity:1;
    transform:translate(calc(var(--lk-w,220px) * .0103), calc(var(--lk-w,220px) * .016)) rotate(51deg) scale(1) rotate(-53deg);
  }
}

@keyframes lkGlowMove{
  0%,44.5%{transform:translate(-50%,-50%) translate(var(--lk-gx,0px), var(--lk-gy,0px)) scale(calc(var(--lk-s,1) * .30));}
  50.5%{transform:translate(-50%,-50%) translate(var(--lk-gx,0px), var(--lk-gy,0px)) scale(calc(var(--lk-s,1) * .40));}
  74%{transform:translate(-50%,-50%) translate(var(--lk-gx,0px), var(--lk-gy,0px)) scale(calc(var(--lk-s,1) * .52));}
  92%,100%{transform:translate(-50%,-50%) translate(0px,0px) scale(1);}
}
@keyframes lkGlowFade{
  0%,40%{opacity:0;}
  46%{opacity:0.9;}
  55%{opacity:0.45;}
  71%{opacity:1;}
  82%{opacity:0.7;}
  92%,100%{opacity:0.55;}
}

@keyframes lkKhIn{
  0%{opacity:0;transform:translate(-50%,-50%) scale(.55);}
  100%{opacity:1;transform:translate(-50%,-50%) scale(1);}
}
@keyframes lkKhGlow{
  0%,42%{filter:drop-shadow(0 0 0 rgba(169,194,255,0)) drop-shadow(0 0 0 rgba(47,93,255,0));}
  46%{filter:drop-shadow(0 0 10px rgba(169,194,255,0.85)) drop-shadow(0 0 26px rgba(47,93,255,0.70));}
  55%{filter:drop-shadow(0 0 5px rgba(169,194,255,0.40)) drop-shadow(0 0 14px rgba(47,93,255,0.35));}
  71%{filter:drop-shadow(0 0 22px rgba(226,236,255,1)) drop-shadow(0 0 58px rgba(120,160,255,0.95));}
  100%{filter:drop-shadow(0 0 10px rgba(169,194,255,0.5)) drop-shadow(0 0 30px rgba(47,93,255,0.5));}
}

@keyframes lkDoorL{ 0%{transform:translateX(0);} 100%{transform:translateX(-101%);} }
@keyframes lkDoorR{ 0%{transform:translateX(0);} 100%{transform:translateX(101%);} }
@keyframes lkShake{
  0%,70%{transform:translate(0,0);}
  71.5%{transform:translate(-3px,1px);}
  73%{transform:translate(2px,-1px);}
  74.5%{transform:translate(-1px,0);}
  76%,100%{transform:translate(0,0);}
}
@keyframes lkFlash{
  0%,68%{opacity:0;transform:translate(-50%,-50%) scale(.12);}
  72%{opacity:1;transform:translate(-50%,-50%) scale(.85);}
  100%{opacity:0;transform:translate(-50%,-50%) scale(2.4);}
}
@keyframes lkSeam{
  0%,70%{opacity:0;transform:scaleX(1);}
  74%{opacity:1;transform:scaleX(1);}
  100%{opacity:0;transform:scaleX(7);}
}

.lk-overlay.lk-run .lk-key-art{animation:lkKey var(--lk-dur) both;}
.lk-overlay.lk-run .lk-glow-wrap{animation:lkGlowMove var(--lk-dur) both;}
.lk-overlay.lk-run .lk-glow{animation:lkGlowFade var(--lk-dur) both;}
.lk-overlay.lk-run .lk-kh{
  animation:lkKhIn calc(var(--lk-dur) * .25) cubic-bezier(.2,.8,.3,1) both,
            lkKhGlow var(--lk-dur) both;
}
.lk-overlay.lk-run .lk-doors{animation:lkShake var(--lk-dur) both;}
.lk-overlay.lk-run .lk-flash{animation:lkFlash var(--lk-dur) both;}
.lk-overlay.lk-run .lk-seam{animation:lkSeam var(--lk-dur) both;}
.lk-overlay.lk-run .lk-door--l{
  animation:lkDoorL calc(var(--lk-dur) * .225) cubic-bezier(.7,0,.16,1) calc(var(--lk-dur) * .76) both;
}
.lk-overlay.lk-run .lk-door--r{
  animation:lkDoorR calc(var(--lk-dur) * .225) cubic-bezier(.7,0,.16,1) calc(var(--lk-dur) * .76) both;
}

/* The real hero key stays out of sight until the hand-off, then picks
   up at keyFloat 0% — the pose the loader key just finished on —
   instead of replaying its own fly-in. */
html.lk-lock .key-art, html.lk-lock .key-glow-wrap{opacity:0;animation:none;}
/* Stop the ambient glow's own loop too. Otherwise it keeps cycling
   behind the lock screen and lk-done resumes it mid-pulse, so the glow
   pops the instant the hand-off happens. Suppressed here, lk-done
   starts it fresh at keyGlowPulse 0% — opacity .55, exactly where the
   loader glow finishes. */
html.lk-lock .key-glow-ambient{animation:none;}
html.lk-done .key-art{animation:keyFloat 8s ease-in-out infinite;}
html.lk-done .key-glow-ambient{animation:keyGlowPulse 6s ease-in-out infinite;}

/* hero copy and nav arrive behind the opening door */
@keyframes lkRise{ 0%{opacity:0;transform:translateY(16px);} 100%{opacity:1;transform:none;} }
@keyframes lkFade{ 0%{opacity:0;} 100%{opacity:1;} }
html.lk-lock .hero-center > *, html.lk-lock .nav-bar{opacity:0;}
html.lk-intro .hero-center > *{animation:lkRise calc(var(--lk-dur) * .20) cubic-bezier(.2,.75,.25,1) both;}
html.lk-intro .hero-center > *:nth-child(1){animation-delay:calc(var(--lk-dur) * .885);}
html.lk-intro .hero-center > *:nth-child(2){animation-delay:calc(var(--lk-dur) * .903);}
html.lk-intro .hero-center > *:nth-child(3){animation-delay:calc(var(--lk-dur) * .921);}
html.lk-intro .hero-center > *:nth-child(4){animation-delay:calc(var(--lk-dur) * .939);}
html.lk-intro .hero-center > *:nth-child(5){animation-delay:calc(var(--lk-dur) * .957);}
html.lk-intro .hero-center > *:nth-child(6){animation-delay:calc(var(--lk-dur) * .975);}
html.lk-intro .nav-bar{animation:lkFade calc(var(--lk-dur) * .20) ease calc(var(--lk-dur) * .995) both;}

/* click / scroll / keypress to skip */
.lk-overlay.lk-skip{display:block !important;opacity:0;pointer-events:none;transition:opacity .3s ease;}
