/* =========================================================
   demo.css  —  Shared styles for all 8 category demo sites
   Portfolio · Mayank Khandelwal
   ========================================================= */

/* ── TOKENS ──
   The dark palette is the default and is what every demo ships in. Light is a
   second full palette selected by data-theme="light" on <html> — see LIGHT
   THEME below. Two rules make that switch possible and both matter:

   • --accent-ink is the accent used as TEXT. On the dark ground the accent
     itself is legible, so it is just var(--accent). On paper, #C9A84C over
     #FBF8F3 is about 2.2:1 and fails outright, so each category theme needs a
     darkened ink of its own. Anywhere the accent paints type it must be
     --accent-ink, never --accent.
   • --on-accent is whatever sits ON an accent fill. That used to be
     var(--bg), which is correct while --bg is near-black and becomes white
     text on gold the moment --bg is paper.

   Everything from --surface-bar down was a literal rgba() somewhere below.
   The values here are the ones that were already in the file. */
:root {
  --accent:      #C9A84C;
  --accent-2:    #E8C977;
  --accent-dim:  rgba(201,168,76,.12);
  --accent-glow: rgba(201,168,76,.16);
  --accent-ink:  var(--accent);
  --on-accent:   var(--bg);
  --bg:          #0A0F1E;
  --bg-2:        #0E1527;
  --bg-card:     rgba(14,21,39,.85);
  --text:        #F4EFE6;
  --text-1:      #F4EFE6;
  --text-2:      #C8C3BA;
  --text-3:      #8A8578;
  --line:        rgba(244,239,230,.08);
  --line-a:      rgba(201,168,76,.18);

  /* Chrome and raised surfaces */
  --surface-bar:     rgba(8,12,24,.92);
  --surface-nav:     rgba(10,15,30,.88);
  --surface-nav-up:  rgba(10,15,30,.97);
  --surface-menu:    #0B1020;
  --surface-sheet:   rgba(10,15,30,.98);
  --surface-strip:   rgba(14,21,39,.96);
  --surface-strip-2: rgba(14,21,39,.92);
  --surface-glass:   rgba(10,15,30,.92);
  --surface-chip:    rgba(10,15,30,.82);
  --surface-opt:     #0E1527;

  /* Hairlines, highlights and texture */
  --edge-hi:    rgba(255,255,255,.04);
  --edge-hi-2:  rgba(255,255,255,.035);
  --hairline:   rgba(244,239,230,.045);
  --hairline-2: rgba(244,239,230,.06);
  --grid-line:  rgba(244,239,230,.015);
  --sheen:      rgba(244,239,230,.075);
  --mesh-op:    .5;
  --scrim:      rgba(0,0,0,.55);   /* photo foot, ties an image to the ground */
  --scrim-soft: rgba(0,0,0,.45);
  --r:           12px;
  --r-sm:        8px;
  --r-lg:        20px;
  --shadow:      0 8px 32px rgba(0,0,0,.45);
  --preview-h:   44px;
  --f-serif:     'Playfair Display',Georgia,serif;
  --f-sans:      'DM Sans',system-ui,sans-serif;
  --f-mono:      'JetBrains Mono',ui-monospace,monospace;
  --nav-h:       68px;
  --max:         1280px;
  --gutter:      clamp(20px,5vw,64px);
}

