/* ==========================================================================
   KimTech Labs / Dennis Kimatu Kioko — portfolio design system (v4)
   Dark-first "modern engineering" aesthetic: mesh gradient background, subtle
   blueprint grid overlay, glass cards, single-hue sky-blue accent (pulled
   directly from the original site's own light/dark color scheme - no
   violet/cyan), Plus Jakarta Sans for text + JetBrains Mono for code-styled
   accents (eyebrows, hero role line, brand mark).
   A light theme is kept for the toggle, built on the same structure.
   ========================================================================== */

:root {
    --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
    --font-mono: 'JetBrains Mono', 'Consolas', 'SFMono-Regular', Menlo, monospace;

    /* Dark theme (default) - accents match the original site's own dark scheme */
    --bg: #05070d;
    --bg-alt: #10141f;
    --surface: rgba(255, 255, 255, 0.06);
    --surface-strong: rgba(255, 255, 255, 0.1);
    --border: rgba(255, 255, 255, 0.13);
    --text: #eef1f8;
    --text-muted: #8b93a7;
    --accent1: #38bdf8; /* sky-400 - primary, matches original dark-mode accent */
    --accent2: #0ea5e9; /* sky-500 - matches original light-mode accent, same hue */
    --accent3: #7dd3fc; /* sky-300 - lighter highlight, same hue */
    --accent-rgb: 56, 189, 248;
    --mesh-op-1: 0.18;
    --mesh-op-2: 0.16;
    --mesh-op-3: 0.10;
    --btn-primary-text: #04050a;
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.35);
}

:root[data-theme='light'] {
    --bg: #f9fafb;
    --bg-alt: #eef1f6;
    --surface: rgba(255, 255, 255, 0.85);
    --surface-strong: rgba(255, 255, 255, 0.98);
    --border: #dde1e8;
    --text: #1f2937;
    --text-muted: #4b5563;
    --accent1: #0ea5e9; /* sky-500 - original light-mode accent */
    --accent2: #0284c7; /* sky-600 - hover shade, same hue */
    --accent3: #0369a1; /* sky-700 - deeper highlight, same hue */
    --accent-rgb: 14, 165, 233;
    --mesh-op-1: 0.10;
    --mesh-op-2: 0.08;
    --mesh-op-3: 0.06;
    --btn-primary-text: #ffffff;
    --shadow-card: 0 1px 2px rgba(15, 23, 42, 0.04), 0 8px 24px rgba(15, 23, 42, 0.06);
}

* { box-sizing: border-box; }

/* Tells the browser which scheme its OWN widgets should use — select popups,
   scrollbars, focus rings, native date pickers. Without it Chrome renders a
   white dropdown list and inherits our near-white text into it, which is why
   the options were unreadable. CSS can't reach inside those popups; this is
   the only lever. */
:root { color-scheme: dark; }
:root[data-theme='light'] { color-scheme: light; }

html { scroll-behavior: smooth; }

body {
    margin: 0;
    font-family: var(--font-sans);
    background-color: var(--bg);
    color: var(--text);
    line-height: 1.6;
    transition: background-color 0.4s ease, color 0.4s ease;
    overflow-x: hidden;
}

a { color: inherit; }

.container { width: 100%; max-width: 1180px; margin: 0 auto; padding: 0 1.5rem; }

.visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
}

/* ---------- Ambient background: mesh gradient + blueprint grid ---------- */
.mesh {
    position: fixed; inset: 0; z-index: 0; pointer-events: none;
    background:
        radial-gradient(600px circle at 15% 20%, rgba(var(--accent-rgb), var(--mesh-op-1)), transparent 60%),
        radial-gradient(500px circle at 85% 15%, rgba(var(--accent-rgb), var(--mesh-op-2)), transparent 60%),
        radial-gradient(700px circle at 50% 90%, rgba(var(--accent-rgb), var(--mesh-op-3)), transparent 60%);
    animation: drift 18s ease-in-out infinite alternate;
}

@keyframes drift {
    0% { transform: translate3d(0, 0, 0) scale(1); }
    100% { transform: translate3d(-2%, 2%, 0) scale(1.06); }
}

.grid-overlay {
    position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: 0.35;
    background-image:
        linear-gradient(rgba(var(--accent-rgb), 0.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--accent-rgb), 0.05) 1px, transparent 1px);
    background-size: 44px 44px;
    mask-image: radial-gradient(circle at 50% 0%, black, transparent 75%);
}

:root[data-theme='light'] .grid-overlay { opacity: 0.5; }

