/* Pocket Factory design tokens. This is the one file to edit.
 *
 * Each token is a CSS custom property, so the cascade can change it for one device or one part:
 *   <pf-knob style="--shadow: 0"></pf-knob>   this knob casts no shadow
 *   pf-pad { --radius: .2 }                    the keys of the pad get sharper corners
 *
 * The shape tokens are numbers in units. --u is the only length: one unit in pixels.
 * A part reads the tokens when it connects and on a `pf-tokens` event, never in each frame.
 */

@property --u { syntax: '<length>'; inherits: true; initial-value: 12px; }
/* --rows and --stitch do not inherit, so the parts on a case with rows get no rows. */
@property --rows { syntax: '*'; inherits: false; initial-value: none; }
@property --stitch { syntax: '<number>'; inherits: false; initial-value: 0; }
/* --corner-shape-device: the shapes of the corners of a case, as --corner-shape of a key. It does not inherit, so a case
   on a case keeps its own corners. */
@property --corner-shape-device { syntax: '*'; inherits: false; initial-value: round; }
/* The edge of a part (see the edges below). The edge tokens do not inherit, so the parts on a case with a chamfer keep
   their own edges; their start values are the sharp edge. */
@property --edge-shape { syntax: '*'; inherits: false; initial-value: sharp; }
@property --edge-width { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --edge-depth { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --edge-steps { syntax: '<number>'; inherits: false; initial-value: 2; }
/* --edge-profile: the line of a custom edge, as the stops of a mask: t from the outline (0) in to the top (1), h from the
   foot of the edge (0) up to the top (1). none is a straight slope. */
@property --edge-profile { syntax: '*'; inherits: false; initial-value: none; }
/* --edge-blend: a solid whose edge goes down to the surface fades into the surface over this width at its foot, in units,
   so the two meet with no line; 0 is none. */
@property --edge-blend { syntax: '<number>'; inherits: false; initial-value: 0; }
/* --edge-sides: the share of the width of the edge on each side, top, right, bottom and left, as a margin of CSS: 1 the
   edge, 2 an edge twice as wide, 0 none, as the side of a key that goes into its case. */
@property --edge-sides { syntax: '*'; inherits: false; initial-value: 1; }
/* The mask of the top of a part (see the masks below). The mask tokens do not inherit, so the parts on a case with a
   dish keep their own flat tops. */
@property --mask-profile { syntax: '*'; inherits: false; initial-value: none; }
@property --mask-depth { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --mask-gradient { syntax: '*'; inherits: false; initial-value: outline; }
@property --mask-angle { syntax: '<number>'; inherits: false; initial-value: 0; }
/* --mask-blend: how each mask of a part with two or more masks joins the heights of the masks before it: add, min or
   max (blend() in mask.js). --mask-smooth: how round a min or a max joins two masks, from 0 (a crease) to 1. */
@property --mask-blend { syntax: '*'; inherits: false; initial-value: add; }
@property --mask-smooth { syntax: '<number>'; inherits: false; initial-value: 0; }
/* The pattern on the top of a part (pattern.js): the part in its mark slot, repeated, as round cuts (holes), raised
   embosses (bumps) or prints (dots). --pattern-layout is how the marks repeat: stagger, grid, rings or cells (one mark in
   each cell of the --grid-* of the part), and none gives no pattern. --pattern-pitch is the distance between two marks in
   units, one value or across and down; --pattern-margin keeps the field 1 to 4 units in from the sides. The size of a
   mark is the size of its part. They do not inherit, so the parts on a case with a pattern get no pattern. A part takes a
   named pattern with its pattern attribute (the patterns below). --holes: `pitch size`, --holes-margin and --holes-pattern
   are the old short form of a pattern of round holes. */
@property --pattern-layout { syntax: '*'; inherits: false; initial-value: none; }
@property --pattern-pitch { syntax: '*'; inherits: false; initial-value: .55; }
@property --pattern-margin { syntax: '*'; inherits: false; initial-value: 1; }
@property --holes { syntax: '*'; inherits: false; initial-value: none; }
@property --holes-margin { syntax: '*'; inherits: false; initial-value: 1; }
@property --holes-pattern { syntax: '*'; inherits: false; initial-value: stagger; }
/* The opening through the top of a part (opening.js), as the mouth of a port: --opening is its distance in from the
   outline, 1 to 4 values in units, and none gives no opening. --opening-radius is its corner in units (auto: the corner
   of the outline less the distance). Its lip falls into it, --opening-edge units wide, in the shape of an edge
   (--opening-shape): sharp is a wall in the light of --opening-wall, and the other shapes are lit as a relief. They do
   not inherit. */
@property --opening { syntax: '*'; inherits: false; initial-value: none; }
@property --opening-radius { syntax: '*'; inherits: false; initial-value: auto; }
@property --opening-shape { syntax: '*'; inherits: false; initial-value: sharp; }
@property --opening-edge { syntax: '*'; inherits: false; initial-value: 0; }
@property --opening-wall { syntax: '*'; inherits: false; initial-value: .55 .3; }
/* The grid of a surface (src/core/layout.js, docs/grid.md): --grid-cell, --grid-gap and --grid-margin in units,
   --grid-cols and --grid-rows, and --grid-align. They do not inherit, so a case in a case keeps its own grid. With no
   grid, a cell is one unit. */
@property --grid-cell { syntax: '*'; inherits: false; initial-value: 1; }
@property --grid-gap { syntax: '*'; inherits: false; initial-value: 0; }
@property --grid-margin { syntax: '*'; inherits: false; initial-value: 0; }
@property --grid-cols { syntax: '*'; inherits: false; initial-value: none; }
@property --grid-rows { syntax: '*'; inherits: false; initial-value: none; }
@property --grid-align { syntax: '*'; inherits: false; initial-value: center; }
/* --height: the height of one part above its surface, in units. With none, a part has the height of its kind (HEIGHT in
   lighting.js). It does not inherit, so a device with --height does not lift the parts on it. */
@property --height { syntax: '*'; inherits: false; }
/* The shape of a rocker key (pf-key variant=rocker): --rock is how far each end moves when it rocks, in units, and
   --groove the width of the groove across its middle, in parts of its half width (0 for none). They do not inherit. */
@property --rock { syntax: '*'; inherits: false; initial-value: .26; }
@property --groove { syntax: '*'; inherits: false; initial-value: .12; }
/* The print on a key (pf-key): --legend-weight is the weight of the legend, --legend-y the middle of the legend in parts
   of the height of the top (auto: in the middle of a short key and high on a tall one), and --icon-size the size of the
   icon or the SVG on the top, in parts of the top. --label-size gives the size of the legend. They do not inherit. */
@property --legend-weight { syntax: '*'; inherits: false; initial-value: 350; }
@property --legend-y { syntax: '*'; inherits: false; initial-value: auto; }
@property --icon-size { syntax: '*'; inherits: false; initial-value: 1; }
/* --icon-y places the middle of the icon in parts of the height of the top (auto: the middle), and --icon-color gives the
   icon (the first of a list) a color of its own (none: --mark). */
@property --icon-y { syntax: '*'; inherits: false; initial-value: auto; }
@property --icon-color { syntax: '*'; inherits: false; }
@property --icon-colors { syntax: '*'; inherits: false; }
/* The lines of a legend (a | starts a new line): --legend-align (center, start or end), --legend-inset (units in from the
   side, for start and end), --legend-line (units from the middle of a line to the next; 0: 1.5 times the size), and
   --legend-next-size and --legend-next-color for the lines after the first (0 and none: as the first). */
@property --legend-align { syntax: '*'; inherits: false; initial-value: center; }
@property --legend-inset { syntax: '*'; inherits: false; initial-value: .2; }
@property --legend-line { syntax: '*'; inherits: false; initial-value: 0; }
@property --legend-next-size { syntax: '*'; inherits: false; initial-value: 0; }
@property --legend-next-color { syntax: '*'; inherits: false; }
/* The letters of the last line of an LCD, each in the next color of this list (pf-lcd.js); none: the ink. */
@property --ink-colors { syntax: '*'; inherits: false; initial-value: none; }
/* The press of a key (the feels sink and push below): --press-sink, how far the key sinks when it is pressed, in units;
   --press-dim, the part of its color that it keeps; --press-rim, the part of the light of its rim that it keeps;
   --press-shade, how dark the rim of its hole shades it (inset() in lighting.js); and --travel, how far a side button
   (pf-key side=…) goes in toward its case, in units. The start values are the feel sink. They do not inherit. */
@property --press-sink { syntax: '*'; inherits: false; initial-value: .16; }
@property --press-dim { syntax: '*'; inherits: false; initial-value: .9; }
@property --press-rim { syntax: '*'; inherits: false; initial-value: .5; }
@property --press-shade { syntax: '*'; inherits: false; initial-value: .75; }
@property --travel { syntax: '*'; inherits: false; initial-value: .1; }
/* --sink: how far a key sits below the face of its case, or a solid below the rim of the cut that holds it, in units, so the
   rim shades the edges that face the light (a slot button adds its own depth). It does not inherit. */
@property --sink { syntax: '*'; inherits: false; initial-value: 0; }
/* --knurl: the width of a ring of sharp teeth round the top of a round solid, as round the cap of a knob, in units; about
   one tooth each 2 px. 0 is no knurl. It does not inherit. */
@property --knurl { syntax: '*'; inherits: false; initial-value: 0; }
/* The top of a round solid. --spun: spun metal, as a dial of brushed steel: the fine rings of a lathe, one each half pixel,
   this strong, in a bow tie of light that stays while the solid turns (spun() in paint.js). --dome: a dome that bulges this
   much, as the head of a pin, lit with the spec, the gloss and the sat of its material (bowl() in paint.js). A spun or a
   domed top has the light of its own shape, so it takes no finish. 0 is a flat top. They do not inherit. */
@property --spun { syntax: '*'; inherits: false; initial-value: 0; }
@property --dome { syntax: '*'; inherits: false; initial-value: 0; }
/* --bevel: a polished bevel round the top of a solid, or a polished collar round a cut, over its lip: `width slope spec
   gloss`, the width in units, the slope (above 0 it rises toward the middle, below 0 it falls into the cut), and the spec
   and the gloss of the polish (.9 and 30 by default). 0 is none. It does not inherit. */
@property --bevel { syntax: '*'; inherits: false; initial-value: 0; }
/* --skirt: the top of a solid is smaller than its outline by this on each side, 1 to 4 widths in units as a margin of CSS,
   and a skirt slopes from the top down to the outline, as the sides of the cap of a key (skirt() in skirt.js). The skirt
   is steeper where it is narrow. --skirt-rise: how high the top stands above the outline; --top-radius: the corner of
   the top; --top-round: the width of the round edge of the top, all in units. 0 is no skirt. They do not inherit. */
@property --skirt { syntax: '*'; inherits: false; initial-value: 0; }
@property --skirt-rise { syntax: '*'; inherits: false; initial-value: 0; }
@property --top-radius { syntax: '*'; inherits: false; initial-value: 0; }
@property --top-round { syntax: '*'; inherits: false; initial-value: 0; }
/* --engrave: a print is cut into the surface under it: `light dark`, the light of the far wall of each cut (a copy of the
   ink in white, half a pixel away from the light) and the dark of the cut (the alpha of the ink). 0 is flat ink. It does
   not inherit. */
@property --engrave { syntax: '*'; inherits: false; initial-value: 0; }
/* The shadow that a part casts on the surface under it, and the light that it bounces there (castShadow() and reflect()
   in lighting.js). With none, a part has the shadow of its kind. --shadow-alpha: how dark it is; --shadow-fall: how much
   lighter its far end is; --shadow-blur: a factor on its soft edge; --shadow-contact: the dark line where the part meets
   the surface. --bounce-alpha and --bounce-spread: how strong the light that it bounces is, and how far it spreads, in
   units. They do not inherit. */
@property --shadow-alpha { syntax: '*'; inherits: false; }
@property --shadow-fall { syntax: '*'; inherits: false; }
@property --shadow-blur { syntax: '*'; inherits: false; }
@property --shadow-contact { syntax: '*'; inherits: false; }
@property --bounce-alpha { syntax: '*'; inherits: false; }
@property --bounce-spread { syntax: '*'; inherits: false; }
/* A solid (pf-solid): --hairline is the dark line round its edge, where it turns down to the surface, 0 for none, and
   --slab makes its top lighter toward the light and darker away from it, by that part of its color (slab() in
   lighting.js). --glare puts a soft pool of light over its top, as a studio light makes on bead-blasted aluminum: its
   middle at x of the width and y of the height, its radius as a part of the width, and the part of the color that it
   adds, as `x y radius strength` (glare() in lighting.js); none by default. They do not inherit. */
@property --hairline { syntax: '*'; inherits: false; initial-value: .3; }
@property --slab { syntax: '*'; inherits: false; initial-value: 0; }
@property --glare { syntax: '*'; inherits: false; }
/* --rim-light: the light of the lit rim round the top of a part on its side toward the light (finish() in lighting.js), and
   with a second value the dark of the rim on the far side. With none, a part has the rim of its kind. --finish: factors on
   the finish of a part, `sheen texture`: on its sheen and glare, and on the texture of its material. With none, a part has
   the finish of its kind. --rim-width: the width of the rim, in units (at least 1 px). They do not inherit. */
@property --rim-light { syntax: '*'; inherits: false; }
@property --rim-width { syntax: '<number>'; inherits: false; initial-value: .08; }
@property --finish { syntax: '*'; inherits: false; initial-value: none; }
/* The optics of a lens as the tops of round solids (optics.js), each in the middle of the solid, with the solid as the glass:
   --well: the glass, black (--keybed at .3), a little lighter in the middle, with a black bezel wall of this part of the
   radius and a dark line at its edge. --flutes: the barrel, a charcoal ring with a fluted face and a lit lip, from inner
   to outer, parts of the radius. --coat: the coated element in --lens, `element dome retainer`: its radius as a part of the
   radius, the tilt of its dome at its edge in radians (0: a crescent of coating toward the light; above 0 it mirrors the
   studio), and the ring of dark metal that holds it, a part of the radius (0 for none); with a lit edge, a violet glint
   on the far side, the rear element of --pupil (a part of the element, in --lens-rear) and the glint of the light, whose
   alpha is --glint. --cover: the cover glass over them, a soft pool of light toward the light and a thin bright arc at its
   lit edge, this strong. Such a top paints only its own look, and takes no finish. They do not inherit. */
@property --well { syntax: '*'; inherits: false; initial-value: none; }
@property --flutes { syntax: '*'; inherits: false; initial-value: none; }
@property --coat { syntax: '*'; inherits: false; initial-value: none; }
@property --pupil { syntax: '*'; inherits: false; initial-value: 0; }
@property --cover { syntax: '*'; inherits: false; initial-value: 0; }
/* --plain-lip: 1 gives the lip of a cut the flat color of its surface, as a polished chamfer, in place of the face of the
   surface with its texture and its light (hole() in lighting.js). It does not inherit. */
@property --plain-lip { syntax: '*'; inherits: false; initial-value: 0; }
/* A lens (pf-lens): --ring-sheen and --ring-gloss are the strength and the size of the highlight on the slope of its ring;
   --glint is the alpha of the small white glint near the middle of its element (0 for none); --lip is the width of a lit
   chamfer where the ring falls into the glass, in units (0 for none). They do not inherit. */
@property --ring-sheen { syntax: '*'; inherits: false; initial-value: .6; }
@property --ring-gloss { syntax: '*'; inherits: false; initial-value: 14; }
@property --glint { syntax: '*'; inherits: false; initial-value: .95; }
@property --lip { syntax: '*'; inherits: false; initial-value: 0; }

:root {
  /* ---------- light ---------- */
  --light-az: 210;          /* the direction toward the light, in degrees: 0 right, 90 down, 210 up and to the left */
  --light-el: 38;           /* the height of the light above the desk, in degrees */
  --ambient: .55;           /* the light on a surface that faces away from the light */
  /* the studio that a polished metal mirrors (studio() in light.js); a light below sets it too */
  --strips: 0 12 1;         /* the strip lights: each `side width level`, see the lights below */
  --sky: .55;               /* the brightness of the sky over a part */
  --horizon: .06;           /* the dark room at the horizon */
  --floor: .7;              /* the desk under a part */

  /* ---------- lighting layer: 1 is the default strength, and 0 turns the effect off ---------- */
  --shadow: 1;              /* the shadow that a part casts */
  --shadow-length: 1;
  --shadow-soft: 1;
  --reflect: 1;             /* the light that a part bounces onto the surface next to its lit side */
  --glow: 1;                /* the light of a part that is on: an LED, the lamp, a port with power */
  --rim: 1;                 /* the lit edge of a part */
  --grain: 1;               /* the texture of the material, and the grain of the desk */

  /* ---------- shape, in units ---------- */
  --u: min(calc((100vw - 32px) / 88), calc((100dvh - 32px) / 46));
  --radius: .45;            /* the corners of keys and small parts */
  --radius-device: 1.5;     /* the corners of a device case: 1 to 4 radii, from the top left and clockwise */
  --gap: .14;               /* the gap round a part in its hole */
  --emboss-depth: .15;      /* how deep pf-emboss is pressed in, or how high it is raised */
  /* the seat of a part: the surface sets it, see the seats below */
  --seat-edge: 0;           /* the width of the wall of the hole: 0 is a hairline of 1 px, and a wider wall is a rounder edge */
  --seat-shape: sharp;      /* the rim of a hole in the surface: sharp is the wall; chamfer, round or steps fall into the hole, --seat-edge wide */
  --seat-wall: .3 .5;       /* the light of the wall: on its side that faces the light, and on its side away from the light */
  --seat-depth: 0;          /* how deep the floor of the hole is, for the shadow of the rim on the floor */
  --margin: 0;              /* the room from the edge of a surface to the parts on it */
  --seat-radius: auto;      /* the corner of the hole, in units: auto is the corner of the part plus the gap */

  /* ---------- color ---------- */
  /* the theme: --primary, --secondary, --tertiary, --accent, --desk and --ink. Each part takes its color from a role,
     or from a role mixed with black or white, so a new value of a role recolors each part that takes it. Theme in
     src/react sets them. The lights and the glass keep their own colors. */
  --primary: #d4d4d2;       /* the case of a device and its metal: a screw, a port, the grill */
  --secondary: #ecebe6;     /* the controls on a case: a key, a knob, a switch, a fader */
  --tertiary: #2a2a2c;      /* the dark parts: a graphite knob, the pad, a speaker. Keep it dark: the pad prints light text */
  --desk: #e8e7e4;
  --ink: #1d1d1f;           /* printed text */
  --mark: var(--ink);       /* the indicator of a knob, the icon on a key */
  --ink-soft: #8b8b8e;
  --paper: #f7f6f3;         /* the flat ui (the ui page): a field, the active pill of a segmented control */
  --line: #d3d2ce;          /* the flat ui: a hairline that runs the full length of a row */
  --accent: #ff5a1f;        /* signal orange */
  --led-on: #ff4a1c;
  --dot: #e1250c;           /* the dot printed on the round cap of a key */
  --signal-r: #ff3b2f;      /* the three signals of the rgb module: its lenses, and the ring of a jack with that signal */
  --signal-g: #2fd35a;
  --signal-b: #2f7bff;
  --aluminum: var(--primary);
  --bone: var(--secondary);
  --graphite: var(--tertiary);
  --keybed: #171717;
  --glass: #c8d5ce;
  --cable-1: var(--accent);
  --cable-2: var(--tertiary);
  --cable-3: color-mix(in oklab, var(--secondary), white 19%);
  --cable-fleck: #f6f4ee;   /* the tracer yarn of a braided cable */
  --plug-metal: #f5f9ff;    /* the steel of a plug: the jack plug, and the tip of a molded plug */
  --tie: #252527;           /* the nylon of a zip tie */
  --velcro: #3a3f47;        /* the loops of a velcro strap */
  --lens: #26469a;          /* the blue coating of the element in a camera lens */
  --lens-rear: #7b6f5f;     /* the coating of the rear element of a camera lens, round its pupil */
  --silicone: #768baa;      /* the blue gray silicone of a speaker foot */
  --milk: #c4c2be;          /* the frosted diffuser of a light that is off */
  --bezel: #cececc;         /* the metal ring round the lens of a light and of a flash */

  /* ---------- type ---------- */
  --font: 'Geist', ui-sans-serif, system-ui, sans-serif;
  --mono: ui-monospace, 'SF Mono', Menlo, monospace;   /* code */
  --edge: clamp(16px, 4vw, 24px);   /* the side space of a page and of its header */
  --label-size: .62;        /* printed labels, in units */
  --stitch-length: .6;      /* the length of one stitch of a row of stitches, in units */

  /* ---------- feel ---------- */
  --detents: 24;            /* the clicks of a knob in one turn */
  --snap: 1;                /* how hard a knob pulls into its nearest detent: 0 for none (spin.js) */
  --snap-bounce: .45;       /* how much a knob bounces as it snaps in: 0 for none */
  --friction: 1;            /* how fast a spin slows down: 2 stops it in half the time */
  --snap-radius: 34;        /* the distance in pixels from a port at which a plug snaps in */
  --port-node: .8;          /* the width of the node of a free port on a desk with patch (base.css), in units */
  --port-node-offset: 1.2;  /* the distance from the mouth of a jack to the middle of its node, in units: a drag starts there too */
  --cable-width: .6;        /* in units */
  --swing-stiffness: 150;   /* the spring that pulls each point of a cable toward its route: lower trails more */
  --swing-damping: 7;       /* the damping of that spring: lower swings longer */
  --coil-width: 1.8;        /* the outer width of a curly cable, in units */
  --coil-pitch: .62;        /* the length of one turn of a curly cable at rest, in units */
  --coil-rest: .25;         /* the length of a curly cable at rest, as a part of its full length */
  /* The WebGPU cables (src/cables-gpu, /cables-lab): a chain of points that falls to the desk, slides on it and bends.
     The world of a desk: */
  --cable-gravity: 250;     /* the pull of gravity, in units per second²: a plug let go falls by it */
  --cable-tilt: 30;         /* the tilt of the desk toward the bottom of the screen, in degrees from 0 (flat) to 80: gravity pulls down the screen, so the slack of a cable hangs */
  --cable-substeps: 8;      /* the substeps of each step of 1/120 s, from 1 to 32: more costs more */
  --cable-collision: all;   /* a cable keeps its thickness apart from itself and from the other cables (all), only from itself (self), or none */
  /* The feel of a cable, the feel pvc (a feel of the feels below gives another set): */
  --cable-friction: .35;    /* the grip of the desk, as a part of the weight: a cable slides down a tilt steeper than this (.35 is 19°), so it hangs from its plugs, which grip 6 times as much */
  --cable-bend: .3;         /* how stiff a cable is against a bend: the part of a bend that each substep takes away */
  --cable-bounce: .1;       /* the part of its speed that a falling plug keeps when it hits the desk */
  --cable-damping: 1;       /* the damping inside a cable: 0 lets it ripple, 1 moves it as one piece */
  --cable-air: 3;            /* the drag of the air on a cable that moves, per second: more settles it sooner, and a pull does not fling it */
  --cable-stiffness: 1;     /* how stiff a cable is against a stretch: 1 for no give, lower gives as a spring */
  --cable-stretch: 1;       /* the longest that a pull makes a cable, as a part of its length */
  --cable-rest: 1;          /* the length of a cable at rest, as a part of its length: a coil is shorter, and pulls its plugs in */
  --plug-mass: .25;       /* the mass of a plug, as a part of the mass of its cable: a heavy plug drags behind a pull, a light one comes along */
  --cable-grab: 14;        /* how fast the hand that holds a plug or a cable follows the pointer, per second (a spring with no overshoot): less is softer and heavier */
  --cable-segments: auto;   /* the pieces of a cable: auto gives one for each 8 px */
  --cable-relief: .8;       /* the strain relief: how stiff a cable is against a bend where it leaves its plug, as --cable-bend */
  --cable-relief-length: 3; /* how far along the cable the relief reaches, in units: it blends into --cable-bend */
  --cable-bend-radius: 1.5; /* the least radius of a bend, in units: a cable never kinks tighter */
  --cable-release: 8;       /* how far a hand must pull a cable past its full reach, in units, to take the plug at its other end out of its port; none never (a magsafe plug lets go sooner, at the hold of its magnet) */
}

/* A rope is thicker than a molded cable. */
pf-cable[variant=braid], pf-cable[variant=check], pf-cable[variant=dots] { --cable-width: .85; }
/* The jacket of a cable is its material: pvc by default, or tpe, a silicone cable, which is a little thicker. The
 * cables in a clip take --cable-material. */
pf-clip { --cable-material: pvc; }
pf-cable[material=tpe] { --cable-width: .72; }
pf-cable { --led-on: #ffa31a; }   /* the light of a magsafe plug in a port: amber, as while it charges */
/* The plug of a cable (src/desk/pf-plug.js): its pieces from the tail to the head. --from and --to give the ends of a piece,
   in units from the tail, and --inset makes it narrower than the plug, in units on each side. The plug casts the shadow
   of its pieces, so they cast none. The steel is --plug-metal in the material steel; the boot and the body take the
   color of the cable. The jack is measured on a studio photo of a jack plug, to a third of a pixel: the knurled grip,
   the collar, the sleeve, the two black rings, the ring and the tip, a turned pipe with the profile of the photo. */
pf-plug > * { --shadow-alpha: 0; --bounce-alpha: 0; }
.pf-ghost > pf-plug { --shadow-alpha: 0; }
pf-plug > :is(.collar, .shaft, .band, .tip) { --color: var(--plug-metal); }
pf-plug > .head { --color: var(--plug-metal); --sky: .85; }   /* a bright sky, so the polished steel shines */
pf-plug > .barrel { --from: 0; --to: .9555; --pipe-width: 1.0696; --pipe-chamfer: .035; --color: color-mix(in srgb, var(--plug-metal), black 44%);
  --texture: diamonds 1 .00343u, diamonds .5 .00343u; }   /* the knurl of the photo: 80 diamonds round, 11 along, and two layers for its depth */
pf-plug > .collar { --from: .9555; --to: 1.08; --pipe-width: .7697; --pipe-fillet: .007; --rough: .5; }   /* a duller steel than the pin */
pf-plug > .shaft { --from: 1.08; --to: 2.3709; --pipe-width: .55; }
pf-plug > .ins1 { --from: 2.3709; --to: 2.4617; --pipe-width: .5345; }
pf-plug > .band { --from: 2.4617; --to: 2.8885; --pipe-width: .5397; }
pf-plug > .ins2 { --from: 2.8885; --to: 3.017; --pipe-width: .524; }
pf-plug > :is(.ins1, .ins2) { --color: #3a3a3c; }   /* the black rings between the contacts, a little narrower than them: they mirror the studio */
/* The tip: a short foot, the neck, the bulb and the cone to a small flat, as the profile of the photo. */
pf-plug > .tip { --from: 3.017; --to: 3.737; --pipe-width: .5254;
  --pipe-profile: 0 1, .102 .993, .119 .977, .142 .904, .183 .771, .224 .694, .299 .644, .369 .682, .416 .758, .491 .929, .532 .976, .59 .998, .66 .962, .695 .912, .747 .793, .828 .602, .939 .345, .968 .278, 1 .19; }
pf-plug[variant=molded] > .boot { --from: -.4; --to: .5; --pipe-width: .72; --pipe-fillet: .12; --texture: thread 1 .2; --texture-amount: 1; }   /* ribs on the pvc */
pf-plug[variant=molded] > .body { --from: .4; --to: 1.85; --pipe-width: 1.25; --pipe-fillet: .3; }
pf-plug[variant=molded] > .shaft { --from: 1.85; --to: 2.2; --pipe-width: .5; --pipe-seam: .85 .06; }
pf-plug[variant=molded] > .tip { --from: 2.2; --to: 2.5; --pipe-width: .46; --pipe-profile: none; }
pf-plug[variant=sleeve] > .sleeve { --from: 0; --to: 5.65; --pipe-width: 3.36; --pipe-fillet: .15; }
pf-plug[variant=sleeve] > .shaft { --from: 5.65; --to: 6.9409; }
pf-plug[variant=sleeve] > .ins1 { --from: 6.9409; --to: 7.0317; }
pf-plug[variant=sleeve] > .band { --from: 7.0317; --to: 7.4585; }
pf-plug[variant=sleeve] > .ins2 { --from: 7.4585; --to: 7.587; }
pf-plug[variant=sleeve] > .tip { --from: 7.587; --to: 8.307; }
pf-plug[variant=magsafe] > .head { --from: 1.4; --to: 1.86; --inset: .2; --radius-device: .1; --height: .6; }
pf-plug[variant=magsafe] > .body { --from: 0; --to: 1.5; --color: inherit; --radius-device: .32; --height: .8; --edge-width: .2; --edge-depth: .2; }
pf-plug[variant=magsafe] > .lamp { --from: .62; --to: .88; --inset: .92; }
/* A part that spins, as pf-disc and pf-encoder, starts with no snap, so it spins free. --snap on the part, or in a
 * rule for it such as pf-tx6 pf-encoder, gives it snap. */
:where([spin]) { --snap: 0; }

/* A phone in portrait: the devices go in two columns. */
@media (max-width: 720px) and (orientation: portrait) {
  :root { --u: min(calc((100vw - 16px) / 46), calc((100dvh - 32px) / 76)); }
}

/* ---------- the color of each part ---------- */
pf-key { --color: color-mix(in oklab, var(--secondary), black 9%); }
pf-key[variant=slot] { --color: color-mix(in oklab, var(--tertiary), white 9%); }
pf-knob { --color: var(--graphite); --mark: var(--accent); }
pf-knob[variant=well], pf-knob[variant=rotary] { --color: color-mix(in oklab, var(--secondary), black 17%); }
pf-knob[variant=skirt] { --color: var(--bone); }
pf-knob[variant=ramp] { --color: var(--aluminum); }
pf-disc { --color: color-mix(in oklab, var(--secondary), black 12%); --mark: var(--ink); }
pf-switch { --color: color-mix(in oklab, var(--secondary), black 2%); }
pf-selector { --color: var(--aluminum); }
pf-glyph { --color: #f4f6ff; }
pf-led { --color: var(--led-on); }
pf-led[variant=flash] { --color: #ffbf4a; }
pf-lcd { --color: var(--glass); --ink: #1d1d1f; }   /* the segments stay dark when a theme gives a light --ink */
pf-lens { --color: color-mix(in oklab, var(--primary), black 15%); }
pf-screw { --color: color-mix(in oklab, var(--primary), black 6%); }
pf-port { --color: color-mix(in oklab, var(--primary), black 17%); }
pf-port[variant=usb-c], pf-port[variant=lightning] { --radius-device: 99; }   /* a pill */
/* The tongue of usb-c, a seated solid: the gap at the top and the bottom and at the ends, and the bezel, which falls
   into its hole as a chamfer. */
pf-port[variant=usb-c] > .tongue { --color: color-mix(in srgb, var(--keybed) 75%, var(--primary)); --texture-amount: 0; --height: 0; --radius-device: 99;
  --gap: .56 .68; --seat-edge: .24; --seat-shape: chamfer; --seat-radius: auto; }
pf-port[variant=lightning] { --opening: .17; --opening-edge: .17; }
/* The jack (pieces() in pf-port.js): pipes from the case out, which cast no shadow, as the port casts it. --from and --to
   are the ends of a piece along the axis and --inset its room at each side, in parts of the port. The steel is the
   polished steel of a plug (--plug-metal), so a plug and its jack match. The nut is a hex nut seen from the side with a
   face up, a little darker and rougher, in the shade of the case at its foot. The barrel is threaded, in the shade of the
   nut at its start. The ring at the mouth is dark, or lit in --accent while the port has power. The barrel and the ring
   take the bright sky of the plug. */
pf-port { --steel: var(--plug-metal); }
pf-port > :is(.nut, .barrel, .ring) { --color: var(--steel); --height: 0; --shadow-alpha: 0; --inset: .14; --pipe-width: .864; --texture-amount: 0; }
pf-port > .nut { --from: 0; --to: .42; --inset: 0; --pipe-width: 1.2; --pipe-facets: 6; --pipe-shade: .7 .06; --rough: .35; --color: color-mix(in srgb, var(--steel), black 22%); }
pf-port > .barrel { --from: .42; --to: .76; --color: rgb(from var(--steel) calc(r * 1.11) calc(g * 1.11) calc(b * 1.11)); --texture: thread 1 .15; --texture-amount: 1; --pipe-shade: .56 .067; --sky: .85; }
pf-port > .ring { --from: .76; --to: 1; --color: rgb(from var(--steel) calc(r * .65) calc(g * .65) calc(b * .65)); --sky: .85; }
pf-port[powered] > .ring { --color: var(--accent); --pipe-glow: .65; }
pf-roller { --color: color-mix(in oklab, var(--secondary), white 55%); }
pf-roller[variant=notch] { --color: color-mix(in oklab, var(--tertiary), black 14%); --mark: #8fc3e0; }   /* the ring on the outer cap */
/* The pieces of the roller (pieces() in pf-roller.js): straight pipes from the case out, which cast no shadow, as the
   roller casts it. The caps are a little lighter than the roller (--steel). The wheel is the knurl in the color of the
   roller: its start is in the shade of the case or the cap before it, and a seam darkens its end. neck: a fine bright
   knurl, skewed, on a shaft of half the color in the shade of the case. notch: a coarse dark knurl, then a band, the ring
   in --mark and the outer cap with a chamfer. */
pf-roller { --steel: var(--color); }
pf-roller > :is(.shaft, .wheel, .inner, .band, .ring, .cap) { --color: color-mix(in srgb, var(--steel), white 14%); --spec: .35; --gloss: 10; --height: 0; --shadow-alpha: 0; --texture-amount: 0; }
pf-roller > .shaft { --color: rgb(from var(--steel) calc(r * .5) calc(g * .5) calc(b * .5)); --spec: .3; --pipe-shade: .35 .678; --pipe-seam: .45 .075; }
pf-roller > .wheel { --color: color-mix(in srgb, var(--steel), black 35%); --texture: pyramids 1 .25; --texture-amount: 1; --pipe-shade: .4 .265; --pipe-seam: .3 .106; }
pf-roller[variant=notch] > .wheel { --texture: pyramids 1 .5; --pipe-shade: .4 .114; --pipe-seam: .3 .114; }
pf-roller > .inner { --spec: .25; }
pf-roller > :is(.band, .ring) { --pipe-seam: .4 .028; }
pf-roller > .ring { --color: var(--mark); --spec: .25; }
pf-roller > .cap { --pipe-chamfer: .344; }
pf-cut.notch { --keybed: color-mix(in srgb, var(--desk), black 85%); --radius: 0; }   /* the notch of a roller in a case: a dark gap round the roller */
pf-encoder { --color: color-mix(in oklab, var(--secondary), black 6%); --mark: color-mix(in oklab, var(--secondary), black 24%); }   /* the dome; the knurled skirt */
pf-fader { --color: color-mix(in oklab, var(--secondary), black 26%); --keybed: #0f0f0f; }
pf-meter { --color: #ff7a3a; --keybed: #808083; --meter-gap: .1; }   /* the light; the holes; the room between two strips of a bar meter, in units */
pf-meter > pf-led { --color: inherit; }   /* each light of a meter (pieces() in pf-meter.js) is in the color of the meter */
pf-button { --color: color-mix(in oklab, var(--secondary), black 23%); --radius: .25; }
pf-key:is([variant=pill], [variant=rocker], [variant=slot]) { --radius: 99; }   /* the side buttons: round ends; a smaller radius gives corners */
pf-usb { --color: color-mix(in oklab, var(--primary), black 8%); --ink: #3a3a3c; }
pf-tab { --color: color-mix(in oklab, var(--secondary), black 5%); }
pf-clip { --cable-width: 1.1; }   /* on braided cables; the material gives the metal */
pf-pipe { --pipe-width: 1.6; --pipe-bend: 1.6; }   /* in units: the width of the tube, and the radius of a bend at its middle */
pf-pipe.lathe { --pipe-width: 2.4; --pipe-angle: 0; --pipe-profile: 0 .62, .2 .62, .2 1, .42 1, .5 .7, .62 .7, .74 .95, 1 .15; }   /* a turned pipe: a shoulder, a flat, a neck, a bulb and a cone */
pf-qr { --emboss-depth: .07; }   /* a shallow etch */
pf-kill { --color: var(--dot); --mark: #d2d3d5; }   /* the cover; the steel of the toggle */
/* The case of the TX-6: bead-blasted aluminum, lighter toward the light, with a soft pool of light over its top (the Case
   of panel-kit: sheen 3.55, glare [.518, -.36, .363, .475]). */
pf-tx6 { --color: #b5b5b7; --radius-device: 1.195; --ink: #1e1e20; --slab: .1497; --glare: .518 -.36 1.09 .475; --finish: 0 1; }   /* the pool of --glare in place of the sheen of the metal */
pf-tx6 pf-knob { --color: #bbbbbd; --mark: #211f2a; }
pf-tx6 pf-knob.b { --mark: #f54e0b; }
pf-tx6 pf-knob.c { --mark: #ece0d7; }
pf-tx6 .window { --radius: .45; --gap: 0; }   /* the window of the screen */
pf-tx6 .screen { --color: #d2e4ed; --ink: #d2e4ed; --radius: .45; --resolution: 43 59; --subpixels: mono; --black-level: .04; --pixel-fill: .92; --pixel-gap: #c9dae3; --pixel-glow: 0; --sink: .35; }   /* a mono LCD below the face: the glass lit, the content dark, a faint grid */
pf-tx6 pf-led.dot { --color: #ff6a2a; }
pf-tx6 pf-led.usb { --color: #4dff57; }
pf-tx6 pf-led.shift { --color: #ffffff; }
pf-tx6 .fx1 { --mark: #222129; }
pf-tx6 .fx2 { --mark: #f34f14; }
pf-tx6 pf-button[variant=rect] { --color: #aaaaaa; }
pf-tx6 pf-button.shift { --color: #a0a0a0; }
pf-tx6 pf-port { --color: #747474; --steel: var(--color); }   /* gray jacks */
pf-tx6 pf-roller > .wheel { --texture: pyramids 1 .05u; }   /* a knurl in units of the roller: the same count of pyramids at any size */
pf-tx6 pf-key[label=power] { --color: var(--accent); }
pf-tx6 .pf-label { --label-size: 1.075; font-weight: 300; letter-spacing: 0; }   /* FX and shift */
pf-tx6 .pf-label.title { --label-size: 1.85; }   /* TX–6 */
pf-tx6 pf-led.shift { pointer-events: none; }   /* the light lies on the shift button, so a click on it goes to the button */
pf-riddim { --color: #ded3c1; --radius-device: .15; --ink: #08452c; --accent: #fe5a0e; --label-size: .45; --keybed: #050505; }
pf-riddim[material] > * { --gap: .07; --seat-radius: .05; --seat-edge: .03; }   /* tight holes with nearly square corners */
pf-riddim pf-key { --color: #e2d6c4; --mark: #08452c; }
pf-riddim pf-key.num { --color: #e4e4e2; }
pf-riddim pf-key.orange { --color: #f54a06; --mark: #fff6ee; }
pf-riddim pf-key.green { --color: #034a36; --mark: #f1faf5; }
pf-riddim pf-key.enter { --mark: #f3481d; }
pf-riddim pf-knob { --color: #eeedea; }
pf-riddim pf-knob.x { --color: #fe5716; }
pf-riddim pf-knob.y { --color: #034231; }
pf-clip[variant=zip] { --color: var(--tie); --clip-gap: .25; }
pf-clip[variant=velcro] { --color: var(--velcro); --rows: none; --clip-gap: .1; }
pf-riddim pf-led { --color: #ff3d0f; }
/* The lit icons of the display, by the class of their color. */
pf-riddim pf-led.orange { --color: #ffa012; } pf-riddim pf-led.green { --color: #3cff86; } pf-riddim pf-led.blue { --color: #4fc4ff; } pf-riddim pf-led.white { --color: #eefcff; }
pf-riddim pf-led.red { --color: #ff4f1c; } pf-riddim pf-led[label=box] { --color: #ff5a1c; --icon-colors: #45befb; } pf-riddim pf-led[label=square] { --color: #ff6a2a; } pf-riddim pf-led[label=finger] { --color: #f2ffe0; }
pf-riddim pf-led:is([label=conga], [label=guitar]) { --icon-colors: #ff7a1a; } pf-riddim pf-led[label=square-in] { --icon-colors: #ffc58a; }   /* the second color of an icon in two colors */
pf-riddim pf-glass pf-led:where(:not([class])) { --color: #eefcff; }   /* an icon of the display with no color of its own lights white */
pf-riddim pf-key:is([label=sound], [label=fx], [label=erase]) { --plate: #e8e8e6; } pf-riddim pf-key[label=main] { --plate: #fe5410; } pf-riddim pf-key[label=tempo] { --plate: #023a2a; }   /* the plates under the keys with a second function */
pf-riddim pf-key[label=power] { --color: #fd5c19; }
pf-riddim pf-key.art { --mark: #02472c; --icon-colors: #fe5410; } pf-riddim pf-key.art:is([label=ball], [label=square]) { --mark: #fe5410; }   /* the art of the keys: green, and orange over it */
pf-riddim [label=record] > pf-led { --color: none; }   /* a backlight with no color of its own: the orange key lights */
pf-riddim pf-fader { --color: #e6dccb; --mark: #08452c; }
pf-riddim pf-glass { --color: #34aa83; --glass-veil: .04; }
pf-riddim pf-digits { --color: #e8fdfd; }
pf-riddim pf-plate.label { --color: #eeede9; --ring: #d9d8d3; --brand: #fe6b0b; --tagline: #0c3220; }   /* the colors that the pieces of a plate name, as fill="var(--brand)" */
pf-riddim [label=logo] { --color: #025633; }
pf-riddim pf-plate.grill { --color: #e9dfcf; --pinhole: #151412; }
pf-riddim [label=ports] { --band: #e6dbc9; --output: #f3f3ef; --output-ink: #127a49; --input: #fe5102; --sync: #014f3c; --usb: #e9dcc8; --paper: #fbfaf6; }
pf-riddim [label="speaker cavity"] { --color: #0c2e22; } pf-riddim pf-plate.cap { --color: #4c3d3d; }
pf-riddim pf-screw { --color: #5a5c5e; }
pf-riddim pf-speaker { --color: #141312; }
pf-slab { --color: #3e3e3e; --radius-device: .56; --ink: #646464; --label-size: .34; --keybed: #161616; }
pf-slab[material] > *, pf-slab .metal > * { --gap: .11; --seat-radius: .08; --seat-edge: .05; }   /* thin dark frames round the keys */
pf-slab .metal { --color: #a3a3a3; --radius-device: .56 0 0 .56; --shadow-length: .3; }   /* the panel of metal: square on the side of the face, round at the corners of the case on its left, and a short step down to the face */
pf-slab pf-key { --color: #444444; --radius: .06; --mark: #767676; --label-size: .375; --legend-weight: 600; --legend-y: .185; --legend-align: start; --legend-inset: .198; --legend-line: .58; --legend-next-size: .331; --legend-next-color: #5c5c5c; }   /* the print in two lines from the top left */
pf-slab [label="strip mode"] { --legend-next-size: .375; --legend-next-color: #767676; }
pf-slab pf-key.pad { --color: #3b3b3b; }
/* The LED of each pad, from the top left, in the hues of the reference. */
pf-slab [label="pad 1"] > pf-led { --color: #8a4dff; } pf-slab [label="pad 2"] > pf-led { --color: #c04dff; } pf-slab [label="pad 3"] > pf-led { --color: #ff4dc4; } pf-slab [label="pad 4"] > pf-led { --color: #ff4d6d; }
pf-slab [label="pad 5"] > pf-led { --color: #2dff9a; } pf-slab [label="pad 6"] > pf-led { --color: #2de8ff; } pf-slab [label="pad 7"] > pf-led { --color: #3d8bff; } pf-slab [label="pad 8"] > pf-led { --color: #5a5dff; }
pf-slab [label="pad 9"] > pf-led { --color: #ffd42d; } pf-slab [label="pad 10"] > pf-led { --color: #c8ff2d; } pf-slab [label="pad 11"] > pf-led { --color: #7dff3d; } pf-slab [label="pad 12"] > pf-led { --color: #2dff5a; }
pf-slab [label="pad 13"] > pf-led { --color: #ff2d2d; } pf-slab [label="pad 14"] > pf-led { --color: #ff5a1f; } pf-slab [label="pad 15"] > pf-led { --color: #ff8a1f; } pf-slab [label="pad 16"] > pf-led { --color: #ffb21f; }
/* The colors of the decks, which a pad takes in a mode (slab.js view()): chords, melody, bass and drums, and white */
pf-slab pf-key.pad > pf-led.deck0 { --color: #8a4dff; } pf-slab pf-key.pad > pf-led.deck1 { --color: #2de8ff; } pf-slab pf-key.pad > pf-led.deck2 { --color: #ffd42d; } pf-slab pf-key.pad > pf-led.deck3 { --color: #ff5a1f; } pf-slab pf-key.pad > pf-led.white { --color: #ffffff; }
pf-slab .metal pf-key { --color: #a6a6a6; --mark: #ffffff; --legend-y: .25; }
pf-slab .metal :is([label=redo], [label=forward], [label="dial mode"]) { --legend-align: end; }   /* the right key of a pair */
pf-slab .metal pf-key.round { --color: #9c9c9c; --radius: 99; --gap: .16; --seat-radius: auto; }   /* a round hole */
pf-slab [label=record] { --icon-size: .3025; } pf-slab [label=record] > pf-led { --color: #ff2a00; }   /* a red dot and a green arrow, lit with power */
pf-slab [label=play] { --icon-size: .2755; } pf-slab [label=play] > pf-led { --color: #1eea2a; }
pf-slab pf-knob[variant] { --color: #474747; }
pf-slab .metal pf-knob[variant] { --color: #a8a8a8; }
pf-slab .window { --radius: .16; --gap: 0; }   /* the window of the OLED */
pf-slab .screen[variant] { --color: #141414; --ink: #d4d4d4; --radius: .16; --resolution: 128 56; --subpixels: mono; --pixel-fill: .9; --pixel-glow: .4; }   /* a white OLED of 128 by 56 */
pf-slab pf-led { --color: #ffffff; }
pf-slab pf-meter { --color: #ffffff; --keybed: #262626; }
pf-slab pf-plate { --color: #383838; }
pf-slab .logo { --label-size: .8; color: #ececec; letter-spacing: .3em; font-weight: 700; }
pf-slab .jack { --label-size: .62; color: #ececec; } pf-slab .metal .jack { color: #2e2e2e; }   /* in and out: as large as on the other devices, and clear on the face and on the metal */
pf-grid { --color: #36373d; --radius-device: .12; --ink: #9aa3b1; --grain: .35; }   /* a smooth matte case */
/* The print: thin words in the middle, a second line smaller and grayer, and the icons a little smaller than a third of the top. */
pf-grid pf-key { --color: #25262c; --radius: .06; --mark: #d2e1f5; --label-size: .3389; --legend-weight: 250; --legend-y: .4983; --legend-line: .8189; --legend-next-size: .2691; --legend-next-color: #b8c6da; --icon-size: .2963; }
pf-grid pf-key[legend*="|"] { --legend-y: .4824; }   /* two lines */
pf-grid pf-key.fn { --label-size: .319; --legend-y: .3451; --legend-line: .437; --legend-next-size: .2592; }   /* the low keys of the bottom row: the word near the top */
pf-grid .small { --label-size: .2592; --legend-y: .5081; }   /* shift and setup */
pf-grid [icon=chevron] { --label-size: .2691; --legend-y: .8084; --icon-size: .328; }   /* the keys of the right column: an arrow over the word */
pf-grid [label="capture midi"] { --mark: #ec5b62; --label-size: .2691; --legend-y: .8401; --icon-size: .3386; }   /* a red ring over the word */
pf-grid [label=play] { --mark: #3ddc84; }
pf-grid [label=mark] { --mark: #e6eef8; --icon-size: .8889; }
pf-grid [icon=dash] { --icon-size: .9333; }   /* the track keys */
pf-grid :is([icon=dot], [icon=dots]) { --icon-size: .09375; --icon-y: .6719; --icon-color: #b8c6da; } pf-grid [icon=dots] { --icon-size: .4167; }   /* the dots under volume and pan */
pf-grid pf-key.pad { --color: #c8c8ca; --radius: .1; }   /* smooth silicone */
pf-grid .pad[label="pad 28"] { --corner-shape: round round bevel round; --radius: .1 .1 .479 .1; } pf-grid .pad[label="pad 29"] { --corner-shape: round round round bevel; --radius: .1 .1 .1 .479; }   /* the four pads in the middle cut the corner that faces the middle */
pf-grid .pad[label="pad 36"] { --corner-shape: round bevel round round; --radius: .1 .479 .1 .1; } pf-grid .pad[label="pad 37"] { --corner-shape: bevel round round round; --radius: .479 .1 .1 .1; }
pf-grid pf-key > pf-led { --color: #7f8db0; --glow-core: .25; --glow: .5; }   /* the LED of a key that lights: the mode, the show and play */
pf-grid .pad > pf-led { --glow-core: .42; --glow: 0; }   /* with power, each pad lights in the --color of its LED, with no glow round it */
/* The light of each pad in the session mode, as the pads of the reference. */
pf-grid :is([label="pad 1"], [label="pad 2"], [label="pad 10"], [label="pad 12"], [label="pad 28"], [label="pad 33"], [label="pad 34"], [label="pad 44"], [label="pad 49"], [label="pad 50"], [label="pad 60"]) > pf-led { --color: #fea2a4; }
pf-grid :is([label="pad 4"], [label="pad 20"], [label="pad 36"], [label="pad 52"]) > pf-led { --color: #ffa6ff; }
pf-grid :is([label="pad 9"], [label="pad 17"], [label="pad 25"], [label="pad 41"], [label="pad 57"]) > pf-led { --color: #eea4ff; }
pf-grid :is([label="pad 18"], [label="pad 26"], [label="pad 42"], [label="pad 58"]) > pf-led { --color: #a8abfe; }
pf-grid :is([label="pad 19"], [label="pad 27"], [label="pad 35"], [label="pad 43"], [label="pad 51"]) > pf-led { --color: #f1c69a; }
pf-grid :is([label="pad 5"], [label="pad 13"], [label="pad 21"], [label="pad 37"], [label="pad 45"], [label="pad 61"]) > pf-led { --color: #e0fd84; }
pf-grid :is([label="pad 14"], [label="pad 22"], [label="pad 30"], [label="pad 46"], [label="pad 54"], [label="pad 62"]) > pf-led { --color: #cae291; }
pf-grid :is([label="pad 7"], [label="pad 8"]) > pf-led { --color: #84fa8e; }
pf-grid :is([label="pad 15"], [label="pad 23"], [label="pad 31"], [label="pad 39"], [label="pad 47"], [label="pad 55"], [label="pad 63"]) > pf-led { --color: #81f9c5; }
pf-grid :is([label="pad 16"], [label="pad 24"], [label="pad 40"], [label="pad 56"], [label="pad 64"]) > pf-led { --color: #9b9bff; }
pf-grid :is([label="pad 3"], [label="pad 6"], [label="pad 11"], [label="pad 29"], [label="pad 32"], [label="pad 38"], [label="pad 48"], [label="pad 53"], [label="pad 59"]) > pf-led { --color: #d8d8da; }
pf-keypad { --color: #dedbd7; --radius-device: .9; --keybed: #6f6b67; --height: 1.8; }   /* light gray plastic, a deep case, and the dark well of the cells */
pf-keypad pf-key { --color: #d6d3d0; --mark: #fdfcfa; --radius: .2; --gap: .12; --label-size: .78; --legend-weight: 300; --legend-y: .508; --icon-size: .25; }   /* thin digits in the middle, and icons a quarter of the top */
pf-keypad .base { --color: #d6d3d0; --radius-device: .2; --height: .35; --reflect: 0; }   /* the square base of the knob, as high as a key; it bounces no light into the gap at the right of the OLED */
pf-keypad pf-knob { --color: #d9d6d3; --mark: #ffffff; --reflect: 1; }
pf-keypad .screen-hole { --edge-width: var(--seat-edge); --radius: .34; }   /* the cut of the OLED: a lit wall as wide as the wall of the hole of a key, and the corner of the glass plus the gap, .34 = .2 + .14 */
pf-keypad pf-lcd { --color: #0a0a0b; --ink: #f2f2f2; --radius: .2; }   /* an OLED: black glass, and the light of its text */
pf-phone { --color: #461c26; --radius-device: 2.965; --corner-shape-device: continuous; --edge-shape: round; --edge-width: .25; --edge-depth: .4; --rows: groove .27 .09 .02; --shadow-alpha: .4; --shadow-blur: 1.8; --reflect: 0; }   /* burgundy, with the corners of a phone, the round frame and the seam between the frame and the back, a soft light shadow and no bounced light, as on the white of a photo. The frame is .4 deep over .25, so its slope of 45°, which mirrors the white walls of the sweep, lies in the middle of the frame */
pf-phone[material], pf-phone [material=anodized] { --mirror: .7; --rough: .25; --texture-amount: .03; }   /* satin anodized metal: it mirrors the sweep, blurred, so each round edge shows a band of light; a fine grain */
pf-phone .plateau { --color: #461c26; --radius-device: 2.5 2.5 2.5 2.57; --corner-shape-device: continuous; --height: .3; --edge-width: .52; --edge-depth: .3; --edge-blend: .12; --mirror: .35; --rows: bead .47 .06 .025; --shadow-alpha: .5; --shadow-blur: 1.3; }   /* the camera plateau: an S ramp (ogee) as deep as the plateau is high, so it grows out of the case, lit on the side toward the light and dark on the far side, with a fine bead at its top. Each corner has the center of the lens, the flash or the LiDAR window in it: 2.57 = 1.81 (the ring of the ultra wide lens) + .76 (the band at its left), and 2.5 at the others */
pf-phone pf-lens { --color: #5e2834; --lens: #1c2534; --lens-rear: #0b0e14; --keybed: #16161a; --ring-sheen: .3; --ring-gloss: 8; --glint: .35; --lip: .04; }   /* rings of the case metal, black glass and dark navy elements with a clear glint */
pf-phone pf-lens > .ring { --edge-shape: round; --edge-width: .1; --edge-depth: .12; --mirror: .3; --shadow-alpha: .8; --shadow-contact: .9; }   /* the round outer edge of each ring, lit on the side toward the light (less mirror than the case, so the sweep does not light it all round), and its dark shadow on the plateau */
pf-phone pf-led { --color: #fff3df; --milk: #c6c0c0; --phosphor: #eed8ae; }   /* the flash: a warm light behind a frosted Fresnel window with a yellow phosphor */
pf-phone .flash-window { --edge-width: .08; --edge-depth: .08; --gap: .03; }   /* the window of the flash: a round cut with a thin lip, dark on the side of the light */
pf-phone .lidar { --edge-width: .06; --edge-depth: .08; --gap: .05; }   /* the window of the LiDAR scanner: a round cut with a thin lip */
pf-phone .lidar-glass { --color: #0e0e10; --radius-device: 99; --height: 0; --spec: .2; --gloss: 12; --rim-light: .3; --hairline: 0; }   /* flat dark glass, flush in the cut */
pf-phone .logo { --color: #361820; }   /* the Apple logo: darker, as a polished inlay */
pf-phone .antenna { --emboss-depth: .03; }   /* the antenna lines: shallow, so only their walls show */
pf-phone .mic { --edge-width: .08; --edge-depth: .06; }   /* the hole of the microphone: a round lip, lit on the side away from the light */
pf-phone pf-lens .well { --strips: 0 10 1.3; --sky: .4; --horizon: .3; --floor: .2; }   /* the glass of a lens mirrors a dark room with one strip light, so the black glass and the coating stay deep, with a soft streak */
pf-phone pf-key[side] { --color: #461c26; --travel: .06; --radius: .08; --shadow-alpha: .1; }   /* the side buttons, in the case color, with small corners and a faint shadow: a press pushes each in .06 */
/* The camera (pf-camera.js), after a reference picture: bead-blasted silver aluminum, black glass, and a polished collar round
   the dial, its hub and each key. The corners keep one band: the plate of the screen .54 = .9 − .36 (the corner of the case
   less the inset of the plate), the OLED cut 1.35 = 1.28 + .07; the glass keeps the .225 of the photo. */
pf-camera { --color: #cdced0; --radius-device: .9; --keybed: #19191a; }
pf-camera[material], pf-camera .bezel { --texture: grain; --texture-amount: .2; }   /* the grain of bead-blasted metal */
pf-camera .bezel { --color: #cdced0; --radius-device: .54; --height: .02; --hairline: .5; }   /* the plate of the screen, flush, with a seam */
pf-camera .window { --gap: 0; --edge-shape: chamfer; --edge-width: .05; --edge-depth: .05; }
pf-camera .glass { --color: #0b0b0c; --radius-device: .225; --height: 0; --spec: .2; --gloss: 12; --rim-light: .3; --hairline: 0; --grid-margin: .515; }   /* one band of black glass round the live view */
pf-camera .view { --color: #0b0b0c; --radius: 0; --resolution: 320; }   /* the rows follow the shape of the view */
pf-camera .oled { --gap: .07; --edge-shape: chamfer; --edge-width: .07; --edge-depth: .05; }
pf-camera pf-lcd { --color: #050506; --ink: #f7f7f7; --radius: 1.28; }
pf-camera pf-lcd[material] { --spec: .25; }   /* black glass with little glare */
pf-camera .ring { --bevel: .22 -.45 .9 30; }   /* the polished collar of the hole of the dial */
pf-camera .dial > .face { --color: #aaabad; --spun: 0; --bevel: 0; --height: .1; --hairline: 0; --pattern-pitch: .436; --pattern-margin: 0; }
pf-camera .pyramid { --color: #aaabad; --radius-device: 0; --edge-width: .218; --edge-depth: .12; --height: 0; --hairline: 0; --rim-light: 0; }   /* the knurl: a grid of square pyramids, each a solid with a chamfer to its middle */
pf-camera .dial .hub { --bevel: .35 -.5 .9 30; }
pf-camera .ok { --color: #d2d3d5; --radius: 99; --gap: 0; --height: 0; }   /* flush with the case, as the other keys; a press sinks it in the hub */
pf-camera .dot { --keybed: #2a2a2b; }
pf-camera .rocker { --color: #dcdde0; --radius-device: 99; --height: .5; --shadow-alpha: .8; --edge-shape: round; --edge-width: .15; --edge-depth: .15; --texture: grain; --texture-amount: .2; --groove: 0; }   /* the rocker: a trough (its mask) between two raised sides, and no groove */
pf-camera .well { --gap: .3; --bevel: .25 -.75 .9 30; }   /* the hole of a key, with its collar */
pf-camera .key { --color: #b4b5b7; --radius: 99; --mark: #141415; --icon-size: .33; --height: 0; }   /* flush in its hole, so it casts no shadow */
pf-camera .key[icon=more] { --icon-size: .675; }
pf-camera pf-key[side] { --color: #d6d7d9; --travel: .06; }
/* The TP–7 (pf-tp7.js), after a reference picture: bead-blasted silver aluminum, lit from the top left (--slab), a reel of
   the same metal in a round cut with a polished collar and a hub of chrome, an OLED, and keys of the case metal. The hub
   takes a light of its own, so its mirror splits along the line of the picture. The pieces of the reel take a unit of an
   eighth of the reel, so the rim of the chrome is .012 of that unit. Corners: the case 1, the window .6 = .55 + .05. The
   class tp7 gives a case of the assemblies page the same look. */
:is(pf-tp7, .tp7) { --color: #b8b8b8; --radius-device: 1; --slab: .14; --keybed: #19191a; --ink: #343436; }
:is(pf-tp7, .tp7)[material] { --texture: grain; --texture-amount: .2; }   /* the grain of bead-blasted metal */
pf-tp7 .pf-label.title { --label-size: 1.5; font-weight: 300; letter-spacing: 0; }   /* TP-7 */
pf-tp7 .mic { --keybed: #0c0c0d; --edge-width: .04; --edge-depth: .04; }
pf-tp7 pf-led.rec { --color: #ff3b1f; }
pf-tp7 .window { --radius: .6; --gap: .04; --edge-shape: chamfer; --edge-width: .04; --edge-depth: .04; }
pf-tp7 .screen[variant] { --ink: #eef3fb; --radius: .55; --resolution: 74 40; --subpixels: mono; --pixel-fill: .9; --pixel-glow: .4; }   /* a white OLED of 74 by 40 */
pf-tp7 .mark { --mark: #f7f7f7; }   /* the white arrows and the R by the lever */
pf-tp7 .badge { --mark: var(--accent); }
pf-tp7 .badge-text { --mark: #fbe9df; }
:is(pf-tp7, .tp7) .ring { --bevel: .1 -.5 .9 30; }   /* the polished collar round the reel */
:is(pf-tp7, .tp7) .reel { --detents: 120; }   /* a step of 3°, so the motor turns the reel smoothly; a step by hand moves the counter 1 s */
:is(pf-tp7, .tp7) .reel > .platter { --color: #bdbdbd; --radius-device: 99; --height: .15; --slab: .065; --spun: 0; --bevel: 0; --hairline: 0; --edge-shape: round; --edge-width: .05; --edge-depth: .05; --texture: grain; --texture-amount: .2; }
:is(pf-tp7, .tp7) .reel .hub { --bevel: .03 -.5 .9 30; }
:is(pf-tp7, .tp7) .chrome { --radius-device: 99; --height: 0; --gap: .02; --rim-width: .012; --light-az: 115; --strips: 90 140 .2; --sky: .42; --horizon: .3; --floor: .42; }
:is(pf-tp7, .tp7) .reel :is(.spoke, .legend) { --mark: #2a2a2b; }
:is(pf-tp7, .tp7) .reel .pin { --mark: #7a7a7c; }   /* a pin: a dark edge round a light top */
:is(pf-tp7, .tp7) .reel .pin-top { --mark: #d8d8da; }
pf-tp7 .pad { --keybed: #8f8f90; --edge-shape: chamfer; --edge-width: .06; --edge-depth: .05; }
:is(pf-tp7, .tp7) .pocket { --keybed: #acacac; --edge-width: .04; --edge-depth: .05; }   /* a shallow pocket: its floor in the color of the case */
/* The floor of the pocket: a solid in the shape of the pocket, sunk below the case. Its face holds the keys, so their
   shadows and their bounced light fall on it, as in the picture. */
:is(pf-tp7, .tp7) .pocket-floor { --color: #a4a4a4; --height: 0; --sink: .08; --hairline: 0; --texture: grain; --texture-amount: .2; }
:is(pf-tp7, .tp7) pf-key.round { --color: #b2b2b2; --radius: 99; --height: .3; --edge-shape: round; --edge-width: .1; --edge-depth: .12; --rim-light: 1 1; --rim-width: .06; --mark: #3a3a3c; --icon-size: .42; --shadow-alpha: .85; --shadow-contact: 1; }
pf-tp7 .cross { --mark: #3e3e40; }
pf-tp7 .slot { --radius: 99; --keybed: #3a3a3c; }
/* The LED bars: a frosted cover (pf-frost) over a meter of 13 chips (pf-meter variant=bar), which shine through it. The
   chips show as a ladder of soft rungs while they are off, as in the picture. level sets the lit chips. */
pf-tp7 .led-glass { --color: #c9c9cb; --frost-milk: .3; --frost-blur: .5; --radius-device: 99; --rim: 0; }
pf-tp7 .levels { --color: #c8ccd6; --meter-gap: .365; }
pf-tp7 .levels > pf-led { --radius: .02; }
pf-tp7 .bay { --keybed: #333335; }   /* the dark bay under the edge of the face, where the keys go in */
pf-tp7 .transport { --color: #adadad; --radius: .1; --height: .15; --edge-shape: round; --edge-width: .12; --edge-depth: .3; --edge-sides: 7 1 1 1; --light-az: 265; --mark: #1e1e1f; --icon-y: .23; }
/* The transport keys roll over a long round at their top side (--edge-sides), under the slot, and that round catches the
   light of the picture, which falls more from the top than the light of the house: the keys take a light of their own. */
pf-tp7 .transport.rec { --icon-color: var(--accent); --icon-size: .33; }
pf-tp7 .transport.play { --icon-size: .25; }
pf-tp7 .transport.stop { --icon-size: .28; }
pf-tp7 .lever { --color: #d0d0d0; --radius: 99; --height: .5; --groove: 0; --edge-shape: round; --edge-width: .15; --edge-depth: .15; }
pf-tp7 .lever-arm { --color: #d0d0d0; --radius-device: 0; --height: .45; --hairline: 0; --edge-shape: round; --edge-width: .9; --edge-depth: .45; --edge-sides: 1 0 1 0; }   /* the neck from the lobe of the lever to the side of the case: round across, as a bar */
pf-tp7 .pivot { --color: #a4a4a6; }   /* a polished rivet, darker than the lever */
pf-tp7 pf-key[side] { --color: #d0d0d0; --travel: .06; --edge-shape: round; --edge-width: .1; --edge-depth: .2; }
/* A side key is a bar out of the side of the case: flat ends with small corners out of the case and square ones at the case,
   a long round at each end, a short one on its outer side, and none on the side in the case (--edge-sides). The keys on
   the right lie in the shadow of the case, which the case does not cast over a part in the edge slot: their color takes it. */
pf-tp7 pf-key[side=right] { --color: #808082; --radius: 0 .1 .1 0; --edge-sides: 6 1 6 0; }
pf-tp7 pf-key[side=left] { --radius: .1 0 0 .1; --edge-sides: 6 0 6 1; }
pf-tp7 pf-key[side=top] { --radius: .1 .1 0 0; --edge-sides: 2.5 1 0 1; }
pf-tp7 pf-roller { --color: #9a9b9d; }
pf-tp7 pf-roller > .wheel { --texture: pyramids 1 .5; }   /* a coarse knurl, as on the roller of the picture */
/* The dispatch (pf-dispatch.js), after the top view of its concept: light warm gray plastic, a deep case lit from the top
   left, keys of soft-touch plastic in dark wells, an OLED, a dial of spun aluminum with an orange dot, and the light of each
   line: orange while it works, red while it asks and white when it is done. */
pf-dispatch { --color: #cac0bf; --radius-device: 1.6; --height: 3.2; --slab: .1; --grain: .35; --shadow-alpha: .95; --shadow-blur: 1; --keybed: #281d1a; }
pf-dispatch :is(.name, .code) { --mark: #574d4a; }
pf-dispatch :is(.speaker, .vent) { --pattern-margin: 0; --keybed: #5b514f; }
pf-dispatch .speaker { --pattern-pitch: .49; }
pf-dispatch .vent { --pattern-pitch: .478 .463; }
pf-dispatch .window { --gap: .06; --edge-shape: chamfer; --edge-width: .06; --edge-depth: .05; }   /* the corner of the glass plus the gap, .41 = .35 + .06 */
pf-dispatch pf-lcd { --color: #0f0e0e; --ink: #f9f8f8; --radius: .35; --label-size: 1.72; --legend-line: 2.06; --legend-inset: 1.35; --legend-y: .29; --legend-weight: 530; }
pf-dispatch pf-lcd[data-ink=bypass] { --ink: #ff4b3e; }   /* bypass permissions, in red */
pf-dispatch pf-lcd[data-ink=ultrathink] { --ink-colors: #de7669 #eeaa7b #e3cc92 #b9dcab #9db8e1 #9988c6 #bd86b1; }   /* ultrathink, in a rainbow */
pf-dispatch .effort { --color: #d4c9c5; --mark: #5d514d; --radius: 99; --label-size: .62; --gap: .08; }   /* a pill under the dial */
pf-dispatch .dial > .cap { --color: #f4f2f2; --radius-device: 99; --spun: .06; --bevel: .1 .9 .9 30; --knurl: .04; --height: 2.4; --shadow-alpha: .95; --shadow-blur: 1; }   /* spun aluminum with a fine knurl round its rim */
pf-dispatch .dial .dot { --mark: #f0661c; }
pf-dispatch .well { --gap: 0; --radius: .32; }   /* the corner of a cap plus the band round it, two margins: .32 = .151 + .168 */
pf-dispatch pf-keycap { --color: #d4c9c5; --ink: #7d7471; --label-size: 1.3; --legend-y: .52; }
pf-dispatch pf-keycap > .cap { --margin: .084; --skirt: .3; --skirt-rise: .14; --top-round: .1; --top-radius: .45; --grain: .1; }   /* soft-touch: a wide top on a low skirt */
pf-dispatch pf-keycap pf-led { --keybed: #8f8784; }   /* the light of a line that is free: a gray dot */
pf-dispatch pf-keycap[data-state=works] { --ink: #ef9a37; } pf-dispatch pf-keycap[data-state=works] pf-led { --color: #ff9a2a; }
pf-dispatch pf-keycap[data-state=asks] { --color: #dcc3c0; --ink: #f0473b; } pf-dispatch pf-keycap[data-state=asks] pf-led { --color: #ff3b2e; }
pf-dispatch pf-keycap[data-state=done] { --color: #d3cfd5; --ink: #fbfbfb; } pf-dispatch pf-keycap[data-state=done] pf-led { --color: #ffffff; }
pf-dispatch pf-keycap.yes { --color: #dedbdc; --ink: #5d5857; }
pf-dispatch pf-keycap.no { --color: #514848; --ink: #ece8e6; }
pf-dispatch pf-keycap.esc { --color: #d06f2d; --ink: #5a2108; }
pf-dispatch pf-keycap.mode { --color: #afa4a0; --ink: #5d514d; }
pf-dispatch pf-keycap:is(.yes, .no, .esc, .mode) { --label-size: 1; }
pf-dispatch pf-key[label=power] { --color: #cbc1bf; --travel: .06; }
/* The palm microphone of the dispatch (pf-mic.js): a round case with a dome, a grille of rings, the orange talk bar round
   its right side, and a coiled cable in signal orange. */
pf-mic { --color: #d1c8c6; --radius-device: 5.85; --dome: .2; --height: 1.6; --grain: .35; }   /* round: the radius is half its side */
pf-mic .grille { --pattern-pitch: .49; --pattern-margin: 0; --keybed: #5b514f; }
pf-mic .talk { --color: #e8641e; }
pf-cable.mic { --color: #e8641e; }
pf-grill { --color: color-mix(in oklab, var(--primary), black 6%); }
pf-speaker { --color: color-mix(in oklab, var(--tertiary), black 21%); }
pf-solid, pf-device, pf-battery { --color: var(--aluminum); }
/* The pieces of a lens (pieces() in pf-lens.js) take the color of the lens. The ring casts the shadow of the lens and
   bounces its light, with a softer rim and less sheen and grain than a solid. The cut of the glass shows no wall, and the
   solids in it are flush, with no hairline: each one paints its own top (optics.js). */
:where(pf-lens) :is(.ring, .well, .barrel, .element, .cover) { --color: inherit; --radius-device: 99; }
pf-lens > .ring { --hairline: 0; --rim-light: .8 .5; --finish: .3 .5; --shadow-alpha: .5; --shadow-fall: 1; --shadow-blur: 1.2; --shadow-contact: .55; --bounce-alpha: .55; --bounce-spread: .3; }
pf-lens .glass { --seat-wall: 0 0; --plain-lip: 1; }
pf-lens .well, pf-lens .well > * { --height: 0; --hairline: 0; }
pf-lens .cover { --cover: 1; }
/* The pieces of the ramp knob (pieces() in pf-knob.js) take the color of the knob, or the color of the material of a
   piece, and they cast the shadow of a knob. The base is a low disc; the cap stands 1.2 units on it, with a knurl round
   its top and a top that is lighter toward the light; the hole is a cut in the cap. */
:where(pf-knob[variant=ramp]) > .base, :where(pf-knob[variant=ramp] > .base) > .cap { --color: inherit; --radius-device: 99; }
pf-knob[variant=ramp] :is(.base, .cap) { --hairline: 0; --shadow-alpha: .7; --shadow-fall: .45; --shadow-blur: 1.35; --shadow-contact: .3; }
pf-knob[variant=ramp] > .base { --height: .3; --bounce-alpha: .55; --bounce-spread: .45; }
pf-knob[variant=ramp] .cap { --height: 1.2; --knurl: .225; --slab: .05; --rim-light: .5; --reflect: 0; }
pf-knob[variant=ramp] .hole { --seat-wall: .3 .6; }
/* The pieces of a plain skirt knob (pieces() in pf-knob.js): the base is a low disc, and the cap stands 1.2 units on it.
   Each one has a bevel, a band round its top lit by the way it faces, as a part of its half side, so it grows with the
   knob. They take the color of the knob, or of the material of a piece, and cast the shadow of a knob. */
:where(pf-knob[variant=skirt]) > .base, :where(pf-knob[variant=skirt] > .base) > .cap { --color: inherit; --radius-device: 99; }
pf-knob[variant=skirt] :is(.base, .cap) { --hairline: 0; --shadow-alpha: .7; --shadow-fall: .45; --shadow-blur: 1.35; --shadow-contact: .3; }
pf-knob[variant=skirt] > .base { --height: .5; --bevel: 8% .06 .5 9; --bounce-alpha: .55; --bounce-spread: .45; }
pf-knob[variant=skirt] .cap { --height: 1.2; --bevel: 20% .45 .3 9; --reflect: 0; }
/* The pieces of a pill switch (pieces() in pf-switch.js), in units of a third of the switch across its travel. The track is
   a cut with round ends and a chamfer. Its floor is --keybed with a little of the color of the switch, or --accent while
   the switch is on (--pill-floor). The cap is a round solid of the color of the switch in the material pyramids, a knurl
   (--cap-material, as each knurl cap takes), low over the floor, at the end of the floor less its margin. It casts the
   shadow of the switch, and bounces no light. */
pf-switch[variant=pill] { --pill-floor: color-mix(in srgb, var(--keybed) 92%, var(--color)); }
pf-switch[variant=pill]:not([cap]), [cap=knurl] { --cap-material: pyramids; }
pf-switch[variant=pill][on] { --pill-floor: var(--accent); }
pf-switch[variant=pill] > [slot=track] { --keybed: var(--pill-floor); --radius: 99; --edge-shape: chamfer; --edge-width: .3; --edge-depth: .13; --seat-depth: .5; }
:where(pf-switch[variant=pill]) > .cap { --color: inherit; }
pf-switch[variant=pill] > .cap { --radius-device: 99; --margin: .12; --height: .4; --hairline: 0; --rim-light: 1 .4; --reflect: 0;
  --shadow-alpha: .55; --shadow-fall: .8; --shadow-blur: 1.2; --shadow-contact: .5; }
/* The pieces of a lens, a flash and a dome (pieces() in pf-led.js), in units of the radius of the light. The bezel is a
   round solid in --bezel, flush, so it casts no shadow. The well is the cut that holds the light, in from the edge of the
   bezel by the margin of its grid: its lip is a chamfer on a lens and a wall on a flash. The light in the well takes the
   color of the light that holds it, and the gap round it. */
pf-led > .bezel { --color: var(--bezel); --radius-device: 99; --height: 0; --hairline: 0; --texture-amount: 0; --slab: .3; }
pf-led[variant=lens] > .bezel { --grid-margin: .12; }
pf-led[variant=flash] > .bezel { --grid-margin: .1; }
pf-led[variant=lens] .well { --edge-shape: chamfer; --edge-width: .08; --edge-depth: .08; }
pf-led[variant=flash] .well { --radius: 99; --edge-width: 0; --seat-wall: .45 .5; }
pf-led:has(> .bezel, > .well) { --bulb-color: var(--color); }
pf-led .bulb { --color: var(--bulb-color); --gap: 0; }
pf-led[variant=lens] .bulb { --gap: .08; }
pf-led[variant=dome] .bulb { --gap: .18; }
/* ---------- the LED tokens ----------
 * The look of a light (pf-led), so the code of the part keeps only the shape of each gradient. The light: --color,
 * --brightness and --glow (above). --glow-halo is the glow round a lit light, as layers `blur alpha`: each blur in units,
 * or in radii of the light with r (.7r). --glow-spread grows the round shape of the glow to that many radii, as the halo
 * round a hole. The diffuser is the cover in front of the light: --milk is its color while the light is off,
 * --diffuser-frost the part of the milk over the tint of the light, and --diffuser-white how much white lightens it.
 * --diffuser-grain is the grain of its plastic (lit, off); --diffuser-depth how far it lies under the surface, in units, so
 * the rim of its hole shades it; --diffuser-seam the seam of a deeper tone round it, in units; --diffuser-rim the light
 * and the dark of the hairline at its edge; --diffuser-glint the alpha of the highlight toward the light (off, lit); and
 * --diffuser-rings the rings of a lens (the count, the alpha off, the alpha lit). --phosphor-size is the phosphor of a
 * flash, in parts of its radius. --led-bar is the strip of a bar LED in the top of a key: its height and its inset, in
 * parts of the top. They inherit, so the light in the pieces of a lens, a flash or a dome takes the tokens of the light
 * that holds it; for the same reason a rule of a variant names the light that holds the pieces with :not(.bulb). */
@property --glow-halo { syntax: '*'; inherits: true; initial-value: .08 .5, .25 .3, .6 .3; }
@property --glow-spread { syntax: '<number>'; inherits: true; initial-value: 1; }
@property --diffuser-frost { syntax: '<number>'; inherits: true; initial-value: .94; }
@property --diffuser-white { syntax: '<number>'; inherits: true; initial-value: .25; }
@property --diffuser-grain { syntax: '*'; inherits: true; initial-value: .22 .12; }
@property --diffuser-depth { syntax: '<number>'; inherits: true; initial-value: .12; }
@property --diffuser-seam { syntax: '<number>'; inherits: true; initial-value: .04; }
@property --diffuser-rim { syntax: '*'; inherits: true; initial-value: .55 .35; }
@property --diffuser-glint { syntax: '*'; inherits: true; initial-value: 0 0; }
@property --diffuser-rings { syntax: '*'; inherits: true; initial-value: 0 0 0; }
@property --phosphor-size { syntax: '<number>'; inherits: true; initial-value: .22; }
@property --led-bar { syntax: '*'; inherits: true; initial-value: .13 .035; }
:where(pf-led[variant=lens]:not(.bulb)) { --diffuser-frost: .55; --diffuser-white: 0; --diffuser-rim: .4 .25; --diffuser-glint: .55 0; --diffuser-rings: 4 .16 .12; }   /* a milky lens with faint rings */
:where(pf-led[variant=flash]:not(.bulb)) { --diffuser-glint: .45 0; }   /* the sheen of the window of a flash while it is off */
:where(pf-led[variant=dome]:not(.bulb)) { --diffuser-rim: .45 .45; --diffuser-glint: .45 .6; }   /* a clear glossy dome */
:where(pf-led[variant=icon]) { --glow-halo: .08 .45, .3 .25; }   /* an icon glows along its own shape */
:where(pf-led[variant=hole]) { --glow-halo: .7r .9; --glow-spread: 2.2; }   /* a light behind a hole: a halo on the face, 2.2 times as wide as the hole */
/* The pieces of the disc (pieces() in pf-disc.js). The face is a round solid of spun steel in the color of the disc, with a
   polished bevel and a dark line round its edge, and it casts the shadow of the disc. The text is engraved in the face. The
   hub is a round cut with a polished collar that falls into it. The felt in the hub is a little lighter than --keybed, with
   grain, .3 units under the collar. The pin is a matte dome of steel, a little darker than the face (--steel). */
:where(pf-disc) > .face { --color: inherit; --radius-device: 99; }
pf-disc > .face { --steel: var(--color); --height: .7; --spun: .07; --bevel: .14 .9 .9 30;
  --shadow-alpha: .6; --shadow-fall: .6; --shadow-blur: 1.3; --shadow-contact: .4; --bounce-alpha: .5; --bounce-spread: .4; }
pf-disc .text { --engrave: .4 .5; }
pf-disc .hub { --bevel: .12 -.75 .8 30; }
pf-disc .felt { --color: rgb(from var(--keybed) calc(r * 1.1) calc(g * 1.1) calc(b * 1.1)); --radius-device: 99; --gap: .12; --sink: .3;
  --height: 0; --hairline: 0; --spec: 0; --rim: 0; --texture: grain 1 1; --texture-amount: 1; }
pf-disc .pin { --color: color-mix(in srgb, var(--steel), black 5%); --radius-device: 99; --height: 0; --hairline: 0; --dome: .3; --spec: .1; --gloss: 8; --sat: 0; }
pf-dial { --color: var(--bone); }
pf-pad { --color: var(--graphite); --ink: #ebeae6; --ink-soft: #8e8e91; }
pf-pad pf-key { --color: color-mix(in oklab, var(--secondary), black 7%); }
pf-rgb { --color: var(--graphite); --ink: #ebeae6; --ink-soft: #8e8e91; }
pf-rgb pf-led.r { --color: var(--signal-r); } pf-rgb pf-led.g { --color: var(--signal-g); } pf-rgb pf-led.b { --color: var(--signal-b); }
pf-port[signal=r] { --accent: var(--signal-r); } pf-port[signal=g] { --accent: var(--signal-g); } pf-port[signal=b] { --accent: var(--signal-b); }
pf-display { --color: var(--bone); }
pf-display .window { --gap: 0; }
pf-display .display-body { --radius-device: .45; }   /* .45 = 0 + .45: the band of the body round the pixels */
pf-display pf-bars { --radius: 0; }   /* the pixels have square corners */
pf-loudspeaker { --color: var(--bone); }
pf-lamp { --color: var(--accent); --ink-soft: color-mix(in oklab, var(--accent), black 40%); }
pf-lamp .pf-lens { --lamp-light: #fff0d6; --color: color-mix(in oklab, var(--lamp-light) var(--level, 100%), #a8642e); }   /* a dial dims it toward amber (--level, from pf-lamp.js) */
/* The flush key of a device (header() in pf-device.js): a round key level with the case in a round cut, as the play key of
   the camera, with the gap and the collar of the camera at the size of this key. It has the color of the case, and
   pf-device.js gives it the material of the case. Its rim is not lit (--rim: 0), so it does not stand out of the cut.
   Its icon is small. Its light is white with power, and with no power the icon is in --ink-soft, as the code of the
   device. */
pf-cut.flush-well { --gap: .13; --bevel: .1 -.75 .9 30; }
pf-key.flush { --color: inherit; --radius: 99; --height: 0; --rim: 0; --icon-size: .6; }
pf-key.flush > pf-led { --color: #fff; }
pf-key.flush > pf-led:not([on]) { --color: var(--ink-soft); }
pf-keyboard { --color: var(--aluminum); }
pf-keyboard pf-knob { --color: #19191a; --mark: #19191a; }   /* black spun knobs with no mark: the teeth show the turn */
pf-keycap { --color: #eef0ed; --ink: #707273; }
pf-keycap.accent { --color: var(--accent); --ink: #fff4ec; }
pf-keycap { --label-size: .7; }   /* the size of the lines of its legend, in units */
/* The pieces of a keycap (pieces() in pf-keycap.js), in units of a keycap 4 units high. The cap fills the keycap less the
   gap round it (--margin), in the color of the keycap, with a skirt round its top, and casts the shadow of the key. The
   bar sits in the middle of the room of the grid of the cap, low on its top. The prints fill the keycap, in --ink. */
:where(pf-keycap) > .cap, :where(pf-keycap > .cap) > .bar { --color: inherit; }
pf-keycap > .cap { --height: .35; --margin: .112; --radius-device: .151; --skirt: .434 .302 .415 .321; --skirt-rise: .234; --top-radius: .906; --top-round: .302;
  --hairline: 0; --rim: 0; --grain: .35; --shadow-alpha: .5; --shadow-fall: 1.1; --shadow-blur: 1.1; --shadow-contact: .55; --bounce-alpha: 0; --grid-margin: 1.661 0 0; }
pf-keycap .bar { --height: .18; --radius-device: .12; --hairline: 0; --grain: 0; --rim: 1; --mask-depth: .06;
  --shadow-alpha: .2; --shadow-fall: .3; --shadow-blur: .6; --shadow-contact: 0; --bounce-alpha: 0;
  --press-sink: 0; }   /* a round bar (mask=barrel). It goes down with the cap, so a press only dims it: it keeps its height on the cap */
pf-keycap > pf-print { --mark: var(--ink); }
pf-screen { --color: #ff7a00; --screen-mid: #fff783; --ink: #ffffff; --mark: #e6f53f; }   /* the glow from the top down to --screen-mid; the time; the date */
/* pf-panel: a display of pixels. --resolution: the pixels across, or across and down. --subpixels: stripe (red, green and
   blue bars), pentile (red and blue diamonds and green ovals), mono (one dot in --ink) or smooth (too fine to see). --pixel-fill: the part of each
   pixel that its lights fill. --black-level: the light of a black pixel. --color is the glass with its pixels off. */
/* The body of a display (the display skill): black glass, flush with the case and matte, with the lit rim of its edge,
   light on the side toward the light and dark on the far side, as the bezel of the screen of the keyboard. It sits in a
   window cut, and the pixels (pf-panel, pf-bars) lie in it. */
pf-solid.display-body { --color: #0a0a0b; --height: 0; --hairline: 0; --spec: 0; --texture-amount: 0; --rim-light: .8 .3; --rim-width: .03; }
pf-panel, pf-bars { --color: #0c0d0e; --ink: #f2f2f2; --radius: .3; --resolution: 128; --subpixels: stripe; --pixel-fill: .8; --pixel-pitch: 0; --pixel-size: 0; --pixel-glow: .6; --black-level: .05; }   /* an LCD, lit from behind */
:is(pf-panel, pf-bars)[variant=oled] { --color: #000; --subpixels: pentile; --pixel-fill: 1; --pixel-glow: 1.2; --black-level: 0; }   /* an OLED: a black pixel is off */
:is(pf-panel, pf-bars)[variant=led] { --color: #0b0b0c; --subpixels: led; --pixel-pitch: .5; --pixel-size: .35; --black-level: 0; }   /* an LED matrix: a round LED each .5 units on a black board */
pf-bars { --color: #0f1012; --radius: .45; --resolution: 320 200; }   /* the test card of the display: 320 by 200 pixels in its black glass */
pf-frost { --color: #f2f3f1; --frost-milk: .42; --frost-blur: .35; }   /* the milk of the glass; how much of it covers the parts behind; the blur for one unit of distance */

/* ---------- materials ----------
 * A part sets its own material attribute when it connects, so it never takes the material of its device.
 * --spec and --gloss: the strength and the size of the specular highlight (a high gloss gives a small, sharp highlight).
 * --sat: how much deeper and more saturated the dark side of a colored surface gets.
 * --texture: the textures of the material, over each other: the tiles grain, cloud, dust, leather, cloth, webbing,
 * melange and pyramids of noise.js, each as `kind amount px` (src/core/material.js), and --texture-amount their strength. amount is a factor on
 * --texture-amount (1 by default), and px the size of one noise pixel in CSS pixels (.5, and 1 for leather).
 * --rows: lines round the top, each `kind distance width depth` in units from the outline (ROWS in material.js). A row
 * lays a piece on the top (stitch, inlay, rivet or punch) or cuts the top (groove, bead, trench or step), such as
 * `groove .8, stitch 1.4`. none gives no rows, and --stitch: d is short for `stitch d`. The thread of a stitch, an inlay
 * and a rivet take --stitch-color (a little lighter than the part when it has none) and --stitch-material.
 * --stitch-length is the length of a stitch, and the step from one rivet or hole to the next.
 * --sheen: the soft light of a fabric where it turns away from the eye, as the edge of velvet, from 0 (none) to 1.
 * --sound: the sound of the material, a name of the sounds below. */
[material] { --mirror: 0; --sheen: 0; }   /* only the polished metals below mirror the studio, a part has a sheen only when it asks for one, and a part does not take either from its device */
[material=plastic] { --spec: .14; --gloss: 9;  --sat: .35; --texture: grain; --texture-amount: .18; --sound: plastic; }
[material=metal]   { --spec: .5;  --gloss: 26; --sat: 0;   --texture: cloud .2 2, grain; --texture-amount: .2; --sound: metal; }
[material=rubber]  { --spec: .03; --gloss: 3;  --sat: .15; --texture: grain; --texture-amount: .22; --sound: rubber; }
[material=glass]   { --spec: .9;  --gloss: 60; --sat: 0;   --texture: none;  --texture-amount: 0;   --sound: glass; }
[material=leather] { --spec: .05; --gloss: 4;  --sat: .3;  --texture: leather; --texture-amount: .24; --sound: leather; }
[material=cloth]   { --spec: .02; --gloss: 2;  --sat: .25; --texture: cloth; --texture-amount: .3; --sound: cloth; }
/* webbing: the nylon of a strap. A coarser weave with a sheen, stitched round its edge. */
[material=webbing] { --spec: .1; --gloss: 3; --sat: .3; --texture: webbing; --texture-amount: .55; --rows: stitch .55; --sound: webbing; }
/* melange: the wool of a speaker front. A coarse weave of heathered yarn, light and dark fibers in each thread, and no shine. */
[material=melange] { --spec: .01; --gloss: 2; --sat: .1; --texture: melange; --texture-amount: 1; --sound: melange; }
[material=silicone] { --spec: .08; --gloss: 4; --sat: .2; --texture: grain; --texture-amount: .04; --sound: silicone; }
/* pvc: the molded jacket of a cable. Glossy, with a small sharp highlight, and the dark side of a color goes deeper. */
[material=pvc] { --spec: .85; --gloss: 60; --sat: .35; --texture: none; --texture-amount: 0; --sound: plastic; }
/* tpe: the soft jacket of a silicone cable. Matte, with a broad, faint sheen and no sharp highlight. */
[material=tpe] { --spec: .3; --gloss: 10; --sat: .15; --texture: grain; --texture-amount: .04; --sound: silicone; }
/* pyramids: plastic with a knurl of small square pyramids, as the grip on the cap of a switch. The knurl is the tile
   pyramids of noise.js, a map of light at full strength, over the grain of plastic. */
[material=pyramids] { --spec: .14; --gloss: 9; --sat: .35; --texture: pyramids, grain .18; --texture-amount: 1; --sound: plastic; }
/* knurl: steel with a knurl of small pyramids (the tile pyramids), as the wheel of a roller or the barrel of a jack plug.
   threaded: polished steel with the grooves of a screw thread (the tile thread), as the barrel of a jack port. A pipe wraps the
   tile round its tube, and a part sets the size of the tile with --texture, as the roller does. */
[material=knurl]    { --spec: .5; --gloss: 26; --sat: 0; --texture: pyramids 1 .3, grain .18; --texture-amount: 1; --sound: metal; }
[material=threaded] { --color: #f5f9ff; --mirror: 1; --spec: .5; --gloss: 26; --sat: 0; --texture: thread 1 .3, grain .18; --texture-amount: 1; --sound: metal; }
/* frost: glass with a matte face, as sandblasted acrylic: a wide soft sheen and a fine grain. */
[material=frost] { --spec: .3; --gloss: 5; --sat: 0; --texture: grain; --texture-amount: .06; --sound: frost; }
/* gold, chrome, gunmetal: polished metal that mirrors a small studio (polish() in light.js), so its bands slide when the
 * light moves. Each one gives its color. A flat top stays even, and its polished edge shows the move. */
[material=gold]     { --color: #fdd286; --mirror: 1; --spec: .6; --gloss: 40; --sat: 0; --texture: none; --texture-amount: 0; --sound: metal; }
[material=chrome]   { --color: #f5f9ff; --mirror: 1; --spec: .6; --gloss: 40; --sat: 0; --texture: none; --texture-amount: 0; --sound: metal; }
[material=gunmetal] { --color: #5b5c61; --mirror: 1; --spec: .6; --gloss: 40; --sat: 0; --texture: none; --texture-amount: 0; --sound: metal; }
/* satin: the same metal, bead-blasted, as a frosted handle. --rough (0 to 1) blurs the studio, so its bands are wide and
 * soft. Any part takes --mirror (how much it mirrors the studio) and --rough, and does not take them from its device. */
[material] { --rough: 0; }
[material=satin]    { --color: #dddedf; --mirror: 1; --rough: .85; --spec: .3; --gloss: 12; --sat: 0; --texture: grain; --texture-amount: .05; --sound: metal; }
/* steel: turned steel with a satin polish, as the pin of a jack plug: it mirrors the studio through a blur (--rough), so
 * its bands are broad and soft as in a product photo, with a soft highlight. */
[material=steel]    { --color: #f5f9ff; --mirror: 1; --rough: .2; --spec: .3; --gloss: 16; --sat: 0; --texture: none; --texture-amount: 0; --sound: metal; }
/* anodized: aluminum under a dyed skin of oxide, as the case of a phone: the color of the part, a soft sheen that keeps the
   color, deep sides, and a fine grain. */
[material=anodized] { --spec: .42; --gloss: 5; --sat: .3; --texture: grain; --texture-amount: .06; --sound: metal; }

/* ---------- sounds ----------
 * A sound is the click of a part, as one tick of the sound engine (src/core/audio.js): a noise burst through a band-pass filter that
 * rings at --click-freq (Hz) with --click-q, and fades in --click-decay (s); --click-tail is the level of its sine tail
 * and --click-bright the level of its bright attack, from 0 to 1. With --click-soft: 1 a press is a squish and a release
 * is silent, as on a soft pad. A material names its sound with --sound, and a part with --sound takes another sound. */
[sound=plastic]  { --click-freq: 2600; --click-q: 6; --click-decay: .004; --click-tail: .5; --click-bright: .4; }
[sound=metal]    { --click-freq: 3120; --click-q: 7; --click-decay: .0032; --click-tail: .6; --click-bright: .55; }
[sound=rubber]   { --click-freq: 1400; --click-q: 5; --click-decay: .006; --click-tail: .8; --click-bright: .25; --click-soft: 1; }
[sound=glass]    { --click-freq: 4200; --click-q: 9; --click-decay: .0018; --click-tail: .3; --click-bright: .7; }
[sound=leather]  { --click-freq: 900; --click-q: 3; --click-decay: .007; --click-tail: .6; --click-bright: .15; }
[sound=cloth]    { --click-freq: 700; --click-q: 2; --click-decay: .008; --click-tail: .3; --click-bright: .1; }
[sound=webbing]  { --click-freq: 800; --click-q: 2.5; --click-decay: .007; --click-tail: .3; --click-bright: .15; }
[sound=melange]  { --click-freq: 650; --click-q: 2; --click-decay: .009; --click-tail: .3; --click-bright: .08; }
[sound=silicone] { --click-freq: 1100; --click-q: 3; --click-decay: .009; --click-tail: .7; --click-bright: .1; --click-soft: 1; }
[sound=frost]    { --click-freq: 3600; --click-q: 5; --click-decay: .0024; --click-tail: .25; --click-bright: .4; }

/* ---------- feels ----------
 * A feel is how a part that turns, as a knob, a disc or an encoder, moves under the finger and how its steps sound
 * (spin.js, sound.js). A part takes a feel with its feel attribute:
 *   <pf-encoder feel=motor></pf-encoder>
 * click: the detents of a knob, firm, with a small bounce. free: a flywheel with no snap, as the disc and the encoder.
 * motor: a brushless motor with virtual detents: a flick coasts past them, then it snaps into one and bounces. */
[feel=click] { --detents: 24; --snap: 1; --snap-bounce: .45; --friction: 1; }
[feel=free]  { --detents: 24; --snap: 0; --snap-bounce: .45; --friction: 1; }
[feel=motor] { --detents: 24; --snap: .3; --snap-bounce: .8; --friction: .6; }
/* The feel of a key is its press (pf-key, pf-keycap), as the tokens of the press above give it:
 *   <pf-key feel=push side=right></pf-key>
 * sink: the key sinks into its hole, gets darker, its rim gets dimmer, and the rim of its hole shades it. push: a side
 * button goes in toward its case by --travel units, the way that its side gives, with no sink and no dim. A key with
 * side and no feel takes push. */
[feel=sink] { --press-sink: .16; --press-dim: .9; --press-rim: .5; --press-shade: .75; --travel: 0; }
[feel=push], :where(pf-key[side]:not([feel])) { --press-sink: 0; --press-dim: 1; --press-rim: 1; --press-shade: .75; --travel: .1; }
/* The feel of a WebGPU cable (src/cables-gpu, /cables-lab) is how it slides, hangs, bends and stretches, as the tokens
 * of the cables give it. A cable takes a feel with its feel attribute, or from its desk:
 *   <pf-gpu-cable feel=silicone></pf-gpu-cable>
 * pvc: the molded cable, the start: it hangs a little and settles soon. silicone: soft and limp, with a short, soft
 * boot: it folds closer and drags its plugs. braided: stiff against a bend, with a wide least bend: it slides on the desk
 * and moves as one piece. rubber: springy: a pull stretches it a quarter, and it comes back with a small bounce. coiled:
 * a coil at rest at a third of its length, which pulls its plugs in, and a pull stretches it to its full length. */
[feel=pvc]      { --cable-friction: .35; --cable-bend: .3; --cable-bounce: .1; --cable-damping: 1; --cable-air: 3; --cable-stiffness: 1; --cable-stretch: 1; --cable-rest: 1; --plug-mass: .25; --cable-grab: 14; --cable-relief: .8; --cable-relief-length: 3; --cable-bend-radius: 1.5; --cable-release: 8; }
[feel=silicone] { --cable-friction: .4; --cable-bend: .02; --cable-bounce: .02; --cable-damping: .7; --cable-air: 4; --cable-stiffness: 1; --cable-stretch: 1.02; --cable-rest: 1; --plug-mass: .2; --cable-grab: 10; --cable-relief: .5; --cable-relief-length: 2; --cable-bend-radius: .8; --cable-release: 10; }
[feel=braided]  { --cable-friction: .3; --cable-bend: .8; --cable-bounce: .1; --cable-damping: 1; --cable-air: 2.5; --cable-stiffness: 1; --cable-stretch: 1; --cable-rest: 1; --plug-mass: .25; --cable-grab: 14; --cable-relief: .9; --cable-relief-length: 3; --cable-bend-radius: 2.5; --cable-release: 6; }
[feel=rubber]   { --cable-friction: .45; --cable-bend: .2; --cable-bounce: .3; --cable-damping: .6; --cable-air: 2; --cable-stiffness: .3; --cable-stretch: 1.25; --cable-rest: 1; --plug-mass: .25; --cable-grab: 12; --cable-relief: .7; --cable-relief-length: 2.5; --cable-bend-radius: 1.2; --cable-release: 12; }
[feel=coiled]   { --cable-friction: .5; --cable-bend: .5; --cable-bounce: .2; --cable-damping: .9; --cable-air: 2.5; --cable-stiffness: .05; --cable-stretch: 1; --cable-rest: .3; --plug-mass: .3; --cable-grab: 12; --cable-relief: .8; --cable-relief-length: 2; --cable-bend-radius: 1; --cable-release: 5; }
/* ---------- lights ----------
 * A light is all the light round a part, as the HDR of a 3D app: the key light, which gives the shading and the shadows
 * (--light-az, --light-el, --ambient, --shadow-soft), and the studio that a polished metal mirrors (studio() in light.js).
 * A part, a device or the page takes a light with its light attribute, and the parts on it take that light too:
 *   <pf-knob light=night></pf-knob>   <html light=window>
 * --strips: the strip lights of the studio, each `side width level`: its angle in degrees from the light to the side, its
 * width in degrees, and its brightness (1 for the strip of studio). A strip runs along the light, so it turns with the
 * light. none gives no strips. --sky, --horizon and --floor: the brightness of the sky, of the room at the horizon, and
 * of the desk under the part. studio is the light of :root. */
[light=studio]  { --light-az: 210; --light-el: 38; --ambient: .55; --shadow-soft: 1; --strips: 0 12 1; --sky: .55; --horizon: .06; --floor: .7; }
/* softbox: two strips, one at each side of the light, as in a photo of a product. */
[light=softbox] { --light-az: 225; --light-el: 45; --ambient: .58; --shadow-soft: 1.6; --strips: -14 8 1.1, 17 5 .8; --sky: .3; --horizon: .03; --floor: .55; }
/* window: a large window low at the left. The light is soft and bright, and the shadows are long and soft. */
[light=window]  { --light-az: 180; --light-el: 22; --ambient: .62; --shadow-soft: 2.2; --strips: 0 40 .65; --sky: .75; --horizon: .3; --floor: .8; }
/* top: a light high over the desk, with short shadows. */
[light=top]     { --light-az: 250; --light-el: 74; --ambient: .5; --shadow-soft: 1.2; --strips: 0 20 1.1; --sky: .45; --horizon: .05; --floor: .6; }
/* night: one small hard lamp, low, in a dark room. */
/* side: a big softbox high on the right, as in the photo of a product: the highlights fall right of the middle. */
[light=side]    { --light-az: 0; --light-el: 55; --ambient: .85; --shadow-soft: 2; --strips: 0 30 1.1; --sky: .4; --horizon: 1; --floor: .45; }
[light=night]   { --light-az: 320; --light-el: 16; --ambient: .3; --shadow-soft: .6; --strips: 0 4 1.6; --sky: .1; --horizon: .02; --floor: .25; }
/* sweep: the white sweep of a photo of a product. It keeps the key light of the page and gives only the studio: white walls
   all round at the horizon, and a sky and a desk as bright as a flat top sees them. A round edge of a satin metal then
   shows a band of light on each side, with a dark line at its outline. The phone takes it. */
[light=sweep], pf-phone:not([light]) { --strips: none; --sky: .9; --horizon: 2; --floor: .9; }
/* turned: the studio of a photo of turned steel, as a jack plug: a dark room with one broad softbox over the part, a weak
   strip under it, a dark horizon and a desk as bright as a soft fill. Polished steel then shows a thin light line at each
   outline, a dark line in from the top one, a broad band and a dark core, as in the photo. It keeps the key light of the
   page. The steel of a plug takes it. */
[light=turned], pf-plug > :is(.collar, .shaft, .ins1, .band, .ins2, .tip) { --strips: 29 22 1, -55 18 .45; --sky: .25; --horizon: .3; --floor: .5; }

/* ---------- flares ----------
 * A flare is the light of a very bright light in a camera (flare() in lighting.js): the bloom, a glow that falls off fast
 * near the light and slowly far from it; the streaks, thin rays through it; and the ghosts, soft rings on the line from it
 * away from the key light. --flare is its strength (0 for none, the start value), --flare-size how far the bloom reaches
 * past the light in units, --flare-tint its color (none: the color of the light), --flare-streaks the count of rays (2 to
 * a line), and --flare-ghosts the strength of the ghosts. A light (pf-led) takes a flare with its flare attribute and
 * shows it only while it is on, dimmed by --brightness. They do not inherit. */
@property --flare { syntax: '*'; inherits: false; initial-value: 0; }
@property --flare-size { syntax: '*'; inherits: false; initial-value: 1.5; }
@property --flare-tint { syntax: '*'; inherits: false; }
@property --flare-streaks { syntax: '*'; inherits: false; initial-value: 0; }
@property --flare-ghosts { syntax: '*'; inherits: false; initial-value: 0; }
[flare=soft] { --flare: .6; --flare-size: 1.6; --flare-streaks: 0; --flare-ghosts: 0; }   /* a bloom alone */
[flare=star] { --flare: .55; --flare-size: 1.4; --flare-streaks: 4; --flare-ghosts: 0; }   /* a bloom and a thin cross */
[flare=lens] { --flare: .5; --flare-size: 1.8; --flare-streaks: 2; --flare-ghosts: .6; }   /* a bloom, one line across and the ghosts of a camera lens */

/* ---------- edges ----------
 * An edge is the shape of the side of a part, as a cut through it from its outline in to its top (src/core/edge.js).
 * --edge-shape: sharp (a hairline and the lit rim), chamfer (a straight slope), round (a quarter round), steps (a stair),
 * cove (a concave quarter round), ogee (an S curve), bead (a half round with a quirk in from it) or facets (a round of
 * flat faces).
 * --edge-width and --edge-depth: how far in from the outline and how far down the edge goes, in units. --edge-steps: the
 * count of the steps or of the faces. A part, a device or a piece takes an edge with its edge attribute, and its tokens change it:
 *   <pf-device edge=chamfer style="--edge-width: .8"></pf-device>
 * The light falls on the edge as on a relief, so each step casts a shadow on the step under it. */
[edge=sharp]   { --edge-shape: sharp; --edge-width: 0; --edge-depth: 0; }
[edge=chamfer] { --edge-shape: chamfer; --edge-width: .45; --edge-depth: .3; }
[edge=round]   { --edge-shape: round; --edge-width: .8; --edge-depth: .8; }
[edge=steps]   { --edge-shape: steps; --edge-width: .9; --edge-depth: .36; --edge-steps: 3; }
[edge=cove]    { --edge-shape: cove; --edge-width: .6; --edge-depth: .6; }
[edge=ogee]    { --edge-shape: ogee; --edge-width: .9; --edge-depth: .6; }
[edge=bead]    { --edge-shape: bead; --edge-width: .7; --edge-depth: .35; }
[edge=facets]  { --edge-shape: facets; --edge-width: .8; --edge-depth: .8; --edge-steps: 3; }
[edge=custom]  { --edge-shape: custom; --edge-width: .9; --edge-depth: .6; --edge-profile: 0 0 .35 0, 1 1 .35 0; }   /* a line of points: here a soft ramp, flat at its foot and at the top */

/* ---------- patterns ----------
 * A pattern repeats the part in the mark slot of a part over its top (src/core/pattern.js): its layout and the pitch in
 * units. A part takes a pattern with its pattern attribute, and its tokens change it:
 *   <pf-solid pattern=rings style="--pattern-pitch: .6"><pf-cut slot=mark variant=round></pf-cut></pf-solid>
 * cells puts one mark in the middle of each cell of the grid of the part, so the marks line up with its parts. */
[pattern=stagger] { --pattern-layout: stagger; --pattern-pitch: .55; }
[pattern=grid]    { --pattern-layout: grid; --pattern-pitch: .55; }
[pattern=rings]   { --pattern-layout: rings; --pattern-pitch: .55; }
[pattern=cells]   { --pattern-layout: cells; }

/* ---------- masks ----------
 * A mask gives the top of a part its heights, as a gray image does: 1 (white) is the top, and 0 (black) is --mask-depth
 * units below it (src/core/mask.js). --mask-profile: the stops "r h, r h, …" from the middle (r 0) out to the outline
 * (r 1), with straight slopes between them and round corners. A stop "r h dx dy" has handles, as a point of a vector
 * editor, so the line through it is a curve; "r h ix iy ox oy" gives each handle its own way (stops() in mask.js). A part, a device or a piece takes a mask with its mask
 * attribute, and its tokens change it:
 *   <pf-button mask=dish style="--mask-depth: .4"></pf-button>
 * --mask-gradient: the way the profile runs over the top (along() in edge.js): outline, from the middle out to the
 * outline, so the mask follows the shape of the part; radial, out from the middle in circles; or linear, across the part
 * along --mask-angle, 0 from left to right and 90 from top to bottom.
 * The light falls on the mask as on a relief, so a high rim casts its shadow into a low well.
 * dish: after the camera of a doorbell, a straight cone down from the rim to a collar round the lens, and the well of the lens. */
[mask=dish] { --mask-profile: 0 0, .425 0, .435 .3, .495 .4, .505 .4, .515 .27, .53 .27, .975 1; --mask-depth: 1; }
/* dome: high in the middle, round down to the outline, as the cap of a push button. */
[mask=dome] { --mask-profile: 0 1 .4 0, 1 0 .05 -.6; --mask-depth: .8; }
/* bowl: low in the middle, round up to the rim, steep at the rim. */
[mask=bowl] { --mask-profile: 0 0 .4 0, 1 1 .05 .6; --mask-depth: 1; }
/* cone: a straight slope from a point in the middle down to the outline. */
[mask=cone] { --mask-profile: 0 1, 1 0; --mask-depth: .8; }
/* pillow: a flat top that rolls down at the edge, as a soft key. */
[mask=pillow] { --mask-profile: 0 1, .55 1 .2 0, 1 .2; --mask-depth: .6; }
/* ramp: a straight slope from left to right, low on the left. */
[mask=ramp] { --mask-gradient: linear; --mask-angle: 0; --mask-profile: 0 0, 1 1; --mask-depth: 2; }
/* barrel: a round top from top to bottom, as a roller that lies from left to right. */
[mask=barrel] { --mask-gradient: linear; --mask-angle: 90; --mask-profile: 0 0 .05 .5, .5 1 .25 0, 1 0 .05 -.5; --mask-depth: 2.5; }
/* ridge: the shell over a pipe, as on the cup of a headphone: an arc that keeps .3 units round a pipe 1.7 units in
 * radius, then a fillet down to the flat on each side. A linear gradient of a plate gives it from the middle of the
 * ridge (r 0) out to its foot (r 1). */
[mask=ridge] { --mask-profile: 0 1 .169 0, .426 .574 -.097 .267 .131 -.36, 1 0 .229 0; --mask-depth: 2; }
/* paddle: the top of the paddle of a power switch, after the photo of 2026-10-28: flat from its bottom end up to a round
 * crease, then a slope down to its top end. A rocker turns it over on its on half, so the slope is at the end that is up. */
[mask=paddle] { --mask-gradient: linear; --mask-angle: 90; --mask-profile: 0 0, .14 1 .04, 1 1; --mask-depth: .6; }
/* trough: low along the middle and round up to the two sides, across the part from left to right, as the rocker of a
 * camera. The light makes the side that faces away from it dark and the other side bright. */
[mask=trough] { --mask-gradient: linear; --mask-angle: 0; --mask-profile: 0 1 .15 -.5, .5 0 .2 0, 1 1 .15 .5; --mask-depth: .6; }
/* The masks of one side: each one changes the top only along one side, so a part can take several of them, as
 * mask="roll-top lip-right". A part with two or more names takes each named mask in order. --mask-blend on the part
 * joins each mask to the heights of the masks before it: add puts it on that surface, so it follows the curve of the
 * masks before it; min keeps the deeper cut and max the less deep one, with a round of --mask-smooth where they meet.
 * roll-top: the top rolls down at its top side, as a quarter round, and is flat past it. roll-right, roll-bottom and
 * roll-left roll down at their own side. */
[mask=roll-top]    { --mask-gradient: linear; --mask-angle: 90;  --mask-profile: 0 0 .05 .6, .3 1 .15 0, 1 1; --mask-depth: 1; }
[mask=roll-right]  { --mask-gradient: linear; --mask-angle: 180; --mask-profile: 0 0 .05 .6, .3 1 .15 0, 1 1; --mask-depth: 1; }
[mask=roll-bottom] { --mask-gradient: linear; --mask-angle: 270; --mask-profile: 0 0 .05 .6, .3 1 .15 0, 1 1; --mask-depth: 1; }
[mask=roll-left]   { --mask-gradient: linear; --mask-angle: 0;   --mask-profile: 0 0 .05 .6, .3 1 .15 0, 1 1; --mask-depth: 1; }
/* lip-right: a raised lip along the right side: the top is low, and curves up to the lip, the other way to a roll. */
[mask=lip-right]   { --mask-gradient: linear; --mask-angle: 180; --mask-profile: 0 1 .05 -.6, .3 0 .15 0, 1 0; --mask-depth: 1; }
/* fresnel: the rings of a Fresnel lens, as the frosted window of a flash: eight low rings round the middle, each a soft
   ridge, so the light rolls over them. */
[mask=fresnel] { --mask-gradient: radial; --mask-profile: 0 1, .0625 .6, .125 1, .1875 .6, .25 1, .3125 .6, .375 1, .4375 .6, .5 1, .5625 .6, .625 1, .6875 .6, .75 1, .8125 .6, .875 1, .9375 .6, 1 1; --mask-depth: .015; }

/* ---------- grids ----------
 * A grid is the layout of the parts on a surface, as the grid of CSS, Tailwind or Figma (src/core/layout.js,
 * docs/grid.md). --grid-cell: the size of a cell, one value or x y. --grid-gap: the space between two cells.
 * --grid-margin: the space from the edge of the surface to the grid, 1 to 4 values as the margin of CSS; the --margin of
 * a stitched material adds to it. --grid-cols and --grid-rows: the count of cells, none for a grid that fills the room
 * inside the margin. --grid-align: where a grid with a count sits in that room, start, center or end. A surface takes a
 * grid with its grid attribute. A part takes whole cells with col and row, from 1, and span, how many; it fills them,
 * and place: start, center or end keeps its own size there.
 *   <pf-device grid=keys><pf-key col="2" row="1"></pf-key></pf-device>
 * keys: a cell of a key, 4 units, as on the keyboard and the riddim. base: half a key, for our own new devices. */
[grid=keys] { --grid-cell: 4; }
[grid=base] { --grid-cell: 2; }

/* ---------- seats ----------
 * The surface sets the spacing of the parts on it. These rules go on the children of a surface, so the hole of a part
 * comes from the material of the face, not from the part, and a part on the desk gets the values of :root.
 * Metal is machined: a tight gap and a crisp lit edge. Plastic is molded: a softer edge. Rubber and silicone are soft:
 * a wide gap and a wide, soft edge. The stitched materials also keep a margin, so the parts stay clear of the stitches.
 * The side nav lists only the rules that are exactly [material=x], so these do not show there. */
[material=metal] > *, [material=gold] > *, [material=chrome] > *, [material=gunmetal] > *, [material=satin] > *, [material=anodized] > * { --gap: .08; --seat-edge: .07; --seat-wall: .85 .3; }
[material=plastic] > * { --gap: .14; --seat-edge: .12; --seat-wall: .35 .45; }
[material=rubber] > *, [material=silicone] > * { --gap: .22; --seat-edge: .2; --seat-wall: .5 .3; }
[material=leather] > *, [material=cloth] > *, [material=webbing] > *, [material=melange] > * { --gap: .18; --seat-edge: .12; --seat-wall: .3 .5; --margin: .8; }
[material=webbing] > * { --margin: 1.1; }
