/********** Template CSS **********/
:root {
    --primary: #6244C5;
    --secondary: #FFC448;
    --light: #FAFAFB;
    --dark: #12141D;

    /* --- Spacing scale: keeps new/edited components on one consistent rhythm --- */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 2.5rem;
    --space-8: 3rem;
    --space-9: 4rem;
    --space-10: 5rem;
    --space-11: 6rem;
    --space-12: 8rem;

    /* --- Shared radii / shadows / easing for a consistent "premium" feel --- */
    --radius-sm: 10px;
    --radius-md: 16px;
    --radius-lg: 24px;
    --shadow-sm: 0 4px 16px rgba(18, 20, 29, 0.06);
    --shadow-md: 0 12px 32px rgba(18, 20, 29, 0.10);
    --shadow-lg: 0 20px 60px rgba(18, 20, 29, 0.15);
    --ease: cubic-bezier(0.4, 0, 0.2, 1);

    /* --- Fluid type scale: replaces fixed Bootstrap display sizes so headings --- */
    /* --- never overflow on 320px phones nor look tiny on 4K/ultrawide --- */
    --fs-display-hero: clamp(2.25rem, 1.35rem + 4vw, 4.5rem);
    --fs-display-section: clamp(1.75rem, 1.35rem + 1.8vw, 2.75rem);
    --fs-years-stat: clamp(4.5rem, 3rem + 6vw, 10rem);

    /* --- Theme-aware tokens — LIGHT values below match the current design --- */
    /* --- exactly (same hex/rgba as before), so light mode is unchanged.    --- */
    --bg-page: #FFFFFF;
    --bg-section-alt: #FAFAFB;
    --bg-elevated: #FFFFFF;
    --bg-surface: #FFFFFF;
    --bg-dark-section: var(--dark);
    --text-heading: var(--dark);
    --text-body: #3C3C47;
    --text-muted: rgba(18, 20, 29, 0.6);
    --border-subtle: rgba(18, 20, 29, 0.08);
    --chip-bg: rgba(18, 20, 29, 0.06);
    --chip-bg-strong: rgba(18, 20, 29, 0.12);
    --track-bg: rgba(18, 20, 29, 0.08);
    --glass-bg: rgba(255, 255, 255, 0.75);
    --glass-bg-soft: rgba(255, 255, 255, 0.6);
    --glass-border: rgba(255, 255, 255, 0.45);
    /* Text-on-dark accent: identical to --primary in light mode. In dark
       mode, --primary itself is untouched (buttons/badges/thumb stay the
       exact same brand purple) but the raw brand purple only measures
       ~2.4:1 against the dark backgrounds when used as *text* — well under
       WCAG AA's 4.5:1. --text-accent is a lightened tint used only for
       primary-coloured text so it stays legible; every purple background
       usage keeps referencing --primary unchanged. */
    --text-accent: var(--primary);
    --theme-transition: 250ms ease;
}

/* --- DARK theme — polished, not a naive invert. Backgrounds/cards/text per --- */
/* --- spec; brand purple & yellow accents are untouched (same --primary/   --- */
/* --- --secondary everywhere), and the hero image/yellow splash are untouched. --- */
:root[data-theme="dark"] {
    --bg-page: #0F1117;
    --bg-section-alt: #151922;
    --bg-elevated: #151922;
    --bg-surface: #1C2230;
    --bg-dark-section: #0B0D12;
    --text-heading: #FFFFFF;
    --text-body: #D0D6E0;
    --text-muted: #9AA4B2;
    --border-subtle: rgba(255, 255, 255, 0.08);
    --chip-bg: rgba(255, 255, 255, 0.06);
    --chip-bg-strong: rgba(255, 255, 255, 0.12);
    --track-bg: rgba(255, 255, 255, 0.12);
    --glass-bg: rgba(28, 34, 48, 0.75);
    --glass-bg-soft: rgba(28, 34, 48, 0.6);
    --glass-border: rgba(255, 255, 255, 0.1);
    --text-accent: #9985D9;
    --shadow-sm: 0 4px 16px rgba(0, 0, 0, 0.35);
    --shadow-md: 0 12px 32px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.55);
}

/* Smooth 200-300ms colour transition on theme switch, no page refresh */
html,
body {
    overflow-x: hidden;
}

body {
    margin: 0;
    background-color: var(--bg-page);
    transition: background-color var(--theme-transition), color var(--theme-transition);
}

:root[data-theme="dark"] body {
    color: #D0D6E0;
}

