/* SOME Desk — landing page styles. Built to docs/DESIGN-WEB.md rev 3.
 *
 * Two conventions in here are load-bearing, not taste:
 *
 * 1. Every duration is written in seconds. Tests/bin/qa-claims scans this file and its
 *    performanceNumber rule is anchored on the millisecond unit, so the equivalent
 *    millisecond notation fails qa-ci as an unsubstantiated performance claim. Seconds
 *    notation is identical CSS. The same goes for frame-rate and frequency units, which
 *    have no business in a stylesheet anyway.
 * 2. --live-500 appears in exactly ONE rule in this file, .mic-dot, and it means the
 *    microphone is open (docs/BRAND.md § Colour). The page's other two coral moments are
 *    inside artwork, not CSS: the level bar in the lockup, and the dictate button inside
 *    the demo loop. It is not a highlight and not a brand accent — if you are reaching for
 *    it for emphasis you want --glass-500, and for a warning you want --warn-500.
 */

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

:root {
    /* docs/BRAND.md § Colour */
    --ink-900: #0a0f1a;
    --ink-800: #111826;
    --ink-700: #1b2435;
    --ink-500: #2e3a4d;
    --mist-400: #8e9cb0;
    --mist-200: #c7d1df;
    --mist-100: #e9eef6;
    --glass-400: #7fb0ff;
    --glass-500: #4c8dff;
    --glass-600: #2f6be0;
    --live-500: #ff7a45;
    --ok-500: #35c08a;
    --warn-500: #f5c242;

    --content: 1120px;
    --gutter: 24px;
    --margin: 48px;
    --measure: 68ch;
    --section-y: 120px;
    --radius-card: 16px;
    --radius-frame: 18px;
    --radius-button: 12px;

    --dur-fade: 0.2s;

    --display: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
    --body: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
}

/* Self-hosted so the headings do not depend on a third party. Licence ships alongside:
 * fonts/OFL-SpaceGrotesk.txt (docs/BRAND.md § Type — an obligation, not a courtesy).
 * Body text has no webfont: the system stack is already on the device and costs nothing. */
