/* ==========================================================
   Jay Wadekar: shared stylesheet
   Single file. No framework, no build step, no dependencies.
   Replaces normalize.css + base.css + code.css.
   ========================================================== */

/* ---------- Design tokens ---------- */

:root {
    color-scheme: light dark;

    /* Colors. Every color in this file comes from a token.
       Palette taken from ai4astro.org: warm cream ground, blue-shifted near
       black text, blue accent. Nothing here is pure black or pure white. */
    --bg:        #f7f7f2;              /* cream */
    --surface:   #ffffff;              /* cream-2, for raised elements */
    --fg:        #162331;              /* ink */
    --fg-muted:  #55657a;

    /* Blue accent, for section rules, borders and focus rings: the places
       where it is a shape rather than a letterform. */
    --accent:    #2563eb;

    /* The reference's darker blue, for accent-coloured *text*. #2563eb is
       4.81:1 on untinted cream, which the background wash erodes to 4.54:1;
       #1d4ed8 holds 5.88:1 over the same worst-case pixel. */
    --accent-ink: #1d4ed8;
    --rule:      rgba(22, 35, 49, 0.15);
    /* Narrow mat behind the headshot, so the photo reads as a framed print
       rather than floating. Originally added because the previous headshot had
       a warm sandstone backdrop that clashed with the cool page; the current
       photo is near-neutral at its edge, so this is now framing, not a fix. */
    --mat:       #ffffff;
    --code-bg:   rgba(22, 35, 49, 0.05);

    /* Shadows tinted with the text color rather than black, and given a large
       negative spread so they sit tight under the element. Lifted from the
       ai4astro token set. */
    --shadow-card: 0 12px 22px -10px rgba(22, 35, 49, 0.14);
    --shadow-soft: 0 10px 20px rgba(22, 35, 49, 0.09);
    --radius:      0.5rem;

    /* Typography */
    --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --size-base: 17px;
    --leading:   1.65;

    /* Spacing scale: every vertical gap is a multiple of this */
    --space: 1.25rem;

    /* Layout */
    --measure: 70ch;
    --gutter:  calc(var(--space) * 1.6);

    /* ---- Background system ----
       --bg-hero is the single swappable background source. To use a photo
       instead of the gradients, redefine just this one property:

           :root { --bg-hero: url("images/bg/whatever.jpg"); }

       Nothing else needs to change: the noise, the scrim, the sizing and the
       repeat behaviour are all wired up around it below. If you do swap in a
       photo, raise --bg-scrim as well; see images/bg/README.md.

       Vertical offsets are in px, not %, so the wash is the same height on a
       short page and on the 5000px research page. */
    --bg-hero:
        radial-gradient(58rem 38rem at 82% -80px,
                        rgba(37, 99, 235, 0.055), transparent 62%),
        radial-gradient(46rem 32rem at 4% 180px,
                        rgba(37, 99, 235, 0.032), transparent 64%),
        linear-gradient(180deg, rgba(37, 99, 235, 0.028), transparent 620px);

    /* Sits between the page background and the text. Transparent while the
       background is gradients; give it a real value if --bg-hero becomes a
       photo, so body copy keeps its contrast. */
    --bg-scrim: linear-gradient(transparent, transparent);

    /* Monochrome fractal noise, generated inline. Breaks up the flat gradient
       banding that large low-contrast gradients show on 8-bit displays. The
       opacity lives inside the SVG rather than on an element, so it tints the
       backdrop without touching the text drawn over it. */
    --bg-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.032'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
    :root {
        /* The reference has no dark mode; it uses these same tokens for its
           dark *sections*. --deep becomes the page ground and --green-light
           the accent, which is the swap it already makes over dark panels. */
        --bg:       #0c2340;               /* deep */
        --surface:  #16386b;               /* deep-2 */
        --fg:       #e6ecf5;
        --fg-muted: #93a7c4;
        --rule:     rgba(255, 255, 255, 0.18);
        --mat:      rgba(255, 255, 255, 0.14);
        --code-bg:  rgba(255, 255, 255, 0.07);

        /* #2563eb is far too dark over this ground. #38bdf8 is the reference's
           own on-dark accent and measures 7.37:1, so text and rules can share
           one value here. */
        --accent:   #38bdf8;
        --accent-ink: #38bdf8;

        --shadow-card: 0 12px 22px -10px rgba(0, 0, 0, 0.5);
        --shadow-soft: 0 10px 20px rgba(0, 0, 0, 0.35);

        /* Same three layers in the lightened accent. Slightly stronger than
           the light-mode values because a tint of this size is less visible
           against a dark ground. */
        --bg-hero:
            radial-gradient(58rem 38rem at 82% -80px,
                            rgba(56, 189, 248, 0.075), transparent 62%),
            radial-gradient(46rem 32rem at 4% 180px,
                            rgba(56, 189, 248, 0.045), transparent 64%),
            linear-gradient(180deg, rgba(56, 189, 248, 0.03), transparent 620px);

        /* Noise is more visible on a dark ground, so it is dialled back. */
        --bg-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.022'/%3E%3C/svg%3E");
    }
}