/* Bootstrap utility classes ship their own colours with !important, so the
   dark overrides need the same weight — matched by a more specific selector
   (attribute + class) rather than fighting specificity another way. */
:root[data-theme="dark"] .bg-white {
    background-color: var(--bg-elevated) !important;
}

:root[data-theme="dark"] .bg-light {
    background-color: var(--bg-section-alt) !important;
}

:root[data-theme="dark"] .bg-dark {
    background-color: var(--bg-dark-section) !important;
}

:root[data-theme="dark"] .text-dark {
    color: var(--text-heading) !important;
}

/* Bootstrap's .text-primary ships as a fixed #6244C5 with !important — used
   directly in the HTML (navbar brand, hero eyebrow, About checkmarks/stats,
   timeline company names). Raw brand purple only measures ~2.4-2.8:1 against
   the dark theme's backgrounds (WCAG AA needs 4.5:1 for text), so it needs
   the same lightened --text-accent already used for our own components.
   --primary itself is untouched, so every purple *background* (buttons,
   badges, thumb) stays the exact same brand purple in both themes. */
:root[data-theme="dark"] .text-primary {
    color: var(--text-accent) !important;
}

:root[data-theme="dark"] .border-primary {
    border-color: var(--text-accent) !important;
}

:root[data-theme="dark"] .text-muted {
    color: var(--text-muted) !important;
}

/* Bootstrap colours every h1-h6/.h1-.h6 with a fixed #12141D by default —
   without this override, every heading on the page (hero name, section
   titles, card titles) would stay near-black and unreadable on dark
   backgrounds. text-primary/text-white headings keep their own colour since
   those utility classes are more specific and come after in the cascade. */
:root[data-theme="dark"] h1,
:root[data-theme="dark"] h2,
:root[data-theme="dark"] h3,
:root[data-theme="dark"] h4,
:root[data-theme="dark"] h5,
:root[data-theme="dark"] h6,
:root[data-theme="dark"] .h1,
:root[data-theme="dark"] .h2,
:root[data-theme="dark"] .h3,
:root[data-theme="dark"] .h4,
:root[data-theme="dark"] .h5,
:root[data-theme="dark"] .h6 {
    color: var(--text-heading);
}

:root[data-theme="dark"] .form-control {
    background-color: var(--bg-surface);
    color: var(--text-heading);
    border-color: var(--border-subtle);
}

:root[data-theme="dark"] .form-control:focus {
    background-color: var(--bg-surface);
    color: var(--text-heading);
    box-shadow: 0 0 0 0.25rem rgba(98, 68, 197, 0.35);
}

:root[data-theme="dark"] .form-control::placeholder {
    color: var(--text-muted);
}

:root[data-theme="dark"] #skill .nav-pills {
    border-color: var(--primary) !important;
}

/* Respect users who've asked for less motion */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* Visible keyboard focus everywhere (nav, buttons, cards, form fields, icon links) */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
.skill-card:focus-visible,
.timeline-card:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--primary);
    outline-offset: 3px;
    border-radius: var(--radius-sm);
}

/* Ultrawide: keep the nav's inner content from sprawling edge-to-edge on 1920px+ */
@media (min-width: 1400px) {
    .navbar-collapse {
        max-width: 1320px;
        margin: 0 auto;
    }
}

/* Centers the "Shuraj03" brand mark in the desktop navbar. justify-content-between
   only centers the middle item when both flanking groups are equal width — the
   theme switcher living inside the right-hand nav group makes it wider than the
   left, which is what was pulling the logo visually off-center. Giving both
   groups equal flex-grow forces them to the same width regardless of their
   content, while justify-content on each keeps their links hugging the brand
   exactly as before — so spacing next to the logo is unchanged. */
@media (min-width: 992px) {
    #navbarCollapse .navbar-nav {
        flex: 1 1 0;
    }

    #navbarCollapse .navbar-nav.ms-auto {
        justify-content: flex-end;
    }

    #navbarCollapse .navbar-nav.me-auto {
        justify-content: flex-start;
    }
}

/* Fluid headings — same visual weight as the original template, but scale continuously */
.display-3 {
    font-size: var(--fs-display-hero);
    line-height: 1.1;
}

.display-5 {
    font-size: var(--fs-display-section);
    line-height: 1.2;
}

.back-to-top {
    position: fixed;
    display: none;
    right: 45px;
    bottom: 45px;
    z-index: 99;
}

