/* tokens.css — the ONE source of the Hoop design language (design tokens v1, 0.2.13).
   hoop.css @imports this file first (after the fonts); pages still link ONE stylesheet
   (hoop.css) — this is the token layer of that one cascade, never a second skin.

   LAW (tools/test-design-tokens.mjs is the gate):
     · every custom property the OS uses is DEFINED HERE and nowhere else — hoop.css and
       motion.css only reference tokens; a `var(--x)` with no definition is a red light
       (0.2.12 shipped `--shadow-card` / `--r-card` undefined: the strip lost its shadow).
     · hoop.css / motion.css carry no literal colour, no literal duration or easing, no
       literal font-size or radius (allow-list: 16px = the iOS no-zoom law, clamp() heroes,
       em-relative markdown sizes). The WORK-FRAME's breakpoints are read by gram-stage.js
       through getComputedStyle (CSS queries cannot read var()), so they too live only here.
     · motion: three durations (120 / 240 / 480ms), one stagger (40ms), two transition
       curves (standard / emphasized); loops (breathe / pulse / shimmer) are the only
       ambient motion and mean "this is alive", never "look here". Under
       prefers-reduced-motion every duration is 0ms — JS reads the tokens, so it goes
       still too (motion.js). Only transform, opacity and the stroke of a drawn icon move.

   Naming: the 0.2.12 names (--fs-*, --sp-*, --r-*, --dur-*, --ease, --brand …) stay —
   they are what 2,200 lines of hoop.css and nav.js's token-riding rules speak. The
   OS-DESIGN semantic names (--motion-*, --ease-standard, --wf-*, --surface-*, --text-*,
   --accent-*, --status-*, --z-*, --tap) are layered on top as the vocabulary for new
   work; --dur-* and --ease are aliases of them, so there is still one number per idea. */