/* ── CATEGORY THEMES ── */
.theme-ember   { --accent:#D9823C; --accent-2:#F0A96B; --accent-dim:rgba(217,130,60,.12); --accent-glow:rgba(217,130,60,.18); }
.theme-mint    { --accent:#4DA99A; --accent-2:#7ECFC2; --accent-dim:rgba(77,169,154,.12);  --accent-glow:rgba(77,169,154,.15);  }
.theme-plum    { --accent:#9B59B6; --accent-2:#C07FD8; --accent-dim:rgba(155,89,182,.12);  --accent-glow:rgba(155,89,182,.15);  }
.theme-pearl   { --accent:#C9A07A; --accent-2:#E8C9A0; --accent-dim:rgba(201,160,122,.12); --accent-glow:rgba(201,160,122,.18); }
.theme-sage    { --accent:#6B9E7A; --accent-2:#8FBA8C; --accent-dim:rgba(107,158,122,.12); --accent-glow:rgba(107,158,122,.15); }
.theme-gold    { --accent:#C9A84C; --accent-2:#E8C977; --accent-dim:rgba(201,168,76,.12);  --accent-glow:rgba(201,168,76,.18);  }
.theme-saffron { --accent:#E8A13E; --accent-2:#F5C76F; --accent-dim:rgba(232,161,62,.12);  --accent-glow:rgba(232,161,62,.15);  }
.theme-cocoa   { --accent:#B8895A; --accent-2:#D4A87A; --accent-dim:rgba(184,137,90,.12);  --accent-glow:rgba(184,137,90,.18);  }


/* ── LIGHT THEME ──
   Selected by data-theme="light" on <html>; the control lives in the Netloom
   preview bar and demo.js remembers the choice across the demo's pages.

   Dark stays the default deliberately — it is the studio look and it is what a
   prospect should see first. Following prefers-color-scheme would open the
   demo in light for anyone whose laptop is set that way, and they would never
   see the register the site is actually selling.

   The ground is warm paper, not white, and the values are the same ones
   commerce/store.css already uses, so the light demos and the store read as
   one studio rather than two.

   Attribute selectors outrank a bare :root, so this block wins over the token
   defaults above AND over the depth tokens defined much further down the file,
   whatever the source order. */
:root[data-theme="light"] {
  --bg:          #FBF8F3;
  --bg-2:        #F4EEE4;
  --bg-card:     rgba(255,255,255,.86);
  --text:        #1A1613;
  --text-1:      #1A1613;
  --text-2:      #4B4239;
  --text-3:      #837A6E;
  --line:        rgba(26,22,19,.11);
  --on-accent:   #14100B;

  --surface-bar:     rgba(255,253,249,.90);
  --surface-nav:     rgba(251,248,243,.86);
  --surface-nav-up:  rgba(251,248,243,.97);
  --surface-menu:    #FFFDF9;
  --surface-sheet:   rgba(251,248,243,.98);
  --surface-strip:   rgba(244,238,228,.96);
  --surface-strip-2: rgba(244,238,228,.92);
  --surface-glass:   rgba(251,248,243,.92);
  --surface-chip:    rgba(255,253,249,.88);
  --surface-opt:     #FFFDF9;

  --edge-hi:    rgba(26,22,19,.030);
  --edge-hi-2:  rgba(26,22,19,.025);
  --hairline:   rgba(26,22,19,.055);
  --hairline-2: rgba(26,22,19,.085);
  --grid-line:  rgba(26,22,19,.035);
  --sheen:      rgba(26,22,19,.045);
  --mesh-op:    .34;
  /* A wash heavy enough to seat a photo on near-black reads as a bruise on
     paper. The caption scrim is deliberately not softened here — white
     caption text has to stay legible over an arbitrary photograph, and that
     is the same problem in both themes. */
  --scrim:      rgba(38,30,20,.26);
  --scrim-soft: rgba(38,30,20,.20);

  /* A shadow on paper is a fraction of the weight it is on near-black, and it
     is warm rather than neutral. The top hairline that sells a raised surface
     in the dark inverts: white, not a light tint. */
  --shadow: 0 8px 28px rgba(38,30,20,.10);
  --e1:   0 1px 2px rgba(38,30,20,.05), 0 3px 8px -2px rgba(38,30,20,.055), 0 8px 20px -8px rgba(38,30,20,.09);
  --e2:   0 1px 2px rgba(38,30,20,.055), 0 6px 14px -4px rgba(38,30,20,.075), 0 18px 40px -12px rgba(38,30,20,.13);
  --e3:   0 2px 4px rgba(38,30,20,.06), 0 12px 28px -6px rgba(38,30,20,.10), 0 34px 70px -18px rgba(38,30,20,.17);
  --edge: inset 0 1px 0 rgba(255,255,255,.75);

  color-scheme: light;
}

/* Per-category ink for light. Each is its own accent walked down in lightness
   until it clears 4.5:1 on #FBF8F3, with the hue held so a salon still reads
   plum and a clinic still reads mint. --line-a and --accent-dim also step up:
   an 18% tint that separates cleanly from near-black disappears on paper. */
:root[data-theme="light"] .theme-ember   { --accent-ink:#A04B15; --line-a:rgba(217,130,60,.32);  --accent-dim:rgba(217,130,60,.14);  --accent-glow:rgba(217,130,60,.13)  }
:root[data-theme="light"] .theme-mint    { --accent-ink:#26685E; --line-a:rgba(77,169,154,.34);  --accent-dim:rgba(77,169,154,.14);  --accent-glow:rgba(77,169,154,.12)  }
:root[data-theme="light"] .theme-plum    { --accent-ink:#6E3184; --line-a:rgba(155,89,182,.32);  --accent-dim:rgba(155,89,182,.13);  --accent-glow:rgba(155,89,182,.11)  }
:root[data-theme="light"] .theme-pearl   { --accent-ink:#8A5A33; --line-a:rgba(201,160,122,.36); --accent-dim:rgba(201,160,122,.16); --accent-glow:rgba(201,160,122,.14) }
:root[data-theme="light"] .theme-sage    { --accent-ink:#3A6647; --line-a:rgba(107,158,122,.34); --accent-dim:rgba(107,158,122,.15); --accent-glow:rgba(107,158,122,.12) }
:root[data-theme="light"] .theme-gold    { --accent-ink:#846718; --line-a:rgba(201,168,76,.36);  --accent-dim:rgba(201,168,76,.16);  --accent-glow:rgba(201,168,76,.14)  }
:root[data-theme="light"] .theme-saffron { --accent-ink:#8E5C0F; --line-a:rgba(232,161,62,.36);  --accent-dim:rgba(232,161,62,.16);  --accent-glow:rgba(232,161,62,.13)  }
:root[data-theme="light"] .theme-cocoa   { --accent-ink:#77502D; --line-a:rgba(184,137,90,.36);  --accent-dim:rgba(184,137,90,.16);  --accent-glow:rgba(184,137,90,.14)  }
/* A page with no category class still needs an ink that is not raw gold. */
:root[data-theme="light"] { --accent-ink:#846718; --line-a:rgba(201,168,76,.36); --accent-dim:rgba(201,168,76,.16); --accent-glow:rgba(201,168,76,.14) }

/* ── RESET ── */
*,*::before,*::after { box-sizing:border-box; margin:0; padding:0 }
html { scroll-behavior:smooth; color-scheme:dark }
body {
  background:var(--bg); color:var(--text);
  font-family:var(--f-sans); line-height:1.65;
  overflow-x:hidden; -webkit-font-smoothing:antialiased;
}
a { color:inherit; text-decoration:none }
img { max-width:100%; display:block }
::selection { background:var(--accent); color:var(--on-accent) }

/* Repainting every surface at once looks like a smear if each one eases
   independently, so transitions are suppressed for one frame while the
   attribute flips. demo.js adds and removes .ntl-theming. */
html.ntl-theming, html.ntl-theming *, html.ntl-theming *::before, html.ntl-theming *::after {
  transition:none !important; animation-duration:.001s !important;
}

/* ── AMBIENT GLOW ── */
body::before {
  content:''; position:fixed; inset:0; pointer-events:none; z-index:0;
  background:
    radial-gradient(1000px 600px at 80% -5%, var(--accent-glow), transparent 55%),
    radial-gradient(700px 400px at -5% 65%, var(--accent-glow), transparent 60%);
  opacity:var(--mesh-op);
}
body::after {
  content:''; position:fixed; inset:0; pointer-events:none; z-index:0;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size:60px 60px;
  mask-image:radial-gradient(ellipse at 50% 20%, black, transparent 70%);
}

/* ── PREVIEW BANNER ── */
.preview-bar {
  position:fixed; top:0; left:0; right:0; z-index:2000;
  height:var(--preview-h);
  display:flex; align-items:center; gap:14px;
  padding:0 16px;
  background:var(--surface-bar);
  backdrop-filter:blur(14px) saturate(140%);
  border-bottom:1px solid var(--line-a);
  font-family:var(--f-mono); font-size:10.5px; letter-spacing:.1em;
  color:var(--text-3);
}
.preview-bar a { color:var(--accent-ink); transition:opacity .2s }
/* The mark's two uprights are a hardcoded fill="#E8E2D6" in every page's
   markup — correct on near-black, invisible on paper. A presentation
   attribute loses to any author rule, so this retints it in both themes
   without touching 36 files. */
.pb-mark rect { fill:var(--text) }
.preview-bar a:hover { opacity:.8 }
.preview-bar .sep { opacity:.3 }
.pb-left { display:flex; align-items:center; gap:10px; white-space:nowrap }
.pb-badge {
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 9px; border-radius:99px;
  background:var(--accent-dim); border:1px solid var(--line-a);
  color:var(--accent-ink); font-size:9.5px; letter-spacing:.14em; text-transform:uppercase;
}
.pb-badge::before {
  content:""; width:5px; height:5px; border-radius:50%;
  background:var(--accent); box-shadow:0 0 0 0 rgba(201,168,76,.6);
  animation:pbPulse 2.4s infinite;
}
@keyframes pbPulse{
  0%{box-shadow:0 0 0 0 rgba(201,168,76,.55)}
  70%{box-shadow:0 0 0 7px rgba(201,168,76,0)}
  100%{box-shadow:0 0 0 0 rgba(201,168,76,0)}
}
.pb-biz {
  display:inline-flex; align-items:center;
  padding:4px 10px; border-radius:99px;
  background:var(--accent-dim); border:1px solid var(--line-a);
  color:var(--accent-ink); font-size:9.5px; letter-spacing:.12em; text-transform:uppercase;
  white-space:nowrap; max-width:38vw; overflow:hidden; text-overflow:ellipsis;
}
@media (max-width:720px){ .pb-biz{ display:none } }
.pb-item-flag .pb-item-name{ color:var(--accent-ink) }
.pb-new{
  display:inline-block; margin-left:6px; padding:2px 6px; border-radius:99px;
  background:var(--accent); color:var(--on-accent);
  font-size:8px; letter-spacing:.1em; text-transform:uppercase; vertical-align:1px;
}
.pb-spacer { flex:1 }

/* ── Industry switcher ── */
.pb-switch { position:relative }
.pb-switch-btn {
  display:inline-flex; align-items:center; gap:8px;
  height:26px; padding:0 12px;
  border-radius:99px;
  border:1px solid var(--line-a);
  background:var(--edge-hi);
  color:var(--text-1);
  font-family:var(--f-mono); font-size:10px; letter-spacing:.1em;
  cursor:pointer; white-space:nowrap;
  transition:border-color .2s, background .2s;
}
.pb-switch-btn:hover { border-color:var(--accent-ink); background:var(--accent-dim) }
.pb-switch-btn .chev { transition:transform .25s; font-size:8px; opacity:.7 }
.pb-switch.open .pb-switch-btn .chev { transform:rotate(180deg) }
.pb-menu {
  position:absolute; top:calc(100% + 8px); right:0;
  width:290px; padding:7px;
  border-radius:14px;
  background:var(--surface-menu);
  background-image:linear-gradient(180deg, var(--edge-hi-2), transparent 40%);
  border:1px solid var(--line-a);
  box-shadow:var(--e3);
  opacity:0; visibility:hidden; transform:translateY(-8px) scale(.98);
  transition:opacity .22s, transform .22s, visibility .22s;
  max-height:min(72vh,470px); overflow-y:auto; overscroll-behavior:contain;
}
.pb-switch.open .pb-menu { opacity:1; visibility:visible; transform:none }
.pb-menu-head {
  padding:9px 11px 7px; font-size:9px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--text-3); opacity:.65;
}
.pb-item {
  display:flex; align-items:center; gap:11px;
  padding:9px 11px; border-radius:9px;
  color:var(--text-1) !important; text-decoration:none;
  transition:background .16s;
}
.pb-item:hover { background:var(--accent-dim); opacity:1 !important }
.pb-item.current { background:var(--accent-glow) }
.pb-item i {
  width:26px; height:26px; flex:none;
  display:grid; place-items:center; border-radius:7px;
  background:var(--accent-dim); color:var(--accent-ink); font-size:11px;
}
.pb-item-txt { display:flex; flex-direction:column; gap:2px; min-width:0 }
.pb-item-name {
  font-family:var(--f-sans); font-size:12.5px; font-weight:500;
  letter-spacing:0; color:var(--text-1);
}
.pb-item-biz {
  font-size:9.5px; letter-spacing:.06em; color:var(--text-3);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pb-cta {
  display:inline-flex; align-items:center; gap:7px;
  height:26px; padding:0 13px; border-radius:99px;
  background:var(--accent); color:var(--on-accent) !important;
  font-size:10px; font-weight:600; letter-spacing:.08em;
  white-space:nowrap; transition:transform .2s, box-shadow .2s;
}
.pb-cta:hover { transform:translateY(-1px); box-shadow:0 6px 18px -4px var(--accent-glow); opacity:1 !important }

@media (max-width:760px){
  .pb-left .pb-tagline, .pb-left .sep { display:none }
  .preview-bar { gap:9px; padding:0 11px }
  .pb-menu { width:min(88vw,290px) }
  .pb-cta span { display:none }
}


/* ── Light / dark control (preview bar) ──
   Injected by demo.js rather than written into all 36 demo pages. A two-state
   segmented control, not a single toggle: a prospect should be able to SEE
   that both registers are on offer, which a lone moon icon does not say. */
.pb-theme {
  display:inline-flex; align-items:center; gap:2px;
  height:26px; padding:2px;
  border:1px solid var(--line-a); border-radius:99px;
  background:var(--edge-hi);
}
.pb-theme-btn {
  display:inline-grid; place-items:center;
  width:30px; height:20px; padding:0;
  border:0; border-radius:99px; background:transparent;
  color:var(--text-3); font-size:10px; line-height:1;
  cursor:pointer; transition:background .18s, color .18s;
  -webkit-appearance:none; appearance:none;
}
.pb-theme-btn:hover { color:var(--accent-ink) }
.pb-theme-btn[aria-pressed="true"] {
  background:var(--accent); color:var(--on-accent);
}
.pb-theme-btn:focus-visible { outline:2px solid var(--accent-ink); outline-offset:2px }
/* The label is for the pitch, not for the visitor — first thing to go. */
.pb-theme-lbl {
  font-family:var(--f-mono); font-size:9px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--text-3); margin-right:2px;
}
@media (max-width:900px){ .pb-theme-lbl { display:none } }

/* ── NAVIGATION ── */
.nav {
  position:fixed; top:var(--preview-h); left:0; right:0; z-index:1000;
  height:var(--nav-h);
  display:flex; align-items:center;
  padding:0 var(--gutter);
  background:var(--surface-nav); backdrop-filter:blur(16px);
  border-bottom:1px solid var(--line);
  transition:background .3s;
}
.nav.scrolled { background:var(--surface-nav-up) }
.nav-inner {
  max-width:var(--max); margin:0 auto; width:100%;
  display:flex; align-items:center; justify-content:space-between;
}
.nav-logo {
  font-family:var(--f-serif); font-size:22px; font-weight:600;
  letter-spacing:-.01em;
}
.nav-logo em { color:var(--accent-ink); font-style:italic }
.nav-links {
  display:flex; align-items:center; gap:28px; list-style:none;
}
.nav-links a {
  font-size:13px; font-weight:500; color:var(--text-2);
  transition:color .3s; letter-spacing:.01em;
}
.nav-links a:hover,.nav-links a.active { color:var(--accent-ink) }
.nav-cta {
  background:var(--accent) !important; color:var(--on-accent) !important;
  padding:8px 20px; border-radius:999px;
  font-weight:700 !important; font-size:12px !important;
  letter-spacing:.04em; transition:opacity .3s !important;
}
.nav-cta:hover { opacity:.85 !important; color:var(--on-accent) !important }
.nav-toggle {
  display:none; flex-direction:column; gap:5px;
  cursor:pointer; padding:8px; background:none; border:none; color:inherit;
}
.nav-toggle span {
  display:block; width:22px; height:2px;
  background:var(--text); border-radius:2px; transition:all .3s;
}

/* ── LAYOUT HELPERS ── */
.wrap { max-width:var(--max); margin:0 auto; padding:0 var(--gutter); position:relative; z-index:1 }
.section { padding:clamp(60px,8vw,120px) 0; position:relative; z-index:1 }
.section-alt { background:var(--bg-2); border-top:1px solid var(--line); border-bottom:1px solid var(--line) }
.text-center { text-align:center }
.text-center .section-sub { margin-left:auto; margin-right:auto }

/* ── TYPOGRAPHY ── */
.eyebrow {
  font-family:var(--f-mono); font-size:10px; letter-spacing:.28em; text-transform:uppercase;
  color:var(--accent-ink); margin-bottom:16px;
  display:flex; align-items:center; gap:12px;
}
.eyebrow::after { content:''; flex:0 0 50px; height:1px; background:var(--line-a) }
.text-center .eyebrow { justify-content:center }
.text-center .eyebrow::after { display:none }

.section-title {
  font-family:var(--f-serif); font-size:clamp(28px,3.5vw,48px);
  font-weight:500; line-height:1.1; letter-spacing:-.01em; margin-bottom:16px;
}
.section-title em { font-style:italic; color:var(--accent-ink) }
.section-sub {
  font-size:15px; color:var(--text-2); max-width:60ch; line-height:1.7; margin-bottom:48px;
}

/* ── PAGE HEADER (inner pages) ── */
.page-header {
  padding:calc(var(--nav-h) + var(--preview-h) + 64px) var(--gutter) 64px;
  text-align:center; border-bottom:1px solid var(--line);
  position:relative; z-index:1;
}
.page-header .eyebrow { justify-content:center }
.page-header .eyebrow::after { display:none }
.page-header h1 {
  font-family:var(--f-serif); font-size:clamp(32px,4.5vw,64px);
  font-weight:500; letter-spacing:-.015em; margin-bottom:16px;
}
.page-header h1 em { font-style:italic; color:var(--accent-ink) }
.page-header p { font-size:16px; color:var(--text-2); max-width:55ch; margin:0 auto; line-height:1.7 }

/* ── HERO ── */
.hero {
  min-height:100vh;
  display:flex; align-items:center;
  padding:calc(var(--nav-h) + var(--preview-h) + 60px) var(--gutter) 80px;
  position:relative; overflow:hidden;
}
.hero-inner {
  max-width:var(--max); margin:0 auto; width:100%;
  display:grid; grid-template-columns:1.1fr 1fr; gap:64px; align-items:center;
}

/* Jewellery / ecommerce / realestate use .hero-content + .hero-visual instead of
   .hero-inner. Those two classes had no rules at all, so .hero-visual collapsed to
   zero width and its SVG art never showed. Mirror the .hero-inner grid here. */
.hero:has(> .hero-visual) {
  display:grid; grid-template-columns:1.1fr 1fr; gap:64px; align-items:center;
  max-width:calc(var(--max) + var(--gutter) * 2); margin:0 auto; width:100%;
}
.hero-content { min-width:0 }
.hero-visual {
  min-width:0; width:100%;
  border-radius:var(--r-lg); overflow:hidden;
  border:1px solid var(--line);
  box-shadow:var(--shadow);
  background:var(--bg-2);
}
.hero-visual > svg { display:block; width:100%; height:auto }
.hero-eyebrow {
  font-family:var(--f-mono); font-size:10px; letter-spacing:.3em; text-transform:uppercase;
  color:var(--accent-ink); margin-bottom:24px;
  display:flex; align-items:center; gap:12px;
}
.hero-eyebrow::before { content:''; display:block; width:36px; height:1px; background:var(--accent) }
.hero h1 {
  font-family:var(--f-serif); font-size:clamp(40px,5.5vw,76px);
  font-weight:500; line-height:1.03; letter-spacing:-.015em; margin-bottom:22px;
}
.hero h1 em { font-style:italic; color:var(--accent-ink) }
.hero-sub {
  font-size:clamp(15px,1.5vw,17px); color:var(--text-2);
  max-width:50ch; margin-bottom:36px; line-height:1.75;
}
.hero-meta {
  display:flex; gap:28px; margin-bottom:36px; flex-wrap:wrap;
  padding:20px 0; border-top:1px solid var(--line); border-bottom:1px solid var(--line);
}
.hero-meta-item { display:flex; flex-direction:column; gap:4px }
.hero-meta-item .label {
  font-family:var(--f-mono); font-size:9px; letter-spacing:.2em; text-transform:uppercase; color:var(--text-3)
}
.hero-meta-item .value { font-size:14px; font-weight:600 }

/* Hero visual */
.hero-art {
  border-radius:var(--r-lg); overflow:hidden;
  aspect-ratio:4/5; background:var(--bg-2); border:1px solid var(--line);
  position:relative; z-index:2;
}
.hero-art svg { width:100%; height:100% }
.float-tag {
  position:absolute; bottom:20px; left:20px; right:20px;
  display:flex; flex-direction:column; gap:8px;
}
.float-chip {
  display:inline-flex; align-items:center; gap:8px;
  padding:8px 14px; border-radius:999px;
  background:var(--surface-chip); backdrop-filter:blur(8px);
  border:1px solid var(--line-a); font-size:12px; width:max-content;
  animation:chipFloat 4s ease-in-out infinite;
}
.float-chip:nth-child(2) { animation-delay:2s }
@keyframes chipFloat { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-6px)} }

/* ── BUTTONS ── */
.btns { display:flex; gap:14px; flex-wrap:wrap }
.btn {
  display:inline-flex; align-items:center; gap:8px;
  padding:13px 28px; border-radius:999px;
  font-size:13px; font-weight:600; font-family:var(--f-sans);
  transition:all .3s; cursor:pointer; border:none; letter-spacing:.02em;
}
.btn-primary { background:var(--accent); color:var(--on-accent) }
.btn-primary:hover { opacity:.85; transform:translateY(-1px) }
.btn-ghost { background:transparent; color:var(--text); border:1px solid var(--line-a) }
.btn-ghost:hover { border-color:var(--accent); color:var(--accent-ink) }
.btn-sm { padding:9px 20px; font-size:12px }

/* ── GRIDS ── */
.grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:24px }
.grid-3 { display:grid; grid-template-columns:repeat(3,1fr); gap:24px }
.grid-4 { display:grid; grid-template-columns:repeat(4,1fr); gap:24px }

/* ── CARDS ── */
.card {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; transition:transform .3s, border-color .3s;
}
.card:hover { transform:translateY(-4px); border-color:var(--line-a) }
.card-thumb {
  aspect-ratio:16/10; overflow:hidden; background:var(--bg-2); position:relative;
}
.card-thumb svg { width:100%; height:100%; display:block }
.card-body { padding:24px }
.card-tag { font-family:var(--f-mono); font-size:9px; letter-spacing:.2em; text-transform:uppercase; color:var(--accent-ink); margin-bottom:8px }
.card-title { font-family:var(--f-serif); font-size:20px; font-weight:500; margin-bottom:8px; line-height:1.25 }
.card-desc { font-size:14px; color:var(--text-2); line-height:1.65; margin-bottom:16px }
.card-price { font-family:var(--f-serif); font-size:22px; color:var(--accent-ink) }
.card-meta { font-size:12px; color:var(--text-3) }
.card-footer { padding:16px 24px; border-top:1px solid var(--line); display:flex; justify-content:space-between; align-items:center }

/* ── FEATURES ── */
.features { display:grid; grid-template-columns:repeat(3,1fr); gap:24px }
.feature {
  padding:32px; background:var(--bg-card); border:1px solid var(--line);
  border-radius:var(--r); transition:border-color .3s;
}
.feature:hover { border-color:var(--line-a) }
.feature-icon {
  width:46px; height:46px; border-radius:10px; background:var(--accent-dim);
  display:flex; align-items:center; justify-content:center;
  color:var(--accent-ink); font-size:18px; margin-bottom:20px;
}
.feature h4 { font-family:var(--f-serif); font-size:19px; font-weight:500; margin-bottom:10px }
.feature p { font-size:14px; color:var(--text-2); line-height:1.65 }

/* ── STATS STRIP ── */
.stats {
  display:grid; grid-template-columns:repeat(4,1fr);
  gap:1px; background:var(--line); border:1px solid var(--line);
  border-radius:var(--r); overflow:hidden;
}
.stat { background:var(--bg-2); padding:32px 24px; text-align:center }
.stat-num {
  font-family:var(--f-serif); font-size:44px; font-weight:500;
  color:var(--accent-ink); line-height:1; margin-bottom:8px;
}
.stat-label { font-size:13px; color:var(--text-2) }

/* ── SPLIT LAYOUT ── */
.split { display:grid; grid-template-columns:1fr 1fr; gap:60px; align-items:center }
.split-text h3 { font-family:var(--f-serif); font-size:clamp(24px,2.8vw,36px); font-weight:500; margin-bottom:14px }
.split-text h3 em { font-style:italic; color:var(--accent-ink) }
.split-text p { font-size:15px; color:var(--text-2); line-height:1.7; margin-bottom:14px }
.split-text ul { list-style:none; display:flex; flex-direction:column; gap:10px; margin-top:4px }
.split-text ul li { font-size:14px; color:var(--text-2); display:flex; align-items:flex-start; gap:10px }
.split-text ul li::before { content:'—'; color:var(--accent-ink); flex-shrink:0 }

/* ── TESTIMONIALS ── */
.testimonial-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:24px }
.testimonial {
  padding:28px; background:var(--bg-card); border:1px solid var(--line);
  border-radius:var(--r); position:relative;
}
.testimonial::before {
  content:'"'; position:absolute; top:20px; right:20px;
  font-family:var(--f-serif); font-size:60px; color:var(--accent-ink); opacity:.15; line-height:1;
}
.testimonial-stars { color:var(--accent-ink); font-size:12px; margin-bottom:14px; letter-spacing:2px }
.testimonial-text { font-size:15px; color:var(--text-2); line-height:1.72; margin-bottom:20px; font-style:italic }
.testimonial-author { display:flex; align-items:center; gap:12px }
.testimonial-avatar {
  width:40px; height:40px; border-radius:50%; background:var(--accent-dim);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--f-serif); font-size:16px; color:var(--accent-ink); font-weight:600; flex-shrink:0;
}
.testimonial-name { font-weight:600; font-size:14px; margin-bottom:2px }
.testimonial-role { font-size:12px; color:var(--text-3) }

/* ── FAQ ── */
.faq-list { display:flex; flex-direction:column }
.faq-item { border-bottom:1px solid var(--line) }
.faq-question {
  padding:22px 0; display:flex; justify-content:space-between; align-items:center;
  cursor:pointer; font-weight:500; font-size:16px; transition:color .3s;
  background:none; border:none; color:var(--text); font-family:var(--f-sans); width:100%; text-align:left;
}
.faq-question:hover { color:var(--accent-ink) }
.faq-question i { color:var(--accent-ink); font-size:14px; transition:transform .3s; flex-shrink:0 }
.faq-answer { font-size:15px; color:var(--text-2); line-height:1.72; padding-bottom:22px; display:none }
.faq-item.open .faq-answer { display:block }
.faq-item.open .faq-question i { transform:rotate(45deg) }
.faq-item.open .faq-question { color:var(--accent-ink) }

/* ── GALLERY ── */
.gallery-grid {
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:16px; grid-auto-rows:220px;
}
.gallery-item {
  border-radius:var(--r-sm); overflow:hidden; background:var(--bg-2);
  border:1px solid var(--line); cursor:pointer; position:relative;
  transition:transform .3s, border-color .3s;
}
.gallery-item:hover { transform:scale(1.02); border-color:var(--line-a) }
.gallery-item.tall { grid-row:span 2 }
.gallery-item.wide { grid-column:span 2 }
.gallery-item svg { width:100%; height:100%; display:block }
.gallery-caption {
  position:absolute; bottom:0; left:0; right:0;
  padding:12px 16px; background:linear-gradient(transparent, rgba(0,0,0,.7));
  font-size:12px; color:var(--text-2); opacity:0; transition:opacity .3s;
}
.gallery-item:hover .gallery-caption { opacity:1 }

/* ── FORM ── */
.form-wrap { display:flex; flex-direction:column; gap:20px }
.form-row { display:grid; grid-template-columns:1fr 1fr; gap:20px }
.form-group { display:flex; flex-direction:column; gap:7px }
.form-group label {
  font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--text-3)
}
.form-group input,
.form-group select,
.form-group textarea {
  background:var(--bg-2); border:1px solid var(--line); border-radius:var(--r-sm);
  padding:13px 16px; color:var(--text); font-family:var(--f-sans); font-size:14px;
  transition:border-color .3s; outline:none; appearance:none;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus { border-color:var(--accent) }
.form-group textarea { resize:vertical; min-height:110px }
.form-group select option { background:var(--surface-opt) }

/* Autofill — see the note on the main site: Chrome ignores background-color on
   an autofilled control, so the fill has to come from an inset shadow. Uses the
   theme vars, so each demo's palette carries through. */
.form-group input:autofill,
.form-group select:autofill,
.form-group textarea:autofill {
  background:var(--bg-2); color:var(--text); filter:none;
}
.form-group input:-webkit-autofill,
.form-group input:-webkit-autofill:hover,
.form-group input:-webkit-autofill:focus,
.form-group select:-webkit-autofill,
.form-group select:-webkit-autofill:hover,
.form-group select:-webkit-autofill:focus,
.form-group textarea:-webkit-autofill,
.form-group textarea:-webkit-autofill:hover,
.form-group textarea:-webkit-autofill:focus {
  -webkit-text-fill-color:var(--text);
  -webkit-box-shadow:0 0 0 1000px var(--bg-2) inset;
          box-shadow:0 0 0 1000px var(--bg-2) inset;
  caret-color:var(--text);
  border-color:var(--line);
  -webkit-transition:background-color 100000s ease-in-out 0s;
          transition:background-color 100000s ease-in-out 0s;
}
.form-group input:-webkit-autofill:focus,
.form-group select:-webkit-autofill:focus,
.form-group textarea:-webkit-autofill:focus { border-color:var(--accent) }

/* ── BOOKING / CALENDAR ── */
.cal {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r); padding:28px;
}
.cal-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:20px }
.cal-title { font-family:var(--f-serif); font-size:18px; font-weight:500 }
.cal-nav-btns { display:flex; gap:8px }
.cal-nav-btns button {
  width:32px; height:32px; border-radius:50%; border:1px solid var(--line);
  background:none; color:var(--text); cursor:pointer; font-size:12px;
  display:flex; align-items:center; justify-content:center; transition:all .3s;
}
.cal-nav-btns button:hover { border-color:var(--accent); color:var(--accent-ink) }
.cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:4px; margin-bottom:16px }
.cal-label { text-align:center; font-size:10px; color:var(--text-3); font-weight:600; padding:6px 0 }
.cal-date { text-align:center; padding:8px 4px; border-radius:8px; font-size:13px; cursor:pointer; transition:all .2s }
.cal-date:hover { background:var(--accent-dim); color:var(--accent-ink) }
.cal-date.sel { background:var(--accent); color:var(--on-accent); font-weight:700 }
.cal-date.off { opacity:.28; cursor:not-allowed }
.cal-date.dot::after { content:''; display:block; width:4px; height:4px; border-radius:50%; background:var(--accent); margin:2px auto 0 }
.time-slots { display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin-top:8px }
.time-slot {
  padding:10px 6px; text-align:center; border:1px solid var(--line);
  border-radius:8px; font-size:12px; cursor:pointer; transition:all .2s;
}
.time-slot:hover { border-color:var(--accent); color:var(--accent-ink) }
.time-slot.sel { background:var(--accent); color:var(--on-accent); border-color:var(--accent); font-weight:700 }
.time-slot.full { opacity:.3; cursor:not-allowed; text-decoration:line-through }

/* ── TEAM ── */
.team-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:28px }
.team-card {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; text-align:center; transition:transform .3s, border-color .3s;
}
.team-card:hover { transform:translateY(-4px); border-color:var(--line-a) }
.team-photo { aspect-ratio:1/1; background:var(--bg-2); overflow:hidden }
.team-photo svg { width:100%; height:100%; display:block }
.team-info { padding:22px }
.team-name { font-family:var(--f-serif); font-size:19px; font-weight:500; margin-bottom:4px }
.team-role { font-family:var(--f-mono); font-size:9px; letter-spacing:.18em; text-transform:uppercase; color:var(--accent-ink); margin-bottom:10px }
.team-bio { font-size:13px; color:var(--text-2); line-height:1.65 }

/* ============================================================
   PHOTOGRAPHY
   Real photos replace the placeholder SVGs in every media slot.
   Each slot already sets its own aspect-ratio and overflow:hidden,
   so the image just fills it. A theme-toned scrim keeps photos
   sitting inside each vertical's palette instead of on top of it.
   ============================================================ */
.hero-art img,
.gallery-item img,
.team-photo img,
.blog-thumb img,
.product-img img,
.photo-slot img {
  width:100%; height:100%;
  object-fit:cover; object-position:center;
  display:block;
  background:var(--bg-2);
}

/* Scrim: ties the photo to the theme accent and keeps overlaid text legible. */
.hero-art, .gallery-item, .blog-thumb, .product-img, .team-photo { position:relative }
.hero-art::after,
.gallery-item::after,
.team-photo::after {
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to bottom, transparent 45%, var(--scrim) 100%);
}
.gallery-item img { transition:transform .6s cubic-bezier(.2,.7,.3,1) }
.gallery-item:hover img { transform:scale(1.05) }
.gallery-caption { z-index:2 }

.product-img { aspect-ratio:1/1; background:var(--bg-2); overflow:hidden }
.product-img img { transition:transform .5s cubic-bezier(.2,.7,.3,1) }
.product-card:hover .product-img img { transform:scale(1.04) }

.blog-card:hover .blog-thumb img { transform:scale(1.03) }
.blog-thumb img { transition:transform .5s cubic-bezier(.2,.7,.3,1) }

/* Photos load lazily; reserve the box so nothing shifts as they arrive. */
.gallery-item img, .blog-thumb img, .product-img img, .team-photo img { min-height:100% }

@media (prefers-reduced-motion:reduce){
  .gallery-item img, .product-img img, .blog-thumb img { transition:none }
  .gallery-item:hover img, .product-card:hover .product-img img, .blog-card:hover .blog-thumb img { transform:none }
}

/* ── BLOG ── */
.blog-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:28px }
.blog-card {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; transition:transform .3s, border-color .3s;
}
.blog-card:hover { transform:translateY(-4px); border-color:var(--line-a) }
.blog-thumb { aspect-ratio:16/9; background:var(--bg-2); overflow:hidden }
.blog-thumb svg { width:100%; height:100%; display:block }
.blog-content { padding:24px }
.blog-tag { font-family:var(--f-mono); font-size:9px; color:var(--accent-ink); text-transform:uppercase; letter-spacing:.2em; margin-bottom:10px }
.blog-title { font-family:var(--f-serif); font-size:20px; font-weight:500; margin-bottom:8px; line-height:1.3 }
.blog-excerpt { font-size:14px; color:var(--text-2); line-height:1.65; margin-bottom:16px }
.blog-meta { font-size:12px; color:var(--text-3); display:flex; gap:16px; align-items:center }
.blog-meta i { color:var(--accent-ink) }

/* ── PRICING ── */
.pricing-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:24px }
.pricing-card {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  padding:36px 28px; position:relative; transition:transform .3s, border-color .3s;
}
.pricing-card.featured { border-color:var(--accent) }
.pricing-card:hover { transform:translateY(-4px) }
.pricing-badge {
  position:absolute; top:-12px; left:50%; transform:translateX(-50%);
  background:var(--accent); color:var(--on-accent);
  font-family:var(--f-mono); font-size:9px; letter-spacing:.15em; text-transform:uppercase;
  padding:4px 14px; border-radius:999px; font-weight:700; white-space:nowrap;
}
.pricing-tier { font-family:var(--f-mono); font-size:10px; letter-spacing:.2em; text-transform:uppercase; color:var(--accent-ink); margin-bottom:12px }
.pricing-price { font-family:var(--f-serif); font-size:44px; font-weight:500; margin-bottom:4px; line-height:1 }
.pricing-price small { font-size:16px; font-weight:400; font-family:var(--f-sans) }
.pricing-note { font-size:12px; color:var(--text-3); margin-bottom:28px }
.pricing-features { list-style:none; display:flex; flex-direction:column; gap:12px; margin-bottom:28px }
.pricing-features li { font-size:14px; color:var(--text-2); display:flex; align-items:flex-start; gap:10px }
.pricing-features li i { color:var(--accent-ink); margin-top:2px; flex-shrink:0 }
.pricing-features li.off { opacity:.38 }
.pricing-features li.off i { color:var(--text-3) }

/* ── CONTACT ── */
.contact-grid { display:grid; grid-template-columns:1fr 1fr; gap:48px; align-items:start }
.contact-info { display:flex; flex-direction:column; gap:16px }
.contact-item {
  display:flex; align-items:flex-start; gap:16px;
  padding:18px; background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r-sm);
}
.contact-icon {
  width:40px; height:40px; border-radius:10px; background:var(--accent-dim);
  display:flex; align-items:center; justify-content:center;
  color:var(--accent-ink); font-size:16px; flex-shrink:0;
}
.contact-detail .label { font-family:var(--f-mono); font-size:9px; letter-spacing:.2em; text-transform:uppercase; color:var(--text-3); margin-bottom:4px }
.contact-detail .value { font-size:15px; font-weight:500; line-height:1.4 }
.map-placeholder {
  border-radius:var(--r); overflow:hidden; background:var(--bg-2);
  border:1px solid var(--line); aspect-ratio:16/10; display:flex; align-items:center; justify-content:center;
  color:var(--text-3); font-size:14px; flex-direction:column; gap:10px;
}
.map-placeholder i { font-size:36px; color:var(--accent-ink) }

/* ── CTA BANNER ── */
.cta-banner {
  background:linear-gradient(120deg, var(--bg-2), var(--bg));
  border:1px solid var(--line-a); border-radius:var(--r-lg); padding:56px 60px;
  display:flex; justify-content:space-between; align-items:center; gap:40px;
  position:relative; overflow:hidden;
}
.cta-banner::before {
  content:''; position:absolute; top:-50%; right:-15%; width:500px; height:500px;
  border-radius:50%; background:var(--accent-glow); pointer-events:none;
}
.cta-text h3 { font-family:var(--f-serif); font-size:clamp(24px,3vw,38px); font-weight:500; margin-bottom:10px }
.cta-text h3 em { font-style:italic; color:var(--accent-ink) }
.cta-text p { font-size:15px; color:var(--text-2); max-width:50ch; line-height:1.7 }

/* ── SERVICE LIST ── */
.service-list { display:flex; flex-direction:column; gap:0 }
.service-item {
  display:flex; justify-content:space-between; align-items:center;
  padding:20px 0; border-bottom:1px solid var(--line);
  transition:all .2s;
}
.service-item:hover .service-name { color:var(--accent-ink) }
.service-name { font-weight:500; font-size:16px; margin-bottom:4px }
.service-desc { font-size:13px; color:var(--text-3) }
.service-price { font-family:var(--f-serif); font-size:20px; color:var(--accent-ink); white-space:nowrap; margin-left:20px }
.service-duration { font-size:11px; color:var(--text-3); text-align:right; margin-top:2px }

/* ── MENU ── */
.menu-section { margin-bottom:48px }
.menu-section-title {
  font-family:var(--f-serif); font-size:26px; font-weight:500;
  margin-bottom:20px; padding-bottom:14px; border-bottom:1px solid var(--line-a);
  display:flex; align-items:center; gap:12px;
}
.menu-section-title i { color:var(--accent-ink) }
.menu-items { display:grid; grid-template-columns:1fr 1fr; gap:16px }
.menu-item {
  padding:18px; background:var(--bg-card); border:1px solid var(--line);
  border-radius:var(--r-sm); transition:border-color .3s; display:flex; justify-content:space-between; align-items:start;
}
.menu-item:hover { border-color:var(--line-a) }
.menu-item-info { flex:1 }
.menu-item-name { font-weight:600; font-size:15px; margin-bottom:4px }
.menu-item-desc { font-size:13px; color:var(--text-3); line-height:1.5 }
.menu-item-tags { display:flex; gap:6px; margin-top:8px; flex-wrap:wrap }
.menu-tag {
  font-family:var(--f-mono); font-size:8px; letter-spacing:.1em; text-transform:uppercase;
  padding:3px 8px; border-radius:999px; border:1px solid var(--line-a); color:var(--text-3);
}
.menu-tag.veg { color:#6B9E7A; border-color:rgba(107,158,122,.3) }
.menu-tag.spicy { color:#D9823C; border-color:rgba(217,130,60,.3) }
.menu-item-price { font-family:var(--f-serif); font-size:18px; color:var(--accent-ink); white-space:nowrap; margin-left:16px; padding-top:2px }

/* ── PROPERTY CARD ── */
.property-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:24px }
.property-card {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; transition:transform .3s, border-color .3s;
}
.property-card:hover { transform:translateY(-4px); border-color:var(--line-a) }
.property-img { aspect-ratio:4/3; background:var(--bg-2); overflow:hidden; position:relative }
.property-img svg { width:100%; height:100%; display:block }
.property-badge {
  position:absolute; top:14px; left:14px;
  background:var(--accent); color:var(--on-accent);
  font-family:var(--f-mono); font-size:9px; letter-spacing:.1em; text-transform:uppercase;
  padding:4px 10px; border-radius:999px; font-weight:700;
}
.property-body { padding:22px }
.property-name { font-family:var(--f-serif); font-size:20px; font-weight:500; margin-bottom:6px }
.property-loc { font-size:13px; color:var(--text-3); margin-bottom:14px; display:flex; align-items:center; gap:6px }
.property-loc i { color:var(--accent-ink) }
.property-specs { display:flex; gap:20px; margin-bottom:14px }
.property-spec { font-size:13px; color:var(--text-2); display:flex; align-items:center; gap:6px }
.property-spec i { color:var(--accent-ink); font-size:11px }
.property-price { font-family:var(--f-serif); font-size:22px; color:var(--accent-ink) }
.property-price span { font-family:var(--f-sans); font-size:12px; color:var(--text-3); font-weight:400 }

/* ── COLLECTION / PRODUCT ── */
.product-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:20px }
.product-card {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; transition:transform .3s, border-color .3s;
}
.product-card:hover { transform:translateY(-4px); border-color:var(--line-a) }
.product-thumb { aspect-ratio:1/1; background:var(--bg-2); overflow:hidden }
.product-thumb svg { width:100%; height:100%; display:block }
.product-info { padding:16px }
.product-name { font-weight:600; font-size:14px; margin-bottom:4px }
.product-cat { font-size:11px; color:var(--text-3); margin-bottom:8px }
.product-price { font-family:var(--f-serif); font-size:18px; color:var(--accent-ink) }

/* ── FOOTER ── */
.footer {
  border-top:1px solid var(--line); padding:64px var(--gutter) 36px;
  position:relative; z-index:1;
}
.footer-inner {
  max-width:var(--max); margin:0 auto;
  display:grid; grid-template-columns:1.6fr 1fr 1fr 1fr; gap:48px; margin-bottom:48px;
}
.footer-brand .name { font-family:var(--f-serif); font-size:26px; font-weight:600; margin-bottom:14px }
.footer-brand .name em { color:var(--accent-ink); font-style:italic }
.footer-brand p { font-size:14px; color:var(--text-2); line-height:1.7; max-width:28ch; margin-bottom:20px }
.footer-social { display:flex; gap:10px }
.footer-social a {
  width:36px; height:36px; border-radius:50%; border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center;
  font-size:14px; color:var(--text-2); transition:all .3s;
}
.footer-social a:hover { border-color:var(--accent); color:var(--accent-ink) }
.footer-col h5 { font-family:var(--f-mono); font-size:9px; letter-spacing:.22em; text-transform:uppercase; color:var(--accent-ink); margin-bottom:16px }
.footer-col ul { list-style:none; display:flex; flex-direction:column; gap:10px }
.footer-col ul a { font-size:14px; color:var(--text-2); transition:color .3s }
.footer-col ul a:hover { color:var(--accent-ink) }
.footer-bottom {
  max-width:var(--max); margin:0 auto; padding-top:28px; border-top:1px solid var(--line);
  display:flex; justify-content:space-between; align-items:center;
  font-size:12px; color:var(--text-3);
}
.footer-bottom a { color:var(--accent-ink) }

/* ── WHATSAPP FLOAT ── */
.wa-float {
  position:fixed; bottom:28px; right:28px; z-index:998;
  width:52px; height:52px; border-radius:50%; background:#25D366;
  display:flex; align-items:center; justify-content:center;
  font-size:22px; color:#fff; box-shadow:0 4px 20px rgba(37,211,102,.4);
  transition:transform .3s;
}
.wa-float:hover { transform:scale(1.08) }

/* ── SCROLL REVEAL ── */
.reveal { opacity:0; transform:translateY(22px); transition:opacity .7s, transform .7s }
.reveal.visible { opacity:1; transform:none }
.reveal[data-d="1"] { transition-delay:.1s }
.reveal[data-d="2"] { transition-delay:.2s }
.reveal[data-d="3"] { transition-delay:.3s }
.reveal[data-d="4"] { transition-delay:.4s }
.reveal[data-d="5"] { transition-delay:.5s }

/* ── BREADCRUMB ── */
.breadcrumb {
  font-family:var(--f-mono); font-size:10px; letter-spacing:.15em;
  text-transform:uppercase; color:var(--text-3);
  display:flex; align-items:center; gap:8px; margin-bottom:20px;
}
.breadcrumb a { color:var(--text-3); transition:color .3s }
.breadcrumb a:hover { color:var(--accent-ink) }
.breadcrumb i { font-size:8px }

/* ── NOTICE CHIP ── */
.chip {
  display:inline-flex; align-items:center; gap:8px;
  padding:6px 14px; border-radius:999px; font-size:12px;
  border:1px solid var(--line-a); color:var(--text-2);
}
.chip.accent { background:var(--accent-dim); border-color:var(--accent); color:var(--accent-ink) }

/* ── EMI CALCULATOR ── */
.calc-box {
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  padding:36px;
}
.calc-box label { font-size:12px; color:var(--text-3); font-weight:600; letter-spacing:.08em; text-transform:uppercase; display:block; margin-bottom:8px }
.calc-box input[type=range] { width:100%; accent-color:var(--accent); margin-bottom:4px }
.calc-box .range-labels { display:flex; justify-content:space-between; font-size:11px; color:var(--text-3); margin-bottom:20px }
.calc-result { margin-top:28px; padding:24px; background:var(--accent-dim); border:1px solid var(--accent); border-radius:var(--r-sm); text-align:center }
.calc-emi { font-family:var(--f-serif); font-size:44px; color:var(--accent-ink); font-weight:500; margin-bottom:4px }
.calc-emi-label { font-size:13px; color:var(--text-2) }

/* ── PROCESS STEPS ── */
.process { display:grid; grid-template-columns:repeat(4,1fr); gap:32px }
.step { position:relative }
.step-num {
  font-family:var(--f-mono); font-size:11px; letter-spacing:.15em;
  color:var(--accent-ink); margin-bottom:12px;
}
.step h4 { font-family:var(--f-serif); font-size:18px; font-weight:500; margin-bottom:8px }
.step p { font-size:14px; color:var(--text-2); line-height:1.65 }

/* ── FILTER TABS ── */
.filter-tabs { display:flex; gap:10px; flex-wrap:wrap; margin-bottom:36px }
.filter-tab {
  padding:8px 20px; border-radius:999px; border:1px solid var(--line);
  font-size:13px; font-weight:500; cursor:pointer;
  transition:all .2s; color:var(--text-2); background:none; font-family:var(--f-sans);
}
.filter-tab:hover, .filter-tab.active { background:var(--accent); color:var(--on-accent); border-color:var(--accent) }

/* ── RESPONSIVE ── */
@media (max-width:1024px) {
  .hero-inner { grid-template-columns:1fr }
  .hero:has(> .hero-visual) { grid-template-columns:1fr }
  .hero-art { display:none }
  .hero-visual { display:none }
  .features { grid-template-columns:1fr 1fr }
  .grid-4,.product-grid { grid-template-columns:1fr 1fr }
  .stats { grid-template-columns:1fr 1fr }
  .footer-inner { grid-template-columns:1fr 1fr }
  .cta-banner { flex-direction:column; text-align:center }
  .pricing-grid { grid-template-columns:1fr; max-width:440px; margin-left:auto; margin-right:auto }
  .process { grid-template-columns:1fr 1fr }
  .property-grid { grid-template-columns:1fr 1fr }
}
@media (max-width:768px) {
  .nav-links { display:none; position:absolute; top:var(--nav-h); left:0; right:0; flex-direction:column; gap:0; background:var(--surface-sheet); padding:0 var(--gutter) 16px; border-bottom:1px solid var(--line) }
  .nav-links.open { display:flex }
  .nav-links li { border-bottom:1px solid var(--line) }
  .nav-links a { display:block; padding:14px 0 }
  .nav-toggle { display:flex }
  .grid-2,.grid-3,.team-grid,.blog-grid,.testimonial-grid,.gallery-grid,.menu-items,.split,.contact-grid { grid-template-columns:1fr }
  .features { grid-template-columns:1fr }
  .form-row { grid-template-columns:1fr }
  .footer-inner { grid-template-columns:1fr; gap:28px }
  .cta-banner { padding:36px 28px }
  .process { grid-template-columns:1fr 1fr }
  .property-grid,.product-grid { grid-template-columns:1fr }
  .gallery-grid { grid-auto-rows:160px }
}
@media (max-width:480px) {
  :root { --gutter:20px }
  .stats { grid-template-columns:1fr }
  .hero h1 { font-size:34px }
  .process { grid-template-columns:1fr }
  .gallery-item.wide { grid-column:span 1 }
}

/* =========================================================
   v2 UPLIFT — May 2026
   New components: local-bar, jump-nav, trust-strip, header-chips,
   listing-toolbar, fssai-mark, row-action, focus-visible, breadcrumb-fix.
   ========================================================= */

/* ── FOCUS VISIBLE (keyboard a11y) ── */
:focus:not(:focus-visible) { outline:none }
:focus-visible {
  outline:2px solid var(--accent);
  outline-offset:3px;
  border-radius:6px;
}
.nav-cta:focus-visible,
.btn:focus-visible { outline-offset:4px }

/* ── LOCAL BAR (open-now / hours / contact strip below nav) ── */
.local-bar {
  position:sticky; top:var(--nav-h); z-index:900;
  background:linear-gradient(180deg, var(--surface-strip), var(--surface-strip-2));
  backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line);
  padding:10px var(--gutter);
  display:flex; justify-content:center; align-items:center; flex-wrap:wrap;
  gap:8px 28px;
  font-size:12px; color:var(--text-2); font-family:var(--f-sans);
}
.local-bar { top:calc(var(--nav-h) + var(--preview-h)) }
.local-bar-item { display:inline-flex; align-items:center; gap:8px; white-space:nowrap }
.local-bar-item i { color:var(--accent-ink); font-size:11px }
.local-bar-item a { color:var(--text); transition:color .2s }
.local-bar-item a:hover { color:var(--accent-ink) }
.local-bar-sep { width:1px; height:14px; background:var(--line); opacity:.6 }
.live-dot {
  width:7px; height:7px; border-radius:50%;
  background:#3FBF7F; box-shadow:0 0 0 0 rgba(63,191,127,.5);
  animation:livePulse 2.2s infinite;
}
.live-dot.closed { background:#C04A3D; animation:none }
@keyframes livePulse {
  0%   { box-shadow:0 0 0 0 rgba(63,191,127,.55) }
  70%  { box-shadow:0 0 0 8px rgba(63,191,127,0) }
  100% { box-shadow:0 0 0 0 rgba(63,191,127,0) }
}

/* ── JUMP NAV (sticky pill row for long content pages) ── */
.jump-nav {
  position:sticky; top:var(--nav-h); z-index:5;
  background:var(--surface-glass); backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line);
  padding:12px var(--gutter);
}
.jump-nav { top:calc(var(--nav-h) + var(--preview-h)) }
.local-bar + .jump-nav { top:calc(var(--nav-h) + 38px) }
.local-bar + .jump-nav { top:calc(var(--nav-h) + var(--preview-h) + 38px) }
.jump-nav-inner {
  max-width:var(--max); margin:0 auto;
  display:flex; gap:8px; overflow-x:auto;
  scrollbar-width:none;
}
.jump-nav-inner::-webkit-scrollbar { display:none }
.jump-link {
  padding:7px 16px; border-radius:999px;
  border:1px solid var(--line);
  font-size:12px; font-weight:500; color:var(--text-2);
  white-space:nowrap; flex-shrink:0;
  transition:all .2s; cursor:pointer;
  display:inline-flex; align-items:center; gap:6px;
}
.jump-link i { font-size:10px; opacity:.65 }
.jump-link:hover, .jump-link.active {
  background:var(--accent); color:var(--on-accent); border-color:var(--accent);
}
.jump-link:hover i, .jump-link.active i { opacity:.85 }

/* ── PAGE HEADER CHIPS (contextual metadata in the page-header) ── */
.header-chips {
  display:flex; flex-wrap:wrap; gap:10px;
  justify-content:center; margin-top:24px;
}
.header-chip {
  display:inline-flex; align-items:center; gap:8px;
  padding:7px 14px; border-radius:999px;
  background:var(--bg-card); border:1px solid var(--line);
  font-size:12px; color:var(--text-2);
}
.header-chip i { color:var(--accent-ink); font-size:11px }
.header-chip strong { color:var(--text); font-weight:600; font-family:var(--f-sans) }
.header-chip .num {
  font-family:var(--f-serif); color:var(--accent-ink);
  font-size:15px; font-weight:600; line-height:1;
}

/* ── BREADCRUMB (existing styles + position helper) ── */
.page-header .breadcrumb { justify-content:center; margin-bottom:18px }
.breadcrumb a { transition:color .2s }
.breadcrumb a:hover { color:var(--accent-ink) }

/* ── TRUST STRIP ── */
.trust-strip {
  display:flex; flex-wrap:wrap; gap:18px 36px;
  justify-content:center; align-items:center;
  padding:28px var(--gutter);
  background:var(--bg-2);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
}
.trust-chip {
  display:inline-flex; align-items:center; gap:10px;
  font-size:12px; color:var(--text-2);
}
.trust-chip i { color:var(--accent-ink); font-size:15px }
.trust-chip strong { color:var(--text); font-weight:600; font-family:var(--f-sans); display:block; line-height:1.3 }
.trust-chip span { font-size:11px; color:var(--text-3); display:block }
.trust-chip .stack { display:flex; flex-direction:column; gap:2px }

/* ── LISTING TOOLBAR (count + sort dropdown) ── */
.listing-toolbar {
  display:flex; justify-content:space-between; align-items:center;
  gap:20px; flex-wrap:wrap; margin-bottom:28px;
}
.listing-count { font-size:13px; color:var(--text-2) }
.listing-count strong { color:var(--text); font-weight:700; font-family:var(--f-serif); font-size:16px }
.listing-sort {
  display:inline-flex; align-items:center; gap:10px;
  font-size:11px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--text-3); font-family:var(--f-mono);
}
.listing-sort select {
  background:var(--bg-2); border:1px solid var(--line); border-radius:8px;
  padding:9px 34px 9px 14px; color:var(--text);
  font-family:var(--f-sans); font-size:13px; letter-spacing:0; text-transform:none;
  appearance:none; cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 12 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23C8C3BA' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-position:right 12px center; background-repeat:no-repeat; background-size:10px;
}
.listing-sort select:hover { border-color:var(--line-a) }
.listing-sort select:focus { border-color:var(--accent); outline:none }

/* ── FSSAI VEG / NON-VEG SQUARE MARK (Indian standard) ── */
.fssai-mark {
  display:inline-grid; place-items:center;
  width:13px; height:13px; border:1.8px solid #3D8B3D;
  flex-shrink:0; vertical-align:middle;
}
.fssai-mark::after {
  content:''; width:5px; height:5px;
  background:#3D8B3D; border-radius:50%;
}
.fssai-mark.non { border-color:#C04A3D }
.fssai-mark.non::after { background:#C04A3D }

/* ── ROW ACTION (inline tiny CTAs in long lists) ── */
.row-action {
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--f-mono); font-size:10px;
  letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent-ink);
  padding:6px 12px; border:1px solid var(--line-a); border-radius:999px;
  transition:all .2s; cursor:pointer; background:none;
  white-space:nowrap;
}
.row-action:hover { background:var(--accent); color:var(--on-accent); border-color:var(--accent) }
.row-action i { font-size:11px }

/* Menu-item layout adjustment to host an action row */
.menu-item-info { display:flex; flex-direction:column; gap:6px }
.menu-item-actions { display:flex; align-items:center; gap:8px; margin-top:4px; flex-wrap:wrap }
.menu-item-actions .row-action { padding:5px 10px; font-size:9px }

/* Service-list row action */
.service-item .service-actions { display:flex; align-items:flex-end; flex-direction:column; gap:6px; margin-left:20px }

/* ── PROPERTY CARD: ensure proper rendering even when product-card markup is used ── */
.property-card { background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r); overflow:hidden; transition:transform .3s, border-color .3s }
.property-card:hover { transform:translateY(-4px); border-color:var(--line-a) }
.property-img { aspect-ratio:4/3 }

