/* ============================================================================
   RAGHEB ALKASER — PORTFOLIO STYLESHEET
   ----------------------------------------------------------------------------
   Structure of this file, top to bottom:
     1.  Theme Variables & Global Reset
     2.  Site Navigation (desktop + mobile drawer)
     3.  Language Dropdown
     4.  Hero / Profile Card
     5.  Skills Section (+ its entrance animation)
     6.  Timeline (wave, date pills, "Future" tooltip)
     7.  Story Card (the expanded year detail view)
     8.  Shared Entrance Animations & Keyframes
     9.  Contact Section
     10. Footer
     11. Mobile Responsive Overrides (drawer nav + fluid timeline)
     12. General Responsive Overrides (everything else)
============================================================================ */


/* ============================================================================
   1. THEME VARIABLES & GLOBAL RESET
   ----------------------------------------------------------------------------
   Every color in this file is a CSS variable. That's what makes the dark/
   light theme toggle work: script.js only ever adds or removes
   data-theme="light" on <html> — it never touches any color directly.
   The two blocks below define the same variable names twice, once for the
   default (dark) theme, once for light mode.
============================================================================ */
:root {
    /* Base palette — dark theme (this is the default look) */
    --bg: #0B0D12;
    --card: #151922;
    --text: #F5F5F5;
    --muted: #8A94A6;
    --accent: #3B82F6;
    --border: rgba(255, 255, 255, 0.08);
    --header-bg: rgba(11, 13, 18, 0.1);

    /* Background decoration */
    --bg-dot: rgba(59, 130, 246, 0.25);        /* the dotted grid pattern */
    --bg-radial-start: #17223b;                /* center of the page glow */
    --bg-radial-end: #0B0D12;                  /* edges of the page glow */

    /* Subtle diagonal texture used inside .profile-card and .story-card */
    --card-pattern: rgba(59, 130, 246, 0.02);
    --card-pattern-2: rgba(59, 130, 246, 0.01);

    /* Timeline date-pill background (semi-transparent so the dotted
       background shows through slightly) */
    --point-bg: rgba(21, 25, 34, 0.55);
    --point-bg-hover: rgba(59, 130, 246, 0.7);
}

:root[data-theme="light"] {
    /* Same variable names, light-theme values. Deliberately NOT plain
       white/gray — uses a muted blue-slate palette so it still feels
       like "this site", not a generic default light mode. */
    --bg: #D8E0EE;
    --card: #C7D3EA;
    --text: #1A2233;
    --muted: #556077;
    --accent: #2F6FED;
    --border: rgba(26, 34, 51, 0.15);
    --header-bg: rgba(216, 224, 238, 0.1);

    /* Background glow is intentionally reversed vs. dark mode: light mode
       glows brighter at the EDGES and slightly darker in the center,
       which was a deliberate stylistic choice (see --bg-radial-start vs
       --bg-radial-end below — the center is the darker of the two). */
    --bg-dot: rgba(47, 111, 237, 0.4);
    --bg-radial-start: #A9B8D6;
    --bg-radial-end: #F1F4FA;

    --card-pattern: rgba(47, 111, 237, 0.04);
    --card-pattern-2: rgba(47, 111, 237, 0.03);

    --point-bg: rgba(199, 211, 234, 0.55);
    --point-bg-hover: rgba(47, 111, 237, 0.7);
}

html {
    scroll-behavior: smooth;       /* smooth-scrolls for #anchor links and .scrollIntoView() calls */
    scrollbar-gutter: stable;      /* reserves scrollbar space so content doesn't shift width when a
                                       scrollbar appears/disappears (e.g. after a language switch
                                       changes the page's total height) */
    overflow-y: scroll;            /* forces the vertical scrollbar to always be present, for the
                                       same reason as scrollbar-gutter above — belt and suspenders */
    overflow-x: hidden;            /* prevents a horizontal scrollbar from appearing while elements
                                       are still mid-animation (several entrance animations start
                                       from off-screen positions like translateX(200px)) */
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-color: var(--bg);
    background-image:
        /* Layer 1: the dotted grid pattern */
        radial-gradient(var(--bg-dot) 2px, transparent 2px),
        /* Layer 2: soft ambient glow behind everything */
        radial-gradient(circle at 50% 50%, var(--bg-radial-start) 0%, var(--bg-radial-end) 100%);
    background-size: 36px 36px, 100% 100%;
    background-position: center;
    background-attachment: fixed;  /* keeps the background static while the page content scrolls */
    padding-top: 68px;             /* reserves space equal to the fixed nav's height, so page content
                                       doesn't start underneath it */
    color: var(--text);
    font-family: "Inter", sans-serif;
    min-height: 100vh;
    overflow-x: hidden;            /* belt-and-suspenders with the html rule above */
}

.hero {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    padding: 4vh 0 0 0;
    width: 100%;
}


/* ============================================================================
   2. SITE NAVIGATION
   ----------------------------------------------------------------------------
   Desktop shows .nav-links directly in the bar. Below 900px, .nav-links is
   hidden and replaced by the hamburger + slide-out drawer defined in
   Section 11.
============================================================================ */
.site-nav {
    position: fixed;               /* fixed (not sticky) so it stays pinned even while the mobile
                                       drawer locks body scrolling */
    top: 0;
    left: 0;
    z-index: 1000;
    width: 100%;
    background: var(--header-bg);
    backdrop-filter: blur(8px);    /* frosted-glass effect over whatever scrolls beneath it */
    border-bottom: 1px solid var(--border);
}

