/* ─────────────────────────────────────────────
   THE PINESPARK AGENT STORE STYLESHEET

   Every size in this file comes from a named step. No rule writes a font size,
   a padding, a margin, a gap, a line height, a letter spacing or a weight as a
   loose number. The steps are the ones the previous PineSpark site defined, and
   they are listed in full in the TOKENS layer.

   The following are deliberately not on a step, and each is stated where it
   appears: the fixed pixel dimensions of drawn boxes such as an icon or an
   avatar, where snapping to the nearest step would redraw the artwork, and the
   corner radii, which the previous site's system does not cover.

   The file runs in layers, from the widest to the narrowest, and a rule is
   written in the earliest layer that can hold it:

     TOKENS      the type scale, the spacing scale and everything named
     THEMES      the light and the dark values, and nothing else
     GROUND      the reset, the body, the background layers
     RECIPES     the rules several places share, written here for all of them
     CHROME      the top bar, the page frame, the footer
     SECTIONS    the frames a section is drawn in
     PARTS       the small pieces that appear on many sections
     HOME        the browsing page
     AGENT       the product page
     SIGN IN     the sign-in and sign-up pages
     CONSENT     the framework's cookie bar, restyled to this design
     RESPONSIVE  the narrower screen widths
     FALLBACKS   what to do where a feature is missing

   Nothing here writes a color value either. Every color is one of the
   colors by function palette.css names, and palette.css makes each of them
   from its theme palette, so retuning a color there retunes the site and
   every illustration together.
   ───────────────────────────────────────────── */

/* ─────────────────────────────────────────────
   TOKENS
   ───────────────────────────────────────────── */
:root{

	/* THE TYPE SCALE
	   Steps carried over from the previous PineSpark site, in rem, so the whole
	   scale answers to the root size. The steps widen as they climb: small
	   increments near the reading size where an eye notices them, large jumps at
	   display sizes where they have to carry.

	   Nothing on this site is set below xs. That step is the floor, and the
	   captions, the meta lines and the figures on a card all sit on it. */
	--text-xs:0.75rem;
	--text-sm:0.875rem;
	--text-base:1rem;
	--text-lg:1.25rem;
	--text-xl:1.5rem;
	--text-2xl:2rem;
	--text-3xl:2.75rem;
	--text-4xl:3.5rem;

	/* THE SPACING SCALE
	   Every step is a whole multiple of the finest step, so every spacing lands
	   on a common grid. The steps are fine at the small end and widen as they
	   climb. Every padding, margin and gap on
	   this site names a step of this scale. */
	--space-0:0;
	--space-1:0.25rem;
	--space-2:0.5rem;
	--space-3:0.75rem;
	--space-4:1rem;
	--space-5:1.5rem;
	--space-6:2rem;
	--space-7:2.5rem;
	--space-8:3rem;
	--space-9:4rem;
	--space-10:5rem;
	--space-11:6rem;
	--space-12:8rem;

	/* The visible content of a section ends this far before the rule that
	   starts the next section. */
	--rule-gap:var(--space-6);

	/* LINE HEIGHT
	   Unitless, so each one stays in proportion to whatever size it is given.

	   A line is never shorter than its font is large. The body sets text on the
	   normal line, and a rule may set a line of its own only where it sets one no
	   shorter than the size of its font.

	   The steps climb in the finest fraction that still lands every step of the
	   type scale but --text-sm on a whole pixel, and that is arithmetic rather
	   than taste. Any other fraction leaves most sizes on a fractional pixel, and
	   a fractional pixel is what makes a line box round unevenly and the spacing
	   around it look wrong.

	   The --text-sm step is the one that does not divide by that fraction, so it
	   takes a line height of its own, chosen so that its line is exactly a whole
	   number of pixels tall. Every rule that sets --text-sm text sets this line
	   height with it. A child set in another size inherits the multiplier rather
	   than the pixel height it produced, so such a child names its own line
	   height. */
	--leading-none:1;
	--leading-normal:1.5;
	--leading-relaxed:1.75;
	--leading-sm:calc(20 / 14);

	/* LETTER SPACING
	   Tightening as the size grows, opening up for small capitals. */
	--tracking-tight:-0.025em;
	--tracking-snug:-0.015em;
	--tracking-normal:0em;
	--tracking-wide:0.04em;
	--tracking-wider:0.08em;
	--tracking-widest:0.14em;

	/* WEIGHT
	   PSPrompt carries each of these weights as a real file, so none of them is
	   synthesized. */
	--weight-light:300;
	--weight-regular:400;
	--weight-medium:500;
	--weight-semibold:600;
	--weight-bold:700;

	/* CONTENT WIDTHS */
	--content-narrow:640px;
	--content-sm:768px;
	--content-md:960px;
	--content-lg:1140px;
	--content-xl:1200px;

	/* CORNER RADII
	   The previous site's system has no radius scale, so these are this site's
	   own and they stay as drawn. */
	--r-pill:999px;
	--r-card:16px;
	--r-ctrl:10px;
	--r-tile:12px;

	/* the height of the top bar, which the previous PineSpark sites also used */
	--bar:60px;
	/* the gutter between cards in every grid */
	--gutter:var(--space-4);
	/* The width of a side panel, the same beside the Agent catalog and on an
	   Agent's page. It is a layout measurement rather than a step. */
	--side-panel-width:280px;
	/* the page's own side padding, narrowing on a small screen */
	--pad:clamp(var(--space-4),3.4vw,var(--space-7));

	--grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");

	/* the PineSpark icon drawn in white */
	--mark-white:url(/img/ps-icon-i.svg);

	/* An SVG stroke cannot take a CSS gradient, so the layout writes gradient
	   definitions into the page and an icon names the definition it needs. */
	--icon-paint:url(#ci);

	/* The glass every raised surface is made of: what shows through it is
	   blurred and made a little more colorful. */
	--glass:blur(18px) saturate(160%);

	/* The short, even change a control makes when the pointer reaches it. */
	--quick:.16s ease;

	/* The hairline every rule and every outline on the site is drawn with, in
	   the page's own line color. */
	--hairline:1px solid var(--line);
}

/* ─────────────────────────────────────────────
   THEMES
   The light and the dark block carry every value other than a color that
   differs between the themes, and nothing else. The colors that differ
   between them stand in palette.css, with the rest of the colors by function.

   The logo comes as a lockup of the icon and the wordmark, and as the icon
   alone, each in a dark ink for the light page and a light ink for the dark
   page.
   ───────────────────────────────────────────── */
:root[data-theme="light"]{
	color-scheme:light;
	--grain-op:.055;
	--grain-blend:multiply;
	--logo-lockup:url(/img/ps-logo.svg);
	--logo-icon:url(/img/ps-icon.svg);
	/* how far the halo and the wide glow around a hero's gradient words reach */
	--hero-glow-near-size:.08em;
	--hero-glow-far-size:.5em;
}
:root[data-theme="dark"]{
	color-scheme:dark;
	--grain-op:.045;
	--grain-blend:normal;
	--logo-lockup:url(/img/ps-logo-i.svg);
	--logo-icon:var(--mark-white);
	/* how far the halo and the wide glow around a hero's gradient words reach */
	--hero-glow-near-size:.08em;
	--hero-glow-far-size:.38em;
}

/* ─────────────────────────────────────────────
   GRADIENT
   The site's one gradient, drawn from the brand gradient's stops that
   palette.css names as colors by function: how deep each place draws it, its
   pattern and its flow. A change to how the gradient is drawn is made here and
   nowhere else, and a change to its colors is made in palette.css.

   The gradient runs from its first stop to its second, glows softly into its
   third stop in the middle of the second, and runs back to the first. The
   glow reaches --gradient-spark-width on either side of its middle. It blends
   in along a cosine curve rather than a straight line, through stops that
   hold 15, 50 and 85 percent of the third stop, so its edges meet the second
   stop without a corner. A straight blend changes its slope abruptly at each
   edge, and the eye reads each such corner as a bright line. The pattern
   repeats along the gradient's line, so a
   banner shows several steps of it at a time. It blends in OKLCH, a color
   space whose lightness follows what the eye sees, around the color wheel, so
   it carries no gray patch.

   Three kinds of place draw it, each with its own layout:

     the hero's highlighted words and every gradient link draw it across

     the banners draw it on the diagonal

     a section teaser's ground draws it at the angle and the position its
     section names, and it stands still

   Each kind of place has a strength of its own: how much darker it draws
   each color, --hero-darker, --band-darker and --teaser-darker, and how much
   of each color's chroma it keeps, --hero-color, --band-color and
   --teaser-color. A teaser adds its own darkening to the banners' and
   multiplies their chroma by its own. Every darkening stands at 0 and every
   chroma at 1, so every place draws the stops exactly as the theme holds
   them.

   The hero's words and the banners flow with the page's scroll. The pattern
   slides back along its line as the reader scrolls, a whole pattern taking
   several window heights of scrolling, and stands still while the reader does
   not scroll. Every one slides at the same rate, and each starts from its own
   place in the pattern, which store.js writes to its --flow-offset from how far
   down the page it stands, so neighboring ones never show the same colors.
   No color is animated: a point changes hue only because a different part of
   the pattern slides over it. The distance slid is a registered percentage,
   because a custom property animates only when the browser knows its type. A
   browser that cannot tie an animation to the scroll, and a reader who asks
   for reduced motion, sees the pattern standing still. A Channel's hero keeps
   its own ground and does not flow.
   ───────────────────────────────────────────── */
:root{
	/* the length of one pattern along the gradient's line, which store.js reads
	   too */
	--gradient-period:133.333%;
	/* the soft glow around a gradient link's words */
	--gradient-glow:drop-shadow(0 0 .28em color-mix(in srgb,var(--ci-gradient-stop-2) 45%,transparent));
	/* The glow around a hero's gradient words: a tight halo, and a wide glow
	   around the words and their halo together. The theme blocks set how far
	   each reaches and palette.css their colors. */
	--hero-glow:drop-shadow(0 0 var(--hero-glow-near-size) var(--hero-glow-near)) drop-shadow(0 0 var(--hero-glow-far-size) var(--hero-glow-far));
	/* the strength of each kind of place, at which it draws the stops as the
	   theme holds them */
	--hero-darker:0;
	--hero-color:1;
	--band-darker:0;
	--band-color:1;
	--teaser-darker:0;
	--teaser-color:1;
}
@property --gradient-shift{syntax:'<percentage>';inherits:true;initial-value:0%}
@keyframes gradient-flow{to{--gradient-shift:calc(var(--gradient-period) * -1)}}
/* the places the gradient flows in, which store.js names too */
.band:not(.icon-ground):not(.teaser-ground),.wall-offer,.channel-all,.side-promo,.hero-headline,.gradient-link{
	--gradient-angle:135deg;
	--gradient-darker:var(--band-darker);
	--gradient-color:var(--band-color);
	--gradient-middle:calc(var(--gradient-period) * .57);
	@supports (animation-timeline:scroll()){
		animation:gradient-flow linear both;
		animation-timeline:scroll(root);
		animation-range:0 500vh;
	}
	@media (prefers-reduced-motion:reduce){animation:none}
}
.hero-headline,.gradient-link{--gradient-angle:90deg;--gradient-darker:var(--hero-darker);--gradient-color:var(--hero-color)}
/* A teaser's own style attribute, which StoreElement.teaserGroundAttributes
   writes, names its angle and where the gradient's spark stands. */
.teaser-ground{
	--gradient-angle:var(--teaser-angle);
	--gradient-darker:calc(var(--band-darker) + var(--teaser-darker));
	--gradient-color:calc(var(--band-color) * var(--teaser-color));
	--gradient-middle:var(--teaser-middle);
	--gradient-period:100%;
	--gradient-shift:0%;
	--flow-offset:0%;
}
/* Every place that draws the gradient writes it out for itself, because a
   custom property takes the values of the element it is declared on. An
   element inside one of them, such as a word of the hero's headline, takes the
   gradient its place wrote out. The pattern starts where the flow has slid it
   to, from the place's own offset. */
.band:not(.icon-ground),.wall-offer,.channel-all,.side-promo,.hero-headline,.gradient-link,.teaser-ground{
	--gradient-from:oklch(from var(--ci-gradient-stop-1) calc(l - var(--gradient-darker)) calc(c * var(--gradient-color)) h);
	--gradient-to:oklch(from var(--ci-gradient-stop-2) calc(l - var(--gradient-darker)) calc(c * var(--gradient-color)) h);
	--gradient-spark:oklch(from var(--ci-gradient-stop-3) calc(l - var(--gradient-darker)) calc(c * var(--gradient-color)) h);
	--gradient-spark-width:calc(var(--gradient-period) * .225);
	--gradient-spark-near:color-mix(in oklch,var(--gradient-spark) 85%,var(--gradient-to));
	--gradient-spark-half:color-mix(in oklch,var(--gradient-spark) 50%,var(--gradient-to));
	--gradient-spark-far:color-mix(in oklch,var(--gradient-spark) 15%,var(--gradient-to));
	--gradient-start:calc(var(--gradient-shift) + var(--flow-offset, 0%));
	--gradient-spark-middle:calc(var(--gradient-start) + var(--gradient-middle));
	--gradient:repeating-linear-gradient(var(--gradient-angle) in oklch,
		var(--gradient-from) var(--gradient-start),
		var(--gradient-to) calc(var(--gradient-spark-middle) - var(--gradient-spark-width)),
		var(--gradient-spark-far) calc(var(--gradient-spark-middle) - var(--gradient-spark-width) * .75),
		var(--gradient-spark-half) calc(var(--gradient-spark-middle) - var(--gradient-spark-width) * .5),
		var(--gradient-spark-near) calc(var(--gradient-spark-middle) - var(--gradient-spark-width) * .25),
		var(--gradient-spark) var(--gradient-spark-middle),
		var(--gradient-spark-near) calc(var(--gradient-spark-middle) + var(--gradient-spark-width) * .25),
		var(--gradient-spark-half) calc(var(--gradient-spark-middle) + var(--gradient-spark-width) * .5),
		var(--gradient-spark-far) calc(var(--gradient-spark-middle) + var(--gradient-spark-width) * .75),
		var(--gradient-to) calc(var(--gradient-spark-middle) + var(--gradient-spark-width)),
		var(--gradient-from) calc(var(--gradient-start) + var(--gradient-period)));
}

/* ─────────────────────────────────────────────
   GROUND
   ───────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}

/* The base is the one the previous PineSpark site set: the reading step over
   the normal line, at the regular weight, in PSPrompt.

   The smoothing hints belong with it. PSPrompt renders noticeably heavier
   without them, and the previous site set them on this same rule. */
body,button,input,textarea{
	-webkit-font-smoothing:antialiased;
	-moz-osx-font-smoothing:grayscale;
	font-family:"PSPrompt","Helvetica Neue",Helvetica,Arial,sans-serif;
	font-size:var(--text-base);
	line-height:var(--leading-normal);
	font-weight:var(--weight-regular);
}
body{
	margin:0;min-height:100vh;position:relative;overflow-x:hidden;
	background:var(--bg);color:var(--ink);
	transition:background-color .22s ease,color .22s ease;
}
/* Every input uses the same opaque themed ground. Components may keep the input
   transparent only when their wrapper paints this ground for the whole
   compound control. */
input{background:var(--input-ground);color:var(--ink)}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--acc);outline-offset:3px;border-radius:6px}

/* the color blooms, fixed behind everything */
.wash{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.wash i{position:absolute;display:block;border-radius:50%;filter:blur(70px)}
.wash .a{width:min(760px,96vw);height:min(760px,96vw);top:-32vw;right:-16vw;background:radial-gradient(circle,var(--wash-a),transparent 66%)}
.wash .b{width:min(620px,86vw);height:min(620px,86vw);top:34vh;left:-22vw;background:radial-gradient(circle,var(--wash-b),transparent 68%)}
.wash .c{width:min(560px,80vw);height:min(560px,80vw);bottom:-24vw;right:6vw;background:radial-gradient(circle,var(--wash-c),transparent 70%)}

.grain{
	position:fixed;inset:0;pointer-events:none;z-index:1;
	background-image:var(--grain);opacity:var(--grain-op);mix-blend-mode:var(--grain-blend);
}

/* the gradient definitions and the icon symbols are paint sources and drawing
   sources, never pictures, so neither takes any room on the page */
.paints,.sprite{position:absolute;width:0;height:0;overflow:hidden}

/* ─────────────────────────────────────────────
   RECIPES
   The rules several places share. Each is written here and named by
   whatever needs it, so a change to it is made here and nowhere else.
   ───────────────────────────────────────────── */

/* the shared surface: a flat tint, a hairline, and a highlight along its top
   edge */
.surf{
	background:var(--surf);
	border:var(--hairline);
	box-shadow:var(--edge),var(--drop);
	-webkit-backdrop-filter:var(--glass);
	backdrop-filter:var(--glass);
	transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease;
}

/* Text on the CI gradient: every ground the gradient paints, a banner, a hero,
   a tile painted like a banner and the catalog's promotion, sets its text in
   --ink-on-gradient, which palette.css sets for each theme. The text carries a
   faint shadow under its letters, a tight one and a soft wide one in the
   shades palette.css sets for each theme, dark behind the dark page's white
   text and light behind the light page's dark text, so it reads more easily
   on the gradient. The class text-on-gradient marks text that stands on the
   gradient where its ground carries no such class of its own. A trail on the
   gradient takes the same ink as the text around it. */
.text-on-gradient,.band:not(.icon-ground),.wall-offer,.channel-all,.side-promo{
	color:var(--ink-on-gradient);
	text-shadow:0 0 .5em var(--ink-on-gradient-shade-near),0 0 2.2em var(--ink-on-gradient-shade-far);
}
.band:not(.icon-ground) .crumbs,.band:not(.icon-ground) .crumbs a:hover,.band:not(.icon-ground) .crumbs b{color:var(--ink-on-gradient)}
/* The tool's find-agents hero stands on the tool's own ground, and it writes
   its trail in the primary CI color. */
.tool-hero .crumbs,.tool-hero .crumbs a:hover,.tool-hero .crumbs b{color:var(--brand-ink)}

/* a panel that raises itself when the pointer is over it */
.lift:hover{background:var(--surf-hi);box-shadow:var(--edge),var(--drop-lift)}

/* A link written in the gradient, the way the highlighted words of the hero's
   headlines are: its letters are filled with the gradient and glow softly in
   its second color, and the pointer over the link underlines it in that
   color. Where a browser cannot clip a background to text, the link stands in
   the gradient's first color. */
.gradient-link{
	color:var(--ci-gradient-stop-1);
	filter:var(--gradient-glow);
	text-decoration:none;
}
.gradient-link:hover{
	text-decoration:underline;text-decoration-color:var(--ci-gradient-stop-2);
	text-underline-offset:.2em;
}
/* Large accent text is filled with the gradient rather than a flat color: a
   gradient link, and the hero's headlines further down. The text has to go
   transparent for the fill to show, so the rule is guarded: where a browser
   cannot clip a background to text, the color stands. */
@supports (background-clip:text) or (-webkit-background-clip:text){
	.gradient-link,.hero-step span{
		background-image:var(--gradient);
		-webkit-background-clip:text;
		        background-clip:text;
		color:transparent;
	}
}

/* a figure held to the right end of its row, digits aligned */
.tally{
	text-decoration:none;margin-left:auto;font-variant-numeric:tabular-nums;
	font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--faint);
}

/* the small caption that heads a column */
.sec-tag,.side-section h4,.foot-col h5{
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);
	color:var(--faint);font-weight:var(--weight-medium);
}

/* a small line that carries no heading weight */
.pager,.foot-base,.crumbs,.sec-head .more,#ps-cookie-popup .ps-cookie-popup-locked-label{
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);color:var(--faint);
}

/* a phrase set in bold inside quieter text, which stands out in the full ink */
.crumbs b,.channel-intro b,.tile-empty b,.lineage-row b,#ps-cookie-popup .ps-cookie-popup-note b{
	color:var(--ink);font-weight:var(--weight-medium);
}

/* An icon is a drawn box, so its dimensions are pixels rather than steps: the
   nearest step would change the drawing rather than the space around it. */
.icon{width:16px;height:16px;flex:none;display:block}
/* the icon inside a small control, the picture in a tool's two smallest
   frames, and the icon in a line of small text */
.side-more .icon,.side-open .icon,.side-expand .icon,.channel-arrow .icon,.catalog-search .icon,.flow-about .icon,
.tool-icon-xs img,.tool-icon-xs .icon,.tool-icon-sm img,.tool-icon-sm .icon{width:14px;height:14px}
.crumbs .icon,.seg button .icon{width:13px;height:13px}

/* A list without markers or indent. Every list on the site starts from it, and
   a list that needs a margin or a padding of its own names it in its own rule. */
.industry-tiles,.role-list,.side-list,.agents-by-list,.agents-by-band-row,.agents-by-grid,.category-list,
.shelves,.say-points,.numbers,.explained-list,.lineage,.lineage ul,.structure-tools,.flow-data-list{
	list-style:none;margin:0;padding:0;
}

/* The drawing inside a box, which fills the box. A drawing on a teaser's
   ground lies over the ground, and one inside a tile that moves under the
   pointer moves with it. */
.find-hero-head > .channel-mark svg,.find-hero-visual svg,.category-detail-visual svg{display:block;width:100%;height:100%}
.dirtile svg,.dirmini-tile svg,.category-thumb svg{position:absolute;inset:0;width:100%;height:100%;display:block}
.dirtile svg,.dirmini-tile svg{transition:transform .3s ease}
.dirtop:hover .dirtile svg,.dirmini:hover .dirmini-tile svg{transform:scale(1.035)}

/* A chevron in the sprite points down, so a button that leads to one side
   turns it to face that side. */