/* ---------- Navbar ---------- */
.navbar {
    position: sticky; top: 0; z-index: 50;
    backdrop-filter: blur(14px);
    background: rgba(5, 7, 13, 0.6);
    border-bottom: 1px solid var(--border);
}

:root[data-theme='light'] .navbar { background: rgba(249, 250, 251, 0.75); }

.navbar-inner { display: flex; align-items: center; justify-content: space-between; height: 4.5rem; }

.brand {
    font-weight: 800; font-size: 1.1rem; text-decoration: none;
    display: flex; align-items: center; gap: 0.6rem; letter-spacing: 0.01em;
}

.brand-mark {
    width: 2.1rem; height: 2.1rem; border-radius: 0.55rem;
    background: linear-gradient(135deg, var(--accent1), var(--accent2));
    display: flex; align-items: center; justify-content: center;
    font-size: 0.72rem; font-weight: 800; color: var(--btn-primary-text);
    font-family: var(--font-mono);
    box-shadow: 0 0 24px rgba(var(--accent-rgb), 0.45);
}

.nav-links { display: none; gap: 2.25rem; list-style: none; margin: 0; padding: 0; }
.nav-links a { text-decoration: none; font-weight: 500; font-size: 0.92rem; color: var(--text-muted); transition: color 0.2s; }
.nav-links a:hover { color: var(--text); }

.nav-actions { display: flex; align-items: center; gap: 0.75rem; }

.theme-toggle, .menu-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.4rem; height: 2.4rem; border-radius: 999px;
    border: 1px solid var(--border); background: transparent; color: var(--text); cursor: pointer;
}
.theme-toggle svg, .menu-toggle svg { width: 1.1rem; height: 1.1rem; }

.nav-cta {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.6rem 1.2rem; border-radius: 0.6rem; font-weight: 700; font-size: 0.88rem;
    text-decoration: none; color: var(--btn-primary-text);
    background: linear-gradient(135deg, var(--accent1), var(--accent2));
}

.mobile-menu {
    display: none; flex-direction: column; gap: 0.25rem;
    padding: 0.5rem 1.5rem 1.25rem; border-bottom: 1px solid var(--border); background: var(--bg);
}
.mobile-menu.is-open { display: flex; }
.mobile-menu a { padding: 0.6rem 0; text-decoration: none; color: var(--text); font-weight: 500; border-bottom: 1px solid var(--border); }

@media (min-width: 860px) {
    .nav-links { display: flex; }
    .menu-toggle { display: none; }
}

/* ---------- Hero (text-only, no photo) ---------- */
.hero { position: relative; z-index: 1; padding: 7rem 0 5rem; text-align: center; }
.hero-inner { max-width: 760px; margin: 0 auto; }

/* On desktop the hero owns the whole first screen: viewport height minus the
   4.5rem sticky navbar, content optically centred inside it. The `svh` line
   overrides the `vh` one where supported (mobile Safari, where `vh` counts
   retracting browser chrome). Also gated on a min-height so short landscape
   laptops don't get a cramped, clipped hero. */
@media (min-width: 900px) and (min-height: 620px) {
    .hero {
        min-height: calc(100vh - 4.5rem);
        min-height: calc(100svh - 4.5rem);
        display: flex; flex-direction: column;
        align-items: center; justify-content: center;
        padding: 3rem 0 7rem;
    }
    .hero-inner { width: 100%; }
    .hero-scroll-cue { display: flex; }
}

/* Scroll affordance - only shown when the hero is full-height, otherwise the
   next section is already in view and the cue would just be noise. */
.hero-scroll-cue {
    display: none;
    position: absolute; bottom: 2.5rem; left: 50%; transform: translateX(-50%);
    flex-direction: column; align-items: center; gap: 0.6rem;
    text-decoration: none; color: var(--text-muted);
    font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.18em;
    text-transform: uppercase;
    transition: color 0.2s ease;
}
.hero-scroll-cue:hover { color: var(--accent1); }
.hero-scroll-cue .cue-track {
    width: 1.45rem; height: 2.35rem; border-radius: 999px;
    border: 1px solid var(--border);
    display: flex; justify-content: center; padding-top: 0.42rem;
}
.hero-scroll-cue .cue-dot {
    width: 0.28rem; height: 0.45rem; border-radius: 999px; background: var(--accent1);
    animation: cue-drop 1.9s ease-in-out infinite;
}
@keyframes cue-drop {
    0%, 100% { transform: translateY(0); opacity: 1; }
    55% { transform: translateY(0.72rem); opacity: 0.25; }
}

