/* ==================================================
   KAUSHIK VISHWAKARMA
   Portfolio v2
   Part 1 — Reset, Base & Navigation
================================================== */

/* ---------- RESET ---------- */

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

    /* Site-wide theme transition — background/text/border only, so
       switching light↔dark fades colour without touching layout or
       any element's own transform/shadow transitions below. */
    transition:background-color .25s ease, color .25s ease, border-color .25s ease;
}

:root{

    /* Apple-style deceleration curve — quick start, long soft settle */
    --ease-out-apple:cubic-bezier(.16,1,.3,1);

    color-scheme:light;

    /* ---------- THEME — LIGHT (default) ---------- */
    --bg:#F7F3EE;
    --surface:#F5F0EA;
    --text:#181818;
    --muted:#5f5f5f;
    /* Was #8b8b8b, which sat at 3.08:1 on --bg — below AA for every
       place it's used (nav links, eyebrows, work numbers, footer, the
       impact labels and pipeline arrows), none of which qualify for the
       large-text exemption. #6f6f6f clears 4.5:1 and stays clearly
       recessed from --muted. Dark mode's value already passes at ~5.8:1
       and is left alone. */
    --muted-2:#6f6f6f;
    --border:#e4ded3;
    --button-border:#cfc7be;
    --ink-contrast:#ffffff;
    --ink-hover:#000000;
    --nav-bg:rgba(247,243,238,.70);
    --nav-bg-scrolled:rgba(247,243,238,.88);
    --scrollbar-track:#EFEAE4;
    --scrollbar-thumb:#B9B2AA;
    --scrollbar-thumb-hover:#8F8880;

}

/* ---------- THEME — DARK ---------- */
/* Deliberately not a straight inversion — a warm charcoal editorial
   palette, not pure black. Toggled by JS via [data-theme] on <html>. */
[data-theme="dark"]{

    color-scheme:dark;

    --bg:#121212;
    --surface:#181818;
    --text:#F5F3EF;
    --muted:#ADA79C;
    --muted-2:#948E82;
    --border:#2A2A2A;
    --button-border:#3A3A3A;
    --ink-contrast:#121212;
    --ink-hover:#ffffff;
    --nav-bg:rgba(18,18,18,.72);
    --nav-bg-scrolled:rgba(18,18,18,.88);
    --scrollbar-track:#1C1C1C;
    --scrollbar-thumb:#3A3A3A;
    --scrollbar-thumb-hover:#55534D;

}

/* Logo/wordmark only — never used for body copy, nav, or headings */
@font-face{
    font-family:"Midstar";
    src:url("Fonts/Midstar_Personal_Use.otf") format("opentype");
    font-weight:400;
    font-style:normal;
    font-display:swap;
}

html{
    scroll-behavior:smooth;

    /* <nav> is position:fixed, so without this every in-page jump —
       the menu links, the Impact section's bridge link to #work —
       parked the target heading underneath the nav bar. */
    scroll-padding-top:110px;
}

body{
    font-family:"Manrope",sans-serif;
    background:var(--bg);
    color:var(--text);
    overflow-x:hidden;
    line-height:1.8;
}

img{
    display:block;
    width:100%;
}

a{
    text-decoration:none;
    color:inherit;
}

::selection{
    background:var(--text);
    color:var(--ink-contrast);
}

/* ---------- LAYOUT ---------- */

section{
    width:min(1180px,90%);
    margin:auto;
    /* Was 72px — every section-to-section transition compounded to
       144px of dead space (this section's bottom + the next one's
       top), which read as wasted air rather than intentional rhythm.
       64px keeps the same consistent, editorial cadence everywhere
       while tightening that compounded gap to 128px. */
    padding:64px 0;
}

/* Major headings — highly legible, modern, not decorative. Body copy,
   nav, buttons, labels and the logo stay on their own fonts below. */
h1,h2,h3{
    font-family:"DM Sans",sans-serif;
}

h2{
    font-size:56px;
    font-weight:700;
    letter-spacing:-2px;
    margin-bottom:18px;
}

p{
    font-size:20px;
    color:var(--muted);
    line-height:1.9;
}

/* ---------- NAVIGATION ---------- */

nav{

    position:fixed;

    top:0;
    left:0;

    width:100%;

    padding:16px 0;

    line-height:1;

    background:var(--nav-bg);

    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);

    border-bottom:1px solid var(--border);

    z-index:999;

    transition:.35s;

}

/* Same width:min(1180px,90%) column every section and the footer
   use — keeps the logo and menu lined up with the rest of the
   site's left/right edges instead of nav tracking viewport % on
   its own formula. */
.nav-inner{

    width:min(1180px,90%);

    margin:auto;

    display:flex;
    justify-content:space-between;
    align-items:center;

}

.logo a{

    display:flex;

    align-items:center;

}

.logo img{

    display:block;

    height:34px;

    width:auto;

}

/* The mark is solid black on a transparent ground — invert it to
   white in dark mode rather than shipping a second file. */
[data-theme="dark"] .logo img{

    filter:invert(1);

}

.menu{

    display:flex;

    gap:36px;

}

.menu a{

    position:relative;

    font-size:15px;

    font-weight:600;

    color:var(--muted-2);

    transition:.3s;

}

.menu a:hover{

    color:var(--text);

}

.menu a::after{

    content:"";

    position:absolute;

    left:0;
    bottom:-6px;

    width:0;

    height:2px;

    background:var(--text);

    transition:.3s;

}

.menu a:hover::after,
.menu a.active::after{

    width:100%;

}

/* ---------- MOBILE MENU ---------- */

.menu-toggle{

    display:none;

    flex-direction:column;

    gap:6px;

    cursor:pointer;

}

.menu-toggle span{

    width:28px;

    height:2px;

    background:var(--text);

    transition:.3s;

}
/* ==================================================
   HERO
================================================== */