.my-6 {
    margin-top: clamp(3rem, 2rem + 4vw, 6rem);
    margin-bottom: clamp(3rem, 2rem + 4vw, 6rem);
}

.py-6 {
    padding-top: clamp(3rem, 2rem + 4vw, 6rem);
    padding-bottom: clamp(3rem, 2rem + 4vw, 6rem);
}


/*** Spinner ***/
#spinner {
    opacity: 0;
    visibility: hidden;
    transition: opacity .5s ease-out, visibility 0s linear .5s;
    z-index: 99999;
}

#spinner.show {
    transition: opacity .5s ease-out, visibility 0s linear 0s;
    visibility: visible;
    opacity: 1;
    /* Pure-CSS failsafe: normally main.js removes "show" within milliseconds,
       so this never finishes playing. But if jQuery/main.js fails to load or
       errors (blocked CDN, offline, etc.), this still forces the spinner
       away after 4s regardless of JS — the page is never permanently
       blocked by a fixed, full-viewport overlay with no JS dependency. */
    animation: spinner-failsafe-hide 0s 4s forwards;
}

@keyframes spinner-failsafe-hide {
    to {
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
    }
}


/*** Button ***/
.btn {
    font-weight: 500;
    transition: .5s;
}

.btn.btn-primary,
.btn.btn-secondary {
    color: #FFFFFF;
}

.btn-square {
    width: 44px;
    height: 44px;
}

.btn-sm-square {
    width: 32px;
    height: 32px;
}

.btn-lg-square {
    width: 48px;
    height: 48px;
}

.btn-square,
.btn-sm-square,
.btn-lg-square {
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: normal;
}


/*** Navbar ***/
.navbar.fixed-top {
    display: none;
    transition: .5s;
}

.navbar-brand-text {
    display: inline-block;
    font-size: 1.75rem;
    line-height: 1.2;
}

.navbar .navbar-nav .nav-link {
    position: relative;
    padding: 20px 15px;
    color: var(--text-heading);
    font-size: 18px;
    font-weight: 600;
    transition: color .3s var(--ease);
}

.navbar .navbar-nav .nav-link:hover,
.navbar .navbar-nav .nav-link.active {
    color: var(--text-accent);
}

/* Subtle animated underline instead of an abrupt color-only switch */
.navbar .navbar-nav .nav-link::after {
    content: "";
    position: absolute;
    left: 15px;
    right: 15px;
    bottom: 12px;
    height: 2px;
    background: var(--primary);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .3s var(--ease);
}

.navbar .navbar-nav .nav-link:hover::after,
.navbar .navbar-nav .nav-link.active::after {
    transform: scaleX(1);
}

.navbar-toggler {
    min-width: 44px;
    min-height: 44px;
}

/* Bootstrap bakes the hamburger icon's colour into an SVG data-URI (dark
   grey), which would be nearly invisible on a dark navbar — flip it light */
:root[data-theme="dark"] .navbar-toggler-icon {
    filter: invert(1);
}

@media (max-width: 991.98px) {
    .navbar .navbar-nav .nav-link {
        padding: 12px 4px;
        min-height: 44px;
        display: flex;
        align-items: center;
    }

    .navbar .navbar-nav .nav-link::after {
        left: 4px;
        right: 4px;
        bottom: 6px;
    }
}

/*** Theme Switcher — premium segmented pill (Light / Dark / System) ***/
.theme-switcher {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    background: var(--chip-bg);
    border-radius: 999px;
    padding: 3px;
    gap: 2px;
    margin-left: 12px;
    transition: background-color var(--theme-transition);
}

.theme-option {
    position: relative;
    z-index: 1;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    border-radius: 50%;
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    transition: color .25s var(--ease);
}

.theme-option:hover {
    color: var(--text-heading);
}

.theme-option.active {
    color: #FFFFFF;
}

.theme-switcher-thumb {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--primary);
    box-shadow: var(--shadow-sm);
    transition: transform .3s var(--ease);
    z-index: 0;
}

.theme-switcher[data-active="dark"] .theme-switcher-thumb {
    transform: translateX(36px);
}

.theme-switcher[data-active="system"] .theme-switcher-thumb {
    transform: translateX(72px);
}

@media (max-width: 991.98px) {
    .theme-switcher {
        /* .navbar-nav is a column-direction flex container below lg, so
           margin:auto alone won't center this along the (now vertical)
           main axis — align-self does the centering here instead */
        align-self: center;
        margin: var(--space-4) 0 0;
    }
}