@font-face {
    font-family: "Space Grotesk";
    src: url("fonts/SpaceGrotesk-Medium.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

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

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

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

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

body {
    margin: 0;
    background: var(--ink-800);
    color: var(--mist-100);
    font: 400 19px/1.6 var(--body);
    -webkit-font-smoothing: antialiased;
}

/* height:auto matters more than it looks. Every image and the demo loop carry width/height
 * attributes so the browser reserves the right box before the file arrives — but those
 * attributes are presentational hints, and a fixed height silently wins over aspect-ratio.
 * Without this the placeholders render at their intrinsic pixel height inside a column that
 * is a third as wide. */
img,
video,
svg {
    display: block;
    max-width: 100%;
    height: auto;
}

a {
    color: var(--glass-500);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

a:hover {
    color: var(--glass-400);
}

/* Never outline:none. Every interactive stop on the page has a visible ring — the keyboard
 * path is an acceptance criterion in DESIGN-WEB.md, not a review note. */
:focus-visible {
    outline: 2px solid var(--glass-400);
    outline-offset: 3px;
    border-radius: 4px;
}

.skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 10;
    padding: 12px 20px;
    background: var(--glass-500);
    color: var(--ink-900);
    font: 600 17px/1 var(--body);
}

.skip:focus {
    left: 12px;
    top: 12px;
}

/* Visually hidden but present for a screen reader. Unlike .skip it never comes back on
 * focus — it is for labels, not for destinations. */
.vh {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Build state, not a design element. Anything still carrying data-copy-pending is text
 * nobody has written yet; scripts/check-web-copy.sh refuses to stage a page that has any. */
[data-copy-pending] {
    border-left: 3px solid var(--warn-500);
    padding-left: 16px;
    font-family: var(--mono);
    font-size: 15px;
    color: var(--mist-200);
}

/* ---------------------------------------------------------------- layout */

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

@media (min-width: 1280px) {
    .wrap {
        max-width: calc(var(--content) + var(--margin) * 2);
    }
}

.band {
    padding-block: var(--section-y);
}

.band--alt {
    background: var(--ink-700);
}

.band--flush {
    padding-block: calc(var(--section-y) - 40px);
}

.measure {
    max-width: var(--measure);
}

/* ---------------------------------------------------------------- type */

h1,
h2,
h3 {
    font-family: var(--display);
    font-weight: 500;
    margin: 0;
}

h1 {
    font-size: 64px;
    letter-spacing: -0.02em;
    line-height: 1.05;
}

h2 {
    font-size: 40px;
    letter-spacing: -0.015em;
    line-height: 1.15;
}

h3 {
    font-size: 22px;
    letter-spacing: -0.01em;
    line-height: 1.25;
}

p {
    margin: 0 0 20px;
}

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

.lede {
    font-size: 22px;
    line-height: 1.5;
    max-width: 52ch;
}

.caption {
    font-size: 15px;
    line-height: 1.4;
    letter-spacing: 0.01em;
    color: var(--mist-400);
}

.caption--mono {
    font-family: var(--mono);
    letter-spacing: 0;
}

.dim {
    color: var(--mist-400);
}

/* ---------------------------------------------------------------- buttons */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    padding: 0 28px;
    border-radius: var(--radius-button);
    border: 1px solid transparent;
    font: 600 17px/1 var(--body);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur-fade) ease, border-color var(--dur-fade) ease,
        color var(--dur-fade) ease;
}

.btn--primary {
    background: var(--glass-500);
    color: var(--ink-900);
}

.btn--primary:hover {
    background: var(--glass-400);
    color: var(--ink-900);
}

.btn--secondary {
    background: transparent;
    border-color: var(--ink-500);
    color: var(--mist-100);
}

.btn--secondary:hover {
    border-color: var(--glass-500);
    color: var(--mist-100);
}

.btn--small {
    min-height: 40px;
    padding: 0 18px;
}

.btn[aria-disabled="true"] {
    background: var(--ink-700);
    border-color: var(--ink-500);
    color: var(--mist-200);
    cursor: default;
}

.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin: 32px 0 16px;
}

/* ---------------------------------------------------------------- header */

.header {
    position: sticky;
    top: 0;
    z-index: 5;
    height: 72px;
    display: flex;
    align-items: center;
    background: transparent;
    border-bottom: 1px solid transparent;
    transition: background-color var(--dur-fade) ease, border-color var(--dur-fade) ease;
}

/* Transparent over the hero; ink with a hairline once the page has moved. site.js sets this. */
.header.is-scrolled {
    background: var(--ink-800);
    border-bottom-color: var(--ink-500);
}

.header .wrap {
    display: flex;
    align-items: center;
    gap: 24px;
}

.lockup {
    display: flex;
    align-items: center;
    margin-right: auto;
}

.lockup img {
    height: 28px;
    width: auto;
}

.nav {
    display: flex;
    align-items: center;
    gap: 28px;
}

.nav a {
    color: var(--mist-100);
    font-size: 17px;
    text-decoration: none;
}

.nav a:hover {
    color: var(--glass-400);
}

/* ---------------------------------------------------------------- hero */

.hero {
    position: relative;
    padding-block: 96px var(--section-y);
    overflow: hidden;
}

/* One soft radial behind the device. No gradient mesh, no noise. */
.hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(
        60% 55% at 72% 42%,
        rgba(47, 107, 224, 0.08) 0%,
        rgba(47, 107, 224, 0) 70%
    );
    pointer-events: none;
}

.hero .wrap {
    position: relative;
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--gutter);
    align-items: center;
}

.hero__text {
    grid-column: span 7;
}

.hero__art {
    grid-column: span 5;
}