.hero{

    width:min(1180px,90%);

    margin:auto;

    /* Was min-height:84vh — on any display taller than the hero's own
       content (most laptop/desktop screens), that reserved a fixed
       slice of the viewport regardless of what the content actually
       needed, leaving a dead gap before "About". Sizing from padding
       instead means the hero is exactly as tall as its content plus
       one section-unit of breathing room, on every screen. */
    display:grid;

    grid-template-columns:1.15fr .85fr;

    gap:90px;

    align-items:center;

    padding:78px 0 64px;

}

.hero.small-hero{

    grid-template-columns:1fr;

    min-height:auto;

    padding-bottom:60px;

}

.hero-text{

    animation:fadeUp 1s ease;

}

.eyebrow{

    text-transform:uppercase;

    letter-spacing:4px;

    font-size:12px;

    font-weight:700;

    color:var(--muted-2);

    margin-bottom:22px;

}

.intro{

    max-width:560px;

    font-size:21px;

    line-height:1.9;

    color:var(--muted);

    margin-bottom:42px;

}

.hero-buttons{

    display:flex;

    gap:18px;

    flex-wrap:wrap;

}

.button{

    display:inline-flex;

    align-items:center;

    justify-content:center;

    padding:16px 34px;

    border-radius:999px;

    background:var(--text);

    color:var(--ink-contrast);

    font-weight:700;

    transition:.35s ease;

}

.button:hover{

    transform:translateY(-3px);

    background:var(--ink-hover);

}

.button.secondary{

    background:transparent;

    color:var(--text);

    border:1px solid var(--button-border);

}

.button.secondary:hover{

    background:var(--text);

    color:var(--ink-contrast);

    border-color:var(--text);

}

/* ---------- HERO IMAGE ---------- */

.hero-image{

    width:100%;

    max-width:420px;

    justify-self:end;

    border-radius:28px;

    overflow:hidden;

    background:var(--surface);

    box-shadow:0 30px 80px rgba(0,0,0,.12);

}

.hero-image img{

    width:100%;

    aspect-ratio:4/5;

    object-fit:cover;

    transition:transform .7s ease;

}

.hero-image:hover img{

    transform:scale(1.04);

}

/* ---------- HERO ANIMATION ---------- */

@keyframes fadeUp{

    from{

        opacity:0;

        transform:translateY(40px);

    }

    to{

        opacity:1;

        transform:translateY(0);

    }

}
/* ==================================================
   PART 3 — ABOUT, WORK & FEATURED
================================================== */

/* ---------- ABOUT ---------- */

#about p{

    max-width:820px;

    font-size:21px;

    margin-bottom:28px;

}

#about p:last-child{

    margin-bottom:0;

}

/* ---------- WORK ---------- */

.work-intro{

    max-width:520px;

}

.work-grid{

    display:grid;

    grid-template-columns:repeat(3,1fr);

    /* Cards keep their own natural height instead of stretching to
       match the tallest one — otherwise a card with a longer caption
       (e.g. Journal) would force dead space into the shorter ones. */
    align-items:start;

    gap:28px;

    margin-top:32px;

}

.work-card{

    background:var(--surface);
    backdrop-filter:blur(18px);
    border:1px solid var(--border);

}

.work-card:hover{

    transform:translateY(-10px);
    box-shadow:0 22px 55px rgba(0,0,0,.12);

}

.work-card img{

    width:100%;

    height:260px;

    object-fit:cover;

}

.work-info{

    padding:28px;

}

.work-info h3{

    font-size:30px;

    color:var(--text);

    margin-bottom:12px;

}

.work-info p{

    font-size:17px;

    color:var(--muted);

}

/* Selected Work only — scoped to #work so journal.html's identical
   .work-card markup (its "Latest Entries" grid) is unaffected.

   Drops the boxed-card chrome in favour of large image / minimal
   metadata: no background, no border, no whole-card lift on hover —
   the photograph is the only thing that moves, so nothing competes
   with it and nothing is ever overlaid or filtered on top of it. */
#work .work-card{

    background:transparent;

    backdrop-filter:none;

    border:none;

    border-radius:20px;

    overflow:hidden;

}

#work .work-card:hover{

    transform:none;

    box-shadow:none;

}

/* Visible only for keyboard focus, not mouse clicks — matches the
   .frames-track ring so the whole homepage shares one focus style. */
#work .work-card:focus-visible{

    outline:2px solid var(--text);
    outline-offset:4px;

}

#work .work-card img{

    height:440px;

    transition:transform .8s var(--ease-out-apple);

}

#work .work-card:hover img{

    transform:scale(1.035);

}

#work .work-info{

    padding:18px 2px 0;

}

/* Small editorial index (01/02/03) — same uppercase/tracked language
   as .eyebrow, just smaller and unbolded so it reads as a caption
   detail rather than a second section label. */
#work .work-number{

    display:block;

    text-transform:uppercase;
    letter-spacing:3px;
    font-size:11px;
    font-weight:500;
    font-variant-numeric:tabular-nums;
    color:var(--muted-2);

    margin-bottom:10px;

}

#work .work-info h3{

    font-size:21px;

    margin-bottom:4px;

}

#work .work-info p{

    font-size:15px;

}

/* ---------- FEATURED STORY ---------- */

/* Slightly more room than the standard section rhythm — this is the
   one deliberately "editorial feature" moment on the homepage. */
#featured{

    /* Was 100px — kept proportionally larger than the 64px base
       rhythm (this is still the one deliberate "editorial feature"
       moment), just no longer so much larger that it doubles up with
       the sections on either side into a visibly oversized gap. */
    padding:88px 0;

    display:grid;

    /* The photograph is a tall portrait crop — giving it slightly
       less width (rather than an even 1fr/1fr split) lets it read as
       an intentional portrait rather than a stretched square, and
       gives the longer paragraph a little more room to breathe. */
    grid-template-columns:.92fr 1.08fr;

    gap:70px;

    align-items:center;

}