/*** Header ***/
#home {
    margin-bottom: 6rem;
    /* Hero always fills exactly one screen — min-height (not height) so it
       still grows rather than clipping on very short/landscape viewports */
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    background: url(../img/bg-header.png) left top no-repeat;
    background-size: clamp(220px, 22vw, 420px) auto;
}

#home > .container {
    width: 100%;
}

.hero-eyebrow {
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.contact-info-link:hover,
.contact-info-link:focus-visible {
    color: var(--text-accent);
}

.hero-actions {
    gap: var(--space-4) var(--space-5);
}

.hero-btn {
    margin: 0;
}

/* Below ~420px "✨ What Makes Me Different?" no longer fits comfortably
   alongside another button on one row — stack both full-width instead of
   letting either get squeezed or overflow */
@media (max-width: 420px) {
    .hero-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .hero-btn {
        width: 100%;
        text-align: center;
    }
}

/* Hero portrait: fluid, but always balanced — never postage-stamp small on
   phones, never overpowering the copy on desktop or ultrawide.
   ~20% larger than before to close up the empty space beside it on desktop —
   width/max-width only (no cropping), so face/hands/background stay intact. */
.hero-portrait {
    width: clamp(260px, 68vw, 560px);
    height: auto;
}

@media (min-width: 992px) {
    .hero-portrait {
        width: 100%;
        max-width: 624px;
    }
}

.typed-cursor {
    font-size: clamp(20px, 2.2vw, 30px);
    color: var(--text-heading);
}

/*** What Makes Me Different - Interactive Glassmorphism Card ***/

/* Toggle button (outlined, matches Download CV) gets a subtle lift on hover */
.wmd-toggle-btn {
    position: relative;
}

.wmd-toggle-btn:hover {
    transform: translateY(-2px);
}

.wmd-toggle-btn.active {
    background: var(--primary);
    color: #FFFFFF;
}

/* Centered modal overlay — fixed to the viewport (not the hero column), so
   opening it can never grow the page or push content down. The overlay
   itself doubles as the dark, blurred backdrop; clicking it (but not its
   .wmd-card child) closes the modal. */
.wmd-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1050;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-5);
    background: rgba(18, 20, 29, 0.55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 350ms var(--ease), visibility 0s linear 350ms;
}

.wmd-modal-overlay.open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 350ms var(--ease), visibility 0s linear 0s;
}

/* Locks background scroll while the modal is open */
body.wmd-no-scroll {
    overflow: hidden;
}

/* The glass card itself */
.wmd-card {
    position: relative;
    width: 100%;
    max-width: 560px;
    max-height: min(85vh, 640px);
    overflow-y: auto;
    background: var(--glass-bg);
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    border: 1px solid var(--glass-border);
    border-radius: 24px;
    box-shadow: 0 20px 60px rgba(18, 20, 29, 0.25), 0 2px 8px rgba(18, 20, 29, 0.1);
    padding: 32px 32px 24px;
    transform: scale(0.92) translateY(10px);
    opacity: 0;
    transition: transform 350ms var(--ease), opacity 300ms ease, box-shadow 300ms ease, background-color var(--theme-transition), border-color var(--theme-transition);
}

.wmd-modal-overlay.open .wmd-card {
    transform: scale(1) translateY(0);
    opacity: 1;
}

.wmd-close-btn {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: var(--chip-bg);
    color: var(--text-heading);
    font-size: 16px;
    cursor: pointer;
    transition: background 200ms ease, color 200ms ease, transform 200ms ease;
}

.wmd-close-btn:hover {
    background: var(--chip-bg-strong);
    transform: rotate(90deg);
}

/* Slides - only the active one is visible, fading/sliding in on change */
.wmd-slide {
    display: none;
}

.wmd-slide.active {
    display: block;
    animation: wmdFadeSlideIn 400ms ease forwards;
}

@keyframes wmdFadeSlideIn {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.wmd-slide-title {
    font-size: 22px;
    font-weight: 800;
    color: var(--dark);
    margin-bottom: 14px;
    letter-spacing: -0.02em;
}

.wmd-slide-body p {
    font-size: 15.5px;
    line-height: 1.7;
    color: var(--text-body);
    margin-bottom: 12px;
}

/* Replaces the emoji that used to lead each "How I Think" line */
.wmd-think-icon {
    color: var(--text-accent);
    width: 1.1em;
    margin-right: 8px;
    text-align: center;
}

.wmd-list {
    list-style: none;
    padding: 0;
    margin: 0 0 16px;
}

.wmd-list li {
    position: relative;
    padding-left: 22px;
    margin-bottom: 8px;
    font-size: 15.5px;
    color: var(--text-body);
}

.wmd-list li:before {
    content: "→";
    position: absolute;
    left: 0;
    color: var(--text-accent);
    font-weight: 700;
}

.wmd-emphasis {
    font-weight: 700;
    color: var(--text-heading);
}

.wmd-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 16px;
}