/* ---------- Minimal reset ---------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body,
h1, h2, h3,
p, ul, ol, figure, blockquote {
    margin: 0;
}

img {
    max-width: 100%;
    height: auto;
}

/* Video embeds carry hardcoded width="560" height="315" in the markup,
   which overflows narrow viewports. Scale them with the column instead,
   holding 16:9, and keep 560px as the ceiling on wide screens. */
iframe {
    display: block;
    width: 100%;
    max-width: 560px;
    height: auto;
    aspect-ratio: 16 / 9;
    border: 0;
}

/* ---------- Base typography ---------- */

html {
    font-size: var(--size-base);
}

body {
    background-color: var(--bg);
    /* Layer order, front to back: noise, scrim, hero. */
    background-image: var(--bg-noise), var(--bg-scrim), var(--bg-hero);
    background-repeat: repeat, no-repeat, no-repeat;
    background-size: 160px 160px, cover, cover;
    background-position: 0 0, center top, center top;
    /* Deliberately not `fixed`: iOS Safari handles fixed backgrounds badly,
       and anchoring to the viewport makes the tint follow the reader down a
       long page. Scrolling with the document keeps it a masthead wash that
       fades out once you are into the content. */
    background-attachment: scroll, scroll, scroll;
    color: var(--fg);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: var(--leading);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

p {
    margin: 0 0 var(--space);
}

p:last-child {
    margin-bottom: 0;
}

h1 {
    font-size: 1.9rem;
    line-height: 1.2;
    font-weight: 600;
    letter-spacing: -0.01em;
}

h2 {
    font-size: 1.2rem;
    line-height: 1.3;
    font-weight: 600;
    margin: 0 0 var(--space);
}

h3 {
    font-size: 1.05rem;
    font-weight: 600;
    margin: calc(var(--space) * 1.5) 0 calc(var(--space) * 0.4);
}

small {
    font-size: 0.82rem;
    color: var(--fg-muted);
}

code, pre, tt {
    font-family: var(--font-mono);
    font-size: 0.88em;
    background: var(--code-bg);
    border-radius: 3px;
}

code, tt {
    padding: 0.1em 0.35em;
}

pre {
    padding: var(--space);
    overflow-x: auto;
    margin: 0 0 var(--space);
}

pre code {
    background: none;
    padding: 0;
}

/* ---------- Links ---------- */

a {
    color: var(--accent-ink);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    transition: opacity 0.15s ease-in-out;
}

a:hover,
a:focus {
    opacity: 0.7;
}

a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

/* ---------- Layout ---------- */

.content {
    max-width: var(--measure);
    margin: 0 auto;
    padding: calc(var(--space) * 2.4) var(--gutter) calc(var(--space) * 3);
}

/* ---------- Header and nav ---------- */

header {
    margin: 0 0 calc(var(--space) * 2);
}

header h1 {
    margin: 0 0 var(--space);
}

header h1 a {
    color: var(--fg);
    text-decoration: none;
}

header h1 a:hover {
    opacity: 1;
    color: var(--accent-ink);
}

nav ul {
    list-style: none;
    padding: 0 0 calc(var(--space) * 0.6);
    margin: 0;
    border-bottom: 1px solid var(--rule);
    display: flex;
    flex-wrap: wrap;
    gap: 0 calc(var(--space) * 1.1);
}

nav li {
    margin: 0;
}

nav a {
    text-decoration: none;
    color: var(--fg-muted);
    font-size: 0.94rem;
}

nav a:hover {
    color: var(--accent-ink);
    opacity: 1;
}

/* Current page */
nav a.active {
    color: var(--accent-ink);
    font-weight: 600;
}

/* ---------- Headshot ---------- */

.headshot {
    float: right;
    width: 180px;
    max-width: 180px;
    height: auto;
    border-radius: 6px;
    margin: 0 0 var(--space) calc(var(--space) * 1.4);
    padding: 5px;
    background: var(--mat);
    box-shadow: var(--shadow-soft);
}

/* ---------- Sections ---------- */

section {
    margin: 0 0 calc(var(--space) * 2);
}

/* Rule between sections, in the accent color */
section + section {
    border-top: 1px solid var(--accent);
    padding-top: calc(var(--space) * 2);
}

section ul {
    padding-left: 1.25em;
    margin: 0 0 var(--space);
}

section ul.plain {
    list-style: none;
    padding-left: 0;
}

section li {
    margin: 0 0 calc(var(--space) * 0.5);
}

/* ---------- Figures ---------- */

figure {
    margin: calc(var(--space) * 1.5) 0;
    text-align: center;
}

figcaption {
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--fg-muted);
    text-align: left;
    margin-top: calc(var(--space) * 0.5);
}

/* Data-heavy plots need more room than the text measure. These bleed
   symmetrically past the column and stay inside the viewport, replacing
   the old hand-tuned negative margins that assumed a 600px column. */
figure.wide {
    width: min(94vw, 1080px);
    max-width: none;
    margin-left: calc((100% - min(94vw, 1080px)) / 2);
    margin-right: 0;
}

/* Same symmetric bleed, held back a little. For single plots that carry their
   own legend and do not need the full width of a multi-panel compilation. */