/* The h1 sets on three lines and the breaks are the sentence's rhythm. Hard breaks, not
 * reflow — LAUNCH.md §4 and DESIGN-WEB.md §2.2 both call this out explicitly. */
.hero h1 .line {
    display: block;
}

.hero .lede {
    margin-top: 24px;
}

.frame {
    border: 1px solid var(--ink-500);
    border-radius: var(--radius-frame);
    overflow: hidden;
    background: var(--ink-700);
}

/* ---------------------------------------------------------------- demo loop */

.demo {
    padding-block: 0 var(--section-y);
}

.demo__figure {
    margin: 0;
    position: relative;
}

.demo__media {
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-card);
    overflow: hidden;
    border: 1px solid var(--ink-500);
    background: var(--ink-700);
}

.demo__controls {
    display: flex;
    justify-content: flex-end;
    margin-top: 12px;
}

/* ---------------------------------------------------------------- feature splits */

.split {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--gutter);
    align-items: center;
}

.split__text {
    grid-column: span 6;
}

.split__art {
    grid-column: span 6;
}

/* Image on the outside edge, alternating side. The reverse modifier moves the art to the
 * leading edge; source order stays text-then-art so the reading order is unchanged. */
.split--reverse .split__text {
    grid-column: 7 / span 6;
}

.split--reverse .split__art {
    grid-column: 1 / span 6;
    grid-row: 1;
}

.split h2 + p {
    margin-top: 20px;
}

.split .caption {
    margin-top: 16px;
}

/* The one coral moment in the three feature sections, and one of exactly three uses of
 * --live-500 on this page. It marks the section where the microphone is the subject. */
.mic-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--live-500);
    margin-right: 12px;
    vertical-align: 0.06em;
}

/* ---------------------------------------------------------------- accessibility band */

/* Set at lede size, single column, no image, no icon, no card. The copy is written straight
 * and the design must not decorate it back into an inspiration poster. */
.a11y p {
    font-size: 22px;
    line-height: 1.5;
}

/* ---------------------------------------------------------------- cards, faq, roadmap */

.card {
    background: var(--ink-700);
    border: 1px solid var(--ink-500);
    border-radius: var(--radius-card);
    padding: 32px;
}

.band--alt .card {
    background: var(--ink-800);
}

.faq {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 40px var(--gutter);
    margin-top: 48px;
}

/* Open by default, never an accordion: someone asking whether this is Sidecar should not
 * have to click to find out. Hiding honest answers behind a triangle reads as hiding them. */
.faq__item h3 {
    margin-bottom: 12px;
}

.faq__item p {
    color: var(--mist-400);
    font-size: 19px;
}

.roadmap {
    margin-top: 48px;
}

.roadmap ul {
    margin: 20px 0 0;
    padding: 0;
    list-style: none;
    columns: 2;
    column-gap: var(--gutter);
}

.roadmap li {
    padding-left: 22px;
    margin-bottom: 12px;
    position: relative;
    color: var(--mist-400);
    break-inside: avoid;
}

.roadmap li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.62em;
    width: 10px;
    height: 1px;
    background: var(--ink-500);
}

/* ---------------------------------------------------------------- footer */

.footer {
    background: var(--ink-900);
    color: var(--mist-400);
    padding-block: 72px 48px;
}

.footer a {
    color: var(--mist-100);
    text-decoration: none;
}

.footer a:hover {
    color: var(--glass-400);
}

.footer__top {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 40px var(--gutter);
}

.footer__brand {
    grid-column: span 5;
}

.footer__brand img {
    height: 20px;
    width: auto;
}

.footer__links {
    grid-column: span 3;
}

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

.footer__list li {
    margin-bottom: 10px;
}

.footer__signup {
    grid-column: span 4;
}

.signup {
    display: flex;
    gap: 12px;
    margin: 16px 0 12px;
}