.wmd-tag {
    font-size: 12.5px;
    font-weight: 600;
    padding: 6px 14px;
    border-radius: 999px;
    background: rgba(98, 68, 197, 0.1);
    color: var(--text-accent);
    transition: transform 200ms ease, background 200ms ease;
}

.wmd-tag:hover {
    background: rgba(98, 68, 197, 0.18);
    transform: translateY(-2px) scale(1.03);
}

.wmd-quote {
    margin: 16px 0 4px;
    padding-left: 16px;
    border-left: 3px solid var(--secondary);
    font-style: italic;
    font-size: 14.5px;
    color: var(--text-heading);
}

/* Footer navigation - Previous / dots / Next-Close */
.wmd-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--border-subtle);
}

.wmd-nav-btn {
    background: none;
    border: none;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-accent);
    padding: 12px 8px;
    min-height: 44px;
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: transform 200ms ease, opacity 200ms ease, color 200ms ease, background 200ms ease;
}

.wmd-nav-btn:hover:not(:disabled) {
    background: rgba(98, 68, 197, 0.08);
}

.wmd-nav-btn.wmd-next:hover {
    transform: translateX(2px);
}

.wmd-nav-btn.wmd-prev:hover {
    transform: translateX(-2px);
}

.wmd-nav-btn:disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}

.wmd-nav-btn.wmd-close {
    color: var(--text-heading);
}

.wmd-dots {
    display: flex;
    gap: 6px;
}

.wmd-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--chip-bg-strong);
    transition: all 300ms ease;
}

.wmd-dot.active {
    width: 18px;
    border-radius: 3px;
    background: var(--primary);
}

/* Tablet: slightly narrower card */
@media (max-width: 991.98px) {
    .wmd-card {
        max-width: 480px;
    }
}

/* Mobile: full-width modal card, tighter backdrop padding so the card gets
   as much of the small viewport as possible */
@media (max-width: 575.98px) {
    .wmd-modal-overlay {
        padding: var(--space-3);
    }

    .wmd-card {
        max-width: 100%;
        max-height: min(88vh, 640px);
        padding: 24px 20px 20px;
        border-radius: 18px;
    }

    .wmd-slide-title {
        font-size: 20px;
    }
}


/*** About ***/
#about .years .display-1 {
    font-size: var(--fs-years-stat);
    line-height: 1;
}

#about .years h5 {
    --years-tracking: clamp(6px, 2.2vw, 30px);
    letter-spacing: var(--years-tracking);
    margin-right: calc(-1 * var(--years-tracking));
}

/* Brand-colored panels used in place of unrelated stock photography */
.about-visual {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    text-align: center;
    color: #FFFFFF;
    box-shadow: var(--shadow-md);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}

.about-visual:hover {
    transform: translateY(-6px);
    box-shadow: var(--shadow-lg);
}

.about-visual i {
    font-size: clamp(2rem, 4vw, 2.75rem);
}

.about-visual span {
    font-weight: 700;
    font-size: 0.95rem;
    letter-spacing: 0.01em;
}

.about-visual-primary {
    background: linear-gradient(145deg, var(--primary), #4a339c);
}

.about-visual-secondary {
    background: linear-gradient(145deg, #efb52e, var(--secondary));
    color: var(--dark);
}


/*** Skills ***/
/* One full-width row per category rather than a multi-column grid — with 12
   categories and up to 21 skills in one of them, packing categories side by
   side left each one either far too narrow or absurdly tall. A single column
   of short horizontal-scroll strips (below) keeps every category's visible
   height the same regardless of how many skills are in it. */
.skills-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-5);
    margin-top: var(--space-2);
}

.skill-category-title {
    font-size: 0.9rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-accent);
    margin-bottom: var(--space-3);
    padding-bottom: var(--space-2);
    border-bottom: 2px solid rgba(98, 68, 197, 0.12);
}

/* Responsive wrapping grid — a fixed column count per breakpoint (2 on
   mobile, 3 on tablet, 4 then 5 on wider desktops) so cards are always equal
   width and wrap onto new rows on their own. No overflow, no scrollbar:
   a category with many skills just gets taller, never wider than the page. */
