/* ==========================================================================
   Design tokens — Microsoft palette
   The four logo squares are used as accents to signal the tech stack; the
   Fluent "communication blue" carries interactive elements.
   ========================================================================== */

:root {
    /* Microsoft logo squares */
    --ms-red: #F25022;
    --ms-green: #7FBA00;
    --ms-blue: #00A4EF;
    --ms-yellow: #FFB900;

    /* Translucent versions for background washes. Defined here so no colour
       literal exists outside :root. */
    --ms-red-wash: rgba(242, 80, 34, .13);
    --ms-green-wash: rgba(127, 186, 0, .15);
    --ms-blue-wash: rgba(0, 164, 239, .13);
    --ms-yellow-wash: rgba(255, 185, 0, .16);

    /* Fluent communication blue — primary interactive colour */
    --primary: #0078D4;
    --primary-hover: #106EBE;
    --primary-active: #005A9E;
    --primary-subtle: #DEECF9;

    /* Fluent neutrals */
    --grey-190: #201F1E;
    --grey-160: #323130;
    --grey-130: #605E5C;
    --grey-90: #8A8886;
    --grey-60: #C8C6C4;
    --grey-30: #EDEBE9;
    --grey-20: #F3F2F1;
    --white: #FFFFFF;

    /* Semantic */
    --bg: var(--white);
    --bg-subtle: var(--grey-20);
    --surface: var(--white);

    /* Card background, separate from --surface so the header, form inputs and
       pills keep a fixed colour. Cards alternate against their section instead:
       a card must contrast with whatever it sits on, and the page alternates
       plain and tinted sections. See the .section-alt override below. */
    --card: var(--grey-20);
    --text: var(--grey-190);
    --text-muted: var(--grey-130);
    --border: var(--grey-30);

    --header-height: 4rem;
    --content-max: 68rem;

    --radius: 4px;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .08), 0 2px 4px rgba(0, 0, 0, .04);
    --shadow-md: 0 2px 4px rgba(0, 0, 0, .10), 0 8px 16px rgba(0, 0, 0, .06);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #1B1A19;
        --bg-subtle: #252423;
        /* Must stay distinct from --bg-subtle. Cards sit on tinted sections, so
           when these matched, only a 1px border separated a card from its
           background and nothing read as a surface. Lighter rather than darker:
           in a dark theme, elevation reads as lighter, and the cards already
           carry a hover shadow. */
        --surface: #2E2D2C;
        --card: #2E2D2C;
        --text: #F3F2F1;
        --text-muted: #C8C6C4;
        --border: #3B3A39;
        --primary: #2899F5;
        --primary-hover: #4FADF7;
        --primary-subtle: #10334F;
    }

}

/* Cards contrast with whatever section they sit on, flipping direction rather
   than holding one colour. On a plain section the card is the lighter tone; on
   a tinted section it is the darker one. That is the conventional light-mode
   pattern (white cards on grey, grey cards on white) and gives equal separation
   in dark mode without a card ever matching its own background — which is what
   happened when a single value had to serve both. */
.section-alt {
    --card: var(--white);
}

@media (prefers-color-scheme: dark) {
    .section-alt {
        --card: #1B1A19;
    }
}

/* ==========================================================================
   Reset & base
   ========================================================================== */

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

html {
    scroll-behavior: smooth;
    /* Anchor targets clear the sticky header instead of hiding under it. */
    scroll-padding-top: calc(var(--header-height) + 1rem);
}

body {
    margin: 0;
    font-family: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    margin: 0 0 .5em;
    line-height: 1.25;
    font-weight: 600;
    letter-spacing: -.01em;
}

h1 { font-size: clamp(2rem, 5vw, 3rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2rem); }
h3 { font-size: 1.25rem; }

p { margin: 0 0 1rem; }

a {
    color: var(--primary);
    text-decoration: none;
}

a:hover { color: var(--primary-hover); text-decoration: underline; }

/* Visible keyboard focus everywhere — never remove without a replacement. */
:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

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

