/* marketing/public/css/site.css — www.cn-s.org (idea #2670)
 *
 * Every color here is a var() from design-tokens.css, which is generated from
 * design/tokens/dark-plus.json. There is deliberately not a single hex in this file:
 * that's the house rule (idea #1426), and it's what makes the marketing site retheme in
 * lock-step with NetWatch and the PSA instead of drifting into a fourth palette.
 *
 * Where a translucent tint is needed, it's color-mix(in srgb, var(--token) N%, transparent)
 * rather than a retyped rgba(). Same reason: an rgba() literal goes stale the moment the
 * palette moves, and this site is meant to be the shop window for a product whose whole
 * pitch is that we keep things consistent.
 *
 * Conventions follow CLAUDE.md's visual guidelines: Inter stack, 14px base, flex/grid
 * layout, --radius-* corners, --shadow-* elevation, one breakpoint at 768px, FontAwesome
 * icons in their own <i>, no inline styles.
 */

/* ── reset / base ───────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
    margin: 0;
    font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-primary);
    background: var(--bg-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.2; font-weight: 700; color: var(--text-primary); }
h1 { font-size: 2.75rem; letter-spacing: -.02em; }
h2 { font-size: 2rem; letter-spacing: -.015em; }
h3 { font-size: 1.125rem; font-weight: 600; }
p { margin: 0 0 1em; }
a { color: var(--link-color); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--link-hover); }
img { max-width: 100%; height: auto; }

::selection { background: var(--selection-bg); }

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

/* Skip straight to content for keyboard/screen-reader users. */
#main { display: block; }

.eyebrow {
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--accent-color);
    margin: 0 0 .75rem;
}

.lede, .section-lede {
    font-size: 1.125rem;
    line-height: 1.6;
    color: var(--text-secondary);
    max-width: 62ch;
}

/* ── buttons ────────────────────────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .7rem 1.25rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-size: .95rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition), transform var(--transition);
    text-align: center;
}
.btn:active { transform: scale(.98); }

/* --accent-chrome is a FILL and never text (CLAUDE.md) — a button background is exactly what
   it exists for. What that rule doesn't say is that the INVERSE also needs care: on #007acc,
   --text-primary is only 3.4:1 and --bg-primary is worse, so both fail AA. --on-accent
   (white, 5.0:1) is the only one that passes, which is why that token exists.

   The color then FLIPS on hover, and that is deliberate rather than an oversight: hover
   lightens the fill to --accent-hover (#4daafc), where white drops to ~2.5:1 and fails,
   while dark text rises to ~6.8:1. Each state uses the one that passes on its own fill. */
.btn-primary { background: var(--accent-chrome); color: var(--on-accent); font-weight: 600; }
.btn-primary:hover { background: var(--accent-hover); color: var(--bg-primary); }

.btn-outline { background: transparent; border-color: var(--border-strong); color: var(--text-primary); }
.btn-outline:hover { border-color: var(--accent-color); color: var(--accent-color); background: var(--accent-subtle); }

.btn-block { width: 100%; justify-content: center; }
.btn[disabled] { opacity: .55; cursor: not-allowed; }
.btn[disabled]:active { transform: none; }

/* ── header / nav ───────────────────────────────────────────────────────── */
.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: .85rem 2rem;
    background: color-mix(in srgb, var(--bg-secondary) 92%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border-subtle);
}

.brand { display: flex; align-items: center; gap: .75rem; color: var(--text-primary); }
.brand:hover { color: var(--text-primary); }

/* The CNS logo lockup. Was a "CN" monogram tile on --accent-chrome; it is now the real brand
   asset, so there is no colored backing plate — the logo carries its own color and a solid
   tile behind a transparent PNG would only box it in. Sized by height with width:auto so the
   asset's own 551x122 ratio is preserved rather than squashed. */
.brand-logo {
    height: 46px;
    width: auto;
    flex: 0 0 auto;
    display: block;
}

.foot-brand .brand-logo { height: 52px; margin-bottom: .5rem; }

/* (.brand-text / .brand-name / .brand-tag were removed with the header's duplicate company
   name — the logo lockup already reads "COMPUTER & NETWORK SOLUTIONS".) */

.site-nav { display: flex; align-items: center; gap: .35rem; margin-left: auto; }
.site-nav a {
    padding: .5rem .8rem;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: .9rem;
    font-weight: 500;
}
.site-nav a:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.site-nav a.active { color: var(--accent-color); background: var(--accent-subtle); }
.site-nav .nav-cta { margin-left: .5rem; color: var(--on-accent); }
.site-nav .nav-cta:hover { color: var(--bg-primary); }