.kicker {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.4rem 0.9rem; border-radius: 999px; font-size: 0.78rem; font-weight: 600;
    background: var(--surface); border: 1px solid var(--border); color: var(--accent3);
    margin-bottom: 1.5rem;
}
.kicker .pulse {
    width: 0.45rem; height: 0.45rem; border-radius: 999px; background: var(--accent1);
    box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.6); animation: pulse 2s infinite;
}
@keyframes pulse {
    0% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.55); }
    70% { box-shadow: 0 0 0 8px rgba(var(--accent-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0); }
}

.hero h1 {
    font-size: clamp(2.4rem, 5.5vw, 3.75rem); line-height: 1.08; font-weight: 800;
    margin: 0 0 1.1rem; letter-spacing: -0.02em;
}
.hero h1 .grad {
    background: linear-gradient(100deg, var(--accent1), var(--accent2));
    -webkit-background-clip: text; background-clip: text; color: transparent;
}

.hero-role {
    font-size: clamp(1.05rem, 2.3vw, 1.3rem); color: var(--text-muted);
    margin: 0 0 2.2rem; min-height: 1.8em; font-family: var(--font-mono);
}
.hero-role .accent { color: var(--accent3); }
.hero-role .cursor { color: var(--accent1); animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0; } }

.hero-actions { display: flex; flex-wrap: wrap; gap: 0.9rem; justify-content: center; }

.hero-stats {
    display: flex; gap: 2.4rem; margin-top: 3.25rem; flex-wrap: wrap; justify-content: center;
}
.hero-stats .stat-num {
    font-size: 1.6rem; font-weight: 800;
    background: linear-gradient(135deg, var(--accent1), var(--accent3));
    -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero-stats .stat-label { font-size: 0.8rem; color: var(--text-muted); font-weight: 500; }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; gap: 0.55rem;
    padding: 0.85rem 1.7rem; border-radius: 0.7rem; font-weight: 700; font-size: 0.95rem;
    text-decoration: none; border: none; cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}
.btn-primary {
    color: var(--btn-primary-text);
    background: linear-gradient(135deg, var(--accent1), var(--accent2));
    box-shadow: 0 10px 30px -8px rgba(var(--accent-rgb), 0.55);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 16px 36px -8px rgba(var(--accent-rgb), 0.7); }
.btn-ghost { color: var(--text); background: var(--surface); border: 1px solid var(--border); }
.btn-ghost:hover { border-color: var(--accent1); background: var(--surface-strong); }
.btn-danger { background: #dc2626; color: #fff; }
.btn-danger:hover { background: #b91c1c; }

/* ---------- Sections ---------- */
section { position: relative; z-index: 1; padding: 5.5rem 0; border-top: 1px solid var(--border); }
section#home { border-top: none; }
.section-alt { background: var(--bg-alt); }

.section-head { text-align: center; max-width: 640px; margin: 0 auto 3rem; }
.eyebrow {
    display: block; font-size: 0.78rem; font-weight: 600; letter-spacing: 0.03em;
    color: var(--accent3); margin-bottom: 0.75rem; font-family: var(--font-mono);
}
.section-head h2 { font-size: clamp(1.85rem, 3.2vw, 2.35rem); margin: 0 0 0.75rem; font-weight: 800; letter-spacing: -0.01em; }
.section-head p { color: var(--text-muted); margin: 0; }

/* ---------- Cards (shared) ---------- */
.card {
    background: var(--surface); border: 1px solid var(--border); border-radius: 1.1rem;
    padding: 1.9rem; box-shadow: var(--shadow-card); backdrop-filter: blur(14px);
    position: relative; overflow: hidden;
    transition: transform 0.25s ease, border-color 0.25s ease, background 0.25s ease, box-shadow 0.25s ease;
}
/* A thin accent strip along the top edge keeps cards reading as distinct
   components against whichever section background they sit on. */
.card::after {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
    background: linear-gradient(90deg, var(--accent1), var(--accent3));
    opacity: 0.55; transition: opacity 0.25s ease;
}
.card:hover::after { opacity: 1; }
.card:hover { transform: translateY(-4px); border-color: rgba(var(--accent-rgb), 0.4); background: var(--surface-strong); }

/* ---------- About ---------- */
.about-grid { display: grid; gap: 2.5rem; }
@media (min-width: 900px) { .about-grid { grid-template-columns: 0.75fr 1.25fr; align-items: center; } }

.about-copy p { color: var(--text-muted); margin: 0 0 1.1rem; }
.about-copy p:last-child { margin-bottom: 0; }

/* Clean, static photo frame (no spin, no floating badges) - lives in About only */
.photo-frame-wrap { display: flex; justify-content: center; }
.photo-frame {
    position: relative; width: clamp(200px, 60%, 300px); aspect-ratio: 1;
    border-radius: 1.5rem; overflow: hidden;
    border: 1px solid rgba(var(--accent-rgb), 0.35);
    box-shadow: 0 24px 48px -20px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.03) inset;
}
.photo-frame::before {
    content: ''; position: absolute; inset: -30%; z-index: 0;
    background: radial-gradient(circle, rgba(var(--accent-rgb), 0.25), transparent 70%);
    filter: blur(10px);
}
.photo-frame img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }

