/* LoopIn on the web: the one design system every page draws from.
 *
 * White, ink and a rare coral. The app has always been a white page with
 * #11181C ink and LoopIn coral (constants/Colors.ts); the website was a
 * warm cream with a brown ink and a rust accent, so a student moving from
 * one to the other met two products. This file is the web half of the app's
 * palette, and every page loads it after icons.css and before its own CSS.
 *
 * COLOUR HAS THREE JOBS AND NO OTHERS.
 *   --text / --bg      everything. Hierarchy comes from size, weight and the
 *                      two greys, never from a colour.
 *   --accent           a MARK, never a fill behind words: the live dot, the
 *                      focus ring, a selected rule, the brand. 3.8:1 on white,
 *                      which is enough for a mark and not for text.
 *   --accent-ink       coral that has to be READ (a link in a sentence).
 *   --danger           an error, or a control that deletes. Deliberately not
 *                      the brand coral: a red error beside a coral brand mark
 *                      should not look like the same thing.
 * Nothing here is green. Green is a gain (docs/design/DESIGN_SYSTEM.md).
 *
 * TYPE is Geist and only Geist. Calm weights (500-600), slightly negative
 * tracking on display sizes, tabular numerals. A headline's <em> is a muted
 * second voice, not an italic.
 *
 * MOTION mirrors `Motion` in constants/design.ts so the web and the app
 * settle at the same rate:
 *   press 110 · scope 180 · fade 200 · enter 320 · emphasis 600 (ms)
 *   --ease-settle and --ease-lens are the app's two springs, sampled into
 *   CSS linear(): settle {damping 18, stiffness 160, mass 1} (708 ms to rest)
 *   and lens {14, 170, 1.15} (1117 ms). Sampled at 25 points by integrating
 *   x'' = (-k(x-1) - c x') / m from rest until |x-1| < .002.
 * Rules: enter = fade + a short rise; exit is faster and does not travel;
 * only transform, opacity and filter animate; reduced motion keeps opacity
 * and drops movement.
 *
 * Dark tokens are OPT-IN (`<html data-color-scheme="auto">`). The Study Room
 * is used at night and asks for them; the marketing pages are light.
 */