.nav-toggle {
    display: none;
    margin-left: auto;
    padding: .5rem .7rem;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 1rem;
    cursor: pointer;
}

/* ── hero ───────────────────────────────────────────────────────────────── */
.hero {
    position: relative;
    padding: 5.5rem 2rem 4.5rem;
    overflow: hidden;
    border-bottom: 1px solid var(--border-subtle);
    background:
        radial-gradient(900px 420px at 78% -10%, var(--accent-subtle), transparent 70%),
        var(--bg-primary);
}

.hero-inner {
    max-width: 1180px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    gap: 3.5rem;
    align-items: center;
}
.hero-inner:has(.hero-copy:only-child) { grid-template-columns: minmax(0, 1fr); }

.hero h1 { margin-bottom: 1rem; }
.hero .lede { font-size: 1.2rem; margin-bottom: 1.75rem; }

.cta-row { display: flex; flex-wrap: wrap; gap: .75rem; }

/* The hero's right-hand product panel — a fake app chrome so the site shows the thing it
   is selling. Same surfaces/borders as the real dashboards, because they're the same tokens. */
.mock-window {
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--bg-secondary);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}
.mock-bar {
    display: flex; align-items: center; gap: .5rem;
    padding: .6rem .9rem;
    background: var(--bg-tertiary);
    border-bottom: 1px solid var(--border-subtle);
    font-size: .75rem;
    color: var(--text-muted);
}
.mock-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--border-strong); }
.mock-dot.is-live { background: var(--success); }
.mock-body { padding: 1rem; display: grid; gap: .6rem; }

.mock-row {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: .75rem;
    padding: .6rem .75rem;
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--bg-tertiary);
    font-size: .82rem;
}
.mock-row.ok { border-left-color: var(--success); }
.mock-row.warn { border-left-color: var(--warning); }
.mock-row.info { border-left-color: var(--accent-color); }
.mock-host { color: var(--text-primary); font-weight: 500; }
.mock-meta { display: block; color: var(--text-muted); font-size: .74rem; margin-top: .15rem; }

/* Status pill — the house idiom: translucent tint + solid text (station-modal pattern). */
.pill {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .18rem .55rem;
    border-radius: 10px;
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
}
.pill-success { background: var(--success-subtle); color: var(--success); }
.pill-warning { background: var(--warning-subtle); color: var(--warning); }
.pill-danger  { background: var(--danger-subtle);  color: var(--danger); }
.pill-info    { background: var(--accent-subtle);  color: var(--accent-color); }
.pill-purple  { background: var(--purple-subtle);  color: var(--purple); }
.pill-teal    { background: var(--teal-subtle);    color: var(--teal); }

/* ── sections ───────────────────────────────────────────────────────────── */
.section { padding: 4.5rem 2rem; }
.section-inner { max-width: 1180px; margin: 0 auto; }
.section h2 { margin-bottom: .75rem; }
.section-lede { margin-bottom: 2.5rem; }

.tone-alt { background: var(--bg-secondary); border-block: 1px solid var(--border-subtle); }
.tone-deep { background: var(--bg-tertiary); border-block: 1px solid var(--border-subtle); }

/* ── cards ──────────────────────────────────────────────────────────────── */
.card-grid { display: grid; gap: 1.25rem; }
.card-grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.card-grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.card-grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.card {
    padding: 1.5rem;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition);
}
.card:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow-md); }
.card h3 { margin-bottom: .5rem; }
.card p { color: var(--text-secondary); margin-bottom: 0; }

.card-icon {
    display: grid; place-items: center;
    width: 42px; height: 42px;
    margin-bottom: 1rem;
    border-radius: var(--radius-md);
    background: var(--accent-subtle);
    color: var(--accent-color);
    font-size: 1.05rem;
}

.card-points { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: .5rem; }
.card-points li { display: flex; gap: .55rem; align-items: flex-start; font-size: .875rem; color: var(--text-secondary); }
.card-points li i { color: var(--success); margin-top: .18rem; flex: 0 0 auto; }

/* A list of things we DON'T do (the "It does not create" panel on /get-started). Its marks
   are ✗, and inheriting the green above made them read as green ticks at a glance — the
   exact opposite of the meaning, on the one panel whose entire job is to reassure someone
   that we are not installing anything. Muted rather than red: these are reassurances, not
   errors, and --danger would make a calm list look like a warning. */