.featured-image{

    overflow:hidden;

    border-radius:26px;

    box-shadow:0 20px 60px rgba(0,0,0,.08);

}

.featured-image img{

    transition:transform .8s ease;

}

.featured-image:hover img{

    transform:scale(1.05);

}

.featured-content h2{

    /* A step above the standard h2 (56px / 40px on mobile) — this is
       the one section meant to feel like a feature rather than a
       category header — but scaled at the same breakpoint as every
       other heading, so the relationship holds at every size. */
    font-size:64px;

    margin:18px 0 24px;

}

.featured-content p{

    margin-bottom:34px;

    max-width:540px;

}
/* ==================================================
   PART 4 — GALLERY, JOURNAL, CONTACT & FOOTER
================================================== */

/* ---------- GALLERY ---------- */

#gallery p{

    margin-bottom:36px;

    max-width:700px;

}

.masonry{

    columns:3 320px;

    column-gap:20px;

}

.masonry img{

    width:100%;

    margin-bottom:20px;

    border-radius:22px;

    display:block;

    cursor:pointer;

    break-inside:avoid;

    transition:
        transform .6s var(--ease-out-apple),
        opacity .6s var(--ease-out-apple),
        filter .6s var(--ease-out-apple),
        box-shadow .35s ease;

    box-shadow:0 10px 30px rgba(0,0,0,.08);

}

.masonry img:hover{

    transform:translateY(-6px) scale(1.02);

    opacity:.95;

}

/* ---------- THE CONTACT SHEET (horizontal gallery) ---------- */
/* A simple native overflow-x strip, not scroll-jacked — smoother and
   far more robust across devices than mapping vertical scroll to
   horizontal movement. Scrolls within its own container only, so the
   page always returns to normal vertical scrolling right after it. */

.frames-track{

    /* Single source of truth for the strip's height — every frame
       reads its own width from this via its natural aspect ratio,
       so a portrait, a landscape and a square frame can sit side by
       side without ever being forced into the same box. */
    --frame-height:440px;

    display:flex;

    align-items:center;

    gap:20px;

    height:calc(var(--frame-height) + 16px);

    margin-top:32px;

    overflow-x:auto;
    overflow-y:hidden;

    scroll-snap-type:x proximity;
    -webkit-overflow-scrolling:touch;

    padding-bottom:16px;

}

.frames-track img{

    flex:0 0 auto;

    /* Height is fixed, width is intrinsic — each photograph keeps its
       own natural proportions instead of being cropped to match its
       neighbours. */
    height:var(--frame-height);
    width:auto;

    border-radius:20px;

    scroll-snap-align:start;

    box-shadow:0 10px 30px rgba(0,0,0,.1);

    transition:transform .5s var(--ease-out-apple);

}

.frames-track img:hover{

    transform:scale(1.03);

}

.frames-track:focus-visible{

    outline:2px solid var(--text);
    outline-offset:4px;

}

.frames-track::-webkit-scrollbar{

    height:6px;

}

.frames-track::-webkit-scrollbar-track{

    background:var(--scrollbar-track);

}

.frames-track::-webkit-scrollbar-thumb{

    background:var(--scrollbar-thumb);
    border-radius:50px;

}

/* ---------- LIGHTBOX ---------- */

#lightbox{

    position:fixed;

    inset:0;

    display:flex;

    justify-content:center;

    align-items:center;

    background:rgba(10,10,10,.92);

    opacity:0;

    visibility:hidden;

    transition:.35s;

    z-index:9999;

}

#lightbox.active{

    opacity:1;

    visibility:visible;

}

#lightbox img{

    width:auto;

    height:auto;

    max-width:92vw;

    max-height:92vh;

    object-fit:contain;

    border-radius:18px;

    box-shadow:0 30px 80px rgba(0,0,0,.35);

}

/* ---------- JOURNAL ---------- */

#journal{

    text-align:center;

}

#journal p{

    max-width:760px;

    margin:0 auto 32px;

}

/* ---------- CONTACT ---------- */

#contact{

    text-align:center;

}

#contact p{

    margin-bottom:22px;

}

#contact .intro{

    margin-left:auto;

    margin-right:auto;

}

#contact strong{

    color:var(--text);

    font-size:18px;

}

#contact .button{

    margin-top:25px;

}

/* ---------- FOOTER ---------- */

footer{

    width:min(1180px,90%);

    margin:auto;

    padding:56px 0;

    border-top:1px solid var(--border);

    display:flex;

    justify-content:space-between;

    align-items:center;

    flex-wrap:wrap;

    gap:20px;

}

footer p{

    font-size:15px;

    color:var(--muted-2);

}
/* ==================================================
   PART 5 — RESPONSIVE, ANIMATIONS & FINISHING TOUCHES
================================================== */

/* ---------- SCROLL ANIMATION ---------- */

.hidden{

    opacity:0;

    transform:translateY(56px) scale(.97);

    filter:blur(8px);

    transition:all 1.1s var(--ease-out-apple);

    will-change:opacity, transform, filter;

}

.show{

    opacity:1;

    transform:translateY(0) scale(1);

    filter:blur(0);

}

