/* ==================================================================
   Kveldo Theme — v2 depth layer + new components
   Loaded after kveldo-theme.css. Everything here was added when the
   site was brought up to the Inkova visual bar and re-grounded on the
   application's Oxford Blue palette. Tokens come from kveldo-theme.css.
   ================================================================== */

/* ── Inner-page hero (breadcrumb) — icon + tagline ─────────────────── */
.breadcrumb-area {
    background: var(--gradient-ground) !important;
    border-bottom: 0;
    padding: 160px 0 90px !important;
    position: relative;
    overflow: hidden;
}
.breadcrumb-area::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 20% 30%, rgba(124,58,237,0.34), transparent 62%),
        radial-gradient(ellipse at 86% 72%, rgba(34,207,255,0.18), transparent 58%);
    pointer-events: none;
}
.breadcrumb-area > .container { position: relative; z-index: 2; }
.breadcrumb-hero-content {
    display: flex;
    align-items: center;
    /* The column is centred, but the icon+text group sizes to its content and
       was packed flush-left inside it: on /security that left 335px of dead
       space on the right and the hero read as left-weighted. Center the group
       so the hero is optically centred whatever the title's length, while the
       text itself stays left-aligned to read as prose rather than a banner. */
    justify-content: center;
    gap: 28px;
    text-align: left;
}
.breadcrumb-hero-icon {
    font-size: 72px;
    color: #7FD4FF;
    flex-shrink: 0;
    line-height: 1;
}
.breadcrumb-hero-text h1 {
    color: #ffffff !important;
    font-size: clamp(2rem, 4vw, 3rem) !important;
    font-weight: 800 !important;
    margin: 0;
}
.breadcrumb-hero-tagline {
    color: rgba(226,232,240,0.82) !important;
    font-size: 0.98rem;
    line-height: 1.65;
    margin: 10px 0 0;
    max-width: 640px;
}
@media (max-width: 767px) {
    .breadcrumb-area { padding: 130px 0 60px !important; }
    .breadcrumb-hero-content { flex-direction: column; text-align: center; gap: 16px; }
    .breadcrumb-hero-icon { font-size: 54px; }
    .breadcrumb-hero-tagline { margin-inline: auto; }
}

/* ── CTA band — dark gradient card inset on a light surface, so a page
      never runs two dark bands back-to-back into the footer. ────────── */
.request-call-back-area.bg-dark {
    background: var(--color-light-alt) !important;
    background-image: none !important;
    padding: 70px 0 !important;
    position: relative;
}
.request-call-back-area.bg-dark > .container {
    background: var(--gradient-ground);
    border-radius: 22px;
    padding: 56px 60px;
    position: relative;
    overflow: hidden;
    box-shadow: var(--shadow-lg);
}
.request-call-back-area.bg-dark > .container::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 24% 30%, rgba(124,58,237,0.40), transparent 62%),
        radial-gradient(ellipse at 86% 70%, rgba(34,207,255,0.22), transparent 58%);
    pointer-events: none;
}
.request-call-back-area.bg-dark > .container > .row { position: relative; z-index: 1; }
.request-call-back-area.bg-dark h2,
.request-call-back-area.bg-dark .title { color: #fff !important; font-weight: 800; }
.request-call-back-area.bg-dark p { color: rgba(226,232,240,0.86) !important; }
@media (max-width: 767px) {
    .request-call-back-area.bg-dark > .container { padding: 38px 26px; border-radius: 16px; }
}

/* ── Footer — same ground gradient as the hero ─────────────────────── */
footer.bg-dark {
    background: var(--gradient-ground) !important;
    border-top: 0;
    position: relative;
}
footer.bg-dark::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 22% 26%, rgba(124,58,237,0.30), transparent 62%),
        radial-gradient(ellipse at 84% 74%, rgba(34,207,255,0.16), transparent 58%);
    pointer-events: none;
    z-index: 0;
}
footer.bg-dark > .container,
footer.bg-dark > .footer-bottom { position: relative; z-index: 1; }
footer.bg-dark .footer-shape { display: none; }
.footer-bottom {
    border-top: 1px solid rgba(72,127,255,0.35) !important;
    background: transparent !important;
}

/* ── Logo ──────────────────────────────────────────────────────────── */
/* The base theme swaps to a dark "scrolled" logo once the navbar sticks,
   assuming the sticky bar turns white. Kveldo's navbar is Oxford Blue at every
   scroll position, so the dark wordmark vanished against it. Keep the white
   logo throughout and never show the dark one. */
header .navbar .logo-display { display: inline-block !important; }
header .navbar .logo-scrolled { display: none !important; }
/* validnavs re-asserts the swap with !important inside its mobile breakpoint,
   so the override has to be repeated there at matching specificity. */
@media (max-width: 1199px) {
    header nav.navbar.validnavs.navbar-fixed .logo-display { display: block !important; }
    header nav.navbar.validnavs.navbar-fixed .logo-scrolled { display: none !important; }
}