.card-points.is-negative li i { color: var(--text-muted); }

/* ── stat strip ─────────────────────────────────────────────────────────── */
.stat-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1px;
    background: var(--border-subtle);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.stat { padding: 1.5rem 1.25rem; background: var(--bg-secondary); text-align: center; }
.stat-value { display: block; font-size: 1.75rem; font-weight: 700; color: var(--accent-color); }
.stat-label { display: block; margin-top: .35rem; font-size: .8rem; color: var(--text-secondary); }

/* ── alternating detail rows ────────────────────────────────────────────── */
.detail-rows { display: grid; gap: 3.5rem; }
.detail-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3rem;
    align-items: center;
}
.detail-row.reverse .detail-copy { order: 2; }
.detail-row h3 { font-size: 1.5rem; font-weight: 700; }
.detail-row p { color: var(--text-secondary); }
.detail-row .eyebrow { display: flex; align-items: center; gap: .45rem; }

/* ── key/value detail items (house pattern) ─────────────────────────────── */
.kv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 1.25rem; }
.kv-item { display: flex; flex-direction: column; gap: .25rem; }
.kv-label { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }
.kv-value { font-size: 13px; color: var(--text-primary); }

/* ── CTA band ───────────────────────────────────────────────────────────── */
.cta-band {
    padding: 4.5rem 2rem;
    text-align: center;
    border-top: 1px solid var(--border-subtle);
    background:
        radial-gradient(700px 300px at 50% 0%, var(--accent-subtle), transparent 70%),
        var(--bg-secondary);
}
.cta-band .section-lede { margin-inline: auto; margin-bottom: 2rem; }
.cta-band .cta-row { justify-content: center; }
.cta-alt { margin-top: 1.5rem; font-size: .875rem; color: var(--text-muted); }

/* ── forms ──────────────────────────────────────────────────────────────── */
.form-card {
    max-width: 640px;
    padding: 2rem;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}
.form-grid { display: grid; gap: 1.1rem; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }

.field { display: flex; flex-direction: column; gap: .4rem; }
.field label { font-size: .82rem; font-weight: 600; color: var(--text-secondary); }
.field .req { color: var(--danger); margin-left: .15rem; }
.field .hint { font-size: .78rem; color: var(--text-muted); }

.field input, .field textarea, .field select {
    padding: .65rem .8rem;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: inherit;
    font-size: .92rem;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.field input::placeholder, .field textarea::placeholder { color: var(--text-muted); }
.field input:focus, .field textarea:focus, .field select:focus {
    outline: none;
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px var(--accent-subtle);
}
.field textarea { min-height: 130px; resize: vertical; }

/* The honeypot. Must be invisible to humans but NOT display:none — some bots skip
   display:none fields specifically because they know it's a trap. Off-screen with
   aria-hidden + tabindex=-1 keeps it out of the tab order and off screen readers. */
.hp-field {
    position: absolute !important;
    left: -9999px !important;
    width: 1px; height: 1px;
    overflow: hidden;
}

.form-status { padding: .85rem 1rem; border-radius: var(--radius-sm); font-size: .9rem; display: none; }
.form-status.show { display: block; }
.form-status.ok { background: var(--success-subtle); color: var(--success); }
.form-status.err { background: var(--danger-subtle); color: var(--danger); }

.form-note { font-size: .8rem; color: var(--text-muted); margin-top: 1rem; }

.form-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); gap: 3rem; align-items: start; }

/* ── contact/support tiles ──────────────────────────────────────────────── */
.contact-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; }
.contact-tile {
    display: flex; gap: .9rem; align-items: flex-start;
    padding: 1.25rem;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-color);
    border-radius: var(--radius-md);
}
.contact-tile i { color: var(--accent-color); font-size: 1.1rem; margin-top: .15rem; }
.contact-tile strong { display: block; font-size: .95rem; }
.contact-tile span { font-size: .85rem; color: var(--text-secondary); }

/* ── prose (privacy policy etc.) ────────────────────────────────────────── */
/* Long-form reading: the About story and the privacy policy. The 14px/1.5 body scale is right
   for dense dashboard UI, which is what it was chosen for — it is too tight for prose, and the
   About page's history section is the most important copy on the site. 16px at 1.75 with a
   ~68ch measure is a normal reading setting; the section-lede above it stays larger so the
   hierarchy still reads. */