/* ── WhatsApp float: keep clear of bottom CTAs on mobile ── */
@media (max-width:768px) {
  .wa-float { width:48px; height:48px; bottom:18px; right:18px; font-size:20px }
  .cta-banner { padding-bottom:32px }
}

/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; scroll-behavior:auto !important }
  .live-dot { animation:none }
  .reveal { opacity:1; transform:none }
}

/* ── filter-btn: alias of filter-tab (fixes unstyled buttons on jewellery/ecommerce/realestate) ── */
.filter-tabs .filter-btn {
  padding:8px 20px; border-radius:999px; border:1px solid var(--line);
  font-size:13px; font-weight:500; cursor:pointer;
  transition:all .2s; color:var(--text-2); background:none; font-family:var(--f-sans);
}
.filter-tabs .filter-btn:hover,
.filter-tabs .filter-btn.active { background:var(--accent); color:var(--on-accent); border-color:var(--accent) }

/* ── SKIP TO MAIN (accessibility) ── */
.skip-link {
  position:fixed; top:-100%; left:50%; transform:translateX(-50%);
  background:var(--accent); color:var(--on-accent);
  padding:10px 24px; border-radius:0 0 8px 8px;
  font-size:13px; font-weight:600; z-index:9999;
  transition:top .2s;
}
.skip-link:focus { top:0 }

