/* ==========================================================================
   theme.css — design tokens, reset, typography, page shell.
   Everything visual is driven from the custom properties below.
   ========================================================================== */

:root {
    /* --- surfaces ------------------------------------------------------ */
    --bg-main: #302D2F;
    --bg-deep: #252223;
    --bg-secondary: #3A3638;

    --glass: rgba(255, 255, 255, 0.08);
    --glass-strong: rgba(255, 255, 255, 0.11);
    --glass-soft: rgba(255, 255, 255, 0.045);
    --glass-border: rgba(255, 255, 255, 0.13);
    --glass-border-soft: rgba(255, 255, 255, 0.08);
    --glass-hairline: rgba(255, 255, 255, 0.06);

    /* --- accents (desaturated, premium) -------------------------------- */
    --health: #3C9E72;
    --nutrition: #BFA863;
    --activity: #78A560;
    --accent: var(--health);

    /* --- text ----------------------------------------------------------- */
    /* Tuned so every text tier clears WCAG AA (4.5:1) on the glass surfaces,
       including the nested rows inside cards. --text-faint is for graphics
       (inactive dots), never for text. */
    --text-primary: #F7F7F5;
    --text-secondary: rgba(255, 255, 255, 0.74);
    --text-muted: rgba(255, 255, 255, 0.60);
    --text-faint: rgba(255, 255, 255, 0.42);

    /* --- radii ---------------------------------------------------------- */
    --radius-card: 28px;
    --radius-md: 20px;
    --radius-sm: 14px;
    --radius-pill: 999px;

    /* --- spacing scale -------------------------------------------------- */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;

    /* --- glass recipe --------------------------------------------------- */
    --blur-card: 24px;
    --blur-bar: 30px;

    /* --- floating glass ---------------------------------------------------
       The material the tab bar and the two header buttons are cut from. Grey
       and white only — nothing here takes an accent.

       The blur is 10px, not the forty-odd a heavy frosted panel suggests:
       measured through the glass, text-scale detail from the page bottoms out
       around 8-10px and climbs again above it, because the engine downsamples
       the backdrop at large radii and the resampling puts the detail back. It
       is also the cheaper number on a phone. */
    --pane-blur: 10px;
    --pane-saturate: 190%;
    --pane-brightness: 108%;

    /* The rim: one hairline that catches light at the top-left, gives a little
       back at the bottom-right, and nearly vanishes across the face — an edge
       with thickness rather than an outline drawn around a box. */
    --pane-rim: linear-gradient(152deg,
        rgba(255, 255, 255, 0.46) 0%,
        rgba(255, 255, 255, 0.13) 22%,
        rgba(255, 255, 255, 0.045) 52%,
        rgba(255, 255, 255, 0.10) 78%,
        rgba(255, 255, 255, 0.26) 100%);
    --surface-gradient: linear-gradient(135deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.04));
    --surface-gradient-quiet: linear-gradient(135deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.028));
    --shadow-inset: inset 0 1px 0 rgba(255, 255, 255, 0.08);
    --shadow-card: 0 15px 35px rgba(0, 0, 0, 0.18);
    --shadow-float: 0 12px 28px rgba(0, 0, 0, 0.3);

    /* --- typography ------------------------------------------------------ */

    /* SF Pro, by the route Apple actually ships it.

       -apple-system and BlinkMacSystemFont come first on purpose. On Apple
       platforms they resolve to San Francisco and pick the optical size for
       you — SF Pro Text below about 20px, SF Pro Display above it. Naming a
       cut first instead would pin every size to that one cut, and the Display
       cut's tighter fit is the wrong thing under a 10px tab label.

       The named families behind them are for browsers that ignore
       -apple-system but do have SF Pro available, and are where a self-hosted
       @font-face would attach: a browser only downloads a face it actually
       uses, so Apple devices would keep using the system copy and download
       nothing. Text precedes Display because most type in this app is UI-sized.

       Nothing after that is a design choice, it is what is left when SF Pro is
       absent: Helvetica Neue is the nearest grotesque most non-Apple machines
       have, then whatever the system calls sans-serif. */
    --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
        "Helvetica Neue", sans-serif;

    /* The same idea for the two file paths in the setup notice: SF Mono is the
       monospace member of this family, and ui-monospace is how you ask for it
       without naming it. */
    --font-mono: ui-monospace, "SF Mono", Menlo, monospace;

    --fs-brand: 1.4rem;    /* app name            ~22px */
    --fs-section: 1.3rem;  /* section titles      ~21px */
    --fs-score: 2.9rem;    /* primary score       ~46px */
    --fs-score-sm: 1.75rem;/* secondary scores    ~28px */
    --fs-body: 0.9375rem;  /* body                 15px */
    --fs-label: 0.875rem;  /* labels               14px */
    --fs-small: 0.8125rem; /* captions             13px */
    --fs-tiny: 0.6875rem;  /* eyebrow / tabs       11px */

    --tracking-wide: 0.08em;

    /* --- motion ---------------------------------------------------------- */
    --transition-fast: 180ms ease;
    --transition-slow: 420ms cubic-bezier(0.22, 0.61, 0.36, 1);
    --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);

    /* Screen-to-screen transition: same family as the micro-interactions,
       just long enough to read as a push and short enough to feel instant. */
    --screen-duration: 280ms;
    --screen-ease: cubic-bezier(0.22, 1, 0.36, 1);

    /* --- layout ---------------------------------------------------------- */
    /* One source of truth for the page column: content, header, tab bar and
       the floating control all align to --shell-w. */
    --shell-w: min(92vw, 33.5rem);
    --content-width: var(--shell-w);
    --page-max: 1080px;
    /* The tab bar floats: it is a capsule with air under it and at its sides,
       not a slab welded to the bottom of the screen. Its own height is small
       — just enough margin around an icon and a label — and everything that
       has to clear it uses --dock-clearance rather than doing the sum again. */
    --tabbar-height: 54px;
    --dock-gap: 12px;
    --dock-clearance: calc(var(--tabbar-height) + var(--dock-gap) + var(--safe-bottom));

    /* How far the bar's reflection is drawn past its own edge before being
       clipped back to the capsule. Must clear the displacement in
       #glass-refraction (scale 19, so ±9.5px) or that layer's own edge
       arrives at the cut and shows. */
    --sheen-overhang: 16px;

    /* The tab's interior. Every number here applies to all five tabs alike:
       the icons are normalised on their own grid instead, so nothing is
       corrected tab by tab. The icon leads and the label supports, which is
       why the icon box is well over twice the type size. */
    --tab-icon: 24px;
    --tab-gap: 3px;
    --tab-label: 0.625rem;
    --tab-glow-inset: 4px;

    /* The one correction left, in label ems so it follows the type: the icon
       box is a square frame around marks that are mostly wider than they are
       tall, so it carries more dead space above the strokes than the label's
       box carries under its baseline. */
    --tab-optical: 0.124;

    /* Edge padding on the row of tabs, so the gap beside the first and last
       label stays close to the gap under all of them.

       It has to fall as the screen grows. The five columns are equal and each
       label is centred in its own, so every pixel the capsule gains is split
       among the cells and half of the outer cells' share lands outside the
       outer labels — the gap widens on its own at 0.1px per px of bar. Giving
       the padding the opposite slope holds it still; the cap is where a small
       phone would rather have the width than the symmetry. */
    --tab-edge: clamp(0px, calc(49.5px - 10.65vw), 12px);

    /* The header pair, on the same terms as the bar: one button size and one
       icon box for the two of them, the icon box the same as a tab's so the
       two rows read as one family. */
    --header-btn: 46px;
    --header-icon: 24px;
    --header-height: 56px;
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* Accent binding — any element can opt into a category colour. */
[data-accent="health"] { --accent: var(--health); }
[data-accent="nutrition"] { --accent: var(--nutrition); }
[data-accent="activity"] { --accent: var(--activity); }