/* ---------- Skills ---------- */
.skills-grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.skill-card h3 { margin: 0 0 1rem; font-size: 1.05rem; display: flex; align-items: center; gap: 0.65rem; }
.skill-icon {
    width: 2.1rem; height: 2.1rem; border-radius: 0.6rem; display: flex; align-items: center; justify-content: center;
    font-size: 1rem; background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.22), rgba(var(--accent-rgb), 0.1));
}
.pill-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pill {
    font-size: 0.78rem; font-weight: 600; padding: 0.35rem 0.75rem; border-radius: 999px;
    background: rgba(var(--accent-rgb), 0.1); border: 1px solid var(--border); color: var(--text-muted);
}
/* Tighter variant for the tech-stack row inside project cards, so the pills
   stay secondary to the summary text above them. */
.pill-sm { font-size: 0.7rem; padding: 0.28rem 0.6rem; }

/* ---------- Projects ---------- */
.projects-grid { display: grid; gap: 1.75rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.project-card { display: flex; flex-direction: column; overflow: hidden; padding: 0; }
.project-card img, .project-thumb {
    width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
    border-bottom: 1px solid var(--border);
}

/* Placeholder tile for projects with no screenshot yet: a blueprint grid
   fading out at the edges, with the project's initials in the mono face.
   Reads as a deliberate part of the design rather than a broken image. */
.project-thumb {
    display: flex; align-items: center; justify-content: center;
    position: relative; overflow: hidden;
    background:
        linear-gradient(135deg, rgba(var(--accent-rgb), 0.16), rgba(var(--accent-rgb), 0.03)),
        var(--bg-alt);
}
.project-thumb::before {
    content: ''; position: absolute; inset: 0;
    background-image:
        linear-gradient(rgba(var(--accent-rgb), 0.14) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--accent-rgb), 0.14) 1px, transparent 1px);
    background-size: 26px 26px;
    -webkit-mask-image: radial-gradient(ellipse at center, #000 0%, transparent 78%);
    mask-image: radial-gradient(ellipse at center, #000 0%, transparent 78%);
}
.project-mono {
    position: relative; font-family: var(--font-mono); font-size: 1.9rem; font-weight: 800;
    letter-spacing: 0.05em; color: var(--accent1); opacity: 0.9;
}

.project-card-body { padding: 1.5rem; display: flex; flex-direction: column; gap: 0.75rem; flex: 1; }
.project-card-body h3 { margin: 0; font-size: 1.1rem; }
.project-card-body p { margin: 0; color: var(--text-muted); font-size: 0.92rem; flex: 1; }
.project-card-body .pill-row { margin-top: 0.15rem; }
.project-links { display: flex; align-items: center; gap: 1.25rem; margin-top: auto; padding-top: 0.4rem; }
.project-card-body .project-link { font-weight: 700; color: var(--accent3); text-decoration: none; font-size: 0.9rem; }
.project-card-body .project-link:hover { text-decoration: underline; }
/* Scoped the same way as the rule above it, otherwise `.project-card-body
   .project-link` outranks it on specificity and the Source link never goes
   muted. */
.project-card-body .project-link-muted { color: var(--text-muted); font-weight: 600; }
.project-card-body .project-link-muted:hover { color: var(--accent3); }
.projects-empty, .projects-error { text-align: center; color: var(--text-muted); padding: 3rem 1rem; }

/* ---------- Contact ---------- */
.contact-card { max-width: 640px; margin: 0 auto; }
.form-row { margin-bottom: 1.25rem; }
.form-row label { display: block; font-weight: 600; font-size: 0.82rem; margin-bottom: 0.45rem; color: var(--text-muted); }

.form-input, .form-textarea {
    width: 100%; padding: 0.8rem 1rem; border-radius: 0.65rem; border: 1px solid var(--border);
    background: rgba(var(--accent-rgb), 0.03); color: var(--text); font-family: inherit; font-size: 0.94rem;
}
.form-input:focus, .form-textarea:focus {
    outline: none; border-color: var(--accent1); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.18);
}
/* Textareas were inheriting the browser's default line-height and resize
   behaviour, which reads as cramped next to the rest of the form. */