/* ── MOBILE STICKY CTA BAR ── */
.mobile-cta-bar {
  display:none;
  position:fixed; bottom:0; left:0; right:0; z-index:800;
  padding:12px 20px;
  background:linear-gradient(180deg, transparent 0%, var(--bg) 20%);
  pointer-events:none;
}
.mobile-cta-bar .mobile-cta-btn {
  display:flex; align-items:center; justify-content:center; gap:10px;
  width:100%; padding:15px;
  background:var(--accent); color:var(--on-accent);
  border-radius:12px; font-size:14px; font-weight:600;
  font-family:var(--f-sans); border:none; cursor:pointer;
  pointer-events:all;
  box-shadow:var(--shadow);
}
.mobile-cta-bar .mobile-cta-btn i { font-size:15px }
@media (max-width:768px) {
  .mobile-cta-bar { display:block }
  body { padding-bottom:80px }
  .wa-float { bottom:88px }
}

/* ── COOKIE CONSENT BANNER ── */







@media (max-width:768px) {



}

/* ── Responsive tweaks for new components ── */
@media (max-width:768px) {
  .local-bar { font-size:11px; padding:8px var(--gutter); gap:6px 18px }
  .local-bar-sep { display:none }
  .header-chips { gap:8px }
  .header-chip { font-size:11px; padding:6px 12px }
  .trust-strip { gap:14px 24px; padding:20px var(--gutter) }
  .listing-toolbar { justify-content:flex-start }
  .jump-nav { padding:10px var(--gutter) }
  .schedule-wrap { overflow-x:auto; -webkit-overflow-scrolling:touch }
}