@font-face{font-family:Geist;src:url('/fonts/geist-latin.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:swap}
@font-face{font-family:GeistMono;src:url('/fonts/geist-mono-latin.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:swap}

:root{
  --bg:#ffffff;--bg-subtle:#f7f7f8;--bg-muted:#efeff1;--bg-inverse:#0f1115;
  --text:#0f1115;--text-2:#5e6470;--text-3:#686d77;--text-inverse:#ffffff;
  --line:#e7e8eb;--line-strong:#d4d6db;
  --accent:#e9474d;--accent-ink:#c8323a;--accent-soft:#fde8e8;--coral:#e9474d;
  --danger:#b42318;--danger-soft:#fdecea;
  --scrim:rgba(15,17,21,.4);
  --shadow-sm:0 1px 2px rgba(15,17,21,.06);
  --shadow-md:0 1px 2px rgba(15,17,21,.04),0 8px 24px -8px rgba(15,17,21,.14);
  --shadow-lg:0 2px 6px rgba(15,17,21,.05),0 24px 64px -16px rgba(15,17,21,.24);
  --r-sm:8px;--r-md:12px;--r-lg:20px;--r-xl:28px;--r-pill:999px;
  --font:Geist,system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:GeistMono,ui-monospace,SFMono-Regular,Menlo,monospace;
  --dur-press:110ms;--dur-scope:180ms;--dur-fade:200ms;--dur-enter:320ms;--dur-settle:560ms;--dur-emphasis:600ms;
  --ease-out:cubic-bezier(.16,1,.3,1);--ease-in:cubic-bezier(.4,0,1,1);--ease-in-out:cubic-bezier(.65,0,.35,1);
  --ease-settle:linear(0,.062,.197,.366,.529,.679,.797,.892,.956,1,1.025,1.037,1.04,1.038,1.032,1.025,1.019,1.013,1.008,1.004,1.002,1,.999,.998,1);
  --ease-lens:linear(0,.136,.422,.718,.956,1.099,1.157,1.153,1.113,1.064,1.021,.992,.977,.974,.979,.987,.994,1,1.003,1.004,1.004,1.003,1.001,1,1);
  --glass-wash:rgba(255,255,255,.76);--glass-solid:rgba(248,248,251,.96);
  --glass-rim:rgba(255,255,255,.75);--glass-edge:rgba(15,17,21,.08);
  --glass-sheen:rgba(255,255,255,.55);--glass-lens:rgba(15,17,21,.06);
  --glass-blur:blur(24px) saturate(1.8);
  --glass-shadow:0 1px 1px rgba(15,17,21,.04),0 12px 32px -12px rgba(15,17,21,.22);
  color-scheme:light
}
@media (prefers-color-scheme:dark){
  :root[data-color-scheme="auto"]:not([data-theme="light"]){
    --bg:#0f1012;--bg-subtle:#17181b;--bg-muted:#212328;--bg-inverse:#ededef;
    --text:#ededef;--text-2:#a0a4ad;--text-3:#8f939c;--text-inverse:#0f1012;
    --line:#26282d;--line-strong:#363840;
    --accent:#ff5a5f;--accent-ink:#ff7a7e;--accent-soft:#3a1d1f;--coral:#ff5a5f;
    --danger:#ff8a80;--danger-soft:#3a1c1a;
    --scrim:rgba(0,0,0,.6);
    --shadow-sm:0 1px 2px rgba(0,0,0,.4);
    --shadow-md:0 1px 2px rgba(0,0,0,.3),0 8px 24px -8px rgba(0,0,0,.6);
    --shadow-lg:0 2px 6px rgba(0,0,0,.4),0 24px 64px -16px rgba(0,0,0,.7);
    --glass-wash:rgba(23,24,27,.7);--glass-solid:rgba(23,24,27,.97);
    --glass-rim:rgba(255,255,255,.14);--glass-edge:rgba(0,0,0,.45);
    --glass-sheen:rgba(255,255,255,.12);--glass-lens:rgba(255,255,255,.10);
    --glass-shadow:0 1px 1px rgba(0,0,0,.3),0 14px 36px -12px rgba(0,0,0,.7);
    color-scheme:dark
  }
}

/* Moving between pages of the site is one cross-fade, and the wordmark
   stays where it is. Same-origin navigations only; a browser without
   cross-document view transitions simply navigates. */
@view-transition{navigation:auto}
::view-transition-old(root),::view-transition-new(root){animation-duration:var(--dur-fade);animation-timing-function:var(--ease-out)}
.vt-brand{view-transition-name:brand}

@keyframes lx-rise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes lx-fade{from{opacity:0}to{opacity:1}}
@keyframes lx-pop{from{opacity:0;transform:translateY(6px) scale(.98)}to{opacity:1;transform:none}}
@keyframes lx-shimmer{from{background-position:150% 0}to{background-position:-50% 0}}
@keyframes lx-shake{0%,100%{transform:none}25%{transform:translateX(-3px)}75%{transform:translateX(3px)}}
@keyframes lx-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.04)}}

/* GLASS: the app's material (Glass.light / Glass.dark in constants/design.ts)
   on the web. A wash over a blurred, saturated backdrop; a bright rim along
   the top edge where light would catch it; a hairline that keeps the edge on
   white; and a specular layer (::after) that follows a fine pointer, set by
   page script through --mx / --my.
   Glass only reads as glass with something passing under it, so a page that
   uses it lets content scroll beneath. Never nest it: a backdrop-filter
   inside another one samples only its parent, which is how a dropdown ends
   up showing the page un-blurred. Menus and lenses inside glass are tints.
   Where the browser cannot blur, or the reader asked for less transparency,
   it is a solid surface with the same rim and edge. */
.glass{position:relative;isolation:isolate;background-color:var(--glass-wash);-webkit-backdrop-filter:var(--glass-blur);backdrop-filter:var(--glass-blur);
  box-shadow:inset 0 1px 0 var(--glass-rim),0 0 0 1px var(--glass-edge),var(--glass-shadow)}
.glass::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background:radial-gradient(280px circle at var(--mx,50%) var(--my,-60%),var(--glass-sheen),transparent 70%),linear-gradient(180deg,var(--glass-sheen),transparent 60%);
  opacity:.5;transition:opacity var(--dur-enter) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .glass:hover::after{opacity:1}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass{background-color:var(--glass-solid)}
}
@media (prefers-reduced-transparency:reduce){
  .glass{background-color:var(--glass-solid);-webkit-backdrop-filter:none;backdrop-filter:none}
}

/* Scroll reveals, for the marketing pages only (never inside a tool).
   Without scroll-driven animations the content is simply there; world.js
   adds `reveal-js` to <html> and an observer where the browser lacks them. */
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline:view()){
    .reveal{animation:lx-rise linear both;animation-timeline:view();animation-range:entry 0% entry 70%}
  }
  .reveal-js .reveal{opacity:0;transform:translateY(16px);transition:opacity var(--dur-settle) var(--ease-out),transform var(--dur-settle) var(--ease-out)}
  .reveal-js .reveal.is-in{opacity:1;transform:none}
}
@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
  .reveal{animation:none!important;opacity:1!important;transform:none!important}
  .glass::after{transition:none}
}