.channel-prev .icon,.carousel-prev .icon{transform:rotate(90deg)}
.channel-next .icon,.carousel-next .icon{transform:rotate(-90deg)}

/* The content of a banner and of a tile painted like one stands above the glow
   the banner paints. */
.band-in,.channel-card.icon-ground > *,.channel-hero .crumbs,.channel-hero-main{position:relative;z-index:1}

/* Every drawn icon is stroked with the palette gradient rather than a flat
   color. Only a custom property reaches inside the tree a <use> element
   builds, so the stroke is set here and read in the symbol. */
.job,.agents-by-way a{--icon-stroke:var(--icon-paint)}
/* the small controls keep a flat stroke, because they are furniture */
.finder,.crumbs,.tools,.save,.seg{--icon-stroke:currentColor}


/* The flat control, in its solid and its quiet weight. It is fully rounded,
   and it is the reference every other rounded control is measured against:
   where one of these sits inside another rounded box, that box's radius and
   height follow from this one rather than the other way around.

   Its height is stated rather than left to fall out of the text. A line of this
   size on this leading is not a whole number of pixels tall, so with the
   padding and the border it gives a control whose middle falls between pixels.
   The browser then rounds the top and the bottom differently and the padding
   reads uneven. A stated height on a step is a whole even number of pixels, so
   the top and the bottom round the same way and a full round lands on an exact
   radius. */
.btn{
	display:inline-flex;align-items:center;justify-content:center;
	gap:var(--space-2);white-space:nowrap;min-height:var(--space-7);
	font:inherit;font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);
	border-radius:var(--r-pill);padding:var(--space-2) var(--space-4);
	cursor:pointer;border:1px solid transparent;
	transition:background-color var(--quick),color var(--quick),border-color var(--quick);
}
/* The solid weight, which a pressed segment of a segmented control takes too. */
.btn-solid,.seg button[aria-pressed="true"]{background:var(--solid);color:var(--solid-ink)}
.btn-solid:hover{opacity:.88}
.btn-quiet{background:transparent;color:var(--ink);border-color:var(--line-hi)}

/* A control that takes the sunk ground under the pointer. An arrow with nowhere
   further to go keeps the sunk ground it rests on. */
.btn-quiet:hover,.context-action:hover,.burger:hover,.role-entry:hover,.role-entry:focus-visible,
.channel-arrow[aria-disabled="true"]:hover{background:var(--surf-sink)}
/* A row that takes the full ink and the sunk ground under the pointer, and a
   menu button of the bar while its menu is open. */
.bar-nav a:hover,.bar-menu-button:hover,.bar-menu-button[aria-expanded="true"],a.side-entry:hover,button.side-entry:hover,.agents-by-entry:hover,
.shelves li:not(.all) > a:hover{color:var(--ink);background:var(--surf-sink)}
/* Text that takes the full ink: a link or a control under the pointer, the
   bar's link to the page the reader is on and the button of a menu holding it,
   the heading of the form to modify an Agent, and the words of a step in the
   drawing of how an Agent works. */
.modify-agent h2,.flow-text,.flow-question,.bar-nav a[aria-current="page"],.bar-menu-button[data-current],.bar-link:hover,.foot-col a:hover,.foot-base a:hover,.pager a:hover,
.crumbs a:hover,.sec-head .more:hover,.side-more:hover,.side-open:hover,.side-expand:hover b,
.side-expand:hover .icon,.seg button:not([aria-pressed="true"]):hover,.flow-about:hover,.login-privacy a:hover,
#ps-cookie-banner .ps-cookie-banner-customize:hover{color:var(--ink)}
/* The words of a control that take the full ink and an underline under the
   pointer. */
:is(button,a):is(.multi-tool-row,.multi-industry-row,.multi-role-row):hover :is(.multi-tool-text,.multi-industry-text,.multi-role-text),
.structure-tool:hover .structure-tool-name{
	color:var(--ink);text-decoration:underline;text-underline-offset:.2em;
}
/* A Channel's name underlined under the pointer, where the badge or the row it
   stands in is a link. */
a.channel-badge:hover .channel-name,a.side-entry:hover .channel-name{text-decoration:underline}
/* Text that takes the accent: the name of a category's entry under the pointer,
   a row of the Agent tree under the pointer, the count of the open pick, and a
   message that reports a success. */
.dirtop:hover .dirhead h3,.dirmini:hover h3.dirmini-name,a.lineage-row:hover,a.lineage-row:hover b,
a.lineage-row:hover .lineage-name,.side-entry[aria-current="true"] .tally,.login-message.success{color:var(--acc)}
/* A control with nowhere further to go is dimmed, and the pointer over it
   changes nothing. */
.channel-arrow[aria-disabled="true"],.tile-pager .btn[aria-disabled="true"]{opacity:.35;cursor:default}

/* A context element: a panel that opens over the page next to the button that
   opens it, such as the list of every tool an item of an Agent's drawing holds.
   It stands on the raised surface the menu panel of the bar wears, and it is
   never wider or taller than the window leaves room for. The browser opens and
   closes it as a popover, and context.js places it next to its button, as that
   script states. It stays invisible until the script has placed it. */
.context{
	--context-pad-y:var(--space-3);
	--context-pad-x:var(--space-4);
	position:fixed;inset:auto;margin:0;
	width:max-content;max-width:calc(100vw - var(--space-4) * 2);
	max-height:calc(100vh - var(--space-4) * 2);overflow:auto;
	padding:var(--context-pad-y) var(--context-pad-x);border-radius:var(--r-tile);
	background:var(--surf-hi);color:var(--ink);
	border:var(--hairline);box-shadow:var(--drop-lift);
	-webkit-backdrop-filter:var(--glass);
	backdrop-filter:var(--glass);
}
.context:not([data-placed]){visibility:hidden}
/* A context element's closing action: a link that fills the element's whole
   width at its foot, under a hairline, like the last segment of a button
   segmented from top to bottom. It reaches past the element's padding to the
   element's edges, and its ground turns the sunk surface while the pointer is
   over it. */
.context-action{
	display:block;
	margin:var(--context-pad-y) calc(var(--context-pad-x) * -1) calc(var(--context-pad-y) * -1);
	padding:var(--context-pad-y) var(--context-pad-x);
	border-top:var(--hairline);
	font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	color:var(--ink);text-decoration:none;
}

/* The ruled separator between repeated rows and between neighboring
   segments, which nearly every list and every panel of segments wants. */
.shelves li + li,.side-section + .side-section,.faq div + div,.numbers li + li,
.agents-by-detail + .agents-by-detail,.panel-stack > * + *,.structure-description,.hero-actions{border-top:var(--hairline)}

/* ─────────────────────────────────────────────
   CHROME
   ───────────────────────────────────────────── */
/* The bar keeps the hairline the surface gives it along its bottom edge, and
   drops the hairlines on its other edges. That line is the same weight and the
   same color as the rule a section opens with, so the page is ruled
   consistently from top to bottom.

   The shadow carries the top highlight alone. A drop shadow under a bar this
   close to the content reads as another line beneath the hairline. */
.bar{
	position:sticky;top:0;z-index:20;
	border-left:0;border-right:0;border-top:0;border-radius:0;
	box-shadow:var(--edge);
}
.bar-in{
	max-width:var(--content-xl);margin:0 auto;height:var(--bar);
	padding:0 var(--pad);display:flex;align-items:center;gap:var(--space-4);
}

/* The PineSpark logo is a drawing that holds the icon and the wordmark together,
   so it is placed as a background image rather than built out of an icon and a
   line of text. Its width and its vertical position are the figures the
   previous site used, and they are drawing measurements rather than steps.

   The ink does not sit centered inside the drawing's own box, so a box centered
   by the usual means leaves the mark reading low. The vertical position places
   the drawing higher in the spare room of the bar than centering would, and
   that lifts the ink back to the middle.

   The drawing comes in a light and a dark ink, and each theme names the one
   that reads on it. */
.mark{
	display:block;flex:none;width:144px;
	background:var(--logo-lockup) 0% 38.5% / 100% auto no-repeat;
}

/* The box the mark sits in is a little shorter than the bar, by the figure the
   site before this one used for the same drawing in the same bar.

   The box is centered in the bar, so it starts a little way down, and the
   vertical position then places the ink inside it. Giving the box the bar's
   full height instead puts the ink slightly higher, which is what leaves the
   mark reading above center. */
.bar .mark{height:calc(var(--bar) - 12px)}

.bar-nav{display:flex;gap:var(--space-1);margin-left:var(--space-2)}
.bar-nav a,.bar-menu-button{
	padding:var(--space-2) var(--space-3);border-radius:var(--r-ctrl);
	color:var(--mute);font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	white-space:nowrap;
	transition:color var(--quick),background-color var(--quick);
}

/* A menu of the bar: a button worded and drawn as the bar's links are, with
   the sprite's chevron, which points down and turns up while the menu is open,
   and the menu's links in a panel under it, on the page's solid surface. */
.bar-menu{position:relative}
.bar-menu-button{display:flex;align-items:center;gap:var(--space-1);border:0;background:transparent;font-family:inherit;cursor:pointer}
.bar-menu-button .icon{width:14px;height:14px;transition:transform var(--quick)}
.bar-menu-button[aria-expanded="true"] .icon{transform:rotate(180deg)}
.bar-menu-panel{
	display:none;position:absolute;top:calc(100% + var(--space-2));left:0;min-width:220px;
	flex-direction:column;gap:2px;padding:var(--space-2);
	border:var(--hairline);border-radius:var(--r-card);
	background:var(--surf-solid);box-shadow:var(--drop-lift);
}
.bar-menu-button[aria-expanded="true"] + .bar-menu-panel{display:flex}

.bar-r{margin-left:auto;display:flex;align-items:center;gap:var(--space-2)}
.toggle{
	display:inline-flex;padding:2px;border:var(--hairline);
	border-radius:var(--r-pill);background:var(--surf-sink);
}
/* Each button of the color-mode control is a round button holding its mode's
   drawing, a sun or a moon. */
.toggle button{
	display:grid;place-items:center;
	border:0;background:transparent;color:var(--faint);
	padding:var(--space-1);border-radius:var(--r-pill);cursor:pointer;
	transition:color var(--quick),background-color var(--quick);
}
.toggle button[aria-pressed="true"]{background:var(--surf-hi);color:var(--ink)}

/* the quieter way into an account, beside the button that is the louder
   one */
.bar-link{
	padding:var(--space-2);color:var(--mute);white-space:nowrap;
	font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	transition:color var(--quick);
}

/* The button that opens the links. It appears only at the width where the links
   leave the bar's row, so it is drawn here and shown there.

   It is square at the height every other control states, so it lines up with
   the sign-in button beside it and a full round lands on an exact radius. */
.burger{
	display:none;align-items:center;justify-content:center;flex:none;
	width:var(--space-7);height:var(--space-7);
	border:1px solid var(--line-hi);border-radius:var(--r-pill);
	background:transparent;color:var(--ink);cursor:pointer;
	transition:background-color var(--quick);
}
.burger .icon{width:18px;height:18px}
.burger .burger-shut{display:none}
.bar[data-menu="open"] .burger .burger-open{display:none}
.bar[data-menu="open"] .burger .burger-shut{display:block}

.page{
	position:relative;z-index:2;max-width:var(--content-xl);margin:0 auto;
	padding:0 var(--pad) var(--space-9);
}
/* A page whose scroll PineScroll moves, as start.js hands the start page's
   scroll to it, carries data-pine-scroll on its root. PineScroll fixes the page
   frame to the window's top left corner, as wide as the window, and moves it by
   a transform. The frame stays in the middle of the window, as wide as it is
   everywhere else, because it stands against the window's right edge as well
   and its margins share the room left over. The bar stays in the body's own
   flow above it, so the frame keeps the bar's height and the bar's hairline
   free at its top, and the page's content starts under the bar as it does
   everywhere else. The hairline is a drawn line, so it is a pixel. */
html[data-pine-scroll] .page{right:0;padding-top:calc(var(--bar) + 1px)}
/* The opening block of every page stands a rule gap below the site bar, the
   same gap that separates the sections below it, so a page's opening banner
   has as much room above it as below it. This rule alone sets that gap, and no
   block sets a top margin of its own for it. The start page's hero is the only
   exception: it fills the stretch under the bar and places its headline
   within that stretch itself. Every section keeps the same gap above it. */
.page > :first-child:not(.hero),.sec{margin-top:var(--rule-gap)}

.foot{margin-top:var(--rule-gap);border-top:var(--hairline);padding-top:var(--space-6)}
/* The text about PineSpark stands on the left across every row, and the
   navigation columns fill four tracks beside it, row after row, so seven
   columns stand four above three. */
.foot-top{
	display:grid;grid-template-columns:minmax(280px,1.9fr) repeat(4,minmax(0,1fr));
	gap:var(--space-7) var(--space-6);
}
/* The footer wears the same drawing, wider than in the bar and in the same
   proportion to it that the previous site used, in a box tall enough that the
   vertical position still has slack to work in. The width and the height are
   drawing measurements. */
.foot-brand .mark{width:224px;height:60px;margin-bottom:var(--space-4)}
/* The text about PineSpark stands across both rows of columns, and it keeps a
   step of space on its right beyond the gap between the columns, so the
   navigation columns stand clear of it. */
.foot-brand{grid-row:span 2;padding-right:var(--space-5)}
.foot-brand p{
	margin:0;font-size:var(--text-sm);line-height:var(--leading-sm);
	color:var(--mute);max-width:42ch;
}
/* The blurb runs to several paragraphs, so each paragraph after the opening one
   stands off the paragraph above it, and the whole reads as paragraphs rather
   than as a solid block. */
.foot-brand p + p{margin-top:var(--space-3)}
.foot-col h5{margin:0 0 var(--space-3)}
.foot-col a{
	display:block;padding:var(--space-1) 0;font-size:var(--text-sm);line-height:var(--leading-sm);
	color:var(--mute);transition:color var(--quick);
}
.foot-base{
	margin-top:var(--space-6);padding-top:var(--space-4);border-top:var(--hairline);
	display:flex;align-items:center;justify-content:space-between;
	gap:var(--space-4);flex-wrap:wrap;
}
.foot-base nav{display:flex;gap:var(--space-4);flex-wrap:wrap}
.foot-disclaimer{
	flex:1 1 100%;margin:0;max-width:var(--content-lg);
	font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--faint);
}

/* ─────────────────────────────────────────────
   SECTIONS
   ───────────────────────────────────────────── */

/* The separator remains visible while the section label and its bullet stay
   in the markup without taking a visible line. The margin, the separator's
   hairline and the headline's inset place its visible ink a rule gap below the
   separator. */
.sec-tag{
	display:block;border-top:var(--hairline);
	margin-bottom:calc(var(--space-4) + var(--space-3) - 1px);
	font-size:0;
}
.sec-tag i{display:none}

.sec-head{
	display:flex;align-items:baseline;justify-content:space-between;
	gap:var(--space-4);margin-bottom:var(--space-4);
}
/* The heading of a section, of a reading block, of a card or a tile, of the
   catalog's results, and of the form to modify an Agent. A reading block's
   heading keeps a step of room under it, as the rule for it below states. */
.sec-head h2,.block h2,.channel-card h2,.dirhead h3,.stack h3,.tools h2,.modify-agent h2{
	margin:0;font-size:var(--text-lg);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);
}
.sec-head p{margin:var(--space-1) 0 0;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--faint)}
.sec-head .more{white-space:nowrap}

/* a reading block on the agent page, which takes a plainer heading */
.block h2{margin:0 0 var(--space-1)}
.block .note{margin:0 0 var(--space-4);font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--faint)}
.block p{
	margin:0 0 var(--space-3);font-size:var(--text-sm);
	line-height:var(--leading-sm);color:var(--mute);
}
.block p:last-child{margin-bottom:0}

/* the banner: a stretch of the gradient, so the page has a place that is not
   a glass panel on the page color.

   Every gradient ground, the banners' and the Channels', is laid out over the
   whole box, border included. A background is laid out inside the border by
   default and repeated to fill the space under it, so the see-through border
   would show a strip of the far edge's colors along each edge. */
.band{
	position:relative;overflow:hidden;border-radius:var(--r-card);
	background:var(--gradient) border-box;border:var(--hairline);
	padding:clamp(var(--space-5),3.6vw,var(--space-7));
	box-shadow:var(--drop);
}
.band::after{
	content:"";position:absolute;width:420px;height:420px;right:-140px;top:-220px;
	border-radius:50%;pointer-events:none;
	background:radial-gradient(circle,var(--glow),transparent 68%);
}
/* A solid button on a banner, or on a tile painted like one, takes the banner's
   ink as its color, so it stands out against the banner in either theme. Its
   text stands on the button rather than on the gradient, so it carries no
   shadow. */
.band .btn-solid,.wall-offer .btn-solid,.channel-all .btn-solid{background:var(--band-ink);color:var(--band-button-ink);text-shadow:none}
/* The heading takes the banner's ink from the head around it. */
.band-head{max-width:52ch;margin-bottom:clamp(var(--space-5),3vw,var(--space-6));color:var(--band-ink)}
.band-head h2{
	margin:0;font-size:var(--text-2xl);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-tight);
}
.band-head p{
	margin:var(--space-2) 0 0;font-size:var(--text-sm);
	line-height:var(--leading-sm);color:var(--band-mute);
}

/* ─────────────────────────────────────────────
   PARTS
   ───────────────────────────────────────────── */

/* the category name a card wears */
.tag{
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);
	color:var(--acc);background:var(--acc-soft);border-radius:6px;
	padding:var(--space-1) var(--space-2);
}

/* the flag on a job that was added this month */
.new{
	font-size:var(--text-xs);line-height:var(--leading-normal);letter-spacing:var(--tracking-normal);
	color:var(--acc);background:var(--acc-soft);border-radius:var(--r-pill);
	padding:2px var(--space-2);margin-left:var(--space-2);
}

/* a tool name, worn in a row */
.chips{display:flex;flex-wrap:wrap;gap:var(--space-1);margin-top:auto;padding-top:var(--space-1)}
.chip{
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);color:var(--faint);
	border:var(--hairline);border-radius:6px;padding:var(--space-1) var(--space-2);
}

/* an evidence pill: what buyers rated, or what a figure says */
.stats{display:flex;flex-wrap:wrap;gap:var(--space-1)}
.stat{
	display:inline-flex;align-items:center;gap:var(--space-1);
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);color:var(--mute);
	border:var(--hairline);border-radius:6px;padding:var(--space-1) var(--space-2);
}
.stat .icon{width:11px;height:11px;color:var(--acc)}
.stat u{text-decoration:none;color:var(--faint)}

/* A tool's picture, which the ToolIcon element draws wherever the store shows a
   tool. The picture stands in a white frame, so every picture reads on any ground
   in either theme, and a tool without a picture shows the plug drawing in the
   same frame, stroked in the ink of the white paper. Each size is a drawn box, so
   its frame, its picture and its radius stay in pixels. The fill size takes the
   whole face and the shape of the control it stands in. */
.tool-icon{
	flex:none;display:grid;place-items:center;
	background:var(--paper-frame);border:1px solid var(--paper-line);
	--icon-stroke:var(--paper-dim);
}
.tool-icon img{object-fit:contain}
.tool-icon-xs{width:20px;height:20px;border-radius:5px}
.tool-icon-sm{width:24px;height:24px;border-radius:7px}
.tool-icon-md{width:44px;height:44px;border-radius:12px;box-shadow:var(--edge)}
.tool-icon-md img,.tool-icon-md .icon{width:28px;height:28px}
.tool-icon-lg{width:56px;height:56px;border-radius:14px;box-shadow:var(--edge)}
.tool-icon-lg img,.tool-icon-lg .icon{width:36px;height:36px}
.tool-icon-fill{width:100%;height:100%;border:0;border-radius:inherit}
.tool-icon-fill img,.tool-icon-fill .icon{width:44%;height:44%}

/* An industry's mark and a role's avatar are painted in the record's own
   color, which palette.css makes from the brand's colors by a harmony of each
   kind's own, at the place the element writes into --mark-place. Their colors
   are the same in the light and the dark theme, like a tool's picture, and
   deep enough to carry white text. Their sizes are drawn boxes, so they are
   pixels. */
.industry-mark{
	display:block;flex:none;border-radius:7px;
	background:linear-gradient(135deg,
		oklch(from var(--industry-light-source) l calc(c * var(--industry-keep)) calc(h + var(--industry-arc-start) + var(--mark-place) * var(--industry-arc))),
		oklch(from var(--industry-deep-source) l calc(c * var(--industry-keep)) calc(h + (var(--industry-arc-start) + var(--mark-place) * var(--industry-arc)) * (1 - var(--industry-lean)))));
}
.industry-mark-sm{width:24px;height:24px}
/* The medium mark carries the industry's first letter at its middle, in white. */
.industry-mark-md{width:56px;height:56px;display:grid;place-items:center}
.industry-mark-md i{
	font-style:normal;font-size:var(--text-xl);line-height:var(--leading-none);font-weight:var(--weight-semibold);
	color:var(--ink-on-color);
}
/* The large mark is a tile that carries the industry's name at its foot, and its
   first letter large and faint in its top right corner. */
.industry-mark-lg{
	position:relative;overflow:hidden;display:flex;align-items:flex-end;min-height:96px;
	padding:var(--space-3);border-radius:var(--r-tile);box-shadow:var(--drop);
}
.industry-mark-lg i{
	position:absolute;top:var(--space-1);right:var(--space-3);
	font-style:normal;font-size:var(--text-3xl);line-height:var(--leading-none);font-weight:var(--weight-semibold);
	color:color-mix(in srgb,var(--ink-on-color) 28%,transparent);
}
/* The name on the tile is white, with a slight dark shadow a pixel down and
   blurred well beyond that, so each letter stands off the industry's color. */