/* =========================================================
   TRACK A — modern-UI uplift · September 2026
   -----------------------------------------------------------------
   Everything below hangs off classes that ALREADY exist across the 80
   demo pages, so not one .html file changes and nothing needs
   rebuilding. Two rules held throughout:

   1. Every enhancement must degrade to a correct static page, never a
      broken one. Where a scroll-driven animation drives opacity, the
      BASE state is visible and the animation drives 0 -> 1. An
      unresolvable timeline then leaves readable content rather than a
      blank column on 80 pages at once.

   2. Scroll-driven animations are progress-based, so the global
      prefers-reduced-motion block further up — which clamps
      animation-duration — does NOT neutralise them. Every timeline here
      is therefore declared inside `prefers-reduced-motion: no-preference`
      explicitly, not left to that block.
   ========================================================= */

/* ── DEPTH TOKENS ──
   A single wide blur reads as a smudge. A tight contact shadow, a mid
   spread and a wide ambient one read as depth — and the hairline top
   highlight is what actually sells a raised surface on a dark ground. */
:root {
  --e1:   0 1px 2px rgba(0,0,0,.30), 0 3px 8px -2px rgba(0,0,0,.24), 0 8px 20px -8px rgba(0,0,0,.34);
  --e2:   0 1px 2px rgba(0,0,0,.32), 0 6px 14px -4px rgba(0,0,0,.30), 0 18px 40px -12px rgba(0,0,0,.46);
  --e3:   0 2px 4px rgba(0,0,0,.34), 0 12px 28px -6px rgba(0,0,0,.34), 0 34px 70px -18px rgba(0,0,0,.58);
  --edge: inset 0 1px 0 var(--hairline-2);
  --ease: cubic-bezier(.16,1,.3,1);
}