:root{
  /* ── colour: brand amber leads, blue assists — both as accents, never a filled area ── */
  --brand:#F5B301; --brand-600:#E0A200; --on-brand:#221A00;
  --brand-ink:#9C7500;                      /* brand as readable text/icon on bg */
  --brand-soft:rgba(245,179,1,.13);         /* brand as a whisper (active tints) */
  --accent:#2A78D6; --ring:rgba(42,120,214,.4);
  /* surfaces: warm paper (default = 系统黄蓝, light half) */
  --bg:#FCFBF6; --surface:#FFFFFF; --surface-2:#F5F3EB;
  --fg:#1C1A14; --dim:#8B877A;
  /* lines are translucent ink: they take the colour of whatever they sit on */
  --line:color-mix(in oklab, var(--fg) 9%, transparent);
  --line-soft:color-mix(in oklab, var(--fg) 5.5%, transparent);
  --line-2:color-mix(in oklab, var(--fg) 16%, transparent);
  --paper:var(--surface);   /* what inputs/keys are cut from; lifted a shade in the dark */
  --code:#F4F2E9; --own:#F6F0DE; --lift:rgba(28,26,20,.05);
  --ok:#3F9E58; --bad:#D03B3B; --warn:#C77B28;
  --hl-key:#a626a4; --hl-str:#50771c; --hl-num:#b25d0e; --hl-com:#9c9b96; --hl-fn:#2a63c9;
  --scrim:rgba(20,18,10,.4);
  /* the few inks that are the same in every theme (media stages, QR paper, scrims) */
  --ink-stage:#101010;                       /* a video / desktop stream's bezel */
  --surface-white:#FFFFFF;                   /* QR codes must sit on true white */
  --on-scrim:#FFFFFF; --on-bad:#FFFFFF;      /* text on a scrim / on the danger fill */
  --scrim-strong:rgba(0,0,0,.55); --scrim-stronger:rgba(0,0,0,.75);
  --selection:rgba(245,179,1,.28);
  --glint:rgba(255,255,255,.25);             /* the shimmer's moving highlight */
  --reader-paper:#FBF7EC; --reader-ink:#1C1A14;          /* the reader stage, day */
  --reader-night:#15140F; --reader-night-ink:#D9D6CB;    /* … and lamplight */
  --tl-idle:color-mix(in oklab, var(--fg) 30%, transparent);   /* window lights at rest */
  /* semantic aliases (OS-DESIGN tokens v1): what a colour MEANS in the frame */
  --surface-home:var(--bg);                  /* the quiet root (家) */
  --surface-pane:var(--surface);             /* chancellor / check panes */
  --surface-raised:var(--glass-bg);          /* gate cards, menus, temporary layers */
  --text-1:var(--fg); --text-2:var(--dim);
  --text-3:color-mix(in oklab, var(--fg) 45%, transparent);
  --accent-owner:var(--brand);               /* the owner's own action */
  --accent-agent:var(--accent);              /* an agent is present / acting */
  --accent-gate:var(--warn);                 /* waiting for the owner's word */
  --status-working:var(--brand); --status-success:var(--ok);
  --status-warn:var(--warn); --status-danger:var(--bad);

  /* ── motion (the only numbers in the OS that move) ─────────────────────── */
  --motion-fast:120ms;      /* press, focus, micro feedback */
  --motion-base:240ms;      /* a pane or card enters, a state changes */
  --motion-slow:480ms;      /* the four narrative places only: .ai hero, the four
                               states, the PA's presence, the check pane switching */
  --motion-stagger:40ms;    /* a few related things, never a long list; ≤6 */
  --motion-breathe:2.6s;    /* the hoop mark breathing (ambient: alive, not busy) */
  --motion-pulse:1.2s;      /* something is working right now */
  --motion-shimmer:1.4s;    /* a skeleton waiting for real content */
  --ease-standard:cubic-bezier(.2,0,0,1);     /* position / scale */
  --ease-emphasized:cubic-bezier(.2,.8,.2,1); /* stage & three-state transitions */
  --ease-loop:ease-in-out;                    /* the ambient loops only */
  --ease-linear:linear;                       /* the shimmer sweep only */
  /* 0.2.12 names = aliases, one number per idea */
  --dur-1:var(--motion-fast); --dur-2:var(--motion-base); --dur-3:var(--motion-slow);
  --ease:var(--ease-standard);
  --rise:rise var(--dur-2) var(--ease);

  /* ── shape & depth: one radius ladder; controls sit on the tighter --r-btn ── */
  --r-2xs:3px; --r-xs:6px; --r-sm:10px; --r-md:14px; --r-lg:18px; --r-xl:24px;
  --r-2xl:28px; --r-pill:999px;
  --r-btn:var(--r-pill); --r-in:14px; --r-card:var(--r-lg);
  /* DESIGN-TOKENS v1 names: control / card / panel / stage — the same four rungs */
  --radius-1:var(--r-xs); --radius-2:var(--r-sm); --radius-3:var(--r-lg); --radius-4:var(--r-xl);
  --btn-h:34px; --btn-h-sm:28px;
  /* glass (②b): what floats is translucent, blurred, and rimmed with light */
  --glass-bg:color-mix(in oklab, var(--surface) 76%, transparent);
  --glass-blur:blur(22px) saturate(1.6);
  --glass-rim:inset 0 1px 0 rgba(255,255,255,.55), inset 0 -1px 0 rgba(0,0,0,.04),
    0 0 0 1px color-mix(in oklab, var(--fg) 7%, transparent);
  /* the dock's column (nav.js pads body by --dock-w; its 44px icons sit 10px off the
     edge, so their axis is 32px in). A 32px float at --float-end shares that axis. */
  --dock-w:64px; --float-end:16px;
  --shadow-1:inset 0 1px 0 rgba(255,255,255,.6), 0 1px 2px rgba(0,0,0,.035), 0 2px 10px rgba(0,0,0,.04);
  --shadow-pop:0 10px 36px rgba(0,0,0,.14), 0 2px 8px rgba(0,0,0,.05);
  --shadow-key:inset 0 1px 0 rgba(255,255,255,.38), inset 0 -1px 0 rgba(0,0,0,.10),
    0 1px 0 color-mix(in oklab, var(--brand-600) 45%, transparent),
    0 4px 12px -6px color-mix(in oklab, var(--brand) 55%, transparent);
  --shadow-card:var(--shadow-1);
  --shadow-win-focus:0 0 0 1px color-mix(in oklab, var(--brand) 35%, transparent);
  --focus:0 0 0 3px var(--ring);
  --focus-outline:2px solid var(--accent);   /* where a glow would be clipped (frames, the divider) */
  --focus-offset:2px;

  /* ── type: the ladder (V0.1.7 ② codex): every font-size in the OS is a rung.
     2xs badges/fineprint · xs meta labels · sm action links · md secondary text
     · ui controls · h card headings · rd chat reading · base document body
     · lg inputs/emphasis · xl page titles · 2xl hero · 3xl money/big numbers
     · display the lock screen. (V0.1.8: the UI rungs stepped down ½px — a sans face
     sits visually larger than the serif did at the same size.) */
  --fs-2xs:11px; --fs-xs:12px; --fs-sm:12.5px; --fs-md:13px; --fs-ui:13.5px;
  --fs-h:14px; --fs-rd:15px; --fs-base:15px; --fs-lg:15.5px;
  --fs-xl:20px; --fs-2xl:24px; --fs-3xl:28px;
  --fs-display:clamp(4.5rem, 14vw, 9rem);
  --fs-reader:17px;                          /* the reader stage's long-form body */
  /* the DOCUMENT scale (DESIGN-TOKENS v1 --fs-1..7, rem so it follows the reader's zoom):
     for documents, books and plans inside the check pane and the .ai/.com pages —
     UI chrome keeps the px role ladder above; two purposes, one file */
  --fs-1:.75rem; --fs-2:.875rem; --fs-3:1rem; --fs-4:1.125rem; --fs-5:1.375rem; --fs-6:1.75rem; --fs-7:2.25rem;
  --lh-tight:1.2; --lh-body:1.5; --lh-reading:1.7;
  /* ── space: same group small, across groups large; no stray magic numbers ── */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px; --sp-8:64px;
  /* ── columns ── */
  --doc-col:42rem;                           /* T1 document column */
  --reading-col:46rem;                       /* the conversation's reading column */
  --wide-col:78rem;                          /* T2 workbenches */
  --reading-width:68ch;                      /* a document's body inside the check pane */
  /* ── density & touch ── */
  --tap:44px;                                /* the touch target; danger never adjacent */
  --row-h:48px; --control-h:44px;            /* --density-comfortable (default and touch) */
  --density:comfortable;                     /* "comfortable" | "compact" — what html[data-density] chose */
  --win-h:44px;

  /* ── WORK-FRAME v1 (OS-DESIGN §3): the sizes the frame reasons with. gram-stage.js
     reads them through getComputedStyle and measures #main's available width (not the
     device) — so no query in hoop.css repeats a number from here. ── */
  --wf-compact-max:599px;                    /* < 600: one focus, check is an overlay */
  --wf-medium-min:600px; --wf-medium-max:839px;   /* one focus; split only if both fit */
  --wf-expanded-min:840px; --wf-expanded-max:1199px;   /* split, chancellor 320–400 */
  --wf-large-min:1200px;                     /* split, chancellor 360–440, no third pane */
  --wf-chancellor-min:288px; --wf-chancellor-ideal:360px; --wf-chancellor-max:440px;
  --wf-check-min:480px;
  --wf-divider:1px; --wf-divider-hit:12px;   /* the line you see · the line you grab */
  --wf-page-max:1440px;                      /* beyond this: breathing room, not panes */
  --wf-safe-top:env(safe-area-inset-top); --wf-safe-bottom:env(safe-area-inset-bottom);
  --wf-safe-start:env(safe-area-inset-left); --wf-safe-end:env(safe-area-inset-right);
  /* ── the frame's layer ladder (the rest of the OS keeps its 0.2.12 rungs; 0.3.0 ladders them) ── */
  --z-pane:2; --z-pane-raised:3; --z-drawer:7; --z-strip:8; --z-chrome:40; --z-float:50;

  /* Three content voices + one sealed wordmark (codex art. 4). --font stays as an
     alias of the body voice so token-riding pieces outside hoop.css follow. */
  --font-ui:"Inter","Source Han Sans SC","Noto Sans Arabic","Inter Fallback",system-ui,
    -apple-system,"PingFang SC","Segoe UI",sans-serif;
  --font-brand:"Source Serif 4","Source Han Serif SC",Georgia,"Songti SC","Noto Naskh Arabic",serif;
  --font-wordmark:"HoopGram Wordmark","Marcellus","Source Serif 4",Georgia,serif;
  --font:var(--font-ui);
  --mono:"Maple Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
/* compact density: precise pointers only, and only when the owner chose it in settings;
   the tap target does not shrink — critical actions keep their 44px hit area */
html[data-density="compact"]{--row-h:36px; --control-h:32px; --density:compact}

/* ── the three themes: EVERY colour token is defined on bare :root above; these
   blocks only override. 1. default (no data-theme) = 系统黄蓝: warm light, warm dark via
   media. 2. data-theme="light" = 白色为主. 3. data-theme="dark" = 暗色为主. ── */
@media (prefers-color-scheme: dark){ :root:not([data-theme]){
  --brand:#F5B301; --brand-600:#FFC426; --on-brand:#221A00;
  --brand-ink:#F5B301; --brand-soft:rgba(245,179,1,.15);
  --accent:#5B9BEF; --ring:rgba(91,155,239,.45);
  --bg:#141410; --surface:#1C1B15; --surface-2:#191812;
  --fg:#E8E6DD; --dim:#8F8B7E;
  --line:color-mix(in oklab, var(--fg) 11%, transparent);
  --line-soft:color-mix(in oklab, var(--fg) 7%, transparent);
  --line-2:color-mix(in oklab, var(--fg) 20%, transparent);
  --paper:#24231C;
  --code:#1E1D16; --own:#262317; --lift:rgba(255,255,255,.05);
  --ok:#6fbf85; --bad:#e66767; --warn:#d99a55;
  --hl-key:#cf8fe8; --hl-str:#9cbf6f; --hl-num:#dba064; --hl-com:#6e6d68; --hl-fn:#7fb2f5;
  --scrim:rgba(0,0,0,.5);
  --shadow-1:inset 0 1px 0 rgba(255,255,255,.07), 0 1px 2px rgba(0,0,0,.25), 0 2px 10px rgba(0,0,0,.22);
  --shadow-pop:0 10px 36px rgba(0,0,0,.5), 0 2px 8px rgba(0,0,0,.3);
  --shadow-key:inset 0 1px 0 rgba(255,255,255,.28), inset 0 -1px 0 rgba(0,0,0,.25),
    0 4px 14px -6px color-mix(in oklab, var(--brand) 40%, transparent);
  --glass-bg:color-mix(in oklab, var(--surface) 55%, transparent);
  --glass-rim:inset 0 1px 0 rgba(255,255,255,.12), inset 0 -1px 0 rgba(0,0,0,.35),
    0 0 0 1px rgba(255,255,255,.06);
}}
/* 白色为主: forced light, whiter and cooler, amber at its quietest */
:root[data-theme="light"]{
  --brand:#F5B301; --brand-600:#E0A200; --on-brand:#221A00;
  --brand-ink:#96700A; --brand-soft:rgba(245,179,1,.11);
  --accent:#2A78D6; --ring:rgba(42,120,214,.4);
  --bg:#FDFDFC; --surface:#FFFFFF; --surface-2:#F6F6F4;
  --fg:#171614; --dim:#8A8880;
  --line:color-mix(in oklab, var(--fg) 8%, transparent);
  --line-soft:color-mix(in oklab, var(--fg) 5%, transparent);
  --line-2:color-mix(in oklab, var(--fg) 15%, transparent);
  --code:#F5F4F0; --own:#F3F1EA; --lift:rgba(23,22,20,.05);
  --ok:#3F9E58; --bad:#D03B3B; --warn:#C77B28;
  --hl-key:#a626a4; --hl-str:#50771c; --hl-num:#b25d0e; --hl-com:#9c9b96; --hl-fn:#2a63c9;
  --scrim:rgba(20,18,10,.4);
}
/* 暗色为主: forced charcoal, amber at its boldest */
:root[data-theme="dark"]{
  --brand:#F5B301; --brand-600:#FFC426; --on-brand:#221A00;
  --brand-ink:#F5B301; --brand-soft:rgba(245,179,1,.15);
  --accent:#5B9BEF; --ring:rgba(91,155,239,.45);
  --bg:#141410; --surface:#1C1B15; --surface-2:#191812;
  --fg:#E8E6DD; --dim:#8F8B7E;
  --line:color-mix(in oklab, var(--fg) 11%, transparent);
  --line-soft:color-mix(in oklab, var(--fg) 7%, transparent);
  --line-2:color-mix(in oklab, var(--fg) 20%, transparent);
  --paper:#24231C;
  --code:#1E1D16; --own:#262317; --lift:rgba(255,255,255,.05);
  --ok:#6fbf85; --bad:#e66767; --warn:#d99a55;
  --hl-key:#cf8fe8; --hl-str:#9cbf6f; --hl-num:#dba064; --hl-com:#6e6d68; --hl-fn:#7fb2f5;
  --scrim:rgba(0,0,0,.5);
  --shadow-1:inset 0 1px 0 rgba(255,255,255,.07), 0 1px 2px rgba(0,0,0,.25), 0 2px 10px rgba(0,0,0,.22);
  --shadow-pop:0 10px 36px rgba(0,0,0,.5), 0 2px 8px rgba(0,0,0,.3);
  --shadow-key:inset 0 1px 0 rgba(255,255,255,.28), inset 0 -1px 0 rgba(0,0,0,.25),
    0 4px 14px -6px color-mix(in oklab, var(--brand) 40%, transparent);
  --glass-bg:color-mix(in oklab, var(--surface) 55%, transparent);
  --glass-rim:inset 0 1px 0 rgba(255,255,255,.12), inset 0 -1px 0 rgba(0,0,0,.35),
    0 0 0 1px rgba(255,255,255,.06);
}

/* ── still: the owner asked the OS not to move (system setting, or the Hoop's own
   Accessibility switch). Every duration becomes 0ms here, so CSS AND the scripts that
   read the tokens (motion.js) go quiet from one place; hoop.css additionally pins
   animation/transition durations to ~0 for anything that carries a literal loop. ── */
@media (prefers-reduced-motion:reduce){
  :root{--motion-fast:0ms; --motion-base:0ms; --motion-slow:0ms; --motion-stagger:0ms;
    --motion-breathe:0ms; --motion-pulse:0ms; --motion-shimmer:0ms}
}
html.hoop-reduce-motion{--motion-fast:0ms; --motion-base:0ms; --motion-slow:0ms; --motion-stagger:0ms;
  --motion-breathe:0ms; --motion-pulse:0ms; --motion-shimmer:0ms}