.industry-mark-lg b{
	position:relative;font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-semibold);
	color:var(--ink-on-color);
	text-shadow:0 1px 8px color-mix(in srgb,var(--brand-ink) 60%,transparent);
}
.role-avatar{
	display:grid;place-items:center;flex:none;border-radius:50%;
	background:oklch(from var(--role-source) l calc(c * var(--role-keep)) calc(h + var(--role-arc-start) + var(--mark-place) * var(--role-arc)));color:var(--ink-on-color);
	font-weight:var(--weight-semibold);letter-spacing:var(--tracking-normal);
}
.role-avatar-sm{width:24px;height:24px;font-size:var(--text-xs);line-height:var(--leading-none)}
.role-avatar-lg{width:44px;height:44px;font-size:var(--text-base);line-height:var(--leading-none)}

/* THE ITEMS OF A RECORD
   One industry, one role or one category drawn as an item that carries its own
   context element, as the IndustryTile, RoleEntry and CategoryEntry elements
   draw them, and several of one kind as a list, as IndustryTiles, RoleList and
   CategoryList draw them. An item opens its context element while the pointer
   rests on it, unless the placement places it without hover, and a press either
   opens it too or follows the item's link, as the placement decides. A
   category's small entry is drawn by the ways to find Agents and by the preview
   of the directory.

   An industry's tiles stand in a grid, as many to a row as fit at their
   narrowest readable width, and a single one as wide as the list where the list
   is narrower than that. Under the pointer the picture in a tile rises a little
   while the tile stays where it is, so the place the pointer rests on and the
   place a press lands on are the same tile. A tile that counts the Agents made
   for its industry shows the count under the picture, and a tile given a line
   shows it under that, set as a role's line is. */
.industry-tiles{
	display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--space-3);
}
.industry-tile{
	display:block;width:100%;padding:0;border:0;background:none;
	font:inherit;text-align:left;cursor:pointer;border-radius:var(--r-tile);
}
.industry-tile .industry-mark-lg{transition:transform .15s ease}
.industry-tile:hover .industry-mark-lg,.industry-tile:focus-visible .industry-mark-lg{transform:translateY(-2px)}
.industry-tile .tally{display:block;margin:var(--space-2) 0 0}
.industry-tile-line{
	display:block;margin:var(--space-1) 0 0;
	font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute);
}
/* A role's entries stand on a panel like a list of colleagues, each its avatar
   beside its name and a line under the name, in as many columns as fit at their
   narrowest readable width, and in a single one as wide as the panel where the
   panel is narrower than that. An entry reaches a step past its avatar and its
   words on either side, and under the pointer the whole of it takes the sunk
   ground, as a row of a side panel does. */
.role-list{
	padding:var(--space-2) var(--space-5);border-radius:var(--r-card);
	display:grid;grid-template-columns:repeat(auto-fill,minmax(min(17rem,100%),1fr));column-gap:var(--space-6);
}
.role-entry{
	display:flex;align-items:center;gap:var(--space-3);
	width:calc(100% + var(--space-3) * 2);margin:0 calc(var(--space-3) * -1);padding:var(--space-3);
	border:0;border-radius:var(--r-tile);background:none;font:inherit;text-align:left;color:inherit;cursor:pointer;
}
/* a name on a line of its own, in the full ink: a role's name in its entry, and
   the name of an input or an output a context element explains */
.role-entry b,.explained-name{
	display:block;font-size:var(--text-sm);line-height:var(--leading-sm);
	font-weight:var(--weight-medium);color:var(--ink);
}
.role-entry > div > span{display:block;font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute)}

/* The head of a context element that is about one thing: its picture beside its
   name, such as a tool's icon, an industry's mark, a role's avatar or a
   thumbnail of a category's drawing. */
.context-head{display:flex;align-items:center;gap:var(--space-2)}
.context-head b{font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);color:var(--ink)}
/* The thumbnail of a category's drawing on its teaser ground, which heads the
   category's context element, as tall as the small pictures that head the
   others. It is a drawn box, so its size is in pixels. */
.category-thumb{
	flex:none;height:24px;aspect-ratio:16/9;border-radius:6px;overflow:hidden;position:relative;
	border:var(--hairline);
}

/* The context element of a record, at a reading width: its head, then what it
   holds, and at its foot the link to every Agent of the record. An industry's,
   a role's or a category's holds the words its item was given, such as what an
   Agent does for it or the record's own summary. A tool's holds the inputs and
   the outputs of the Agent it makes up, each group under its small heading. */
.relation-context,.structure-about-panel{width:20rem}
.relation-context > p,.channel-post p{margin:var(--space-2) 0 0;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute)}
.relation-context h5{
	margin:var(--space-4) 0 var(--space-2);font-size:var(--text-xs);line-height:var(--leading-normal);
	font-weight:var(--weight-medium);letter-spacing:var(--tracking-normal);color:var(--faint);
}

/* The tools an Agent works with, under the description on its card: a label,
   and under it a multi tool row of the tools the export holds a picture for,
   laid out the way the card's Published by row is. */
.with{display:flex;flex-direction:column;align-items:flex-start}

/* The multi rows, MultiToolRow, MultiIndustryRow and MultiRoleRow: a row of
   pictures that stands for several things, then the words that say how many.
   The pictures stand side by side, or overlap in a stack where the row stands
   for many things. In a stack each picture casts a soft shadow onto the one it
   covers, so the edge between two pictures shows in the light and the dark
   theme. A row that opens or links underlines its words while the pointer is
   over it. */
.multi-tool-row,.multi-industry-row,.multi-role-row{
	display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-2);
	padding:0;border:0;background:none;text-align:left;
	font:inherit;font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute);
}
button:is(.multi-tool-row,.multi-industry-row,.multi-role-row),
a:is(.multi-tool-row,.multi-industry-row,.multi-role-row){cursor:pointer}
.multi-tool-text,.multi-industry-text,.multi-role-text{white-space:nowrap}
.multi-tool-pictures,.multi-industry-pictures,.multi-role-pictures{display:flex;gap:var(--space-1)}
.multi-tool-stacked,.multi-industry-stacked,.multi-role-stacked{gap:0}
.multi-tool-stacked .tool-icon + .tool-icon,
.multi-industry-stacked .industry-mark + .industry-mark,
.multi-role-stacked .role-avatar + .role-avatar{
	margin-left:calc(var(--space-2) * -1);
	box-shadow:-1px 0 3px color-mix(in srgb,var(--paper-shadow) 28%,transparent);
}

/* A Channel's own icon, shared by Channel cards and the Channel badge. The
   Channel's masthead shows the icon's drawing alone, as .channel-mark. The icon
   always sits in a white frame drawn the way .tool-icon frames a
   tool's picture, so it reads on any ground in either theme. The export draws
   the icon as a square tile in the Channel's accent colors, and its corners
   are rounded so the tile sits concentric in the frame: the frame's radius less
   the distance between the frame's edge and the tile's edge. Frame and icon are
   drawn boxes, so their sizes stay in pixels. */
.channel-icon{
	width:32px;height:32px;flex:none;display:grid;place-items:center;
	border-radius:9px;background:var(--paper-frame);border:1px solid var(--paper-line);
	box-shadow:var(--edge);
}
.channel-icon svg{display:block;width:20px;height:20px;border-radius:3px}

/* A Channel's name, in the Channel's own colors: the primary accent in the
   light theme and the secondary accent in the dark theme. The tag the name is
   written in carries the primary and the secondary accent, and light-dark()
   picks between them by the color scheme each theme block sets. */
.channel-name{color:light-dark(var(--accent-1),var(--accent-2))}

/* The ChannelBadge element: a Channel's icon and name drawn like a segmented
   button, with the icon as its left segment and the name, in a white box, as
   its right one. The name always stands on white, so it always takes the
   color the light theme gives it, the primary accent.

   The frame paints no ground of its own. It holds the element's radius and
   crops the icon and the white box to it. Nothing lies beneath the icon, so no
   white shows through the soft edge of its cropped corners. Around its outside
   the frame casts --badge-glow, a soft dark shadow on the light page and a soft
   white glow on the dark page, so the badge stands out a little from what it
   sits on. A frame that crops its content still draws its own shadow outside
   itself.

   The frame is as tall as a tool in a side panel list, which is the frame of
   the tool's picture at the sm size. The icon's box fills the frame from its
   top edge to its bottom edge and from its left edge, and it has no radius of
   its own. The box is square, so the icon's tile fills it whole. The frame's
   radius is the radius of that tool picture, so the two round alike.

   The white box fills the rest of the frame, from top to bottom. Its hairline
   runs along its top, right and bottom edges, and never between it and the
   icon. Its right corners take the frame's radius, so the hairline follows the
   frame's curve rather than being cropped away with the corners.

   The name always stands on one line, on the middle of the white box, and
   where the white box has too little room for it, the name ends in an
   ellipsis. The same step of white stands on either side of the name: between
   the icon and the name, and between the name and the hairline. Frame and icon
   are drawn boxes, so their sizes stay in pixels. */
.channel-badge{
	align-self:flex-start;display:inline-flex;align-items:stretch;max-width:100%;
	overflow:hidden;border-radius:7px;box-shadow:var(--badge-glow);
}
.channel-badge .channel-icon{flex:none;width:24px;height:24px;border:0;border-radius:0;background:none;box-shadow:none}
.channel-badge .channel-icon svg{width:24px;height:24px;border-radius:0}
.channel-badge-text{
	display:flex;align-items:center;min-width:0;
	padding:0 calc(var(--space-2) + 1px) 0 var(--space-2);
	border-radius:0 7px 7px 0;background:var(--paper-frame);
	box-shadow:inset 0 1px 0 var(--paper-line),inset -1px 0 0 var(--paper-line),inset 0 -1px 0 var(--paper-line),var(--edge);
}
.channel-badge b{
	display:block;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;
	font-size:var(--text-xs);line-height:var(--leading-normal);font-weight:var(--weight-medium);
}
.channel-badge .channel-name{color:var(--accent-1)}

/* THE SIDE PANEL
   The filter panel beside the Agent catalog and the panel that stays in view on
   an Agent's page are the same side panel: a raised surface held in view under
   the bar while the page scrolls, holding side panel sections one above the
   other. The classes side and buy carry only what differs between the two
   places.

   A section stands in from the panel's edge by the panel's padding and its
   own, and a hairline stands between neighboring sections, as the ruled
   separator states. Its caption is set as every small column caption is. */
.side-panel{
	position:sticky;top:calc(var(--bar) + var(--space-4));
	border-radius:var(--r-card);padding:var(--space-1);
}
/* A side panel still taller than its room once side-panel.js has collapsed
   every section that can collapse is held to that room, which side-panel.js
   writes as its max-height, and its sections scroll inside it, so the panel
   never runs past the bottom of the window. */
.side-panel[data-scrolls]{overflow-y:auto;overscroll-behavior:contain}
.side-section{padding:var(--space-3)}
.side-section h4{margin:0 0 var(--space-2)}

/* A side panel list holds an entry to a row. A row reaches a step past the
   section's text on either side, so the ground a row takes under the pointer
   stands clear of its words. A row that picks, opens or links takes the sunk
   ground under the pointer, and the pick that is open takes the accent's
   ground. An entry's count stands at the right end of its row. */
.side-entry{
	display:flex;align-items:center;gap:var(--space-2);
	width:calc(100% + var(--space-2) * 2);margin:0 calc(var(--space-2) * -1);
	padding:var(--space-1) var(--space-2);border:0;border-radius:8px;background:none;
	font:inherit;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute);text-align:left;
	transition:color var(--quick),background-color var(--quick);
}
a.side-entry,button.side-entry{cursor:pointer}
.side-entry[aria-current="true"]{color:var(--ink);background:var(--acc-soft)}
/* A Channel entry shows the Channel badge. The badge gives up width before the
   count beside it does, and its name then ends in an ellipsis, as the badge's
   own rule states. A row that links underlines the name under the pointer, as a
   badge that is itself a link does. */
.side-entry .channel-badge{min-width:0}

/* A side panel section marked side-empty holds no row, and it stays out of
   view. The Agent catalog renders a filter group that way where the agents on
   view give it nothing to list, so a later view can fill it in its place. */
.side-empty{display:none}

/* The button under a list that holds more entries than it shows at first. On a
   folded list it shows a downward arrow and the words that say how many entries
   there are, and on an unfolded list an upward arrow and the word that folds the
   list again. Its aria-expanded says which state the list is in, and
   side-panel.js sets it. A folded list shows the entries before its fold and its
   open pick alone. The button a list without pictures collapses to, .side-open,
   looks the same and opens the list's context element. */
.side-list[data-folded] > [data-past-fold]{display:none}
.side-more,.side-open{
	display:flex;align-items:center;gap:var(--space-2);margin-top:var(--space-1);padding:var(--space-1) 0;
	border:0;background:none;cursor:pointer;
	font:inherit;font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--faint);
	--icon-stroke:currentColor;
}
.side-more-hide,.side-more[aria-expanded="true"] .side-more-show{display:none}
.side-more[aria-expanded="true"] .side-more-hide{display:inline}
/* the chevron in the sprite points down, so the button of an unfolded list turns it up */
.side-more[aria-expanded="true"] .icon{transform:rotate(180deg)}

/* A section that can collapse holds its collapsed form after its content: for
   a list of things with pictures a single multi row that stands for every
   entry, for any other list its button that shows every entry, and for the
   Agent tree a single row that counts its variants. The form shows only where
   side-panel.js has marked the section data-collapsed, because the side panel
   has no room for the section's content, and it then takes the place of every
   part of the section but its caption and its context element.

   A section that folds or collapses also holds a context element with its full
   content, set at the side panel's width and headed by the section's caption.
   It opens where the full content has no room in the window, and it scrolls
   where the content is taller than the window. */
.side-collapsed{display:none}
.side-section[data-collapsed] > :not(h4,.side-collapsed,.context){display:none}
.side-section[data-collapsed] > .side-collapsed{display:block}
.side-context{width:var(--side-panel-width)}
.side-context-title{
	display:block;margin-bottom:var(--space-2);
	font-size:var(--text-xs);line-height:var(--leading-normal);
	font-weight:var(--weight-medium);color:var(--faint);
}
/* The collapsed form of the Agent tree: its row that counts the variants, as a
   button across the section's width with an arrow pointing down at its right
   end, which expands the tree. */
.side-expand{width:100%;border:0;background:none;font:inherit;text-align:left;cursor:pointer}
.side-expand .icon{margin-left:auto;color:var(--faint)}

/* The buttons of a side panel, one above the other at the section's full
   width, and the same buttons in the segment under an Agent's hero, side by
   side. Each is a taller control than the standard one, so it states the
   taller even height. */
.side-acts{display:grid;gap:var(--space-2)}
.side-acts .btn,.hero-actions .btn{
	min-height:var(--space-8);
	padding:var(--space-3) var(--space-5);font-size:var(--text-sm);
}
.side-acts .btn{width:100%}

/* The trail back to where this page sits.

   It carries its space below rather than above, so whatever follows it is
   separated by the trail's own rule and no place that uses it has to write one.
   Above it there is nothing to supply, because the section marker that precedes
   it in the catalog already ends with the same step, and on an agent page the
   trail opens the banner. */
.crumbs{display:flex;align-items:center;gap:var(--space-2);margin:0 0 var(--space-2);flex-wrap:wrap}
/* Every stage of the trail that links somewhere is underlined while the
   pointer is over it. The home stage is a drawing rather than text, and a text
   underline draws nothing under a drawing, so its underline is a hairline along
   its bottom edge. The hairline is always there and takes a color only on
   hover, so the trail does not move. */
.crumbs a:hover{text-decoration:underline;text-underline-offset:.2em}
.crumbs a:has(> .icon:only-child){display:inline-flex;border-bottom:1px solid transparent}
.crumbs a:has(> .icon:only-child):hover{border-bottom-color:currentColor}

/* ─────────────────────────────────────────────
   HOME
   ───────────────────────────────────────────── */

/* the hero, where the search is the storefront door */
/* The section opens and closes on the same gap.

   The hero is not capped as a whole, because the headline wants more room
   than the search box under it. Each part states the width it sits in. */
.hero{padding:var(--space-6) 0;text-align:center}
/* Every section opens with a margin above it, which would land on top of the
   hero's own bottom padding and leave a wider gap under the hero than the hero
   asked for. The section after the hero drops that margin, so the gap below the
   hero is the hero's padding and nothing else. */
.hero + .sec{margin-top:0}

/* THE FIND-AGENTS HEROES: the hero every page of the Agent catalog under
   /find-agents opens with, FindAgentsHero and the hero of each kind that
   inherits it. Each holds the page's trail, a picture beside the headline, the
   line under the headline, and on its right the PineSpark icon or a drawing.
   Its padding stays at a compact step, so the hero introduces the catalog
   without pushing the results out of the initial view.

   A hero on the CI gradient, the banners' flowing ground or a section's teaser
   ground, sets all of its text, its trail included, as text on the CI
   gradient. A hero on a ground of its own, a tool's, a Channel's, an
   industry's or a role's, sets its headline and its line in the colors the
   ground carries: the ground's name color for the headline, and its ink for
   the line. The hero of a Channel, an industry or a role writes its trail in
   the ground's ink too, and the tool's hero writes it in the primary CI
   color.

   On a window wider than a phone, every find-agents hero is the same height at
   a given width, whatever it holds, so the catalog under it starts at the same
   place on every such page. Its content is a fixed stack of rows: the trail on
   one line, the row of the headline as tall as the picture beside it, and the
   line under it, which always takes room for its lines, as many as
   --find-hero-note-lines names. A trail too long for its line is cut at the
   right edge, a headline too long for its lines ends in an ellipsis, and so
   does a line under it. On a phone the headline shows whole instead, as the
   rule for a phone's width below states. The heading
   of the results under the hero names the view in full. The picture beside the
   headline, a tool's picture, an industry's mark, a role's avatar or a
   Channel's drawing, is a drawn box, so its size is in pixels.

   When the Agent catalog shows another view in place, catalog.js fades the new
   hero in over the old one: the new hero stands in the place faded out, the old
   one lies over it at the same spot, and each fades to its end. */
.find-hero{
	--find-hero-picture:56px;
	--find-hero-headline-lines:1;
	--find-hero-head:var(--find-hero-picture);
	--find-hero-note-lines:2;
	--find-hero-trail:calc(var(--text-xs) * var(--leading-normal));
	--find-hero-note:calc(var(--find-hero-note-lines) * var(--text-base) * var(--leading-normal));
	--find-hero-inner:calc(var(--find-hero-trail) + var(--space-2) + var(--find-hero-head) + var(--space-3) + var(--find-hero-note));
	transition:opacity .8s ease;
}
/* A compact hero keeps its padding at a compact step: every find-agents hero,
   the heroes of the category directory, of a category and of the Channels
   page, a Channel's hero, and a Channel's intro under it. */
.find-hero,.category-hero,.category-detail-hero,.channel-index-hero,.channel-hero,.channel-intro{padding:var(--space-5) var(--space-6)}
/* A find-agents hero and the hero of an Agent's page hold their text beside the
   PineSpark icon, which takes a column of its own on the right. */
.find-hero .band-in,.hero-band .band-in{
	display:grid;grid-template-columns:minmax(0,1fr) minmax(72px,96px);
	gap:var(--space-6);align-items:stretch;
}
.find-hero .band-in{height:var(--find-hero-inner)}
.find-hero-content,.agent-hero-content{min-width:0;align-self:center}
.find-hero .crumbs{
	height:var(--find-hero-trail);margin:0 0 var(--space-2);
	flex-wrap:nowrap;overflow:hidden;white-space:nowrap;line-height:var(--leading-normal);
}
.find-hero-head{display:flex;align-items:center;gap:var(--space-4);height:var(--find-hero-head)}
.find-hero-head > .tool-icon,.find-hero-head > .industry-mark,.find-hero-head > .role-avatar,.find-hero-head > .channel-mark{
	flex:none;width:var(--find-hero-picture);height:var(--find-hero-picture);
}
.find-hero-head > .role-avatar{font-size:var(--text-lg);line-height:var(--leading-none)}
.find-hero-head h1{
	margin:0;min-width:0;font-size:var(--text-2xl);line-height:var(--leading-normal);
	font-weight:var(--weight-semibold);letter-spacing:var(--tracking-tight);
	display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--find-hero-headline-lines);overflow:hidden;
}
.find-hero-note{
	margin:var(--space-3) 0 0;max-width:58ch;height:var(--find-hero-note);
	font-size:var(--text-base);line-height:var(--leading-normal);
	display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--find-hero-note-lines);overflow:hidden;
}
/* Text on an icon's ground takes the ground's colors: its name color for a
   headline and the stages of a trail that stand out, and its ink for the rest,
   in a find-agents hero, a Channel's hero and a Channel's tile. */
.find-hero.icon-ground .find-hero-head h1,.find-hero.icon-ground:not(.tool-hero) .crumbs a:hover,
.find-hero.icon-ground:not(.tool-hero) .crumbs b{color:var(--icon-name)}
.find-hero.icon-ground .find-hero-note,.find-hero.icon-ground:not(.tool-hero) .crumbs,
.channel-card.icon-ground .channel-subheadline,.channel-hero .crumbs{color:var(--icon-ink)}
#catalog-hero{position:relative}
.find-hero.find-hero-entering,.find-hero.find-hero-gone{opacity:0}
.find-hero.find-hero-leaving{position:absolute;top:0;left:0;right:0;z-index:1;pointer-events:none}
/* A section's drawing stands on the right of its hero, as tall as the hero's
   content and as wide as its shape needs at that height, on the ground with no
   ground of its own. */