.nav-inner {
    width: 94%;
    max-width: 1500px;
    margin: 0 auto;
    height: 68px;                  /* NOTE: this value must match body's padding-top above, and the
                                       scroll-margin-top values used throughout this file, so that
                                       anchor-linked sections don't end up hidden behind the nav. */
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.nav-logo {
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--text);
}

.nav-links {
    display: flex;
    gap: 2rem;
    margin-left: auto;
    margin-right: 2rem;
}

.nav-links a {
    color: var(--muted);
    font-weight: 500;
    font-size: 0.95rem;
    text-decoration: none;
    transition: color 0.2s ease;
}

.nav-links a:hover {
    color: var(--accent);
}

.nav-controls {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

/* Shared square icon-button style used by both the language toggle and
   theme toggle buttons in the nav. */
.nav-icon-btn {
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 12px;
    color: var(--muted);
    font-size: 1rem;
    cursor: pointer;
    transition: all 0.2s ease;
    box-shadow: none;   /* overrides the global button glow/shadow (see Section 4) which would
                           otherwise look too heavy on these small icon buttons */
    padding: 0;
}

.nav-icon-btn:hover {
    background: rgba(59, 130, 246, 0.12);
    border-color: var(--accent);
    color: var(--text);
    transform: none;    /* also overrides the global button's hover scale-up */
    box-shadow: none;
}

/* Hides the desktop nav links below 900px — the mobile drawer (Section 11)
   takes over navigation at that breakpoint instead. */
@media (max-width: 900px) {
    .nav-links {
        display: none;
    }
}

/* Sun/moon icon swap: only one icon is visible at a time, depending on
   which theme is currently active. */
.nav-icon-btn .fa-sun {
    display: none;
}

:root[data-theme="light"] .nav-icon-btn .fa-sun {
    display: block;
}

:root[data-theme="light"] .nav-icon-btn .fa-moon {
    display: none;
}

/* Entrance animation for the desktop nav links: each one slides in from
   the right with a slightly increasing delay, so they appear to cascade
   in left-to-right rather than all at once. */
.nav-links a {
    animation: slideRight 0.7s ease forwards;
}

.nav-links a:nth-child(1) { animation-delay: 0.1s; }
.nav-links a:nth-child(2) { animation-delay: 0.2s; }
.nav-links a:nth-child(3) { animation-delay: 0.3s; }


/* ============================================================================
   3. LANGUAGE DROPDOWN
============================================================================ */
.lang-dropdown {
    position: relative;    /* anchors the absolutely-positioned .lang-menu below it */
}

.lang-flag {
    font-size: 1.1rem;
    line-height: 1;
}

.lang-menu {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 170px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.35);
    padding: 0.4rem;

    /* Hidden by default — JS toggles the .is-open class to reveal it */
    opacity: 0;
    transform: translateY(-8px);
    pointer-events: none;
    transition: opacity 0.15s ease, transform 0.15s ease;
    z-index: 300;
}

.lang-menu.is-open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.lang-option {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    text-align: left;
    padding: 0.6rem 0.75rem;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text);
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease;
    box-shadow: none;   /* overrides global button shadow, same reasoning as .nav-icon-btn */
}

.lang-option:hover {
    background: rgba(59, 130, 246, 0.12);
    transform: none;
    box-shadow: none;
}

/* Highlights whichever language is currently active, set via JS
   (aria-current="true") */
.lang-option[aria-current="true"] {
    color: var(--accent);
    font-weight: 700;
}