@media (prefers-reduced-motion:reduce){

    .hidden{

        opacity:0;

        transform:none;

        filter:none;

        transition:opacity .4s ease;

    }

    .show{

        /* opacity MUST be restated here. `.hidden` is redeclared a few
           lines above, i.e. *after* the base `.show{opacity:1}` rule and
           at the same specificity — and every revealed element carries
           both classes. Without this line the later `.hidden{opacity:0}`
           wins the cascade and the whole page stays invisible for
           reduced-motion visitors. */
        opacity:1;

        transform:none;

        filter:none;

    }

    /* All hover/scroll-driven scale effects — the discrete hover
       state can stay, but nothing should visibly animate into it. */
    .hero-image img,
    .featured-image img,
    .masonry img,
    #work .work-card img,
    .frames-track img,
    .theme-toggle-icon{

        transition:none;

    }

    .hero-image:hover img,
    .featured-image:hover img,
    .masonry img:hover,
    #work .work-card:hover img,
    .frames-track img:hover{

        transform:none;

    }

    /* Horizontal gallery: keep it usable, just remove the snap
       "pull" some users find disorienting under reduced motion. */
    .frames-track{

        scroll-snap-type:none;

    }

}

/* ---------- STICKY NAVIGATION ---------- */

nav.scrolled{

    background:var(--nav-bg-scrolled);

    backdrop-filter:blur(24px);

    -webkit-backdrop-filter:blur(24px);

    box-shadow:0 10px 40px rgba(0,0,0,.06);

}

/* ---------- BUTTONS ---------- */

.button{

    transition:
        transform .35s ease,
        box-shadow .35s ease,
        background .35s ease,
        color .35s ease;

}

.button:hover{

    transform:translateY(-4px);

    box-shadow:0 15px 35px rgba(0,0,0,.12);

}

/* ---------- SMOOTH IMAGES ---------- */

img{

    user-select:none;

    -webkit-user-drag:none;

}

/* ---------- MOBILE ---------- */

@media (max-width:900px){

nav{

    padding:14px 0;

}

.menu{

    position:absolute;

    top:50px;

    left:0;

    width:100%;

    background:var(--bg);

    flex-direction:column;

    gap:24px;

    padding:30px;

    display:none;

    border-bottom:1px solid var(--border);

}

.menu.active{

    display:flex;

}

.menu-toggle{

    display:flex;

}

.hero{

    grid-template-columns:1fr;

    gap:55px;

    padding-top:82px;

    min-height:auto;

}

.hero-image{

    justify-self:center;

    max-width:340px;

}

.intro{

    font-size:18px;

}

.hero-buttons{

    flex-direction:column;

    align-items:flex-start;

}

.button{

    width:100%;

    justify-content:center;

}

section{

    padding:42px 0;

}

h2{

    font-size:40px;

}

.featured-content h2{

    font-size:46px;

}

.work-grid{

    grid-template-columns:1fr;

}

#work .work-card img{

    height:320px;

}

.frames-track{

    --frame-height:300px;

}

#featured{

    padding:56px 0;

    grid-template-columns:1fr;

    gap:40px;

}

.masonry{

    columns:2 180px;

}

footer{

    flex-direction:column;

    text-align:center;

}

}

/* ---------- SMALL PHONES ---------- */

@media (max-width:600px){

.masonry{

    columns:1;

}

.frames-track{

    --frame-height:220px;

    gap:14px;

}

.logo img{

    height:28px;

}

}

/* ---------- LARGE DISPLAYS ---------- */

@media (min-width:1500px){

.hero,
section,
footer,
.nav-inner{

    width:1280px;

}

}

/* ---------- SCROLLBAR ---------- */

::-webkit-scrollbar{

    width:10px;

}

::-webkit-scrollbar-track{

    background:var(--scrollbar-track);

}

::-webkit-scrollbar-thumb{

    background:var(--scrollbar-thumb);

    border-radius:50px;

}

::-webkit-scrollbar-thumb:hover{

    background:var(--scrollbar-thumb-hover);

}
/* ==========================
   HERO TITLE FINAL
========================== */

.hero h1{
    /* .hero h1 already outranks the global h1,h2,h3 rule on
       specificity alone (class+element beats a bare element
       selector), so none of this needs !important. */
    font-family:"DM Sans",sans-serif;
    /* Fluid between the same floor/ceiling the old breakpoints used
       (36px mobile → 62px desktop) — smooth instead of stepped. */
    font-size:clamp(36px, 24px + 3.2vw, 62px);
    font-weight:700;
    line-height:1.05;
    letter-spacing:-0.02em;
    color:var(--text);
    margin-bottom:24px;
}
/* ==================================================
   PART 6 — IMPACT / "WORK, IN NUMBERS"
================================================== */

/* ---------- PASTEL TINT SYSTEM ----------
   Ported from the featured-story pages (same mechanism, same hex
   values — a modifier class alongside a component sets --tint-bg /
   --tint-border / --tint-accent, which the component reads with a
   var() fallback to the site's normal surface/border/text). This is
   the first place it's used on the homepage itself; keep any future
   additions here in sync with the *-story.css files' tint sets so the
   whole site keeps reading as one system. */

/* The accents are a step darker than the featured-story files' originals
   (#4E7B99 / #7C67A6 / #5C8A55 / #A9843A / #B97A52). Those were picked
   as decorative rules and borders, but here they also colour the 12px
   uppercase .impact-label / .capability-label, where they landed between
   3.0:1 and 4.1:1 — under AA, and worst on the two hero cards, which
   have no tint background at all and put the accent straight onto --bg.
   These values clear 4.8:1 on both the tint background and the page
   background while keeping the same hue. Borders and backgrounds are
   unchanged, so the section's colour still reads identically. */