code {
    font-family: 'Cascadia Code', Consolas, 'Courier New', monospace;
    font-size: .9em;
    background: var(--bg-subtle);
    padding: .15em .4em;
    border-radius: var(--radius);
}

/* ==========================================================================
   Shared building blocks
   ========================================================================== */

.container {
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    padding-inline: 1.5rem;
}

/* The four Microsoft squares, used as a brand mark and section marker. */
.ms-squares {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2px;
    width: 1.5rem;
    height: 1.5rem;
    flex: none;
}

.ms-squares span { display: block; border-radius: 1px; }
.ms-squares span:nth-child(1) { background: var(--ms-red); }
.ms-squares span:nth-child(2) { background: var(--ms-green); }
.ms-squares span:nth-child(3) { background: var(--ms-blue); }
.ms-squares span:nth-child(4) { background: var(--ms-yellow); }

/* Four-colour rule used to separate major regions. */
.ms-rule {
    height: 3px;
    border: 0;
    margin: 0;
    background: linear-gradient(to right,
        var(--ms-red) 0 25%,
        var(--ms-green) 25% 50%,
        var(--ms-blue) 50% 75%,
        var(--ms-yellow) 75% 100%);
}

.btn {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .625rem 1.25rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}

.btn-primary {
    background: var(--primary);
    color: var(--white);
}

.btn-primary:hover { background: var(--primary-hover); color: var(--white); text-decoration: none; }
.btn-primary:active { background: var(--primary-active); }

.btn-secondary {
    background: transparent;
    color: var(--text);
    border-color: var(--grey-90);
}

.btn-secondary:hover { background: var(--bg-subtle); text-decoration: none; }

/* Tech stack pill. Accent colour is set per-item so the stack reads as the
   Microsoft palette rather than a single flat colour. */
.tech-pill {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem .75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: .875rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.tech-pill::before {
    content: "";
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: var(--accent, var(--primary));
    flex: none;
}

/* Accent classes rather than inline style attributes — the CSP sets
   style-src 'self', which blocks style="" by design.
   One per project page; the four logo colours are the whole set. */
.accent-red { --accent: var(--ms-red); --accent-wash: var(--ms-red-wash); }
.accent-green { --accent: var(--ms-green); --accent-wash: var(--ms-green-wash); }
.accent-blue { --accent: var(--ms-blue); --accent-wash: var(--ms-blue-wash); }
.accent-yellow { --accent: var(--ms-yellow); --accent-wash: var(--ms-yellow-wash); }

.not-found {
    padding-block: clamp(3rem, 9vw, 6rem);
    max-width: 40rem;
}

.not-found-code {
    margin: 0;
    font-size: clamp(3.5rem, 12vw, 6rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.04em;
    color: var(--grey-60);
}

/* ==========================================================================
   Blazor framework UI
   ========================================================================== */

.valid.modified:not([type=checkbox]) { outline: 1px solid var(--ms-green); }
.invalid { outline: 1px solid var(--ms-red); }
.validation-message { color: var(--ms-red); font-size: .875rem; }

#blazor-error-ui {
    background: var(--ms-yellow);
    color: var(--grey-190);
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, .2);
    display: none;
    left: 0;
    padding: .6rem 1.25rem .7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: .75rem;
    top: .5rem;
}

.blazor-error-boundary {
    background: var(--ms-red);
    padding: 1rem;
    color: var(--white);
    border-radius: var(--radius);
}

.blazor-error-boundary::after { content: "An error has occurred."; }

/* Startup loading indicator, recoloured to the palette. */
.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

.loading-progress circle {
    fill: none;
    stroke: var(--grey-30);
    stroke-width: .5rem;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.loading-progress circle:last-child {
    stroke: var(--primary);
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
    transition: stroke-dasharray .05s ease-in-out;
}

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: 600;
    color: var(--text-muted);
    inset: calc(20vh + 3.25rem) 0 auto 0;
}

.loading-progress-text:after { content: var(--blazor-load-percentage-text, "Loading"); }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