.skill-cards {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3);
    align-items: stretch;
}

@media (min-width: 576px) {
    .skill-cards {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 992px) {
    .skill-cards {
        grid-template-columns: repeat(4, 1fr);
    }
}

@media (min-width: 1440px) {
    .skill-cards {
        grid-template-columns: repeat(5, 1fr);
    }
}

.skill-card {
    height: 100%;
    background: var(--bg-surface);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    box-shadow: var(--shadow-sm);
    transition: transform .3s var(--ease), box-shadow .3s var(--ease), background-color var(--theme-transition);
}

.skill-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
}

.skill-card-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.skill-icon {
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    background: rgba(98, 68, 197, 0.1);
    color: var(--text-accent);
    font-size: 1rem;
    transition: background .3s var(--ease), color .3s var(--ease);
}

.skill-card:hover .skill-icon {
    background: var(--primary);
    color: #FFFFFF;
}

.skill-name {
    font-weight: 600;
    color: var(--text-heading);
}

.skill-level {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.skill-level-label {
    flex-shrink: 0;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--chip-bg);
    color: var(--text-muted);
    transition: background-color var(--theme-transition), color var(--theme-transition);
}

.skill-level[data-level="4"] .skill-level-label {
    background: var(--primary);
    color: #FFFFFF;
}

.skill-level[data-level="3"] .skill-level-label {
    background: rgba(98, 68, 197, 0.15);
    color: var(--text-accent);
}

.skill-segments {
    flex: 1;
    display: flex;
    gap: 4px;
}

.segment {
    position: relative;
    flex: 1;
    height: 8px;
    border-radius: 999px;
    overflow: hidden;
    background: var(--track-bg);
    transition: background-color var(--theme-transition);
}

.segment-fill {
    position: absolute;
    inset: 0;
    display: block;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--primary), #8467d9);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .6s var(--ease);
}

.skill-card.in-view .segment:nth-child(1) .segment-fill { transition-delay: .05s; }
.skill-card.in-view .segment:nth-child(2) .segment-fill { transition-delay: .15s; }
.skill-card.in-view .segment:nth-child(3) .segment-fill { transition-delay: .25s; }
.skill-card.in-view .segment:nth-child(4) .segment-fill { transition-delay: .35s; }

.skill-card.in-view .segment-fill {
    transform: scaleX(1);
}

/*** Experience / Education Timeline ***/
.timeline-block {
    margin-top: var(--space-11);
}

.timeline {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}

.timeline::before {
    content: "";
    position: absolute;
    left: 11px;
    top: 6px;
    bottom: 6px;
    width: 2px;
    background: rgba(98, 68, 197, 0.18);
}

.timeline-item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--space-5);
    padding-bottom: var(--space-7);
}

.timeline-item:last-child {
    padding-bottom: 0;
}

.timeline-node {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    margin-top: 4px;
    border-radius: 50%;
    background: var(--bg-surface);
    border: 3px solid var(--primary);
    position: relative;
    z-index: 1;
    transition: background-color var(--theme-transition);
}

.timeline-node::after {
    content: "";
    position: absolute;
    inset: 5px;
    border-radius: 50%;
    background: var(--primary);
}

.timeline-card {
    flex: 1;
    min-width: 0;
    background: var(--bg-surface);
    border-radius: var(--radius-md);
    padding: var(--space-5);
    box-shadow: var(--shadow-sm);
    transition: transform .3s var(--ease), box-shadow .3s var(--ease), background-color var(--theme-transition);
}

.timeline-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
}

.timeline-date {
    display: inline-block;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-accent);
    background: rgba(98, 68, 197, 0.1);
    padding: 4px 12px;
    border-radius: 999px;
    margin-bottom: var(--space-3);
}

.timeline-points {
    margin: var(--space-3) 0 0;
    padding-left: 1.1rem;
}

.timeline-points li {
    margin-bottom: var(--space-2);
    color: var(--text-body);
    line-height: 1.6;
}

.timeline-points li:last-child {
    margin-bottom: 0;
}

@media (max-width: 575.98px) {
    .timeline-item {
        gap: var(--space-3);
    }

    .timeline-card {
        padding: var(--space-4);
    }
}

#skill .nav-pills .nav-link {
    color: var(--text-heading);
}

#skill .nav-pills .nav-link.active {
    color: #FFFFFF;
}

