/* ============================================================
   CV Builder — Visual Effects
   Applied to public CV sections and the builder preview.
   ============================================================ */

/* ------ Circular colour swatches ------ */
.color-swatch {
    appearance: none;
    -webkit-appearance: none;
    width: 32px;
    height: 32px;
    border-radius: 9999px;
    border: 2px solid #d1d5db;
    padding: 0;
    cursor: pointer;
    background: none;
    transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.color-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.color-swatch::-webkit-color-swatch { border: none; border-radius: 9999px; }
.color-swatch::-moz-color-swatch { border: none; border-radius: 9999px; }
.color-swatch:hover { transform: scale(1.12); border-color: #9ca3af; }
.color-swatch:focus { outline: none; box-shadow: 0 0 0 2px #e5e7eb; }

/* ------ Shared surfaces / theme variables ------ */
.cv-theme-light,
.cv-theme-dark {
    color: var(--cv-text-colour, #111827);
}

.cv-surface {
    background: var(--cv-card-bg, #ffffff);
}

.cv-section-border {
    border: 1px solid var(--border-colour, var(--cv-card-border, #e5e7eb));
}

.cv-text-white {
    color: #f9fafb;
}

.cv-text-black {
    color: #111827;
}

.cv-muted {
    color: var(--cv-muted-colour, #6b7280);
}

.cv-builder-sidebar,
.cv-builder-panel {
    --cv-card-bg: #ffffff;
    --cv-card-border: #e5e7eb;
    --cv-text-colour: #111827;
    --cv-muted-colour: #6b7280;
    color: #374151;
    color-scheme: light;
}

.cv-builder-sidebar .cv-theme-input,
.cv-builder-panel .cv-theme-input {
    background-color: #ffffff;
    border-color: #e5e7eb;
    color: #374151;
}

.cv-builder-sidebar select,
.cv-builder-sidebar input:not([type="color"]):not([type="checkbox"]):not([type="hidden"]),
.cv-builder-panel select,
.cv-builder-panel input:not([type="color"]):not([type="checkbox"]):not([type="hidden"]) {
    background-color: #ffffff;
    color: #374151;
    color-scheme: light;
}

.cv-builder-sidebar {
    background: #e8eaf0;
    border-right: 1px solid #c2c8d4;
}

.cv-builder-toolbar {
    background: #ffffff;
    border: 1px solid #e5e7eb;
}

.cv-builder-panel {
    background: #e8eaf0;
    border-left: 1px solid #c2c8d4;
}

.cv-builder-panel-empty {
    color: var(--cv-muted-colour, #6b7280);
}

.cv-theme-input {
    border: 1px solid color-mix(in srgb, var(--cv-card-border, #e5e7eb) 80%, var(--cv-secondary-colour, #e0e7ff));
    background: color-mix(in srgb, var(--cv-card-bg, #ffffff) 96%, var(--cv-secondary-colour, #e0e7ff));
}

.cv-builder-panel-header {
    background: rgba(232, 234, 240, 0.97);
}

.cv-builder-panel-card {
    background: #ffffff;
    border: 1px solid #e5e7eb;
}

/* Glow preset + colour only take effect when the glow border is enabled.
   Dim and disable them while the toggle is off so the dependency is obvious. */
.section-fx-group:has(input[name="glow_border"]:not(:checked)) .glow-dependent {
    opacity: 0.4;
    pointer-events: none;
}

/* ──────────────────────────────────────────────────────────────
   Builder canvas — the live CV preview. A recessed, clearly-framed
   "window" so it's obvious what will and won't appear on the
   published CV, regardless of the CV's own background colour.
   ────────────────────────────────────────────────────────────── */
.cv-builder-canvas {
    box-shadow:
        inset 0 0 0 1px rgba(17, 24, 39, 0.12),
        inset 9px 0 18px -14px rgba(17, 24, 39, 0.28),
        inset -9px 0 18px -14px rgba(17, 24, 39, 0.28);
}

/* Section cards inside the builder always show a defined outline so each
   block reads as a distinct card, independent of its own border setting.
   Scoped to the builder only — the public CV is untouched. */
.cv-builder-canvas .section-card {
    box-shadow: 0 1px 2px rgba(16, 24, 39, 0.06);
}

.cv-builder-canvas .section-card.cv-section-border {
    border-color: color-mix(in srgb, var(--cv-card-border, #e5e7eb) 45%, #9aa1ad);
}

.cv-builder-canvas .section-card:not(.cv-section-border):not(.glow-border) {
    border: 1px dashed rgba(17, 24, 39, 0.16);
}

.cv-soft-chip {
    background: color-mix(in srgb, var(--cv-secondary-colour, #e0e7ff) 20%, transparent);
    border: 1px solid color-mix(in srgb, var(--cv-secondary-colour, #e0e7ff) 55%, var(--cv-card-border, #e5e7eb));
    color: var(--cv-text-colour, #111827);
}

.cv-accent-text {
    color: color-mix(in srgb, var(--cv-secondary-colour, #e0e7ff) 70%, var(--cv-text-colour, #111827));
}

.cv-primary-text {
    color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 82%, var(--cv-text-colour, #111827));
}

.cv-accent-link {
    color: color-mix(in srgb, var(--cv-secondary-colour, #e0e7ff) 78%, var(--cv-text-colour, #111827));
    transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}

.cv-accent-link:hover {
    color: var(--cv-text-colour, #111827);
}

.cv-header-link {
    color: color-mix(in srgb, var(--cv-secondary-colour, #e0e7ff) 78%, var(--cv-text-colour, #111827));
    transition: color 0.15s ease;
}

.cv-header-link:hover {
    color: var(--cv-text-colour, #111827);
}

.cv-flat-card {
    box-shadow: none !important;
}

.cv-transparent-section {
    min-height: 2rem;
}

.cv-builder-transparent {
    outline: 1px dashed rgba(0, 0, 0, 0.15);
    outline-offset: -1px;
}

.cv-side-panel {
    position: absolute;
    top: 0;
    bottom: 0;
    width: calc(
        max(0px, (100% - min(100%, calc(var(--cv-content-max-width, 56rem) + (var(--cv-content-shell-padding, 1.5rem) * 2)))) / 2)
        + (min(100%, calc(var(--cv-content-max-width, 56rem) + (var(--cv-content-shell-padding, 1.5rem) * 2))) * var(--cv-side-panel-ratio, 0.25))
    );
    background: var(--cv-side-panel-colour, var(--cv-secondary-colour, #e0e7ff));
    opacity: 1;
    z-index: 0;
    pointer-events: none;
    border-color: color-mix(in srgb, var(--cv-side-panel-colour, var(--cv-secondary-colour, #e0e7ff)) 65%, var(--cv-card-border, #e5e7eb));
}

.cv-side-panel-left {
    left: 0;
    border-right-width: 1px;
}

.cv-side-panel-right {
    right: 0;
    border-left-width: 1px;
}

/* ══════════════════════════════════════════════════════════════
   Section spotlight removed — sections no longer self-highlight
   based on scroll position. Per-section glow settings remain the
   only source of card highlighting.
   ══════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════
   Effect preview popups (builder edit panel)
   An eye icon next to each effect; hovering/focusing it reveals a
   small live demo of the effect so the user knows what it does.
   ══════════════════════════════════════════════════════════════ */
.fx-preview {
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
}

.fx-eye {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    color: #9ca3af;
    border: 1px solid transparent;
    background: transparent;
    cursor: help;
    transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.fx-eye:hover,
.fx-eye:focus-visible {
    color: #4b5563;
    background: #ffffff;
    border-color: #e5e7eb;
    outline: none;
}

.fx-pop {
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    z-index: 60;
    width: 210px;
    padding: 10px;
    background: #ffffff;
    border: 1px solid #e5e7eb;
    border-radius: 12px;
    box-shadow: 0 14px 34px -10px rgba(17, 24, 39, 0.35);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}
.fx-preview:hover .fx-pop,
.fx-preview:focus-within .fx-pop {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.fx-pop-label {
    display: block;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #9ca3af;
    margin-bottom: 6px;
}

.fx-demo {
    display: block;
    margin-top: 8px;
    padding: 8px 10px;
    border-radius: 10px;
    background: #ffffff;
    border: 1px solid #e5e7eb;
    font-size: 11px;
    line-height: 1.3;
    color: #374151;
    text-align: center;
}
.fx-demo:first-of-type {
    margin-top: 0;
}

/* Looping fade demo (the real entrance-fade only plays once on load) */
@keyframes fx-demo-fade {
    0% { opacity: 0; transform: translateY(10px); }
    55%, 100% { opacity: 1; transform: translateY(0); }
}
.fx-demo-fade {
    animation: fx-demo-fade 2.4s ease-in-out infinite;
}

/* Centre a single demo object (avatar ring) */
.fx-demo-center {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 10px;
}

/* Banner demo tile — fills edge-to-edge so the shine sweep reads clearly */
.fx-demo-banner {
    display: block;
    height: 42px;
    border-radius: 10px;
    border: 1px solid #e5e7eb;
    background: linear-gradient(135deg, #6366f1 0%, #a855f7 100%);
}

/* ══════════════════════════════════════════════════════════════
   Quick-pick theme colour chips (builder colour fields)
   Pull the CV's primary / secondary colour into a colour input.
   ══════════════════════════════════════════════════════════════ */
.cv-quickchip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    border-radius: 9999px;
    border: 1px solid #e5e7eb;
    background: #ffffff;
    font-size: 11px;
    font-weight: 500;
    color: #4b5563;
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
}
.cv-quickchip:hover {
    border-color: #d1d5db;
    background: #f9fafb;
    color: #1f2937;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.cv-quickchip-dot {
    width: 12px;
    height: 12px;
    border-radius: 9999px;
    flex-shrink: 0;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
}
.cv-quickchip-primary {
    background: var(--cv-primary-colour, #6366f1);
}
.cv-quickchip-secondary {
    background: var(--cv-secondary-colour, #e0e7ff);
}

/* ------ Skill chips (theme-aware) ------ */
.cv-skill-chip {
    background: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 12%, var(--cv-card-bg, #fff));
    color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 85%, var(--cv-text-colour, #111827));
    ring: 1px solid color-mix(in srgb, var(--cv-primary-colour, #6366f1) 25%, transparent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--cv-primary-colour, #6366f1) 22%, transparent);
}

/* ------ Link rows (theme-aware) ------ */
.cv-link-row {
    background: color-mix(in srgb, var(--cv-card-bg, #fff) 92%, var(--cv-primary-colour, #6366f1));
    border: 1px solid color-mix(in srgb, var(--cv-card-border, #e5e7eb) 80%, var(--cv-primary-colour, #6366f1));
    color: var(--cv-text-colour, #111827);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.cv-link-row:hover {
    background: color-mix(in srgb, var(--cv-card-bg, #fff) 80%, var(--cv-primary-colour, #6366f1));
    border-color: color-mix(in srgb, var(--cv-card-border, #e5e7eb) 50%, var(--cv-primary-colour, #6366f1));
}
/* ══════════════════════════════════════════════════════════════
   Glow border presets — four deliberately distinct looks.
   Both .glow-border (base = "Default") and .glow-preset-* are
   applied together; preset rules come after the base so they win.
   ══════════════════════════════════════════════════════════════ */

/* Default — a crisp ring with a clean, steady bloom. Static. */
.glow-border {
    box-shadow:
        0 0 0 1.5px var(--glow-colour, #6366f1),
        0 0 16px 2px color-mix(in srgb, var(--glow-colour, #6366f1) 38%, transparent);
    border-color: var(--glow-colour, #6366f1) !important;
}

/* Subtle — no hard ring, just a soft diffuse halo. The understated option. */
.glow-preset-subtle {
    box-shadow:
        0 0 0 1px color-mix(in srgb, var(--glow-colour, #6366f1) 28%, transparent),
        0 0 24px 6px color-mix(in srgb, var(--glow-colour, #6366f1) 13%, transparent);
    border-color: color-mix(in srgb, var(--glow-colour, #6366f1) 50%, transparent) !important;
    filter: none;
}

/* Neon — a bright electric tube that breathes. The solid (non-transparent)
   inner shadow is what gives it the lit-glass-tube core. */
.glow-preset-neon {
    border-color: var(--glow-colour, #6366f1) !important;
    filter: saturate(1.6) brightness(1.08);
    animation: glow-neon-pulse 1.8s ease-in-out infinite;
}

@keyframes glow-neon-pulse {
    0%, 100% {
        box-shadow:
            0 0 0 1px var(--glow-colour, #6366f1),
            0 0 6px 1px var(--glow-colour, #6366f1),
            0 0 18px 4px color-mix(in srgb, var(--glow-colour, #6366f1) 60%, transparent);
    }
    50% {
        box-shadow:
            0 0 0 1.5px var(--glow-colour, #6366f1),
            0 0 13px 3px var(--glow-colour, #6366f1),
            0 0 36px 11px color-mix(in srgb, var(--glow-colour, #6366f1) 78%, transparent);
    }
}

/* Rainbow — ignores the single glow colour and cycles the spectrum. The ring
   (the 1.5px spread) carries the colour, so the real border is left transparent
   (border-color can't be animated via !important inside @keyframes). */
.glow-preset-rainbow {
    border-color: transparent !important;
    filter: saturate(1.25);
    animation: glow-rainbow-cycle 6s linear infinite;
}

@keyframes glow-rainbow-cycle {
    0% {
        box-shadow: 0 0 0 1.5px #ff3b30, 0 0 22px 5px color-mix(in srgb, #ff3b30 55%, transparent);
    }
    16% {
        box-shadow: 0 0 0 1.5px #ff9500, 0 0 22px 5px color-mix(in srgb, #ff9500 55%, transparent);
    }
    33% {
        box-shadow: 0 0 0 1.5px #ffcc00, 0 0 22px 5px color-mix(in srgb, #ffcc00 55%, transparent);
    }
    50% {
        box-shadow: 0 0 0 1.5px #34c759, 0 0 22px 5px color-mix(in srgb, #34c759 55%, transparent);
    }
    66% {
        box-shadow: 0 0 0 1.5px #0a84ff, 0 0 22px 5px color-mix(in srgb, #0a84ff 55%, transparent);
    }
    83% {
        box-shadow: 0 0 0 1.5px #af52de, 0 0 22px 5px color-mix(in srgb, #af52de 55%, transparent);
    }
    100% {
        box-shadow: 0 0 0 1.5px #ff3b30, 0 0 22px 5px color-mix(in srgb, #ff3b30 55%, transparent);
    }
}

/* Respect reduced-motion: drop the animation, keep a strong static glow. */
@media (prefers-reduced-motion: reduce) {
    .glow-preset-neon {
        animation: none;
        box-shadow:
            0 0 0 1.5px var(--glow-colour, #6366f1),
            0 0 12px 3px var(--glow-colour, #6366f1),
            0 0 30px 9px color-mix(in srgb, var(--glow-colour, #6366f1) 68%, transparent);
    }
    .glow-preset-rainbow {
        animation: none;
        box-shadow:
            0 0 0 1.5px #0a84ff,
            0 0 22px 5px color-mix(in srgb, #0a84ff 55%, transparent);
    }
}

.shine-border {
    position: relative;
    overflow: hidden;
}

.shine-border::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        118deg,
        transparent 8%,
        color-mix(in srgb, var(--cv-primary-colour, #6366f1) 18%, transparent) 28%,
        color-mix(in srgb, var(--cv-secondary-colour, #e0e7ff) 55%, white) 50%,
        color-mix(in srgb, var(--cv-primary-colour, #6366f1) 18%, transparent) 72%,
        transparent 92%
    );
    transform: translateX(-130%) skewX(-12deg);
    animation: border-shine 4.2s ease-in-out infinite;
    pointer-events: none;
    mix-blend-mode: overlay;
    opacity: 0.9;
}

@keyframes border-shine {
    0%, 45% {
        transform: translateX(-130%) skewX(-12deg);
        opacity: 0;
    }
    52% {
        opacity: 1;
    }
    75%, 100% {
        transform: translateX(130%) skewX(-12deg);
        opacity: 0;
    }
}

/* ------ Entrance fade (triggered by IntersectionObserver in effects.js) ------ */
.entrance-fade {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.6s ease, transform 0.6s ease;
}

.entrance-fade.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ------ Animated glow around the profile avatar ------ */
@keyframes avatar-glow {
    0%, 100% {
        box-shadow: 0 0 var(--avatar-glow-blur-min, 10px) var(--avatar-glow-spread-min, 3px) var(--glow-colour, #6366f1);
    }
    50% {
        box-shadow: 0 0 var(--avatar-glow-blur-max, 24px) var(--avatar-glow-spread-max, 8px) var(--glow-colour, #6366f1);
    }
}

.glow-avatar {
    --avatar-glow-blur-min: 10px;
    --avatar-glow-blur-max: 24px;
    --avatar-glow-spread-min: 3px;
    --avatar-glow-spread-max: 8px;
    animation: avatar-glow 2.5s ease-in-out infinite;
}

.glow-preset-subtle .glow-avatar,
.glow-avatar.glow-preset-subtle {
    --avatar-glow-blur-min: 8px;
    --avatar-glow-blur-max: 16px;
    --avatar-glow-spread-min: 2px;
    --avatar-glow-spread-max: 4px;
}

.glow-preset-neon .glow-avatar,
.glow-avatar.glow-preset-neon {
    --avatar-glow-blur-min: 12px;
    --avatar-glow-blur-max: 30px;
    --avatar-glow-spread-min: 4px;
    --avatar-glow-spread-max: 10px;
}

.glow-preset-rainbow .glow-avatar,
.glow-avatar.glow-preset-rainbow {
    --avatar-glow-blur-min: 12px;
    --avatar-glow-blur-max: 28px;
    --avatar-glow-spread-min: 4px;
    --avatar-glow-spread-max: 9px;
}

/* ------ Social link pills (always on white/light bg — always dark text) ------ */
.cv-social-pill {
    color: #374151;
    background: rgba(255, 255, 255, 0.85);
    border: 1px solid #e5e7eb;
    transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease,
                box-shadow 0.15s ease;
}
.cv-social-pill:hover {
    color: #111827;
    background: rgba(255, 255, 255, 1);
    border-color: #d1d5db;
    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}

/* ------ Social icon idle Y-axis flip + stagger ------ */
.social-icon-spin {
    display: inline-block;
    animation: icon-idle-flipY 6s ease-in-out infinite;
}

/* Each icon flips at a different phase so they feel individual */
.cv-social-pill:nth-child(1) .social-icon-spin { animation-delay: 0s; }
.cv-social-pill:nth-child(2) .social-icon-spin { animation-delay: 1.2s; }
.cv-social-pill:nth-child(3) .social-icon-spin { animation-delay: 2.4s; }
.cv-social-pill:nth-child(4) .social-icon-spin { animation-delay: 3.6s; }
.cv-social-pill:nth-child(5) .social-icon-spin { animation-delay: 4.8s; }

@keyframes icon-idle-flipY {
    0%, 78%  { transform: perspective(180px) rotateY(0deg); }
    88%      { transform: perspective(180px) rotateY(180deg); }
    100%     { transform: perspective(180px) rotateY(360deg); }
}

/* On hover: fast snappy flip, overrides idle */
.cv-social-pill:hover .social-icon-spin {
    animation: icon-hover-flipY 0.55s cubic-bezier(0.22, 0.68, 0, 1.2) forwards;
}

@keyframes icon-hover-flipY {
    0%   { transform: perspective(180px) rotateY(0deg) scale(1); }
    50%  { transform: perspective(180px) rotateY(180deg) scale(1.2); }
    100% { transform: perspective(180px) rotateY(360deg) scale(1); }
}

/* ------ Confirm modal ------ */
.confirm-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
}

.confirm-modal-backdrop.is-open {
    opacity: 1;
    pointer-events: auto;
}

.confirm-modal-panel {
    transform: translateY(16px) scale(0.98);
    transition: transform 0.18s ease;
}

.confirm-modal-backdrop.is-open .confirm-modal-panel {
    transform: translateY(0) scale(1);
}

/* ──────────────────────────────────────────────────────────────
   Banner shine sweep
   ────────────────────────────────────────────────────────────── */
.cv-banner-shine {
    position: relative;
    overflow: hidden;
}

.cv-banner-shine::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -60%;
    width: 35%;
    background: linear-gradient(
        105deg,
        transparent 0%,
        color-mix(in srgb, white 6%, transparent) 30%,
        color-mix(in srgb, white 20%, transparent) 50%,
        color-mix(in srgb, white 6%, transparent) 70%,
        transparent 100%
    );
    transform: skewX(-18deg);
    animation: banner-shine-sweep 9s ease-in-out infinite;
    pointer-events: none;
}

@keyframes banner-shine-sweep {
    0%, 50% { left: -60%; opacity: 0; }
    55%     { opacity: 1; }
    82%     { opacity: 1; }
    90%, 100% { left: 130%; opacity: 0; }
}

/* ──────────────────────────────────────────────────────────────
   Spinning gradient ring around the avatar
   ────────────────────────────────────────────────────────────── */
.cv-avatar-outer {
    display: inline-block;
    border-radius: 9999px;
    padding: 3px;
    background: conic-gradient(
        from 0deg,
        var(--cv-primary-colour, #6366f1) 0deg,
        var(--cv-secondary-colour, #e0e7ff) 120deg,
        rgba(255, 255, 255, 0.95) 180deg,
        var(--cv-secondary-colour, #e0e7ff) 240deg,
        var(--cv-primary-colour, #6366f1) 360deg
    );
    animation: avatar-ring-spin 5s linear infinite;
    box-shadow:
        0 0 18px color-mix(in srgb, var(--cv-primary-colour, #6366f1) 45%, transparent),
        0 6px 20px rgba(0, 0, 0, 0.25);
    flex-shrink: 0;
}

.cv-avatar-img {
    display: block;
    border: 3px solid var(--cv-card-bg, #ffffff);
    border-radius: 9999px;
    animation: avatar-img-counter 5s linear infinite;
}

.cv-avatar-placeholder {
    border: 3px solid var(--cv-card-bg, #ffffff);
    animation: avatar-img-counter 5s linear infinite;
}

@keyframes avatar-ring-spin {
    to { transform: rotate(360deg); }
}

@keyframes avatar-img-counter {
    to { transform: rotate(-360deg); }
}

/* ══════════════════════════════════════════════════════════════
   Portfolio card grid — text-focused compact project cards
   ══════════════════════════════════════════════════════════════ */
.pf-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 0.75rem;
}

/* Horizontal single-row scroll variant */
.pf-card-scroll {
    display: flex;
    flex-direction: row;
    overflow-x: auto;
    gap: 0.75rem;
    padding-bottom: 0.625rem;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    /* Hide scrollbar on WebKit but keep it scrollable */
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 30%, transparent) transparent;
}
.pf-card-scroll::-webkit-scrollbar {
    height: 4px;
}
.pf-card-scroll::-webkit-scrollbar-track {
    background: transparent;
}
.pf-card-scroll::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 35%, transparent);
    border-radius: 999px;
}
.pf-card-scroll .pf-card {
    flex: 0 0 260px;
    scroll-snap-align: start;
}

.pf-card {
    border-radius: 0.75rem;
    overflow: hidden;
    border: 1px solid var(--cv-card-border, #e5e7eb);
    background: color-mix(in srgb, var(--cv-card-bg, #fff) 97%, var(--cv-primary-colour, #6366f1));
    display: flex;
    flex-direction: column;
    transition: box-shadow 0.2s ease, transform 0.18s ease;
}

.pf-card:hover {
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.13);
    transform: translateY(-2px);
}

.pf-card-thumb-wrap {
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: #000;
    flex-shrink: 0;
    cursor: zoom-in;
    position: relative;
}

/* Zoom-in hint badge — appears on hover */
.pf-card-thumb-wrap::after {
    content: "⤢";
    position: absolute;
    top: 0.4rem;
    right: 0.4rem;
    width: 22px;
    height: 22px;
    border-radius: 0.375rem;
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
    font-size: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.15s ease;
    pointer-events: none;
    line-height: 22px;
    text-align: center;
}

.pf-card-thumb-wrap:hover::after {
    opacity: 1;
}

.pf-card-thumb-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.35s ease;
}

.pf-card:hover .pf-card-thumb-img {
    transform: scale(1.04);
}

.pf-card-body {
    padding: 0.625rem 0.75rem 0.75rem;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.pf-card-caption {
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.5;
    color: var(--cv-text-colour, #111827);
    flex: 1;
}

/* Prominent project link button */
.pf-project-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.65rem;
    border-radius: 0.5rem;
    font-size: 0.75rem;
    font-weight: 500;
    background: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--cv-primary-colour, #6366f1) 25%, transparent);
    color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 90%, var(--cv-text-colour, #111827));
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease;
    align-self: flex-start;
}

.pf-project-link:hover {
    background: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 22%, transparent);
    border-color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 45%, transparent);
}

/* ── Portfolio image lightbox ── */
.pf-lightbox {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.875rem;
    background: rgba(0, 0, 0, 0.88);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
    cursor: zoom-out;
    padding: 1.5rem;
}

.pf-lightbox.open {
    opacity: 1;
    pointer-events: auto;
}

.pf-lightbox-img {
    max-width: 92vw;
    max-height: 80vh;
    object-fit: contain;
    border-radius: 0.625rem;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
    display: block;
    transform: scale(0.95);
    transition: transform 0.22s ease;
}

.pf-lightbox.open .pf-lightbox-img {
    transform: scale(1);
}

.pf-lightbox-caption {
    font-size: 0.875rem;
    color: rgba(255, 255, 255, 0.85);
    text-align: center;
    max-width: 640px;
    line-height: 1.5;
}

.pf-lightbox-close {
    position: absolute;
    top: 0.875rem;
    right: 0.875rem;
    width: 32px;
    height: 32px;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.2);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease;
}

.pf-lightbox-close:hover {
    background: rgba(255, 255, 255, 0.22);
}

/* ══════════════════════════════════════════════════════════════
   Certification thumbnails
   ══════════════════════════════════════════════════════════════ */
.cert-thumb {
    width: 48px;
    height: 48px;
    border-radius: 0.625rem;
    object-fit: cover;
    flex-shrink: 0;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.08);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.cert-thumb:hover {
    transform: scale(1.07);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
}

.cert-view-link {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.6875rem;
    font-weight: 500;
    padding: 0.2rem 0.55rem;
    border-radius: 9999px;
    background: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 12%, transparent);
    color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 90%, var(--cv-text-colour, #111827));
    border: 1px solid color-mix(in srgb, var(--cv-primary-colour, #6366f1) 22%, transparent);
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.cert-view-link:hover {
    background: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 22%, transparent);
    border-color: color-mix(in srgb, var(--cv-primary-colour, #6366f1) 40%, transparent);
}

/* ══════════════════════════════════════════════════════════════
   Certification lightbox — click-to-enlarge overlay
   ══════════════════════════════════════════════════════════════ */
.cert-lightbox {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.82);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
    cursor: pointer;
}

.cert-lightbox.open {
    opacity: 1;
    pointer-events: auto;
}

.cert-lightbox-backdrop {
    display: none;
}

.cert-lightbox-panel {
    position: relative;
    z-index: 1;
    max-width: min(92vw, 660px);
    background: var(--cv-card-bg, #fff);
    border-radius: 1rem;
    overflow: hidden;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
    transform: scale(0.94);
    transition: transform 0.22s ease;
}

.cert-lightbox.open .cert-lightbox-panel {
    transform: scale(1);
}

.cert-lightbox-img {
    display: block;
    width: 100%;
    max-height: 78vh;
    object-fit: contain;
    background: #000;
}

.cert-lightbox-info {
    padding: 0.75rem 1rem 0.875rem;
    border-top: 1px solid var(--cv-card-border, #e5e7eb);
}

.cert-lightbox-name {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--cv-text-colour, #111827);
    line-height: 1.35;
}

.cert-lightbox-meta {
    font-size: 0.75rem;
    color: var(--cv-muted-colour, #6b7280);
    margin-top: 0.2rem;
}

.cert-lightbox-close {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    width: 30px;
    height: 30px;
    border-radius: 9999px;
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease;
    z-index: 2;
}

.cert-lightbox-close:hover {
    background: rgba(0, 0, 0, 0.75);
}

.cert-thumb-clickable {
    cursor: zoom-in;
}