figure.mid {
    width: min(84vw, 900px);
    max-width: none;
    margin-left: calc((100% - min(84vw, 900px)) / 2);
    margin-right: 0;
}

/* ---------- Section-header pattern ---------- */

/* Small uppercase label above a heading. Adapted from the reference site,
   scaled down: this is a faculty page, so the heading below it stays at the
   existing h2 size rather than jumping to 3rem. */
.eyebrow {
    display: block;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--accent-ink);
    margin: 0 0 calc(var(--space) * 0.35);
}

.eyebrow + h2 {
    margin-bottom: calc(var(--space) * 0.6);
}

/* The opening line is the page's claim, not a section label, so it carries
   more weight than the h2s below it, but well short of the reference site's
   3rem, which would read as a product landing page. */
h2.lead {
    font-size: 1.5rem;
    line-height: 1.25;
    letter-spacing: -0.015em;
    margin-bottom: calc(var(--space) * 0.9);
}

/* Short standfirst under a section heading */
.section-intro {
    color: var(--fg-muted);
    margin: 0 0 calc(var(--space) * 1.2);
}

/* ---------- Row pattern (news, software, people, collaborators) ---------- */

/* Distinct typographic tiers built from two sizes plus muting, following the
   reference site's lecture-row hierarchy. */

/* Dated list entries (News) */
.date {
    color: var(--fg-muted);
    font-variant-numeric: tabular-nums;
    margin-right: 0.5em;
}

/* Software entries */
.project-name {
    font-weight: 600;
}

/* Tier-3 line: role, affiliation, or any secondary metadata */
.meta {
    display: block;
    font-size: 0.88rem;
    color: var(--fg-muted);
}

/* People rows. Photos are optional: with no <img> the row collapses to a
   flat text entry with no reserved gap and no placeholder box. */
ul.people {
    list-style: none;
    padding-left: 0;
    margin: 0 0 var(--space);
}

ul.people li {
    display: flex;
    align-items: flex-start;
    gap: var(--space);
    margin: 0 0 calc(var(--space) * 0.9);
}

ul.people img {
    flex: 0 0 auto;
    width: 72px;
    height: 72px;
    object-fit: cover;
    border-radius: var(--radius);
    box-shadow: var(--shadow-soft);
}

.person-name {
    font-weight: 600;
}

/* Long people lists in two columns. Grid rather than CSS columns so each
   entry stays whole instead of being split across the column break. */
ul.people.two-col {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--gutter);
}

@media (max-width: 700px) {
    ul.people.two-col {
        grid-template-columns: 1fr;
    }
}

/* ---------- Topic tags ---------- */

/* Frequency-weighted term list. Rendered as real text at varying size rather
   than as a generated image, so it stays selectable, searchable, scalable and
   readable by a screen reader. --w runs 0 (rarest) to 1 (most common). */
ul.topics {
    list-style: none;
    padding-left: 0;
    margin: 0 0 var(--space);
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35em 0.9em;
    line-height: 1.5;
}

ul.topics li {
    margin: 0;
    font-size: calc(0.85rem + (var(--w) * 0.75rem));
    color: color-mix(in srgb, var(--fg) calc(45% + (var(--w) * 55%)), transparent);
}

/* ---------- Unwritten copy ---------- */

/* Deliberately loud. These are placeholders for Jay to write; if one ever
   reaches the live site it should be impossible to miss. */
.todo {
    display: block;
    border-left: 3px solid var(--accent);
    padding: 0.15em 0 0.15em 0.75em;
    color: var(--fg-muted);
    font-style: italic;
}

.todo::before {
    content: "TODO ";
    font-style: normal;
    font-weight: 700;
    letter-spacing: 0.08em;
    font-size: 0.78rem;
    color: var(--accent-ink);
}

/* ---------- Footer ---------- */

footer {
    margin: calc(var(--space) * 2.5) 0 0;
    padding-top: calc(var(--space) * 1.2);
    border-top: 1px solid var(--rule);
    font-size: 0.9rem;
    color: var(--fg-muted);
}

/* Grouped columns, collapsing to a single column on narrow screens. */
.footer-cols {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: var(--space) var(--gutter);
    margin: 0 0 calc(var(--space) * 1.5);
}

.footer-title {
    font-size: 0.74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--fg-muted);
    margin: 0 0 calc(var(--space) * 0.5);
}

footer ul {
    list-style: none;
    padding-left: 0;
    margin: 0;
}

footer li {
    margin: 0 0 calc(var(--space) * 0.25);
}

.copyright {
    padding-top: var(--space);
    border-top: 1px solid var(--rule);
    font-size: 0.84rem;
}

@media (max-width: 700px) {
    .footer-cols {
        grid-template-columns: 1fr;
    }
}

/* ---------- Small screens ---------- */

@media (max-width: 700px) {
    :root {
        --gutter: var(--space);
    }

    h1 {
        font-size: 1.6rem;
    }

    /* Headshot stacks and centers */
    .headshot {
        float: none;
        display: block;
        margin: 0 auto var(--space);
    }

    nav ul {
        gap: 0 calc(var(--space) * 0.85);
    }
}