/*** Service (What I Bring) ***/
.bring-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
    gap: var(--space-5);
}

.bring-card {
    background: var(--bg-surface);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: var(--shadow-sm);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease), background-color var(--theme-transition);
}

.bring-card:hover {
    transform: translateY(-6px);
    box-shadow: var(--shadow-lg);
}

.bring-icon {
    width: 64px;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    background: rgba(98, 68, 197, 0.1);
    color: var(--text-accent);
    font-size: 1.5rem;
    margin-bottom: var(--space-4);
    transition: background .3s var(--ease), color .3s var(--ease), transform .3s var(--ease);
}

.bring-card:hover .bring-icon {
    background: var(--primary);
    color: #FFFFFF;
    transform: scale(1.08) rotate(-4deg);
}


/*** Project Portfolio ***/
#portfolio-flters li {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 8px 4px;
    font-weight: 500;
    color: var(--text-heading);
    cursor: pointer;
    transition: color .3s var(--ease), border-color .3s var(--ease);
    border-bottom: 2px solid transparent;
}

#portfolio-flters li:hover,
#portfolio-flters li.active {
    color: var(--text-accent);
    border-color: var(--primary);
}

/* Native CSS Grid (not Isotope's JS-measured absolute positioning) so row
   heights are always correct and live — they recompute automatically on any
   content change instead of relying on a one-time JS measurement that can
   go stale and cause cards to overlap the row below. */
/* Fixed column counts per breakpoint (not auto-fit/minmax) so a track's
   width is set purely by the current breakpoint — filtering to fewer visible
   cards never changes how many tracks exist, so remaining cards keep their
   exact width instead of stretching to fill the freed-up space.
   align-items:start (not the grid default of stretch) means each card sizes
   to its own content — hovering one card taller never stretches its row
   siblings, it only pushes rows below it down. */
.portfolio-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-4);
    align-items: start;
}

@media (min-width: 768px) {
    .portfolio-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 1024px) {
    .portfolio-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 1440px) {
    .portfolio-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

.portfolio-item.is-hidden {
    display: none;
}

.portfolio-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--bg-surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease), background-color var(--theme-transition);
}

.portfolio-card:hover,
.portfolio-card:focus-within {
    transform: translateY(-6px);
    box-shadow: var(--shadow-lg);
}

.portfolio-cover {
    position: relative;
    aspect-ratio: 16 / 10;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #FFFFFF;
}

.portfolio-cover i {
    font-size: clamp(2.25rem, 5vw, 3.25rem);
}

.portfolio-date {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: #FFFFFF;
    background: rgba(255, 255, 255, 0.2);
    padding: 4px 10px;
    border-radius: 999px;
    backdrop-filter: blur(4px);
}