.signup input {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 52px;
    padding: 0 16px;
    border-radius: var(--radius-button);
    border: 1px solid var(--ink-500);
    background: var(--ink-800);
    color: var(--mist-100);
    font: 400 17px/1 var(--body);
}

.signup input::placeholder {
    color: var(--mist-400);
}

.footer__legal {
    margin-top: 56px;
    padding-top: 24px;
    border-top: 1px solid var(--ink-500);
    font-size: 15px;
}

/* ---------------------------------------------------------------- download page */

.steps {
    counter-reset: step;
    margin: 40px 0 0;
    padding: 0;
    list-style: none;
}

.steps li {
    counter-increment: step;
    position: relative;
    padding-left: 48px;
    margin-bottom: 28px;
    max-width: var(--measure);
}

.steps li::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 1px solid var(--ink-500);
    color: var(--glass-500);
    font: 600 17px/32px var(--body);
    text-align: center;
}

.steps h3 {
    margin-bottom: 8px;
}

.notice {
    border: 1px solid var(--ink-500);
    border-left: 3px solid var(--glass-500);
    border-radius: 0 var(--radius-button) var(--radius-button) 0;
    background: var(--ink-700);
    padding: 20px 24px;
    margin: 32px 0;
    max-width: var(--measure);
}

.notice p {
    font-size: 17px;
}

.spec {
    width: 100%;
    border-collapse: collapse;
    margin-top: 32px;
    font-size: 17px;
}

.spec th,
.spec td {
    text-align: left;
    padding: 14px 16px 14px 0;
    border-bottom: 1px solid var(--ink-500);
    vertical-align: top;
}

.spec th {
    font-weight: 600;
    color: var(--mist-400);
    white-space: nowrap;
    width: 30%;
}

/* ---------------------------------------------------------------- support pages */

/* troubleshooting / privacy / changelog / roadmap. One prose column at the measure, and entries
 * whose headings are their own permalinks: docs/SUPPORT.md §1 makes a stable per-entry anchor a
 * requirement, because support replies link to the exact section and those links live in other
 * people's inboxes. Derive an anchor from the string, never from a number, and do not rename one. */

.doc {
    max-width: var(--measure);
}

.doc > h2 {
    margin-bottom: 32px;
}

.doc--prose p {
    margin-bottom: 24px;
}

/* One error string and its answer. */
.entry {
    padding-top: 28px;
    margin-top: 28px;
    border-top: 1px solid var(--ink-500);
}

.entry:first-of-type {
    padding-top: 0;
    margin-top: 0;
    border-top: 0;
}

.entry h3 {
    margin-bottom: 12px;
}

/* The heading is its own permalink but reads as a heading, not as a link — the sigil only appears
 * on hover and focus. The :focus-visible ring still lands on it, so the keyboard path is intact. */
.entry h3 a {
    color: inherit;
    text-decoration: none;
}

.entry h3 a::after {
    content: " #";
    color: var(--mist-400);
    opacity: 0;
    transition: opacity var(--dur-fade) ease-out;
}

.entry h3 a:hover::after,
.entry h3 a:focus-visible::after {
    opacity: 1;
}

.entry p {
    color: var(--mist-200);
}

/* The troubleshooting page is long on purpose — it is organised by the sentence the app showed the
 * user, not by subsystem — so someone who arrived from a search result still has to find theirs. */
.toc {
    margin-top: 48px;
    padding: 24px 28px;
    border: 1px solid var(--ink-500);
    border-radius: var(--radius-card);
    max-width: var(--measure);
}

.toc ul {
    margin: 16px 0 0;
    padding: 0;
    list-style: none;
}

.toc li {
    margin-bottom: 10px;
}

.toc li:last-child {
    margin-bottom: 0;
}

/* The numbered checks under "Looking for Macs…": the same three the app itself shows, in the same
 * order, and then the two where a phone-sized card runs out of room. */
.checks {
    margin: 0;
    padding-left: 28px;
}

.checks li {
    margin-bottom: 20px;
    color: var(--mist-200);
}