/* ============================================================================
   4. HERO / PROFILE CARD
============================================================================ */
.profile-card {
    width: 94%;
    max-width: 1500px;
    min-height: 520px;
    background: var(--card);

    /* Six overlapping diagonal gradients create a subtle repeating diamond
       texture across the card. --card-pattern controls the 4 "outer"
       diagonal lines; --card-pattern-2 controls the 2 finer crosshatch
       lines layered on top. Both are theme-aware variables. */
    background-image:
        linear-gradient(30deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(150deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(30deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(150deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(60deg, var(--card-pattern-2) 25%, transparent 25.5%, transparent 75%, var(--card-pattern-2) 75.5%, var(--card-pattern-2)),
        linear-gradient(60deg, var(--card-pattern-2) 25%, transparent 25.5%, transparent 75%, var(--card-pattern-2) 75.5%, var(--card-pattern-2));
    background-size: 40px 70px;
    /* IMPORTANT: this position list must have exactly one entry per gradient
       layer above (6 layers → 6 positions), or the pattern will misalign. */
    background-position: 0 0, 0 0, 20px 35px, 20px 35px, 0 0, 20px 35px;

    padding: 4rem;
    overflow: hidden;
    border-radius: 30px;
    border-top: 2px solid var(--accent);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
    margin-bottom: 2rem;
}

.profile-content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 5rem;
}

.profile-text {
    flex: 1;
}

h1 {
    font-size: 4rem;
    margin-bottom: 1rem;
    font-weight: 700;
}

.subtitle {
    color: var(--accent);
    font-size: 1.2rem;
    margin-bottom: 1.2rem;
    font-weight: 500;
}

.description {
    color: var(--muted);
    max-width: 650px;
    line-height: 1.8;
    font-size: 1.15rem;
    margin-bottom: 2rem;
}

.social-links {
    display: flex;
    gap: 1rem;
    margin-bottom: 2rem;
}

.social-links a {
    width: 48px;
    height: 48px;
    display: flex;
    justify-content: center;
    align-items: center;
    text-decoration: none;
    color: var(--muted);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 14px;
    font-size: 1.2rem;
    transition: all 0.3s ease;
}

.social-links a:hover {
    background: rgba(59, 130, 246, 0.12);
    border-color: var(--accent);
    color: var(--text);
    transform: translateY(-4px) scale(1.08);
}

/* --------------------------------------------------------------------------
   Global button style. This applies to EVERY <button> element on the page
   by default (the hero CTA, the "Back to Timeline" button, etc.) — more
   specific selectors elsewhere (like .nav-icon-btn) override pieces of
   this where a different look is needed.
-------------------------------------------------------------------------- */
button,
.back-to-timeline-btn {
    background: var(--accent);
    color: white;
    border: none;
    padding: 15px 36px;
    border-radius: 14px;
    cursor: pointer;
    font-size: 1rem;
    font-weight: 600;
    transition: all 0.3s ease;
    box-shadow: 0 4px 14px rgba(59, 130, 246, 0.3);
}

button:hover,
.back-to-timeline-btn:hover {
    transform: scale(1.05);
    box-shadow: 0 6px 20px rgba(59, 130, 246, 0.45);
}

.profile-photo {
    width: 500px;
    height: 500px;
    border-radius: 50%;
    overflow: hidden;
}

.profile-photo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: bottom center;

    /* Subtle color-grade + soft blue rim-light glow, meant to tie the photo
       visually into the site's blue-toned dark theme (photos shot in
       plain daylight otherwise look "pasted on" against a moody
       background). Two stacked drop-shadows: a tighter, brighter one for
       edge definition, and a wider, softer one for ambient glow. Values
       are deliberately understated — a strong glow reads as gimmicky on
       a professional portfolio. */
    filter:
        saturate(0.9)
        contrast(1.05)
        brightness(0.97)
        drop-shadow(0 0 18px rgba(59, 130, 246, 0.35))
        drop-shadow(0 0 40px rgba(59, 130, 246, 0.15));
    transition: filter 0.3s ease;
}

/* Light-mode equivalent, using the light theme's accent color and a
   slightly gentler treatment since the page itself is already bright. */
:root[data-theme="light"] .profile-photo img {
    filter:
        saturate(0.95)
        contrast(1.03)
        brightness(1.02)
        drop-shadow(0 0 18px rgba(47, 111, 237, 0.3))
        drop-shadow(0 0 40px rgba(47, 111, 237, 0.12));
}


/* ============================================================================
   5. SKILLS SECTION
============================================================================ */
.skills-section {
    width: 94%;
    max-width: 1500px;
    margin: 0 auto 3rem auto;

    /* Reserves space above this section when the browser scrolls here via
       an anchor link (#skills) or JS, so the fixed nav doesn't cover the
       heading. Should stay close to .nav-inner's 68px height. */
    scroll-margin-top: 75px;
}

.skills-heading h2 {
    font-size: 1.8rem;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 1.5rem;
    text-align: left;
}

/* Reuses the Skills heading appearance while aligning the Journey title
   with the timeline below it. */
.timeline-heading {
    width: 94%;
    max-width: 1500px;
    margin: 0 auto;
}

.skills-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.5rem;
}

.skill-card {
    background: var(--card);
    border-radius: 20px;
    padding: 2rem;
    border-top: 2px solid var(--accent);
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25);
}