.find-hero-drawn .band-in{grid-template-columns:minmax(0,1fr) auto}
.find-hero-visual{height:var(--find-hero-inner);aspect-ratio:16/9;overflow:hidden;border-radius:var(--r-card)}
/* On a light ground the white frame of the tool's picture stands on white. It
   carries no hairline there, and a layered shadow lifts it off the ground
   instead: a close one that draws its edge, an even one all around it, and a
   soft one that falls a little lower. Every layer blurs several times further
   than it is offset, so the shadow shows on every side of the frame. The
   hairline is transparent rather than gone, so the frame keeps its size. The
   ground is the same in the light and the dark theme, so the shadow is too,
   rather than taking the theme's own. */
.tool-hero.icon-ground-light .tool-icon-lg{
	border-color:transparent;
	box-shadow:0 1px 3px color-mix(in srgb,var(--paper-shadow) 18%,transparent),0 0 14px 1px color-mix(in srgb,var(--paper-shadow) 16%,transparent),0 4px 22px color-mix(in srgb,var(--paper-shadow) 22%,transparent);
}
/* The find-agents heroes and the hero of an Agent's page show the white
   PineSpark icon on their right, in the light and the dark theme, lifted by the
   same kind of layered shadow as the tool's picture on a light ground. The icon
   is a picture drawn as a background, so the shadow is a drop shadow, which
   follows the icon's own shape rather than its box, and it lets the white icon
   read on white and on a light accent alike. It fills the content height inside
   the hero's own padding. */
.hero-pinespark{
	display:block;align-self:stretch;min-height:92px;
	background:var(--mark-white) center right / contain no-repeat;
	filter:drop-shadow(0 1px 2px color-mix(in srgb,var(--paper-shadow) 12%,transparent)) drop-shadow(0 6px 10px color-mix(in srgb,var(--paper-shadow) 32%,transparent));
}
/* The tool's true colors show to the right of the hero's text alone.
   tool-hero.js measures where the text ends and writes it into
   --hero-text-end, and the layer of true colors fades in from a step past
   that point. Until the script has measured, the true colors stay hidden and
   the ground shows the shades the text reads on throughout. */
.tool-hero.icon-ground::after{
	--hero-true-from:calc(var(--hero-text-end, 100%) + var(--space-5));
	-webkit-mask-image:linear-gradient(90deg,transparent var(--hero-true-from),var(--mask-shown) calc(var(--hero-true-from) + var(--space-9)));
	mask-image:linear-gradient(90deg,transparent var(--hero-true-from),var(--mask-shown) calc(var(--hero-true-from) + var(--space-9)));
}

/* The category directory and the Channels page need only a short orientation
   before their own heading, so their heroes are compact text blocks. A
   category's hero sets its headline the same way, in its own color. */
.category-hero h1,.channel-index-hero h1,.category-detail-copy h1{
	margin:0;font-size:var(--text-2xl);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-tight);color:var(--band-ink);
}
.category-hero p,.channel-index-hero p{
	margin:var(--space-2) 0 0;max-width:58ch;font-size:var(--text-base);
	line-height:var(--leading-normal);color:var(--band-mute);
}

/* A category detail hero gives the category drawing equal weight with its
   short introduction without taking the height of the full Agent hero. */
/* It clips what it holds to its rounded corners, and so does the panel at the
   top of an Agent's page. */
.category-detail-hero,.panel-stack{overflow:hidden;border-radius:var(--r-card)}
.category-detail-hero .band-in{
	display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,360px);
	gap:var(--space-6);align-items:center;
}
.category-detail-hero.category-detail-hero-no-visual .band-in{grid-template-columns:1fr}
.category-detail-intro{display:flex;align-items:center;gap:var(--space-5);min-width:0}
/* The hero stands on its section's teaser ground, so its headline and the
   line under it are text on the CI gradient, and the PineSpark icon beside
   them is the white one. */
.category-detail-pinespark{
	width:80px;height:80px;flex:none;display:block;
	background:var(--mark-white) center / contain no-repeat;
}
.category-detail-copy{min-width:0}
.category-detail-copy p{
	margin:var(--space-2) 0 0;max-width:48ch;font-size:var(--text-base);
	line-height:var(--leading-normal);
}
/* The section teaser in the hero of a category page stands directly on the
   hero, which is its ground, so its box paints no ground of its own and has no
   border. */
.category-detail-visual{
	aspect-ratio:16/9;overflow:hidden;
	border-radius:var(--r-card);
}

/* A ground of its own, which the Channel page hero, the Channel tiles, the tool
   page hero and the hero of a single industry or role are painted with, the
   same in the light and the dark theme. The ground is painted from
   --hero-ground-paint, and a further layer from --hero-glow-paint lies over it.
   A Channel's and a tool's values come from the custom properties ChannelArt
   and ToolArt generated at startup from their icons, and the text and the ink
   each reach the contrast that small text needs against what lies under them,
   which GroundPalette checks. An industry's and a role's values come from
   .record-ground below.

   A Channel's ground is a medium gradient of the hue of the accent that covers
   more of the Channel's icon, with a lighter band, and its upper layer is the
   other accent glowing from a corner over the same share of the ground that it
   covers in the icon. The gradient's angle, the band's place and the glow's
   corner differ from Channel to Channel, and the gradient differs even between
   Channels that share their accents.

   A tool's ground is a sweep of its picture's colors from left to right, in
   the shades its text reads on, and its upper layer is the same sweep in the
   picture's true colors, which the tool hero shows to the right of its text
   alone. */
.icon-ground{
	--icon-ground:var(--hero-ground-paint);
	--icon-ink:var(--hero-ink);
	--icon-name:var(--hero-name);
	/* The ground is medium in the light and the dark theme and carries white
	   text, so everything on it takes the ink for a deep ground, whichever theme
	   the page is in. */
	--band-ink:var(--deep-ink);
	--band-mute:var(--deep-mute);
	--band-faint:var(--deep-faint);
	--band-acc:var(--deep-acc);
	--band-line:var(--deep-line);
	--band-wash:var(--deep-wash);
	--band-button-ink:var(--deep-button-ink);
	background:var(--icon-ground) border-box;
}
.icon-ground::after{
	content:"";position:absolute;inset:0;width:auto;height:auto;
	border-radius:inherit;pointer-events:none;background:var(--hero-glow-paint);
}
.icon-ground .channel-name{color:var(--ink-on-color)}
/* A light ground carries dark text: the ground's dark name color and dark ink
   take the place of the deep ground's light ones. */
.icon-ground-light{
	--band-ink:var(--icon-name);
	--band-mute:var(--icon-ink);
	--band-faint:var(--icon-ink);
	--band-acc:var(--icon-name);
}
/* The ground of the find-agents hero of a single industry or role, in the
   record's own hue, as palette.css describes it. The hero carries the class of
   its kind, which turns the ground's hue as far from the brand's as the
   record's place on its kind's arc does, and the variation
   StoreElement.recordGroundAttributes() writes: the gradient's angle, where its
   lighter band stands, and the corner and the core of its glow. The ground is
   painted through the values every ground of its own reads, so the hero sets
   its text like a Channel's: the headline in white and the line in the
   ground's ink. */
.industry-ground{--record-turn:calc(var(--industry-arc-start) + var(--mark-place) * var(--industry-arc));--record-keep:var(--industry-keep)}
.role-ground{--record-turn:calc(var(--role-arc-start) + var(--mark-place) * var(--role-arc));--record-keep:var(--role-keep)}
.record-ground{
	--hero-ground-paint:linear-gradient(var(--record-angle),
		oklch(from var(--record-ground-deep-source) l calc(c * var(--record-keep)) calc(h + var(--record-turn))),
		oklch(from var(--record-ground-light-source) l calc(c * var(--record-keep)) calc(h + var(--record-turn))) var(--record-band),
		oklch(from var(--record-ground-deeper-source) l calc(c * var(--record-keep)) calc(h + var(--record-turn))));
	--hero-glow-paint:radial-gradient(ellipse 75% 75% at var(--record-glow-at),var(--record-ground-glow) 0,var(--record-ground-glow) var(--record-glow-core),transparent 100%);
	--hero-ink:oklch(from var(--record-ground-ink-source) .97 calc(c * .2) calc(h + var(--record-turn)));
	--hero-name:var(--theme-h-000);
}
/* The record's own mark or avatar stands beside the headline in the ground's
   own hue, so a white ring sets it off the ground. */
.record-ground .find-hero-head > .industry-mark,.record-ground .find-hero-head > .role-avatar{box-shadow:0 0 0 2px var(--paper-frame)}

/* the grid of Channel tiles on the Channels page, and the bundle shelf */
.channel-grid,.shelf{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gutter)}
.channel-card{
	border-radius:var(--r-card);padding:var(--space-5);
	display:flex;flex-direction:column;gap:var(--space-3);
}
.channel-card-top{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}
/* the same size as a tool's picture in its frame on the tool wall */
.channel-card-top .channel-icon{width:44px;height:44px;border-radius:12px}
.channel-card-top .channel-icon svg{width:28px;height:28px;border-radius:4px}
/* A line of small reading text in the muted ink. It stands after the reading
   block's own paragraphs, so a paragraph of these inside a reading block keeps
   this margin. */
.channel-subheadline,.stack p,.step p,.card .desc,.hero-actions-note,.faq p{
	margin:0;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute);
}
.step p a{color:var(--ink);text-decoration:underline;text-underline-offset:.2em}

.channel-strip{
	display:grid;grid-template-columns:var(--space-7) minmax(0,1fr) var(--space-7);
	gap:var(--space-3);align-items:center;
}
/* A card rests with its start against the row's start, so each step of the
   arrows moves the row by a card and lands on the next resting place. The snap
   padding matches the row's own padding, so the leading card rests where the
   page initially draws it.

   Where an edge of the row cuts through a card, the strip script sets
   fade-start or fade-end, and the row fades out over a short stretch toward
   that edge. A mask reads only the opacity of what it names, so its colors are
   --mask-shown and transparent.

   The start and the end fade widths are registered as lengths, because a
   custom property animates only when the browser knows its type. The fade then
   grows and shrinks over the same short time whenever an edge starts or stops
   cutting a card, rather than appearing and vanishing abruptly. */
@property --fade-start{syntax:'<length>';inherits:false;initial-value:0px}
@property --fade-end{syntax:'<length>';inherits:false;initial-value:0px}
.channel-viewport{
	--fade-start:0px;--fade-end:0px;
	transition:--fade-start .3s ease,--fade-end .3s ease;
	overflow-x:auto;scroll-behavior:smooth;scrollbar-width:none;
	scroll-snap-type:x mandatory;padding:0 var(--space-2);scroll-padding-inline:var(--space-2);
	-webkit-mask-image:linear-gradient(to right,transparent,var(--mask-shown) var(--fade-start),var(--mask-shown) calc(100% - var(--fade-end)),transparent);
	mask-image:linear-gradient(to right,transparent,var(--mask-shown) var(--fade-start),var(--mask-shown) calc(100% - var(--fade-end)),transparent);
}
.fade-start .channel-viewport{--fade-start:var(--space-9)}
.fade-end .channel-viewport{--fade-end:var(--space-9)}
.channel-viewport::-webkit-scrollbar{display:none}
.channel-track{display:flex;gap:var(--gutter)}
.channel-track > .channel-card{
	flex:0 0 29%;scroll-snap-align:start;
}
/* The strip's last tile, which leads to every Channel. It takes the ground of
   the site's own banners rather than a Channel's, and its button is drawn the
   way the banners draw theirs. */
.channel-all{
	justify-content:center;align-items:center;
	background:var(--gradient) border-box;border:var(--hairline);box-shadow:var(--drop);
}
/* Every Channel tile, in the start page's row and on the Channels page, is
   painted with its Channel's own ground, the same as the Channel page hero, and
   the content is raised above the glow.
   Like the hero, the tile casts the drop shadow alone, without the surface's
   highlight along its top. */
.channel-card.icon-ground{position:relative;overflow:hidden;box-shadow:var(--drop)}
.channel-card.icon-ground.lift:hover{background:var(--icon-ground) border-box;box-shadow:var(--drop-lift)}
.channel-arrow{
	width:var(--space-7);height:var(--space-7);display:grid;place-items:center;
	border:1px solid var(--line-hi);border-radius:var(--r-pill);
	background:var(--surf-sink);color:var(--ink);cursor:pointer;
}
.channel-arrow:hover{background:var(--surf-hi)}

/* The Channel's hero writes its content straight into the band rather than
   into .band-in, so the recipe that raises a banner's content names its trail
   and its main block. */
.channel-hero,.channel-intro{border-radius:var(--r-card)}
.channel-hero .crumbs a:hover,.channel-hero .crumbs b{color:var(--band-ink)}
/* The label is outlined rather than filled, because a fill would lighten the
   ground under its text and lower the contrast the ink was picked for. */
.channel-hero .tag{color:var(--icon-ink);background:transparent;box-shadow:inset 0 0 0 1px currentColor}
.channel-hero-main{
	display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,360px);
	gap:var(--space-6);align-items:start;
}
.channel-hero-copy{min-width:0}
/* The masthead stands on the Channel's own ground, so it shows the drawing of
   the Channel's icon alone, with no frame around it and no tile under it. The
   drawing takes the box the framed icon takes elsewhere, and fills it. */
.channel-hero-copy .channel-mark{display:block;width:48px;height:48px;margin-bottom:var(--space-3)}
.channel-hero-copy .channel-mark svg{display:block;width:48px;height:48px}
.channel-hero h1{
	margin:var(--space-3) 0 0;font-size:var(--text-3xl);line-height:var(--leading-none);
	font-weight:var(--weight-semibold);letter-spacing:var(--tracking-tight);
}
.channel-promise{
	margin:var(--space-3) 0 0;max-width:62ch;font-size:var(--text-base);
	line-height:var(--leading-normal);color:var(--icon-ink);
}

/* A Channel's intro sits on one of the site's panels, set as reading text in a
   column narrow enough to read comfortably, with the phrases the Channel marks
   in bold standing out in the page's full ink. */
.channel-intro p{
	margin:0 0 var(--space-4);max-width:var(--content-narrow);
	font-size:var(--text-base);line-height:var(--leading-relaxed);color:var(--mute);
}
.channel-intro p:last-child{margin-bottom:0}
.channel-byline{
	display:grid;grid-template-columns:auto 1fr;gap:var(--space-3);
	padding:var(--space-4);border-radius:var(--r-card);background:var(--band-wash);border:1px solid var(--band-line);
}
.channel-byline .btn{grid-column:1 / -1;width:100%}

.channel-posts{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--gutter)}
.channel-post,.channel-resource-group{border-radius:var(--r-card);padding:var(--space-4)}
.channel-post time{font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--faint)}
.channel-post h3{margin:var(--space-2) 0 0;font-size:var(--text-lg);font-weight:var(--weight-medium)}
.channel-resources{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--gutter)}
.channel-resource-group h3{margin:var(--space-3) 0 0;font-size:var(--text-lg);font-weight:var(--weight-medium)}
.channel-resource-group article{margin-top:var(--space-4);padding-top:var(--space-3);border-top:var(--hairline)}
.channel-resource-group article b,.wall-tool b{font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium)}
.channel-resource-group article p,.explained-text{margin:var(--space-1) 0 0;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute)}
/* The stretch from the top of the hero down to the search box, holding the
   headlines. It stands at least this tall however few lines a headline takes.
   The headlines stand --headline-lift above its middle, so the space above a
   headline is that much shorter than an even split would give it, and the space
   below that much longer. The lift is a drawn measurement rather than a spacing
   step.

   The carousel's dots and pause button sit at the foot of this stretch, just
   above the search box, and its arrows sit against its side edges, level with the
   middle of the headline, so the arrows and the headline share the same middle. The
   controls are placed against the stretch rather than set in the flow, so they
   take none of the room the headlines stand in, and they stay where they are
   however many lines a headline takes.

   The search box adds no margin of its own on top, so this height is the whole
   distance between the hero's top padding and the search box. */
.hero-say{
	--headline-lift:15px;
	position:relative;min-height:324px;
	display:flex;flex-direction:column;justify-content:center;
}

/* The headline holds a step for each headline, and those are the carousel's steps.
   They stand in a shared grid cell, on top of each other, so the headline is as tall
   as the tallest of them and nothing below it moves when the step changes, and
   each is centered in that cell. Only the current step is shown. */
.hero-step{grid-area:1 / 1;align-self:center}
.hero-step:not([data-current]){visibility:hidden}

/* The canvas the particles are drawn on covers the viewport, so particles can be
   thrown well past the headline. It sits in the page's background, above the
   color wash and the grain and below the page itself, so every part of the page
   stays in front of the particles. It shares the grain's z-index and comes after
   the grain in the document, which is what puts it above the grain, so the grain
   never textures the particles and they match the real text they take over from.

   Over a light page the particles glow in the hero colors, which the canvas
   carries as the --particle-glow properties and which run across the screen.
   Over a dark page they glow in their own colors. Those properties are
   registered as colors, so the script reads each one as a color it can paint
   rather than as the mix it is written with. */
@property --particle-glow-1{syntax:'<color>';inherits:false;initial-value:transparent}
@property --particle-glow-2{syntax:'<color>';inherits:false;initial-value:transparent}
@property --particle-glow-3{syntax:'<color>';inherits:false;initial-value:transparent}
@property --particle-glow-4{syntax:'<color>';inherits:false;initial-value:transparent}
.particle-burst{
	z-index:1;
	--particle-glow-1:var(--ci-gradient-stop-1);--particle-glow-2:var(--ci-gradient-stop-2);
	--particle-glow-3:var(--hero-c);--particle-glow-4:var(--hero-d);
}

.hero-headline{
	/* A headline this large needs no leading of its own: at this size the font's
	   own ascent and descent already separate its lines. The design it comes
	   from set barely any leading for the same reason.

	   The headline's margin above is a spacing step less the lift, and its
	   margin below is the same step plus the lift. The stretch centers the headline
	   together with its margins, so the headline stands the lift above the
	   stretch's middle. Those margins are the gaps it keeps from the top and the
	   foot of the stretch when a long headline makes the stretch taller than its
	   minimum. */

	/* The headline sits in a wider column than the search box, because the
	   sentences of a headline need the room at this size to fall on a line each
	   rather than wrapping onto more lines. Balancing then splits them at the
	   period instead of filling the opening line to the edge, and a browser
	   without it fills greedily and still gets the same number of lines.

	   The column is as wide as the room the page leaves in a window of a chosen
	   reference width: that width less the page's side padding on each side at
	   that width. Wider windows keep that width. */
	display:grid;
	margin:calc(var(--space-5) - var(--headline-lift)) auto calc(var(--space-5) + var(--headline-lift));
	max-width:calc(840px - 2 * 28.56px);
	text-wrap:balance;
	font-size:var(--text-4xl);
	line-height:var(--leading-none);font-weight:var(--weight-semibold);
	letter-spacing:var(--tracking-tight);
	/* The headline's own text takes the hero's ink, which the dark theme makes
	   pure white so it stands out more than the page's ink does. */
	color:var(--hero-ink);
}
/* Where a browser cannot clip a background to text, the highlighted words stand
   in the gradient's first color. Anywhere else their text stays transparent,
   so the gradient the recipe for a gradient link fills them with shows through. */
@supports not ((background-clip:text) or (-webkit-background-clip:text)){
	.hero-step span{color:var(--ci-gradient-stop-1)}
}

/* The highlighted words are filled with the gradient, as the gradient section
   draws it for the headline. The headline writes the gradient out and flows it,
   so every word in the headline takes the same distance at the same moment,
   measured along its own box. The particle painter reads the gradient as it
   stands at the moment it paints, so the particles take over exactly the
   colors the words showed.

   The highlighted words also carry the hero's glow, which stays the same while
   the pattern moves. A filter is not painted by the particle painter, and the
   glow goes out with the words when the particles take over, so the
   particles' own glow replaces it. */
.hero-step > span:not(.hero-tools):not(:has(> .hero-words)){filter:var(--hero-glow)}

/* A column of words inside a headline, which the carousel turns word by word
   like a wheel. The words stand in a shared grid cell, so the column is as wide
   as its widest word and as tall as a line, and each word sits against the
   column's right edge. The carousel gives each word these values: --offset, how
   many places it stands from the headline's line, negative above it; --distance,
   the same without the sign; and --current, how fully it is the word on the
   line, from not at all to completely.

   The words stand on the face of a wheel. Its axis runs across the column,
   --wheel-radius behind the headline's line, and each place turns a word a further
   --wheel-step around that axis, so a word's height above or below the line and its
   depth behind it follow the wheel's curve together: a word a place further out
   sits closer to its inner neighbor than that neighbor sits to the line, stands
   further back, and is turned a further step. The step is small enough that a
   word further out still keeps a visible height rather than turning edge-on, and
   the radius puts a neighbor a little under a line away. The perspective is
   gentle, because a strong one pulls the far
   edge of a steeply turned word toward the vanishing point and flattens it to a
   sliver. It looks from the column's right edge, so turning, receding and shrinking
   keep every word against that edge.

   The word on the line is full size, filled with the gradient, with the hero's
   glow around it. A neighboring word is shrunk, slightly blurred,
   and in the ink color at the strength the carousel's arrows have, and a word
   further out is blurred and faded further. Every word passes
   smoothly between these as its numbers move: its ink covers the pattern as
   strongly as the word is not the one on the line. The column sits on the
   headline's baseline, and the words above and below it spill out of the line
   without moving anything around them.

   Each word paints the pattern itself, so neither the column nor the span around
   it paints one. A pattern the column painted would be clipped to where the words
   stand before they are moved, which is all of them on the headline's line, while
   a word's own background moves with the word. The glow is a drop shadow rather
   than a text shadow, because a text shadow is painted over a background clipped
   to the text and would tint the pattern inside the letters. Where a browser
   cannot clip a background to text, the word on the line stands in the
   gradient's first color. */