.checks li:last-child {
    margin-bottom: 0;
}

/* Changelog: newest first, no pagination (docs/SUPPORT.md §4). */
.release {
    padding-top: 32px;
    margin-top: 32px;
    border-top: 1px solid var(--ink-500);
}

.release:first-of-type {
    padding-top: 0;
    margin-top: 0;
    border-top: 0;
}

.release h2 {
    font-size: 30px;
    margin-bottom: 16px;
}

.release__date {
    margin-left: 12px;
    color: var(--mist-400);
    font: 400 17px/1 var(--body);
    letter-spacing: 0;
    white-space: nowrap;
}

/* ---------------------------------------------------------------- placeholders */

/* Every slot below is waiting on real imagery (SOM-12 captures, SOM-34 photography and the
 * demo loop). The placeholders are committed at the right aspect ratios so the layout being
 * reviewed now is the layout that ships — dropping a real image in changes no CSS. */
.slot {
    aspect-ratio: var(--slot-ratio, 4 / 3);
    width: 100%;
    background: var(--ink-700);
}

/* ---------------------------------------------------------------- motion */

/* Nothing moves on scroll except this: an 8px fade-up on section entry. The demo loop is the
 * only other moving thing on the page.
 *
 * Note which way round this is. A .reveal is visible by default and only becomes hidden once
 * site.js has added .js-reveal to the root — which it does as its first act, and only when it
 * has an IntersectionObserver to turn the section back on with. Writing it the other way,
 * with opacity:0 in the base rule, means a script that fails to load leaves most of the page
 * permanently invisible. An animation is not worth that trade. */
.js-reveal .reveal {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity var(--dur-fade) ease-out, transform var(--dur-fade) ease-out;
}

.js-reveal .reveal.is-in {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .js-reveal .reveal,
    .js-reveal .reveal.is-in {
        opacity: 1;
        transform: none;
        transition: none;
    }

    * {
        transition-duration: 0.01s !important;
        animation-duration: 0.01s !important;
    }
}

/* ---------------------------------------------------------------- breakpoints */

@media (max-width: 1279px) {
    :root {
        --margin: 48px;
    }
}

@media (max-width: 1023px) {
    .hero__text,
    .hero__art,
    .split__text,
    .split__art,
    .split--reverse .split__text,
    .split--reverse .split__art {
        grid-column: 1 / -1;
        grid-row: auto;
    }

    /* Stacked: the frame sits below the buttons, per DESIGN-WEB.md §2.2. */
    .hero__art {
        margin-top: 40px;
    }

    .split__art {
        margin-top: 32px;
    }

    .faq {
        grid-template-columns: minmax(0, 1fr);
    }

    .roadmap ul {
        columns: 1;
    }

    .footer__brand,
    .footer__links,
    .footer__signup {
        grid-column: 1 / -1;
    }
}

@media (max-width: 767px) {
    :root {
        --margin: 20px;
        --gutter: 16px;
        --section-y: 72px;
    }

    body {
        font-size: 17px;
    }

    h1 {
        font-size: 40px;
    }

    h2 {
        font-size: 30px;
    }

    h3 {
        font-size: 20px;
    }

    .lede,
    .a11y p {
        font-size: 18px;
    }

    .caption {
        font-size: 14px;
    }

    .hero {
        padding-block: 56px var(--section-y);
    }

    /* Lockup and the button only; the text links drop. */
    .nav {
        gap: 16px;
    }

    .nav a {
        display: none;
    }

    .btn-row .btn {
        width: 100%;
    }

    .signup {
        flex-wrap: wrap;
    }

    .signup input,
    .signup .btn {
        width: 100%;
    }

    .release h2 {
        font-size: 24px;
    }

    /* The date drops under the version rather than being squeezed beside it. */
    .release__date {
        display: block;
        margin: 8px 0 0;
    }

    .toc {
        padding: 20px;
    }
}