.prose { max-width: 68ch; font-size: 1rem; line-height: 1.75; }
.prose h2 { font-size: 1.4rem; margin-top: 2.25rem; }
.prose h3 { margin-top: 1.75rem; }
.prose p, .prose li { color: var(--text-secondary); }
.prose p { margin-bottom: 1.15em; }
.prose strong { color: var(--text-primary); }
.prose ul { padding-left: 1.25rem; display: grid; gap: .5rem; }

/* ── footer ─────────────────────────────────────────────────────────────── */
.site-footer { background: var(--bg-secondary); border-top: 1px solid var(--border-subtle); }
.foot-grid {
    max-width: 1180px;
    margin: 0 auto;
    padding: 3.5rem 2rem 2.5rem;
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
    gap: 2.5rem;
}
.foot-col { display: flex; flex-direction: column; gap: .55rem; }
.foot-col h3 { font-size: .78rem; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted); margin-bottom: .35rem; }
.foot-col a { color: var(--text-secondary); font-size: .88rem; }
.foot-col a:hover { color: var(--accent-color); }
.foot-blurb { color: var(--text-secondary); font-size: .88rem; max-width: 40ch; margin: .75rem 0 .5rem; }
.foot-contact { display: flex; flex-direction: column; gap: .35rem; margin: 0; }
.foot-contact a { font-size: .88rem; }

.foot-bar {
    max-width: 1180px;
    margin: 0 auto;
    padding: 1.25rem 2rem;
    border-top: 1px solid var(--border-subtle);
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: .82rem;
    color: var(--text-muted);
}
.foot-bar a { color: var(--text-muted); }
.foot-bar a:hover { color: var(--accent-color); }

/* ── utilities ──────────────────────────────────────────────────────────── */
/* Bootstrap-NAMED so the markup reads the same as the rest of the app, even though this
   site doesn't load Bootstrap (house rule: prefer the familiar utility names where they
   exist rather than inventing new ones). Kept to the handful actually used — an unused
   utility framework is just dead CSS. */
.mt-1 { margin-top: .5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.5rem; }
.mb-0 { margin-bottom: 0; }
.text-center { text-align: center; }
.mx-auto { margin-inline: auto; }
.justify-center { justify-content: center; }
.d-flex { display: flex; }
.gap-2 { gap: 1rem; }

/* ── 404 ────────────────────────────────────────────────────────────────── */
.notfound { padding: 6rem 2rem; text-align: center; }
.notfound .code { font-size: 4rem; font-weight: 700; color: var(--accent-color); line-height: 1; }

