/*
 * The CodigoSH design system.
 *
 * The accent is the house orange and it is the same in every CodigoSH project.
 * It is NOT mirrored or rotated per product: the identity of the house is
 * worth more than telling the products apart by colour.
 *
 * Theme resolution happens entirely in CSS, with no JavaScript: bare :root is
 * light, prefers-color-scheme handles the system setting, and [data-theme]
 * lets an explicit choice win in both directions. Doing it in JS means a flash
 * of the wrong theme on every cold load, and a script that has to run before
 * anything paints.
 */

:root {
    color-scheme: light dark;

    /*
     * The side margin of every screen, in one place.
     *
     * Anything that has to reach the edge of the window — the screen header,
     * the tab bar — bleeds out of this gutter with a negative margin and pays
     * it back as padding. Written as two independent numbers they drifted:
     * -1rem against a 1.25rem gutter left four pixels down each side where
     * the content scrolled past the header in the clear.
     */
    --gutter: 1.25rem;

    /* Accent. Always define the -rgb pair: every tint in the system is
       rgba(var(--accent-rgb), a). */
    --accent: #e8520e;
    --accent-rgb: 232, 82, 14;
    --accent-alt: #c2410c;

    /* Measured: #e8520e on white is 3.6:1 — fine for large text, icons,
       borders and surfaces, but below the 4.5:1 that AA requires for body
       text. --accent-alt is 4.8:1 and passes. On the dark canvas the pure
       orange is 5.2:1 and is used directly. */
    --accent-text: var(--accent-alt);

    /*
     * The canvas is warm, and that is the whole trick.
     *
     * A neutral grey behind white cards reads as a document. A canvas with a
     * trace of the accent in it reads as a surface the cards are resting on,
     * and it costs nothing: no second colour is introduced, the accent is the
     * house's own, and the tint is far too weak to compete with anything
     * drawn on top.
     */
    --canvas: #f6f2ef;
    --panel: #ffffff;
    --surface: rgba(255, 255, 255, 0.72);
    --surface-solid: #ffffff;
    --border: rgba(0, 0, 0, 0.05);
    --card-border: rgba(0, 0, 0, 0.07);
    --text-main: #0f172a;
    --text-dim: #64748b;

    --danger-color: #dc2626;
    --success-color: #16a34a;
    --warning-color: #ea580c;
    --info-color: #0284c7;

    /*
     * The toast, which is always the inverse of the surface it floats over.
     *
     * That is what a snackbar is on both platforms: a dark pill in daylight
     * and a light one at night, so it reads as a thing on top of the page
     * rather than as another card on it.
     */
    --toast-bg: #1f2430;
    --toast-text: #ffffff;

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.10);
    --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.14);
    --shadow-xl: 0 20px 50px rgba(0, 0, 0, 0.18);

    /* The light bevel along the top edge is the signature of the system. */
    --card-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 2px 10px rgba(0, 0, 0, 0.06);

    /*
     * A softer, wider shadow for the one card on a screen that matters most.
     *
     * The bevel stays: it is the signature and it is what makes a surface look
     * lit rather than drawn. What was missing underneath it was room — a tight
     * shadow makes a card look stuck to the page, and a wide diffuse one makes
     * the same card look like it is resting on it. Half of why a well-made
     * application feels calm is this and spacing, and neither costs anything.
     */
    --card-shadow-raised: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 6px 28px rgba(0, 0, 0, 0.09);

    /*
     * Radii.
     *
     * A native application on a phone is made of rounded rectangles, and eight
     * pixels is a web page's corner rather than an app's. The scale below is
     * what separates "a card" from "a bordered div": tiles are generously
     * round, controls are pills, and nothing that a thumb touches has a sharp
     * corner.
     */
    --radius: 8px;
    --radius-card: 22px;
    --radius-tile: 18px;
    --radius-control: 14px;
    --radius-pill: 999px;

    /*
     * The spacing scale. Four pixels, doubling, and nothing in between.
     *
     * Spacing was written by hand at every site that needed some: 0.15rem,
     * 0.2rem, 0.35rem, 0.4rem, 0.6rem — two, three, five, six and nine pixels,
     * each one a judgement call made once and never compared with the others.
     * Measured across every screen, that produced rows four pixels apart,
     * sections with none at all, and labels welded to the things above them.
     * A phone reads as a phone partly because its spacing is a scale rather
     * than a series of opinions, and the whole of this one fits in one line.
     *
     * --space-4 (16px) is the screen margin and the resting distance between
     * unrelated things; --space-2 (8px) binds things that belong together;
     * --space-6 and --space-8 separate sections. Anything not on the scale
     * should be a considered exception with a reason beside it, not a number
     * somebody typed.
     */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
    --space-10: 40px;

    /* The old name for --space-3, kept so nothing breaks while the stylesheet
       moves over to the scale. */
    --spacing-sm: var(--space-3);

    /*
     * The type scale for numbers that are the answer.
     *
     * A weight lifted, a week's load, a body weight: the figure somebody came
     * to the screen for. They were the same size as the label above them,
     * which made every screen a uniform grey wall that had to be read rather
     * than seen. Tabular figures, always, so a column of them lines up and a
     * changing one does not jump.
     */
    --font-size-display: 2rem;
    --font-size-figure: 1.5rem;

    --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
    --font-mono: 'JetBrains Mono', 'Fira Code', monospace;

    --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);

    /* Anything usable mid-set has to be reachable with a thumb, on a phone,
       with wet hands. 48px is the floor and it is not negotiable per widget. */
    --touch-target: 48px;

    /*
     * And 44px everywhere else, which is the floor both phone platforms
     * publish.
     *
     * Two numbers rather than one, because they answer different questions.
     * 48 is what a wet thumb needs between sets; 44 is what a finger needs on
     * a settings screen. A control smaller than 44 is not small — it is
     * missable, and measuring found several at 30 and 36. Where a control is
     * deliberately smaller than its target (a switch is 51x31 on iOS and
     * should stay that size), the shape stays and an invisible ::after takes
     * the target out to here.
     */
    --touch-min: 44px;

    /*
     * The tone of a screen.
     *
     * The application this one is modelled on gives every screen its own
     * colour: purple for sleep, wine for the cycle, amber for steps. It reaches
     * the background wash, the glow behind the hero figure and the ring on the
     * round header buttons, and it is a real part of why those screens feel
     * distinct rather than repeated.
     *
     * Here it is one token and it is the house orange everywhere, because the
     * accent is a rule of the house and five screen colours is that rule
     * rotated per view under another name. The mechanism exists so that
     * changing it later is one line per screen rather than a rebuild.
     */
    /*
     * The unlit fill of the body map.
     *
     * Opaque on purpose. Mixing the accent into a *transparent* grey gives a
     * semi-transparent brown — the two colours average and the alpha averages
     * with them — and the figure came out muddy rather than tinted.
     */
    --body-base: #d9dce1;

    /*
     * The outline of the body map.
     *
     * Darker than the unlit fill rather than a shade of the text colour: it
     * has to stay readable against a region lit to full accent, and a line
     * that only contrasts with the *empty* figure vanishes exactly where the
     * drawing has something to say.
     */
    --body-edge: #9aa0a8;

    --tone: var(--accent);
    --tone-rgb: var(--accent-rgb);
}