.skill-card-title {
    color: var(--accent);
    font-size: 1.1rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

.skill-card-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.skill-card-list li {
    color: var(--muted);
    padding: 0.6rem 0;
    border-top: 1px solid var(--border);
    font-size: 1rem;
}

.skill-card-list li:first-child {
    border-top: none;
}

@media (max-width: 900px) {
    .skills-grid {
        grid-template-columns: 1fr;
    }
}

/* ----------------------------------------------------------------------
   Skills entrance animation.
   ------------------------------------------------------------------------
   Hidden state (opacity: 0 + a directional transform) is applied
   immediately on page load. Once script.js's IntersectionObserver adds
   the .animate class to .skills-section (when it scrolls into view), each
   card plays its own directional slide-in animation, and each <li> inside
   fades in individually with a staggered delay — so the cards move INTO
   place while their contents appear gradually, rather than everything
   popping in at once.
---------------------------------------------------------------------- */
.skills-section .skill-card {
    opacity: 0;
}

/* Card 1 (Technical) starts off-screen to the LEFT */
.skills-section .skill-card:nth-child(1) {
    transform: translateX(-120px);
}

/* Card 2 (IT & Hardware) starts below its final position */
.skills-section .skill-card:nth-child(2) {
    transform: translateY(60px);
}

/* Card 3 (Languages) starts off-screen to the RIGHT */
.skills-section .skill-card:nth-child(3) {
    transform: translateX(120px);
}

.skills-section .skill-card-list li {
    opacity: 0;
    transition: opacity 0.4s ease;
}

.skills-section.animate .skill-card:nth-child(1) {
    animation: skillSlideRight 0.7s ease forwards;
}

.skills-section.animate .skill-card:nth-child(2) {
    animation: skillSlideUp 0.7s ease forwards 0.15s;
}

.skills-section.animate .skill-card:nth-child(3) {
    animation: skillSlideLeft 0.7s ease forwards 0.3s;
}

.skills-section.animate .skill-card-list li {
    opacity: 1;
}

/* Staggered per-item reveal delays. NOTE: if you ever add/remove a skill
   from a group in the i18n JSON files, you'll need to add/remove a
   matching nth-child(n) rule here too, or the new item won't get a
   fade-in delay assigned to it. */
.skills-section.animate .skill-card:nth-child(1) .skill-card-list li:nth-child(1) { transition-delay: 0.5s; }
.skills-section.animate .skill-card:nth-child(1) .skill-card-list li:nth-child(2) { transition-delay: 0.6s; }
.skills-section.animate .skill-card:nth-child(1) .skill-card-list li:nth-child(3) { transition-delay: 0.7s; }

.skills-section.animate .skill-card:nth-child(2) .skill-card-list li:nth-child(1) { transition-delay: 0.65s; }
.skills-section.animate .skill-card:nth-child(2) .skill-card-list li:nth-child(2) { transition-delay: 0.75s; }
.skills-section.animate .skill-card:nth-child(2) .skill-card-list li:nth-child(3) { transition-delay: 0.85s; }
.skills-section.animate .skill-card:nth-child(2) .skill-card-list li:nth-child(4) { transition-delay: 0.95s; }

.skills-section.animate .skill-card:nth-child(3) .skill-card-list li:nth-child(1) { transition-delay: 0.8s; }
.skills-section.animate .skill-card:nth-child(3) .skill-card-list li:nth-child(2) { transition-delay: 0.9s; }
.skills-section.animate .skill-card:nth-child(3) .skill-card-list li:nth-child(3) { transition-delay: 1s; }

@keyframes skillSlideRight {
    from { opacity: 0; transform: translateX(-120px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes skillSlideLeft {
    from { opacity: 0; transform: translateX(120px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes skillSlideUp {
    from { opacity: 0; transform: translateY(60px); }
    to   { opacity: 1; transform: translateY(0); }
}


/* ============================================================================
   6. TIMELINE
   ----------------------------------------------------------------------------
   The timeline is an SVG wave path with clickable "date pill" divs
   absolutely positioned on top of it, plus a small arrow/tooltip at the
   end that opens the "Future" story card.
============================================================================ */
.timeline-wrapper {
    width: 94%;
    max-width: 1500px;
    height: 160px;
    position: relative;
    margin: 0 auto -2rem;
}

/* The anchor wraps both the heading and the timeline, so navigation reveals
   the Journey title without the fixed site navigation covering it. */
.timeline-section {
    width: 100%;
    scroll-margin-top: 75px;
}

.wave {
    position: absolute;
    width: 100%;
    height: 100%;
}

.wave path {
    stroke: rgba(59, 130, 246, 0.35);
    stroke-width: 5;
    fill: none;
}

.wave polygon {
    /* This is the clickable arrowhead at the end of the wave, leading to
       the "Future" story card. */
    fill: var(--accent);
    opacity: 0;     /* hidden until .timeline-wrapper.animate reveals it (Section 8) */
    cursor: pointer;
    transition: transform 0.3s ease;   /* ONLY transform is transitioned here — see the note
                                           on @keyframes arrowReveal in Section 8 for why opacity
                                           is animated separately via @keyframes instead. */
    transform-origin: center;
    transform-box: fill-box;
}

.wave polygon:hover {
    transform: scale(1.3);
}

#timeline-ball {
    /* The small dot that visually travels along the wave path once, via
       an SVG <animateMotion> element triggered from script.js. */
    fill: #4f8cff;
    filter: drop-shadow(0px 0px 8px #4f8cff);
    opacity: 0;
}

.timeline-points {
    position: absolute;
    width: 100%;
    height: 100%;
    pointer-events: none;   /* lets clicks pass through to the SVG underneath, except where a
                                child .point explicitly re-enables pointer-events below */
}

.point {
    position: absolute;
    transform: translateX(-50%);   /* centers the pill horizontally on its "left: X%" coordinate */
    padding: 8px 16px;

    /* Semi-transparent background + blur, rather than a solid fill — keeps
       the pill from looking too "flat" against the dotted background,
       while still being clearly readable. */
    background: var(--point-bg);
    backdrop-filter: blur(4px);

    border: 2px solid var(--accent);
    border-radius: 20px;
    cursor: pointer;
    color: var(--text);
    font-weight: 500;
    transition: all 0.3s ease;
    pointer-events: auto;   /* re-enables clicking, overriding the parent's pointer-events: none */
}

.point:hover {
    background: var(--point-bg-hover);
    box-shadow: 0 0 20px rgba(59, 130, 246, 0.30);
}

.point:active {
    /* Slight press-down scale feedback on click, distinct from the larger
       hover scale below. */
    transform: translateX(-50%) scale(0.95);
}

.top {
    top: 24px;
}

.bottom {
    bottom: 22px;
}

.top:hover,
.bottom:hover {
    transform: translateX(-50%) scale(1.15);
}

.top:active,
.bottom:active {
    transform: translateX(-50%) scale(1.05);
}


/* ----------------------------------------------------------------------
   "Click on it!" tooltip that points at the future-arrow, encouraging
   the visitor to discover the hidden "Future" story card.
---------------------------------------------------------------------- */
.future-arrow-tooltip {
    position: absolute;
    right: 4.8%;
    transform: translateX(50%);
    top: 4px;

    background: var(--card);
    color: var(--text);
    padding: 6px 12px;
    border: 2px solid var(--accent);
    border-radius: 16px;
    font-weight: 600;
    font-size: 0.85rem;

    text-align: center;
    max-width: 110px;
    line-height: 1.3;
    /* Decorative cue only: let clicks pass through to the arrow it highlights. */
    cursor: default;
    pointer-events: none;

    opacity: 0;   /* hidden until the timeline's entrance animation reveals it */
    transition: all 0.3s ease;
}

/* Reveals the tooltip after the wave-drawing animation finishes, then
   keeps it gently pulsing to draw the eye. animation-delay has two
   comma-separated values, one per animation listed above (showTooltip,
   pulseGlow). */
.timeline-wrapper.animate .future-arrow-tooltip {
    animation:
        showTooltip 1.8s ease-out forwards,
        pulseGlow 2.5s infinite;
    animation-delay: 3.75s, 5.55s;
}

.future-arrow-tooltip:hover {
    transform: translateX(50%) scale(1.1);
    background: var(--accent);
    color: #FFFFFF;
}

/* Small downward-pointing triangle beneath the tooltip, aiming at the
   arrow it refers to. Built with the classic border-trick (a box with
   zero width/height and only one visible border side becomes a triangle). */
.future-arrow-tooltip::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -14px;
    transform: translateX(-50%);
    width: 0;
    height: 0;
    border-left: 9px solid transparent;
    border-right: 9px solid transparent;
    border-top: 14px solid var(--accent);
    transition: border-top-color 0.3s ease;
}

.future-arrow-tooltip:hover::after {
    border-top-color: var(--accent);
}

@keyframes showTooltip {
    from { opacity: 0; transform: translateX(50%) translateY(15px); }
    to   { opacity: 1; transform: translateX(50%) translateY(0); }
}


/* ============================================================================
   7. STORY CARD
   ----------------------------------------------------------------------------
   This is the expanded detail view that appears below the timeline when a
   date pill is clicked. Its contents (year/title/blocks) are entirely
   built by script.js's renderStory() function — this CSS only defines
   the structural shell and animations.
============================================================================ */
.story-section {
    padding: 2rem 0 4rem 0;
    width: 100%;

    /* Guarantees there's always enough scrollable space below the timeline
       for the browser to scroll all the way to the story card — even
       before any date has been clicked and the card is still empty.
       Without this, clicking a date on a fresh page load can leave the
       scroll landing short, inside the timeline instead of at the card. */
    min-height: 60vh;

    transition: min-height 0.1s ease;
}

.story-card {
    /* Starts fully hidden and non-interactive; JS adds .active once
       content has been rendered into it. */
    opacity: 0;
    pointer-events: none;
    user-select: none;

    width: 94%;
    max-width: 1500px;
    margin: auto;
    background: var(--card);

    /* Same diagonal texture pattern as .profile-card — see the detailed
       comment there for how the 6-layer gradient + background-position
       system works. */
    background-image:
        linear-gradient(30deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(150deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(30deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(150deg, var(--card-pattern) 12%, transparent 12.5%, transparent 87%, var(--card-pattern) 87.5%, var(--card-pattern)),
        linear-gradient(60deg, var(--card-pattern-2) 25%, transparent 25.5%, transparent 75%, var(--card-pattern-2) 75.5%, var(--card-pattern-2)),
        linear-gradient(60deg, var(--card-pattern-2) 25%, transparent 25.5%, transparent 75%, var(--card-pattern-2) 75.5%, var(--card-pattern-2));
    background-size: 40px 70px;
    background-position: 0 0, 0 0, 20px 35px, 20px 35px, 0 0, 20px 35px;

    padding: 4rem;
    overflow: hidden;
    border-radius: 30px;
    border-top: 2px solid var(--accent);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
    transition: opacity 0.4s ease;
}

#story-year {
    font-size: 1.5rem;
    color: var(--accent);
    font-weight: 700;
    margin-bottom: 0.5rem;
}

#story-title {
    font-size: 2.5rem;
    font-weight: 700;
    margin-bottom: 3rem;
}

#story-container {
    display: flex;
    flex-direction: column;
    gap: 4rem;
}

.story-block-heading {
    /* The short bolded heading above each block's paragraph (e.g.
       "Facing the Jury"). Rendered conditionally by JS — years/blocks
       without a heading (like the "Future" entry) simply omit this
       element entirely rather than rendering it empty. */
    color: var(--text);
    font-size: 1.15rem;
    font-weight: 700;
    margin-bottom: 0.6rem;
}

.story-block {
    display: flex;
    align-items: center;
    gap: 4rem;
}

/* Alternates image-left/text-right and image-right/text-left, applied by
   JS based on each block's index (even/odd). */
.story-block.reverse {
    flex-direction: row-reverse;
}

.story-image-box {
    width: 500px;
    flex-shrink: 0;
}

.story-image-box img {
    width: 100%;
    height: 320px;
    object-fit: cover;
    border-radius: 20px;
    border: 2px solid rgba(255, 255, 255, 0.06);
}

.story-text-box {
    flex: 1;
}

.story-text-box p {
    color: var(--muted);
    font-size: 1.15rem;
    line-height: 2;
}

.story-back-btn-wrapper {
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    padding-top: 2rem;
    margin-top: 1rem;
}

.back-to-timeline-btn {
    /* Starts hidden; revealed by .story-card.active's animation trigger
       in Section 8. */
    opacity: 0;
    transform: translateY(60px);
}


/* ============================================================================
   8. SHARED ENTRANCE ANIMATIONS & KEYFRAMES
   ----------------------------------------------------------------------------
   This section defines the "hidden until triggered" starting states for
   the hero and story-card elements, plus the animations that reveal them
   once the relevant trigger class (.animate or .active) is added by JS.
============================================================================ */

/* --- Hidden starting states (applied immediately on page load) --- */
.profile-text h1,
.subtitle,
.description,
button,
.social-links a,
#story-year,
#story-title,
.story-text-box,
.point {
    opacity: 0;
    transform: translateX(-120px);   /* most elements slide in from the LEFT */
}

.social-links a {
    transform: translateX(-80px);    /* shorter distance than the group above, so the icons
                                          feel lighter/quicker than the larger text elements */
}

.profile-photo,
.story-image-box,
.nav-links a {
    opacity: 0;
    transform: translateX(200px);    /* these three slide in from the RIGHT instead */
}

.wave path {
    /* The wave line itself uses a stroke-dashoffset "drawing" animation
       rather than a simple fade — see @keyframes drawLine below. */
    opacity: 0;
    stroke-dasharray: 5000;
    stroke-dashoffset: 5000;
}

/* --- Hero entrance sequence (plays automatically on page load, no
       scroll-trigger needed since the hero is always the first thing
       visible) --- */
.profile-text h1 {
    animation: slideLeft .9s ease forwards;
}

.subtitle {
    animation: slideLeft .9s ease forwards .2s;
}

.description {
    animation: slideLeft .9s ease forwards .4s;
}

.profile-photo {
    animation: slideRight 1.1s ease forwards .4s;
}

button {
    /* Slides in, then keeps a subtle infinite glow pulse afterward to draw
       attention to the CTA. */
    animation: slideLeft .8s ease forwards 1s, pulseGlow 2.5s infinite 2s;
}

.social-links a {
    animation: slideLeft .7s ease forwards;
}

.social-links a:nth-child(1) { animation-delay: .6s; }
.social-links a:nth-child(2) { animation-delay: .8s; }

/* --- Timeline entrance sequence (triggered by IntersectionObserver in
       script.js when the timeline scrolls into view) --- */
.timeline-wrapper.animate .wave path {
    opacity: 1;
    stroke: var(--accent);
    animation: drawLine 7.75s linear forwards;
}

.timeline-wrapper.animate #timeline-ball {
    opacity: 1;
    animation: fadeBallOut 0.4s linear forwards 3s;   /* fades out once the traveling dot reaches
                                                           the point along the line where the arrow
                                                           reveal begins */
}

.timeline-wrapper.animate .wave polygon {
    /* NOTE: only opacity is animated here — NOT transform/scale. This is
       deliberate: an @keyframes rule with `forwards` permanently "owns"
       whichever CSS properties it animates, for as long as the animation
       stays applied. If scale were included here, it would silently
       override the .wave polygon:hover rule above and the hover effect
       would stop working after the reveal animation finished. Keeping
       this keyframe opacity-only lets :hover freely control transform. */
    animation: arrowReveal 0.6s ease forwards 3s;
}

.timeline-wrapper.animate .point.top {
    animation: pointTopReveal 0.6s ease forwards;
}

.timeline-wrapper.animate .point.bottom {
    animation: pointBottomReveal 0.6s ease forwards;
}

/* Staggered reveal so each date pill pops in slightly after the previous
   one, left to right along the timeline. */
.timeline-wrapper.animate .point:nth-child(1) { animation-delay: 1.0s; }
.timeline-wrapper.animate .point:nth-child(2) { animation-delay: 1.4s; }
.timeline-wrapper.animate .point:nth-child(3) { animation-delay: 1.8s; }
.timeline-wrapper.animate .point:nth-child(4) { animation-delay: 2.2s; }
.timeline-wrapper.animate .point:nth-child(5) { animation-delay: 2.6s; }
.timeline-wrapper.animate .point:nth-child(6) { animation-delay: 3s; }

/* --- Story card entrance sequence (triggered by adding .active in
       script.js's renderStory(), every time a date is clicked) --- */
.story-card.active {
    opacity: 1;
    pointer-events: auto;
    user-select: auto;
}

.story-card.active #story-year {
    animation: slideLeft .9s ease forwards;
}

.story-card.active #story-title {
    animation: slideLeft .9s ease forwards .15s;
}

.story-card.active .story-image-box {
    animation: slideRight 1.1s ease forwards .3s;
}

.story-card.active .story-text-box {
    animation: slideLeft .9s ease forwards .3s;
}

.story-card.active .back-to-timeline-btn {
    animation:
        slideUpReveal 1.5s cubic-bezier(0.16, 1, 0.3, 1) forwards 1s,
        pulseGlow 2.5s infinite 1.5s;
}

/* --- Keyframe definitions --- */

@keyframes slideLeft {
    from { opacity: 0; transform: translateX(-120px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes slideRight {
    from { opacity: 0; transform: translateX(200px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes slideUpReveal {
    from { opacity: 0; transform: translateY(60px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes pulseGlow {
    0%, 100% { box-shadow: 0 0 5px rgba(59, 130, 246, 0.4); }
    50%      { box-shadow: 0 0 20px rgba(59, 130, 246, 0.8); }
}

@keyframes drawLine {
    /* Animates stroke-dashoffset from 5000 (set in the hidden state above)
       down to 0, creating a "drawing itself" effect along the wave path. */
    to { stroke-dashoffset: 0; }
}

@keyframes pointTopReveal {
    from { opacity: 0; transform: translateX(-50%) translateY(-40px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

@keyframes pointBottomReveal {
    from { opacity: 0; transform: translateX(-50%) translateY(40px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

@keyframes arrowReveal {
    /* Opacity-only — see the detailed note above at
       .timeline-wrapper.animate .wave polygon for why. */
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes fadeBallOut {
    to { opacity: 0; }
}


/* ============================================================================
   9. CONTACT SECTION
============================================================================ */
.contact-section {
    width: 94%;
    max-width: 1500px;
    margin: 0 auto;
    padding: 5rem 0;
    text-align: center;
    scroll-margin-top: 75px;
}

.contact-inner h2 {
    font-size: 2.2rem;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 1rem;
}

.contact-inner p {
    color: var(--muted);
    font-size: 1.1rem;
    max-width: 520px;
    margin: 0 auto 2rem auto;
}

.contact-actions {
    display: flex;
    justify-content: center;
    gap: 1rem;
    flex-wrap: wrap;
}

/* Contact buttons are <a> tags (they need to be real links for mailto:
   and the LinkedIn URL), styled to look like buttons — separate from the
   global `button` selector in Section 4, which only targets actual
   <button> elements. */
.btn-contact {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    padding: 14px 28px;
    border-radius: 14px;
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    cursor: pointer;
    transition: all 0.3s ease;
    border: 1px solid transparent;
}

.btn-contact-primary {
    background: var(--accent);
    color: #FFFFFF;
    box-shadow: 0 4px 14px rgba(59, 130, 246, 0.3);
}

.btn-contact-primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(59, 130, 246, 0.45);
}

.btn-contact-secondary {
    background: var(--card);
    color: var(--text);
    border-color: var(--border);
}

.btn-contact-secondary:hover {
    border-color: var(--accent);
    color: var(--accent);
    transform: translateY(-2px);
}


/* ============================================================================
   10. FOOTER
============================================================================ */
.site-footer {
    border-top: 1px solid var(--border);
    padding: 2rem 0;
    text-align: center;
    color: var(--muted);
    font-size: 0.9rem;
}


/* ============================================================================
   11. MOBILE RESPONSIVE — SIDE DRAWER NAV & FLUID TIMELINE
   ----------------------------------------------------------------------------
   Everything in this section only applies at 900px and below. It replaces
   the desktop nav with a hamburger + slide-out drawer, and makes the
   timeline's SVG/date-pills shrink fluidly using viewport-relative units
   (vw) instead of fixed pixel sizes, so they scale smoothly across very
   small screens rather than just snapping to one fixed mobile layout.
============================================================================ */

/* Hidden by default on desktop; shown only inside the @media block below. */
.mobile-menu-toggle,
.mobile-drawer,
.drawer-overlay {
    display: none;
}

@media (max-width: 900px) {

    /* ---- 11.1 Navigation & hamburger button ---- */
    .site-nav .nav-links {
        display: none !important;
    }

    .mobile-menu-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        background: transparent;
        border: none;
        color: var(--text, #ffffff);
        font-size: 1.5rem;
        cursor: pointer;
        padding: 8px;
        margin-left: 10px;
        transition: color 0.25s ease;
    }

    .mobile-menu-toggle:hover {
        color: var(--accent, #4f8cff);
    }

    /* ---- 11.2 Slide-out drawer menu + dark overlay ---- */
    .mobile-drawer {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: 0;
        right: -320px;   /* starts off-screen; .open below slides it into view */
        width: 300px;
        height: 100vh;
        background: var(--card, #121824);
        box-shadow: -10px 0 30px rgba(0, 0, 0, 0.4);
        z-index: 2000;
        transition: right 0.4s cubic-bezier(0.16, 1, 0.3, 1);
        padding: 24px;
        box-sizing: border-box;
    }

    .mobile-drawer.open {
        right: 0;
    }

    .drawer-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        padding-bottom: 20px;
        margin-bottom: 30px;
    }

    .drawer-logo {
        font-weight: 700;
        font-size: 1.2rem;
        color: var(--text, #ffffff);
    }

    .drawer-close {
        background: transparent;
        border: none;
        color: var(--text, #ffffff);
        font-size: 1.5rem;
        cursor: pointer;
        padding: 8px;
        transition: transform 0.25s ease, color 0.25s ease;
    }

    .drawer-close:hover {
        transform: rotate(90deg);
        color: var(--accent, #4f8cff);
    }

    .mobile-drawer .drawer-links {
        display: flex;
        flex-direction: column;
        gap: 20px;
        align-items: flex-start;   /* keeps each link's underline (below) bound to its own text
                                       width, rather than stretching full-width */
    }

    /* NOTE ON !important: the .mobile-drawer prefix + !important combo
       here is intentional insurance against specificity conflicts with
       the desktop .nav-links a rules earlier in the file (which share
       some property names). Not needed in most codebases, but harmless
       and kept as-is since it's already working correctly. */
    .mobile-drawer .drawer-links a {
        position: relative !important;
        display: inline-block !important;
        color: var(--text, #ffffff) !important;
        text-decoration: none !important;
        font-size: 1.2rem !important;
        font-weight: 500 !important;
        padding: 6px 0 !important;
        transition: color 0.3s ease !important;
    }

    /* Animated underline beneath each drawer link, hidden until hover. */
    .mobile-drawer .drawer-links a::after {
        content: '' !important;
        position: absolute !important;
        width: 100% !important;
        height: 2px !important;
        bottom: 0 !important;
        left: 0 !important;
        background-color: #4f8cff !important;
        transform: scaleX(0) !important;
        transform-origin: bottom center !important;
        transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
        box-shadow: 0 0 8px rgba(79, 140, 255, 0.8) !important;
        z-index: 5 !important;
    }

    .mobile-drawer .drawer-links a:hover {
        color: #4f8cff !important;
        text-shadow: 0 0 8px rgba(79, 140, 255, 0.4) !important;
    }

    .mobile-drawer .drawer-links a:hover::after {
        transform: scaleX(1) !important;
    }

    .drawer-overlay {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        background: rgba(0, 0, 0, 0.6);
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        z-index: 1999;   /* just below .mobile-drawer's z-index, so the drawer stays on top */
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease;
    }

    .drawer-overlay.open {
        opacity: 1;
        pointer-events: auto;
    }

    /* ---- 11.3 Fluid shrinking timeline ---- */
    .timeline-wrapper {
        width: 100%;
        overflow: visible;
        padding: 24px 0;   /* extra vertical breathing room so pill borders/text don't clip */
        scrollbar-width: none;
    }

    .timeline-wrapper::-webkit-scrollbar {
        display: none;
    }

    /* Locks the SVG's aspect ratio (matching its viewBox: 1900 / 220) so
       it scales down proportionally rather than distorting on narrow
       screens. */
    .timeline-svg-container {
        width: 90% !important;
        max-width: 1200px;
        margin: 0 auto !important;
        position: relative;
        aspect-ratio: 1900 / 220;
        height: auto !important;
    }

    .timeline-svg-container svg {
        width: 100% !important;
        height: auto !important;
        display: block;
    }

    .timeline-points {
        position: absolute;
        top: 0;
        left: 0;
        width: 100% !important;
        height: 100% !important;
        min-width: unset !important;
    }

    /* Date pills use viewport-width (vw) units instead of fixed px, so
       their size, padding, and border all shrink together smoothly as
       the screen gets narrower — rather than needing separate fixed
       breakpoints for every possible phone width. */
    .timeline-points .point {
        position: absolute;
        font-size: clamp(8px, 1.7vw, 14px) !important;   /* never smaller than 8px, never
                                                        larger than 14px */
        color: var(--text, #ffffff) !important;
        padding: 0.5vw 1.2vw !important;
        min-height: 3.2vw !important;
        min-width: 7vw !important;
        background-color: var(--card, #121824) !important;
        border: 0.15vw solid var(--accent, #4f8cff) !important;
        border-radius: 100px !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
        text-align: center !important;
        white-space: nowrap;
        line-height: 1 !important;
        box-sizing: border-box !important;
        transform: translate(-50%, -50%) !important;   /* centers the pill on its coordinate,
        replacing the desktop version's
        translateX(-50%)-only approach */
    }

    .timeline-points .point.top {
        top: 22% !important;
        bottom: auto !important;
    }

    .timeline-points .point.bottom {
        top: 78% !important;
        bottom: auto !important;
        padding: 0.5vw 1.2vw !important;
    }

    /* Fluid version of the "Click on it!" tooltip, same vw-based scaling
       approach as the date pills above. */
    .future-arrow-tooltip {
        display: block !important;
        position: absolute;
        left: 95% !important;
        right: auto !important;
        top: 16% !important;
        transform: translate(-50%, -50%) !important;
        font-size: 1.6vw !important;
        padding: 0.5vw 1vw !important;
        border-radius: 0.8vw !important;
        border-width: 0.15vw !important;
        white-space: nowrap;
        z-index: 10;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    }

    .future-arrow-tooltip::after {
        border-width: 0.8vw 0.8vw 0 0.8vw !important;
        bottom: -0.8vw !important;
        left: 50% !important;
        transform: translateX(-50%) !important;
    }
}


/* ============================================================================
   12. GENERAL RESPONSIVE OVERRIDES
   ----------------------------------------------------------------------------
   Separate from Section 11 — this covers layout adjustments for the hero,
   profile card, and story-card blocks that aren't specific to the nav/
   timeline system above.
============================================================================ */
@media (max-width: 900px) {
    body {
        background-size: 24px 24px, 100% 100%;   /* smaller dot-grid spacing on narrow screens */
    }

    .hero {
        padding: 2rem 0;
    }

    .profile-card,
    .story-card {
        padding: 2rem;
        width: 90%;
    }

    .profile-content {
        flex-direction: column;
        text-align: center;
        gap: 2.5rem;
    }

    .profile-photo {
        order: -1;
    }

    h1 {
        font-size: 2.5rem;
    }

    .description {
        margin: 0 auto 2rem auto;
    }

    .social-links {
        justify-content: center;
    }

    .profile-photo {
        width: min(320px, 100%);
        aspect-ratio: 1;
        height: 320px;
    }

    .story-block,
    .story-block.reverse {
        flex-direction: column;
        gap: 2rem;
    }

    .story-image-box {
        width: 100%;
    }

    .story-image-box img {
        width: 100%;
        max-width: 100%;
        height: 260px;
    }

    #story-title {
        font-size: 2rem;
    }
}