.cover-1 { background: linear-gradient(135deg, var(--primary), #8467d9); }
.cover-2 { background: linear-gradient(135deg, #3a2a80, var(--primary)); }
.cover-3 { background: linear-gradient(135deg, #efb52e, var(--secondary)); color: var(--dark); }
.cover-4 { background: linear-gradient(135deg, #241a4d, var(--primary)); }
.cover-5 { background: linear-gradient(135deg, var(--primary), var(--secondary)); }
.cover-6 { background: linear-gradient(135deg, #4a339c, #8467d9); }

.cover-3 .portfolio-date {
    color: var(--dark);
    background: rgba(18, 20, 29, 0.1);
}

.portfolio-body {
    padding: var(--space-5);
    flex: 1;
    display: flex;
    flex-direction: column;
}

.portfolio-tag {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-accent);
}

.portfolio-expand-btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    align-self: flex-start;
    margin-top: var(--space-3);
    padding: 8px 2px;
    min-height: 36px;
    background: none;
    border: none;
    color: var(--text-accent);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.portfolio-expand-btn i {
    font-size: 0.72rem;
    transition: transform .3s var(--ease);
}

.portfolio-card.is-expanded .portfolio-expand-btn i {
    transform: rotate(180deg);
}

/* Collapsed by default — expands only via .portfolio-expand-btn, one card at
   a time (see the accordion logic in main.js). Because the grid is native
   CSS Grid (not Isotope), the row height recalculates live as this grows,
   so the layout is pushed down naturally with no overlap. */
.portfolio-desc-wrap {
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    transition: max-height .4s var(--ease), opacity .3s var(--ease), margin-top .4s var(--ease);
}

.portfolio-card.is-expanded .portfolio-desc-wrap {
    max-height: 240px;
    opacity: 1;
}

.portfolio-desc-wrap p {
    margin: 0 0 var(--space-3);
    color: var(--text-body);
    max-height: 190px;
    overflow-y: auto;
}

/* Desktop/laptop (true hover support): the card itself expands on hover —
   no click needed, and the Details button (mobile/touch fallback) is
   hidden since it's redundant once hover already reveals the content.
   :focus-within keeps this reachable by keyboard via the GitHub link. */
@media (hover: hover) and (pointer: fine) {
    .portfolio-expand-btn {
        display: none;
    }

    .portfolio-card:hover .portfolio-desc-wrap,
    .portfolio-card:focus-within .portfolio-desc-wrap {
        max-height: 240px;
        opacity: 1;
    }
}

.portfolio-link {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-weight: 600;
    color: var(--text-accent);
    text-decoration: none;
    margin-top: auto;
    transition: gap .3s var(--ease);
}

.portfolio-link:hover,
.portfolio-link:focus-visible {
    gap: .55rem;
    color: var(--text-accent);
}


/*** Team / Certifications ***/
.cert-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
    gap: var(--space-5);
    max-width: 800px;
    margin: 0 auto;
}

.cert-card {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    height: 100%;
    background: var(--bg-surface);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    box-shadow: var(--shadow-sm);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease), border-color .35s var(--ease), background-color var(--theme-transition);
}

.cert-card:hover {
    transform: translateY(-6px);
    box-shadow: var(--shadow-lg);
    border-color: rgba(98, 68, 197, 0.25);
}

.cert-badge {
    flex-shrink: 0;
    width: 64px;
    height: 64px;
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(98, 68, 197, 0.1);
    color: var(--text-accent);
    font-size: 1.75rem;
    transition: background .3s var(--ease), color .3s var(--ease);
}

.cert-card:hover .cert-badge {
    background: var(--primary);
    color: #FFFFFF;
}

.cert-body h5 {
    margin-bottom: 4px;
}

.cert-issuer,
.cert-date {
    display: block;
    font-size: 0.85rem;
}

.cert-issuer {
    color: var(--text-muted);
}

.cert-date {
    color: var(--text-accent);
    font-weight: 600;
}


/*** Testimonial / Recommendations ***/
.recs-card {
    position: relative;
    background: var(--glass-bg-soft);
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--space-8) var(--space-6);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease), background-color var(--theme-transition), border-color var(--theme-transition);
}

.recs-card:hover {
    transform: translateY(-6px);
}

/* backdrop-filter shipped in Firefox 103 (mid-2022) — on anything older it's
   silently ignored, which is normally fine since our glass panels are
   already 60-75% opaque. To be safe rather than rely on that alone, swap to
   a fully solid surface colour on browsers that can't blur, so text always
   stays clearly readable with no dependency on what's behind the panel. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .wmd-card,
    .recs-card {
        background: var(--bg-surface);
    }

    .wmd-modal-overlay {
        background: rgba(18, 20, 29, 0.85);
    }
}

.recs-icon {
    width: 64px;
    height: 64px;
    margin: 0 auto var(--space-4);
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(98, 68, 197, 0.1);
    color: var(--text-accent);
    font-size: 1.5rem;
}


/*** Contact ***/
#contact h3.fw-bold {
    font-size: clamp(1.25rem, 1rem + 1.5vw, 1.75rem);
    overflow-wrap: break-word;
}

.form-control {
    transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out, background-color var(--theme-transition), color var(--theme-transition);
}

#contact .form-floating > label {
    color: var(--text-muted);
}


/*** Map ***/
/* Keeps the map's dark box from touching the (also dark) footer directly —
   ~1cm of visible page background between the two */
.map-section {
    margin-bottom: 38px;
}

/* iframes are inline-replaced elements by default, which leaves a few
   pixels of baseline/descender gap below them inside their block parent —
   that gap was showing the dark wrapper's background as a thin strip under
   the (visually lighter) map. display:block removes the inline gap entirely. */
.map-section iframe {
    display: block;
}


/*** Footer ***/
.footer-credit {
    line-height: 1.6;
    font-size: 0.9rem;
}

.footer-credit a.text-secondary {
    transition: color .3s var(--ease);
    padding: 2px 1px;
}

.footer-credit a.text-secondary:hover,
.footer-credit a.text-secondary:focus-visible {
    color: #FFFFFF !important;
}

@media (max-width: 767.98px) {
    .footer-credit + .footer-credit {
        margin-top: var(--space-2);
    }
}