/* ── SURFACE DEPTH ──
   The card family shared one flat border and a 4px lift. Give the whole
   family the same elevation language so a page reads as layers rather
   than as outlined rectangles. */
.card, .feature, .blog-card, .product-card, .property-card,
.team-card, .pricing-card, .testimonial {
  box-shadow: var(--e1), var(--edge);
  transition: transform .5s var(--ease), border-color .45s, box-shadow .45s var(--ease);
}
.card:hover, .feature:hover, .blog-card:hover, .product-card:hover,
.property-card:hover, .team-card:hover, .pricing-card:hover, .testimonial:hover {
  box-shadow: var(--e2), var(--edge);
  border-color: var(--line-a);
}
.feature:hover { transform: translateY(-3px) }
.hero-art, .hero-visual { box-shadow: var(--e3), var(--edge) }
.stats { box-shadow: var(--e1) }

/* ── GLASS ──
   The fixed chrome already blurred. Saturating behind it stops the bar
   going grey over a colour-rich page, and the top hairline gives the
   pane an edge instead of letting it float. */
.nav, .preview-bar, .local-bar, .jump-nav {
  -webkit-backdrop-filter: blur(18px) saturate(165%);
          backdrop-filter: blur(18px) saturate(165%);
}
.nav { box-shadow: 0 1px 0 var(--hairline), 0 10px 30px -18px rgba(0,0,0,.7) }
.nav.scrolled { box-shadow: 0 1px 0 var(--hairline-2), 0 14px 40px -18px rgba(0,0,0,.85) }