.hero-words{display:inline-grid;perspective:8em;perspective-origin:100% 50%}
.hero-step .hero-word{
	--wheel-radius:1.7em;
	--wheel-step:30deg;
	grid-area:1 / 1;justify-self:end;
	transform-origin:100% 50% calc(-1 * var(--wheel-radius));
	transform:
		rotateX(calc(var(--offset) * -1 * var(--wheel-step)))
		scale(calc(1 - .25 * min(var(--distance), 1)));
	filter:
		blur(calc(min(var(--distance), 2) * 1.5px))
		drop-shadow(0 0 calc(var(--current) * var(--hero-glow-near-size)) color-mix(in srgb, var(--hero-glow-near) calc(var(--current) * 100%), transparent))
		drop-shadow(0 0 calc(var(--current) * var(--hero-glow-far-size)) color-mix(in srgb, var(--hero-glow-far) calc(var(--current) * 100%), transparent));
	background-image:none;
	color:color-mix(in srgb, var(--ci-gradient-stop-1) calc(var(--current) * 100%), var(--hero-ink));
	opacity:calc(1 - .6 * min(var(--distance), 1) - .2 * max(var(--distance) - 1, 0));
}
@supports (background-clip:text) or (-webkit-background-clip:text){
	.hero-step .hero-word{
		background-image:var(--gradient);
		color:color-mix(in srgb, var(--hero-ink) calc((1 - var(--current)) * 100%), transparent);
	}
}
/* A column of words, the span around it, and the layer of circles paint no
   gradient of their own, as the rules for the words and for the circles state. */
.hero-step .hero-words,
.hero-step span:has(> .hero-words),.hero-step .hero-tools{background-image:none}

/* A headline's circles, which stand in rows above and below the headline's text,
   on columns every row shares, and show the integrations of the headline's queue.
   The layer covers the stretch the headlines stand in, and the carousel places each
   circle in it by its middle: --x and --y say where the middle is, and --shown how
   strongly the circle shows. The layer's row gap is the clearance the carousel keeps
   between a circle and the text, the controls, the arrows and the stretch's edges,
   and between a circle and the card it opens; its column gap is the space between
   neighboring circles in the grid. A circle the grid has no cell for is hidden.

   Every circle is the same size, and every one is one of the site's raised
   surfaces, with its icon in the accent. Each circle is a button that opens a card,
   so it takes the pointer, but only while it shows fully and holds still: the
   carousel marks such a circle data-settled, and a circle fading in or out lets the
   pointer through. The circle whose card is open wears the accent as its edge. The
   layer itself lets the pointer through everywhere else. The circles sit inside the
   headline, so they set their own color and background over the gradient the
   headline's spans are filled with, which is clipped to text. */
.hero-tools{position:absolute;inset:0;pointer-events:none;row-gap:var(--space-4);column-gap:var(--space-8)}
.hero-step .hero-tool{
	position:absolute;left:0;top:0;
	width:var(--space-8);height:var(--space-8);
	display:grid;place-items:center;
	padding:0;font:inherit;cursor:pointer;
	border:var(--hairline);border-radius:var(--r-pill);
	background:var(--surf-hi);
	box-shadow:var(--edge),var(--drop);
	color:var(--acc);--icon-stroke:currentColor;
	transform:translate(calc(var(--x, 0px) - 50%), calc(var(--y, 0px) - 50%));
	opacity:var(--shown, 0);
	pointer-events:none;
}
.hero-step .hero-tool[data-settled]{pointer-events:auto}
.hero-step .hero-tool[aria-expanded="true"]{border-color:var(--acc)}
.hero-step .hero-tool[hidden]{display:none}

/* The card a circle opens. It names the circle's integration, says in a short sentence
   what the Agents do with it, and offers those Agents. The carousel places it by its
   top left corner with --x and --y: centered across its circle, kept inside the
   stretch, and on the side of the circle that faces the headline's text, so it stays
   inside the stretch too. It is one of the site's raised surfaces, and it stands in
   front of the headline, the controls and the arrows.

   The button spans the card's width at its foot, so the card's corners are
   concentric with the button's: the button's full-round radius, plus the padding
   around it, plus the card's hairline. */
.hero-tool-card{
	position:absolute;left:0;top:0;z-index:2;
	width:calc(2 * var(--space-12));max-width:100%;
	display:flex;flex-direction:column;gap:var(--space-2);
	padding:var(--space-4);text-align:left;
	border:var(--hairline);border-radius:calc(var(--space-7) / 2 + var(--space-4) + 1px);
	background:var(--surf-hi);
	box-shadow:var(--edge),var(--drop-lift);
	-webkit-backdrop-filter:var(--glass);
	backdrop-filter:var(--glass);
	transform:translate(var(--x, 0px), var(--y, 0px));
}
.hero-tool-card[hidden]{display:none}
.hero-tool-card-name{
	padding:0 var(--space-2);
	font-size:var(--text-base);line-height:var(--leading-normal);font-weight:var(--weight-semibold);
	color:var(--ink);
}
.hero-tool-card-text{
	margin:0;padding:0 var(--space-2);
	font-size:var(--text-sm);line-height:var(--leading-sm);
	color:var(--mute);
}
.hero-tool-card-agents{margin-top:var(--space-2)}

/* The search box is a rounded box holding a rounded button, so the box and the
   button have to be concentric: the box's curve is the button's curve plus the
   distance between them, or the button sits in a corner that is the wrong shape.

   The button is fully rounded, so its radius follows from its height. The box
   leaves the same gap between the button and its top, bottom and right edges,
   so the box is the button's height plus that gap above and below, and its
   radius is the button's radius plus the gap. The box's hairline border is
   part of that gap, and the padding inside the border makes up the rest.

   The box states its height rather than taking it from the field, so a browser
   that draws the field taller cannot push the box's curve off the button's.

   The catalog's search and the field the form to modify an Agent takes its
   change in are the same box, a field and its button in a shared rounded box. */
.finder,.catalog-search,.modify-field{
	display:flex;align-items:center;gap:var(--space-2);
	height:calc(var(--space-7) + 2 * var(--space-2));
	border-radius:calc(var(--space-7) / 2 + var(--space-2));
	padding:calc(var(--space-2) - 1px) calc(var(--space-2) - 1px) calc(var(--space-2) - 1px) var(--space-4);
	background:var(--input-ground);
}
.finder{text-align:left;cursor:text}
/* the icon and the field share a row, and a click anywhere on them lands in
   the field, because they sit inside a label */
.finder-field,.catalog-search-field,.modify-field-input{display:flex;align-items:center;gap:var(--space-2);flex:1;min-width:0}
.finder input,.catalog-search input,.modify-field input{
	flex:1;min-width:0;background:transparent;color:var(--ink);
	font:inherit;font-size:var(--text-sm);line-height:var(--leading-sm);
}
.finder input{min-height:var(--space-7);padding:var(--space-2) 0;border:1px solid transparent}
/* the quiet parts of a field: its icon and its placeholder */
.finder .icon,.finder input::placeholder,.catalog-search input::placeholder,.modify-field input::placeholder,
.login-input::placeholder{color:var(--faint)}
.finder input:focus,.catalog-search input:focus,.modify-field input:focus{outline:0}
.finder:focus-within,.catalog-search:focus-within,.modify-field:focus-within{border-color:var(--line-hi)}

.tries{display:flex;flex-wrap:wrap;gap:var(--space-2);justify-content:center;max-width:720px;margin:0 auto}
.tries span{font-size:var(--text-xs);color:var(--faint);padding:var(--space-1) 0;margin-right:2px}
.try{
	font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute);border:var(--hairline);
	background:var(--surf-sink);border-radius:var(--r-pill);
	padding:var(--space-1) var(--space-3);cursor:pointer;
	transition:color var(--quick),border-color var(--quick);
}
.try:hover{color:var(--ink);border-color:var(--line-hi)}

/* The hero is a carousel of steps, and these are the controls that move between
   them: an arrow at each side edge of the stretch the headlines stand in, level
   with the headline's middle, and a row just above the search box holding a dot
   for each step beside a button that pauses and resumes the steps advancing.

   An arrow is a bare chevron with no circle around it. The chevron itself stays
   faint until the pointer or the keyboard reaches its button, so it never
   competes with the headline between the arrows. The button stays square at a
   comfortable size, so the target a finger or a pointer has to hit is larger
   than the chevron drawn in it. */
.carousel-arrow{
	position:absolute;top:calc(50% - var(--headline-lift));z-index:1;transform:translateY(-50%);
	width:var(--space-8);height:var(--space-8);
	display:grid;place-items:center;
	padding:0;border:0;background:transparent;color:var(--ink);cursor:pointer;
}
.carousel-arrow .icon{width:32px;height:32px;opacity:.4;transition:opacity var(--quick)}
.carousel-arrow:hover .icon,.carousel-arrow:focus-visible .icon{opacity:1}
/* each arrow stands against its side and faces it, as the recipe for a
   chevron states */
.carousel-prev{left:0}
.carousel-next{right:0}

/* The row of dots and the pause button, placed against the foot of the stretch
   that holds the headline. It sits above the search box by the same gap the
   example chores keep below it.

   The row is exactly as wide as the dots and the button, centered, so hovering it
   means hovering the controls rather than an empty stretch on either side of them.

   The dots and the pause button stand as tall as a line of --text-xs text with
   the finest spacing step of padding above and below it and a hairline on each
   side. */
.carousel-controls{
	--control-height:calc(var(--text-xs) * var(--leading-normal) + 2 * var(--space-1) + 2px);
	position:absolute;left:50%;bottom:var(--space-3);transform:translateX(-50%);width:max-content;
	display:flex;align-items:center;gap:var(--space-2);
}

/* At rest the dots and the pause symbol stand on their own, with no capsule and
   no circle around them, so they draw as little attention as they can. Hovering
   the row, or reaching one of its controls with the keyboard, fades the capsule
   and the circle in, which is when a reader is about to use them. */
.carousel-dots,.carousel-play{
	border:1px solid transparent;background-color:transparent;
	transition:border-color .2s ease,background-color .2s ease;
}
.carousel-controls:hover .carousel-dots,.carousel-controls:hover .carousel-play,
.carousel-controls:has(:focus-visible) .carousel-dots,.carousel-controls:has(:focus-visible) .carousel-play{
	border-color:var(--line);background-color:var(--surf-sink);
}

/* The dots sit in a capsule, the way a phone's home screen shows its pages. Each
   dot's button fills the capsule's height and is as wide as the least room a
   touch target should have, so the buttons' centers sit that far apart. The dot
   drawn inside each button is a drawn box far smaller than the button.

   A dot that is not the current step is faded, and it comes up to full strength
   under the pointer and when it becomes the current step. */
.carousel-dots{
	display:flex;height:var(--control-height);padding:0 var(--space-1);
	border-radius:var(--r-pill);
}
.carousel-dot{
	width:24px;padding:0;
	display:grid;place-items:center;
	border:0;border-radius:var(--r-pill);background:transparent;cursor:pointer;
}
.carousel-dot::before{
	content:"";width:6px;height:6px;border-radius:var(--r-pill);
	background:var(--faint);opacity:.6;
	transition:background-color var(--quick),opacity var(--quick);
}
.carousel-dot:hover::before{background:var(--mute);opacity:1}
.carousel-dot[aria-current="true"]::before{background:var(--ink);opacity:1}

.carousel-play{
	width:var(--control-height);height:var(--control-height);
	padding:0;display:grid;place-items:center;
	border-radius:var(--r-pill);color:var(--ink);cursor:pointer;
}
/* the circle under the pointer is raised above the faded-in capsule beside it */
.carousel-controls .carousel-play:hover{background-color:var(--surf-hi)}
.carousel-play .icon{width:12px;height:12px}
/* The button draws the symbol for what a press does: pause while the reader has
   not paused the steps, and play while they have. It follows the reader's own
   pause alone, because that is the only hold a press of the button changes. */
.carousel-icon-play{display:none}
.hero[data-paused-by~="reader"] .carousel-icon-pause{display:none}
.hero[data-paused-by~="reader"] .carousel-icon-play{display:block}

/* The ways to find Agents, which the AgentsBy element draws right after the
   hero. A list names the ways on the left, at a side panel's width, and a view
   on the right shows a section for each way, one at a time.

   The panel holding the list and the view is as tall as the taller of the two,
   and never taller than half the window. The sections share the single cell of
   the view's grid, so the cell is as tall as the tallest of them, and each
   section is moved down from the cell by a cell's height for every way ahead of
   it, so the sections stand one under the next like the sections of a page. A
   section taller than the view is cut off at the view's foot. The cell is
   exactly as wide as the view, so a band's row, which is as wide as all its
   records together, widens no section.

   As written here, the element stands wherever PineScroll does not move the
   page, as the rule further down states. The view then scrolls through the
   sections on its own, a band scrolls sideways on its own, and the list shows
   no panel behind its ways.

   The panel keeps a step of room under the bar while the page holds still, as
   its scroll margin names. */
.agents-by-panel{
	display:grid;grid-template-columns:var(--side-panel-width) minmax(0,1fr);
	grid-template-rows:minmax(0,1fr);gap:var(--space-5);max-height:50vh;
	scroll-margin-top:var(--space-4);
}
.agents-by-master{border-radius:var(--r-card);padding:var(--space-1)}
/* Every way's entry in the list is as tall as the next, and the entries stand
   the same gap apart. The panel behind them is as tall as an entry, so it lands
   exactly on each entry as it moves down the list by an entry and a gap at a
   time. The entry's height is stated, the way a control's is, so every entry
   rounds to the same whole number of pixels. */
.agents-by-ways{
	--way-height:var(--space-8);
	--way-gap:var(--space-1);
	position:relative;
}
.agents-by-list{position:relative;display:grid;gap:var(--way-gap)}
.agents-by-way{height:var(--way-height)}
/* A way's entry is a link to its way's section, and the pointer turns into a
   hand over it. Nothing else about the entry changes under the pointer, because
   the panel behind the list is what marks a way. */
.agents-by-way a{
	display:flex;align-items:center;gap:var(--space-3);height:100%;
	padding:0 var(--space-3);border-radius:8px;cursor:pointer;
	font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);color:var(--ink);
}
.agents-by-way b{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:inherit}
/* a way's drawing, a drawn box the size a category's sign draws its drawing at */
.agents-by-way .icon{width:17px;height:17px}
/* The panel behind the list, painted the way a side panel paints the entry that
   is picked. It stands at the top of the list, behind the first way, and it
   shows only where the element holds the page still. */
.agents-by-highlight{
	display:none;position:absolute;top:0;left:0;right:0;height:var(--way-height);
	border-radius:8px;background:var(--acc-soft);
}
.agents-by-view{border-radius:var(--r-card);overflow-y:auto}
.agents-by-details{display:grid;grid-template-columns:minmax(0,1fr);height:100%}
/* A way's section: its heading, set as a section's heading is, over its
   records, moved down by its place among the ways. A hairline stands between
   neighboring sections. */
.agents-by-detail{
	grid-area:1 / 1;min-width:0;translate:0 calc(var(--way) * 100%);
	overflow:clip;padding:var(--space-5);
}
/* The records of a way whose kind stands in a band: one row of the store's own
   items, each as wide as its kind names, which the reader scrolls sideways
   wherever PineScroll does not move the page. An industry's tile uses the room the
   band gives it and stands taller than a tile in a grid, and its height is a
   drawn box, so it is in pixels. It is wide enough that the summary under it
   takes a few lines. A category stands as its small entry in its vertical
   variant, its drawing over its name and its line, so it takes less room across
   than an industry's tile. The band keeps a step of room above its items, so a
   tile that rises under the pointer is not cut off. */
.agents-by-band{overflow-x:auto;overscroll-behavior-x:contain;padding-top:var(--space-1)}
.agents-by-band-row{display:flex;gap:var(--space-3);width:max-content}
.agents-by-band-row > li{flex:none}
.agents-by-band-industry li{width:17rem}
.agents-by-band-industry .industry-mark-lg{min-height:128px}
.agents-by-band-category li{width:14rem}
/* The records of a way whose kind stands in rows. A role's entries stand in as
   many columns as fit at their narrowest readable width, straight on the view
   rather than on a panel of their own. A tool's rows stand as many to a row as
   the grid's columns name, each its picture beside its name and how many Agents
   it has, and the whole of it takes the sunk ground under the pointer, as a row
   of a side panel does. A name too long for its column ends in an ellipsis. */
.agents-by-grid{display:grid}
.agents-by-roles{grid-template-columns:repeat(auto-fill,minmax(min(17rem,100%),1fr));column-gap:var(--space-6)}
.agents-by-tools{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-1) var(--space-4)}
.agents-by-entry{
	display:flex;align-items:center;gap:var(--space-2);min-width:0;
	padding:var(--space-2);border-radius:8px;
	font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute);
	transition:color var(--quick),background-color var(--quick);
}
.agents-by-entry b{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:var(--weight-medium)}
.agents-by-entry .tally{flex:none;white-space:nowrap}

/* Where start.js has handed the page's scroll to PineScroll, as the rule at
   .page states, the page holds still while the element's view shows the ways.
   PineScroll then moves the view, its bands and the panel behind the list, and
   the view and the bands clip what they hold rather than scrolling it. */
html[data-pine-scroll] .agents-by-view,html[data-pine-scroll] .agents-by-band{overflow:clip}
html[data-pine-scroll] .agents-by-highlight{display:block}
/* The page scrolls slowly past the How it works band until the band stands a
   step under the bar, as start.js reads this margin. */
.HowItWorksBand .band{scroll-margin-top:var(--space-4)}
/* While PineScroll moves the page, the How it works band stands in gray, with
   its ground and the glow on it partly see-through, and its colors come in
   over the first part of the page's way on from the ways to where the band
   stands a step under the bar, as start.js raises --how-it-works-color from 0
   to 1. The gray band keeps --how-it-works-gray-saturation of the ground's
   saturation, which is none. Its ground is as opaque as
   --how-it-works-gray-ground names, and brightened by the factor
   --how-it-works-gray-brightness names, so the see-through gray does not read
   as dark against the page. All of them return to the ground's own as the
   color comes in, so the band ends in the gradient's own colors.

   The band paints its ground on a layer of its own rather than as its
   background, so the see-through ground leaves the heading and the steps
   opaque. The band clips that layer to the inside of its hairline, so the layer
   draws the hairline itself, and its radius is the band's less the hairline, so
   it stays concentric with the band. The layer carries the band's flowing
   ground, which it takes from the band. */
html[data-pine-scroll] .HowItWorksBand .band{
	--how-it-works-gray-saturation:0;
	--how-it-works-gray-ground:.4;
	--how-it-works-gray-brightness:1.6;
	--how-it-works-ground:calc(var(--how-it-works-gray-ground) + (1 - var(--how-it-works-gray-ground)) * var(--how-it-works-color, 0));
	background:none;border-color:transparent;
	filter:saturate(calc(var(--how-it-works-gray-saturation) + (1 - var(--how-it-works-gray-saturation)) * var(--how-it-works-color, 0)));
}
html[data-pine-scroll] .HowItWorksBand .band::before{
	content:"";position:absolute;inset:0;pointer-events:none;
	border-radius:calc(var(--r-card) - 1px);
	background:var(--gradient) border-box;box-shadow:inset 0 0 0 1px var(--line);
	opacity:var(--how-it-works-ground);
	filter:brightness(calc(var(--how-it-works-gray-brightness) + (1 - var(--how-it-works-gray-brightness)) * var(--how-it-works-color, 0)));
}
html[data-pine-scroll] .HowItWorksBand .band::after{opacity:var(--how-it-works-ground)}

/* The signs: the category signs of the category tiles, and the sign of every
   job on the Tasks page. */
.jobs{display:grid;grid-template-columns:repeat(5,1fr);gap:var(--gutter)}
.job{border-radius:var(--r-tile);padding:var(--space-4) var(--space-3) var(--space-3);display:block}
.job .icon{width:17px;height:17px;color:var(--acc);margin-bottom:var(--space-4)}
.job b{display:block;font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);letter-spacing:var(--tracking-snug)}
.job span{
	display:block;font-size:var(--text-xs);line-height:var(--leading-normal);
	color:var(--mute);margin-top:var(--space-1);
}
.job em{
	display:block;font-style:normal;font-size:var(--text-xs);
	letter-spacing:var(--tracking-normal);color:var(--faint);
	margin-top:var(--space-2);
}
.jobs-all{
	display:flex;align-items:center;justify-content:flex-start;
	padding:var(--space-4) var(--space-3) var(--space-3);
}

/* the directory: an illustrated tile, then the named jobs beneath it. This
   section carries no glass panel, so it reads as an index rather than as
   another row of cards. */
.dir{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-6) var(--gutter)}
/* The preview of the directory sets its categories narrower, with more to a
   row than the directory on its own page, as many as its columns name. The
   narrower widths fall back to the directory's own columns. */
.dir-preview{grid-template-columns:repeat(4,1fr)}
.dircard{display:flex;flex-direction:column}
.dirtop{display:block}
/* The teaser ground: the gradient as a section teaser draws it, which the
   gradient section describes, and which a section's boxes are painted with. A
   section teaser draws no ground of its own, so every tile it is shown in
   carries the teaser ground underneath it, and so does the hero of the
   section's own page, whose teaser stands on the hero itself, as
   .category-detail-visual states.

   A box carries the teaser ground by its class teaser-ground, and carries its
   own variation of the gradient in its style attribute. Both come from
   StoreElement.teaserGroundAttributes, which draws the variation from the
   section's key: the gradient's angle, where its second color stands, how
   large it is drawn compared with the box, and where it stands across and down
   the box. A gradient drawn larger than the box shows the part of it the
   position picks. So every box of a section stands on the same ground, and
   neighboring sections stand on different ones. The ground is laid out over
   the whole box, border included, for the reason the banner states. */
