/*
    albiegolf.app

    Hand-written, no build step. Colors come from tokens.css, which is generated from the app's
    Resources/Styles/Colors.xaml, so a palette change happens in one place and reaches both.

    Dark only, deliberately, and not a preference: Colors.xaml says the app is dark because the
    video is the subject and a bright chrome washes out in sun. A site that flipped to white under
    prefers-color-scheme would be a different product's site above the fold.

    The type scale mirrors Resources/Styles/Styles.xaml, scaled up for a page read at arm's length
    rather than held: Space Grotesk Bold for headings, Inter for everything else.
*/

@import url('tokens.css');

/* ── Fonts ───────────────────────────────────────────────────────────────── */
/* Subsetted from Resources/Fonts by tools/site/fonts.mjs. Self-hosted: a site arguing that
   nothing leaves your phone should not open by asking Google for two files. */

@font-face {
    font-family: 'Space Grotesk';
    src: url('fonts/space-grotesk-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Inter';
    src: url('fonts/inter-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Inter';
    src: url('fonts/inter-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

/* ── Base ────────────────────────────────────────────────────────────────── */

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

:root {
    color-scheme: dark;

    --font-display: 'Space Grotesk', system-ui, sans-serif;
    --font-sans: 'Inter', system-ui, -apple-system, sans-serif;

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-24: 6rem;

    --radius: 18px;
    --radius-sm: 12px;

    --measure: 66ch;
}

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

body {
    min-height: 100dvh;
    font-family: var(--font-sans);
    font-size: 1.0625rem;
    line-height: 1.6;
    color: var(--text-primary);
    background-color: var(--surface-base);
    background-image: var(--ground);
    background-repeat: no-repeat;
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img,
picture,
svg {
    display: block;
    max-width: 100%;
}

input,
button,
textarea,
select {
    font: inherit;
}

/* ── Typography ──────────────────────────────────────────────────────────── */

h1,
h2,
h3 {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
    text-wrap: balance;
}

h1 {
    font-size: clamp(2.25rem, 6vw, 3.25rem);
}

h2 {
    font-size: clamp(1.5rem, 3.5vw, 1.875rem);
    margin-top: var(--space-12);
    margin-bottom: var(--space-4);
}

h3 {
    font-size: 1.1875rem;
    margin-top: var(--space-8);
    margin-bottom: var(--space-2);
}

p,
ul,
ol,
dl {
    max-width: var(--measure);
}

p + p,
p + ul,
p + ol,
ul + p,
ol + p {
    margin-top: var(--space-4);
}

li + li {
    margin-top: var(--space-2);
}

ul,
ol {
    padding-left: 1.25em;
}

li::marker {
    color: var(--text-muted);
}

strong {
    font-weight: 600;
    color: var(--text-primary);
}

a {
    color: var(--trace);
    text-decoration-color: color-mix(in srgb, var(--trace) 45%, transparent);
    text-underline-offset: 0.2em;
    transition: text-decoration-color 150ms ease;
}

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

/* The eyebrow from Styles.xaml: 11px, uppercase, tracked out. The site's only small-caps label. */
.eyebrow {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/*
    The third line of the tagline, mirroring the idle screen in SwingPage.xaml: "One swing. One fix."
    on its own is finite, and sounds like Albie diagnoses you once and you are done. This resolves it
    into a loop, and it is the only place on the page where headline weight and the accent color meet.

    Sized at half the heading, which is what 17pt against the 34pt Display style is in the app.
*/
/*
    Block, with the glyph inline inside it, rather than a flex row. Flex is one rule away from
    stacking the two if this element is ever seen with an older albie.css, and an unhashed
    stylesheet guarantees that happens for a minute after every deploy. Inline layout puts them
    side by side in every state, including no stylesheet at all.
*/
.tagline-loop {
    display: block;
    margin-top: var(--space-2);
    font-size: clamp(1.125rem, 3vw, 1.625rem);
    color: var(--trace);
    letter-spacing: -0.01em;
}

/*
    The ↻ in front of it, drawn rather than typed. The app uses the character at U+21BB, the same
    glyph as "Hear it again", and neither Space Grotesk nor Inter contains it: as text the browser
    would fall back to whatever the device has, at a weight and width nobody chose, beside a 52px
    heading. Drawn as a path it inherits the color, scales with the text, and is identical on every
    device. Sized and weighted to sit with Space Grotesk Bold rather than to be a UI icon.
*/
.loop-glyph {
    display: inline-block;
    vertical-align: -0.1em;
    margin-right: 0.28em;
    width: 0.82em;
    height: 0.82em;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Solid rather than two stroked arms: at 20px a V-shaped head merges into the arc it sits on. */
.loop-glyph .head {
    fill: currentColor;
    stroke: none;
}

.lede {
    font-size: clamp(1.125rem, 2.5vw, 1.3125rem);
    line-height: 1.5;
    color: var(--text-secondary);
    max-width: 34ch;
    text-wrap: pretty;
}

.muted {
    color: var(--text-secondary);
}

.small {
    font-size: 0.9375rem;
}

/* ── Layout ──────────────────────────────────────────────────────────────── */

.page {
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-height: 100dvh;
}

.wrap {
    width: 100%;
    max-width: 68rem;
    margin-inline: auto;
    padding-inline: var(--space-6);
}

/* Privacy and support are documents, not layouts. Narrower, and the measure does the rest. */
.wrap--prose {
    max-width: 46rem;
}

/*
    Top padding only. Sections stack on the landing page, so a symmetric block would compound into
    an 8rem trench between every two of them; the footer's own margin closes the bottom of the page.
*/
.section {
    padding-top: var(--space-16);
}

/* A section leads with its eyebrow, so the heading under one owns no margin of its own. */
.eyebrow + h2 {
    margin-top: var(--space-2);
}

/* ── Header and footer ───────────────────────────────────────────────────── */

.site-header {
    padding-block: var(--space-6);
}

.site-header .wrap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
}

/* The wordmark carries the one dot of Trace, the same mark the store screenshots use. */
.wordmark {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    text-decoration: none;
}

.wordmark::before {
    content: '';
    width: 0.44em;
    height: 0.44em;
    border-radius: 50%;
    background: var(--trace);
}

.site-nav {
    display: flex;
    gap: var(--space-6);
    font-size: 0.9375rem;
}

.site-nav a {
    color: var(--text-secondary);
    text-decoration: none;
}

.site-nav a:hover,
.site-nav a[aria-current='page'] {
    color: var(--text-primary);
}

.site-footer {
    margin-top: var(--space-24);
    padding-block: var(--space-8);
    border-top: 1px solid var(--hairline);
    color: var(--text-muted);
    font-size: 0.9375rem;
}

.site-footer .wrap {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
}

.site-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-6);
}

.site-footer a {
    color: var(--text-secondary);
    text-decoration: none;
}

.site-footer a:hover {
    color: var(--text-primary);
}

/* ── Components ──────────────────────────────────────────────────────────── */

/*
    BorderStrong rather than the fill does the work here, exactly as in the app: SurfaceRaised sits
    at 1.09:1 against SurfaceBase, so the edge is the only thing that makes a card a card.
*/
.card {
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface-raised);
    padding: var(--space-6);
}

.card > * + * {
    margin-top: var(--space-3);
}

.card h2,
.card h3 {
    margin-top: 0;
}

.card--narrow {
    max-width: 34rem;
}

.card-title {
    font-size: 1.1875rem;
    margin-top: 0;
    margin-bottom: var(--space-2);
}

/*
    The only utilities on the site, and the reason they exist rather than a style attribute: the
    Content-Security-Policy in staticwebapp.config.json has no 'unsafe-inline', so an inline style
    is silently dropped in production and looks fine in a local file:// preview.
*/
.mt-2 { margin-top: var(--space-2); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mt-12 { margin-top: var(--space-12); }

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 3.25rem;
    padding: var(--space-3) var(--space-8);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-primary);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease;
}

.btn:hover {
    background: var(--surface-raised);
}

.btn:active {
    transform: scale(0.98);
}

/* One bright element per view. If a page has a primary button, that is the one. */
.btn--primary {
    background: var(--trace);
    border-color: var(--trace);
    color: var(--text-on-accent);
}

.btn--primary:hover {
    background: var(--trace-dim);
    border-color: var(--trace-dim);
}

/*
    The nine faults. Three columns of plain text with a rule over each, and deliberately not nine
    cards: a card says "feature", and these are one list of things the detector looks for. No accent
    color either. Nine bright markers would be nine bright elements, and the page allows one.
*/
.faults {
    display: grid;
    /* 17rem lands on three columns at full width, which is the only count that divides nine evenly. */
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    gap: var(--space-6);
    list-style: none;
    padding: 0;
    max-width: none;
    margin-top: var(--space-8);
}

.faults li {
    margin-top: 0;
    padding-top: var(--space-4);
    border-top: 1px solid var(--hairline);
    color: var(--text-secondary);
}

/* The one sentence a section is really making. Sized between the body and a heading. */
.pull {
    font-family: var(--font-display);
    font-size: clamp(1.25rem, 2.6vw, 1.625rem);
    line-height: 1.25;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    max-width: 28ch;
    text-wrap: balance;
}

/* A definition list is what a privacy summary actually is: a term and what it means. */
.facts {
    display: grid;
    gap: var(--space-4);
    max-width: var(--measure);
}

.facts > div {
    display: grid;
    gap: var(--space-1);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--hairline);
}

.facts dt {
    font-weight: 600;
}

.facts dd {
    color: var(--text-secondary);
}

/* Numbered steps, for the setup guide. The number is the only shape on the line. */
.steps {
    list-style: none;
    padding: 0;
    counter-reset: step;
    max-width: var(--measure);
}

.steps li {
    position: relative;
    padding-left: 2.75rem;
    counter-increment: step;
}

.steps li + li {
    margin-top: var(--space-6);
}

.steps li::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: 0.1em;
    display: grid;
    place-items: center;
    width: 1.875rem;
    height: 1.875rem;
    border: 1px solid var(--border-strong);
    border-radius: 50%;
    font-family: var(--font-display);
    font-size: 0.9375rem;
    color: var(--text-secondary);
}

/* FAQ and troubleshooting. <details> so it works with JavaScript switched off, because there is none. */
details {
    border-bottom: 1px solid var(--hairline);
    padding-block: var(--space-4);
    max-width: var(--measure);
}

summary {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

summary::-webkit-details-marker {
    display: none;
}

summary::after {
    content: '+';
    font-family: var(--font-display);
    color: var(--text-muted);
    flex: none;
}

details[open] summary::after {
    content: '–';
}

details[open] summary {
    margin-bottom: var(--space-3);
}

details > *:not(summary) {
    color: var(--text-secondary);
}

/* ── Accessibility ───────────────────────────────────────────────────────── */

:focus-visible {
    outline: 2px solid var(--trace);
    outline-offset: 3px;
    border-radius: 4px;
}

.skip-link {
    position: absolute;
    left: var(--space-4);
    top: -4rem;
    z-index: 10;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--trace);
    color: var(--text-on-accent);
    font-weight: 600;
    text-decoration: none;
    transition: top 150ms ease;
}

.skip-link:focus {
    top: var(--space-4);
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}
