/* GintiFlow website — v5 claymorphism (docs/GintiFlow_website_demo_v5_full_claymorphism.html).
   Ported into the real site's existing class contract — every selector below is referenced by
   real HTML/JS (calculator pages, the invoice generator) — so only colour/shadow/radius/type
   changed here, no DOM structure assumed. New classes (`.btn*`, `.wrap`, `.home-*`, `.tool*`,
   `.dashboard`/`.dash*`) exist only for index.html's richer landing layout. */

@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Outfit:wght@500;600;700;800&display=swap');

:root {
  --pearl: #FAF9F6;
  --white: #FFFFFF;
  --ink: #1B1830;
  /* Body-copy colour — softer than --ink, darker than --muted. */
  --ink2: #423E5C;
  /* Secondary/caption text only — fails AA for extended body copy, matches the app's own
     `subtle`-vs-`muted` split (see mobile/src/theme/colors.ts). */
  --muted: #6F6B78;
  --border: #E6E2EA;

  /* Text/CTA green — AA-safe on pearl (mirrors the app's `forest`, Part 33/40's fix for the
     bright #159447 failing AA as text). Never use --green-bright for text. */
  --green: #116B3A;
  --green-bright: #159447;
  --green-bright-2: #0D7438;
  --green-bg: #EFFAF2;
  --green-bg-2: #DDF4E3;

  --lavender: #B9A7E8;
  --lavender-deep: #8E78C8;
  --lavender-pale: #EEE9FA;
  --lavender-wash: #F5F1FC;

  --indigo: #25204F;
  --indigo-2: #332B67;
  --indigo-soft: #E9E6F6;

  --amber: #A96A08;
  --amber-bg: #FFF7E7;
  --red: #B42318;
  --red-bg: #FDF0EE;

  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  --shadow: 12px 16px 30px rgba(37,32,79,.13), -10px -10px 24px rgba(255,255,255,.9), inset 1px 1px 0 rgba(255,255,255,.7);
  --shadow-sm: 7px 9px 16px rgba(37,32,79,.10), -6px -6px 13px rgba(255,255,255,.9), inset 1px 1px 0 rgba(255,255,255,.65);
  --shadow-green: 8px 11px 20px rgba(21,148,71,.20), -5px -5px 12px rgba(255,255,255,.6), inset 1px 1px 0 rgba(255,255,255,.3);
  --shadow-indigo: 12px 16px 30px rgba(18,14,50,.28), -6px -6px 15px rgba(92,81,145,.16), inset 1px 1px 0 rgba(255,255,255,.10);
  /* For a light card/button floating on a dark section — the other --shadow* tokens' white
   * highlight component (simulating light reflecting off a light surface's own background) glows
   * as a visible white halo against a dark backdrop instead of blending in. Plain dark drop-shadow
   * only, no highlight. (Found on the Business dashboard's white card and the CTA band's button,
   * both sitting on .section.indigo — device/screenshot feedback, 2026-09-11.) */
  --shadow-on-dark: 0 18px 40px rgba(0,0,0,.35), 0 6px 14px rgba(0,0,0,.22);
}

* {
  box-sizing: border-box;
  /* Android Chrome's default tap feedback is an opaque blue-grey rectangle over whatever you
     tapped, for a split second before the next page loads — reads as a rendering glitch, not
     intentional feedback (user-reported on a real Android device, 2026-09-11). Every tappable
     element below has its own :active/:hover treatment instead. */
  -webkit-tap-highlight-color: transparent;
}

html {
  scroll-behavior: smooth;
}

/* Homepage-only brand loader (2026-09-16, user request; revised same day) — the mechanical
   odometer + growth-glyph icon from the app's own splash (mobile/src/onboarding/SplashScreen.tsx).
   All 3 rows now (INVOICING / GINTIFLOW / GROWTHGST), matching the app exactly — the first pass
   dropped the two subtext rows to save markup weight, but the user wanted the full word set.

   Real bug found on first load (not a reload): with `@import`ing the Outfit/DM Sans font at the
   top of this file, first-visit CSS is render-blocking until those fonts download, but an SVG's
   SMIL animation timeline starts ticking from when the SVG is PARSED, independent of when the
   page actually paints. On a slow/cold first load the whole ~1.3s roll could finish invisibly
   before the browser ever painted a frame — the user would only ever see the landed end state,
   looking like no animation played at all. A page reload has the fonts cached, paint happens
   immediately, and the roll is visible in real time — exactly the "works on reload, not the first
   time" symptom reported. Fixed by decoupling the animation's start from parse time: every
   `<animateTransform>` below is `begin="indefinite"`, and the tiny inline script right after the
   loader markup in index.html fires `.beginElement()` on all of them (and adds `.playing` here,
   which is what actually carries the fade-out timing) inside a double `requestAnimationFrame` —
   the standard "wait for one real paint to have happened" technique, so the roll is guaranteed to
   start only once the browser can actually show it, regardless of font/network timing. A
   `<noscript>` in index.html hides #site-loader outright for JS-disabled visitors, since without
   JS `begin="indefinite"` would never fire and the loader would otherwise sit on screen forever
   (this is the one reason this loader is no longer a pure zero-JS decoration). */