/* ── Section heading rhythm ────────────────────────────────────────── */
.kveldo-eyebrow {
    display: inline-block;
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-theme-dark);
    margin-bottom: 14px;
}
.kveldo-section-title {
    font-size: clamp(1.8rem, 3.2vw, 2.6rem);
    font-weight: 800;
    line-height: 1.14;
    letter-spacing: -0.025em;
    margin-bottom: 16px;
}
.kveldo-section-lead {
    font-size: 1.04rem;
    line-height: 1.75;
    color: var(--text-mid);
    max-width: 720px;
    margin-inline: auto;
}
.text-light .kveldo-eyebrow { color: #7FD4FF; }
.text-light .kveldo-section-title { color: #fff !important; }
.text-light .kveldo-section-lead { color: rgba(226,232,240,0.84); }

/* ── Product mockup — a CSS-drawn stand-in for a real screenshot.
      Replaces the dashed "screenshot goes here" boxes that were 404-ing
      on missing PNGs; swap the markup for an <img> when captures land. ─ */
.kveldo-mock {
    background: #ffffff;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 30px 80px rgba(0,0,0,0.40);
    border: 1px solid rgba(255,255,255,0.16);
}
.kveldo-mock--light {
    box-shadow: var(--shadow-md);
    border: 1px solid #E9EFF9;
}
.kveldo-mock__bar {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 12px 16px;
    background: #F1F5FB;
    border-bottom: 1px solid #E3EAF5;
}
.kveldo-mock__dot { width: 10px; height: 10px; border-radius: 50%; background: #D3DCEA; }
.kveldo-mock__title {
    margin-left: 10px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.kveldo-mock__body { padding: 20px; background: #fff; }
/* Hero variant reserves a clear band at the bottom-left so the floating stat
   badge overlaps empty card rather than a transaction row. */
.kveldo-mock--hero .kveldo-mock__body { padding-bottom: 62px; }
.kveldo-mock__head {
    display: flex; align-items: baseline; justify-content: space-between;
    padding: 0 4px 14px;
}
.kveldo-mock__head strong { font-size: 0.9rem; color: var(--text-dark); font-weight: 700; }
.kveldo-mock__head span { font-size: 0.72rem; color: var(--text-muted); }
.kveldo-mock__stats { display: flex; gap: 10px; padding: 0 4px 16px; }
.kveldo-mock__stat {
    flex: 1;
    background: #F6F9FE;
    border: 1px solid #E7EDF7;
    border-radius: 10px;
    padding: 10px 12px;
}
.kveldo-mock__stat b {
    display: block;
    font-family: 'Montserrat', sans-serif;
    font-size: 1.15rem; font-weight: 800;
    color: var(--color-theme); line-height: 1.2;
}
.kveldo-mock__stat span { font-size: 0.66rem; color: var(--text-muted); }
.kveldo-mock__row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 4px;
    border-bottom: 1px solid #EEF3FA;
}
.kveldo-mock__row:last-child { border-bottom: 0; }
.kveldo-mock__row .lbl { flex: 1; height: 9px; border-radius: 5px; background: #E7EDF7; }
.kveldo-mock__row .lbl.w75 { max-width: 75%; }
.kveldo-mock__row .lbl.w60 { max-width: 60%; }
.kveldo-mock__row .lbl.w45 { max-width: 45%; }
.kveldo-mock__row .txt { flex: 1; font-size: 0.8rem; color: var(--text-mid); }
.kveldo-mock__pill {
    font-size: 0.66rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 100px;
    white-space: nowrap;
}
.kveldo-mock__pill.ok   { background: var(--color-affirm-tint); color: var(--color-affirm); }
.kveldo-mock__pill.wait { background: rgba(225,29,72,0.14);  color: #BE123C; }
.kveldo-mock__pill.info { background: rgba(72,127,255,0.14); color: #2F63D6; }

/* ── On-dark text ──────────────────────────────────────────────────────
   The base theme sets `h1..h6 { color: var(--text-dark) !important }`, which
   is right on the light pages and catastrophic on the dark ones — headings
   rendered near-black on Oxford Blue at 1.07:1. Any section carrying a dark
   ground gets .text-light, and these rules give it a full, legible palette.
   Specificity plus !important is required to beat the base heading rule. ── */
.text-light h1, .text-light h2, .text-light h3,
.text-light h4, .text-light h5, .text-light h6 { color: #FFFFFF !important; }
.text-light p,
.text-light li,
.text-light td { color: rgba(226,232,240,0.88); }
.text-light strong { color: #FFFFFF; }
.text-light a { color: #9FC0FF; }
.text-light a:hover { color: #C8DBFF; }
.text-light .text-muted,
.text-light small { color: rgba(226,232,240,0.66) !important; }
/* The eyebrow chip needs a light-blue on dark; the darkened blue used on the
   light pages drops to 3.2:1 here. */
.text-light .site-heading .sub-title,
.text-light h4.sub-title,
.text-light span.sub-title,
.text-light .kveldo-eyebrow,
.text-light .pill-tag { color: #9FC0FF !important; }

/* Bootstrap's own .text-muted (#6C757D) sits at 4.4:1 on the light-gray band —
   just under AA. Point it at the site token, which is calibrated for both. */
.text-muted { color: var(--text-muted) !important; }

/* ── Contrast repairs ──────────────────────────────────────────────────
   Three components were readable only on the ground they were first designed
   for, and inherited badly everywhere else. Each is pinned to its own colors
   here so the surrounding section can never wash it out. ────────────────── */

/* 1. The mockup is always a light card, including inside a .text-light section.
      Without this it inherits white-on-near-white and the labels vanish. */
.kveldo-mock,
.text-light .kveldo-mock { color: var(--text-mid); }
.text-light .kveldo-mock .kveldo-mock__title { color: var(--text-muted) !important; }
.text-light .kveldo-mock .kveldo-mock__head strong { color: var(--text-dark) !important; }
.text-light .kveldo-mock .kveldo-mock__head span,
.text-light .kveldo-mock .kveldo-mock__stat span { color: var(--text-muted) !important; }
.text-light .kveldo-mock .kveldo-mock__stat b { color: var(--color-theme-dark) !important; }
.text-light .kveldo-mock .kveldo-mock__row .txt { color: var(--text-mid) !important; }
/* Status pills carry meaning, so they keep semantic color — darkened to clear
   4.5:1 against their own tint at 11px. */
.kveldo-mock__pill.ok   { background: var(--color-affirm-tint); color: var(--color-affirm) !important; }
.kveldo-mock__pill.wait { background: rgba(159,18,57,0.12);  color: #9F1239 !important; }
.kveldo-mock__pill.info { background: rgba(47,99,214,0.13);  color: #2F63D6 !important; }
.kveldo-mock__stat b { color: var(--color-theme-dark); }

/* 2. The comparison table is used on a light band (Pricing, Features) and a dark
      one (home). It was styled for light only, so on the dark band it rendered
      dark-gray text on Oxford Blue — 2.3:1. */
.text-light .comparison-table th { background: rgba(255,255,255,0.06); color: #fff; }
.text-light .comparison-table th.kveldo-col { background: rgba(72,127,255,0.22); color: #CFE0FF; }
.text-light .comparison-table td { color: rgba(226,232,240,0.88); border-color: rgba(255,255,255,0.10); }
.text-light .comparison-table tr:hover td { background: rgba(255,255,255,0.04); }
.text-light .comparison-table .kveldo-col { color: #CFE0FF; }
.text-light .comparison-table .check { color: var(--color-affirm-bright); }
.text-light .comparison-table .cross { color: rgba(255,255,255,0.45); }
/* On the light band the tick and the "not included" cross both need to clear
   the small-text ratio; #ccc measured 1.6:1. */
.comparison-table .check { color: var(--color-affirm); }
.comparison-table .cross { color: #6B7280; }

/* 3. Cyan reads as an accent on dark and as invisible on light. Text-sized cyan
      on a light ground uses the darkened variant instead. */
.pill-tag[style*="22CFFF"],
.pill-tag[style*="34,207,255"] {
    color: #0C6179 !important;
    background: rgba(12,97,121,0.10) !important;
    border-color: rgba(12,97,121,0.30) !important;
}

/* ── Resources: category cards + article cards ─────────────────────── */
.resource-categories .resource-cat-card {
    display: flex; flex-direction: column; align-items: center;
    background: #ffffff;
    border-radius: 14px;
    padding: 32px 24px;
    border: 1px solid #E9EFF9;
    box-shadow: var(--shadow-sm);
    text-decoration: none; color: inherit;
    text-align: center; height: 100%;
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.resource-categories .resource-cat-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
    border-color: rgba(72,127,255,0.38);
}
.resource-categories .resource-cat-card i {
    font-size: 38px;
    color: var(--color-theme);
    line-height: 1;
    margin-bottom: 16px;
}
.resource-categories .resource-cat-card h4 { color: var(--text-dark); font-size: 1.06rem; margin-bottom: 8px; }
.resource-categories .resource-cat-card p { color: var(--text-mid); font-size: 0.87rem; line-height: 1.6; margin: 0; }

.article-card {
    display: block;
    background: #ffffff;
    border-radius: 12px;
    border: 1px solid #E9EFF9;
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    text-decoration: none; color: inherit;
    transition: transform 0.25s ease, box-shadow 0.25s ease;
    height: 100%;
}
.article-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.article-card .article-card-body { padding: 22px; }
.article-cat {
    display: inline-block;
    background: rgba(72,127,255,0.10);
    color: var(--color-theme-dark);
    font-weight: 700; font-size: 11px;
    text-transform: uppercase; letter-spacing: 0.06em;
    padding: 4px 10px; border-radius: 100px; margin-bottom: 12px;
}
.article-card h3, .article-card h4 { color: var(--text-dark); margin-bottom: 8px; }
.article-card h3 { font-size: 1.28rem; line-height: 1.3; }
.article-card h4 { font-size: 1rem; line-height: 1.42; }
.article-card p { color: var(--text-mid); line-height: 1.6; font-size: 0.9rem; margin-bottom: 10px; }
.article-meta { color: var(--text-muted); font-size: 0.78rem; }

/* Featured card leads with a gradient panel rather than stock photography. */
.article-card-featured .article-card-art {
    height: 200px;
    background: var(--gradient-ground);
    position: relative;
    display: flex; align-items: center; justify-content: center;
}
.article-card-featured .article-card-art::before {
    content: '';
    position: absolute; inset: 0;
    background:
        radial-gradient(ellipse at 30% 35%, rgba(124,58,237,0.42), transparent 62%),
        radial-gradient(ellipse at 82% 70%, rgba(34,207,255,0.24), transparent 58%);
}
.article-card-featured .article-card-art i {
    font-size: 52px; color: rgba(255,255,255,0.94);
    position: relative; z-index: 1;
}
.article-card-featured h3 { font-size: 1.4rem; }

/* ── Article body typography ───────────────────────────────────────── */
.article-body { max-width: 760px; margin: 0 auto; }
.article-body h2 { font-size: 1.55rem; font-weight: 800; margin: 42px 0 14px; line-height: 1.25; }
.article-body h3 { font-size: 1.14rem; font-weight: 700; margin: 30px 0 10px; }
.article-body p { font-size: 1.02rem; line-height: 1.82; margin-bottom: 18px; color: var(--text-mid); }
.article-body ul, .article-body ol { margin: 0 0 20px; padding-left: 22px; }
.article-body li { font-size: 1.02rem; line-height: 1.78; margin-bottom: 9px; color: var(--text-mid); }
.article-body strong { color: var(--text-dark); font-weight: 700; }
.article-lede {
    font-size: 1.16rem !important;
    line-height: 1.7 !important;
    color: var(--text-dark) !important;
    font-weight: 500;
    margin-bottom: 30px !important;
}
.article-callout {
    background: #fff;
    border: 1px solid #E9EFF9;
    border-left: 3px solid var(--color-cyan);
    border-radius: 0 12px 12px 0;
    padding: 20px 24px;
    margin: 28px 0;
    box-shadow: var(--shadow-sm);
}
.article-callout h4 { font-size: 1rem; margin-bottom: 8px; }
.article-callout p { font-size: 0.96rem; }
.article-callout p:last-child { margin-bottom: 0; }
.article-tocbox {
    background: var(--color-light-mid);
    border-radius: 12px;
    padding: 22px 26px;
    margin-bottom: 34px;
}
.article-tocbox h4 { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted) !important; margin-bottom: 12px; }
.article-tocbox ul { margin: 0; padding-left: 18px; }
.article-tocbox li { font-size: 0.94rem; margin-bottom: 6px; line-height: 1.5; }

/* ── Glossary ──────────────────────────────────────────────────────── */
.glossary-search-bar {
    position: sticky; top: 78px; z-index: 20;
    background: rgba(255,255,255,0.95);
    backdrop-filter: blur(10px);
    border: 1px solid #E9EFF9;
    border-radius: 14px;
    padding: 18px 20px;
    box-shadow: var(--shadow-sm);
    margin-bottom: 30px;
}
.glossary-search-bar input {
    width: 100%;
    border: 1px solid #D8E0EE;
    border-radius: 10px;
    padding: 11px 16px;
    font-family: 'Outfit', sans-serif;
    font-size: 0.95rem;
    outline: none;
}
.glossary-search-bar input:focus { border-color: var(--color-theme); box-shadow: 0 0 0 3px rgba(72,127,255,0.12); }
.glossary-letters { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
/* A letter with no terms behind it is not a link. It used to render as
   <a href="#">, which looked identical to a live letter, hovered blue, and
   jumped the reader to the top of the page when clicked. It is a <span> now,
   and it looks disabled because it is. */
.glossary-letters a,
.glossary-letters span {
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 8px;
    font-size: 0.8rem; font-weight: 700;
    color: var(--text-muted);
    background: #F2F6FD;
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
}
.glossary-letters a:hover { background: var(--color-theme); color: #fff; }
.glossary-letters .is-empty {
    background: #F7F9FD;
    color: #C2CBDC;
    cursor: default;
}
.glossary-group { margin-bottom: 34px; scroll-margin-top: 200px; }
.glossary-group > h2 {
    font-size: 1.55rem; font-weight: 800;
    color: var(--color-theme) !important;
    border-bottom: 2px solid #E9EFF9;
    padding-bottom: 10px; margin-bottom: 18px;
}
.glossary-term {
    background: #fff;
    border: 1px solid #E9EFF9;
    border-radius: 12px;
    padding: 17px 22px;
    margin-bottom: 12px;
    box-shadow: var(--shadow-sm);
}
.glossary-term h3 { font-size: 1rem; font-weight: 700; margin-bottom: 6px; }
.glossary-term p { font-size: 0.92rem; line-height: 1.68; margin: 0; color: var(--text-mid); }
.glossary-term .term-cat {
    display: inline-block;
    font-size: 10.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--color-theme-dark);
    background: rgba(72,127,255,0.10);
    padding: 3px 9px; border-radius: 100px;
    margin-left: 8px; vertical-align: middle;
}
.glossary-empty { text-align: center; padding: 50px 0; color: var(--text-muted); }

/* ── ROI calculator ────────────────────────────────────────────────── */
#kveldo-roi .roi-panel {
    background: #fff;
    border-radius: 14px;
    padding: 36px 32px;
    box-shadow: var(--shadow-sm);
    border: 1px solid #E9EFF9;
}
#kveldo-roi .roi-panel h3 {
    font-size: 1.1rem;
    border-bottom: 2px solid #EEF3FA;
    padding-bottom: 14px;
    margin-bottom: 24px;
}
#kveldo-roi .form-label { font-weight: 600; color: var(--text-dark); margin-bottom: 6px; font-size: 0.9rem; }
#kveldo-roi .form-control {
    border-radius: 9px;
    border: 1px solid #D8E0EE;
    padding: 10px 14px;
    font-family: 'Outfit', sans-serif;
}
#kveldo-roi .form-control:focus { border-color: var(--color-theme); box-shadow: 0 0 0 3px rgba(72,127,255,0.12); }
#kveldo-roi .form-range { accent-color: var(--color-theme); }
#kveldo-roi small.text-muted { display: block; margin-top: 5px; font-size: 0.78rem; color: var(--text-muted) !important; }
#kveldo-roi .roi-badge {
    background: var(--color-light-mid);
    color: var(--color-theme-dark);
    font-weight: 700; font-size: 0.82rem;
    padding: 4px 10px; border-radius: 8px;
    min-width: 52px; text-align: center;
}

#kveldo-roi .roi-results-panel {
    background: var(--gradient-ground);
    color: #fff;
    border-radius: 16px;
    padding: 34px 32px;
    position: sticky;
    top: 100px;
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}
#kveldo-roi .roi-results-panel::before {
    content: '';
    position: absolute; inset: 0;
    background:
        radial-gradient(ellipse at 28% 22%, rgba(124,58,237,0.42), transparent 62%),
        radial-gradient(ellipse at 84% 78%, rgba(34,207,255,0.24), transparent 58%);
    pointer-events: none;
}
#kveldo-roi .roi-results-panel > * { position: relative; z-index: 1; }
#kveldo-roi .roi-kicker {
    text-transform: uppercase; letter-spacing: 0.09em;
    font-size: 0.72rem; font-weight: 700;
    color: rgba(226,232,240,0.72);
    margin-bottom: 8px;
}
#kveldo-roi .roi-headline {
    font-family: 'Montserrat', sans-serif;
    font-size: 2.9rem; font-weight: 800; line-height: 1.08;
    color: #fff;
}
#kveldo-roi .roi-multiplier { font-size: 1rem; color: rgba(226,232,240,0.82); margin-top: 4px; }
#kveldo-roi .roi-results-panel hr { border-color: rgba(255,255,255,0.22); opacity: 1; margin: 22px 0; }
#kveldo-roi .roi-row {
    display: flex; justify-content: space-between; align-items: center;
    gap: 14px;
    padding: 8px 0; font-size: 0.95rem; color: rgba(226,232,240,0.9);
}
#kveldo-roi .roi-row .value { font-weight: 700; color: #fff; white-space: nowrap; }
#kveldo-roi .roi-row.total { border-top: 1px dashed rgba(255,255,255,0.26); padding-top: 14px; margin-top: 6px; }
#kveldo-roi .roi-row.total .value,
#kveldo-roi .roi-row.payback .value { font-size: 1.14rem; }
#kveldo-roi .roi-results-panel .btn { width: 100%; margin-top: 26px; }
#kveldo-roi .roi-fineprint { color: rgba(226,232,240,0.66); font-size: 0.8rem; text-align: center; margin: 10px 0 0; }

.roi-method-block {
    background: #fff;
    border-radius: 12px;
    padding: 24px 28px;
    margin-bottom: 18px;
    border: 1px solid #E9EFF9;
    box-shadow: var(--shadow-sm);
}
.roi-method-block h4 { font-size: 1.04rem; margin-bottom: 10px; }
.roi-method-block p { font-size: 0.94rem; line-height: 1.7; }
.roi-method-block code {
    display: inline-block;
    background: var(--color-light-mid);
    color: var(--color-theme-dark);
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 0.87rem;
    margin: 4px 0;
}
.roi-method-block ul { padding-left: 20px; margin-bottom: 0; }
.roi-method-block ul li { font-size: 0.9rem; line-height: 1.65; color: var(--text-muted); }
@media (max-width: 991px) {
    #kveldo-roi .roi-results-panel { position: static; margin-top: 30px; }
}

/* ── Capability cards (Platform / Features / Security) ─────────────── */
.cap-card {
    background: #fff;
    border: 1px solid #E9EFF9;
    border-radius: 14px;
    padding: 28px 26px;
    height: 100%;
    box-shadow: var(--shadow-sm);
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.cap-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: rgba(72,127,255,0.34); }
.cap-card__icon {
    width: 48px; height: 48px;
    border-radius: 12px;
    background: var(--gradient-main);
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 1.12rem;
    margin-bottom: 18px;
}
.cap-card h4 { font-size: 1.04rem; margin-bottom: 9px; }
.cap-card > p { font-size: 0.91rem; line-height: 1.65; margin: 0; }
.cap-card ul { list-style: none; padding: 0; margin: 12px 0 0; }
.cap-card ul li {
    font-size: 0.87rem; line-height: 1.55;
    color: var(--text-mid);
    padding-left: 20px; position: relative; margin-bottom: 7px;
}
.cap-card ul li::before {
    content: '\f00c';
    /* The theme ships Font Awesome 5 PRO — the Free family is never declared,
       so asking for it fell back to a text font and the private-use codepoint
       rendered as a tofu box on every card bullet. */
    font-family: 'Font Awesome 5 Pro'; font-weight: 900;
    position: absolute; left: 0; top: 2px;
    color: var(--color-theme); font-size: 0.7rem;
}

/* Dark variant, for capability grids sitting on the ground gradient. */
.text-light .cap-card {
    background: rgba(255,255,255,0.05);
    border-color: rgba(255,255,255,0.12);
    box-shadow: none;
    backdrop-filter: blur(4px);
}
.text-light .cap-card:hover { border-color: rgba(127,212,255,0.45); background: rgba(255,255,255,0.08); }
.text-light .cap-card h4 { color: #fff !important; }
.text-light .cap-card > p,
.text-light .cap-card ul li { color: rgba(226,232,240,0.82); }
.text-light .cap-card ul li::before { color: #7FD4FF; }

/* ── Stat strip ────────────────────────────────────────────────────── */
.kveldo-statstrip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 1px;
    background: rgba(255,255,255,0.14);
    border-radius: 16px;
    overflow: hidden;
}
.kveldo-statstrip .stat {
    background: rgba(11,20,38,0.55);
    padding: 28px 22px;
    text-align: center;
}
.kveldo-statstrip .stat b {
    display: block;
    font-family: 'Montserrat', sans-serif;
    font-size: 1.95rem; font-weight: 800; color: #fff; line-height: 1.15;
}
.kveldo-statstrip .stat span { font-size: 0.82rem; color: rgba(226,232,240,0.74); }

/* ── Dark ground section wrapper ───────────────────────────────────── */
.kveldo-ground {
    background: var(--gradient-ground);
    position: relative;
    overflow: hidden;
}
.kveldo-ground::before {
    content: '';
    position: absolute; inset: 0;
    background:
        radial-gradient(ellipse at 20% 28%, rgba(124,58,237,0.32), transparent 62%),
        radial-gradient(ellipse at 86% 72%, rgba(34,207,255,0.18), transparent 58%);
    pointer-events: none;
}
.kveldo-ground > .container { position: relative; z-index: 1; }

/* ── Numbered step rail ────────────────────────────────────────────── */
.step-rail { position: relative; }
.step-rail .step-item {
    display: flex; gap: 20px;
    padding-bottom: 30px;
    position: relative;
}
.step-rail .step-item:not(:last-child)::before {
    content: '';
    position: absolute;
    left: 21px; top: 46px; bottom: 0;
    width: 2px;
    background: linear-gradient(180deg, rgba(72,127,255,0.4), rgba(72,127,255,0.06));
}
.step-rail .step-num {
    width: 44px; height: 44px; flex-shrink: 0;
    border-radius: 12px;
    background: var(--gradient-main);
    color: #fff;
    font-family: 'Montserrat', sans-serif;
    font-weight: 800; font-size: 1rem;
    display: flex; align-items: center; justify-content: center;
    position: relative; z-index: 1;
}
.step-rail .step-body h4 { font-size: 1.04rem; margin-bottom: 6px; }
.step-rail .step-body p { font-size: 0.92rem; line-height: 1.68; margin: 0; }

/* ── Integration tiles ─────────────────────────────────────────────── */
.integration-tile {
    background: #fff;
    border: 1px solid #E9EFF9;
    border-radius: 12px;
    padding: 22px 20px;
    height: 100%;
    box-shadow: var(--shadow-sm);
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.integration-tile:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: rgba(72,127,255,0.34); }
.integration-tile__top { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.integration-tile__mark {
    width: 40px; height: 40px; flex-shrink: 0;
    border-radius: 10px;
    background: var(--color-light-mid);
    color: var(--color-theme);
    display: flex; align-items: center; justify-content: center;
    font-size: 1rem;
}
.integration-tile h4 { font-size: 0.98rem; margin: 0; }
.integration-tile p { font-size: 0.86rem; line-height: 1.6; margin: 0; color: var(--text-mid); }
.integration-tile .tag {
    display: inline-block; margin-top: 10px;
    font-size: 10.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.06em;
    padding: 3px 9px; border-radius: 100px;
    background: rgba(72,127,255,0.10); color: var(--color-theme-dark);
}
.integration-tile .tag.soon { background: rgba(71,85,105,0.12); color: #334155; }

/* ── Utility ───────────────────────────────────────────────────────── */
.kveldo-divider {
    height: 3px; width: 56px;
    background: var(--gradient-main);
    border-radius: 100px;
    margin: 0 auto 20px;
}
.text-start .kveldo-divider { margin-left: 0; }

/* ── Header edge ───────────────────────────────────────────────────────
   The navbar is near-black and sits directly on the hero, so without a rule
   between them the header stops reading as its own surface. The base theme
   draws a hairline at 6% white, which is invisible against the hero's radial
   glows.

   One clean horizontal line in the logo's cyan, full width, on every page.
   The neutral hairline underneath is dropped to almost nothing so there is a
   single divider rather than two competing ones.
   ==================================================================== */
header nav.navbar.validnavs,
header nav.navbar.validnavs.inner-page-nav,
header nav.navbar.validnavs.affix,
header nav.navbar.validnavs.sticking {
    border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important;
}

header nav.navbar.validnavs::after {
    content: '';
    /* The base theme uses this same pseudo-element as a clearfix —
       `display: table; clear: both` — and a table box shrink-wraps, so
       left/right never stretch it and the line computed to 0px wide.
       Overriding display is what makes the rule take effect at all. */
    display: block;
    clear: none;
    position: absolute;
    left: 0;
    right: 0;
    top: auto;
    bottom: -2px;              /* sits directly under the border, not over it */
    width: auto;
    height: 2px;
    pointer-events: none;
    background: var(--color-cyan);
    box-shadow: 0 0 12px rgba(34, 207, 255, .45);
}

/* Mobile: the off-canvas menu slides over the bar and the line would show
   through its edge, so the bar keeps the neutral hairline alone. */
@media (max-width: 991px) {
    header nav.navbar.validnavs::after { display: none; }
}

/* ── Pricing "Most Popular" badge ──────────────────────────────────────
   The base theme pins .pricing-badge at top:-80px right:-75px, which was
   written for a rotated ribbon image hanging off the card corner. With a
   text pill it floats clear of the card entirely and collides with whatever
   sits above the pricing row. Re-anchor it to the top edge of its own card.
   ==================================================================== */
.pricing-style-one { position: relative; }
.pricing-style-one .pricing-badge {
    position: absolute;
    top: -13px;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    margin-bottom: 0;
    white-space: nowrap;
    z-index: 2;
    box-shadow: 0 4px 14px rgba(47, 107, 255, .35);
}
/* The badge is absolutely positioned above the card's top edge, so it takes
   no layout space and the header needs no clearance. The 10px that used to
   be here pushed the entire Team column 10px below the other three. */
.pricing-style-one.active .pricing-header { padding-top: 0; }

/* Plan feature lists: keep a per-head figure from breaking away from its
   dash onto the next line. */
.pricing-style-one ul li .nowrap { white-space: nowrap; }

/* ── Contrast guard: light-mode heading blocks inside dark sections ────
   `.site-heading .title` is pinned to the dark ink color with !important
   (0,2,0), which outranks `.text-light h2` (0,1,1) even though that is
   !important too — so any .site-heading dropped into a .kveldo-ground or
   .bg-dark band rendered near-black text on a near-black ground.

   The same trap applies to .heading-left, the section paragraph, the
   sub-title chip and the accordion, all of which were colored for the
   light pages only. Each is re-pinned here at a specificity that wins on
   dark ground, so mixing the two component families can no longer produce
   invisible text.
   ==================================================================== */
.text-light .site-heading .title,
.text-light .heading-left .title,
.text-light .site-heading h2,
.text-light .site-heading h3,
.text-light .heading-left h2 { color: #FFFFFF !important; }

.text-light .site-heading p,
.text-light .heading-left p { color: rgba(226, 232, 240, 0.84) !important; }

.text-light .site-heading .sub-title,
.text-light .heading-left .sub-title {
    color: #9FC0FF !important;
    background: rgba(159, 192, 255, 0.12) !important;
}

/* Accordions: the collapsed button and the body text are both dark-on-light
   by default, so an FAQ block on a dark band lost its questions entirely. */
.text-light .accordion-single { background: rgba(255, 255, 255, 0.04); border-color: rgba(255, 255, 255, 0.12); }
.text-light .accordion-button { color: #FFFFFF !important; background: transparent !important; }
.text-light .accordion-button:not(.collapsed) { color: #9FC0FF !important; }
.text-light .accordion-body,
.text-light .accordion-body p { color: rgba(226, 232, 240, 0.86) !important; }

/* .value-card and .services-style-one-item are white cards; on a dark band
   they keep their own light ground, so their text must stay dark. */
.text-light .value-card,
.text-light .services-style-one-item { color: var(--text-mid); }
.text-light .value-card h4,
.text-light .services-style-one-item h4 { color: var(--text-dark) !important; }
.text-light .value-card p,
.text-light .services-style-one-item p { color: var(--text-mid) !important; }

/* ── .article-callout on a dark ground ─────────────────────────────────
   The callout is a white card with a cyan rule, written for the article
   pages. Dropped into a .kveldo-ground or .bg-dark band it kept the white
   background while .text-light turned its heading and body white too —
   white on white, invisible rather than merely low-contrast.

   Given the same dark treatment as .cap-card so the two read as one family.
   ==================================================================== */
.text-light .article-callout {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.13);
    border-left: 3px solid var(--color-cyan);
    box-shadow: none;
}
.text-light .article-callout h4 { color: #FFFFFF !important; }
.text-light .article-callout p,
.text-light .article-callout li { color: rgba(226, 232, 240, 0.86) !important; }
.text-light .article-callout strong { color: #FFFFFF; }
.text-light .article-callout a { color: #9FC0FF; }
.text-light .article-callout em { color: rgba(226, 232, 240, 0.92); }
.text-light .article-callout code {
    background: rgba(255, 255, 255, 0.10);
    color: #CFE0FF;
}

/* The success pill missed 4.5:1 by a hair (4.21) at 11px. The earlier pass
   darkened it but not far enough; measured again and taken to 4.79. */
/* (a third .kveldo-mock__pill.ok declaration lived here, restating the
   color as #147637 — removed; the token above is the single source.) */

/* ── Inline <code> ─────────────────────────────────────────────────────
   Bootstrap ships code at #d63384 with no background. That pink sits at
   4.23:1 on the light-gray band and 3.82:1 on the dark one — under AA on
   both, and it belongs to no palette on this site. Given a tinted chip in
   the brand blue instead, defined for each ground.
   ==================================================================== */
code {
    background: rgba(72, 127, 255, 0.10);
    color: var(--color-theme-dark);
    padding: 1px 6px;
    border-radius: 5px;
    font-size: 0.9em;
    font-weight: 600;
}
.text-light code {
    background: rgba(255, 255, 255, 0.10);
    color: #CFE0FF;
}

/* ── .hero-badge outside the hero ──────────────────────────────────────
   The badge is glass-on-dark: 10% white fill, 22% white border, #CFE0FF
   text. On the Login page it is used on a near-white band, where it fell
   to 1.26:1 — effectively invisible. Give it a light-ground variant.
   ==================================================================== */
.bg-gray .hero-badge,
.early-access-section .hero-badge,
.default-padding:not(.text-light):not(.kveldo-ground):not(.bg-dark) .hero-badge {
    background: rgba(72, 127, 255, 0.10);
    border-color: rgba(72, 127, 255, 0.28);
    color: var(--color-theme-dark);
    backdrop-filter: none;
}

/* ── Timeline year ─────────────────────────────────────────────────────
   --color-theme (#487FFF) is the action blue, calibrated for buttons and
   dark grounds. As 12px text on the light band it reads 3.43:1. The
   darkened companion token is what the rest of the light pages use. ──── */
.timeline-year { color: var(--color-theme-dark); }

/* ── Final AA near-misses ──────────────────────────────────────────────
   Three components landed at 4.40-4.42 against a 4.5 requirement — close
   enough to look fine and still fail an audit. Measured and nudged. ──── */

/* Comparison-table "cross" cells on dark ground: 45% white is 4.42. These
   carry real information (what a competitor does not do), so they have to
   clear AA rather than sit back as decoration: 4.42 -> 5.35 */
.text-light .comparison-table .cross { color: rgba(255, 255, 255, 0.56); }

/* ── Button casing ─────────────────────────────────────────────────────
   The base theme sets `.btn { text-transform: capitalize }`, which is fine on a
   two-word label and poor on a real sentence: "Apply To Be A Founding
   Firm", "Start Your Free Trial", "Read The Comparison". The site's copy
   is written in sentence case, so let the label render as authored.
   ==================================================================== */
.btn, .btn-simple { text-transform: none; }

/* Plan-price captions in a comparison-table header. The muted gray these used
   inline reads 4.36:1 on the tinted "recommended" column, so it is pinned per
   ground instead of hardcoded once. */
.comparison-table th .plan-caption { color: var(--text-mid); font-weight: 400; }
.comparison-table th.kveldo-col .plan-caption { color: #3A4761; font-weight: 500; }
.text-light .comparison-table th .plan-caption { color: rgba(226, 232, 240, 0.80); }
.text-light .comparison-table th.kveldo-col .plan-caption { color: #E4EDFF; }

/* ── Contact sidebar icons ─────────────────────────────────────────────
   Two competing designs were painting at once. The base theme styles the
   glyph element directly — `.contact-style-one-info li i { background:
   var(--color-primary); border-radius:50%; width:60px; height:60px }` —
   because its own markup has no wrapper. Kveldo's markup adds a `.icon`
   div and styles that as a 48px tinted square, so both rendered: a pale
   square with a 60px circle on top, crushed to an ellipse by the 48px flex
   parent, glyph in blue on blue.

   The wrapper wins and the glyph is stripped back to being a glyph. Given
   the same gradient treatment as .cap-card__icon so the two read as one
   family across the site.
   ==================================================================== */
.contact-style-one-info ul li .icon {
    width: 48px;
    height: 48px;
    flex: 0 0 48px;
    border-radius: 12px;
    background: var(--gradient-main);
    border: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 14px rgba(47, 107, 255, .22);
}
.contact-style-one-info ul li .icon i {
    background: none !important;
    width: auto !important;
    height: auto !important;
    min-width: 0 !important;
    border-radius: 0 !important;
    line-height: 1 !important;
    margin: 0 !important;
    box-shadow: none !important;
    color: #fff !important;
    font-size: 1.12rem !important;
}

/* ── Dropdown hover bridge ─────────────────────────────────────────────
   The menu is offset 8px below its nav item (kveldo-theme.css), which looks
   right but leaves a band belonging to neither element. Moving the pointer
   from "Platform" down to the first item crosses it, `:hover` is lost on the
   parent li, and the menu closes before it can be clicked — measured as a
   7px dead zone between the trigger's bottom edge and the menu's top.

   Rather than remove the offset and glue the panel to the bar, the gap is
   bridged with a transparent strip. It is a child of the menu and therefore a
   descendant of the li, so the pointer never leaves the hover target while
   crossing it. Purely a hit area — it paints nothing.
   ==================================================================== */
@media (min-width: 992px) {
    nav.navbar.validnavs .dropdown-menu::before {
        content: '';
        position: absolute;
        left: 0;
        right: 0;
        top: -10px;        /* the 8px offset, plus 2px of tolerance */
        height: 10px;
        background: transparent;
        pointer-events: auto;
    }
}

/* ── "Log in" — the secondary nav action ───────────────────────────────
   It was a 1px border at 50% action blue on a near-black bar, which reads as
   a faint outline rather than a control: the eye goes straight past it to the
   gradient CTA beside it.

   Given the logo's cyan, which is high-luminance against Oxford Blue and now
   also carries the header rule, so the two read as one system. Deliberately
   an outline rather than a fill — signing in and starting a trial are two
   different intents, and a second solid button would make the header argue
   with itself about which one to press.
   ==================================================================== */
.nav-login-btn {
    border: 1px solid rgba(34, 207, 255, 0.55) !important;
    color: #7FD4FF !important;
    background: rgba(34, 207, 255, 0.08) !important;
    border-radius: 100px;
    padding: 7px 22px !important;
    transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
.nav-login-btn:hover,
.nav-login-btn:focus-visible {
    border-color: rgba(34, 207, 255, 0.95) !important;
    color: #C7F1FF !important;
    background: rgba(34, 207, 255, 0.18) !important;
}
.nav-login-btn:focus-visible {
    outline: 2px solid rgba(34, 207, 255, 0.9);
    outline-offset: 2px;
}

/* ── One button shape ──────────────────────────────────────────────────
   The site had three: .btn at 6px, .nav-login-btn and form submits as full
   pills, and .round-btn as a circle. Three shapes for one job.

   Everything actionable is now a rounded rectangle at a single radius.
   The pill is kept, deliberately, for things that are NOT actionable —
   .pill-tag, .kveldo-eyebrow, .trust-badge, .hero-badge, .pricing-badge and
   the mockup status pills. That is the point of consolidating rather than
   flattening: shape now tells you what you can press.

   10px sits with the card geometry (cap-card 14, icon squares 12, callout 12)
   where the old 6px read as an unrelated component. One value, one place —
   change --btn-radius to reshape every control on the site.
   ==================================================================== */
:root { --btn-radius: 10px; }

.btn,
.btn.btn-theme,
.btn.btn-dark,
.btn-theme,
.btn.radius,
.nav-login-btn,
.contact-form-style-one button[type="submit"],
.waitlist-form-card button[type="submit"],
.pricing-style-one .btn {
    border-radius: var(--btn-radius) !important;
}

/* The icon-only arrow affordances were circles. Same family, smaller radius so
   a 44px square does not read as a rounded blob. */
.round-btn {
    border-radius: calc(var(--btn-radius) - 2px) !important;
}

/* ── Button states ─────────────────────────────────────────────────────
   Two faults, one root cause each.

   1. THE HOVER SWEEP. The base theme gives .btn-theme an ::after that skews across the
      button on hover, and inside any .bg-dark section it is painted WHITE
      (`.bg-dark .btn.btn-theme::after { background-color: var(--white) }`).
      The theme compensates by switching the label to #0e0e0e — but our own
      rule forces `color:#fff !important`, so on every dark band the button
      turned white and the white label vanished into it.

      The sweep is removed rather than re-tuned. It is a dated effect, it is
      the only reason two rules had to agree about text color, and hover now
      does something simpler that cannot fail: lift and deepen the shadow.

   2. .btn-dark WAS #232323 — a neutral gray belonging to no palette here —
      with a 10% white border, sitting on the near-black footer and hero. It
      read as a dark smudge. It is now a proper secondary button that inverts
      with its ground: light fill and dark ink on pale sections, translucent
      white and white ink on dark ones.
   ==================================================================== */

/* 1. Kill the sweep on every button variant. */
.btn::after,
.btn.btn-theme::after,
.btn.btn-dark::after,
.btn.btn-theme:hover::after,
.btn.btn-dark:hover::after {
    display: none !important;
    content: none !important;
}

/* Primary keeps a white label at rest and on hover — nothing beneath it moves now. */
.btn.btn-theme,
.btn-theme,
.btn.btn-theme:hover,
.btn-theme:hover,
.bg-dark .btn.btn-theme:hover,
.shadow .btn.btn-theme:hover {
    color: #FFFFFF !important;
}
.btn.btn-theme:hover,
.btn-theme:hover {
    box-shadow: 0 8px 32px rgba(72, 127, 255, 0.45);
    transform: translateY(-1px);
}

/* 2. Secondary button — light ground (the default). */
.btn.btn-dark,
.btn-dark {
    /* A white fill on a white card is not a button. The tint separates it from
       the surface and the border carries the boundary at 3:1, which a 20% ink
       outline (measured 1.27:1) did not. */
    background: #F4F7FF !important;
    border: 1px solid rgba(47, 107, 255, 0.80) !important;
    color: var(--color-theme-dark) !important;
    box-shadow: none;
}
.btn.btn-dark:hover,
.btn-dark:hover {
    background: #E3ECFF !important;
    border-color: var(--color-theme-dark) !important;
    color: var(--color-theme-dark) !important;
}

/* 2b. Secondary button — dark ground. Inverts so it never becomes a smudge. */
.text-light .btn.btn-dark,
.bg-dark .btn.btn-dark,
.kveldo-ground .btn.btn-dark,
.kveldo-hero .btn.btn-dark,
footer .btn.btn-dark,
.request-call-back-area .btn.btn-dark {
    background: rgba(255, 255, 255, 0.10) !important;
    border: 1px solid rgba(255, 255, 255, 0.38) !important;
    color: #FFFFFF !important;
}
.text-light .btn.btn-dark:hover,
.bg-dark .btn.btn-dark:hover,
.kveldo-ground .btn.btn-dark:hover,
.kveldo-hero .btn.btn-dark:hover,
footer .btn.btn-dark:hover,
.request-call-back-area .btn.btn-dark:hover {
    background: rgba(255, 255, 255, 0.20) !important;
    border-color: rgba(255, 255, 255, 0.70) !important;
    color: #FFFFFF !important;
}

/* The vendor's generic `.btn:hover { background-color: var(--color-primary) }`
   would otherwise repaint anything it can reach. */
.btn:hover { background-color: initial; }

/* ══ SECTION EYEBROW ═══════════════════════════════════════════════════
   The small uppercase label above a section heading. It existed as three
   different things — .kveldo-eyebrow (bare text), .sub-title (a pill at 8%
   blue, effectively a 1.06:1 shape) and .pill-tag — so all 83 uses now
   resolve to this one component.

   Second pass on the motion. The first version led with a pulsing dot,
   which reads as a live-status indicator — the wrong signal entirely for a
   static label, and fussy next to a heading. Replaced with:

     · a short vertical gradient rule, a typographic mark rather than a
       blinking light
     · the outline gradient traveling slowly around the chip, so the
       movement is felt at the edge instead of performed in the middle

   The outline is drawn with padding-box/border-box compositing, which is
   how you get a gradient border around a filled pill with no wrapper. The
   fill must stay OPAQUE on both grounds or the gradient floods the chip.
   ==================================================================== */

.kveldo-eyebrow,
.site-heading .sub-title,
h4.sub-title,
h5.sub-title,
span.sub-title,
.pill-tag {
    position: relative;
    display: inline-flex !important;
    align-items: center;
    padding: 6px 18px !important;
    border-radius: 100px !important;
    border: 1px solid transparent !important;
    background:
        linear-gradient(#EDF3FF, #EDF3FF) padding-box,
        linear-gradient(90deg, #7C3AED, #2F6BFF, #22CFFF) border-box !important;
    color: var(--color-theme-dark) !important;
    /* The base theme paints .sub-title as gradient text — -webkit-text-fill-color:
       transparent plus background-clip:text. Replacing the background alone
       left the glyphs transparent, so the chip rendered empty. */
    -webkit-text-fill-color: currentColor !important;
    font-size: 0.74rem !important;
    font-weight: 800 !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    line-height: 1.5 !important;
    margin-bottom: 16px;
    box-shadow: 0 2px 12px rgba(47, 107, 255, 0.14);
    vertical-align: middle;
}

/* Nothing leads the text — the label stands on its own. */
.kveldo-eyebrow::before,
.site-heading .sub-title::before,
h4.sub-title::before,
h5.sub-title::before,
span.sub-title::before,
.pill-tag::before { content: none !important; }

/* A soft glow beneath the chip, breathing slowly. The only motion here. */
.kveldo-eyebrow::after,
.site-heading .sub-title::after,
h4.sub-title::after,
h5.sub-title::after,
span.sub-title::after,
.pill-tag::after {
    content: '';
    position: absolute;
    left: 10%;
    right: 10%;
    bottom: -8px;
    height: 12px;
    border-radius: 50%;
    pointer-events: none;
    background: radial-gradient(ellipse at center, rgba(47, 107, 255, 0.55), rgba(47, 107, 255, 0) 72%);
    filter: blur(6px);
    animation: kv-eyebrow-glow 3.4s ease-in-out infinite;
}

@keyframes kv-eyebrow-glow {
    0%, 100% { opacity: 0.45; transform: scaleX(0.82); }
    50%      { opacity: 1;    transform: scaleX(1.06); }
}

/* ── On a dark ground ───────────────────────────────────────────────── */
.text-light .kveldo-eyebrow,
.text-light .site-heading .sub-title,
.text-light h4.sub-title,
.text-light span.sub-title,
.text-light h5.sub-title,
.text-light .pill-tag,
.kveldo-ground .kveldo-eyebrow,
.kveldo-hero .pill-tag {
    /* Opaque, or the border gradient floods the whole chip — which measured
       3.1:1 for the label, under AA. This fill takes it to 11.7:1. */
    background:
        linear-gradient(#151B38, #151B38) padding-box,
        linear-gradient(90deg, #7C3AED, #2F6BFF, #22CFFF) border-box !important;
    color: #A8DEFF !important;
    box-shadow: 0 2px 16px rgba(34, 207, 255, 0.20);
}
.text-light .kveldo-eyebrow::after,
.text-light .site-heading .sub-title::after,
.text-light h4.sub-title::after,
.text-light .pill-tag::after,
.kveldo-ground .kveldo-eyebrow::after {
    background: radial-gradient(ellipse at center, rgba(34, 207, 255, 0.60), rgba(34, 207, 255, 0) 72%);
}

/* Motion is decoration here; the contrast is not. */
@media (prefers-reduced-motion: reduce) {
    .kveldo-eyebrow,
    .site-heading .sub-title,
    h4.sub-title,
    h5.sub-title,
    .pill-tag::after { animation: none !important; opacity: 0.6 !important; transform: none !important; }
}

/* The contact form's eyebrow was pinned to --color-theme (#487FFF), the action
   blue, which measures 3.28:1 on the chip fill. The darkened companion clears AA. */
.contact-form-style-one h5.sub-title,
.contact-form-style-one span.sub-title { color: var(--color-theme-dark) !important; }

/* ── Hero dashboard beat ───────────────────────────────────────────────
   The mockup plays the product's core loop: a client answers, the chase
   clears, the work advances. The card and its rows arrive on load; the
   status change is driven from Index.cshtml.

   Both entrances use `animation-fill-mode: both`, so the finished state is
   what renders if animations never run — no JavaScript dependency for the
   dashboard to be correct, only for it to move.
   ==================================================================== */
.kveldo-mock--hero {
    animation: kv-hero-card-in 0.8s cubic-bezier(.22, .8, .3, 1) both;
}
@keyframes kv-hero-card-in {
    from { opacity: 0; transform: translateY(16px) scale(0.985); }
    to   { opacity: 1; transform: none; }
}

/* Rows stagger in behind the card. */
.kveldo-mock--hero .kveldo-mock__row {
    animation: kv-hero-row-in 0.5s ease-out both;
}
.kveldo-mock--hero .kveldo-mock__row:nth-of-type(1) { animation-delay: 0.42s; }
.kveldo-mock--hero .kveldo-mock__row:nth-of-type(2) { animation-delay: 0.52s; }
.kveldo-mock--hero .kveldo-mock__row:nth-of-type(3) { animation-delay: 0.62s; }
.kveldo-mock--hero .kveldo-mock__row:nth-of-type(4) { animation-delay: 0.72s; }
@keyframes kv-hero-row-in {
    from { opacity: 0; transform: translateX(10px); }
    to   { opacity: 1; transform: none; }
}

/* The moment a row changes: a brief wash, then it settles. Deliberately
   soft — this sits next to the headline and must not pull focus off it. */
.kveldo-mock--hero .kveldo-mock__row.kv-row-change {
    animation: kv-hero-row-change 1.4s ease-out;
}
@keyframes kv-hero-row-change {
    0%   { background: rgba(47, 107, 255, 0.14); }
    100% { background: transparent; }
}
.kveldo-mock--hero .kveldo-mock__pill { transition: background-color .35s ease, color .35s ease; }
.kveldo-mock--hero .kveldo-mock__stat b { transition: color .35s ease; }

@media (prefers-reduced-motion: reduce) {
    .kveldo-mock--hero,
    .kveldo-mock--hero .kveldo-mock__row { animation: none !important; }
}

/* ── Pain-point cards ──────────────────────────────────────────────────
   Three faults fixed together.

   HEIGHT. The Bootstrap row stretches the columns, but the card inside had
   no height of its own, so a card with one extra line of copy stood 24px
   taller than its neighbours. It now fills its column and lays its content
   out in a column, which also lets the cost line pin to the bottom edge so
   all six align regardless of how long the paragraph runs.

   ARTEFACTS. The base theme draws a 10px gray dot and a connector stub off .icon
   via ::before/::after — leftovers from a numbered-process layout. They
   appeared under every icon as a stray mark. Removed.

   DESIGN. The icon was gradient-clipped text, which reads thin at 2.4rem.
   It is now the same gradient-filled tile used on .cap-card and the contact
   list, so icons look like one family across the site. Each card carries an
   index and closes on the cost of the problem — the section argues with
   evidence instead of adjectives, and gives the eye a consistent bottom line.
   ==================================================================== */
.pain-item {
    height: 100%;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    padding: 28px 26px 22px !important;
}

/* A gradient hairline along the top edge that draws in on hover. */
.pain-item::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--gradient-main);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .4s cubic-bezier(.22, .8, .3, 1);
}
.pain-item:hover::after { transform: scaleX(1); }

/* The base theme positions every <span> inside this card as an absolute 60px watermark
   numeral at 7% opacity (.services-style-one-item span). That rule captured both
   the index and the cost line, pulling them out of the flex flow and rendering
   them as faint text floating over the icon. Returned to normal flow first. */
.pain-item span {
    position: static !important;
    top: auto !important;
    right: auto !important;
    z-index: auto !important;
    opacity: 1 !important;
    line-height: inherit !important;
}

.pain-item .pain-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 18px;
}

/* Kill the vendor's stray dot and connector stub. */
.pain-item .icon::before,
.pain-item .icon::after { content: none !important; display: none !important; }

.pain-item .icon {
    /* The base theme gives .icon padding-right:30px and padding-bottom:60px to make room
       for the dot-and-connector decoration above. With border-box that squeezed
       the glyph clean out of the top of the tile. */
    padding: 0 !important;
    box-sizing: border-box;
    width: 46px !important;
    height: 46px !important;
    flex: 0 0 46px;
    margin: 0 !important;
    border-radius: 12px;
    background: var(--gradient-main);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 14px rgba(47, 107, 255, .24);
}
.pain-item .icon i {
    font-size: 1.15rem !important;
    color: #fff !important;
    background: none !important;
    -webkit-text-fill-color: #fff !important;
    background-clip: border-box !important;
}

.pain-item .pain-no {
    font-size: 0.86rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    color: rgba(11, 20, 38, 0.20);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.pain-item h4 { font-size: 1.04rem; margin-bottom: 9px; }
/* The paragraph takes the slack, so the cost line sits on the bottom edge
   of every card whatever the copy length. */
.pain-item p { font-size: 0.91rem; line-height: 1.65; margin: 0 0 20px; flex: 1 1 auto; }

.pain-item .pain-cost {
    display: block;
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid rgba(11, 20, 38, 0.09);
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--color-theme-dark);
}

/* The index reads as an ordinal, not a smudge: 1.54:1 was low enough to look
   like a rendering fault rather than a deliberate mark. 3.0:1 stays secondary
   to the heading while clearly being on purpose. */
.pain-item .pain-no { color: rgba(11, 20, 38, 0.45); }

/* ── The same card elsewhere ───────────────────────────────────────────
   .services-style-one-item is also used for the six feature pillars on the
   homepage and the three "why Kveldo" cards on Pricing. Those carry the same
   two vendor faults the pain cards had — the stray dot-and-connector off
   .icon, and no height of their own inside a stretched column — so the fixes
   apply there too. The pain-card design (index, cost line) stays scoped to
   .pain-item; this is only the geometry and the artifact.
   ==================================================================== */
.services-style-one-item {
    height: 100%;
    display: flex;
    flex-direction: column;
}
.services-style-one-item .icon::before,
.services-style-one-item .icon::after { content: none !important; display: none !important; }
.services-style-one-item .icon {
    padding: 0 !important;
    margin-bottom: 18px !important;
}
/* The round-btn affordance, where present, sits on the bottom edge so the
   cards align regardless of copy length. */
.services-style-one-item a.round-btn { margin-top: auto !important; }

/* ── One icon language ─────────────────────────────────────────────────
   The site was drawing icons three ways: the gradient tile (.cap-card,
   .pain-item), a bare gradient-clipped glyph (.services-style-one-item on
   Pricing and the homepage pillars), and a vendor circle. The clipped glyph
   is the weakest of the three — a multi-path mark like fa-handshake reads as
   a smudge once the gradient runs through its counters. The tile is now the
   single treatment for every card icon on the site.
   ==================================================================== */
.services-style-one-item .icon {
    align-self: flex-start;
    width: 46px;
    height: 46px;
    min-width: 46px;
    box-sizing: border-box;
    border-radius: 12px;
    background: var(--gradient-main);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 14px rgba(47, 107, 255, 0.24);
}
.services-style-one-item .icon i {
    font-size: 1.15rem !important;
    color: #fff !important;
    /* Undo the vendor's background-clip:text — the glyph is painted, not cut out. */
    background: none !important;
    -webkit-text-fill-color: #fff !important;
    background-clip: border-box !important;
    -webkit-background-clip: border-box !important;
}

/* ── Card "go" affordance ──────────────────────────────────────────────
   The vendor draws this as a 60px circle rotated 45deg — the rotation is
   invisible on a circle, which is why it was never noticed. Once the button
   radius was consolidated to 10px, that same rotation turned it into a large
   diamond: a third button shape on a site that is meant to have one.
   Upright, smaller, and in the same rounded-rectangle language as every
   other control. It is aria-hidden and duplicates the heading link, so it
   reads as an affordance rather than competing for the eye.
   ==================================================================== */
.services-style-one-item a.round-btn,
a.round-btn {
    transform: none !important;
    height: 38px !important;
    width: 38px !important;
    line-height: 36px !important;
    border-radius: var(--btn-radius) !important;
    background: #EDF3FF !important;
    border: 1px solid rgba(47, 99, 214, 0.42) !important;
    transition: background .28s ease, border-color .28s ease, transform .28s ease;
}
/* The vendor shipped this arrow as an inline SVG whose path (M1 17L17 1H7.8)
   draws the diagonal and only ONE leg of the arrowhead — the second leg is
   simply absent from the markup, so it rendered as a stroke with a tick and
   read as a rotated "1". Replaced with a real Font Awesome arrow. */
.services-style-one-item a.round-btn i {
    font-size: 0.82rem;
    line-height: 1;
    color: var(--color-theme-dark);
    transition: color .28s ease;
}

/* The whole card is the hover target, not the little square. */
.services-style-one-item:hover a.round-btn {
    background: var(--gradient-main) !important;
    border-color: transparent;
    transform: translateX(3px) !important;
}
.services-style-one-item:hover a.round-btn i { color: #fff; }

/* On a dark ground the resting outline and arrow have to invert. */
.text-light .services-style-one-item a.round-btn,
.kveldo-ground .services-style-one-item a.round-btn {
    background: #151B38 !important;
    border-color: rgba(168, 222, 255, 0.46) !important;
}
.text-light .services-style-one-item a.round-btn { background: #151B38 !important; border-color: rgba(168, 222, 255, 0.46) !important; }
.text-light .services-style-one-item a.round-btn i,
.kveldo-ground .services-style-one-item a.round-btn i { color: #A8DEFF; }

@media (prefers-reduced-motion: reduce) {
    .services-style-one-item:hover a.round-btn { transform: none !important; }
}

/* ── Horizontal step cards ─────────────────────────────────────────────
   "Live in Three Steps" used the vendor's .process-style-one, which leads
   with a photo. The three photos were the base theme's PLACEHOLDER graphics — gray
   panels with their own pixel dimensions printed on them (649x650, 600x749,
   719x1000) — and because the card had no height of its own the three ran
   49px apart.

   Rebuilt on the number tile already used by .step-rail, so the horizontal
   and vertical step treatments are visibly the same component. The rule
   between cards is the horizontal counterpart of the rail's connector.
   ==================================================================== */
.kv-step {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid #E9EFF9;
    border-radius: 14px;
    padding: 26px 24px 22px;
    box-shadow: var(--shadow-sm);
    transition: transform .28s ease, box-shadow .28s ease, border-color .28s ease;
}
.kv-step:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: #D8E4FB; }

.kv-step__num {
    width: 44px; height: 44px;
    flex: 0 0 44px;
    border-radius: 12px;
    background: var(--gradient-main);
    color: #fff;
    font-family: 'Montserrat', sans-serif;
    font-weight: 800; font-size: 1rem;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 18px;
    box-shadow: 0 4px 14px rgba(47, 107, 255, .24);
}
.kv-step h4 { font-size: 1.08rem; margin-bottom: 10px; }
.kv-step p { flex: 1 1 auto; color: var(--text-mid); font-size: 0.94rem; line-height: 1.7; margin: 0; }

/* Same device as the pain cards' cost line: the claim in the heading is about
   elapsed time, so each card ends by naming its own. */
.kv-step__when {
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid rgba(11, 20, 38, 0.09);
    color: var(--color-theme-dark);
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
}

/* The connector, desktop only — it is meaningless once the cards stack. */
@media (min-width: 992px) {
    .kv-steps > [class*="col-"]:not(:last-child) .kv-step::after {
        content: '';
        position: absolute;
        top: 48px; right: -25px;
        width: 26px; height: 2px;
        background: linear-gradient(90deg, rgba(72,127,255,.42), rgba(72,127,255,.08));
    }
}

/* .article-card is now used on the homepage as well as the Resources hub, so
   it has to survive a stretched row. */
.article-card { height: 100%; display: flex; flex-direction: column; }
.article-card .article-card-body { display: flex; flex-direction: column; flex: 1 1 auto; }
.article-card .article-meta { margin-top: auto; padding-top: 12px; }

/* The homepage cards carry art; the hub's smaller cards do not. Keep the tile
   the same 46px mark used everywhere else rather than the featured banner. */
.article-card:not(.article-card-featured) .article-card-art {
    width: 46px; height: 46px;
    margin: 22px 22px 0;
    border-radius: 12px;
    background: var(--gradient-main);
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 4px 14px rgba(47, 107, 255, .24);
}
.article-card:not(.article-card-featured) .article-card-art i {
    font-size: 1.15rem;
    color: #fff;
    -webkit-text-fill-color: #fff;
}
.article-card:not(.article-card-featured) .article-card-art + .article-card-body { padding-top: 16px; }

/* ══ CONSISTENCY PASS ══════════════════════════════════════════════════
   Measured across all 34 pages. Buttons (189 of them) were already a single
   radius and the eyebrow a single component, but three tokens had drifted —
   all three inherited from the vendor rather than chosen.
   ==================================================================== */

/* 1. CARD RADIUS. Four values were rendering: 14px (cap-card, article-card,
      kv-step), 12px (integration-tile, glossary-term), 16px (the vendor's
      .services-style-one-item) and 20px (.pricing-style-one). The scale is
      meant to be two steps — 14px for a card, 12px for a tile inside one —
      so the two vendor values join it. */
.services-style-one-item,
.pricing-style-one { border-radius: 14px !important; }

/* 2. ICON TILE SIZE. Three sizes were rendering for one mark: 48px
      (.cap-card__icon), 46px (card .icon) and 44px (the step numbers). They
      are the same component doing the same job, so they are one size now.
      46px is the value the rest of the site already used.

      .value-icon (About) was missed by that pass and stayed on the vendor's
      gradient-clipped glyph — no tile at all, a 575px-wide block, and
      fa-handshake turning to mush exactly as the icon standard warns. Added
      here so there is one rule and it cannot drift again. */
.cap-card__icon,
.value-card .value-icon,
.kv-step__num,
.step-rail .step-num {
    width: 46px !important;
    height: 46px !important;
    min-width: 46px;
    flex: 0 0 46px;
    border-radius: 12px !important;
}
/* The two connectors are drawn from the tile's center line, so they move with it. */
.step-rail .step-item:not(:last-child)::before { left: 22px; top: 48px; }
@media (min-width: 992px) {
    .kv-steps > [class*="col-"]:not(:last-child) .kv-step::after { top: 49px; }
}

/* 3. SECTION HEADING WEIGHT. h2.title.split-text renders at 600 in 23 places
      and at 800 in the final CTA band only — the vendor weights
      .request-call-back-area headings differently. It is the same class at the
      same size, and other dark sections already use 600, so the exception goes. */
.request-call-back-area .title,
.request-call-back-area h2.title.split-text { font-weight: 600 !important; }

/* Making .article-card-body a column flex container (so the meta line can be
   pinned to the bottom) also made its children stretch to full width, which
   turned the category chip into a full-width bar. Chips hug their text. */
.article-card .article-cat { align-self: flex-start; }

/* ── Pricing CTA baseline ──────────────────────────────────────────────
   The four plan cards were equal height, but their buttons floated at
   whatever height the feature list ended — a 153px spread across one row.
   The eye reads four CTAs as a set, so they sit on one line. */
.pricing-style-one { display: flex; flex-direction: column; height: 100%; }
.pricing-style-one .pricing-content { display: flex; flex-direction: column; flex: 1 1 auto; }
.pricing-style-one .pricing-content ul { flex: 1 1 auto; }
.pricing-style-one .btn { margin-top: auto; }

/* ── Paragraph rhythm ──────────────────────────────────────────────────
   Three places had two consecutive <p> rendering with a 0px gap, so the
   second paragraph read as a runaway line of the first. Body copy in a
   prose block gets a real space between paragraphs. */
.choose-us-style-one > p + p,
.choose-us-style-one p + p,
.kveldo-prose p + p,
.cap-card p + p,
.site-heading p + p { margin-top: 1em; }

/* The contact cards were the last icons off the 46px grid. */
.contact-style-one-info ul li .icon {
    width: 46px !important;
    height: 46px !important;
    min-width: 46px;
    flex: 0 0 46px;
}

/* ── Plan feature lists ────────────────────────────────────────────────
   These were `display:flex; gap:10px` to put the tick beside the text. But
   flex makes EVERY child its own flex item, so a line like
       <i></i> <strong>Unlimited</strong> client portal users
   became three items with 10px gaps between them — the bold word visibly
   detached from its own sentence — and with nowrap a line carrying a <code>
   chip ("Your own app.yourfirm.com") could not wrap at all.

   The icon is positioned instead, so the text is ordinary inline flow: one
   paragraph, wrapping normally, with <strong> and <code> sitting in it. */
.pricing-style-one .pricing-content ul li {
    display: block !important;
    position: relative;
    padding-left: 28px;
    /* The tick is absolutely positioned, so these three must be stated here
       together: the icon's `top` below is this padding-top, and its box is one
       line-height tall. Change one and change all three. */
    padding-top: 7px;
    padding-bottom: 7px;
    line-height: 1.7;
    gap: 0 !important;
}
.pricing-style-one .pricing-content ul li > i {
    position: absolute;
    left: 0;
    /* Was `top: 0.34em`, a guess against the icon's own font-size, which put
       every tick 5.4px above its row — uniformly, on all four cards. Anchoring
       to the row's padding-top and inheriting the row's font-size and
       line-height makes the icon's box exactly the first line box, so the glyph
       centers on line one whether the row wraps or not. Measured: 0.96px. */
    top: 7px;
    font-size: inherit;
    line-height: inherit;
    height: auto;
    margin: 0 !important;
}
.pricing-style-one .pricing-content ul li code {
    white-space: nowrap;
    word-break: keep-all;
}

/* The error page led with a 5rem ⚠️ emoji — orange, which the palette rules out
   outright, and unstyleable besides. Rose is the site's attention color. */
.error-mark {
    width: 88px; height: 88px;
    margin: 0 auto 22px;
    border-radius: 22px;
    background: rgba(190, 18, 60, 0.16);
    border: 1px solid rgba(244, 114, 141, 0.34);
    display: flex; align-items: center; justify-content: center;
}
.error-mark i { font-size: 2.2rem; color: #FDA4AF; -webkit-text-fill-color: #FDA4AF; }

/* ── Compact plan strip ────────────────────────────────────────────────
   The homepage carried four fully-specified pricing cards — 1,393px that
   restated /Pricing. This states the shape of the pricing (flat, by band of
   staff) and routes to the page that owns the detail. */
.kv-plan {
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: #fff;
    border: 1px solid #E9EFF9;
    border-radius: 14px;
    padding: 22px 20px;
    box-shadow: var(--shadow-sm);
    transition: transform .28s ease, box-shadow .28s ease, border-color .28s ease;
}
.kv-plan:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: #D8E4FB; }
.kv-plan--featured { border-color: var(--color-theme); box-shadow: 0 10px 30px rgba(47,107,255,.16); }
.kv-plan__name {
    font-size: 0.72rem; font-weight: 800; letter-spacing: .14em;
    text-transform: uppercase; color: var(--color-theme-dark);
}
.kv-plan__price {
    font-family: 'Montserrat', sans-serif;
    font-size: 2rem; font-weight: 800; line-height: 1.1;
    color: var(--text-dark);
}
.kv-plan__price i { font-style: normal; font-size: 0.9rem; font-weight: 600; color: var(--text-muted); margin-left: 2px; }
.kv-plan__band { font-size: 0.85rem; color: var(--text-mid); margin-top: auto; }

/* ══ SECTION DENSITY ═══════════════════════════════════════════════════
   The homepage was 16,000px — seventeen screens — largely because it argued
   the same points twice. With the duplicated sections gone, two measurements
   still stood out: 2,100px of the page was section padding, and the site had
   TWO section-heading scales running side by side — `.site-heading .title` at
   55px (vendor) and `.kveldo-section-title` at 41.6px (ours). One heading
   scale, and less air around it.
   ==================================================================== */
.site-heading .title,
.heading-left .title,
.choose-us-style-one .title,
.request-call-back-area .title,
h2.title.split-text,
h2.title {
    font-size: clamp(1.8rem, 3.2vw, 2.6rem) !important;
    line-height: 1.14 !important;
    letter-spacing: -0.025em;
}

/* 100px top and bottom on every band is a 2019 rhythm. 76px reads as
   deliberate breathing room rather than padding for its own sake. */
.default-padding { padding: 76px 0 !important; }
.default-padding-top { padding-top: 76px !important; }
.default-padding-bottom { padding-bottom: 76px !important; }

/* The heading stack itself: eyebrow, title, divider, lead. It was 342px
   before a single card appeared. */
.site-heading { margin-bottom: 8px; }
.site-heading .title { margin-bottom: 10px !important; }
.site-heading p.mt-3 { margin-top: 10px !important; }
.site-heading .devider { margin-top: 12px; }

/* ── FAQ page ──────────────────────────────────────────────────────────
   Themed groups, with the group label held in a sticky left rail so the
   reader always knows which part of the answer set they are in. The rail
   is the reason this reads differently from the homepage FAQ rather than
   being the same accordion twice. */
.faq-group { margin-top: 56px; }
.faq-group:first-of-type { margin-top: 40px; }
.faq-group__head { position: sticky; top: 120px; }
.faq-group__icon {
    width: 46px; height: 46px;
    border-radius: 12px;
    background: var(--gradient-main);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 14px;
    box-shadow: 0 4px 14px rgba(47, 107, 255, .24);
}
.faq-group__icon i { font-size: 1.15rem; color: #fff; -webkit-text-fill-color: #fff; }
.faq-group__head h3 { font-size: 1.12rem; font-weight: 800; margin-bottom: 4px; }
.faq-group__count {
    font-size: 0.72rem; font-weight: 800; letter-spacing: .12em;
    text-transform: uppercase; color: var(--text-muted);
}
@media (max-width: 991px) {
    .faq-group__head { position: static; margin-bottom: 18px; }
    .faq-group { margin-top: 44px; }
}

/* ── Contact form: qualifying fields ───────────────────────────────────
   The form asks three things it used to ask for inside a textarea
   placeholder. As bands they cost a click instead of a sentence, and they
   arrive sortable. The group label is what stops nine inputs reading as a
   wall — it turns the form into three decisions rather than nine chores. */
.form-group-label {
    margin: 14px 0 2px;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-theme-dark);
}
.form-group-label span {
    display: inline-block;
    margin-left: 8px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    font-size: 0.84rem;
    color: var(--text-muted);
}
.form-privacy-note {
    margin: 14px 0 0;
    font-size: 0.84rem;
    line-height: 1.6;
    color: var(--text-muted);
}
.form-privacy-note a { color: var(--color-theme-dark); text-decoration: underline; }

/* ── Footer ────────────────────────────────────────────────────────────
   Links pick up the same cyan as the rule under the header, so the one
   accent that opens the page also closes it. */
footer .f-item.link ul li a:hover,
footer .f-item ul li a:hover,
.footer-bottom ul li a:hover {
    color: var(--color-cyan) !important;
}

/* "Get in touch" fills with the Free Trial gradient on hover — the footer's
   one action reading as the same kind of action as the header's. */
footer .f-item .btn.btn-dark,
footer a.btn.btn-dark {
    margin-top: 22px;          /* room above it; it was crowding the line before */
    transition: background .28s ease, color .28s ease, border-color .28s ease, box-shadow .28s ease;
}
footer .f-item .btn.btn-dark:hover,
footer a.btn.btn-dark:hover {
    background: var(--gradient-main) !important;
    border-color: transparent !important;
    color: #fff !important;
    box-shadow: 0 8px 24px rgba(47, 107, 255, 0.34);
}

/* ── Header CTA hover ──────────────────────────────────────────────────
   The nav library ships `.validnavs a:hover { background: transparent
   !important }` — every anchor inside the nav, using the background
   SHORTHAND, which resets background-image along with the color. So the
   header's "Free trial" button dropped its gradient the moment you pointed at
   it and went almost black, while the identical `.btn.btn-theme` on the
   homepage was untouched. Same markup, same classes; only the nav ancestor
   differed.

   `.validnavs a:hover` is (0,2,1) and carries !important, so our own
   `.nav-login-btn:hover` at (0,2,0) lost to it too — the Log In tint was being
   wiped in exactly the same way. Both selectors below outrank it.

   The result is that the header CTA now hovers exactly like "Start your free
   trial" on the homepage: gradient held, glow lifted, one pixel of rise. */
header a.btn.btn-theme:hover,
.navbar a.btn.btn-theme:hover {
    background: var(--gradient-main) !important;
    box-shadow: 0 8px 32px rgba(72, 127, 255, 0.45) !important;
    transform: translateY(-1px);
    color: #fff !important;
}
header a.nav-login-btn:hover,
.navbar a.nav-login-btn:hover {
    background: rgba(34, 207, 255, 0.18) !important;
}

/* ── The portal door ───────────────────────────────────────────────────
   "Log in" is not a secondary CTA on this site. Free Trial is a once-ever
   action taken by a prospect; Log in is taken every week by every firm and
   by every one of their clients, and hardest during filing season. It was
   the smaller of the two on desktop and, below 550px, it did not exist:
   validnavs hides `.attr-right` outright there and nothing replaced it in
   the hamburger, so a client opening the site on a phone — the device the
   product's own portal pitch is built around — had no way in.
   ==================================================================== */

/* Desktop: same height as the primary CTA. 40px was also under the 44px
   minimum touch target, which matters most for the least confident users. */
header a.nav-login-btn,
.navbar a.nav-login-btn {
    display: inline-flex;
    align-items: center;
    min-height: 46px;
    padding: 8px 24px !important;
    border-radius: var(--btn-radius);
    transition: background .22s ease, border-color .22s ease, box-shadow .22s ease, color .22s ease;
}
/* A door should feel like it opens: the tint lifts, the edge brightens and a
   soft cyan glow appears — the same gesture as the primary button, in the
   secondary key rather than a louder version of it. */
header a.nav-login-btn:hover,
.navbar a.nav-login-btn:hover {
    background: rgba(34, 207, 255, 0.20) !important;
    border-color: rgba(34, 207, 255, 0.95) !important;
    color: #CDEEFF !important;
    box-shadow: 0 6px 22px rgba(34, 207, 255, 0.28);
}
header a.nav-login-btn:focus-visible,
.navbar a.nav-login-btn:focus-visible {
    outline: 2px solid rgba(34, 207, 255, 0.95);
    outline-offset: 3px;
}

/* Mobile: the counterparts inside the hamburger. Hidden wherever the header
   pair is actually visible, so the two never appear at once. */
.nav-mobile-cta { display: none; }
@media (max-width: 550px) {
    .nav-mobile-cta {
        display: flex;
        flex-direction: column;
        gap: 12px;
        padding: 22px 20px 28px;
        margin-top: 10px;
        border-top: 1px solid rgba(255, 255, 255, 0.10);
    }
    /* Login leads, because on a phone that is overwhelmingly why someone came. */
    .nav-mobile-cta__login {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        min-height: 52px;
        border-radius: var(--btn-radius);
        border: 1px solid rgba(34, 207, 255, 0.55);
        background: rgba(34, 207, 255, 0.10);
        color: #A8DEFF !important;
        font-weight: 700;
        font-size: 0.95rem;
        text-decoration: none;
        /* The theme title-cases nav items, which turns this into
           "Log In To Your Portal". It is a sentence, not a heading. */
        text-transform: none !important;
    }
    .nav-mobile-cta__login:hover,
    .nav-mobile-cta__login:focus {
        background: rgba(34, 207, 255, 0.20) !important;
        border-color: rgba(34, 207, 255, 0.95);
        color: #CDEEFF !important;
    }
    .nav-mobile-cta .btn.btn-theme {
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 52px;
        width: 100%;
    }
}

/* At 1024px the header column is 242px and the two controls together did not
   fit, so "Log in" wrapped onto two lines and the button grew to 66px tall.
   It never wraps, and it gives back some horizontal padding where space is
   tight rather than breaking the line. */
header a.nav-login-btn,
.navbar a.nav-login-btn { white-space: nowrap; }

@media (max-width: 1199px) {
    header a.nav-login-btn,
    .navbar a.nav-login-btn { padding: 8px 16px !important; }
}

/* ══ PRODUCT SCREENSHOTS ═══════════════════════════════════════════════
   `.kveldo-shot` is the image counterpart of `.kveldo-mock`. The captures
   deliberately carry no browser chrome of their own, so the window frame is
   still drawn here — one frame, not two.

   Every image ships with width/height attributes, so the box is reserved
   before the file arrives and nothing shifts underneath the reader. The hero
   is the LCP element and is eager with fetchpriority=high; everything below
   the fold is lazy.
   ==================================================================== */
.kveldo-shot {
    margin: 0;
    border-radius: 14px;
    overflow: hidden;
    background: #fff;
    border: 1px solid #E9EFF9;
    box-shadow: 0 24px 60px rgba(11, 20, 38, .22);
}
.kveldo-shot__bar {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 11px 16px;
    background: #F4F7FD;
    border-bottom: 1px solid #E9EFF9;
}
.kveldo-shot__dot {
    width: 9px; height: 9px;
    border-radius: 50%;
    background: #CBD7EA;
    flex: 0 0 9px;
}
.kveldo-shot__title {
    margin-left: 10px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.kveldo-shot img {
    display: block;
    width: 100%;
    height: auto;
}

/* A tall capture is shown as its top band rather than shrunk to illegibility:
   the frame keeps a sane aspect and the image is anchored to its top edge. */
.kveldo-shot--crop {
    position: relative;
}
.kveldo-shot--crop img {
    aspect-ratio: 16 / 10;
    object-fit: cover;
    object-position: top center;
}

/* On the dark hero ground the frame needs its own edge to separate from the
   background, and a deeper shadow to sit above the radial glows. */
.kveldo-shot--hero {
    border-color: rgba(255, 255, 255, .10);
    box-shadow: 0 30px 80px rgba(0, 0, 0, .45);
}
.text-light .kveldo-shot,
.kveldo-ground .kveldo-shot {
    border-color: rgba(255, 255, 255, .10);
    box-shadow: 0 24px 64px rgba(0, 0, 0, .38);
}

/* ══ VERTICAL RHYTHM ═══════════════════════════════════════════════════
   A spacing audit found roughly 4,600px of recoverable height across the
   site, most of it caused by classes that silently did nothing rather than
   by padding that was deliberately chosen.

   The root cause of the silent failures: `.default-padding` sets the
   `padding` SHORTHAND with !important, in the stylesheet that loads last.
   A directional utility beside it — `pt-0`, `pb-0`, `top-less` — has equal
   or lower weight and loses, so the author asks for less space and gets
   none, with nothing to show anything went wrong.
   ==================================================================== */

/* `top-less` and `bottom-less` were used in markup on five pages but
   `top-less` was defined in NO stylesheet at all. Both are real now. */
.default-padding.top-less,
.top-less { padding-top: 0 !important; }
.default-padding.bottom-less,
.bottom-less { padding-bottom: 0 !important; }

/* Directional Bootstrap utilities now beat the shorthand. */
.default-padding.pt-0 { padding-top: 0 !important; }
.default-padding.pb-0 { padding-bottom: 0 !important; }
.default-padding.py-0 { padding-top: 0 !important; padding-bottom: 0 !important; }

/* A tighter band, for runs of consecutive sections that share a ground and
   would otherwise put 152px of flat color between two paragraphs. */
.default-padding--tight { padding: 52px 0 !important; }

/* A margin utility on a gutter row overwrites Bootstrap's negative-margin
   compensation (`.row{margin-top:calc(-1*var(--bs-gutter-y))}`) while every
   column keeps its +gutter, so the gap is the utility value PLUS the gutter.
   `mt-50` on a g-4 row measured 74px. These restore the stated value. */
.row[class*="g-"].mt-50 { margin-top: 26px; }
.row[class*="g-"].mt-40 { margin-top: 16px; }
.row[class*="g-"].mt-30 { margin-top: 6px; }
.row[class*="g-"].mt-4  { margin-top: 0; }
.row[class*="g-"].mt-3  { margin-top: 0; }
.row[class*="g-"].mt-2  { margin-top: 0; }

/* A gutter row already spaces its cards; the per-card bottom margin doubled it. */
.row[class*="g-"] > * > .services-style-one-item { margin-bottom: 0 !important; }

/* 30px of list margin plus 35px on the first item put 65px above the first
   bullet of a three-bullet list. */
.list-item li:first-child { margin-top: 0; }

/* The inner-page hero paid 90px at the bottom into a section paying 76px at
   the top — 166px between a tagline and the heading restating it. */
.breadcrumb-area { padding: 150px 0 60px !important; }

/* ── Footer tap targets on mobile ──────────────────────────────────────
   Footer links rendered 18px tall on a phone — 24 of them, stacked close
   together. The accepted minimum for a touch target is 44px, and this is
   the one place on the site where a mis-tap is likely: a column of short
   links with no spacing between them. Padding is added rather than
   line-height so the text position does not move on desktop. */
/* 991px, not 767 — iPad portrait is 768 wide and is a touch device. */
@media (max-width: 991px) {
    footer .f-item.link ul li a,
    footer .f-item ul li a {
        display: block;
        padding: 12px 0;
        min-height: 44px;
        line-height: 20px;
    }
    footer .f-item.link ul li,
    footer .f-item ul li { margin-bottom: 0; }
    /* the columns need room once each row is taller */
    footer .f-item.link { margin-bottom: 8px; }
    .footer-bottom ul li a { display: inline-block; padding: 10px 0; min-height: 44px; }
}

/* Pricing headline: the currency mark and the cadence.
   The vendor markup is <sup>$</sup>79<sub>/ month</sub> — browser-default
   super/subscript, which The base theme then pushes further with `top: -18px` on a
   zero line-height box. Measured result: the $ sat 16.9px ABOVE the h2's box
   entirely, so it read as a floating mark belonging to nothing, and the
   "/ month" dropped below the digits' baseline. Both are now positioned
   against the digits: the row is a baseline-aligned inline flex line, the $
   is pinned to the top of that line, and the cadence rides the baseline. */
.pricing-style-one .price h2 {
    display: inline-flex;
    align-items: baseline;
    line-height: 1;
}
.pricing-style-one .price h2 sup,
.pricing-style-one .price h2 sub {
    position: static;
    vertical-align: baseline;
    line-height: 1;
    top: auto;
    bottom: auto;
}
.pricing-style-one .price h2 sup {
    font-size: 0.42em;
    align-self: flex-start;
    margin-top: 0.14em;
    margin-right: 0.06em;
}
.pricing-style-one .price h2 sub {
    font-size: 0.36em;
    margin-left: 0.28em;
}

/* The annual-equivalent line under each price. Was four copies of the same
   inline style. It reserves two lines so that a one-line note and a two-line
   note leave the feature lists starting at the same y — the four notes are
   written to the same shape for the same reason. */
.pricing-style-one .price-note {
    color: #656F82;
    font-size: 0.8rem;
    margin-top: 4px;
    min-height: calc(2 * 1.7em);
}

/* ====================================================================
   Features by Plan — the plan matrix.
   The section's whole argument is "everything is on every plan; only
   capacity changes", but as sixteen identical rows of four ticks it read
   as a generic feature grid and argued nothing. This gives it a white
   card on the gray band, splits the body into two labeled bands so the
   shape of the argument is visible before a single row is read, and runs
   the Team column as one continuous tint the way /Pricing marks it.

   Scoped to .plan-matrix on purpose: .comparison-table is shared with
   /Pricing, /bank-statement-conversion and all five /compare pages, and
   none of them should change.
   ==================================================================== */
.plan-matrix__lead {
    margin: 14px auto 0;
    max-width: 44rem;
    color: var(--text-mid);
}
.plan-matrix {
    /* The row's column is a flex item, and a flex item's default min-width is
       auto — it refuses to shrink below its content. Without these the 703px
       table widened the card, the card widened the column, and the whole page
       scrolled sideways on a phone instead of the table scrolling inside it. */
    min-width: 0;
    max-width: 100%;
    background: var(--color-light);
    border: 1px solid rgba(16, 32, 64, .08);
    border-radius: 14px;
    box-shadow: 0 18px 44px rgba(16, 32, 64, .09);
    overflow: hidden;
}
/* Only the table scrolls sideways — the card and the note never do. */
.plan-matrix__scroll { overflow-x: auto; min-width: 0; max-width: 100%; }
/* Belt and braces, and measured rather than assumed: the scroller alone did not
   stop the 703px table contributing to the document's scroll width on a phone —
   the page scrolled sideways while the table sat still. Clipping at the section
   holds the page steady and leaves the inner scroller to move the table. */
.plan-matrix-section { overflow-x: hidden; }

.plan-matrix__table { font-size: .9rem; }
.plan-matrix__table th[scope="col"] {
    position: sticky;
    /* The site nav is fixed at 93px and z-index 100, so a header pinned to 0
       scrolls underneath it and the plan names disappear. Measured, not
       guessed: the nav is 93px at every scroll position. */
    top: 93px;
    z-index: 2;
    background: var(--color-light);
    border-bottom: 1px solid rgba(16, 32, 64, .1);
    white-space: nowrap;
}
/* The highlighted column's header is STICKY, so its tint has to be painted over
   an opaque ground rather than composited with whatever is behind it. As a flat
   rgba() it let the table scroll through: the check icon from the "Included on
   every plan" band showed up under the $199 caption, looking like a stray tick
   in the price row. Color layer as a background-image, opaque ground as the
   background-color — same appearance, nothing behind it. */
.plan-matrix__table th[scope="col"].kveldo-col {
    background-color: var(--color-light);
    background-image: linear-gradient(rgba(72, 127, 255, .09), rgba(72, 127, 255, .09));
}
.plan-matrix__table .plan-caption {
    display: block;
    font-weight: 500;
    font-size: .74rem;
    color: var(--text-mid);
    letter-spacing: .1px;
    margin-top: 2px;
}
/* The feature name is a row header, not a cell — it is what each row is about. */
.plan-matrix__table th[scope="row"] {
    text-align: left;
    font-weight: 500;
    color: var(--text-dark);
    padding: 13px 18px;
    border-bottom: 1px solid rgba(16, 32, 64, .05);
    min-width: 20rem;
}
.plan-matrix__table td {
    text-align: center;
    padding: 13px 18px;
    border-bottom: 1px solid rgba(16, 32, 64, .05);
}
/* The Team column reads as one continuous highlight, top to bottom. */
.plan-matrix__table td.kveldo-col { background: rgba(72, 127, 255, .05); }

/* Band headers: the two-part shape of the argument. */
.plan-matrix__table tr.plan-matrix__band td {
    text-align: left;
    padding: 16px 18px 10px;
    background: rgba(72, 127, 255, .06);
    border-bottom: 1px solid rgba(72, 127, 255, .16);
}
.plan-matrix__table tr.plan-matrix__band--change td {
    background: rgba(16, 32, 64, .04);
    border-bottom-color: rgba(16, 32, 64, .12);
}
.plan-matrix__band-title {
    font-weight: 700;
    color: var(--color-theme-dark);
    letter-spacing: .2px;
}
.plan-matrix__band-title i { margin-right: 7px; }
.plan-matrix__band--change .plan-matrix__band-title { color: var(--text-dark); }
.plan-matrix__band-note {
    margin-left: 10px;
    font-size: .78rem;
    color: var(--text-mid);
}

/* A tick is a filled disc, not a bare glyph — at four per row across
   sixteen rows the raw character reads as noise. */
.plan-matrix__table td.check i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--color-affirm-tint);
    color: var(--color-affirm);
    font-size: .72rem;
}
.plan-matrix__table td.cross i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: rgba(16, 32, 64, .05);
    color: #9AA6B8;
    font-size: .72rem;
}
.plan-matrix__unlimited { font-weight: 600; color: var(--color-affirm); }

.plan-matrix__table tbody tr:not(.plan-matrix__band):hover th[scope="row"],
.plan-matrix__table tbody tr:not(.plan-matrix__band):hover td { background: rgba(72, 127, 255, .04); }
.plan-matrix__table tbody tr:last-child th[scope="row"],
.plan-matrix__table tbody tr:last-child td { border-bottom: 0; }

.plan-matrix__note {
    margin: 0;
    padding: 16px 20px;
    background: rgba(16, 32, 64, .03);
    border-top: 1px solid rgba(16, 32, 64, .07);
    color: var(--text-mid);
    font-size: .84rem;
}

/* Below the desktop nav breakpoint the header becomes a hamburger and the
   table scrolls sideways anyway, so a pinned header buys nothing and risks
   colliding with a nav of a different height. */
@media (max-width: 991px) {
    .plan-matrix__table th[scope="col"] { position: static; top: auto; }
}
@media (max-width: 767px) {
    .plan-matrix__table th[scope="row"] { min-width: 15rem; }
    .plan-matrix__table th[scope="col"],
    .plan-matrix__table th[scope="row"],
    .plan-matrix__table td { padding: 11px 13px; }
}

/* ====================================================================
   Form labels.
   Labels above fields rather than placeholders doing the work: a
   placeholder disappears the moment someone starts typing, which is
   exactly when a person checking their own answer needs it. The
   required marker lives in the LABEL for the same reason -- it has to
   still be visible once the field has content.
   ==================================================================== */
.form-label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.86rem;
    font-weight: 600;
    color: var(--text-dark);
    letter-spacing: .1px;
}
.form-label .req {
    color: var(--color-attention);
    font-weight: 700;
    margin-left: 2px;
}
.field-error {
    display: block;
    margin-top: 5px;
    font-size: 0.82rem;
    color: var(--color-attention);
}
/* A field the browser or the server has marked invalid. */
.form-control.input-validation-error {
    border-color: var(--color-attention);
    background: var(--color-attention-tint);
}

/* Placeholder text sat at --text-muted, the same weight as real content, so a
   hint read as an answer somebody had already given. Now clearly lighter than
   the value that replaces it — and still above the 4.5:1 that placeholder text
   is exempt from but benefits from anyway. */
.form-control::placeholder,
.contact-form-style-one .form-control::placeholder {
    color: #A9B4C6;
    opacity: 1;                 /* Firefox dims placeholders by default */
}
.form-control::-webkit-input-placeholder { color: #A9B4C6; }
.form-control::-moz-placeholder { color: #A9B4C6; opacity: 1; }

/* ── Cookie consent banner ──────────────────────────────────────────────────
   Rendered by _ConsentBanner.cshtml, opened by kveldo-consent.js, and present
   in the DOM only when Google Analytics is configured.

   A bar along the bottom rather than a centered modal on a dimmed page: the
   visitor came to read the page, and a consent gate that blocks it teaches
   people to click Accept without reading. Both answers are one click, neither
   is hidden behind "manage preferences", and Decline is a real button rather
   than a link — a refusal that is harder to give than a consent is not one. */
.kv-consent {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 9999;
    background: var(--color-card-dark);
    border: 1px solid var(--color-border-dark);
    border-radius: 14px;
    box-shadow: var(--shadow-lg);
    padding: 20px 22px;
}
.kv-consent[hidden] { display: none; }

.kv-consent-inner {
    max-width: 1180px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 24px;
}
.kv-consent-copy { flex: 1 1 auto; }

.kv-consent-title {
    font-family: 'Montserrat', sans-serif;
    font-weight: 700;
    font-size: 1rem;
    color: var(--color-light);
    margin: 0 0 4px;
}
.kv-consent-text {
    font-size: 0.9rem;
    line-height: 1.55;
    color: #C7D2E4;
    margin: 0;
}
.kv-consent-text a { color: var(--color-cyan); text-decoration: underline; }

.kv-consent-actions {
    flex: 0 0 auto;
    display: flex;
    gap: 10px;
}
.kv-consent-btn {
    font-family: 'Outfit', sans-serif;
    font-weight: 600;
    font-size: 0.9rem;
    padding: 11px 26px;
    border-radius: 100px;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.kv-consent-btn-solid {
    background: var(--color-theme);
    color: #fff;
}
.kv-consent-btn-solid:hover { background: var(--color-theme-dark); }

.kv-consent-btn-ghost {
    background: transparent;
    color: #C7D2E4;
    border-color: var(--color-border-dark);
}
.kv-consent-btn-ghost:hover {
    color: var(--color-light);
    border-color: var(--color-theme);
}

/* Keyboard focus has to stay visible on a dark ground — this is the one control
   on the site a visitor may be navigating to specifically to refuse something. */
.kv-consent-btn:focus-visible {
    outline: 2px solid var(--color-cyan);
    outline-offset: 2px;
}

@media (max-width: 767px) {
    .kv-consent { left: 10px; right: 10px; bottom: 10px; padding: 18px; }
    .kv-consent-inner { flex-direction: column; align-items: stretch; gap: 16px; }
    .kv-consent-actions { justify-content: stretch; }
    .kv-consent-btn { flex: 1 1 0; padding: 12px 16px; }
}
