/* Every value the home page can tune. Edit by hand or in the design system (system.html), which saves this file. */
:root {
  /* Color */
  --page: #f7f7f7;
  --card: #fcfdff;
  --line: #eeeeee;
  --surface: #ffffff;
  --selected: #faf7f7;
  /* The nav tabs' hover: Grow's fill under a hovered tab (at --jot-hover-fill strength), and Classic's pill while it sits
     on a tab that is not the current one. */
  --tab-hover: #faf7f7;
  --highlight: #f0f0f0;
  --highlight-ink: #111111;
  --ink: #242221;
  --ink-nav: #221c19;
  --mute: #6f6b69;
  --icon: #b0aeae;
  --icon-hover: #887d7d;
  --name-ink: #000000;
  /* Greens, lightest to darkest. Use the darkest very sparingly. Light always comes from the top left: the lighter greens
     go on edges that face it, the darker on edges that face away. */
  --green-1: #d4ddb1;
  --green-2: #aeca8f;
  --green-3: #5f9480;
  --green-4: #286672;

  /* Grain over every page, from rachelchen.tech: fractal noise, blended in by --grain-blend at --grain-opacity, tiled at
     --grain-size. While it is on, the canvas takes her page colour, --grain-bg, and the page behind it --grain-page, our
     grey, so the canvas still stands off the page (her site has one surface; ours has two). These are her exact values,
     read off her live site on 2026-10-11 (body::after: multiply, 0.3, 240px; body: --background #fff); the Tune panel's
     Rachel's exact chip puts them back. --grain: 0 takes it off (the home page's Tune panel has the switch). */
  --grain: 1;
  --grain-opacity: 0.2;
  --grain-size: 240px;
  --grain-blend: multiply;
  --grain-bg: #ffffff;
  --grain-page: #f7f7f7;

  /* Goodbye (index.html, footer.js), Figma node 991:15005: the photo and its line behind the card, shown when the card
     scrolls up past the end. --footer-peek is how much of the card stays showing at the top: 0 scrolls it all the way
     off, its outline too (Keyan, 2026-10-11; Figma left 35px).
     --footer-grain is Rachel's grain again, over the photo only, on top of the grain over the page; --footer-grain-size
     its tile. The print (print.js) reaches the photo too, as its own SVG filter in either engine. */
  --footer-peek: 0px;
  /* --footer-parallax: how fast the goodbye rises as the card leaves, a share of the scroll speed (style.css). 0 holds it
     still behind the card; 0.3 is emmiwu.com's footer; 1 would ride up with the card. */
  --footer-parallax: 0.3;
  --footer-grain: 0.08;
  --footer-grain-size: 240px;
  /* --footer-art: 1 draws the photo as an asset of the scene (goodbye-art.js): on the scene's art-pixel grid, in
     --footer-colours flat colours of its own, corners stepped, then printed as the scene is. 0: the plain photo. */
  --footer-art: 1;
  --footer-colours: 15;
  --footer-ink: #4e4947;

  /* Texture (texture.js; the Tune panel's Texture tab). More grains and papers over every page, each on at 1, so they
     stack with Rachel's. Where each comes from is in texture.js.
     mesq: mesq.me's seeded tile (assets/textures/mesq). blend is overlay, soft-light or multiply; strength is their grain
     (0.0293); size is one texel in screen px (0.25); colour is how far the channels part (0.207); blotch adds big soft
     patches; drift is texels a second the grain slides, 0 for still.
     specks: Ballpoint Gambit's paper specks and fibres. pastel: the alive about page's soft-light tooth. board: the
     board game's black and white grain. riso: riso-photo's cream stock; cream 0 keeps only the fibres and tooth.
     crumpled: Ballpoint Gambit's creased sheet. dots: an even riso dot screen. grid: a dot grid. scale multiplies a tile's size. */
  --texture-mesq: 0;
  --texture-mesq-blend: multiply;
  --texture-mesq-strength: 0.0135;
  --texture-mesq-size: 0.3;
  --texture-mesq-colour: 0.333;
  --texture-mesq-blotch: 0;
  --texture-mesq-drift: 0;
  --texture-specks: 0;
  --texture-specks-opacity: 0.5;
  --texture-specks-scale: 1;
  --texture-specks-fibres: 0.05;
  --texture-pastel: 0;
  --texture-pastel-opacity: 0.32;
  --texture-pastel-scale: 0.4;
  --texture-board: 0;
  --texture-board-amount: 0.08;
  --texture-board-scale: 1;
  --texture-riso: 0;
  --texture-riso-strength: 0.22;
  --texture-riso-cream: 0;
  --texture-crumpled: 0;
  --texture-crumpled-opacity: 1;
  --texture-dots: 0;
  --texture-dots-density: 0.11;
  --texture-dots-spacing: 4;
  --texture-dots-angle: 28;
  --texture-dots-ink: #f8f8f8;
  --texture-grid: 0;
  --texture-grid-spacing: 4;
  --texture-grid-radius: 0.3;
  --texture-grid-ink: #242221;
  --texture-grid-opacity: 0.1;

  /* Type */
  --text-size: 13px;
  --text-leading: 1.4;
  --bar-size: 14px;
  --bar-leading: 16px;
  --bar-track: -0.21px;
  --name-weight: 350;

  /* Canvas */
  --card-top: 12px;
  --card-side: 9px;
  --card-radius: 24px;
  --card-line: 1px;
  --card-min: 480px;

  /* Status line */
  --status-top: 49.5px;

  /* About */
  --about-top: 53px;

  /* Scene */
  --scene-scale: 1.25;
  --scene-x: 0px;
  --scene-y: -15.5px;
  --scene-shadow: #efebec;

  /* Dots and arrow */
  --down-bottom: 56px;
  --down-fade: 1;

  /* Projects. --project-width: the column's width as a share of the window, so it grows with the page (41.7vw is the
     old 720px at 1728 wide, Keyan's main breakpoint); it never goes under --project-min, and never past the card. */
  --project-width: 41.7vw;
  --project-min: 480px;
  --project-gap: 120px;
  --project-title: 18px;
  --project-text: 15px;
  --project-columns: 24px;
  /* The slash between a name and what follows it, in project titles (Agents at Ramp / Summer 2026) and About rows
     (Ramp / Product Design Intern). 1 greys it like the words after it; 0 keeps it the black of the words before. */
  --slash-dim: 1;
  --project-leading: 1.4;
  /* Project hover, press and open (project-open.js, after yiyang.ch). The grey grows out past the project by the spread,
     the cover's picture shrinks inside its frame on press. A click opens the case study (case.js, --case-*). */
  --project-hover-color: #f5f5f5;
  /* The date (/ Summer 2026) darkens to this as the hover grey comes in (projects.css). */
  --project-date-hover: #5a5252;
  --project-grey: 1;
  --project-hover-spread: 18px;
  --project-hover-radius: 26px;
  /* The cover's picture sits zoomed in by this at rest and comes back to its own size on press. */
  --project-zoom: 1.05;
  /* Magnetism: the grey leans toward the cursor on an elastic, by up to --project-magnet; the side it moves toward
     reaches out with its speed by up to --project-stretch, and the other side stays. */
  --project-magnet: 10px;
  --project-stretch: 4px;
  --project-drift: 3px;
  --project-wrap-type: ease; --project-wrap-ease: sheet; --project-wrap-mode: time; --project-wrap-duration: 500ms;
  --project-wrap-bounce: 0; --project-wrap-stiffness: 175; --project-wrap-damping: 26.5; --project-wrap-mass: 1;
  /* A click (projects.css, project-open.js): CSS transitions on cubic-bezier curves ("x1, y1, x2, y2"). The whole
     project, its grey jelly and all, presses down to --project-press-scale over --project-press-duration on
     --project-press-curve, quick, and springs back over --project-release-duration on --project-release-curve, which
     overshoots a touch, after holding down for --project-release-delay. The picture stays as it is. */
  --project-press-scale: 0.985;
  /* A click can also fade, on the press's own timing, to --project-press-opacity: off, image (the cover alone) or jelly
     (the whole project, its grey jelly and all). */
  --project-press-fade: off;
  --project-press-opacity: 0.95;
  --project-press-duration: 150ms; --project-press-curve: 0.2, 0.8, 0.2, 1;
  --project-release-duration: 300ms; --project-release-curve: 0.34, 1.56, 0.64, 1; --project-release-delay: 0ms;
  /* How long after the click the case study opens: 0 at once; longer lets the press and its hold play out first. */
  --project-open-delay: 110ms;
  /* --project-hold: 1 keeps a project pressed after the pointer lets go, until its case study opens (--project-open-delay
     after the click), then lets it spring up, for a slowed-down press; 0 lets go as usual. With it on, the project and
     its grey container start back up --project-release-lead before the case study opens. (Open lab, 2026-10-12.) */
  --project-hold: 1;
  --project-release-lead: 50ms;
  --project-magnet-type: spring; --project-magnet-ease: out; --project-magnet-mode: time; --project-magnet-duration: 400ms;
  --project-magnet-bounce: 0.12; --project-magnet-stiffness: 171.3; --project-magnet-damping: 23; --project-magnet-mass: 1;
  /* Project field (project-field.html, field.js): Keyan's pixel plants along the bottom of a project's cover. Each art pixel
     is --field-scale screen pixels. The plants stand below the cover and reach into it by up to --field-creep, and the field
     runs --field-side past each side. They grow up a pixel row at a time over --field-grow, stepping at --field-fps, and
     start one after another over --field-spread. */
  --field-scale: 2;
  --field-creep: 12px;
  --field-side: 28px;
  --field-spread: 900ms;
  --field-fps: 12;
  /* How the growth spreads: --field-from up (plants start at random), left, right, or sides (both ends to the middle).
     --field-grain: pixels grow alone (1), or in blocks that many art pixels wide. */
  --field-from: up;
  --field-grain: 4;
  /* --field-hover: 1 grows the field only while the project is hovered, and sends it back into the ground after. */
  --field-hover: 1;
  /* --field-on: 0 takes the flowers away. The home page no longer grows them (Keyan, 2026-10-11); project-field.html does. */
  --field-on: 1;
  /* --field-density: how close the plants stand. 1 as drawn, 0.5 half as many, 2 twice as many. */
  --field-density: 0.95;
  --field-grow-type: ease; --field-grow-ease: out; --field-grow-mode: time; --field-grow-duration: 1100ms;
  --field-grow-bounce: 0; --field-grow-stiffness: 175; --field-grow-damping: 26.5; --field-grow-mass: 1;
  /* Jelly frame (project-frame.html, frame.js): each cover inside a painted, deckled frame, after mesq.me/jelly-painting,
     that wobbles like its jelly. --frame-mode: pixel (whole pixels of --frame-pixel, like the pixel art), painted (fine
     soft grain, like the site) or plain (the cover's own rounded frame). The frame sits --frame-inset inside the cover with
     corners of --frame-radius; its sides waver by --frame-wave and its edge breaks into grain over --frame-grain. It
     breathes by --frame-idle, boings by about --frame-wobble on hover, sways up to --frame-sway with the pointer, and is
     drawn at --frame-fps. */
  --frame-mode: plain;
  --frame-pixel: 2;
  --frame-inset: 22px;
  --frame-radius: 10px;
  --frame-wave: 0px;
  --frame-grain: 7px;
  --frame-idle: 1px;
  --frame-wobble: 2px;
  --frame-sway: 0px;
  --frame-fps: 43;
  /* --frame-speck: how big the painted grain's specks are, in px. --frame-uneven: how far irregular bites reach into the
     edge, so it is less straight. --frame-edge: the opacity of the outer band of the frame, --frame-edge-band deep.
     --frame-hover: 1 shows the frame only while the project is hovered, growing in and out over --frame-show. */
  --frame-speck: 4px;
  --frame-uneven: 4.5px;
  --frame-edge: 1;
  --frame-edge-band: 17px;
  --frame-hover: 0;
  /* --frame-cover: how far the framed cover grows past each side, to make up for the frame's inset (22px lines the frame
     up with the text column). */
  --frame-cover: 18px;
  --frame-show-type: ease; --frame-show-ease: out; --frame-show-mode: time; --frame-show-duration: 320ms;
  --frame-show-bounce: 0; --frame-show-stiffness: 385; --frame-show-damping: 39; --frame-show-mass: 1;
  --frame-jelly-type: spring; --frame-jelly-ease: out; --frame-jelly-mode: time; --frame-jelly-duration: 650ms;
  --frame-jelly-bounce: 0.55; --frame-jelly-stiffness: 175; --frame-jelly-damping: 26.5; --frame-jelly-mass: 1;
  /* Cursor effects on the jelly frame page (frame-cursor.js), on everything inside the grey. --frame-effect: off, rotate
     (turns up to --frame-turn with the cursor's side), magnet (moves up to --frame-pull toward it), parallax (the
     layers part by up to --frame-depth) or tilt (magnet, rotate, and a 3D tilt of up to --frame-tilt). Each follows the
     cursor on the --frame-follow spring. */
  --frame-effect: magnet;
  /* --frame-project: which project the jelly frame page shows, ramp or roblox. */
  --frame-project: ramp;
  --frame-turn: 1deg;
  --frame-pull: 6px;
  /* The goodbye's raccoon and "Thanks for visiting :)" follow the same way, but pull by their own amount. */
  --goodbye-pull: 18px;
  --frame-depth: 8px;
  --frame-tilt: 3deg;
  /* --frame-grey-from: where the grey grows from on that page: edges (as on home), cursor (a box opening from where the
     cursor came in) or ripple (a circle from there). It closes toward where the cursor left. */
  --frame-grey-from: edges;
  /* The image's own line on that page (the Default style): its colour and width at rest. On hover it turns the grey's
     colour (--project-hover-color) as the grey comes in. */
  --frame-line-color: #f4f4f4;
  --frame-line-width: 2px;
  --frame-follow-type: spring; --frame-follow-ease: out; --frame-follow-mode: time; --frame-follow-duration: 450ms;
  --frame-follow-bounce: 0.12; --frame-follow-stiffness: 135.4; --frame-follow-damping: 20.5; --frame-follow-mass: 1;
  /* Sunlight in the jelly (frame-light.js), after josephines.world: the cursor brings autumn sun into the cover.
     --light-mode: off, glow, bubbles, dapple or ring (a halo with no light in its middle, -width wide, as a share of its
     size). Colours from the autumn art (butter, amber, orange), shared by all four;
     the Light tab has Japanese sets from nipponcolors.com. Each variation keeps its own look: -fade is 0 for a hard edge,
     1 soft from the middle; -distance is how far outside the cover the cursor starts to bring the light; -bubble is how
     much it flows and bubbles; -autumn is how strongly a tint under the light turns the picture's own colour warm. */
  --light-mode: ring;
  --light-sun: #f9bf45;
  --light-warm: #f19483;
  --light-ember: #eea9a9;
  --light-glow-opacity: 0.6; --light-glow-size: 240px; --light-glow-fade: 0.75; --light-glow-blur: 8px;
  --light-glow-distance: 140px; --light-glow-bubble: 0.6; --light-glow-blend: overlay; --light-glow-autumn: 0.35;
  --light-bubbles-opacity: 0.7; --light-bubbles-size: 200px; --light-bubbles-fade: 0.7; --light-bubbles-blur: 6px;
  --light-bubbles-distance: 120px; --light-bubbles-bubble: 1; --light-bubbles-blend: overlay; --light-bubbles-autumn: 0.35;
  --light-dapple-opacity: 0.8; --light-dapple-size: 27px; --light-dapple-fade: 0.8; --light-dapple-blur: 4px;
  --light-dapple-distance: 140px; --light-dapple-bubble: 0.6; --light-dapple-blend: overlay; --light-dapple-autumn: 0.35;
  --light-ring-opacity: 0.6; --light-ring-size: 57px; --light-ring-width: 0.78; --light-ring-fade: 0.05; --light-ring-blur: 15px;
  --light-ring-distance: 140px; --light-ring-bubble: 1.74; --light-ring-blend: overlay; --light-ring-autumn: 0.15;
  /* The ring alone: -grow, how much bigger it gets while it moves fast, as a share of its size; -spin, how far it turns
     the way it went as the mouse slows down, when it also shrinks back. Both on --light-settle (an ease out; the Motion
     tab can make it a spring). */
  --light-ring-spin: 12deg; --light-ring-grow: 0.12;
  --light-settle-type: ease; --light-settle-ease: out; --light-settle-mode: time; --light-settle-duration: 600ms;
  --light-settle-bounce: 0.3; --light-settle-stiffness: 76.2; --light-settle-damping: 12.2; --light-settle-mass: 1;
  /* --light-delay: the light heads for where the cursor was this long ago, then --light-follow smooths it. */
  --light-delay: 15ms;
  /* --light-inside: 1 brings the light only while the cursor is over the image (each variation's -distance is then
     unused); 0 lets it wake as the cursor comes within -distance. */
  --light-inside: 1;
  /* --light-click: on a click the light swells outward up to half this bigger, on --light-press, and a faint wave of
     light flows out from it; 0 turns it off. */
  --light-click: 0.7;
  --light-press-type: spring; --light-press-ease: out; --light-press-mode: physics; --light-press-duration: 800ms;
  --light-press-bounce: 0.25; --light-press-stiffness: 42.8; --light-press-damping: 7.9; --light-press-mass: 0.95;
  --light-follow-type: spring; --light-follow-ease: out; --light-follow-mode: time; --light-follow-duration: 900ms;
  --light-follow-bounce: 0.15; --light-follow-stiffness: 33.9; --light-follow-damping: 9.9; --light-follow-mass: 1;
  --light-in-type: ease; --light-in-ease: out; --light-in-mode: time; --light-in-duration: 620ms;
  --light-in-bounce: 0; --light-in-stiffness: 71.3; --light-in-damping: 16.9; --light-in-mass: 1;

  /* Case study sheet (case.js, case.css), after an iOS sheet and Figma keyan-folio-v2 node 922:26601.
     It sits --case-drop lower than the card, so the page behind peeks out above it. Coming in, it grows from --case-from-scale,
     rises --case-from-y, sharpens from --case-from-blur (0 for now: Keyan took the blur off) and fades in. The page behind shrinks to --case-back-scale from its top edge,
     dims to --case-back-opacity and blurs by --case-back-blur, --case-stagger after the sheet starts. Its content whites out
     by --case-back-white (1 is fully), so no text shows in the strip above the sheet.
     The sheet fades in and out over --case-fade, faster than it moves, so the two pages never show through each other for long.
     The page behind whites out over --case-white-fade, ahead of the sheet's fade, so nothing on it shows through the sheet.
     0 is at once: the first frame drawn after a click lands 15 to 25ms in, so any longer white-out is still part way
     there on it, and the clicked project showed as a faint ghost under the sheet. */
  /* The cover's height: short, at its own shape (1259 by 551), or full, the sheet's height less 10px above and below. */
  --case-hero: full;
  /* Icons: smooth, or pixel, the pixel art Keyan drew (home/icons/*-pixel.svg): the bar's three links (links.js) and the
     clover on the case study dividers. Then the divider's clover size, and the room between it and the hairline either side. */
  --icons: smooth;
  --case-divider-size: 16px;
  --case-divider-clover: #dcdcdc;
  --case-divider-gap: 12px;
  /* How the bar's section tabs turn into the project tabs as a case study opens, and back: fade (case.js), or one of the
     experiments in home/nav-swap/: morph, roll, cascade, slide, handoff. */
  --case-nav-swap: handoff;
  /* The hand-off (home/nav-swap/handoff.js), tuned in home/nav-lab.html. One pill springs from the section tab to the
     project tab, its back edge --handoff-stretch softer (0 to 0.9) so it stretches on the way; the tray widens or narrows
     to the new row; the labels fade out and in, blurring by up to --handoff-blur as they go (0 keeps them sharp); and the
     whole nav dips to --handoff-scale and comes back (1 for no dip). It waits --handoff-open-delay on opening and
     --handoff-close-delay on closing, and the arriving labels start --handoff-in-delay after the leaving ones.
     Each motion is a set as in Tab motion below. An ease may also be custom: its own -curve, as CSS takes it. */
  --handoff-blur: 0.75px;
  --handoff-scale: 0.985;
  --handoff-stretch: 0.3;
  --handoff-open-delay: 60ms;
  --handoff-close-delay: 20ms;
  --handoff-in-delay: 71ms;
  --handoff-pill-type: spring; --handoff-pill-ease: out; --handoff-pill-curve: .2, .8, .2, 1; --handoff-pill-mode: time; --handoff-pill-duration: 320ms;
  --handoff-pill-bounce: 0.15; --handoff-pill-stiffness: 267.7; --handoff-pill-damping: 27.82; --handoff-pill-mass: 1;
  --handoff-grow-type: ease; --handoff-grow-ease: enter; --handoff-grow-curve: .16, 1, .3, 1; --handoff-grow-mode: time; --handoff-grow-duration: 350ms;
  --handoff-grow-bounce: 0; --handoff-grow-stiffness: 171.3; --handoff-grow-damping: 26.18; --handoff-grow-mass: 1;
  --handoff-shrink-type: spring; --handoff-shrink-ease: out; --handoff-shrink-curve: .2, .8, .2, 1; --handoff-shrink-mode: time; --handoff-shrink-duration: 280ms;
  --handoff-shrink-bounce: 0; --handoff-shrink-stiffness: 237.2; --handoff-shrink-damping: 30.8; --handoff-shrink-mass: 1;
  --handoff-out-type: ease; --handoff-out-ease: out; --handoff-out-curve: .2, .8, .2, 1; --handoff-out-mode: time; --handoff-out-duration: 100ms;
  --handoff-out-bounce: 0; --handoff-out-stiffness: 2741.6; --handoff-out-damping: 104.72; --handoff-out-mass: 1;
  --handoff-in-type: ease; --handoff-in-ease: out; --handoff-in-curve: .2, .8, .2, 1; --handoff-in-mode: time; --handoff-in-duration: 240ms;
  --handoff-in-bounce: 0; --handoff-in-stiffness: 476; --handoff-in-damping: 43.63; --handoff-in-mass: 1;
  --handoff-dip-type: ease; --handoff-dip-ease: out; --handoff-dip-curve: .2, .8, .2, 1; --handoff-dip-mode: time; --handoff-dip-duration: 100ms;
  --handoff-dip-bounce: 0; --handoff-dip-stiffness: 1398.8; --handoff-dip-damping: 74.8; --handoff-dip-mass: 1;
  --handoff-rise-type: ease; --handoff-rise-ease: out; --handoff-rise-curve: .2, .8, .2, 1; --handoff-rise-mode: time; --handoff-rise-duration: 100ms;
  --handoff-rise-bounce: 0.25; --handoff-rise-stiffness: 171.3; --handoff-rise-damping: 19.63; --handoff-rise-mass: 1;
  /* The gap between the cover and the sheet's edges, the same on every side. The cover's corners are --card-radius less
     this, so its curve runs parallel to the sheet's. */
  --case-hero-inset: 7px;
  /* The blur along the case study's bottom edge (case.js): 1 on, 0 off; how far up it reaches (--case-blur-height), its
     strength at the very bottom (--case-blur-max, halving layer by layer above), and how much of it shows over the page,
     0 to 1 (--case-blur-amount). After julienaudiger.com. */
  --case-blur: 1;
  --case-blur-height: 63px;
  --case-blur-max: 4.5px;
  --case-blur-amount: 1;
  /* The same blur along the top edge too: 1 on, 0 off. It shares the strength, distance and amount above. */
  --case-blur-top: 0;
  /* The width of the case study's text (everything in its middle column), a share of the window: 33.9vw is 585px on a
     1728px window, as in Figma. Phones take the full column instead (case.css). */
  --case-text-width: 38.1vw;
  --case-drop: 8px;
  --case-from-scale: 0.995;
  --case-from-y: 32px;
  --case-from-blur: 20.5px;
  /* From the open lab (2026-10-12). The sheet is sharp --case-blur-until after it starts coming up (0 ties the blur to the
     whole motion). Its start can stretch on one axis (--case-from-scale-x, -y multiply --case-from-scale) and it grows
     about --case-origin-x, -y. --case-clip 1 cuts it off at the card's bottom edge; --case-trim takes that much off its
     bottom. --case-mirror: how it closes: 1 the values and curve it opened with, all together; reverse the opening played
     backwards; 0 its own --case-out. --case-pblur 1 adds a progressive blur while it moves, --case-pblur-max at its
     bottom edge thinning out up to --case-pblur-reach of its height, clearing with the motion or by --case-pblur-until. */
  --case-blur-until: 90ms;
  --case-from-scale-x: 1;
  --case-from-scale-y: 1;
  --case-origin-x: 50%;
  --case-origin-y: 50%;
  --case-clip: 0;
  --case-trim: 4px;
  --case-mirror: 0;
  /* Off (2026-10-13): even sliced, its backdrop blurs still made Chrome drop the sheet for a frame or two in a window
     (a blank white sheet, or a white band at its bottom). Keyan's recording of the home page showed it. */
  --case-pblur: 0;
  --case-pblur-max: 6px;
  --case-pblur-reach: 40%;
  --case-pblur-until: 0ms;
  --case-fade: 150ms;
  --case-white-fade: 352ms;
  --case-back-scale: 0.98;
  --case-back-opacity: 0.87;
  --case-back-white: 1;
  /* From one project to the next the pages slide sideways inside the sheet by --case-slide of its width (1 is a full page). */
  --case-slide: 1;
  --case-back-blur: 0.25px;
  --case-stagger: 50ms;
  --case-in-type: ease; --case-in-ease: enter; --case-in-mode: time; --case-in-duration: 500ms;
  --case-in-bounce: 0; --case-in-stiffness: 175; --case-in-damping: 26.5; --case-in-mass: 1;
  --case-back-type: ease; --case-back-ease: custom; --case-back-mode: physics; --case-back-duration: 225ms; --case-back-curve: 0.25, 0.46, 0.45, 0.94;
  --case-back-bounce: 0.08; --case-back-stiffness: 300; --case-back-damping: 30; --case-back-mass: 0.79;
  --case-out-type: ease; --case-out-ease: custom; --case-out-mode: time; --case-out-duration: 280ms; --case-out-curve: 0.165, 0.84, 0.44, 1;
  --case-out-bounce: 0; --case-out-stiffness: 560; --case-out-damping: 47.5; --case-out-mass: 1;
  --case-swap-type: spring; --case-swap-ease: sheet; --case-swap-mode: time; --case-swap-duration: 350ms;
  --case-swap-bounce: 0; --case-swap-stiffness: 195; --case-swap-damping: 28; --case-swap-mass: 1;

  /* Panel turn (track.js), from one nav tab's panel to the next: josephines.world's page transition, her values exactly
     (read off her live site, 2026-10-12). The beats are in track.js. Parts rise or sink --page-travel, blurred by up to
     --page-blur. Going right, the new panel's parts start --page-rise-delay in, each --page-rise-stagger after the one
     above; going left, the old panel's parts leave --page-sink-stagger apart. Each motion is a set as in Tab motion below,
     all on her one curve. */
  /* jos (the turn above) or drift (the one before it: the old panel drifts sideways and fades, then the new one drifts in). */
  --panel-turn: jos;
  --page-travel: 18px;
  --page-blur: 0.6px;
  --page-rise-delay: 420ms;
  --page-rise-stagger: 30ms;
  --page-sink-stagger: 35ms;
  --page-rise-type: ease; --page-rise-ease: custom; --page-rise-curve: .32, .08, .18, 1; --page-rise-mode: time; --page-rise-duration: 720ms;
  --page-rise-bounce: 0; --page-rise-stiffness: 52.9; --page-rise-damping: 14.54; --page-rise-mass: 1;
  --page-sink-type: ease; --page-sink-ease: custom; --page-sink-curve: .32, .08, .18, 1; --page-sink-mode: time; --page-sink-duration: 620ms;
  --page-sink-bounce: 0; --page-sink-stiffness: 71.3; --page-sink-damping: 16.89; --page-sink-mass: 1;
  --page-white-type: ease; --page-white-ease: custom; --page-white-curve: .32, .08, .18, 1; --page-white-mode: time; --page-white-duration: 900ms;
  --page-white-bounce: 0; --page-white-stiffness: 33.8; --page-white-damping: 11.64; --page-white-mass: 1;
  --page-turn-type: ease; --page-turn-ease: custom; --page-turn-curve: .32, .08, .18, 1; --page-turn-mode: time; --page-turn-duration: 1200ms;
  --page-turn-bounce: 0; --page-turn-stiffness: 19; --page-turn-damping: 8.73; --page-turn-mass: 1;

  /* Print (print.js): the art looks printed. --print-variant is off, soft or bold; each variant keeps its own parts.
     A part is on at 1, off at 0. split-px: how far the red and blue plates sit out of register.
     scroll-px: how far they part at full scroll speed, up or down with the scroll; --print-settle brings them back.
     halftone: dots that darken the shadows toward --print-ink; size is the dot spacing, reach the lightest shade (0 to 1)
     that gets dots and how big they grow below it; cutoff (0 to 1) keeps them darker than it, so they stay in the shadows
     (1 leaves it to the reach); each (1) reads every scene element's lightness within its own range, darkest to
     lightest, so a light element (the tall tree) gets dots in its own shadows too (0: one scale for the page).
     grain: a still grain on the screen, amount 0 to 1, size in device pixels. Soft started
     from mesq.me's values, Bold turns each part up to see it, and mesq is the mesq.me playground's halftone (0.315,
     6.89px, reach 0.484) and misprint (0.522, here 0.5px) alone.
     split-layer: where the misprint goes. mix: into the art, each plate a colour channel moved (RGB) or an ink where its
     copy is darker than the art (inks), so the art itself shifts; top: a layer over the art, each moved copy printing
     its plate colour as a ghost where it is darker than what lies under it, at split-layer-opacity, so flat areas keep
     their colour; under: the same ghosts behind the art, only where the art is not. top and under take the plate
     colours in either plate mode. */
  --print-variant: soft;
  /* svg: an SVG filter on the art and a grain layer. three: print-gl.js redraws the art in WebGL and prints it in one pass. */
  --print-engine: svg;
  --print-ink: #ac9de1;
  /* pixel: edges step as in mesq.me (three.js only). pixel-size: device pixels per art pixel.
     wobble: px each asset's edge moves as it turns and breathes on its own. */
  --print-soft-pixel: 1; --print-soft-pixel-size: 1.5; --print-soft-wobble: 1px;
  --print-soft-split: 0; --print-soft-split-px: 0.5px; --print-soft-split-layer: mix; --print-soft-split-layer-opacity: 0.4; --print-soft-scroll: 0; --print-soft-scroll-px: 1.5px;
  --print-soft-halftone: 1; --print-soft-halftone-amount: 0.41; --print-soft-halftone-size: 3.25px; --print-soft-halftone-reach: 0.64; --print-soft-halftone-cutoff: 0.34; --print-soft-halftone-each: 0;
  --print-soft-grain: 0; --print-soft-grain-amount: 1; --print-soft-grain-size: 1;
  /* Plate colours: rgb splits the red and blue channels; ink lays plate-a one way and plate-b the other (print.js, TEMPLATES).
     A plate's opacity, 0 to 1, fades its ink, or in rgb how far its channel moves with it. */
  --print-soft-plates: ink; --print-soft-plate-a: #e97400; --print-soft-plate-b: #5f9480;
  --print-soft-plate-a-opacity: 1; --print-soft-plate-b-opacity: 1;
  --print-bold-pixel: 1; --print-bold-pixel-size: 3; --print-bold-wobble: 2px;
  --print-bold-split: 0; --print-bold-split-px: 1.5px; --print-bold-split-layer: mix; --print-bold-split-layer-opacity: 0.4; --print-bold-scroll: 0; --print-bold-scroll-px: 6px;
  --print-bold-halftone: 1; --print-bold-halftone-amount: 0.7; --print-bold-halftone-size: 5px; --print-bold-halftone-reach: 0.95; --print-bold-halftone-cutoff: 1; --print-bold-halftone-each: 1;
  --print-bold-grain: 1; --print-bold-grain-amount: 0.8; --print-bold-grain-size: 1.5;
  --print-bold-plates: rgb; --print-bold-plate-a: #ff4fa6; --print-bold-plate-b: #62e3ff;
  --print-bold-plate-a-opacity: 1; --print-bold-plate-b-opacity: 1;
  --print-mesq-pixel: 0; --print-mesq-pixel-size: 2.5; --print-mesq-wobble: 1px;
  --print-mesq-split: 1; --print-mesq-split-px: 0px; --print-mesq-split-layer: mix; --print-mesq-split-layer-opacity: 0.4; --print-mesq-scroll: 0; --print-mesq-scroll-px: 1.5px;
  --print-mesq-halftone: 1; --print-mesq-halftone-amount: 0.407; --print-mesq-halftone-size: 3.86px; --print-mesq-halftone-reach: 0.562; --print-mesq-halftone-cutoff: 0; --print-mesq-halftone-each: 1;
  --print-mesq-grain: 0; --print-mesq-grain-amount: 0.25; --print-mesq-grain-size: 1;
  --print-mesq-plates: ink; --print-mesq-plate-a: #c46243; --print-mesq-plate-b: #838a2d;
  --print-mesq-plate-a-opacity: 1; --print-mesq-plate-b-opacity: 1;
  --print-settle-type: spring; --print-settle-ease: out; --print-settle-mode: time; --print-settle-duration: 450ms;
  --print-settle-bounce: 0; --print-settle-stiffness: 135.4; --print-settle-damping: 23.27; --print-settle-mass: 1;
  /* Scroll with the three.js print (print-gl.js, 3): the wheel moves the page in the same frame as the art, so the art
     never trails the text. --scroll-sync: locked (at once), spring (glides there on --scroll-glide and settles with a
     small overshoot, the whole page together: bounce 0.25 overshoots about 3%, 11px on a 400px turn) or browser (the
     browser's own; the art trails on a fast scroll). */
  --scroll-sync: browser;
  --scroll-glide-type: spring; --scroll-glide-ease: out; --scroll-glide-mode: time; --scroll-glide-duration: 500ms;
  --scroll-glide-bounce: 0.25; --scroll-glide-stiffness: 109.7; --scroll-glide-damping: 15.71; --scroll-glide-mass: 1;

  /* Bar */
  --bar-height: 47px;
  --bar-top: 16px;
  --bar-side: 45px;
  --bar-bottom: 18px;

  /* Tabs */
  --tabs-pad: 6px;
  --tabs-gap: 4px;
  --tabs-radius: 14px;
  --tabs-lift: 1.5px;
  --tab-pad-y: 8px;
  --tab-pad-x: 14px;
  --tab-radius: 10px;
  --tab-dim: 0.8;

  /* Tab motion. tabs.js reads these on every move.
     A motion is a set of tokens under one name (motion.js reads them):
       -type      ease or spring
       -ease      out, enter or exit: one of the --motion-ease-* curves, for an ease
                  (or custom: the motion's own -curve, "x1, y1, x2, y2" as CSS takes it)
       -mode      time or physics, for a spring
       -duration  the ease's length, or the spring's visual duration in time mode
       -bounce    0 to 0.95, for a spring in time mode
       -stiffness, -damping, -mass   for a spring in physics mode
     --tab-squash 1 turns on squash and stretch: the stretch, dip, squeeze and release below. 0 leaves them out. Amounts are 0 to 1. */
  /* Variant: grow (the default: hover fills, a click grows the pill out of the tab, --grow-* below) or classic (the pill
     follows hover, with optional squash and stretch). Keyan kept these two on 2026-10-11; the Tune panel's Look tab and
     the design system switch between them. jotion, hybrid, tactile and tray still work in tabs.js but are not offered.
     Grow takes Jotion's hover, press and release. Its beats are in tabs.js. Scales are sizes at each beat, 1 is normal.
     Fill is the hover fill's opacity. */
  --tab-variant: classic;
  --jot-hover-scale: 1.04;
  --jot-hover-fill: 0.5;
  --jot-hover-appear: 60ms;
  /* The hover's fade, in and out, on CSS's ease: the tab's fill and its text, and the case study's Orchard link and
     section links. Very quick, but a fade: at 60ms the fill was nearly full on the first frame. */
  --jot-hover-fade: 150ms;
  --jot-press-scale: 0.94;
  --jot-lift-scale: 1.05;
  --jot-hover-type: ease; --jot-hover-ease: out; --jot-hover-mode: time; --jot-hover-duration: 140ms;
  --jot-hover-bounce: 0; --jot-hover-stiffness: 1385; --jot-hover-damping: 74.5; --jot-hover-mass: 1;
  --jot-press-type: ease; --jot-press-ease: out; --jot-press-mode: time; --jot-press-duration: 100ms;
  --jot-press-bounce: 0; --jot-press-stiffness: 2740; --jot-press-damping: 104.5; --jot-press-mass: 1;
  --jot-release-type: ease; --jot-release-ease: out; --jot-release-mode: time; --jot-release-duration: 100ms;
  --jot-release-bounce: 0; --jot-release-stiffness: 2740; --jot-release-damping: 104.5; --jot-release-mass: 1;
  --jot-glide-type: ease; --jot-glide-ease: out; --jot-glide-mode: time; --jot-glide-duration: 300ms;
  --jot-glide-bounce: 0; --jot-glide-stiffness: 305; --jot-glide-damping: 35; --jot-glide-mass: 1;
  --jot-lift-type: ease; --jot-lift-ease: out; --jot-lift-mode: time; --jot-lift-duration: 140ms;
  --jot-lift-bounce: 0; --jot-lift-stiffness: 1385; --jot-lift-damping: 74.5; --jot-lift-mass: 1;
  --jot-settle-type: ease; --jot-settle-ease: out; --jot-settle-mode: time; --jot-settle-duration: 240ms;
  --jot-settle-bounce: 0; --jot-settle-stiffness: 475; --jot-settle-damping: 43.5; --jot-settle-mass: 1;
  /* Hybrid: the pill follows hover as in classic, keeping its size, then after --hyb-delay grows to --hyb-hover-scale with a bounce.
     Press sinks it to --hyb-press-scale and release springs it back. Its beats are in tabs.js. */
  --hyb-hover-scale: 1.05;
  --hyb-delay: 60ms;
  --hyb-press-scale: 0.92;
  --hyb-glide-type: spring; --hyb-glide-ease: out; --hyb-glide-mode: time; --hyb-glide-duration: 240ms;
  --hyb-glide-bounce: 0.13; --hyb-glide-stiffness: 475; --hyb-glide-damping: 38; --hyb-glide-mass: 1;
  --hyb-hover-type: spring; --hyb-hover-ease: out; --hyb-hover-mode: time; --hyb-hover-duration: 300ms;
  --hyb-hover-bounce: 0.4; --hyb-hover-stiffness: 304; --hyb-hover-damping: 21; --hyb-hover-mass: 1;
  --hyb-press-type: ease; --hyb-press-ease: out; --hyb-press-mode: time; --hyb-press-duration: 120ms;
  --hyb-press-bounce: 0; --hyb-press-stiffness: 1900; --hyb-press-damping: 87; --hyb-press-mass: 1;
  --hyb-release-type: spring; --hyb-release-ease: out; --hyb-release-mode: time; --hyb-release-duration: 320ms;
  --hyb-release-bounce: 0.45; --hyb-release-stiffness: 267; --hyb-release-damping: 18; --hyb-release-mass: 1;
  /* Tactile (Figma 928:34736): no tray and no pill. Each tab is its own white key with a lip, at --tac-rest strength.
     Hover darkens it, shows --tac-hover-fill and lifts it --tac-hover-height with no shadow, press pushes it into the page, and a click raises it --tac-raise-height
     over a shadow on the page. Its beats are in tabs.js. */
  --tac-gap: 8px;
  --tac-radius: 0px;
  --tac-rest: 0.5;
  --tac-ink: #38322f;
  --tac-hover-fill: #faf8f7;
  --tac-hover-height: 3px;
  --tac-raise-height: 8.5px;
  --tac-press-depth: 1.5px;
  --tac-hover-type: ease; --tac-hover-ease: out; --tac-hover-mode: time; --tac-hover-duration: 120ms;
  --tac-hover-bounce: 0; --tac-hover-stiffness: 1900; --tac-hover-damping: 87; --tac-hover-mass: 1;
  --tac-press-type: ease; --tac-press-ease: out; --tac-press-mode: time; --tac-press-duration: 70ms;
  --tac-press-bounce: 0; --tac-press-stiffness: 5590; --tac-press-damping: 149.5; --tac-press-mass: 1;
  --tac-release-type: ease; --tac-release-ease: out; --tac-release-mode: time; --tac-release-duration: 120ms;
  --tac-release-bounce: 0; --tac-release-stiffness: 1900; --tac-release-damping: 87; --tac-release-mass: 1;
  --tac-raise-type: spring; --tac-raise-ease: out; --tac-raise-mode: time; --tac-raise-duration: 320ms;
  --tac-raise-bounce: 0.3; --tac-raise-stiffness: 267; --tac-raise-damping: 23; --tac-raise-mass: 1;
  --tac-drop-type: ease; --tac-drop-ease: exit; --tac-drop-mode: time; --tac-drop-duration: 140ms;
  --tac-drop-bounce: 0; --tac-drop-stiffness: 1400; --tac-drop-damping: 75; --tac-drop-mass: 1;
  /* Tray (Figma 931:35311): the tabs stay plain in the tray, and a click pops the current one out as a key, --tray-raise-height
     up over the tray's edge. Hover lifts a tab --tray-hover-height. It shares Tactile's hover fill, press and release. */
  --tray-radius: 10px;
  --tray-hover-height: 1px;
  --tray-raise-height: 22px;
  --tray-raise-type: spring; --tray-raise-ease: out; --tray-raise-mode: time; --tray-raise-duration: 380ms;
  --tray-raise-bounce: 0.25; --tray-raise-stiffness: 190; --tray-raise-damping: 20.7; --tray-raise-mass: 1;
  --tray-drop-type: ease; --tray-drop-ease: exit; --tray-drop-mode: time; --tray-drop-duration: 180ms;
  --tray-drop-bounce: 0; --tray-drop-stiffness: 845; --tray-drop-damping: 58; --tray-drop-mass: 1;
  /* Grow: Jotion with no glide. A click shows the pill on the tab at --grow-from-scale and grows it out to full size,
     while the tab it left shrinks its bg back in. Hover, press and release use the --jot-* values. */
  --grow-from-scale: 0.8;
  --grow-in-type: spring; --grow-in-ease: out; --grow-in-mode: time; --grow-in-duration: 280ms;
  --grow-in-bounce: 0.15; --grow-in-stiffness: 350; --grow-in-damping: 31.8; --grow-in-mass: 1;
  --grow-out-type: ease; --grow-out-ease: out; --grow-out-mode: time; --grow-out-duration: 160ms;
  --grow-out-bounce: 0; --grow-out-stiffness: 1070; --grow-out-damping: 65.4; --grow-out-mass: 1;
  --tab-glide-type: spring;
  --tab-glide-ease: out;
  --tab-glide-mode: time;
  --tab-glide-duration: 240ms;
  --tab-glide-bounce: 0.13;
  --tab-glide-stiffness: 475;
  --tab-glide-damping: 38;
  --tab-glide-mass: 1;
  --tab-squash: 0;
  --tab-release-type: spring;
  --tab-release-ease: out;
  --tab-release-mode: physics;
  --tab-release-duration: 350ms;
  --tab-release-bounce: 0.4;
  --tab-release-stiffness: 225;
  --tab-release-damping: 18;
  --tab-release-mass: 1;
  --tab-stretch: 0.3;
  --tab-dip: 0.1;
  --tab-squeeze: 0.08;
  --tab-dip-time: 340ms;

  /* Links */
  --link-size: 32px;
  --link-icon: 20px;
  --link-gap: 8px;

  /* The cursor on a mouse or trackpad (cursor.js): dot, the dot cursor (Figma node 1001:487); stemless, macOS's arrow
     without its stem across the whole site; or system, the normal arrow.
     Over anything clickable the dot shrinks to --cursor-hover-scale and hops --cursor-hop-height every --cursor-hop-time.
     It follows the pointer exactly, with no motion of its own while moving. */
  --cursor: stemless;
  --cursor-size: 12px;
  --cursor-hover-scale: 0.75;
  --cursor-hop-height: 3.5px;
  --cursor-hop-time: 420ms;
  /* --cursor-hover: hop, or spiral: the dot turns into a spiral that grows to --cursor-spiral-scale and turns once
     every --cursor-spin-time. */
  --cursor-hover: spiral;
  /* --cursor-color: dark, or white with a #2d2222 outline. */
  --cursor-color: white;
  /* The bush cursor (cursor.js): 1 shows a "Rummage" label by the arrow over the autumn bush; the label grows from
     --cursor-label-from of its size as it slides right, on --cursor-label. --cursor-bush-arrow picks the arrow there:
     stemless, or stem (the normal arrow). With --cursor: stemless the site's arrow stays. */
  --cursor-bush: 0;
  --cursor-bush-arrow: stem;
  /* --cursor-label-style: chip, the word on a grey chip, or word, the word alone beside the arrow. */
  --cursor-label-style: chip;
  --cursor-label-from: 0.6;
  --cursor-label-type: ease; --cursor-label-ease: enter; --cursor-label-mode: time; --cursor-label-duration: 260ms;
  --cursor-label-bounce: 0; --cursor-label-stiffness: 405.6; --cursor-label-damping: 40.3; --cursor-label-mass: 1;
  --cursor-spiral-scale: 1.4;
  --cursor-spin-time: 1400ms;
  --cursor-spiral-type: ease; --cursor-spiral-ease: out; --cursor-spiral-mode: time; --cursor-spiral-duration: 320ms;
  --cursor-spiral-bounce: 0; --cursor-spiral-stiffness: 267.7; --cursor-spiral-damping: 32.7; --cursor-spiral-mass: 1;
  --cursor-shrink-type: spring; --cursor-shrink-ease: out; --cursor-shrink-mode: time; --cursor-shrink-duration: 300ms;
  --cursor-shrink-bounce: 0.35; --cursor-shrink-stiffness: 304.6; --cursor-shrink-damping: 22.7; --cursor-shrink-mass: 1;

  --link-radius: 10px;

  /* Motion. Every hover, press and fade uses these two times and three curves. motion.js hands them to the scripts.
     The tab glide and release are motions of their own (--tab-glide-*, --tab-release-*), and intro.js holds its own stage values. */
  --motion-ease-out: cubic-bezier(.2, .8, .2, 1);
  --motion-ease-enter: cubic-bezier(.16, 1, .3, 1);
  --motion-ease-exit: cubic-bezier(.4, 0, 1, 1);
  --motion-ease-sheet: cubic-bezier(.32, .72, 0, 1);
  /* Motion presets: the standard easings, in, out and in-out, each from gentle (quad) to strong (expo, circ). Any CSS can
     use them (transition: scale 200ms var(--ease-out-quint)), and the Tune panel's curve controls offer them in a list. */
  --ease-in-quad: cubic-bezier(.55, .085, .68, .53);
  --ease-in-cubic: cubic-bezier(.550, .055, .675, .19);
  --ease-in-quart: cubic-bezier(.895, .03, .685, .22);
  --ease-in-quint: cubic-bezier(.755, .05, .855, .06);
  --ease-in-expo: cubic-bezier(.95, .05, .795, .035);
  --ease-in-circ: cubic-bezier(.6, .04, .98, .335);
  --ease-out-quad: cubic-bezier(.25, .46, .45, .94);
  --ease-out-cubic: cubic-bezier(.215, .61, .355, 1);
  --ease-out-quart: cubic-bezier(.165, .84, .44, 1);
  --ease-out-quint: cubic-bezier(.23, 1, .32, 1);
  --ease-out-expo: cubic-bezier(.19, 1, .22, 1);
  --ease-out-circ: cubic-bezier(.075, .82, .165, 1);
  --ease-in-out-quad: cubic-bezier(.455, .03, .515, .955);
  --ease-in-out-cubic: cubic-bezier(.645, .045, .355, 1);
  --ease-in-out-quart: cubic-bezier(.77, 0, .175, 1);
  --ease-in-out-quint: cubic-bezier(.86, 0, .07, 1);
  --ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
  --ease-in-out-circ: cubic-bezier(.785, .135, .15, .86);
  --motion-fast: .14s;
  --motion-medium: .24s;
  --press-scale: 0.97;
  --icon-lift: -2px;
  --icon-tilt: -8deg;
  --icon-tilt-random: 0.4;
  --ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1);
  --hit-min: 44px;
}