.tint-blue{ --tint-bg:#E7EEF3; --tint-border:rgba(78,123,153,.28); --tint-accent:#3F6580; }
.tint-lavender{ --tint-bg:#EFEAF6; --tint-border:rgba(124,103,166,.28); --tint-accent:#63508A; }
.tint-sage{ --tint-bg:#E9F1E6; --tint-border:rgba(92,138,85,.28); --tint-accent:#456B40; }
.tint-cream{ --tint-bg:#F6EFDD; --tint-border:rgba(180,145,58,.32); --tint-accent:#7D6023; }
.tint-peach{ --tint-bg:#F5E8DE; --tint-border:rgba(185,122,82,.3); --tint-accent:#8F5834; }

[data-theme="dark"] .tint-blue{ --tint-bg:rgba(110,160,190,.10); --tint-border:rgba(143,180,204,.3); --tint-accent:#8FB4CC; }
[data-theme="dark"] .tint-lavender{ --tint-bg:rgba(170,145,210,.10); --tint-border:rgba(179,155,214,.3); --tint-accent:#B39BD6; }
[data-theme="dark"] .tint-sage{ --tint-bg:rgba(140,190,125,.10); --tint-border:rgba(143,191,128,.3); --tint-accent:#9BC384; }
[data-theme="dark"] .tint-cream{ --tint-bg:rgba(215,180,100,.10); --tint-border:rgba(216,185,104,.32); --tint-accent:#D8B968; }
[data-theme="dark"] .tint-peach{ --tint-bg:rgba(210,150,110,.10); --tint-border:rgba(217,155,114,.32); --tint-accent:#D99B72; }

/* Text for screen readers only. Used to give the counting numbers a
   stable spoken value, since their visible text churns frame by frame
   while the count-up runs. */

.sr-only{

    position:absolute;
    width:1px;
    height:1px;
    padding:0;
    margin:-1px;
    overflow:hidden;
    clip-path:inset(50%);
    white-space:nowrap;
    border:0;

}

/* ---------- HEADLINE + INTRO ---------- */

.impact-statement-hero{

    font-size:clamp(38px,5.2vw,72px);
    font-weight:800;
    /* No h2 rule sets a line-height, so this was inheriting body's 1.8
       — at 72px that put ~58px of air between the two lines and broke
       the statement into two unrelated phrases. */
    line-height:1.1;
    letter-spacing:-.02em;
    max-width:800px;

}

.impact-intro{

    max-width:600px;

    margin-bottom:56px;

}

/* ---------- PRIMARY METRICS ----------
   Two dominant, borderless numbers (the actual "editorial scale"
   moment) plus two smaller, tinted stat call-outs underneath — visual
   variation through scale and treatment rather than four identical
   boxes. */

.impact-grid{

    display:grid;

    grid-template-columns:repeat(4,1fr);

    gap:28px 32px;

    align-items:start;

}

.impact-card{

    display:flex;

    flex-direction:column;

    gap:8px;

}

.impact-card--hero{

    grid-column:span 2;

}

.impact-grid > .impact-card:not(.impact-card--hero){

    grid-column:span 2;

    background:var(--tint-bg,var(--surface));
    border:1px solid var(--tint-border,var(--border));
    border-radius:20px;
    padding:26px 28px;

    transition:transform .5s var(--ease-out-apple);

}

.impact-grid > .impact-card:not(.impact-card--hero):hover{

    transform:translateY(-5px);

}

/* The hover rule above is more specific than `.hidden`, so while a card
   is still revealing it would otherwise override `.hidden`'s
   `transition:all` and leave opacity/blur un-animated — the card would
   pop into view at full strength and only *then* slide up, which is
   exactly what the stagger in Script.js exists to prevent. Restating the
   reveal transition at matching specificity keeps the entrance intact;
   Script.js drops `.hidden` once it finishes, handing hover back to the
   faster rule above. */
.impact-grid > .impact-card.hidden:not(.impact-card--hero){

    transition:all 1.1s var(--ease-out-apple);

}

.impact-rule{

    display:block;
    width:52px;
    height:3px;
    border-radius:2px;
    background:var(--tint-accent,var(--text));
    margin:4px 0 2px;

}

.impact-value{

    font-family:"DM Sans",sans-serif;
    font-weight:800;
    letter-spacing:-2px;
    line-height:1;
    color:var(--text);

}

.impact-card--hero .impact-value{

    font-size:clamp(60px,8vw,124px);

}

.impact-grid > .impact-card:not(.impact-card--hero) .impact-value{

    font-size:44px;
    display:inline-block;

}

/* The "<50" card is the one value that isn't purely numeric. At
   -2px tracking the chevron collides with the 5 and reads as a stray
   mark, so this variant relaxes the letter-spacing back to neutral. */

.impact-value--static{

    letter-spacing:-1px;

}

.impact-value-row{

    display:flex;
    align-items:baseline;
    gap:8px;

}

.impact-unit{

    font-family:"DM Sans",sans-serif;
    font-size:20px;
    font-weight:700;
    color:var(--muted-2);

}

.impact-label{

    text-transform:uppercase;

    letter-spacing:2.5px;

    font-size:12px;

    font-weight:700;

    color:var(--tint-accent,var(--muted-2));

}

.impact-caption{

    font-size:15.5px;

    line-height:1.7;

    color:var(--muted);

    max-width:38ch;

}

/* ---------- FULL-STACK PIPELINE ----------
   The one deliberate "signature" moment in this section — a single
   continuous line rather than a checklist, so it reads as one person
   moving through the whole process rather than a list of skills. */

.pipeline{

    margin-top:72px;
    padding-top:48px;
    border-top:1px solid var(--border);

}

.pipeline-label{

    text-transform:uppercase;
    letter-spacing:3px;
    font-size:12px;
    font-weight:700;
    color:var(--muted-2);
    margin-bottom:22px;

}

/* ---------- THE TIMELINE ----------
   The eight stages sit on one rail that never wraps, because the claim
   the section is making is continuity: a brief goes in one end and a
   finished file comes out the other without changing hands. A wrapped
   list would read as a skills inventory instead. */

.timeline{

    position:relative;
    padding-top:22px;

}

.timeline-rail{

    position:absolute;
    top:0;
    left:0;
    right:0;
    height:2px;

    border-radius:2px;
    background:var(--border);

}

.timeline-progress{

    display:block;
    width:0;
    height:100%;

    border-radius:2px;
    background:var(--text);

    transition:width 1.9s var(--ease-out-apple);

}

/* The playhead is the leading edge of the progress bar rather than a
   separate travelling element, so the two can never drift apart. */
.timeline-progress::after{

    content:"";

    position:absolute;
    top:50%;
    right:0;

    width:9px;
    height:9px;

    border-radius:50%;
    background:var(--text);

    transform:translate(50%,-50%);

}

.timeline-track{

    display:grid;
    /* minmax(0,1fr), not 1fr — a bare 1fr floors at the content's
       min-width, so one nowrap label could widen the whole track and
       push the page sideways on a narrow phone. */
    grid-template-columns:repeat(8,minmax(0,1fr));

    list-style:none;
    gap:8px;

}

.timeline-stage{

    display:flex;
    flex-direction:column;
    align-items:center;
    gap:10px;

    text-align:center;

    /* Each stage lights up as the playhead reaches it. The delay is
       set per-stage in Script.js so the sweep and the reveal stay in
       step no matter how many stages a page has. */
    opacity:.4;
    transition:opacity .5s ease;

}

.pipeline.is-playing .timeline-stage{

    opacity:1;

}

.pipeline.is-playing .timeline-progress{

    width:100%;

}

.stage-icon{

    display:flex;
    align-items:center;
    justify-content:center;

    width:46px;
    height:46px;

    border-radius:50%;
    border:1px solid var(--border);
    background:var(--surface);

    color:var(--text);

}

.stage-icon svg{

    width:22px;
    height:22px;

}

.stage-name{

    font-family:"DM Sans",sans-serif;
    font-weight:700;
    font-size:12px;
    letter-spacing:.4px;
    color:var(--muted);

    /* The names are short by design so eight of them fit one line at
       every width — "Photo", not "Photography". */
    white-space:nowrap;

}

/* ---------- SECONDARY CAPABILITY CARDS ---------- */

.capability-grid{

    display:grid;
    grid-template-columns:repeat(5,1fr);
    gap:16px;
    margin-top:56px;

}

.capability-card{

    background:var(--tint-bg,var(--surface));
    border:1px solid var(--tint-border,var(--border));
    border-radius:16px;
    padding:22px 20px;

    transition:transform .5s var(--ease-out-apple);

}

.capability-card:hover{

    transform:translateY(-5px);

}

/* Same cascade fix as the impact cards above — `.capability-card` is
   declared after `.hidden` at equal specificity, so the reveal needs
   the extra class to win it back. */
.capability-grid > .capability-card.hidden{

    transition:all 1.1s var(--ease-out-apple);

}

.capability-label{

    display:block;
    text-transform:uppercase;
    letter-spacing:1.5px;
    font-size:12px;
    font-weight:700;
    color:var(--tint-accent,var(--text));
    margin-bottom:8px;

}

.capability-card p{

    font-size:14.5px;
    line-height:1.55;
    color:var(--muted);

}

/* ---------- FILM GRID (films.html) ----------
   Written ahead of the markup that uses it: films.html ships its embed
   block commented out, so these rules are what make it work the moment
   a real video is pasted in. Same card language as .work-card, with a
   fixed 16:9 well so a YouTube/Vimeo iframe needs no styling of its
   own and the grid can't shift as embeds load. */

.film-grid{

    display:grid;
    grid-template-columns:repeat(2,1fr);
    gap:32px;
    margin-top:8px;

}

.film-card{

    background:var(--surface);
    border:1px solid var(--border);
    border-radius:20px;
    overflow:hidden;

    transition:transform .5s var(--ease-out-apple);

}

.film-card:hover{

    transform:translateY(-5px);

}

.film-embed{

    position:relative;
    aspect-ratio:16 / 9;
    background:var(--bg);

}

.film-embed iframe,
.film-embed video{

    position:absolute;
    inset:0;

    width:100%;
    height:100%;

    border:0;
    display:block;

}

.film-meta{

    padding:22px 24px 26px;

}

.film-client{

    display:block;
    text-transform:uppercase;
    letter-spacing:1.5px;
    font-size:11px;
    font-weight:700;
    color:var(--muted-2);
    margin-bottom:8px;

}

.film-meta h3{

    font-size:22px;
    letter-spacing:-.01em;
    margin-bottom:8px;

}

.film-meta p{

    font-size:15.5px;
    line-height:1.7;
    color:var(--muted);

}

@media (max-width:900px){

    .film-grid{ grid-template-columns:1fr; gap:24px; }

}

/* ---------- GEAR CARDS (photography.html) ----------
   These had markup and reveal/stagger hooks in Script.js but no styling
   at all, so they rendered as three bare stacked blocks. Built on the
   same surface + border + hover-lift as .capability-card above so the
   inner page reads as the same system as the homepage. */

.projects{

    display:grid;
    grid-template-columns:repeat(3,1fr);
    gap:20px;
    margin-top:8px;

}

.project{

    background:var(--surface);
    border:1px solid var(--border);
    border-radius:16px;
    padding:26px 24px;

    transition:transform .5s var(--ease-out-apple);

}

.project:hover{

    transform:translateY(-5px);

}

.projects > .project.hidden{

    transition:all 1.1s var(--ease-out-apple);

}

.project h3{

    font-size:15px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:1.5px;
    margin-bottom:10px;

}

.project p{

    font-size:15.5px;
    line-height:1.7;
    color:var(--muted);

}

@media (max-width:900px){

    .projects{ grid-template-columns:repeat(2,1fr); }

}

@media (max-width:600px){

    .projects{ grid-template-columns:1fr; }

}

/* ---------- R FOR RABBIT — CREDIT CARD ----------
   A credit block, not a stat bar: client, title, spec line, one-line
   note. The whole thing is a link, so the accent rail doubles as the
   hover and focus affordance. */

.credit{

    display:flex;
    align-items:stretch;
    gap:26px;

    margin-top:56px;
    /* No vertical padding on the card itself — that lives on
       .credit-body, so the rail can run the full height of the card
       instead of floating inside it. */
    padding:0 34px 0 0;

    border-radius:22px;
    background:var(--surface);
    border:1px solid var(--border);

    overflow:hidden;
    color:var(--text);

    transition:transform .5s var(--ease-out-apple),
               border-color .3s ease;

}

.credit:hover{

    transform:translateY(-4px);
    border-color:var(--tint-border,var(--button-border));

}

/* The rail is the card's only colour. It widens on hover, which reads
   as the card leaning toward you without moving any text. */
.credit-rail{

    flex:0 0 auto;
    width:6px;

    align-self:stretch;
    background:var(--text);

    transition:width .4s var(--ease-out-apple);

}

.credit:hover .credit-rail,
.credit:focus-visible .credit-rail{

    width:12px;

}

.credit-body{

    display:block;
    padding:32px 0 32px 8px;

}

.credit-eyebrow{

    display:block;

    text-transform:uppercase;
    letter-spacing:2.5px;
    font-size:11px;
    font-weight:700;
    color:var(--muted-2);

    margin-bottom:8px;

}

.credit-name{

    display:flex;
    align-items:center;
    gap:10px;

    font-family:"DM Sans",sans-serif;
    font-weight:800;
    font-size:clamp(26px,3.4vw,38px);
    letter-spacing:-.02em;
    line-height:1.1;

    margin-bottom:18px;

}

.credit-arrow{

    width:19px;
    height:19px;

    color:var(--muted-2);

    transition:transform .4s var(--ease-out-apple),color .3s ease;

}

.credit:hover .credit-arrow{

    transform:translate(3px,-3px);
    color:var(--text);

}

.credit-stats{

    display:flex;
    flex-wrap:wrap;
    gap:10px 26px;

    font-size:13px;
    font-weight:600;
    letter-spacing:.3px;
    text-transform:uppercase;
    color:var(--muted-2);

    margin-bottom:14px;

}

.credit-stats strong{

    font-family:"DM Sans",sans-serif;
    font-weight:800;
    font-size:20px;
    letter-spacing:-.02em;
    text-transform:none;
    color:var(--text);
    margin-right:5px;

}

.credit-caption{

    display:block;

    font-size:14.5px;
    line-height:1.7;
    color:var(--muted);
    max-width:62ch;

}

/* ---------- BRIDGE TO SELECTED WORK ----------
   The section's one loud moment, and the only inverted block on the
   page. --page-w is the viewport width *without* the scrollbar, set by
   Script.js; 100vw would include it and push the page sideways. The
   fallback keeps the band inside the section if the script never runs
   rather than letting it break the layout. */

.bridge{

    /* Read with a var() fallback rather than declaring --page-w here —
       a local declaration would shadow the real value Script.js sets on
       <html> and the band would silently stay section-width. */
    width:var(--page-w,100%);
    margin-left:calc(50% - var(--page-w,100%) / 2);
    margin-top:80px;

    padding:72px 24px;

    background:var(--text);
    color:var(--bg);

    text-align:center;

}

.bridge-line{

    font-family:"DM Sans",sans-serif;
    font-weight:800;
    font-size:clamp(28px,4.4vw,52px);
    letter-spacing:-.02em;
    line-height:1.12;
    color:var(--bg);

    max-width:16ch;
    margin:0 auto 28px;

}

.bridge-link{

    display:inline-flex;
    align-items:center;
    gap:10px;

    padding:15px 30px;

    border-radius:999px;
    border:1px solid var(--bg);

    font-weight:700;
    font-size:16px;
    color:var(--bg);

    transition:background .35s var(--ease-out-apple),
               color .35s var(--ease-out-apple);

}

.bridge-link svg{

    width:18px;
    height:18px;

    transition:transform .4s var(--ease-out-apple);

}

.bridge-link:hover{

    background:var(--bg);
    color:var(--text);

}

.bridge-link:hover svg{

    transform:translateX(4px);

}

.bridge-link:focus-visible{

    outline:2px solid var(--bg);
    outline-offset:4px;

}

/* ---------- IMPACT — RESPONSIVE ---------- */

@media (max-width:900px){

.impact-grid{

    grid-template-columns:repeat(2,1fr);

}

.impact-card--hero,
.impact-grid > .impact-card:not(.impact-card--hero){

    grid-column:span 2;

}

.capability-grid{

    grid-template-columns:repeat(2,1fr);

}

/* Icons stay full size longer than the labels do — the glyph is what
   carries the stage at a glance, the word only confirms it. */
.stage-icon{ width:40px; height:40px; }
.stage-icon svg{ width:19px; height:19px; }
.stage-name{ font-size:11px; }

}

@media (max-width:600px){

.impact-statement-hero{

    font-size:36px;

}

.impact-grid{

    grid-template-columns:1fr;

    gap:36px;

}

.impact-card--hero,
.impact-grid > .impact-card:not(.impact-card--hero){

    grid-column:span 1;

}

.impact-card--hero .impact-value{

    font-size:clamp(52px,17vw,76px);

}

.pipeline{

    margin-top:56px;
    padding-top:36px;

}

/* The timeline stays one line on phones rather than wrapping or
   scrolling — wrapping would turn it back into the skills list it
   replaced, and scrolling would hide half the pipeline behind a
   gesture nobody knows to make. Instead the cells go fluid: the
   columns are capped at minmax(0,1fr) so no label can widen the grid,
   and the icon and type scale with the viewport down to ~320px. */

.timeline{

    padding-top:18px;

}

.timeline-track{

    gap:4px;

}

.stage-icon{

    width:clamp(30px,8.6vw,38px);
    height:clamp(30px,8.6vw,38px);

}

.stage-icon svg{

    width:clamp(15px,4.3vw,18px);
    height:clamp(15px,4.3vw,18px);

}

.stage-name{

    font-size:clamp(8px,2.35vw,11px);
    letter-spacing:0;

}

.capability-grid{

    grid-template-columns:1fr;

    margin-top:44px;

}

.credit{

    gap:18px;
    padding:0 22px 0 0;

}

.credit-body{

    padding:26px 0 26px 6px;

}

.credit-stats{

    gap:8px 18px;

}

.bridge{

    margin-top:64px;
    padding:56px 20px;

}

}
/* ==================================================
   PART 7 — DARK MODE TOGGLE
================================================== */

.theme-toggle{

    position:fixed;

    bottom:24px;
    right:24px;

    z-index:1000;

    width:46px;
    height:46px;

    border-radius:50%;

    display:flex;
    align-items:center;
    justify-content:center;

    background:var(--surface);
    border:1px solid var(--border);
    color:var(--text);

    box-shadow:0 8px 24px rgba(0,0,0,.14);

    cursor:pointer;

    transition:
        transform .3s var(--ease-out-apple),
        background-color .25s ease,
        border-color .25s ease,
        box-shadow .25s ease;

}

.theme-toggle:hover{

    transform:translateY(-3px);

    box-shadow:0 12px 30px rgba(0,0,0,.18);

}

.theme-toggle:focus-visible{

    outline:2px solid var(--text);
    outline-offset:3px;

}

/* Both icons stay in the DOM and cross-fade/rotate between states,
   instead of an instant display:none swap — .theme-toggle's own
   position:fixed already gives these an anchor to centre against. */
.theme-toggle-icon{

    position:absolute;
    top:50%;
    left:50%;

    width:20px;
    height:20px;

    opacity:0;

    transform:translate(-50%,-50%) rotate(-90deg) scale(.6);

    transition:opacity .35s ease, transform .35s var(--ease-out-apple);

}

.theme-toggle-icon--moon{

    opacity:1;

    transform:translate(-50%,-50%) rotate(0deg) scale(1);

}

[data-theme="dark"] .theme-toggle-icon--sun{

    opacity:1;

    transform:translate(-50%,-50%) rotate(0deg) scale(1);

}

[data-theme="dark"] .theme-toggle-icon--moon{

    opacity:0;

    transform:translate(-50%,-50%) rotate(90deg) scale(.6);

}

@media (max-width:600px){

.theme-toggle{

    bottom:18px;
    right:18px;

    width:42px;
    height:42px;

}

.theme-toggle-icon{

    width:18px;
    height:18px;

}

}

/* ==================================================
   PART 8 — HOME BUTTON (secondary pages)

   Journal, Photography and similar top level pages sit one click
   from Home via the nav, but that link is easy to miss once you're
   scrolled deep into a grid. This gives those pages their own,
   unmissable way back — a floating circular button, opposite corner
   from the theme toggle, so the two never compete for attention.
   Deliberately not the plain "← Back to Home" text link the review
   articles use one level down; this is a distinct affordance for a
   different kind of page.
================================================== */

.home-toggle{

    position:fixed;

    bottom:24px;
    left:24px;

    z-index:1000;

    width:46px;
    height:46px;

    border-radius:50%;

    display:flex;
    align-items:center;
    justify-content:center;

    background:var(--surface);
    border:1px solid var(--border);
    color:var(--text);

    box-shadow:0 8px 24px rgba(0,0,0,.14);

    transition:
        transform .3s var(--ease-out-apple),
        background-color .25s ease,
        border-color .25s ease,
        box-shadow .25s ease;

}

.home-toggle:hover{

    transform:translateY(-3px) translateX(-2px);

    box-shadow:0 12px 30px rgba(0,0,0,.18);

}

.home-toggle:focus-visible{

    outline:2px solid var(--text);
    outline-offset:3px;

}

.home-toggle svg{

    width:20px;
    height:20px;

}

@media (max-width:600px){

.home-toggle{

    bottom:18px;
    left:18px;

    width:42px;
    height:42px;

}

.home-toggle svg{

    width:18px;
    height:18px;

}

}

/* ==================================================
   PART 9 — REDUCED MOTION, CONTINUED

   The main reduced-motion block lives at the top of Part 5, but Parts
   6-8 (impact, theme toggle, home button) are all authored *below* it,
   so their equal-specificity motion rules would otherwise win the
   cascade. Anything with a transition or transform added after Part 5
   belongs here, not up there.
================================================== */

@media (prefers-reduced-motion:reduce){

    /* Anchor jumps land instantly instead of gliding — the single most
       common reduced-motion complaint on a one-page site like this. */
    html{

        scroll-behavior:auto;

    }

    /* The hero's entrance animation still ran on every page load. */
    .hero-text{

        animation:none;

    }

    /* Hover lifts: keep the colour/border change, drop the movement. */
    .impact-grid > .impact-card:not(.impact-card--hero),
    .capability-card,
    .project,
    .film-card,
    .credit,
    .credit-rail,
    .credit-arrow,
    .bridge-link svg,
    .work-card,
    .button,
    .theme-toggle,
    .home-toggle,
    .timeline-progress,
    .timeline-stage{

        transition:none;

    }

    .impact-grid > .impact-card:not(.impact-card--hero):hover,
    .capability-card:hover,
    .project:hover,
    .film-card:hover,
    .credit:hover,
    .work-card:hover,
    .button:hover,
    .theme-toggle:hover,
    .home-toggle:hover{

        transform:none;

    }

    .credit:hover .credit-arrow,
    .bridge-link:hover svg{

        transform:none;

    }

}