/* ── responsive: one breakpoint, per the house rule ─────────────────────── */
@media (max-width: 768px) {
    h1 { font-size: 2rem; }
    h2 { font-size: 1.55rem; }

    .site-header { flex-wrap: wrap; padding: .75rem 1rem; }
    .brand-tag { display: none; }
    .nav-toggle { display: block; }
    .site-nav {
        display: none;
        width: 100%;
        margin-left: 0;
        flex-direction: column;
        align-items: stretch;
        gap: .15rem;
        padding-top: .75rem;
    }
    .site-nav.open { display: flex; }
    .site-nav .nav-cta { margin-left: 0; justify-content: center; margin-top: .5rem; }

    .hero { padding: 3rem 1.25rem 2.5rem; }
    .hero-inner { grid-template-columns: minmax(0, 1fr); gap: 2.25rem; }
    .hero .lede { font-size: 1.05rem; }

    .section { padding: 3rem 1.25rem; }
    .cta-band { padding: 3rem 1.25rem; }

    .detail-row { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
    .detail-row.reverse .detail-copy { order: 0; }

    .form-layout { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
    .form-row { grid-template-columns: minmax(0, 1fr); }
    .form-card { padding: 1.25rem; }

    .foot-grid { grid-template-columns: minmax(0, 1fr); padding: 2.5rem 1.25rem 1.5rem; gap: 1.75rem; }
    .foot-bar { flex-direction: column; align-items: flex-start; padding: 1rem 1.25rem; }
}

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

/* ── cookie consent ─────────────────────────────────────────────────────── */
/* Opt-in consent for Cloudflare Web Analytics (idea #2670).
 *
 * Accept and Reject are deliberately the SAME size, weight and visual prominence. A banner
 * where "Accept" is a filled button and "Reject" is a grey link is a dark pattern, and under
 * GDPR a consent obtained that way is not freely given — i.e. it is worth nothing. If someone
 * later "improves" this by making Accept stand out, they have broken the thing it exists for.
 *
 * It is a bottom BAR, not a modal overlay: the page stays readable and usable while undecided,
 * which is also a consent requirement (access must not be conditional on accepting).
 */
.cookie-bar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 100;
    display: none;
    padding: 1rem 1.25rem;
    background: var(--bg-elevated);
    border-top: 1px solid var(--border-strong);
    box-shadow: var(--shadow-lg);
}
.cookie-bar.show { display: block; }

.cookie-inner {
    max-width: 1180px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.cookie-copy { flex: 1 1 420px; margin: 0; font-size: .875rem; color: var(--text-secondary); }
.cookie-copy strong { color: var(--text-primary); }

.cookie-actions { display: flex; gap: .6rem; flex: 0 0 auto; }
/* Both buttons use the SAME variant on purpose — see the note above. */
.cookie-actions .btn { min-width: 132px; justify-content: center; }

@media (max-width: 768px) {
    .cookie-inner { gap: .9rem; }
    .cookie-actions { width: 100%; }
    .cookie-actions .btn { flex: 1 1 0; min-width: 0; }
}

/* Footer legal/preferences links, kept together at the right of the bottom bar. */
.foot-bar-links { display: flex; gap: 1.25rem; }

/* ── floating "Reach us" card ───────────────────────────────────────────── */
/* Was a panel inside the home page's third differentiator row; it now follows the page so the
 * phone number is one click away from any scroll position. Same mock-window styling as before
 * — this is a relocation, not a redesign.
 *
 * Fixed rather than sticky: it has to outlive the section it came from. Right-hand side and
 * vertically centered, which keeps it clear of the sticky header and the cookie bar.
 */
/* Anchored BOTTOM-right, not middle-right. Worth the note, because middle-right was the first
   attempt and the geometry rules it out: the content column is 1180px wide and centered, so a
   300px card inset 20px from the right edge only clears it once the viewport passes ~1820px.
   On a 1440px laptop it sits directly over the right-hand cards of every full grid row.
   Bottom-right is where users expect a floating contact control and where they are practised
   at ignoring one — and it overlaps the end of a section rather than the middle of a card. */
.reach-float {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    z-index: 60;                /* above content, below the cookie bar (100) */
    width: 300px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: .5rem;
}

.reach-toggle {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    align-self: flex-end;
    padding: .5rem .85rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    color: var(--text-primary);
    font-family: inherit;
    font-size: .82rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition);
}
.reach-toggle:hover { border-color: var(--accent-color); color: var(--accent-color); }
.reach-toggle i { color: var(--accent-color); }
.reach-chevron { transition: transform var(--transition); font-size: .7rem; }

.reach-float { flex-direction: column-reverse; }

.reach-panel {
    box-shadow: var(--shadow-lg);
    transition: opacity var(--transition), transform var(--transition);
    transform-origin: bottom right;
}

/* Collapsed: the panel folds away and only the toggle remains. */
.reach-float.collapsed .reach-panel {
    display: none;
}
.reach-float.collapsed .reach-chevron { transform: rotate(180deg); }

/* The rows are real links here (they were inert divs in the inline version), so they need
   hover affordance and must not inherit the global link color over the mock-row styling. */
a.reach-row { text-decoration: none; color: inherit; }
a.reach-row:hover {
    border-color: var(--border-strong);
    background: var(--bg-elevated);
    color: inherit;
}
a.reach-row .mock-host { color: var(--text-primary); }

/* Below 1200px the card would sit on top of the content it exists to support, so it is
   replaced by a single call button — for a local services business on a phone, that is the
   only control that matters. Nothing is lost: the same details are in the footer, the CTA
   bands and /support. */
@media (max-width: 1199px) {
    .reach-float {
        width: auto;
    }
    .reach-float .reach-panel { display: none; }
    .reach-float .reach-chevron { display: none; }
    .reach-toggle {
        border-radius: 999px;
        padding: .8rem 1.15rem;
        background: var(--accent-chrome);
        border-color: var(--accent-chrome);
        color: var(--on-accent);
        box-shadow: var(--shadow-lg);
    }
    .reach-toggle i { color: var(--on-accent); }
}

/* While the cookie bar is up, the mobile call button would sit on top of it. An earlier
   attempt offset it by a fixed 6.5rem, which was a guess — the bar wraps to roughly double
   that height on a 390px screen, so they still overlapped. Rather than chase the number,
   the button simply stands down until a choice has been made: the banner is asking for a
   decision, and stacking a second floating control over it helps nobody.

   Desktop is unaffected — that card is vertically centered and never comes near the bar. */
@media (max-width: 1199px) {
    body.cookie-visible .reach-float { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .reach-panel, .reach-chevron { transition: none; }
}