/* ── AMBIENT MESH + GRAIN ──
   Two radials became four: the extra pair keeps the lower half of long
   pages from flattening out into plain --bg.

   The grain rides on this same pseudo-element deliberately. It wants its
   own layer, but ::before is the FIRST child of body and therefore paints
   below everything in it, whereas an html::after would be the LAST child
   of the root and would paint OVER any positioned z-index:auto element —
   .hero among them. The existing grid on body::after has exactly that
   problem and only gets away with it at 1.5% alpha. Grain does not.

   One 160px tile of fractal noise, rasterised once and then repeated; it
   is what stops large flat dark areas banding. Alpha is baked into the
   tile because the element already carries opacity:.5. */
body::before {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.16'/%3E%3C/svg%3E"),
    radial-gradient(1000px 600px at 80% -5%,  var(--accent-glow), transparent 55%),
    radial-gradient(700px 400px  at -5% 65%,  var(--accent-glow), transparent 60%),
    radial-gradient(900px 520px  at 105% 78%, var(--accent-glow), transparent 58%),
    radial-gradient(760px 460px  at 18% 112%, var(--accent-glow), transparent 60%);
  background-size: 160px 160px, auto, auto, auto, auto;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat;
}
/* Grain is the one item in Track A with a real per-pixel paint cost, and it
   is invisible at phone size anyway. Drop the tile, keep the mesh. */
@media (max-width:768px) {
  body::before {
    background-image:
      radial-gradient(1000px 600px at 80% -5%,  var(--accent-glow), transparent 55%),
      radial-gradient(700px 400px  at -5% 65%,  var(--accent-glow), transparent 60%),
      radial-gradient(900px 520px  at 105% 78%, var(--accent-glow), transparent 58%),
      radial-gradient(760px 460px  at 18% 112%, var(--accent-glow), transparent 60%);
  }
}


/* ── TYPOGRAPHY ──
   Deliberately anchored to the sizes already shipping. Eighty pages of
   laid-out content is exactly where a 15% type bump breaks button rows
   and card grids, so this refines the ramp rather than resizing it. */
body { font-optical-sizing: auto }

h1, h2, h3, h4,
.hero h1, .page-header h1, .section-title, .card-title, .feature h4,
.blog-title, .property-name, .product-name, .team-name, .split-text h3,
.menu-section-title, .pricing-price {
  text-wrap: balance;
}
p, .hero-sub, .section-sub, .card-desc, .feature p,
.testimonial-text, .blog-excerpt, .team-bio, .property-loc {
  text-wrap: pretty;
}

.section-sub { font-size: clamp(15px, .28vw + 14.2px, 17px) }
.feature p, .card-desc { font-size: clamp(14px, .16vw + 13.4px, 15px) }

/* Prices and figures in columns should not jitter as digits change. */
.stat-num, .card-price, .product-price, .property-price, .menu-item-price,
.service-price, .pricing-price, .cal-date, .listing-count strong {
  font-variant-numeric: tabular-nums;
}
.stat-num, .pricing-price { letter-spacing: -.02em }

/* ── SCROLL-DRIVEN ANIMATION ──────────────────────────────────────────
   The reveal, rebuilt on a view() timeline. Note what the base state is:
   opacity 1, transform none. The animation drives 0 -> 1 from there.

   That inversion is the whole safety argument. If the timeline fails to
   resolve for any reason — an unexpected scroll container, a partial
   implementation, a future spec change — the element keeps its base
   state and the visitor sees readable content with no animation. The
   obvious way round (base opacity 0, animation reveals it) fails to a
   blank page, on 594 elements across 80 pages, with no error anywhere.

   demo.js stands down from its IntersectionObserver when this branch is
   live, so the two never drive the same property at once. */
@keyframes ntlReveal {
  from { opacity: 0; transform: translateY(22px) }
  45%  { opacity: 1 }
  to   { opacity: 1; transform: none }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    .reveal {
      opacity: 1; transform: none;
      animation: ntlReveal linear both;
      animation-timeline: view();
      animation-range: entry 25% entry 85%;
    }
    /* data-d was a transition-delay stagger, which a scrubbed timeline
       ignores. Same effect, expressed as a later slice of the range.

       Every range here both starts and ends inside the ENTRY phase, and
       that is load-bearing rather than stylistic.

       A range ending in the cover phase — the obvious choice, and what
       was written here first — can be unreachable. A short .reveal near
       the end of the document stops scrolling while its cover progress is
       still low, so the animation freezes part-scrubbed and the element
       sits at partial opacity forever, on exactly the pages nobody
       scrolls to the bottom of while checking.

       Entry progress cannot do that. It reaches 100% as soon as the
       element is fully in view — or, for anything taller than the
       viewport, once its top edge passes the top — and both are always
       true by the time a page is scrolled to its end. Keep every end
       value at or below 100%. */
    .reveal[data-d="1"] { animation-range: entry 32% entry 88%  }
    .reveal[data-d="2"] { animation-range: entry 39% entry 91%  }
    .reveal[data-d="3"] { animation-range: entry 46% entry 94%  }
    .reveal[data-d="4"] { animation-range: entry 53% entry 97%  }
    .reveal[data-d="5"] { animation-range: entry 60% entry 100% }

    /* Hero visuals drift against the copy as it scrolls past. Transform
       only, and only on the two hero slots — the gallery, product and
       blog thumbnails already own their transform for the hover zoom,
       and an animation would win over it permanently. */
    .hero-art img, .hero-visual > svg, .hero-visual > img {
      animation: ntlDrift linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
      will-change: transform;
    }

    /* Scroll progress. The element is created by demo.js, so no page
       markup changes; scroll(root) needs no JS at all to drive it. */
    .ntl-progress {
      position: fixed; top: 0; left: 0; right: 0; height: 2px;
      z-index: 2100; pointer-events: none;
      /* Rests at zero width. With no active timeline an unset transform
         means scaleX(1) — a solid accent bar across the top of every page
         too short to scroll. */
      transform: scaleX(0); transform-origin: 0 50%;
      background: linear-gradient(90deg, var(--accent), var(--accent-2));
      animation: ntlProgress linear both;
      animation-timeline: scroll(root);
    }
  }
}
@keyframes ntlDrift {
  from { transform: translate3d(0,-2.5%,0) scale(1.06) }
  to   { transform: translate3d(0, 2.5%,0) scale(1.06) }
}
@keyframes ntlProgress {
  from { transform: scaleX(0) }
  to   { transform: scaleX(1) }
}