.form-textarea { min-height: 9rem; line-height: 1.65; resize: vertical; }

/* Selects: strip the native control and draw our own chevron, so the closed
   state matches the text inputs beside it. The open popup is drawn by the OS
   and can't be styled — `color-scheme` above is what makes it dark. The
   explicit option colours are a belt-and-braces fallback for browsers that
   ignore color-scheme on popups (older Firefox on Linux, mainly). */
select.form-input {
    appearance: none; -webkit-appearance: none;
    padding-right: 2.6rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b93a7' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.95rem center;
    background-size: 1rem;
    cursor: pointer;
}
select.form-input option {
    background-color: var(--bg-alt);
    color: var(--text);
}
.form-input::placeholder, .form-textarea::placeholder { color: var(--text-muted); opacity: 0.65; }

.form-errors { color: #f87171; font-size: 0.8rem; margin-top: 0.35rem; }
.honeypot-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.flash { padding: 1rem 1.25rem; border-radius: 0.7rem; margin-bottom: 1.5rem; font-weight: 500; }
.flash-success { background: rgba(34, 197, 94, 0.14); color: #4ade80; }
.flash-error { background: rgba(220, 38, 38, 0.12); color: #f87171; }

/* ---------- Footer ---------- */
footer { position: relative; z-index: 1; border-top: 1px solid var(--border); padding: 2.5rem 0; text-align: center; color: var(--text-muted); font-size: 0.9rem; }
.social-row { display: flex; justify-content: center; gap: 1rem; margin-bottom: 1.25rem; }
.social-row a {
    width: 2.5rem; height: 2.5rem; display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px; border: 1px solid var(--border); color: var(--text-muted); text-decoration: none;
    transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.social-row a:hover { color: var(--accent1); border-color: var(--accent1); transform: translateY(-2px); }
.social-row svg { width: 1.1rem; height: 1.1rem; }

/* ---------- Scroll reveal ---------- */
[data-reveal] {
    opacity: 0;
    transform: translateY(22px) scale(0.98);
    transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
    transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-visible { opacity: 1; transform: translateY(0) scale(1); }

@media (prefers-reduced-motion: reduce) {
    [data-reveal] { opacity: 1; transform: none; transition: none; }
    .hero-scroll-cue .cue-dot { animation: none; }
}

/* ---------- Scroll progress bar ---------- */
.scroll-progress {
    position: fixed; top: 0; left: 0; z-index: 60; height: 2.5px; width: 0%;
    background: linear-gradient(90deg, var(--accent1), var(--accent3));
    box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.6);
    transition: width 0.08s linear;
}

/* ---------- Admin / auth chrome (shares the same design language) ---------- */
.admin-shell { position: relative; z-index: 1; min-height: 100vh; display: flex; flex-direction: column; }
/* Full-width bar, container-width contents — so the nav aligns with the page
   content below it instead of hugging the window edges on a wide screen. */
.admin-topbar {
    padding: 1rem 1.5rem; border-bottom: 1px solid var(--border);
    backdrop-filter: blur(14px); background: rgba(5, 7, 13, 0.6);
}
.admin-topbar-inner {
    width: 100%; max-width: 1180px; margin: 0 auto;
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 1rem;
}
:root[data-theme='light'] .admin-topbar { background: rgba(249, 250, 251, 0.8); }
.admin-topbar nav { display: flex; gap: 1.25rem; align-items: center; flex-wrap: wrap; }
.admin-topbar nav a { text-decoration: none; color: var(--text-muted); font-weight: 500; font-size: 0.9rem; }
.admin-topbar nav a:hover { color: var(--text); }
.admin-main { flex: 1; padding: 2.5rem 1.5rem; }
.admin-grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); margin-bottom: 2.5rem; }
.stat-card h3 { margin: 0 0 0.35rem; font-size: 0.78rem; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; font-family: var(--font-mono); }
.stat-card .stat-value { font-size: 2rem; font-weight: 800; color: var(--accent1); }

table.admin-table { width: 100%; border-collapse: collapse; }
table.admin-table th, table.admin-table td { text-align: left; padding: 0.85rem 1rem; border-bottom: 1px solid var(--border); }
table.admin-table th { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); font-family: var(--font-mono); }
.badge {
    display: inline-block; padding: 0.2rem 0.6rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700;
    background: rgba(var(--accent-rgb), 0.15); color: var(--accent1);
}
/* Green rather than the accent blue, so "Replied" reads as a settled state at
   a glance and can't be mistaken for the blue "New" badge beside it. */
.badge-replied { background: rgba(34, 197, 94, 0.16); color: #4ade80; }
:root[data-theme='light'] .badge-replied { background: rgba(22, 163, 74, 0.12); color: #15803d; }

/* ---------- Login ---------- */
/* The card was horizontally centred but pinned near the top, leaving a large
   dead area below it on a desktop screen. Centring it in the viewport (minus
   the 4.5rem navbar) puts it where the eye already is. Gated on height so a
   short laptop or a phone in landscape doesn't end up scrolling to reach it. */
/* border-top: none overrides the shared `section` rule — on the login page
   that line sits immediately under the navbar and reads as a double border. */
.auth-section { padding: 3rem 0; border-top: none; }
.auth-card { max-width: 420px; width: 100%; margin: 0 auto; }
.auth-card h1 { text-align: center; margin-bottom: 1.75rem; }

@media (min-height: 620px) {
    .auth-section {
        display: flex; align-items: center; justify-content: center;
        min-height: calc(100vh - 4.5rem);
        min-height: calc(100svh - 4.5rem);
    }
}

.actions-row { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.5rem; }

/* Stacked cards inside an admin page had no gap between them, so separate
   panels read as one block. Applies wherever cards follow each other. */
.admin-main .card + .card { margin-top: 1.75rem; }
.admin-main h1 { margin: 0 0 1.5rem; }
.admin-main > .container > p:first-of-type { margin-bottom: 1.5rem; }

/* ---------- Admin: conversation thread ---------- */
.thread-head { margin-bottom: 1.75rem; }
.thread-head h1 { margin-bottom: 0.4rem; }
.thread-head p { margin: 0; color: var(--text-muted); font-size: 0.9rem; }

.thread { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 1.75rem; }

.bubble {
    border: 1px solid var(--border); border-radius: 1rem; padding: 1.1rem 1.35rem;
    background: var(--surface); max-width: 88%;
}
.bubble p { margin: 0; white-space: pre-wrap; line-height: 1.7; }

/* Received sits left and neutral; sent sits right and tinted, so the
   direction of the conversation is readable without reading any names. */
.bubble-in { align-self: flex-start; border-bottom-left-radius: 0.35rem; }
.bubble-out {
    align-self: flex-end; border-bottom-right-radius: 0.35rem;
    background: rgba(var(--accent-rgb), 0.1); border-color: rgba(var(--accent-rgb), 0.3);
}

.bubble-meta {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.6rem;
    margin-bottom: 0.6rem; font-size: 0.78rem; color: var(--text-muted);
}
.bubble-meta strong { color: var(--text); font-size: 0.85rem; }
.bubble-tag {
    font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.06em;
    text-transform: uppercase; padding: 0.12rem 0.45rem; border-radius: 0.35rem;
    border: 1px solid var(--border);
}

.badge-inbound { background: rgba(var(--accent-rgb), 0.18); color: var(--accent3); }
:root[data-theme='light'] .badge-inbound { background: rgba(var(--accent-rgb), 0.12); color: var(--accent3); }

.danger-zone { border-color: rgba(220, 38, 38, 0.35); }

/* ---------- Admin: client work pipeline ---------- */
.page-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap; margin-bottom: 1.75rem;
}
.page-head h1 { margin: 0; }

.stat-card { display: flex; flex-direction: column; gap: 0.35rem; }
.stat-card h3 { margin: 0; font-size: 0.8rem; font-weight: 600; color: var(--text-muted); }
.stat-label {
    font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--text-muted);
}
.stat-value { font-size: 1.5rem; font-weight: 800; line-height: 1.25; }
.stat-muted { color: var(--text-muted); font-weight: 600; font-size: 1.1rem; }
.stat-note { font-size: 0.78rem; color: var(--text-muted); }

.pipeline-stage { margin-bottom: 2.25rem; }
.pipeline-heading { display: flex; align-items: center; gap: 0.75rem; font-size: 1rem; margin: 0 0 1rem; }
.pipeline-count { font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-muted); }
.pipeline-empty { color: var(--text-muted); font-size: 0.9rem; margin: 0; }