/* ==========================================================================
   Reset
   ========================================================================== */

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

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

/* The document itself does not scroll — each screen owns its own scroller,
   so a whole screen can be translated as one layer during the swipe. */
body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    background-color: var(--bg-deep);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    line-height: 1.5;
    letter-spacing: -0.01em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }

/* Form controls do not inherit the page font on their own — every browser
   substitutes its own for them — so they are named once here rather than left
   to each component to remember. Family only: the sizes belong to the
   components that set them and must not be disturbed from here. */
button,
input,
textarea,
select,
optgroup {
    font-family: var(--font-sans);
}

code, kbd, samp, pre { font-family: var(--font-mono); }

button {
    font: inherit;
    color: inherit;
    margin: 0;
    border: 0;
    background: none;
    cursor: pointer;
    touch-action: manipulation;
}

:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.55);
    outline-offset: 3px;
    border-radius: var(--radius-sm);
}

/* ==========================================================================
   Page shell
   ========================================================================== */

.app { position: relative; }

/* Warm dark ground with two very restrained accent washes. */
.app__backdrop {
    position: fixed;
    inset: 0;
    z-index: -1;
    background:
        radial-gradient(90% 55% at 12% 0%, rgba(60, 158, 114, 0.14), transparent 62%),
        radial-gradient(80% 50% at 96% 12%, rgba(191, 168, 99, 0.10), transparent 58%),
        radial-gradient(120% 70% at 50% 104%, rgba(120, 165, 96, 0.08), transparent 60%),
        linear-gradient(180deg, var(--bg-main) 0%, var(--bg-deep) 100%);
}

