/* Dissecta website — mirrors the app's design tokens (docs/DESIGN.md):
   dark-mode-only, dot grid, teal = precision, gold = progress.
   Colors, radii, shadow and motion durations are taken 1:1 from
   Dissecta/Theme/Theme.swift — change them there first. */

:root {
    --background: #0B1020;
    --screen: #11182B;
    --card: #151D33;
    --card-secondary: #1A2340;
    --panel-stroke: #2A3556;
    --divider: #24304C;
    --text: #F3F5F9;
    --text-secondary: #A6B0C8;
    --muted: #6E7893;
    --teal: #63D6D0;
    --gold: #F2C14E;
    --radius-panel: 24px;
    --radius-card: 18px;
    /* Theme.shadowColor 0x040A18 @ 28 %, radius 15, y 10 — SwiftUI's shadow
       radius is roughly half a CSS blur radius, hence 30px. */
    --shadow-card: 0 10px 30px rgba(4, 10, 24, 0.28);
    /* Theme.Motion.press (easeOut 0.14s). */
    --motion-press: 0.14s ease-out;
    /* Closest bezier to the smoothstep IntroView uses (t²(3−2t)). */
    --ease-smooth: cubic-bezier(0.45, 0, 0.55, 1);
}

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

html {
    scroll-behavior: smooth;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
        "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    background-color: var(--background);
    /* The app's quiet grid dots (white at 7 %). */
    background-image: radial-gradient(circle, rgba(255, 255, 255, 0.07) 1px, transparent 1.4px);
    background-size: 26px 26px;
    color: var(--text);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

.page {
    max-width: 760px;
    margin: 0 auto;
    padding: 0 24px;
}

/* Header */

header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 28px 0;
    flex-wrap: wrap;
}

.brand {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    color: var(--text);
    font-weight: 700;
    font-size: 1.15rem;
    letter-spacing: -0.02em;
}

.brand img {
    width: 30px;
    height: 30px;
}

.header-tools {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

nav {
    display: flex;
    flex-wrap: wrap;
    gap: 14px 18px;
    justify-content: flex-end;
}

nav a {
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 500;
    transition: color var(--motion-press);
}

nav a:hover {
    color: var(--teal);
}

.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 999px;
    border: 1px solid var(--panel-stroke);
    background: var(--card);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--muted);
}

.lang-switch a {
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--motion-press);
}

.lang-switch a:hover,
.lang-switch a[aria-current="true"] {
    color: var(--teal);
}

.lang-switch .sep {
    color: var(--divider);
}

/* Hero */

.hero {
    text-align: center;
    padding: 72px 0 56px;
}

.hero-mark {
    display: block;
    /* The app's lockup spaces mark and wordmark at markSize * 0.32
       (DissectaWordmark) — 108 * 0.32 ≈ 35. */
    margin: 0 auto 35px;
    width: 108px;
    height: 108px;
}

/* The intro cut, echoed once on first paint. IntroView runs 2.1s because a
   cold start earns that pause; a landing page does not, so this is the same
   choreography at roughly half the length — cut sweep, then the segments
   settle apart. The mark is visible the whole time (closed D → dissected D),
   never blank: if the CSS never arrives, the markup's transform attributes
   already render the resting state.
   `both` matters — without it the halves would show the resting split during
   the delay and then snap closed when the animation starts. */

.hero-mark .cut {
    /* Path length is hypot(90.2 − 9.8, 32.1 − 67.9) ≈ 88, but the dash must be
       longer: at exactly 88 the next dash begins on the final point, and a
       zero-length dash with a round linecap paints a visible teal dot at the
       far end while the cut is still supposed to be hidden. */
    stroke-dasharray: 90;
    animation: mark-cut 0.43s var(--ease-smooth) 0.25s both;
}

.hero-mark .half-upper {
    animation: mark-split-upper 0.32s var(--ease-smooth) 0.68s both;
}

.hero-mark .half-lower {
    animation: mark-split-lower 0.32s var(--ease-smooth) 0.68s both;
}

@keyframes mark-cut {
    from {
        stroke-dashoffset: 90;
    }

    to {
        stroke-dashoffset: 0;
    }
}

/* Separation = 0.045 * size along the cut normal at −24° (DissectaMark). */
@keyframes mark-split-upper {
    from {
        transform: translate(0, 0);
    }

    to {
        transform: translate(-1.83px, -4.11px);
    }
}