/*
 * The accent, chosen by whoever is reading.
 *
 * The house orange stays the default — that is a rule about the product, and a
 * bare :root above is what carries it. This is a reader's own choice, the way
 * the language and the theme are, and it only ever redefines the three tokens
 * every tint in the system is built from.
 *
 * Every entry carries its own darker variant for text on a light background,
 * because that pair is not decoration: measured, the orange is 3.7:1 on white,
 * which is fine for a filled surface and short of the 4.5 body text needs. An
 * accent without the pair would be one that quietly fails contrast in the light
 * theme only. The numbers for all six are asserted by contrast.test.ts.
 *
 * They redefine nothing else. --accent-text still resolves per theme: the
 * darker variant on light, the vivid one on the dark canvas, decided by the
 * rules further down rather than repeated here.
 */
:root[data-accent="blue"] {
    --accent: #2563eb;
    --accent-rgb: 37, 99, 235;
    --accent-alt: #1d4ed8;
}

:root[data-accent="green"] {
    --accent: #16a34a;
    --accent-rgb: 22, 163, 74;
    --accent-alt: #15803d;
}

:root[data-accent="purple"] {
    --accent: #7c3aed;
    --accent-rgb: 124, 58, 237;
    --accent-alt: #6d28d9;
}

:root[data-accent="pink"] {
    --accent: #db2777;
    --accent-rgb: 219, 39, 119;
    --accent-alt: #be185d;
}

:root[data-accent="teal"] {
    --accent: #0d9488;
    --accent-rgb: 13, 148, 136;
    --accent-alt: #0f766e;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --canvas: #0f0e0d;
        --panel: #1b1917;
        --surface: rgba(28, 28, 30, 0.70);
        --surface-solid: #242424;
        --border: #333333;
        --card-border: rgba(255, 255, 255, 0.09);
        --text-main: #ffffff;
        --text-dim: #a0a0a0;

        --toast-bg: #f2f2f4;
        --toast-text: #14161c;

        --accent-text: var(--accent);
        --body-base: #2c2c2e;
        --body-edge: #5a5a5e;

        --danger-color: #f87171;
        --success-color: #4ade80;
        --warning-color: #fb923c;
        --info-color: #38bdf8;

        --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
        --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
        --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.5);
        --shadow-xl: 0 20px 50px rgba(0, 0, 0, 0.6);
        --card-shadow-raised: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 6px 28px rgba(0, 0, 0, 0.5);
        --card-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 2px 12px rgba(0, 0, 0, 0.35);
    }
}

:root[data-theme="dark"] {
    --canvas: #0f0e0d;
    --panel: #1b1917;
    --surface: rgba(28, 28, 30, 0.70);
    --surface-solid: #242424;
    --border: #333333;
    --card-border: rgba(255, 255, 255, 0.09);
    --text-main: #ffffff;
    --text-dim: #a0a0a0;

    --toast-bg: #f2f2f4;
    --toast-text: #14161c;

    --accent-text: var(--accent);

    --danger-color: #f87171;
    --success-color: #4ade80;
    --warning-color: #fb923c;
    --info-color: #38bdf8;

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.5);
    --shadow-xl: 0 20px 50px rgba(0, 0, 0, 0.6);
    --card-shadow-raised: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 6px 28px rgba(0, 0, 0, 0.5);
    --card-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 2px 12px rgba(0, 0, 0, 0.35);
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

* {
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--accent-rgb), 0.25) transparent;
}

*::-webkit-scrollbar {
    inline-size: 6px;
    block-size: 6px;
}

*::-webkit-scrollbar-thumb {
    background: rgba(var(--accent-rgb), 0.25);
    border-radius: 10px;
}

/*
 * The hidden attribute means hidden.
 *
 * It applies display:none at the lowest possible specificity, so any rule that
 * sets display — .nav { display: flex } — silently overrides it and the
 * element stays on screen with the attribute correctly set. The DOM says
 * hidden, the screenshot says otherwise, and only the screenshot is right.
 */
[hidden] {
    display: none !important;
}

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