.teaser-ground{
	background-image:var(--gradient);
	background-size:var(--teaser-scale) var(--teaser-scale);
	background-position:var(--teaser-x) var(--teaser-y);
	background-repeat:no-repeat;background-origin:border-box;background-clip:border-box;
}
.dirtile{
	aspect-ratio:16/9;border-radius:var(--r-card);overflow:hidden;position:relative;
	border:var(--hairline);
}
.dirhead{display:flex;align-items:baseline;gap:var(--space-2);margin:var(--space-4) 0 var(--space-2)}

/* A column of small category entries, as the CategoryList element draws it,
   such as the one the directory's preview holds in the place of another card:
   each a small picture of a category beside its name, and last, where the column
   has one, a link that opens every category, its words starting where the
   pictures start. The entries share the column's height evenly, so beside the
   cards they share the height of the cards. Each picture takes a fixed share of
   the entry's width, small enough that every entry fits beside a full card. */
.category-list{display:grid;grid-auto-rows:1fr;gap:var(--space-3)}
.category-list .dirmini{height:100%}
.dirmini{display:flex;align-items:center;gap:var(--space-3);min-width:0}
.dirmini-tile{
	flex:none;width:36%;aspect-ratio:16/9;border-radius:var(--r-tile);overflow:hidden;position:relative;
	border:var(--hairline);
}
/* A small entry's name, and "Show all tools" after the wall of tools, which is
   set exactly as the preview's "Show all Categories" is. */
.dirmini-name,.wall-all{
	font-size:var(--text-base);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);
}
.dirmini-name{margin:0;min-width:0}
/* A small entry that carries a line under its name, such as what its category
   covers, stacks the name and the line beside its picture, the way a tool's
   panel on the wall of tools stacks its name and its count. */
.dirmini-copy,.wall-tool-copy{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}
.dirmini-line{font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute)}
/* A small entry in its vertical variant stands its drawing over its name and
   its line, each as wide as the entry. The drawing stands as far above the
   capitals of the name as the name's baseline stands above the capitals of the
   line. With the store's font, and the name's and the line's sizes and line
   heights, that takes a gap of half a step more than --space-2. */
.dirmini-vertical{flex-direction:column;align-items:stretch;gap:calc(var(--space-2) + var(--space-1) / 2)}
.dirmini-vertical .dirmini-tile{width:100%}

/* a job to each row, ruled, with the count held to the right edge */
.shelves a{
	display:flex;align-items:center;gap:var(--space-2);
	padding:var(--space-2) var(--space-2);margin:0 calc(var(--space-2) * -1);border-radius:8px;
	font-size:var(--text-sm);line-height:var(--leading-sm);
	transition:color var(--quick),background-color var(--quick);
}
/* The job links take the muted ink and a sunk ground under the pointer. The
   link to all of a group's Agents is a gradient link, which sets its own look. */
.shelves li:not(.all) > a{color:var(--mute)}
.shelves .new{margin-left:0}
.shelves a::after{
	content:"›";flex:none;width:6px;line-height:var(--leading-none);
	font-size:var(--text-base);color:var(--acc);
	opacity:0;transform:translateX(-3px);transition:opacity var(--quick),transform var(--quick);
}
.shelves a:hover::after{opacity:1;transform:none}
.shelves .all a::after{opacity:1;transform:none;color:inherit}

/* the bundle shelf, whose grid the Channel grid's rule sets */
.stack{
	border-radius:var(--r-card);padding:var(--space-4);
	display:flex;flex-direction:column;gap:var(--space-3);
}
.stack .flag{
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);color:var(--acc);
}
.stack-foot{
	display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);
	border-top:var(--hairline);padding-top:var(--space-3);
}
.stack-foot b{
	font-size:var(--text-xs);font-weight:var(--weight-medium);
	color:var(--acc);letter-spacing:var(--tracking-normal);
}
.stack-foot em{
	font-style:normal;font-size:var(--text-xs);color:var(--faint);
	letter-spacing:var(--tracking-normal);
}

/* The steps on the banner. The row takes as many columns as the steps it is
   given, because a track with no step in it collapses, so fewer steps fill the
   width the same way more steps do. The minimum track width is the narrowest a
   step reads at, and it is a layout measurement rather than a step of the
   scale. */
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--space-5) var(--gutter)}
/* Each step is one of the site's panels, the same surface and corners as the
   category tiles, so its words stand on the page's own surface rather than on
   the banner's colors. Everything inside it therefore takes the page's ink,
   not the banner's. */
.step{border-radius:var(--r-tile);padding:var(--space-4)}
/* The drawing and the number share a row, so the number costs the step no
   height of its own. The row carries the space under them. */
.step-top{display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-4)}
/* The number and the drawing take the step's title color, and the number is set
   the way the title is, so the number, the drawing and the title read together
   as a heading. */
.step em{
	font-style:normal;font-size:var(--text-base);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);color:var(--ink);
}
.step .art{
	width:46px;height:46px;border-radius:13px;display:grid;place-items:center;flex:none;
	border:var(--hairline);background:var(--surf-sink);color:var(--ink);
	--icon-stroke:currentColor;
}
.step .art .icon{width:22px;height:22px}
.step b{
	display:block;font-size:var(--text-base);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);margin-bottom:var(--space-1);color:var(--ink);
}
/* The list and the row of tool pictures a step may carry under its title, set
   in the step's own sentence type. */
.step-list{
	margin:0;padding-left:var(--space-4);
	font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute);
}
.step-list li + li{margin-top:var(--space-2)}
.step .step-tools{margin-top:var(--space-3)}
/* A step without a number carries its title beside its drawing, where the
   number stands otherwise, so the title adds no space of its own. */
.step-top > b{margin:0}

/* The benefits section uses the theme's benefit colors while its body copy
   keeps the page's reading ink. */
.benefits .sec-tag{border-top-color:var(--benefit-line)}
.benefits .step b{color:var(--benefit-ink)}
.benefits .step{border-color:var(--benefit-line)}
.benefits .step .art{background:var(--benefit-icon-ground);border-color:var(--benefit-line);color:var(--benefit-ink)}

/* On an Agent's page the band of how to start the Agent stands in the reading
   column, and its steps stand one above the other at every width, each as wide
   as the band, so a step with a long list takes the height it needs without
   stretching the steps beside it.

   The band is set tighter than the start page's: the same smaller padding on
   every side, its heading on a line as tall as its type, so the heading's top
   stands as far from the band's edge as the heading's left does, and less
   space under the heading and under each step's drawing. */
.agent-start .band{padding:var(--space-5)}
.agent-start .band-head{margin-bottom:var(--space-4)}
.agent-start .band-head h2{font-size:var(--text-xl);line-height:var(--leading-none)}
.agent-start .step-top{margin-bottom:var(--space-3)}
.agent-start .steps{grid-template-columns:minmax(0,1fr);gap:var(--space-3)}

/* A grid of cards that walk through no steps and come six to a section, as
   CardGrid draws them, stands in rows of three, so its rows come out even. */
.steps.steps-three{grid-template-columns:repeat(3,minmax(0,1fr))}

/* THE INTRO HERO
   The hero that opens a page explaining PineSpark, as IntroHero draws it: its
   headline, its line, and its buttons or its box to describe an Agent in, in a
   centered column on the CI gradient with generous room above and below. Its
   text is text on the gradient, as every banner's is. A quiet button takes the
   banner's ink and outline, so it reads on the gradient beside the solid one. */
.intro-hero{padding:clamp(var(--space-7),6vw,var(--space-10)) var(--pad)}
.intro-hero .band-in{
	display:flex;flex-direction:column;align-items:center;gap:var(--space-4);
	max-width:760px;margin:0 auto;text-align:center;
}
.intro-hero h1{
	margin:0;font-size:var(--text-4xl);line-height:var(--leading-none);
	font-weight:var(--weight-semibold);letter-spacing:var(--tracking-tight);text-wrap:balance;
}
.intro-hero h1 .keep-together{white-space:nowrap}
.intro-hero-note{margin:0;max-width:58ch;font-size:var(--text-lg);line-height:var(--leading-normal)}
.intro-hero-actions{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-3);margin-top:var(--space-2)}
.intro-hero .btn-quiet{color:var(--band-ink);border-color:var(--band-line);text-shadow:none}
/* The box to describe an Agent in: the text area over its button, on the
   ground every field stands on, as wide as the hero's column. Its words stand
   on the field rather than on the gradient, so they carry no shadow. The
   examples under it are pills in the colors of the labels on the gradient. */
.prompt-box{
	display:flex;flex-direction:column;gap:var(--space-3);width:100%;
	margin-top:var(--space-2);padding:var(--space-4);
	border-radius:var(--r-card);background:var(--input-ground);
	text-align:left;text-shadow:none;
}
.prompt-box:focus-within{border-color:var(--line-hi)}
.prompt-box textarea{
	width:100%;min-height:calc(3 * var(--text-base) * var(--leading-normal));resize:vertical;
	padding:0;border:0;outline:0;background:transparent;color:var(--ink);
	font:inherit;font-size:var(--text-base);line-height:var(--leading-normal);
}
.prompt-box textarea::placeholder{color:var(--faint)}
.prompt-box .btn{align-self:flex-end}
.intro-hero .tries span{color:var(--ink-on-gradient)}
.intro-hero .try{background:var(--label-on-gradient);color:var(--ink-on-gradient);border-color:transparent;text-shadow:none}

/* THE GLOW BEHIND AN INPUT
   The moving glow behind an input a page puts forward, as
   StoreElement.inputGlow() writes it: the box to describe an Agent in on the
   Create Agents page and, subtler, the search box on the start page. The glow
   and the input stand on a stage. The input is positioned and follows the
   glow in the markup, so it is painted over the glow, and it sets no stacking
   level of its own, so the start page's search box keeps the level it takes
   while its field holds the focus.

   The glow is two layers of the brand's colors turning around the input at
   different speeds and in opposite directions, blurred into a soft light,
   while the second layer slowly swells and shrinks, so the glow keeps
   changing. It keeps running whatever holds the focus. The turn is a
   registered angle, so it changes gradually. Each layer's corners follow the
   input's, which the stage names in --glow-radius. A subtle glow is fainter,
   reaches less far past the input and is blurred less. A reader who asks for
   reduced motion sees the glow standing still. The blurs and the stretch the
   glow reaches past the input are drawn sizes, in pixels. */
@property --input-glow-turn{syntax:'<angle>';inherits:false;initial-value:0deg}
.glow-stage{position:relative;--glow-radius:var(--r-card)}
.glow-stage > :not(.input-glow){position:relative}
.input-glow{
	position:absolute;inset:-6px;z-index:0;pointer-events:none;
	border-radius:var(--glow-radius);
}
.input-glow i{
	position:absolute;inset:0;border-radius:inherit;
	background:conic-gradient(from var(--input-glow-turn),var(--input-glow-1),var(--input-glow-2),var(--input-glow-3),var(--input-glow-4),var(--input-glow-1));
	filter:blur(24px);
	animation:input-glow-turn 9s linear infinite;
}
.input-glow i + i{
	filter:blur(48px);opacity:.7;
	animation:input-glow-turn 14s linear infinite reverse,input-glow-swell 5s ease-in-out infinite alternate;
}
.input-glow-subtle{inset:-3px;opacity:.55}
.input-glow-subtle i{filter:blur(16px)}
.input-glow-subtle i + i{filter:blur(32px)}
/* The start page's search box stands on its stage in the box's place, and the
   glow's corners follow the box's full round. */
.hero .glow-stage{
	max-width:720px;margin:0 auto var(--space-3);
	--glow-radius:calc(var(--space-7) / 2 + var(--space-2));
}
@keyframes input-glow-turn{to{--input-glow-turn:360deg}}
@keyframes input-glow-swell{from{scale:.94}to{scale:1.06}}
@media (prefers-reduced-motion:reduce){
	.input-glow i,.input-glow i + i{animation:none}
}

/* THE QUIET HERO
   A quiet hero, as IntroHero draws it on the How it works page and the
   Create Agents page, lays a veil over the CI gradient, deep on the dark page
   and pale on the light one, as palette.css sets it, so the hero is quieter
   and its text still reads. Its text, and the PineSpark mark a hero may show,
   stand over the veil. */
.intro-hero-quiet::before{content:"";position:absolute;inset:0;pointer-events:none;background:var(--hero-veil)}
.intro-hero-quiet .band-in,.intro-hero-mark .band-in{position:relative;z-index:1}

/* THE PINESPARK MARK IN LIGHT
   A hero that shows the PineSpark mark, as IntroHero draws it, holds a glow
   behind its text, in the turning colors of the glow behind an input and
   vaguely in the shape of the mark. The white icon, --mark-white, at its own
   outline's thickness, is the mask of every layer, so the turning colors
   start out in the mark's shape. The layers are the glow behind an input's,
   blurred far enough that no edge of the mark stays sharp: a wide glow that
   turns one way and slowly swells and shrinks, and a closer glow that turns
   the other way and keeps the mark's shape faintly. Each layer's blur stands
   on a layer around it, because a blur on the masked layer itself would be
   cut back to the mark's edge. The glow shines at --mark-light-strength, so
   the text over it reads.

   The icon's drawing is square with the mark at its middle. The drawing is
   sized so the mark stands taller than the hero and centered across it, with
   its point near the hero's top, its widest corners inside the hero, and its
   base cut off by the hero's edge. A reader who asks for reduced motion sees
   the colors standing still. The blurs are drawn sizes, in pixels. */
.mark-light{
	--mark-light-strength:.7;
	position:absolute;top:-35%;left:50%;height:196%;aspect-ratio:1;translate:-50% 0;
	pointer-events:none;opacity:var(--mark-light-strength);
}
.mark-light > span,.mark-light i{position:absolute;inset:0}
.mark-light i{
	background:conic-gradient(from var(--input-glow-turn),var(--input-glow-1),var(--input-glow-2),var(--input-glow-3),var(--input-glow-4),var(--input-glow-1));
	-webkit-mask:var(--mark-white) center / 100% 100% no-repeat;
	mask:var(--mark-white) center / 100% 100% no-repeat;
	animation:input-glow-turn 9s linear infinite;
}
.mark-light-glow-wide{filter:blur(72px);opacity:.7;animation:input-glow-swell 5s ease-in-out infinite alternate}
.mark-light-glow-wide i{animation-duration:14s;animation-direction:reverse}
.mark-light-glow{filter:blur(32px)}
@media (prefers-reduced-motion:reduce){
	.mark-light-glow-wide,.mark-light i{animation:none}
}

/* THE HERO THAT REVEALS ITS BOX
   A hero that reveals its box to describe an Agent in, as IntroHero draws it,
   opens with an animation in two parts.

   First the hero stands on the CI gradient with its headline and its line
   alone: its box and its examples are hidden. The box starts to fade in at
   --reveal-input-at and takes --reveal-fill to arrive. The glow behind the
   box starts to fade in at --reveal-glow-at and takes --reveal-glow-fill to
   arrive.

   At --reveal-hold the veil of the quiet hero fades in over the gradient for
   --reveal-quiet, so the hero grows quieter, and last the examples fade in, on
   pills that read on the veil.

   Every part starts in its first state and ends in the state its rules give
   it without the animation, so a reader who asks for reduced motion sees the
   end state at once. */
.intro-hero-reveal{
	--reveal-input-at:.4s;
	--reveal-fill:.9s;
	--reveal-glow-at:.4s;
	--reveal-glow-fill:2.2s;
	--reveal-hold:.8s;
	--reveal-quiet:1.2s;
	--reveal-examples:.6s;
}
.intro-hero-reveal::before{animation:reveal-fade-in var(--reveal-quiet) ease var(--reveal-hold) both}
.intro-hero .glow-stage{width:100%;margin-top:var(--space-2)}
.intro-hero .glow-stage .prompt-box{
	margin-top:0;
	animation:reveal-fade-in var(--reveal-fill) ease var(--reveal-input-at) both;
}
.intro-hero-reveal .input-glow{animation:reveal-fade-in var(--reveal-glow-fill) ease var(--reveal-glow-at) both}
.intro-hero-reveal .tries{animation:reveal-show var(--reveal-examples) ease calc(var(--reveal-hold) + var(--reveal-quiet)) both}
.intro-hero-reveal .tries span{color:var(--reveal-example-ink)}
.intro-hero-reveal .try{background:var(--reveal-example-ground);color:var(--reveal-example-ink)}
@keyframes reveal-fade-in{from{opacity:0}}
@keyframes reveal-show{from{opacity:0;visibility:hidden}}
@media (prefers-reduced-motion:reduce){
	.intro-hero-reveal::before,.intro-hero .glow-stage .prompt-box,
	.intro-hero-reveal .input-glow,.intro-hero-reveal .tries{animation:none}
}

/* The banner that closes a page and leads to another, as LinkBand draws it:
   its heading and line on the left and its button on the right, which moves
   under them where the row is too narrow for both. */
.link-band{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-5)}
.link-band .band-head{margin-bottom:0}
.link-band .btn{flex:none}

/* The band that closes the page. Its heading, its form and the line under the
   form sit in a shared column, which keeps the reader's eye on the box. */
.start-free{display:flex;flex-direction:column;align-items:center;text-align:center}
.start-free-form{
	display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;justify-content:center;
	width:100%;max-width:var(--content-narrow);margin-top:var(--space-5);
}
.start-free-form .login-input{flex:1 1 260px;min-width:0}
/* The button stands as tall as the box beside it, which is the taller control,
   so the box and the button read as a whole. */
.start-free-form .btn{min-height:var(--space-8)}
.start-free-form .login-message{flex:1 1 100%;margin:0;font-size:var(--text-sm);line-height:var(--leading-sm)}
.start-free-note{
	margin:var(--space-3) 0 0;font-size:var(--text-xs);
	letter-spacing:var(--tracking-normal);color:var(--band-faint);
}

/* The wall of tools: a wide panel for each tool, each opening that tool's page.
   The offer takes a square block of tiles in the top right corner, and the
   tools fill in around it. */
.wall{
	/* At the minimum track width, a panel in this proportion leaves enough text
	   width for Microsoft Outlook, the longest tool name in this wall. */
	display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
	gap:var(--gutter);grid-auto-flow:dense;
}
/* The offer carries the same ground as the band further up the page, so it
   reads as the only tile that is not a tool. */
.wall-offer{
	grid-column:-3 / -1;grid-row:span 2;
	display:flex;flex-direction:column;justify-content:center;align-items:flex-start;
	gap:var(--space-2);padding:var(--space-5);
	background:var(--gradient) border-box;border:var(--hairline);border-radius:var(--r-card);
	box-shadow:var(--drop);color:var(--band-ink);
}
.wall-offer b{font-size:var(--text-base);font-weight:var(--weight-medium)}
/* a line of small text on a banner's ground, in the banner's quieter ink: the
   offer's line, and a note's line on the banner that welcomes a reader back */
.wall-offer p,.say-note p{margin:0;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--band-mute)}
.wall-offer .btn{margin-top:var(--space-2)}
/* the offer's heading over its line */
.wall-offer-copy{display:flex;flex-direction:column;gap:var(--space-2)}
/* An offer under a list, on the pages of Agents by industry and by job role,
   stands across the list's width, its heading and line on the left and its
   button on the right, and it wraps the button under them where the width
   runs short. */
.wall-offer.wall-offer-wide{
	margin-top:var(--space-5);
	flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between;column-gap:var(--space-5);
}
.wall-offer-wide .btn{margin-top:0}
.wall-tool{
	display:flex;align-items:center;gap:var(--space-3);
	aspect-ratio:3/1;min-height:var(--space-10);
	padding:var(--space-3) var(--space-4);border:var(--hairline);border-radius:var(--r-card);
	font:inherit;color:var(--ink);text-align:left;
}
.wall-tool .tally{margin-left:0;font-size:var(--text-xs);color:var(--faint)}
.wall-all{
	display:flex;align-items:center;justify-content:flex-start;
	aspect-ratio:3/1;min-height:var(--space-10);padding:var(--space-3) var(--space-4);
	text-align:left;
}
/* The link to every category under the category tiles, the link to all of a
   group's Agents in the directory, and the link to every record of a way beside
   the heading of its section in the ways to find Agents, which are all gradient
   links, are set alike. The last stays on one line beside its heading. */
.jobs-all,.shelves .all a,.agents-by-all{
	font-size:var(--text-sm);line-height:var(--leading-sm);
	font-weight:var(--weight-medium);letter-spacing:var(--tracking-normal);
	text-align:left;
}
.agents-by-all{white-space:nowrap}

/* The catalog: filters beside the grid. The filter panel's column is a side
   panel's width, as wide as the panel on an Agent's page. */
.cat{
	display:grid;grid-template-columns:var(--side-panel-width) minmax(0,1fr);
	gap:var(--space-5);align-items:start;margin-top:var(--space-4);
}
.cat-full{grid-template-columns:1fr}

/* The promotional segment at the foot of the filter panel, painted in the
   gradient as the banners draw it. It spans the panel from edge to edge along its
   bottom: the panel gives up its bottom padding to it, the segment reaches past
   the panel's side padding, and its bottom corners take the panel's radius less
   the panel's hairline, so they follow the panel's curve. It carries no hairline
   above it, because its ground sets it apart. Where a narrower width lays the
   panel's groups side by side, the segment spans every column. Its words are
   text on the CI gradient. */