#site-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--pearl);
}
#site-loader.playing {
  animation: siteLoaderHide .5s ease 1500ms forwards;
}
.site-loader-mark {
  width: min(88vw, 420px);
}
.site-loader-mark svg {
  display: block;
  width: 100%;
  height: auto;
}
.gfL {
  font-family: "Outfit", sans-serif;
  text-anchor: middle;
}
.gfL.lg { font-size: 64px; font-weight: 900; }
.gfL.lg.ink { fill: var(--ink); }
.gfL.lg.forest { fill: var(--green); }
.gfL.sm { font-size: 28px; font-weight: 700; fill: #6B6B6B; }
@keyframes siteLoaderHide {
  to { opacity: 0; visibility: hidden; pointer-events: none; }
}
/* No separate reduced-motion fallback needed beyond removing the roll itself -- SMIL respects
   prefers-reduced-motion in current major browsers by freezing at the end state, and the loader
   still fades away on its own timer either way, so nothing is ever stuck on screen. */
@media (prefers-reduced-motion: reduce) {
  #site-loader.playing { animation-duration: .01s; animation-delay: 0s; }
}

/* Small inline spinner — the "Generating…" state on the invoice generator's Download PDF
   button, replacing a plain text-only swap (user-requested "premium" processing feedback). */
.btn-spinner {
  display: inline-block;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  vertical-align: -3px;
  margin-right: 8px;
  animation: spin .7s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .btn-spinner { animation: none; }
}

body {
  margin: 0;
  color: var(--ink);
  font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  line-height: 1.6;
  background:
    radial-gradient(circle at 9% 8%, rgba(218,205,242,.35), transparent 24%),
    radial-gradient(circle at 92% 28%, rgba(232,225,248,.45), transparent 26%),
    linear-gradient(135deg, #FAF9F5 0%, #F7F4FB 50%, #FAF9F5 100%);
  /* `background-attachment: fixed` was cut (2026-09-11) — it's the classic cause of a blank/
     white flash on scroll (repaint lag on the fixed layer, worse on mobile), which is exactly
     what showed up scrolling this page in Chrome. Default (scroll) attachment paints as part of
     the normal document background, so it always covers the full page height correctly. */
}

.page {
  max-width: 720px;
  margin: 0 auto;
  padding: 48px 24px 96px;
}

.page--wide {
  max-width: 1080px;
}

/* index.html's content width — wider than the standard .page reading column, since it's a
   landing page, not a document. Not used by any other page. Sections needing a full-bleed
   background (`.section.*`) wrap this inside themselves instead of constraining `<main>` itself,
   so colour can run edge to edge while the content stays readable-width. */
.wrap {
  max-width: 980px;
  margin: 0 auto;
  padding: 0 24px;
}

/* Full-bleed section backgrounds (index.html) — alternating white/lavender/indigo bands give the
   page a rhythm; without them every block sat on the same flat pearl and read as a single long
   scroll of text with a few buttons, not a designed page (device feedback, 2026-09-11). */
.section {
  padding: 72px 0;
  position: relative;
  overflow: hidden;
}
.section.white { background: rgba(255, 255, 255, .55); }
.section.lav { background: linear-gradient(145deg, #EEE9F9, #E4DCF4); }
.section.indigo { background: linear-gradient(145deg, #332B67, #211B45); color: #fff; }
.section.indigo .eyebrow { color: #D9CDEF; }
.section.indigo .title { color: #fff; }
.section.indigo .title span { color: #DCCFF1; }
.section.indigo .sub { color: #C9C1E0; }
/* A soft decorative corner blob — the one purely-ornamental touch carried over from the demo,
   kept deliberately subtle (low opacity, blurred via the gradient itself, non-interactive). */
.section:before {
  content: "";
  position: absolute;
  width: 280px;
  height: 280px;
  border-radius: 50%;
  right: -120px;
  top: -110px;
  background: linear-gradient(145deg, rgba(255,255,255,.7), rgba(204,187,234,.28));
  pointer-events: none;
}
.section.indigo:before {
  background: linear-gradient(145deg, rgba(116,99,174,.22), rgba(255,255,255,.03));
}

.eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1.6px;
  font-weight: 800;
  color: var(--green);
}
.title {
  font-family: "Outfit", sans-serif;
  font-size: clamp(26px, 4vw, 34px);
  font-weight: 700;
  letter-spacing: -.8px;
  line-height: 1.15;
  margin: 8px 0 12px;
  color: var(--ink);
}
.title span { color: var(--indigo); }
.sub {
  max-width: 620px;
  color: var(--ink2);
  line-height: 1.7;
  font-size: 15px;
}

.wordmark {
  font-family: "Outfit", "DM Sans", sans-serif;
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -.3px;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

/* Split "Ginti"/"Flow" colouring — matches the app's own compact header brand mark
   (mobile/src/components/brand/GintiFlowWordmark.tsx, used on Home/PersonalHomeTabScreen), not a
   new colour choice. Previously plain --ink text end to end (real-device feedback, 2026-09-19:
   flagged as not matching the app's actual black-ink + green wordmark). */
.wm-ink { color: var(--ink); }
.wm-forest { color: var(--green); }

/* Was a plain "₹" glyph in a gradient box -- not the actual brand mark. Fixed 2026-09-16 (user:
   "why you hiding our brand identity everywhere") to the real icon, same tight PNG crop of the
   true logo master used everywhere else (mobile app icon, in-app header, splash, homepage
   loader) -- see assets/brand/icon-glyph.png's provenance in mobile/docs/build-log.md. This is
   the nav on every single page (all 14 HTML files share this one class), so one fix here covers
   the whole site. */
.wordmark:before {
  content: "";
  display: inline-block;
  width: 30px;
  height: 28px;
  background-image: url("/assets/brand/icon-glyph.png");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

nav {
  /* Bottom trimmed from 18px (real-device feedback, 2026-09-19: too much air between the logo
     and the "Coming soon" badge below it on the homepage hero — see .hero's matching change). */
  padding: 18px 24px 10px;
}

h1 {
  font-family: "Outfit", "DM Sans", sans-serif;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -.8px;
  margin: 32px 0 4px;
  color: var(--ink);
}

.updated {
  color: var(--muted);
  font-size: 13px;
  margin-bottom: 32px;
}

h2 {
  font-family: "Outfit", "DM Sans", sans-serif;
  font-size: 19px;
  font-weight: 700;
  margin-top: 36px;
  margin-bottom: 8px;
  color: var(--ink);
}

p, li {
  color: var(--ink2);
  font-size: 15px;
}

ul {
  padding-left: 20px;
}

a {
  color: var(--green);
}

.callout {
  background: linear-gradient(145deg, #FFFFFF, var(--green-bg-2));
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin: 16px 0;
  font-size: 14px;
  color: var(--ink2);
  box-shadow: var(--shadow-sm);
}

/* ---- Hero (index.html) ---- */
.hero {
  /* Top trimmed from 24px — paired with nav's own bottom-padding trim above, cuts the gap above
     the "Coming soon" badge by about half without removing the breathing room entirely. */
  padding: 12px 0 8px;
  text-align: center;
}

.hero-title {
  font-family: "Outfit", "DM Sans", sans-serif;
  font-size: clamp(30px, 5vw, 42px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -1px;
  margin: 0 0 14px;
  color: var(--ink);
}

.hero-sub {
  font-size: 16px;
  color: var(--ink2);
  max-width: 480px;
  margin: 0 auto 22px;
}

.badge {
  display: inline-block;
  background: linear-gradient(145deg, #F5F1FC, #DDD3F1);
  color: var(--indigo);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .2px;
  padding: 8px 15px;
  border-radius: 999px;
  box-shadow: var(--shadow-sm);
  text-decoration: none;
}

/* ---- App promo (every calculator + the invoice generator) ---- */
/* A consistent "this is better in the app" callout, tied to what each page actually does — not a
   generic banner repeated verbatim. Sits on the indigo surface (like the homepage's other dark
   cards), so its badge/button reuse --shadow-on-dark, not the light-surface clay shadows. */
.app-promo {
  display: flex;
  align-items: center;
  gap: 20px;
  margin: 40px 0;
  padding: 24px;
  border-radius: var(--radius-lg);
  background: linear-gradient(145deg, #332B67, #211B45);
  color: #fff;
  box-shadow: var(--shadow-indigo);
}
@media (max-width: 560px) {
  .app-promo { flex-direction: column; align-items: flex-start; }
}
.app-promo-text { flex: 1; }
.app-promo-text strong {
  display: block;
  font-family: "Outfit", sans-serif;
  font-size: 16px;
  margin-bottom: 4px;
}
.app-promo-text p {
  color: #C9C1E0;
  font-size: 13px;
  margin: 0 0 14px;
}
.app-promo .badge {
  box-shadow: var(--shadow-on-dark);
  margin-bottom: 10px;
}

/* Small blurred "sneak peek" thumbnail — decorative only (no real screenshot), same shapes as
   the hero mock, just abstracted and blurred behind a lock. */
.app-teaser {
  position: relative;
  width: 76px;
  height: 76px;
  flex-shrink: 0;
  border-radius: 16px;
  background: linear-gradient(145deg, #FFFFFF, #F0EDF5);
  box-shadow: var(--shadow-on-dark);
  overflow: hidden;
}
.app-teaser-blur {
  padding: 12px 10px;
  filter: blur(2.5px);
  opacity: .9;
}
.app-teaser-line {
  height: 5px;
  border-radius: 3px;
  background: var(--lavender-pale);
  margin-bottom: 7px;
}
.app-teaser-block {
  height: 20px;
  border-radius: 7px;
  background: linear-gradient(145deg, #332B67, #211B45);
  margin-bottom: 7px;
}
.app-teaser-lock {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(37, 32, 79, .32);
}
.app-teaser-lock svg {
  width: 18px;
  height: 18px;
  stroke: #fff;
  stroke-width: 2;
  fill: none;
}

/* ---- Buttons (index.html CTAs) ---- */
/* Flattened 2026-09-16 alongside the calculator tiles -- same user feedback ("3D floating, not
   readable") applied to these two hero buttons, which the first flatten pass missed since it only
   covered .tool/.tool-icon. No gradient, no neumorphic dual-shadow; a plain flat shadow only on
   hover, matching the app's own Button component (solid forest primary / outlined neutral). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 0;
  border-radius: 15px;
  padding: 13px 20px;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease;
}

.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(27,24,48,.12);
}
/* Replaces the disabled tap-highlight rectangle with an actual pressed state. */
.btn:active {
  transform: translateY(0) scale(.97);
  opacity: .9;
}

.btn-primary {
  background: var(--green);
  color: #fff;
}

.btn-outline {
  background: var(--white);
  color: var(--ink);
  border: 1px solid var(--border);
}

.btn-row {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 24px 0 14px;
}

.small {
  font-size: 12px;
  color: var(--muted);
}

/* ---- Illustrative hero mock (index.html only) ---- */
.hero-art {
  display: flex;
  justify-content: center;
  margin: 56px 0 8px;
  position: relative;
}

/* Floating badge chips around the phone mock — decorative reinforcement of the three things the
   app actually does (bill, get paid, plan), not new claims. Hidden below 780px: there isn't room
   beside a full-width phone mock on a narrow screen without overlapping it. */
.float {
  position: absolute;
  border-radius: 18px;
  background: linear-gradient(145deg, #FFFFFF, #F0EDF5);
  box-shadow: var(--shadow-sm);
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 700;
  color: var(--indigo);
  white-space: nowrap;
}
.float.one { top: 10px; left: -18px; background: linear-gradient(145deg, #F8FFFA, #D8F0E0); color: var(--green); }
.float.two { top: 60px; right: -30px; }
.float.three { bottom: 40px; left: -40px; background: linear-gradient(145deg, #F8F5FD, #DCCFF1); }
@media (max-width: 780px) {
  .float { display: none; }
}

.hero-mock {
  width: 100%;
  max-width: 300px;
  border: 8px solid var(--indigo);
  border-radius: 32px;
  background: linear-gradient(145deg, #FBFAF7, #ECE8F2);
  padding: 20px 16px;
  box-shadow: var(--shadow-indigo), 0 30px 55px rgba(44,37,79,.20);
  text-align: left;
}

.hero-mock-top {
  font-size: 10px;
  color: var(--muted);
}

.hero-mock-title {
  font-family: "Outfit", sans-serif;
  font-size: 22px;
  font-weight: 700;
  margin: 6px 0 14px;
  color: var(--ink);
}

.hero-mock-money {
  background: linear-gradient(145deg, #40376F, #241D49);
  color: #fff;
  border-radius: 18px;
  padding: 16px;
  box-shadow: var(--shadow-indigo);
}

.hero-mock-money small {
  font-size: 9px;
  letter-spacing: .6px;
  opacity: .75;
}

.hero-mock-money strong {
  display: block;
  font-family: "Outfit", sans-serif;
  font-size: 24px;
  margin-top: 5px;
}

.hero-mock-box {
  background: linear-gradient(145deg, #FFFFFF, #F0EDF5);
  border-radius: 16px;
  padding: 13px;
  margin-top: 10px;
  box-shadow: var(--shadow-sm);
}

.hero-mock-box b {
  font-family: "Outfit", sans-serif;
  font-size: 14px;
}

.hero-mock-line {
  height: 6px;
  background: #DDEDDD;
  border-radius: 8px;
  margin-top: 9px;
  overflow: hidden;
}

.hero-mock-line i {
  display: block;
  width: 58%;
  height: 100%;
  background: linear-gradient(90deg, var(--green), #27B765);
  border-radius: 8px;
}

.hero-mock-caption {
  font-size: 10px;
  color: var(--muted);
  margin: 8px 0 0;
}

.hero-mock-note {
  text-align: center;
  font-size: 11px;
  color: var(--muted);
  margin-top: 10px;
}

.cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin: 40px 0;
}

@media (max-width: 560px) {
  .cards {
    grid-template-columns: 1fr;
  }
}

.feature-card {
  border-radius: var(--radius-lg);
  padding: 26px;
  background: linear-gradient(145deg, #FFFFFF, #F5F2FA);
  box-shadow: var(--shadow-sm);
}
.feature-card.green {
  background: linear-gradient(145deg, #FFFFFF, #EDE7F7);
}

.feature-card h2 {
  margin-top: 12px;
}

.feature-card p {
  margin-bottom: 0;
}

.feature-card .pill {
  display: inline-block;
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  background: var(--lavender-pale);
  color: var(--indigo);
}
.feature-card.green .pill {
  background: var(--green-bg);
  color: var(--green);
}

.feature-card ul {
  list-style: none;
  padding: 0;
  margin: 18px 0 0;
}
.feature-card li {
  padding: 9px 0;
  border-top: 1px solid rgba(86, 72, 125, .10);
  font-size: 13px;
}
.feature-card li:first-child { border-top: 0; }
.feature-card li:before {
  content: "✓";
  color: var(--green);
  font-weight: 800;
  margin-right: 8px;
}

/* ---- Goal planner section (index.html) ---- */
.goal {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
}
@media (max-width: 780px) {
  .goal { grid-template-columns: 1fr; }
}
.goal-visual {
  min-height: 320px;
  border-radius: var(--radius-xl);
  background: linear-gradient(145deg, #F2ECFA, #DED4EF);
  box-shadow: var(--shadow);
  display: grid;
  place-items: center;
  position: relative;
}
.orb {
  width: 190px;
  height: 190px;
  border-radius: 50%;
  background: conic-gradient(var(--green-bright) 0 22%, #C9BCE5 22% 100%);
  box-shadow: inset 12px 12px 22px rgba(255,255,255,.85), inset -16px -18px 28px rgba(75,58,123,.2), 12px 18px 30px rgba(44,37,79,.15);
  display: grid;
  place-items: center;
}
.orb div {
  width: 142px;
  height: 142px;
  border-radius: 50%;
  background: linear-gradient(145deg, #FFFFFF, #F0EDF5);
  box-shadow: var(--shadow-sm);
  display: grid;
  place-items: center;
  font-family: "Outfit", sans-serif;
  font-size: 26px;
  font-weight: 800;
  color: var(--indigo);
  text-align: center;
}
.orb div small {
  display: block;
  font-family: "DM Sans", sans-serif;
  font-size: 10px;
  font-weight: 500;
  color: var(--muted);
  margin-top: 2px;
}

/* ---- Business dashboard section (index.html) ---- */
.dashboard {
  display: grid;
  grid-template-columns: .9fr 1.1fr;
  gap: 22px;
  margin-top: 36px;
}
@media (max-width: 780px) {
  .dashboard { grid-template-columns: 1fr; }
}
.dash {
  border-radius: var(--radius-lg);
  padding: 26px;
}
.dash.indigo {
  background: linear-gradient(145deg, #40376F, #231D47);
  box-shadow: var(--shadow-indigo);
}
.dash.white {
  background: linear-gradient(145deg, #FFFFFF, #EFECF5);
  box-shadow: var(--shadow-on-dark);
  color: var(--ink);
}
.dash-label {
  font-size: 11px;
  letter-spacing: .04em;
  font-weight: 800;
  opacity: .8;
}
.dash-amount {
  font-family: "Outfit", sans-serif;
  font-size: 38px;
  font-weight: 800;
  margin: 8px 0 14px;
}
.dash-caption {
  font-size: 13px;
  opacity: .85;
  line-height: 1.5;
}
.chart {
  height: 130px;
  display: flex;
  align-items: flex-end;
  gap: 12px;
  padding-top: 20px;
}
.chart .bar {
  flex: 1;
  border-radius: 8px 8px 3px 3px;
  background: linear-gradient(180deg, #D8F0E0, #B8DFCA);
  box-shadow: 3px 4px 8px rgba(44,37,79,.08), -2px -2px 5px rgba(255,255,255,.9);
}
.chart .bar:last-child {
  background: linear-gradient(180deg, #28B866, #108340);
  box-shadow: var(--shadow-green);
}
.chart-labels {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: 10px;
  margin-top: 8px;
}

/* ---- Final CTA band (index.html) ---- */
.cta {
  border-radius: var(--radius-xl);
  background: linear-gradient(145deg, #40376F, #211A43);
  color: #fff;
  padding: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  box-shadow: var(--shadow-indigo);
  margin: 56px 0;
}
.cta h2 {
  font-family: "Outfit", sans-serif;
  font-size: 28px;
  margin: 4px 0;
  color: #fff;
}
.cta p {
  color: #DED9EE;
  margin: 0;
}
.cta .eyebrow { color: #CFC4E7; }
/* Buttons on a dark section/band glow the same white-highlight way .dash.white did above — same
   fix, a plain dark shadow instead of the light-surface clay formula. */
.section.indigo .btn, .cta .btn {
  box-shadow: var(--shadow-on-dark);
}
.section.indigo .btn:hover, .cta .btn:hover {
  box-shadow: 0 22px 46px rgba(0,0,0,.4), 0 8px 18px rgba(0,0,0,.26);
}

/* ---- Free-tools icon grid (index.html) ---- */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin: 24px 0 8px;
}

@media (max-width: 640px) {
  .tool-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* Flattened 2026-09-16 (user device/readability feedback: the neumorphic gradient+dual-shadow
   treatment below read as "3D floating" and hurt legibility) -- flat white card + a flat green
   icon badge, matching the app's own flat design system (colors.forest on colors.mint, never a
   gradient) instead of this file's earlier claymorphism pass. Kept the hover lift as a plain,
   single flat shadow -- still gives tap/hover feedback without the soft-UI look at rest. */
.tool {
  display: block;
  padding: 18px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  color: var(--ink);
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}

.tool:hover {
  transform: translateY(-3px);
  border-color: var(--green);
  box-shadow: 0 8px 20px rgba(27,24,48,.08);
}
.tool:active {
  transform: scale(.97);
  opacity: .9;
}

/* SVG line icons (Feather set, inlined — no external request), not the text-glyph placeholders
   ("circle circle" — user feedback, 2026-09-11) the first pass used. */
.tool-icon {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--green-bg);
  color: var(--green);
  display: grid;
  place-items: center;
  margin-bottom: 12px;
}
.tool-icon svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .4s ease;
}
/* A little pop + wiggle on the icon itself when its tile is hovered or tapped — kept subtle
   (small scale/rotation, sub-second) so it reads as polish, not a gimmick. */
.tool:hover .tool-icon svg,
.tool:active .tool-icon svg {
  animation: iconPop .5s ease;
}
@keyframes iconPop {
  0% { transform: scale(1) rotate(0deg); }
  40% { transform: scale(1.18) rotate(-10deg); }
  70% { transform: scale(.95) rotate(5deg); }
  100% { transform: scale(1) rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) {
  .tool:hover .tool-icon svg, .tool:active .tool-icon svg { animation: none; }
}

.tool h3 {
  font-family: "Outfit", sans-serif;
  font-size: 15px;
  margin: 0 0 4px;
  color: var(--ink);
}

.tool p {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
  margin: 0;
}

/* ---- "Coming soon" placeholder (index.html, 2026-09-16) ----
   A richer 4-tile "first look inside the app" version of this section (real onboarding-screen
   copy + representative visuals) was built, then deliberately pulled the same session — user
   decision: don't reveal app UI/features before launch, in case a competitor copies the concept
   and ships first. Full HTML+CSS saved verbatim at
   docs/website-app-preview-DRAFT-do-not-publish.txt (outside website/, so it can never
   accidentally get deployed) — paste it back in once the app actually ships. This is just the
   flat "Coming soon" line + the two store badges that remain live in the meantime. */
.app-preview-stores {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}
.store-badge {
  display: inline-block;
  background: var(--pearl);
  border: 1px solid var(--border);
  color: var(--ink2);
  font-size: 12px;
  font-weight: 700;
  padding: 8px 15px;
  border-radius: 999px;
}

/* ---- Indigo "why us" band (index.html) ---- */
.band-indigo {
  background: linear-gradient(145deg, #332B67, #211B45);
  color: #fff;
  border-radius: 30px;
  padding: 36px 32px;
  margin: 48px 0;
  box-shadow: var(--shadow-indigo);
}

.band-indigo h2 {
  color: #fff;
}

.band-indigo ul {
  padding-left: 0;
  list-style: none;
  margin: 18px 0 0;
}

.band-indigo li {
  color: #DED9EE;
  padding: 10px 0;
  border-top: 1px solid rgba(255,255,255,.14);
  font-size: 14px;
}

.band-indigo li:first-child {
  border-top: 0;
}

.band-indigo li strong {
  color: #fff;
}

.footer-links {
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--muted);
}

.footer-links a {
  color: var(--ink2);
  margin-right: 16px;
}

/* index.html uses <footer class="wrap footer-links"> directly (no .page wrapper supplying its
   usual bottom padding), so add it back here. */
footer.footer-links {
  padding-bottom: 40px;
}

/* ---- Zero-login calculators (Part 24) ---- */
.calc-intro { color: var(--ink2); font-size: 15px; margin: 0 0 28px; }

.calc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 16px 20px;
  margin: 0 0 8px;
}
/* Bonds calculator only — the payout <select>'s text ("Non-cumulative (every 6mo)") needs
   meaningfully more room than a rate field ever does (1-2 digits), so this page doesn't split the
   row evenly like every other calc-grid does. Amount / rate / payout ≈ 33% / 17% / 50%. Combined
   with the shorter label + option text (user-reported, 2026-09-11), the full option text — bracket
   included — now fits without truncating on a real device. */
.calc-grid--bonds {
  grid-template-columns: 2fr 1fr 3fr;
}
@media (max-width: 560px) {
  .calc-grid--bonds {
    grid-template-columns: 1fr 1fr;
  }
  .calc-grid--bonds .calc-field:last-child {
    grid-column: 1 / -1;
  }
}
.calc-field { display: flex; flex-direction: column; gap: 6px; }
/* Reserves 2 lines' worth of height for every label in a row, so a field whose label wraps (e.g.
   the Bonds calculator's "Assumed annual rate (% per year)" next to two single-line labels)
   doesn't push its own input down out of alignment with its row-mates (user-reported, 2026-09-11).
   Harmless on short single-line labels elsewhere — just reserves a little empty space below them,
   which keeps every calc-grid row's inputs starting on the same baseline regardless of page. */
.calc-field label { display: flex; align-items: flex-end; min-height: 34px; font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--ink2); }
.calc-field input, .calc-field select {
  font: inherit;
  font-size: 16px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--ink);
  width: 100%;
}
/* A native <select> just hard-clips its selected option's text with no "…" when it's wider than
   the box — the Bonds/Business-Tax dropdowns hit this (user-reported, 2026-09-11; fixed there by
   shortening the option text). Belt-and-braces here too, so any future long option degrades to a
   visible ellipsis instead of an abrupt cut mid-word. */
.calc-field select {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.calc-field input:focus, .calc-field select:focus { outline: 2px solid var(--green); outline-offset: 1px; }

.calc-result {
  margin: 24px 0 8px;
  padding: 22px;
  border-radius: var(--radius-md);
  background: linear-gradient(145deg, #FFFFFF, var(--green-bg-2));
  box-shadow: var(--shadow-sm);
}
.calc-result .headline { font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ink2); margin: 0 0 4px; }
.calc-result .figure { font-family: "Outfit", sans-serif; font-size: 30px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); margin: 0; }
.calc-result .rows { margin: 14px 0 0; padding: 0; list-style: none; }
.calc-result .rows li { display: flex; justify-content: space-between; padding: 5px 0; font-size: 14px; color: var(--ink2); font-variant-numeric: tabular-nums; }
.calc-result .rows li span:last-child { font-weight: 600; color: var(--ink); }

.calc-note { font-size: 13px; color: var(--muted); margin: 12px 0 0; }

/* Was a single line of plain blue-ish text links ("FD RD SIP…") — restyled to match the rest of
   the site's clay-chip language (user-reported as too plain, 2026-09-11). The "More free tools"
   <strong> label and the <a> chips are siblings in the existing markup (no wrapper div to add
   across every page) — flex-basis:100% on the label forces it onto its own line above the chips
   that follow it in the flex row. */
.other-calcs { margin-top: 40px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.other-calcs strong { flex-basis: 100%; }
.other-calcs a {
  display: inline-flex;
  align-items: center;
  padding: 8px 14px;
  border-radius: 999px;
  background: linear-gradient(145deg, #FFFFFF, #F0EDF5);
  box-shadow: var(--shadow-sm);
  color: var(--ink2);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  transition: transform .15s ease, box-shadow .15s ease, color .15s ease;
}
.other-calcs a:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
  color: var(--indigo);
}
.other-calcs a:active {
  transform: scale(.96);
  opacity: .9;
}

/* ---- SEO content sections (Part 24) ---- */
.prose { margin-top: 40px; }
.prose h2 { font-size: 18px; margin-top: 32px; margin-bottom: 8px; }
.prose h3 { font-size: 15px; margin-top: 20px; margin-bottom: 4px; color: var(--ink); }
.prose p { margin: 6px 0; }
.prose .formula {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  background: #fff;
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  overflow-x: auto;
  color: var(--ink2);
  box-shadow: var(--shadow-sm);
}
.prose .example {
  background: linear-gradient(145deg, #FFFFFF, var(--green-bg-2));
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  font-size: 14px;
  box-shadow: var(--shadow-sm);
}

/* ---- Invoice generator (Part 24) ---- */
.ig-toggle {
  display: inline-flex;
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin: 4px 0 24px;
  background: linear-gradient(145deg, #FFFFFF, #EFECF5);
  box-shadow: var(--shadow-sm);
}
.ig-toggle-btn {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 9px 18px;
  border: 0;
  background: transparent;
  color: var(--ink2);
  cursor: pointer;
}
.ig-toggle-btn.is-active {
  background: linear-gradient(145deg, #20A95B, #118241);
  color: #fff;
  border-radius: var(--radius-sm);
}
.ig-toggle-btn:active {
  opacity: .8;
}

.ig-layout {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 32px;
  align-items: start;
}
@media (max-width: 900px) {
  .ig-layout { grid-template-columns: 1fr; }
}

.ig-form fieldset {
  border: 0;
  border-radius: var(--radius-md);
  background: linear-gradient(145deg, #FFFFFF, #F5F2FA);
  box-shadow: var(--shadow-sm);
  padding: 16px 18px 18px;
  margin: 0 0 16px;
}
.ig-form legend {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 6px;
}
.ig-form .calc-field { margin-bottom: 12px; }
.ig-form .calc-field:last-child { margin-bottom: 0; }
.ig-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }
@media (max-width: 480px) { .ig-row { grid-template-columns: 1fr; } }

.ig-item {
  display: grid;
  grid-template-columns: 1fr 90px 56px 100px 28px;
  gap: 8px;
  margin-bottom: 8px;
}
.ig-item input {
  font: inherit;
  font-size: 14px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
  color: var(--ink);
  min-width: 0;
}
.ig-item input:focus { outline: 2px solid var(--green); outline-offset: 1px; }
.ig-rm {
  border: 0;
  background: linear-gradient(145deg, #FFFFFF, #F0EDF5);
  border-radius: 8px;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
}
.ig-rm:hover { color: var(--ink); }
@media (max-width: 900px) {
  .ig-item { grid-template-columns: 1fr 70px 48px 84px 26px; }
}
/* Below ~640px even the trimmed 5-column row squeezes "Description" down to a handful of
   characters (user-reported, 2026-09-11 — barely 4 words visible). Stack instead: description
   gets its own full-width row, the rest wrap to a second row. The remove button is pinned to the
   last column explicitly so it stays on the right whether HSN is showing (GST mode) or hidden
   (non-GST) — auto-placement alone would otherwise leave it drifting depending on how many
   siblings precede it. */
@media (max-width: 640px) {
  .ig-item {
    grid-template-columns: 1fr 1fr 1fr 30px;
    row-gap: 6px;
  }
  .ig-item input:first-child {
    grid-column: 1 / -1;
  }
  .ig-item button {
    grid-column: 4;
  }
  .ig-item input {
    font-size: 15px;
    padding: 10px;
  }
}

.ig-link-btn {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--green);
  background: none;
  border: 0;
  padding: 4px 0;
  cursor: pointer;
}

.ig-download {
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  width: 100%;
  padding: 14px;
  border: 0;
  border-radius: var(--radius-md);
  background: linear-gradient(145deg, #20A95B, #118241);
  color: #fff;
  cursor: pointer;
  margin-top: 4px;
  box-shadow: var(--shadow-green);
}
.ig-download:disabled { opacity: .6; cursor: default; }
.ig-error { color: var(--red); font-size: 13px; margin: 8px 0 0; }

.ig-after {
  background: linear-gradient(145deg, #FFFFFF, var(--green-bg-2));
  border-radius: var(--radius-md);
  padding: 18px 20px;
  margin: 28px 0 0;
  box-shadow: var(--shadow-sm);
}
.ig-after p { margin: 6px 0 10px; font-size: 14px; }

/* preview facsimile */
.ig-preview-wrap { position: sticky; top: 24px; }
.ig-doc {
  border-radius: var(--radius-md);
  background: #fff;
  padding: 26px 24px;
  font-size: 12px;
  color: var(--ink2);
  box-shadow: var(--shadow);
}
.ig-doc-head { display: flex; justify-content: space-between; gap: 16px; border-bottom: 1px solid var(--border); padding-bottom: 12px; }
.ig-biz { font-family: "Outfit", sans-serif; font-size: 17px; font-weight: 700; color: var(--green); }
.ig-doc-meta { text-align: right; }
.ig-doc-title { font-size: 13px; font-weight: 700; color: var(--ink); }
.ig-num { font-size: 12px; font-weight: 700; color: var(--ink); margin: 2px 0 4px; }
.ig-p-line { font-size: 11px; color: var(--muted); margin-top: 2px; }
.ig-billto { margin: 14px 0; }
.ig-label { font-size: 10px; font-weight: 700; letter-spacing: .04em; color: var(--muted); }
.ig-strong { font-weight: 700; color: var(--ink); margin-top: 2px; }
.ig-table { width: 100%; border-collapse: collapse; margin: 10px 0; }
.ig-table th { font-size: 10px; font-weight: 700; color: var(--muted); text-align: left; border-bottom: 1px solid var(--border); padding: 6px 4px; }
.ig-table td { padding: 6px 4px; border-bottom: 1px solid var(--border); font-variant-numeric: tabular-nums; }
.ig-table .r { text-align: right; }
.ig-table .c { text-align: center; }
.ig-totals { width: 62%; margin-left: auto; margin-top: 8px; }
.ig-t-row { display: flex; justify-content: space-between; padding: 3px 0; }
.ig-total-row {
  display: flex; justify-content: space-between;
  background: linear-gradient(145deg, #FFFFFF, var(--green-bg-2));
  border-radius: var(--radius-sm);
  padding: 9px 11px;
  margin-top: 6px;
  font-weight: 700;
  color: var(--ink);
}
.ig-total-row span:last-child { color: var(--green); }
.ig-notes { margin-top: 12px; }
.ig-disclaimer { margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--border); font-size: 10px; color: var(--muted); }