/* --------------------------------------------------------------------------
   Layers.

   Two movements, kept apart on purpose:

     horizontal — .rail carries the five pages and slides as one element
     vertical   — .sheet pulls up OVER the rail, so the page underneath keeps
                  its state and scroll position while the sheet is in front
   -------------------------------------------------------------------------- */
.deck {
    position: fixed;
    inset: 0;
    overflow: hidden;
}

/* --- horizontal: the page rail ---------------------------------------- */
.rail {
    position: absolute;
    inset: 0;
    z-index: 1;
    transform: translate3d(0, 0, 0);
    transition: transform var(--screen-duration) var(--screen-ease);
}

/* One viewport-wide slot per page, parked at its own index. */
.rail__slot {
    position: absolute;
    inset: 0;
    transform: translate3d(calc(var(--page-index, 0) * 100%), 0, 0);
}

.screen {
    position: absolute;
    inset: 0;
    /* Vertical panning and pinch-zoom stay with the browser; horizontal
       movement is the only thing the page gesture ever sees. */
    touch-action: pan-y pinch-zoom;
}

/* Each page scrolls on its own, which is what preserves its scroll position
   when you move sideways or pull the assistant up over it. */
.screen__scroll {
    position: absolute;
    inset: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y pinch-zoom;
}

/* --- vertical: the assistant sheet ------------------------------------- */
.sheet {
    z-index: 40;
    transform: translate3d(0, 100%, 0);
    transition: transform var(--screen-duration) var(--screen-ease);
    border-start-start-radius: var(--radius-card);
    border-start-end-radius: var(--radius-card);
    overflow: hidden;
}

/* The lifted edge only exists while the sheet is off its rest position. */
.deck[data-ai-state="moving"] .sheet,
.deck[data-ai-state="open"] .sheet {
    box-shadow: 0 -18px 42px rgba(0, 0, 0, 0.36), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}

.sheet-scrim {
    position: absolute;
    inset: 0;
    z-index: 35;
    background: rgba(0, 0, 0, 0.42);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--screen-duration) ease;
}

/* While a finger is on the glass, the layers follow it directly. */
.deck.is-dragging .rail,
.deck.is-dragging .sheet,
.deck.is-dragging .sheet-scrim { transition: none; }

/* Single alignment rule for the whole page: header, content and tab bar. */
.shell {
    width: var(--content-width);
    max-width: var(--page-max);
    margin-inline: auto;
}

.app__main {
    padding-top: var(--space-5);
    /* Reserves room for the tab bar, the home indicator and the floating
       control, so the last block is never hidden behind fixed chrome. */
    padding-bottom: calc(var(--dock-clearance) + var(--space-6) + var(--space-6) + var(--space-5));
}

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/* ==========================================================================
   Utilities
   ========================================================================== */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.skip-link {
    position: absolute;
    top: calc(var(--safe-top) + var(--space-2));
    left: 50%;
    transform: translate(-50%, -200%);
    z-index: 50;
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-pill);
    background: var(--bg-secondary);
    color: var(--text-primary);
    font-size: var(--fs-small);
    text-decoration: none;
    transition: transform var(--transition-fast);
}

.skip-link:focus { transform: translate(-50%, 0); }

/* Scroll-in reveal — the class is only added when JS is available. */
.js .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--transition-slow), transform var(--transition-slow);
}

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

/* Press feedback for every tappable surface. */
.press { transition: transform var(--transition-fast), background-color var(--transition-fast), border-color var(--transition-fast); }
.press:active { transform: scale(0.97); }

/* Neutral loading placeholder for data that does not exist yet. */
.skeleton {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.07);
}

.skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.11), transparent);
    animation: shimmer 2.4s var(--ease-out) infinite;
}

.skeleton--line {
    display: block;
    width: 60%;
    height: 9px;
}

@keyframes shimmer {
    to { transform: translateX(100%); }
}

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

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

    .js .reveal { opacity: 1; transform: none; }
}