.side-panel:has(> .side-promo){padding-bottom:0}
.side-panel > .side-promo{
	grid-column:1 / -1;
	margin:var(--space-2) calc(var(--space-1) * -1) 0;
	padding:var(--space-4);border-top:0;
	border-radius:0 0 calc(var(--r-card) - 1px) calc(var(--r-card) - 1px);
	background:var(--gradient);
}
.side-promo b{
	display:block;font-size:var(--text-base);font-weight:var(--weight-semibold);
	letter-spacing:var(--tracking-snug);
}
.side-promo p{margin:var(--space-1) 0 0;font-size:var(--text-sm);line-height:var(--leading-sm)}

/* The rows over the results of a catalog that has no hero above it. The
   heading of what is being shown stands in a row of its own, because a catalog
   of several picks words a long heading, and the line describing what is shown
   stands in the row under it. */
.tools{display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-2);flex-wrap:wrap}
.tools h2{flex:1 1 auto;min-width:0}
.results-sub{margin-bottom:var(--gutter)}
.results-note{margin:0;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--faint)}
/* The catalog's search and the field the form to modify an Agent takes its
   change in, which are the search box's shared rounded box, as the rule at
   .finder states. */
.catalog-search,.modify-field{
	--icon-stroke:currentColor;
	margin-bottom:var(--gutter);border:var(--hairline);color:var(--faint);
}
.catalog-search input,.modify-field input{border:0}
.catalog-search .btn,.modify-field .btn{flex:none}

/* THE SEARCH SUGGESTIONS
   The list search.js opens under a search field while the reader types, whose
   rows SearchSuggestions draws. The search box holds the list, so the list
   stands right under the box at the box's own width, over whatever follows the
   box, and scrolls where it is taller than the room it has: the room search.js
   measures to the foot of the visible window as --search-room, and never more
   than a set height. The list stands on
   the page's own ground, and every row in it on the surface the site's cards
   stand on, gray on the dark page and bright on the light one: its picture,
   its title in the ink over its line in the muted ink, and the label of its
   kind on its right. The kinds differ by their pictures and their labels
   alone. The words that match the query are bold, and the row the arrow keys
   have chosen carries a ring in the page's ink. The pictures are drawn boxes,
   so their sizes are pixels.

   While its field holds the focus, the box stands above everything that
   follows it on the page, so its list does too. A box that blurs what lies
   behind it, as the start page's does, paints its list together with itself,
   and without this a section later on the page paints over the list. */
.finder,.catalog-search{position:relative}
.finder:focus-within,.catalog-search:focus-within{z-index:30}
.search-suggestions{
	position:absolute;left:0;right:0;top:calc(100% + var(--space-2));z-index:40;
	display:grid;gap:var(--space-2);padding:var(--space-2);
	max-height:min(560px,var(--search-room,70vh));overflow-y:auto;
	border-radius:var(--r-card);border:var(--hairline);
	background:var(--bg);box-shadow:var(--drop-lift);
	text-align:left;
}
.search-suggestions[hidden]{display:none}
.search-suggestion{
	display:flex;align-items:center;gap:var(--space-3);
	padding:var(--space-2) var(--space-3);
	border-radius:calc(var(--r-card) - var(--space-2));border:var(--hairline);
	background:var(--surf-hi);color:var(--ink);text-decoration:none;
}
.search-suggestion[aria-selected="true"]{outline:2px solid var(--ink);outline-offset:2px}
/* Every picture stands in a square box of the same size, and a category's or
   a job's drawing in a box of the same height and the drawing's proportions.
   A tool's picture and a Channel's icon sit in their white frames with room
   around them, and the frame's radius keeps the frame's own proportions. */
.search-suggestion-picture{flex:none;display:grid;place-items:center;min-width:34px;height:34px}
.search-suggestion-picture > .tool-icon,.search-suggestion-picture > .channel-icon,
.search-suggestion-picture > .industry-mark,.search-suggestion-picture > .role-avatar{width:34px;height:34px}
.search-suggestion-picture > .tool-icon,.search-suggestion-picture > .channel-icon{border-radius:9px}
.search-suggestion-picture > .tool-icon img,.search-suggestion-picture > .tool-icon .icon,
.search-suggestion-picture > .channel-icon svg{width:18px;height:18px}
.search-suggestion-picture > .industry-mark i{font-size:var(--text-sm);line-height:var(--leading-none)}
.search-suggestion-picture > .role-avatar{font-size:var(--text-xs);line-height:var(--leading-none)}
.search-suggestion-picture > .category-thumb{height:34px}
.search-suggestion-copy{flex:1;min-width:0;display:grid}
.search-suggestion-title,.search-suggestion-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.search-suggestion-title{font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium)}
.search-suggestion-line{font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute)}
.search-suggestion mark{background:none;color:inherit;font-weight:var(--weight-bold)}
.search-suggestion-line b{font-weight:var(--weight-semibold)}
/* Every row's label is the same filled pill, in the colors palette.css sets
   as --label-on-surface and --label-ink-on-surface. */
.search-suggestion .search-suggestion-kind{
	flex:none;line-height:var(--leading-normal);white-space:nowrap;
	padding:var(--space-1) var(--space-2);border-radius:var(--r-pill);
	background:var(--label-on-surface);color:var(--label-ink-on-surface);
}
/* A tile past the rows a capped grid shows takes no place in its section. */
[data-tile][data-over-limit]{display:none}
/* the line a list shows where a search finds nothing in it */
.tile-empty{margin:0 0 var(--gutter);font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute)}
.seg{
	display:flex;gap:var(--space-1);padding:var(--space-1);border-radius:var(--r-pill);
	border:var(--hairline);background:var(--surf-sink);
}
.seg button{
	display:inline-flex;align-items:center;gap:var(--space-2);border:0;cursor:pointer;
	font:inherit;font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);
	padding:var(--space-2) var(--space-3);border-radius:var(--r-pill);
	background:transparent;color:var(--mute);
	transition:color var(--quick),background-color var(--quick);
}
.tools .count{
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);
	color:var(--faint);margin-left:2px;
}
/* The agent card, where the product picture is replaced by the evidence. The
   grid's columns share its width and may shrink below what their cards hold on
   one line, so a long name inside a card, such as a Channel's name, ends in an
   ellipsis rather than widening its column past the grid. */
.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gutter)}
.card{
	border-radius:var(--r-card);padding:var(--space-4);
	display:flex;flex-direction:column;gap:var(--space-3);position:relative;
}
.card-top{display:flex;align-items:flex-start;gap:var(--space-3)}
.card .name{
	font-size:var(--text-base);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);display:flex;align-items:center;
}

/* The Channel that publishes the Agent closes the card, in a row of its own: a
   label reading Published by, and the Channel's badge under it. The row takes
   the card's free space above it, so it sits at the foot of the card, and across
   a row of cards the Channel rows line up. */
.card-channel{display:flex;flex-direction:column;align-items:flex-start;margin-top:auto}

/* The labels of the card's rows, Works with and Published by, set alike: the
   smallest step of type in the faint ink, a step above what they name. */
.with-label,.card-channel-label{
	margin-bottom:var(--space-2);
	font-size:var(--text-xs);line-height:var(--leading-normal);letter-spacing:var(--tracking-normal);color:var(--faint);
}

.pager{display:flex;align-items:center;justify-content:space-between;margin-top:var(--space-5)}
/* The pager under the Agent catalog: the range on the left, and on the right
   the links to the page before and the page after, where the view has them. */
.pager-steps{display:flex;gap:var(--space-4)}
/* The pager under a page of a paginated list: the range on the left, and the
   links to the page before and the page after on the right. A step with no page
   on its side is the same button without a link, dimmed the way the Channel
   strip dims its arrows. */
.tile-pager-steps{display:flex;gap:var(--space-2)}
.tile-pager .btn[aria-disabled="true"]:hover{background:transparent}

/* ─────────────────────────────────────────────
   AGENT
   ───────────────────────────────────────────── */

/* The top of an Agent's page is one panel of segments one above the other: the
   hero's banner, the hero's actions, the drawing of how the Agent works and the
   description under it. The panel clips every segment to its rounded corners,
   and a hairline stands between neighboring segments. The page builds it as a
   PanelStack, which holds the hero and the drawing's panel, and each of those
   holds two segments. The recipe for a ruled separator draws the hairlines,
   and the rule at .category-detail-hero clips the panel. */

/* The hero: its top segment is the banner's ground, carrying the trail, the
   Agent's name and the line saying what kind of Agent it is, with the
   PineSpark icon on its right in a column of its own, as the hero of a tool's
   page carries it. The banner leaves its own outline, corners and shadow to the
   panel around it. Its bottom segment is .hero-actions. */
.agent-hero > .hero-band{border:0;border-radius:0;box-shadow:none}
.hero-band{
	padding:clamp(var(--space-5),2.8vw,var(--space-6)) clamp(var(--space-5),3.4vw,var(--space-7));
}
/* The hero's text, its trail included, is text on the CI gradient. */
.hero-band .tag{background:var(--band-wash);color:var(--band-acc)}
/* The labels above an Agent's name, in a row, each a pill on a ground of its
   own, which palette.css sets as --label-on-gradient: a light ground under the
   light page's dark text and a dark one under the dark page's white text, so
   a label reads on every part of the gradient. A label's text stands on its
   pill rather than on the gradient, so it carries no shadow. */
.hero-labels{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:0 0 var(--space-3);padding:0;list-style:none}
.hero-band .hero-labels .tag{
	line-height:var(--leading-normal);font-weight:var(--weight-semibold);
	padding:var(--space-1) var(--space-3);border-radius:var(--r-pill);
	background:var(--label-on-gradient);color:var(--ink-on-gradient);text-shadow:none;
}
/* the large headline on a banner: an Agent's name, the welcome beside the
   sign-in form, and a legal page's title */
.hero-band h1,.login-say h1,.legal-hero h1{
	margin:0;font-size:var(--text-3xl);line-height:var(--leading-none);
	font-weight:var(--weight-semibold);letter-spacing:var(--tracking-tight);
	color:var(--band-ink);
}

/* the plain-language line under the Agent's name that says what kind of Agent
   it is */
.hero-kind{
	margin:var(--space-2) 0 0;font-size:var(--text-lg);	font-weight:var(--weight-medium);letter-spacing:var(--tracking-snug);color:var(--band-acc);
}
/* The segment attached below the hero's banner, as the description is attached
   below the drawing, which it shares its ground and its hairline with at
   .structure-description. It carries the Agent's two actions, in the styles
   the side panel's buttons take, and beside them the line that says what the
   two do. Its padding at the sides is the banner's, so its buttons line up
   with the banner's text, and it lies on the wash of the ink. */
.hero-actions{
	display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-3);
	padding:var(--space-4) clamp(var(--space-5),3.4vw,var(--space-7));
	background:var(--panel-wash);
}
/* The form Modify Agent opens: its heading, the line saying what it does, and
   the field the change is described in, with the button that sends it. It is
   a context element, as wide as the window leaves room for up to a fixed
   width, so the field has room for a sentence. */
.modify-agent{width:28rem;padding:var(--space-5);border-radius:var(--r-card)}
.modify-agent p{margin:var(--space-2) 0 var(--space-4);font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute)}
.modify-agent .modify-field{margin:0}

/* The drawing's panel, which stands in the panel-stack under the hero, in two
   segments one above the other: the drawing of how the Agent works on top, and
   the paragraph that describes the Agent below it, with a hairline between
   them. One segment lays the wash of the ink, --panel-wash,
   over the panel's ground, and the other stands on the panel's own ground, as
   --drawing-ground and --drawing-foot-ground set for each theme. The top
   segment scrolls sideways where the drawing needs more width than the panel
   has, as the rule at .flows states. */
.structure-drawing{padding:var(--space-6);overflow-x:auto;background:var(--drawing-ground)}
/* The segment attached below the drawing carries the hairline the recipe for
   a ruled separator draws, as the hero's actions do. */
.structure-description{padding:var(--space-5) var(--space-6);background:var(--drawing-foot-ground)}
.structure-description p{
	margin:0;max-width:72ch;font-size:var(--text-base);
	line-height:var(--leading-normal);color:var(--ink);
}

/* The drawing: a flow chart of each of the Agent's processes, one above the
   other, read from the top down. A flow chart stands in two columns. The flow
   runs down the left one, from the box that opens the process through its
   steps, and the box of what happens where a decision's condition holds stands
   in the right one, level with its decision. The rows leave gaps between them,
   where agent-structure.js draws the lines down with arrows, and the columns
   leave a wider gap, where it draws the line of each decision's yes. The lines
   lie in an SVG spread over the whole board behind the boxes.

   Every box of the flow is as wide as its column, except a decision, which is
   as wide as its question needs, up to that width, and stands in the column's
   middle, so every line down runs straight. A decision and the box on its
   branch stand level, so the line between them runs straight too. Where the
   flow charts need more width than the panel has, the board keeps its width
   and the segment it stands in scrolls sideways. */
.flows{position:relative;display:grid;justify-content:center;gap:var(--space-8);min-width:min-content}
.flow{
	display:grid;grid-template-columns:minmax(16rem,26rem) minmax(12rem,20rem);
	column-gap:var(--space-9);row-gap:var(--space-7);align-items:center;
}
.structure-links{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.structure-links path{fill:none;stroke:var(--faint);stroke-width:1.5}
.structure-links marker path{fill:var(--faint);stroke:none}
/* The lines that enter or leave the box under the pointer, and their arrows,
   take the ink, so they stand out: near white on the dark page, and near black
   on the light page. agent-structure.js marks such a line lit and ends it with
   the drawing's lit arrow. */
.structure-links > path.lit{stroke:var(--ink)}
.structure-links marker.lit path{fill:var(--ink)}
/* A box of the flow stands over the lines, in the flow's column, and the box of
   what happens where a decision's condition holds stands in the column beside
   it. */
.flow-node{position:relative;z-index:1;grid-column:1;min-width:0}
.flow-branch{grid-column:2;justify-self:start}
/* The box that opens a process and every box of what happens are panels on the
   drawing's ground. The one that opens a process takes the accent, so the start
   of a flow stands apart from its steps. */
.flow-start,.flow-action{padding:var(--space-3) var(--space-4);border-radius:var(--r-tile)}
.flow-start{background:var(--acc-soft);border:1px solid color-mix(in srgb,var(--acc) 28%,transparent)}
.flow-action{background:var(--drawing-box-ground);border:var(--hairline)}
.flow-name,.flow-text,.flow-question{display:block;font-size:var(--text-sm);line-height:var(--leading-sm)}
.flow-name{font-weight:var(--weight-medium);color:var(--acc)}
/* A decision: its question inside a box whose ends come to a point, drawn as
   two layers of that shape behind the question. The lower layer is the ground
   of a box. The upper one is a hairline ring in the color of a box's border:
   the shape less the same shape inside it. Both colors are see-through, so
   the ring covers only the edge and never lies over a second copy of itself.
   The ring's inner edge is set in pixels, because it draws a hairline: 1px in
   from the flat edges, and as far along the pointed ones as keeps them about
   1px wide. --flow-tip is how far each point reaches, and the question keeps
   clear of it. Its yes stands beside its right point, over the line to its
   branch, and its no stands below it, beside the line down. */
.flow-decision{
	--flow-tip:var(--space-4);
	justify-self:center;text-align:center;
	padding:var(--space-3) calc(var(--flow-tip) + var(--space-3));
}
.flow-decision::before,.flow-decision::after{content:'';position:absolute;inset:0;z-index:-1}
.flow-decision::before{
	background:var(--drawing-box-ground);
	clip-path:polygon(var(--flow-tip) 0,calc(100% - var(--flow-tip)) 0,100% 50%,calc(100% - var(--flow-tip)) 100%,var(--flow-tip) 100%,0 50%);
}
.flow-decision::after{
	background:var(--line);
	clip-path:polygon(evenodd,
		var(--flow-tip) 0,calc(100% - var(--flow-tip)) 0,100% 50%,calc(100% - var(--flow-tip)) 100%,var(--flow-tip) 100%,0 50%,var(--flow-tip) 0,
		calc(var(--flow-tip) + .5px) 1px,calc(100% - var(--flow-tip) - .5px) 1px,calc(100% - 1.2px) 50%,
		calc(100% - var(--flow-tip) - .5px) calc(100% - 1px),calc(var(--flow-tip) + .5px) calc(100% - 1px),1.2px 50%,calc(var(--flow-tip) + .5px) 1px);
}
.flow-yes,.flow-no{position:absolute;font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute)}
.flow-yes{left:100%;bottom:50%;margin:0 0 var(--space-1) var(--space-2)}
.flow-no{top:100%;left:50%;margin:var(--space-1) 0 0 var(--space-2)}
/* What a box reads or writes, and each slot it names, each under a caption in
   the quietest ink. An input or an output shows its category's name, and a slot
   shows the tools that can fill it under the name of its kind of tool. An info
   button beside each name opens the name and the brief explanation of what it
   is. The button is as tall as the name's line, and its icon sits in its
   middle. */
.flow-data,.flow-slot{margin-top:var(--space-2)}
.flow-caption{display:block;font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--faint)}
.flow-slot-head{display:flex;align-items:center;gap:var(--space-1)}
.flow-data-list{display:flex;flex-wrap:wrap;gap:var(--space-1) var(--space-3)}
.flow-data-list li{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute)}
.flow-about{
	display:grid;place-items:center;width:calc(var(--text-xs) * var(--leading-normal));height:calc(var(--text-xs) * var(--leading-normal));padding:0;
	border:0;border-radius:var(--r-pill);background:none;color:var(--faint);cursor:pointer;
}
/* An input or an output explained in a context element: its name over the
   brief explanation of what it is, several of them in a list. A context
   element that explains is set to a reading width, as a record's context
   element is, so the explanation wraps into a few lines. */
.explained-list{display:grid;gap:var(--space-3)}
/* A tool of the drawing is a button that opens the tool's context element, the
   one its entry in the side panel's Works with opens, and its name is
   underlined under the pointer. */
.structure-tools{margin:var(--space-2) 0 0;display:flex;flex-direction:column;gap:var(--space-2)}
.structure-tools li{display:flex;min-width:0}
.structure-tool{
	display:flex;align-items:center;gap:var(--space-2);min-width:0;padding:0;
	border:0;background:none;text-align:left;cursor:pointer;
	font:inherit;font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute);
}
/* The multi tool row under the tools a box shows in full, which stands for the
   tools after them and opens the list of every tool the box works with. It
   keeps the same distance from the row above it as the rows of the tools keep
   from each other. */
.structure-more{margin-top:var(--space-2)}

/* the reading column on the left, and on the right the buying panel, a side
   panel's width, as wide as the filter panel beside the Agent catalog */
/* The columns stand below the panel at the top of the page by the rule gap,
   the same gap the panel stands below the site bar by. */
.detail{
	display:grid;grid-template-columns:minmax(0,1fr) var(--side-panel-width);
	gap:var(--space-5);align-items:start;margin-top:var(--rule-gap);
}
.detail-main > * + *{margin-top:var(--space-7)}

/* what the agent does, in the order it does it */
.numbers{counter-reset:n}
.numbers li{counter-increment:n;display:flex;gap:var(--space-4);padding:var(--space-3) 0}
.numbers li::before{
	content:counter(n,decimal-leading-zero);flex:none;width:22px;padding-top:2px;
	font-size:var(--text-xs);letter-spacing:var(--tracking-normal);color:var(--acc);
}
/* the title of a step the Agent takes, and of a question people ask */
.numbers b,.faq b{
	display:block;font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);margin-bottom:var(--space-1);
}
.numbers span{display:block;font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute)}

/* the questions people ask before they buy */
.faq{display:grid}
.faq div{padding:var(--space-4) 0}

/* The tree of an Agent's variants, drawn the way a model hub draws where a model
   comes from: each level stands a step further in than the level above, and a
   line runs down from under the level above and curves into each row. A row is
   at least as tall as a tool's frame, so the curve meets every row at its middle,
   which is the padding above the row plus the distance to the frame's middle.
   The line runs on past a row wherever a sibling follows it. */
.lineage ul{padding-left:var(--space-5)}
.lineage li{position:relative}
.lineage-row{
	display:flex;align-items:center;gap:var(--space-2);min-height:24px;padding:var(--space-1) 0;
	font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--mute);
}
.lineage-row u{text-decoration:none;margin-left:calc(var(--space-1) * -1);color:var(--faint)}
.lineage-this{
	margin-left:auto;padding:0 var(--space-2);border-radius:var(--r-pill);
	font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--acc);background:var(--acc-soft);
}
/* Every row but the one of the Agent the page shows links to its Agent's own
   page. The base Agent's row names that Agent at its right end, where the other
   pages mark this Agent. */
.lineage-name{margin-left:auto;text-align:right;color:var(--mute)}
.lineage ul > li::before{
	content:"";position:absolute;left:calc(var(--space-3) * -1);top:0;
	width:var(--space-2);height:calc(var(--space-1) + 12px);
	border-left:1px solid var(--line-hi);border-bottom:1px solid var(--line-hi);border-bottom-left-radius:6px;
}
.lineage ul > li:not(:last-child)::after{
	content:"";position:absolute;left:calc(var(--space-3) * -1);top:0;bottom:0;
	border-left:1px solid var(--line-hi);
}

/* ─────────────────────────────────────────────
   SIGN IN AND SIGN UP
   ───────────────────────────────────────────── */

/* the welcome beside the form */
.login{
	display:grid;grid-template-columns:minmax(0,1fr) minmax(0,420px);
	gap:var(--gutter);align-items:stretch;
}
.login-say{display:flex;align-items:center}
/* Only the line under the headline, never a paragraph inside a note, which is a
   paragraph on this banner too. */
.login-say .band-in > p{
	margin:var(--space-4) 0 0;font-size:var(--text-base);
	line-height:var(--leading-normal);color:var(--band-mute);max-width:44ch;
}

/* what the reader gets, on the banner that asks them to sign up */
.say-points{margin:var(--space-5) 0 0;display:grid;gap:var(--space-3)}
.say-points li{
	display:flex;align-items:center;gap:var(--space-3);
	font-size:var(--text-base);color:var(--band-ink);
}
.say-points .icon{width:18px;height:18px;color:var(--band-acc)}