/* ── VIEW TRANSITIONS ──────────────────────────────────────────────────
   Cross-document, which is the one that matters here: these are static
   multi-page sites, and this is what makes clicking between them feel
   like an app rather than a reload. Both sides of every navigation share
   this stylesheet, so the opt-in is always mutual.

   The chrome that persists across pages is named so it is carried rather
   than cross-faded. Both names are unique on every one of the 80 pages —
   a duplicate silently skips the entire transition. The nav logo is
   deliberately NOT named: it sits inside .nav, so naming it would punch
   it out of the nav's snapshot and animate it separately, which is extra
   machinery for an element that never moves between pages.

   Unsupported browsers navigate normally. */
@view-transition { navigation: auto }

.preview-bar { view-transition-name: ntl-preview-bar }
.nav         { view-transition-name: ntl-nav }

/* The old and new root snapshots are composited with mix-blend-mode:
   plus-lighter. That is the UA default, and it is what lets a cross-fade
   sum to exactly 1 rather than dipping through the background half way.

   It also means the two opacity curves MUST be symmetric. Giving the
   incoming page a longer or differently-eased fade than the outgoing one
   makes the pair sum to more than 1 while they overlap — which on a dark
   theme is a white flash on every single navigation. So opacity is linear
   and identical on both sides, and the motion is carried by a separate
   transform animation that is free to be eased however it likes. */
::view-transition-old(root) { animation: ntlVtOut .26s linear both }
::view-transition-new(root) { animation: ntlVtIn  .26s linear both,
                                         ntlVtRise .40s var(--ease) both }
@keyframes ntlVtOut  { to   { opacity: 0 } }
@keyframes ntlVtIn   { from { opacity: 0 } }
@keyframes ntlVtRise { from { transform: translateY(10px) } }

/* ── CURSOR-REACTIVE TILT ──────────────────────────────────────────────
   Reads as 3D, costs no library. Gated behind html.tilt, which demo.js
   adds only for a fine pointer with motion allowed, so touch and
   reduced-motion users keep exactly the old hover behaviour. */

/* Only position, so the sheen below has a containing block. No transform
   here — see the note on .ntl-tilting. */
html.tilt .card, html.tilt .feature, html.tilt .blog-card,
html.tilt .product-card, html.tilt .property-card, html.tilt .team-card,
html.tilt .pricing-card, html.tilt .testimonial {
  position: relative;
}

/* The 3D transform is applied ONLY to the one card the pointer is on.

   Declaring it on every card at rest — which is the obvious way to write
   this, and how it was written first — costs real money on a page that
   has any number of cards. A transform other than none promotes each card
   to its own compositor layer, so a listing page with forty product cards
   permanently holds forty GPU layers, and text inside a 3D-transformed
   box can render measurably softer on fractional-DPI displays. Scoping it
   to .ntl-tilting means one layer at a time, and crisp text everywhere
   the pointer is not.

   The hover lift is folded in here because a tilting card is by
   definition a hovered card, and one transform property cannot hold both.
   Dropping the class hands the element back to the .5s ease on .card, so
   it settles flat on its own. */
html.tilt .ntl-tilting {
  --ty: -4px;
  transform: perspective(900px)
             rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
             translate3d(0, var(--ty), 0);
  transition: transform .12s linear, box-shadow .45s var(--ease);
  will-change: transform;
}
html.tilt .feature.ntl-tilting { --ty: -3px }

/* Sheen follows the cursor. ::after is free on every one of these. */
html.tilt .card::after, html.tilt .feature::after, html.tilt .blog-card::after,
html.tilt .product-card::after, html.tilt .property-card::after,
html.tilt .team-card::after, html.tilt .pricing-card::after,
html.tilt .testimonial::after {
  content: ''; position: absolute; inset: 0; z-index: 3;
  pointer-events: none; opacity: 0; transition: opacity .4s var(--ease);
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx,50%) var(--my,50%),
              var(--sheen), transparent 62%);
}
html.tilt .card:hover::after, html.tilt .feature:hover::after,
html.tilt .blog-card:hover::after, html.tilt .product-card:hover::after,
html.tilt .property-card:hover::after, html.tilt .team-card:hover::after,
html.tilt .pricing-card:hover::after, html.tilt .testimonial:hover::after { opacity: 1 }

/* =========================================================
   PHOTOGRAPHY II — icons out, photographs in
   -----------------------------------------------------------------
   A 46px accent-tinted glyph tile repeated six to a grid was the single
   strongest signal that these pages came out of a template. Every block
   that was using an icon to stand in for a picture now carries a real
   photograph; the icons that remain are the ones doing a UI job — rating
   stars, the FAQ toggle, chevrons, icons inside buttons — where a photo
   would be worse, not better.

   Sizes come from the derivative sets rather than the 1200px originals:
     sm/  560x350  feature bands   ~22 KB
     xs/  200x200  avatars         ~9 KB
   so adding imagery everywhere costs less than the icons' webfont did.
   ========================================================= */

/* ── FEATURE CARDS ──
   The band bleeds out of .feature's 32px padding with a negative margin,
   which leaves the padding and type rhythm of all 109 blocks untouched.
   That padding is constant at every breakpoint, so the bleed is too. */
.feature { overflow: hidden }
.feature-img {
  margin: -32px -32px 22px;
  aspect-ratio: 16/10;
  position: relative;
  overflow: hidden;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
}
.feature-img img {
  width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: center;
  transition: transform .7s cubic-bezier(.2,.7,.3,1);
}
.feature:hover .feature-img img { transform: scale(1.05) }
/* The same theme scrim the gallery uses, so photography sits inside each
   vertical's palette rather than on top of it. */
.feature-img::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to bottom, transparent 45%, var(--scrim-soft) 100%);
}

/* ── TESTIMONIAL AVATARS ──
   Forty-five reviews, every one of them a pair of initials in a circle.
   Real faces are the difference between a testimonial that reads as a
   quote and one that reads as filler. */
.testimonial-avatar { overflow: hidden; padding: 0 }
.testimonial-avatar img {
  width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: center top;
}

@media (prefers-reduced-motion: reduce) {
  .feature:hover .feature-img img { transform: none }
}

/* ── LOCATION MAP ──────────────────────────────────────────────────────
   Replaces the icon-and-address placeholder with a real, interactive map.

   Deliberately NOT filtered. The usual trick for putting a Google map on a
   dark page is invert() + hue-rotate(), and it is tempting here — but the
   filter applies to the whole frame including the Google wordmark and the
   Terms link, and Google's terms require that attribution stay unaltered
   and unobscured. A bright panel is a fair trade for not breaking them.

   The iframe is lazy so it costs nothing until scrolled to, which also
   means Google sets no cookies for visitors who never reach the footer. */
.map-embed {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--bg-2);
  box-shadow: var(--e1), var(--edge);
}
.map-embed iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0; display: block;
}
/* Top-right on purpose: Google's logo sits bottom-left and the Terms link
   bottom-right, and neither may be covered. */
.map-embed .map-open {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 16px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent) !important;
  font-size: 12px; font-weight: 600; letter-spacing: .01em;
  box-shadow: var(--e2);
  transition: filter .25s, transform .25s;
}
.map-embed .map-open:hover { filter: brightness(1.08); transform: translateY(-1px) }
.map-embed .map-open i { font-size: 12px }

@media (max-width: 600px) {
  .map-embed { aspect-ratio: 4 / 3 }
  .map-embed .map-open { padding: 8px 13px; font-size: 11px }
}

/* ── INTERACTION POLISH ────────────────────────────────────────────────
   Small things, all on markup that already exists, that separate a page
   that looks designed from one that looks assembled. */

/* Anchor targets landed underneath the fixed nav on any direct #hash
   link — the jump nav only avoided it by scrolling with its own offset in
   JS, which does nothing for a pasted link, a browser restore or a
   keyboard user tabbing to a target. */
[id] { scroll-margin-top: calc(var(--nav-h) + var(--preview-h) + 20px) }

/* Nav links: a wiping underline instead of a colour swap alone. Excludes
   .nav-cta, which lives in the same list but is a filled pill. */
.nav-links a:not(.nav-cta) { position: relative }
.nav-links a:not(.nav-cta)::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 1px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .4s var(--ease);
}
.nav-links a:not(.nav-cta):hover::after,
.nav-links a:not(.nav-cta).active::after { transform: scaleX(1) }

/* Primary buttons faded to 85% opacity on hover, which reads as a control
   going disabled rather than becoming active. Brightness and a coloured
   shadow read as lifting toward the pointer, which is what was meant. */
.btn-primary:hover {
  opacity: 1;
  transform: translateY(-2px);
  filter: brightness(1.07);
  box-shadow: 0 10px 26px -10px var(--accent), var(--e1);
}
.btn-primary:active { transform: translateY(0); filter: brightness(.97) }
.btn-ghost:hover { background: var(--accent-dim) }
/* .nav-cta carries transition:opacity !important, so the replacement has
   to match it to get anything else to animate at all. */
.nav-cta {
  transition: opacity .3s, filter .3s, box-shadow .3s, transform .3s !important;
}
.nav-cta:hover {
  opacity: 1 !important;
  transform: translateY(-1px);
  filter: brightness(1.07);
  box-shadow: 0 8px 20px -8px var(--accent);
}

/* FAQ answers toggled display straight from none to block, so they could
   not animate at all. allow-discrete keeps display in the transition long
   enough for the fade to run. Both this and @starting-style degrade to
   the instant show/hide that was already shipping. */
.faq-answer {
  opacity: 0;
  transition: opacity .32s var(--ease), display .32s allow-discrete;
}
.faq-item.open .faq-answer { opacity: 1 }
@starting-style {
  .faq-item.open .faq-answer { opacity: 0 }
}

/* ── REDUCED MOTION ────────────────────────────────────────────────────
   The block further up clamps animation-duration, which does nothing to
   a progress-based timeline, and nothing to a view transition. Both have
   to be switched off by name. */
@media (prefers-reduced-motion: reduce) {
  .reveal, .hero-art img, .hero-visual > svg, .hero-visual > img, .ntl-progress {
    animation: none !important;
    animation-timeline: auto !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .ntl-progress { display: none }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) {
    animation: none !important;
  }
}