.stage-badge {
    display: inline-block; padding: 0.25rem 0.7rem; border-radius: 999px;
    font-size: 0.75rem; font-weight: 700; border: 1px solid var(--border);
}
.stage-neutral { color: var(--text-muted); }
.stage-active { background: rgba(var(--accent-rgb), 0.15); color: var(--accent1); border-color: rgba(var(--accent-rgb), 0.35); }
.stage-done { background: rgba(34, 197, 94, 0.16); color: #4ade80; border-color: rgba(34, 197, 94, 0.3); }
.stage-dead { color: var(--text-muted); opacity: 0.7; text-decoration: line-through; }
:root[data-theme='light'] .stage-done { background: rgba(22, 163, 74, 0.12); color: #15803d; }

/* Each stage move is its own form (a POST with a CSRF token, not a link —
   a GET that changes state gets fired by every crawler and prefetcher). */
.stage-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.stage-actions form { display: inline; }
.stage-move {
    border: 1px solid var(--border); background: transparent; color: var(--text-muted);
    border-radius: 0.4rem; padding: 0.25rem 0.6rem; font-size: 0.75rem; font-weight: 600;
    cursor: pointer; font-family: inherit; transition: color 0.15s ease, border-color 0.15s ease;
}
.stage-move:hover { color: var(--accent1); border-color: var(--accent1); }

/* Payment-state badges. Tones, not a rainbow: warn for owed, part for
   partially settled, done for clear, alert for a figure that needs a look. */
.badge-warn { background: rgba(245, 158, 11, 0.16); color: #fbbf24; }
.badge-part { background: rgba(56, 189, 248, 0.16); color: var(--accent3); }
.badge-done { background: rgba(34, 197, 94, 0.16); color: #4ade80; }
.badge-alert { background: rgba(220, 38, 38, 0.16); color: #f87171; }
.badge-neutral { background: var(--surface); color: var(--text-muted); }
:root[data-theme='light'] .badge-warn { background: rgba(217, 119, 6, 0.12); color: #b45309; }
:root[data-theme='light'] .badge-done { background: rgba(22, 163, 74, 0.12); color: #15803d; }
.badge-button { border: none; cursor: pointer; font-family: inherit; }

/* ---------- Data table: toolbar, sorting, payment bars ---------- */
.table-toolbar {
    display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center;
    margin-bottom: 1.25rem;
}
.search-field { position: relative; flex: 1 1 16rem; }
.search-field svg {
    position: absolute; left: 0.9rem; top: 50%; transform: translateY(-50%);
    width: 1rem; height: 1rem; color: var(--text-muted); pointer-events: none;
}
.search-field .form-input { padding-left: 2.5rem; }
.table-filter { flex: 0 1 12rem; }

/* Wide tables scroll inside their own box rather than pushing the page
   sideways — horizontal scroll on the body is never what anyone wants. */
.table-scroll { overflow-x: auto; }
.table-scroll .admin-table { min-width: 48rem; }

.data-table th.is-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table th.is-sortable:hover { color: var(--text); }
.data-table th.is-sortable::after { content: '↕'; opacity: 0.35; margin-left: 0.35rem; font-size: 0.7rem; }
.data-table th.is-sorted-asc::after { content: '↑'; opacity: 1; color: var(--accent1); }
.data-table th.is-sorted-desc::after { content: '↓'; opacity: 1; color: var(--accent1); }

.table-primary { font-weight: 600; text-decoration: none; color: var(--text); }
.table-primary:hover { color: var(--accent1); }
.table-empty, .table-count { color: var(--text-muted); font-size: 0.85rem; margin: 1rem 0 0; }
.table-notice {
    margin: 0 0 1rem; padding: 0.6rem 0.9rem; border-radius: 0.6rem;
    font-size: 0.85rem; color: var(--text-muted);
    background: rgba(var(--accent-rgb), 0.08); border: 1px solid rgba(var(--accent-rgb), 0.25);
}
.table-notice a { color: var(--accent3); font-weight: 600; }

/* Stat tiles are links into the list they count. The arrow appears on hover
   rather than sitting there permanently — it's an affordance, not decoration. */
.stat-link { text-decoration: none; color: inherit; display: flex; position: relative; }
.stat-link:hover { transform: translateY(-3px); border-color: rgba(var(--accent-rgb), 0.45); }
.stat-link::before {
    content: '→'; position: absolute; top: 1rem; right: 1.2rem;
    color: var(--accent1); opacity: 0; transform: translateX(-4px);
    transition: opacity 0.2s ease, transform 0.2s ease;
}
.stat-link:hover::before { opacity: 1; transform: translateX(0); }
.stat-link:focus-visible { outline: 2px solid var(--accent1); outline-offset: 3px; }

/* A thin progress track under the paid figure — the fastest way to read
   "deposit taken" versus "nearly settled" without doing the arithmetic. */
.pay-bar {
    display: block; width: 100%; max-width: 7rem; height: 4px; margin-top: 0.4rem;
    border-radius: 999px; background: var(--surface-strong); overflow: hidden;
}
.pay-bar-lg { max-width: none; height: 8px; margin-top: 1.25rem; }
.pay-bar-fill {
    display: block; height: 100%; border-radius: 999px;
    background: linear-gradient(90deg, var(--accent1), var(--accent3));
}

.money-summary {
    display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}
.money-summary > div { display: flex; flex-direction: column; gap: 0.3rem; align-items: flex-start; }

.text-muted { color: var(--text-muted); }
.text-overdue { color: #f87171; font-weight: 600; }
.field-help { display: block; margin-top: 0.4rem; font-size: 0.8rem; color: var(--text-muted); }

.form-split { display: grid; gap: 0 1.25rem; }
@media (min-width: 640px) { .form-split { grid-template-columns: 1fr 1fr; } }

/* ---------- Date picker ---------- */
.datepicker { position: relative; }
.datepicker .form-input { padding-right: 2.8rem; }

.datepicker-trigger {
    position: absolute; top: 50%; right: 0.55rem; transform: translateY(-50%);
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; border-radius: 0.45rem;
    border: none; background: transparent; color: var(--text-muted); cursor: pointer;
    transition: color 0.15s ease, background-color 0.15s ease;
}
.datepicker-trigger:hover { color: var(--accent1); background: rgba(var(--accent-rgb), 0.12); }
.datepicker-trigger svg { width: 1.05rem; height: 1.05rem; }

.datepicker-panel {
    position: absolute; z-index: 40; top: calc(100% + 0.5rem); left: 0;
    width: min(20rem, calc(100vw - 3rem));
    padding: 0.9rem; border-radius: 0.9rem;
    background: var(--bg-alt); border: 1px solid var(--border);
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.45);
}
:root[data-theme='light'] .datepicker-panel { box-shadow: 0 18px 45px rgba(15, 23, 42, 0.14); }

.datepicker-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.5rem; margin-bottom: 0.75rem;
}
.datepicker-selects { display: flex; gap: 0.4rem; flex: 1; justify-content: center; }
.datepicker-select {
    appearance: none; -webkit-appearance: none;
    border: 1px solid var(--border); border-radius: 0.5rem;
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 0.85rem; font-weight: 600;
    padding: 0.3rem 1.6rem 0.3rem 0.6rem; cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b93a7' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 0.45rem center; background-size: 0.75rem;
}
.datepicker-select:focus { outline: none; border-color: var(--accent1); }
.datepicker-select option { background-color: var(--bg-alt); color: var(--text); }
.datepicker-nav {
    width: 1.9rem; height: 1.9rem; border-radius: 0.5rem; cursor: pointer;
    border: 1px solid var(--border); background: transparent;
    color: var(--text-muted); font-size: 1.1rem; line-height: 1;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.datepicker-nav:hover { color: var(--accent1); border-color: var(--accent1); }

.datepicker-grid {
    display: grid; grid-template-columns: repeat(7, 1fr); gap: 0.15rem;
}
.datepicker-weekday {
    text-align: center; font-family: var(--font-mono); font-size: 0.65rem;
    letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted);
    padding-bottom: 0.35rem;
}
.datepicker-day {
    aspect-ratio: 1; border: none; background: transparent; cursor: pointer;
    border-radius: 0.5rem; color: var(--text); font-family: inherit; font-size: 0.85rem;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.datepicker-day:hover { background: rgba(var(--accent-rgb), 0.16); color: var(--accent1); }
/* Today is outlined, the selected day is filled — so both can show at once
   without competing. */
.datepicker-day.is-today { box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.55); }
.datepicker-day.is-selected {
    background: linear-gradient(135deg, var(--accent1), var(--accent2));
    color: var(--btn-primary-text); font-weight: 700;
}

.datepicker-foot {
    display: flex; gap: 0.5rem; margin-top: 0.75rem;
    padding-top: 0.75rem; border-top: 1px solid var(--border);
}
.datepicker-action {
    flex: 1; padding: 0.4rem 0.6rem; border-radius: 0.5rem; cursor: pointer;
    border: 1px solid var(--border); background: transparent;
    color: var(--text-muted); font-family: inherit; font-size: 0.8rem; font-weight: 600;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.datepicker-action:hover { color: var(--accent1); border-color: var(--accent1); }
.reply-record .reply-meta {
    font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500;
    color: var(--text-muted); margin-left: 0.6rem; text-transform: none; letter-spacing: 0;
}
.reply-hint { color: var(--text-muted); font-size: 0.88rem; margin: 0 0 1.25rem; }