/* what is new and worth knowing, on the banner that welcomes them back */
.say-notes{margin-top:var(--space-5);display:grid;gap:var(--space-3)}
.say-note{
	border:1px solid var(--band-line);border-radius:var(--r-ctrl);
	padding:var(--space-3) var(--space-4);background:var(--band-wash);
}
.say-note em{
	display:block;font-style:normal;font-size:var(--text-xs);
	letter-spacing:var(--tracking-normal);color:var(--band-acc);margin-bottom:var(--space-1);
}
.say-note b{
	display:block;font-size:var(--text-base);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);color:var(--band-ink);margin-bottom:var(--space-1);
}

.login-card{
	border-radius:var(--r-card);padding:clamp(var(--space-5),3vw,var(--space-7));
	display:flex;flex-direction:column;justify-content:center;
}
.login-card h2{
	margin:0 0 var(--space-1);font-size:var(--text-xl);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);
}
.login-card .note{margin:0 0 var(--space-5);font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--faint)}

/* The field takes the same ground and hairline as the search box on the home
   page, so the field and the search box read as the same control rather than
   as different designs. */
/* The field sits directly above the button, so it takes the button's shape and
   the button's stated height. A rounded rectangle over a fully rounded control
   would read as different designs stacked. */
.login-input{
	width:100%;font:inherit;font-size:var(--text-base);min-height:var(--space-8);
	padding:var(--space-3) var(--space-4);border-radius:var(--r-pill);
	border:var(--hairline);color:var(--ink);
	transition:border-color var(--quick);
}
.login-input:focus{outline:0;border-color:var(--line-hi)}
/* the same taller control the buy panel uses */
.login-card .btn{
	width:100%;min-height:var(--space-8);margin-top:var(--space-3);
	padding:var(--space-3) var(--space-4);font-size:var(--text-base);line-height:var(--leading-normal);
}

/* what the script writes back into, empty until it has something to say */
.login-message{
	margin:var(--space-3) 0 0;font-size:var(--text-sm);
	line-height:var(--leading-sm);color:var(--mute);
}
.login-message:empty{display:none}
.login-message.error{color:var(--ink-error)}

.login-privacy{
	margin:var(--space-4) 0 0;font-size:var(--text-xs);
	letter-spacing:var(--tracking-normal);color:var(--faint);
}
/* The documents the line commits the reader to are underlined and a shade
   stronger than the sentence around them, so they read as the links they are. */
.login-privacy a{color:var(--mute);text-decoration:underline;text-underline-offset:2px}

/* A legal page: the document's title and date line in the banner, and its text
   in the article below. The article's headings, paragraphs and lists come from
   the document's Markdown, so every rule for them sits on .legal-document. */
.legal-page{width:100%;max-width:var(--content-xl);margin:0 auto}
.legal-hero{padding:var(--space-6)}
.legal-hero p{
	margin:var(--space-3) 0 0;font-size:var(--text-base);
	line-height:var(--leading-normal);color:var(--band-mute);
}
.legal-document{
	margin-top:var(--space-4);padding:var(--space-6);border-radius:var(--r-card);
}
.legal-document h2{
	margin:var(--space-7) 0 var(--space-3);font-size:var(--text-xl);line-height:var(--leading-normal);
	font-weight:var(--weight-medium);letter-spacing:var(--tracking-snug);color:var(--ink);
}
.legal-document h3{
	margin:var(--space-6) 0 var(--space-2);font-size:var(--text-lg);line-height:var(--leading-normal);
	font-weight:var(--weight-medium);letter-spacing:var(--tracking-snug);color:var(--ink);
}
.legal-document p,.legal-document li{
	margin:0 0 var(--space-3);font-size:var(--text-base);line-height:var(--leading-relaxed);color:var(--mute);
}
.legal-document ul{margin:0 0 var(--space-3);padding-left:var(--space-5)}
.legal-document li{margin-bottom:var(--space-1)}
.legal-document strong{font-weight:var(--weight-semibold);color:var(--ink)}
.legal-document a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
.legal-document hr{margin:var(--space-6) 0;border:0;border-top:var(--hairline)}

/* ─────────────────────────────────────────────
   COOKIE CONSENT

   The consent bar and its popup belong to the framework, which writes them into
   every page with a style block of their own. That block sits after this file in
   the document, so a rule here only wins by being more specific: every selector
   below therefore leads with the identity of the thing it is restyling.

   Nothing here invents a value. The bar becomes one of this site's own glass
   panels, its buttons take the site's own control recipe, and everything it
   draws comes from a step or a theme value, so it follows light and dark
   without a separate set of rules.
   ───────────────────────────────────────────── */

/* The bar across the foot of the page.

   It stands taller than a panel on the page would, and it takes the raised
   surface and the stronger shadow rather than the resting ones, so it reads as
   something asking to be dealt with rather than as part of the page. Its message
   is in the page's own ink instead of the muted gray, for the same reason. */
:root #ps-cookie-banner{
	background:var(--surf-hi);color:var(--ink);
	border-top:var(--hairline);
	box-shadow:var(--edge),var(--drop-lift);
	-webkit-backdrop-filter:var(--glass);
	backdrop-filter:var(--glass);
	padding:var(--space-5) var(--pad);
}
/* The bar's content lines up with the page's content at every width. The page is
   capped at the widest content width with its gutter inside that cap, while the
   bar keeps the same gutter outside its content, so the content takes the cap less
   a gutter on each side. */
#ps-cookie-banner .ps-cookie-banner-inner{
	max-width:calc(var(--content-xl) - 2 * var(--pad));gap:var(--space-4);
}
#ps-cookie-banner .ps-cookie-banner-message{
	font-size:var(--text-sm);line-height:var(--leading-sm);color:var(--ink);
}
#ps-cookie-banner .ps-cookie-banner-actions{gap:var(--space-3)}

/* the buttons, in the site's own control recipe */
#ps-cookie-banner .ps-cookie-banner-accept,
#ps-cookie-popup .ps-cookie-banner-accept{
	font:inherit;font-size:var(--text-sm);line-height:var(--leading-sm);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);
	min-height:var(--space-7);
	padding:var(--space-2) var(--space-4);border-radius:var(--r-pill);
	background:var(--solid);color:var(--solid-ink);border:1px solid transparent;
	transition:opacity var(--quick);
}
#ps-cookie-banner .ps-cookie-banner-accept:hover,
#ps-cookie-popup .ps-cookie-banner-accept:hover{background:var(--solid);opacity:.88}
#ps-cookie-banner .ps-cookie-banner-customize{
	font-size:var(--text-sm);line-height:var(--leading-sm);text-decoration:none;color:var(--faint);
	transition:color var(--quick);
}

/* The popup that opens behind a dimmed page. It is the same raised panel the
   bar is, so it follows the theme the way every other surface on the site does.
   The close control is gone: a click anywhere outside the sheet closes it. */
:root #ps-cookie-popup-backdrop{background:var(--scrim)}
:root #ps-cookie-popup{
	background:var(--surf-hi);color:var(--ink);
	border:var(--hairline);
	box-shadow:var(--edge),var(--drop-lift);
	-webkit-backdrop-filter:var(--glass);
	backdrop-filter:var(--glass);
	padding:var(--space-5);
	/* The sheet's corner is concentric with the button in it: the button's
	   full-round radius, plus the padding around it, plus the sheet's own
	   hairline. */
	border-radius:calc(var(--space-7) / 2 + var(--space-5) + 1px);
}
#ps-cookie-popup .ps-cookie-popup-header{margin:0 0 var(--space-4)}
#ps-cookie-popup .ps-cookie-popup-title{
	font-size:var(--text-lg);font-weight:var(--weight-medium);
	letter-spacing:var(--tracking-snug);color:var(--ink);
}
/* the promise that opens the sheet, above the rows */
#ps-cookie-popup .ps-cookie-popup-note{
	margin:0 0 var(--space-4);font-size:var(--text-sm);
	line-height:var(--leading-sm);color:var(--mute);
}
#ps-cookie-popup .ps-cookie-popup-row{
	gap:var(--space-4);padding:var(--space-4) 0;border-top:var(--hairline);
}
#ps-cookie-popup .ps-cookie-popup-row-title{
	margin:0 0 var(--space-1);font-size:var(--text-sm);line-height:var(--leading-sm);
	font-weight:var(--weight-medium);letter-spacing:var(--tracking-snug);
	color:var(--ink);
}
#ps-cookie-popup .ps-cookie-popup-row-desc{
	font-size:var(--text-xs);line-height:var(--leading-normal);color:var(--mute);
}
/* A toggle that is on is a call to action, so it takes the same ground the
   site's solid button takes, and its knob takes the page color. The ground and
   the knob invert with the theme, so the knob reads against the track in the
   light and the dark theme. */
#ps-cookie-popup .ps-cookie-popup-toggle-locked{background:var(--solid);opacity:.35}
#ps-cookie-popup .ps-cookie-popup-toggle-locked::before,
#ps-cookie-popup .ps-cookie-popup-toggle-slider::before{background:var(--bg)}
#ps-cookie-popup .ps-cookie-popup-toggle-slider{background:var(--line-hi)}
#ps-cookie-popup .ps-cookie-popup-toggle input:checked + .ps-cookie-popup-toggle-slider{background:var(--solid)}
#ps-cookie-popup .ps-cookie-popup-footer{margin-top:var(--space-5)}

/* ─────────────────────────────────────────────
   RESPONSIVE
   ───────────────────────────────────────────── */
@media (max-width:1080px){
	.jobs{grid-template-columns:repeat(4,1fr)}
	.channel-grid,.dir,.steps,.steps.steps-three{grid-template-columns:repeat(2,1fr)}
	.channel-track > .channel-card{flex-basis:43%}
	.grid,.agents-by-tools{grid-template-columns:repeat(2,minmax(0,1fr))}
	/* A way's section of the ways to find Agents that stands in rows shows its
	   leading records alone from here down, as many as fit the view at this
	   width. A band shows every record it holds, because it scrolls sideways. */
	.agents-by-grid > li:nth-child(n + 9){display:none}
	/* A track written as minmax(0,1fr) may grow narrower than its content, which
	   then wraps. A plain 1fr never grows narrower than the widest line in it,
	   and at a narrow width that line would push the page wider than the
	   window. */
	.cat{grid-template-columns:minmax(0,1fr)}
	.side{position:static;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));padding:var(--space-1)}
	.side.side-single,.login{grid-template-columns:1fr}
	.side > .side-section + .side-section:not(.side-promo){border-top:0;border-left:var(--hairline)}
	.foot-top{grid-template-columns:repeat(4,minmax(0,1fr))}
	.foot-brand{grid-column:1 / -1;grid-row:auto}
	.foot-brand p{max-width:64ch}
}
@media (max-width:860px){
	/* The links no longer fit beside the controls, so they leave the bar's row
	   and the menu button appears in their place. They are the same links: the
	   nav is taken out of the flow and hung under the bar as a panel, which the
	   button opens and closes.

	   The panel wears the bar's own raised surface, because it sits over the
	   page rather than in it. */
	.burger{display:inline-flex}
	.bar-nav{
		display:none;position:absolute;left:0;right:0;top:100%;
		flex-direction:column;margin:0;
		padding:var(--space-2) var(--pad) var(--space-3);
		background:var(--surf-hi);border-bottom:var(--hairline);
		box-shadow:var(--drop);
		-webkit-backdrop-filter:var(--glass);
		backdrop-filter:var(--glass);
	}
	.bar[data-menu="open"] .bar-nav{display:flex}
	.bar-nav a,.bar-menu-button{padding:var(--space-3) var(--space-2);font-size:var(--text-base);line-height:var(--leading-normal)}
	/* A menu of the bar opens its links in the panel itself, indented under its
	   button, rather than in a panel of its own. */
	.bar-menu-button{width:100%}
	.bar-menu-panel{position:static;min-width:0;padding:0 0 0 var(--space-4);border:0;border-radius:0;background:none;box-shadow:none}
	.category-detail-hero .band-in{
		grid-template-columns:minmax(0,1fr) minmax(220px,280px);
		gap:var(--space-5);
	}
	.category-detail-intro{gap:var(--space-3)}
	.category-detail-pinespark{width:64px;height:64px}
	.category-detail-copy h1{font-size:var(--text-xl)}
	.channel-hero-main,.shelf{grid-template-columns:1fr}
	.channel-byline{max-width:560px}

	/* Too few columns are left for the offer to take a corner, so it takes a row
	   of its own. It stands partway down the wall rather than at the top,
	   because the tools are what a reader came to the wall for: a set number of
	   tiles are drawn before it and the rest after. The count takes in only the
	   tiles in view, so the offer stands after that many of the tiles a row limit
	   leaves in, and last where fewer are left in. */
	.wall-offer{grid-column:1 / -1;grid-row:auto;order:1}
	.wall-tool:nth-child(n+12 of .wall-tool:not([data-over-limit])){order:2}
	.jobs{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:750px){
	/* An Agent's page keeps its buying panel beside the reading column down to
	   here. Below it the panel stands above the column, so its buttons come
	   first, and it no longer stays in view while the page scrolls. */
	.detail{grid-template-columns:minmax(0,1fr)}
	.buy{position:static;order:-1}

	/* The ways to find Agents stand above their view from here down, the way a
	   side panel stands above the column beside it: the list turns into a row of
	   the ways, each way's words alone and centered on its share of the row, on two
	   lines where one is too narrow for them, and the view takes the width under
	   it and the height the row leaves it. The panel behind the list takes a way's
	   share of the row. Half the window is too short here for a section, whose
	   heading and records wrap onto more lines on a narrow window, so the panel
	   may grow to the height of the window under the bar, less a step above it
	   and a step below it. */
	.agents-by-panel{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);gap:var(--space-3);max-height:calc(100svh - var(--bar) - 2 * var(--space-4))}
	.agents-by-list{grid-template-columns:repeat(var(--ways),minmax(0,1fr))}
	.agents-by-way a{justify-content:center;padding:0 var(--space-1)}
	.agents-by-way b{white-space:normal;text-overflow:clip;text-align:center}
	.agents-by-way .icon{display:none}
	.agents-by-highlight{right:auto;width:calc((100% - (var(--ways) - 1) * var(--way-gap)) / var(--ways))}
}
@media (max-width:640px){
	:root{--bar:56px}
	.jobs,.foot-top{grid-template-columns:repeat(2,1fr)}
	.dir,.steps,.steps.steps-three,.channel-grid,.channel-posts{grid-template-columns:1fr}
	.intro-hero h1{font-size:var(--text-2xl)}
	.grid,.side,.find-hero-drawn .band-in{grid-template-columns:minmax(0,1fr)}
	.side > .side-section + .side-section:not(.side-promo){border-left:0;border-top:var(--hairline)}
	/* Every hero, and the drawing of how an Agent works with the description
	   under it, pad their content at a smaller step on a phone. */
	.find-hero,.hero-band,.category-hero,.category-detail-hero,.channel-index-hero,.channel-hero,
	.structure-drawing,.structure-description{padding:var(--space-4)}
	/* A find-agents hero at a phone's width takes a smaller picture, and its
	   headline takes as many lines of the smaller type as it needs, so the whole
	   headline shows. The row of the headline is as tall as its lines, and never
	   shorter than the picture beside them, and the hero is as tall as what it
	   holds rather than the one height it keeps on a wider window. */
	.find-hero{--find-hero-picture:48px}
	.find-hero .band-in{height:auto}
	.find-hero-head{height:auto;min-height:var(--find-hero-picture)}
	.find-hero-head h1{display:block;overflow:visible}
	.find-hero .band-in,.hero-band .band-in{grid-template-columns:minmax(0,1fr) 64px;gap:var(--space-3)}
	.find-hero-visual{display:none}
	.find-hero-head{gap:var(--space-3)}
	.find-hero .tool-icon-lg{border-radius:12px}
	.find-hero .tool-icon-lg img{width:30px;height:30px}
	.find-hero-head h1,.category-hero h1,.channel-index-hero h1{font-size:var(--text-xl)}
	.hero-actions{padding:var(--space-3) var(--space-4)}
	.hero-band h1,.channel-hero h1{font-size:var(--text-2xl)}
	.category-detail-hero .band-in{grid-template-columns:1fr;gap:var(--space-4)}
	.category-detail-visual{max-width:520px}
	.category-detail-pinespark{width:56px;height:56px}
	.channel-strip{grid-template-columns:32px minmax(0,1fr) 32px;gap:var(--space-2)}
	.channel-arrow{width:32px;height:32px}
	.channel-track > .channel-card{flex-basis:84%}
	/* The button moves onto its own row here, and the icon stays on the line
	   with the text rather than taking a row of its own.

	   The box keeps the surface it has in the wide layout and gains nothing of
	   its own, so the field looks the same in the wide and the narrow layout.
	   The input inside it stays transparent, so the box reads as a plain box
	   rather than a box inside a box. A click anywhere on the box that is not the
	   button lands in the field, because everything but the button sits inside
	   the label.

	   The box is no longer a control wrapped around another, so a full round
	   would read as a stadium. It keeps the radius of the wide layout, which is
	   still concentric with the button it holds: the button's full-round radius
	   plus the gap the box leaves between the button and its bottom, left and
	   right edges. The box's hairline border is part of that gap, and the
	   padding inside the border makes up the rest.

	   The top row, holding the icon and the field, has padding of its own on
	   every side, so the icon and the text sit in from the box's edge by that
	   padding and the box's own. The field drops the height, the padding and the
	   border it takes in the wide layout to match the button, because here it
	   shares no row with the button. The top row is therefore as tall as a line
	   of text plus its padding, and the box's height follows from its rows.

	   The field the form to modify an Agent takes its change in is laid out the
	   same way, so a phone gives its prompt the whole width of the form. */
	.finder,.modify-field{flex-wrap:wrap;height:auto;padding:calc(var(--space-2) - 1px)}
	.finder-field,.modify-field-input{flex:1 1 100%;padding:var(--space-2)}
	.finder input,.modify-field input{min-height:0;padding:0;border:0}
	.finder .btn,.modify-field .btn{flex:1 0 100%;width:100%}

	/* The framework gives the message a flex basis, which is a width while the
	   bar is a row. Here the bar is a column, so that basis becomes a height and
	   the message stretches to fill it. It sizes to its text instead. */
	#ps-cookie-banner .ps-cookie-banner-message{flex:0 0 auto}
	:root #ps-cookie-banner{padding:var(--space-4) var(--pad)}

	/* A section heading and the link beside it sit in a row that never wraps,
	   and the link cannot break because it is a phrase kept whole. Together they
	   need more width than a small phone has. The link drops to its own line
	   here instead. */
	.sec-head{flex-wrap:wrap}
}
@media (max-width:560px){
	/* Every headline drops to a smaller step of the type scale, so a headline
	   with a column of words keeps the column and the words after it on the same
	   line on a phone, and the other headlines match it. */
	.hero-headline{font-size:var(--text-2xl)}

	/* A phone leaves the circles only the bands above and below the headline, so
	   each circle drops a spacing step, and the clearance and the space between
	   circles shrink in the same proportion. */
	.hero-tools{row-gap:var(--space-2);column-gap:var(--space-5)}
	.hero-step .hero-tool{width:var(--space-7);height:var(--space-7)}

	/* On a phone the columns of a flow chart of how an Agent works narrow, its
	   boxes pad their content less, and every box says its text in the smaller
	   type, so the flow chart keeps as much of its width inside the panel as it
	   can before the drawing scrolls. The ways' words drop to the smaller type
	   too, so every way fits its share of the row. */
	.flow{grid-template-columns:minmax(11rem,1fr) minmax(9rem,1fr);column-gap:var(--space-6)}
	.flow-start,.flow-action{padding:var(--space-2)}
	.flow-decision{padding:var(--space-2) calc(var(--flow-tip) + var(--space-2))}
	.flow-name,.flow-text,.flow-question,.agents-by-way a{font-size:var(--text-xs);line-height:var(--leading-normal)}

	/* On a phone a way's records in rows take the view's whole width, each on a
	   row of its own, as many of the leading ones as fit the view, and the
	   records in a band narrow, so a band shows more than one of them at a time. */
	.agents-by-tools{grid-template-columns:minmax(0,1fr)}
	.agents-by-grid > li:nth-child(n + 4){display:none}
	.agents-by-band-industry li{width:13rem}
	.agents-by-band-category li{width:12rem}
	.agents-by-detail{padding:var(--space-4)}
}

@media (max-width:480px){
	/* The bar now has to hold the ways into an account, and the color-mode
	   control is the only thing in it that is a preference rather than a
	   destination. It gives up its room here, and the page keeps the mode the
	   reader last picked, or dark where the reader has picked none. */
	.toggle{display:none}
	.mark{
		width:40px;
		background-image:var(--logo-icon);
		background-position:0% 50%;
	}
	/* the footer has room for the full lockup, so it keeps it */
	.foot-brand .mark{
		width:200px;height:48px;
		background-image:var(--logo-lockup);
		background-position:0% 38.5%;
	}

	/* On the smallest phones the drawing of how an Agent works pads its board
	   less, so its flow charts fit as long as they can before the drawing
	   scrolls. */
	.structure-drawing{padding:var(--space-3)}
}

@media (max-width:360px){
	.intro-hero h1{font-size:var(--text-xl)}
}

/* ─────────────────────────────────────────────
   FALLBACKS
   ───────────────────────────────────────────── */
/* A reader who asks for reduced motion gets no transitions. The gradient
   section stops the gradient's flow for such a reader. */
@media (prefers-reduced-motion:reduce){*{transition:none !important}}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
	.surf{background:var(--surf-solid)}
}