@keyframes mark-split-lower {
    from {
        transform: translate(0, 0);
    }

    to {
        transform: translate(1.83px, 4.11px);
    }
}

.hero h1 {
    font-size: 3rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.tagline {
    color: var(--text-secondary);
    font-weight: 500;
    font-size: 1.15rem;
    margin-top: 10px;
}

.hero p.lead {
    color: var(--text-secondary);
    max-width: 34em;
    margin: 26px auto 0;
}

.store-badge {
    display: inline-block;
    margin-top: 34px;
    padding: 14px 28px;
    border-radius: var(--radius-panel);
    background: var(--card);
    border: 1px solid var(--panel-stroke);
    color: var(--muted);
    font-weight: 600;
    font-size: 0.95rem;
    letter-spacing: 0.02em;
}

/* Beta CTA — same badge shape, but a real button (gold, like PrimaryButton). */
.store-badge.cta {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--background);
    text-decoration: none;
    box-shadow: var(--shadow-card);
    transition: filter var(--motion-press), transform var(--motion-press);
}

.store-badge.cta:hover {
    filter: brightness(1.06);
}

/* Theme.Motion.pressScale (0.97) — the app shrinks buttons on touch. */
.store-badge.cta:active {
    transform: scale(0.97);
}

.beta-note {
    margin-top: 14px;
    color: var(--muted);
    font-size: 0.9rem;
}

/* Feature cards */

.features {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 14px;
    padding: 12px 0 56px;
}

.feature {
    background: var(--card);
    border: 1px solid var(--panel-stroke);
    border-radius: var(--radius-card);
    padding: 22px 20px;
    box-shadow: var(--shadow-card);
}

.feature h3 {
    font-size: 0.98rem;
    font-weight: 600;
    margin-bottom: 6px;
}

/* The brand's cut, echoed as a heading marker — the app has no ◆ in its
   vocabulary (it uses SF Symbols), and a glyph renders differently per
   platform. This is the same teal stroke that splits the D. */
.feature h3 .cut {
    display: inline-block;
    width: 14px;
    height: 2px;
    margin-right: 9px;
    border-radius: 1px;
    background: var(--teal);
    /* DissectaMark.cutAngle */
    transform: rotate(-24deg);
    vertical-align: middle;
}

.feature p {
    color: var(--text-secondary);
    font-size: 0.88rem;
}

@media (max-width: 640px) {
    .features {
        grid-template-columns: 1fr;
    }

    .hero h1 {
        font-size: 2.3rem;
    }
}

/* Content sections (support, legal pages) */

section.panel,
main.legal {
    background: var(--card);
    border: 1px solid var(--panel-stroke);
    border-radius: var(--radius-panel);
    padding: 34px 32px;
    margin-bottom: 56px;
    box-shadow: var(--shadow-card);
}

.section-label {
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--muted);
    margin-bottom: 14px;
}

section.panel h2,
main.legal h1 {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin-bottom: 14px;
}

main.legal h2 {
    font-size: 1.08rem;
    font-weight: 600;
    margin: 28px 0 8px;
}

section.panel p,
main.legal p,
main.legal li {
    color: var(--text-secondary);
    font-size: 0.95rem;
}

main.legal ul {
    padding-left: 1.3em;
    margin: 8px 0;
}

main.legal p + p {
    margin-top: 10px;
}

a.inline {
    color: var(--teal);
    text-decoration: none;
    transition: color var(--motion-press);
}

a.inline:hover {
    text-decoration: underline;
}

.placeholder {
    color: var(--gold);
    font-style: italic;
}

.notice {
    margin-top: 26px;
    padding: 14px 16px;
    border-radius: var(--radius-card);
    background: var(--card-secondary);
    border: 1px solid var(--panel-stroke);
    color: var(--muted);
    font-size: 0.85rem;
}

/* Footer */

footer {
    border-top: 1px solid var(--divider);
    padding: 26px 0 40px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    color: var(--muted);
    font-size: 0.85rem;
}

footer nav {
    gap: 18px;
}

footer nav a {
    font-size: 0.85rem;
}

/* Accessibility */

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

    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
        transition-delay: 0s !important;
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        /* The negative delay matters: killing only the duration leaves the
           hero mark's delays intact, so it would still snap from closed to
           cut to split — jerkier than the animation it replaces. Starting
           in the past lands straight on the end state. */
        animation-delay: -1ms !important;
    }
}
