/* cheatsheet.life family look (Create.Websites goal 3406, Ian 2026-10-06). ONE definition of the visual language the hub
   (www.cheatsheet.life) shares with its product sites (inventory.cheatsheet.life), so they cannot drift.
   Canonical copy: buckets/TEMPLATE/css-lib/cheatsheet-life.css. A site links /css-lib/cheatsheet-life.css after Bulma and
   before its own sheet; seed_lib_files copies a missing one, and testCheatsheetFamilyLook reds on a bucket copy that is not
   byte-identical to TEMPLATE's: edit TEMPLATE, then `cp -p` it into every site that links it. A site's own sheet adds its
   page layout; it never restyles a button, tab, tile or list row defined here.
   Rulings (context: websites/life.cheatsheet.www/look.md):
   - a button's colour says what pressing it does: black (.is-primary) = the click changes data (save, sign up, sign in,
     add, delete); white (a plain .button, or a link styled as one) = it goes somewhere or only changes the page; grey =
     disabled, whatever the role. No other colour on a button (goal 3393).
   - the selected tab and every tile are #EEE, so checkboxes and white buttons stand out against them; the tab track is
     white so the #EEE tab is set apart from it (goal 3394).
   - a list draws its separator between items only, never under the last one (goal 3398).
   Monochrome after Create.Websites designs/DESIGN_Ui.md: hairline borders, pill controls, red only in an error message.
   No inline styles (CSP). Geist is not self-hosted: the stack falls back to Inter, then the system sans.
   Spacing: the root is 16px so every Bulma rem lands on a 4px grid; text stays 14px. */

:root, [data-theme=light], .theme-light {
  color-scheme: light;
  --ink: #0a0a0a; --ink-soft: #171717; --mid-gray: #737373; --hairline: #e5e5e5; --rule: #d4d4d4;
  --canvas: #f5f5f5; --paper: #ffffff; --surface-alt: #fafafa; --ember: #e7000b;
  --tile: #eeeeee;
  --card-shadow: 0 0 0 1px rgba(23, 23, 23, 0.05), 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);

  --bulma-family-primary: 'Geist', 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --bulma-body-size: 16px; --bulma-body-font-size: 14px; --bulma-size-normal: 0.875rem;
  --bulma-scheme-h: 0; --bulma-scheme-s: 0%;
  --bulma-scheme-main-l: 100%; --bulma-scheme-main-bis-l: 98%; --bulma-scheme-main-ter-l: 96%;
  --bulma-scheme-invert-l: 4%; --bulma-background-l: 96%;
  --bulma-body-background-color: var(--canvas);
  --bulma-text: var(--ink); --bulma-text-strong: var(--ink); --bulma-text-weak: var(--mid-gray);
  --bulma-border: var(--hairline); --bulma-border-weak: var(--hairline);
  --bulma-primary-h: 0deg; --bulma-primary-s: 0%; --bulma-primary-l: 4%; --bulma-primary-invert-l: 98%; --bulma-primary-on-scheme-l: 4%;
  --bulma-link-h: 0deg; --bulma-link-s: 0%; --bulma-link-l: 4%; --bulma-link-invert-l: 98%; --bulma-link-on-scheme-l: 4%;
  --bulma-danger-h: 357deg; --bulma-danger-s: 100%; --bulma-danger-l: 45%; --bulma-danger-invert-l: 100%; --bulma-danger-on-scheme-l: 45%;
  --bulma-radius-small: 6px; --bulma-radius: 18px; --bulma-radius-medium: 10px; --bulma-radius-large: 24px;
  --bulma-control-radius: 18px; --bulma-control-radius-small: 18px; --bulma-input-radius: 18px; --bulma-tag-radius: 18px;
  --bulma-box-radius: 24px; --bulma-notification-radius: 18px;
  --bulma-shadow: var(--card-shadow); --bulma-box-shadow: var(--card-shadow);
}

/* ── type ───────────────────────────────────────────────────────── */
body { font-weight: 400; line-height: 1.43; color: var(--ink); }
a { color: var(--ink); }
a:hover { color: var(--ink-soft); text-decoration: underline; }
p a:not(.button), .help a { text-decoration: underline; text-underline-offset: 2px; }   /* a link inside running text reads as one */
.title { font-weight: 600; color: var(--ink); font-size: 30px; line-height: 1.2; letter-spacing: -0.025em; }
.title:not(:last-child), .title:not(.is-spaced):has(+ .subtitle) { margin-bottom: 12px; }   /* one gap under a page title, whatever follows it */
h2.subtitle { font-size: 18px; line-height: 1.56; font-weight: 600; color: var(--ink); margin-top: 32px; }
h2.subtitle:not(:last-child) { margin-bottom: 12px; }
.title + h2.subtitle { margin-top: 0; }   /* a section heading right under the page title keeps the one title gap */
.subtitle.is-6 { font-size: 14px; color: var(--mid-gray); }
.subtitle.is-6:not(:last-child) { margin-bottom: 16px; }
.label { font-size: 14px; font-weight: 500; color: var(--ink); }
.caption { font-size: 12px; line-height: 1.33; letter-spacing: 0.05em; text-transform: uppercase; color: var(--mid-gray); }
.narrow, .container.narrow:not(.is-max-desktop):not(.is-max-widescreen) { max-width: 640px; margin-left: auto; margin-right: auto; }
.section { padding-top: 32px; }

/* ── buttons: the colour is the role ────────────────────────────── */
.button { border-radius: 18px; font-size: 14px; font-weight: 500; border-color: var(--hairline); background: var(--paper); color: var(--ink); box-shadow: none; }
.button:hover { background: var(--surface-alt); border-color: var(--rule); color: var(--ink); text-decoration: none; }
.button.is-small { font-size: 13px; border-radius: 18px; }
.button.is-primary { background: var(--ink); border-color: var(--ink); color: #fafafa; }
.button.is-primary:hover, .button.is-primary:focus { background: var(--ink-soft); border-color: var(--ink-soft); color: #fafafa; }
.button[disabled], .button[disabled]:hover, .button[disabled]:focus { background: var(--ink); border-color: var(--ink); color: #fafafa; opacity: 0.5; }
.buttons { gap: 8px; }

/* ── inputs ─────────────────────────────────────────────────────── */
.input, .textarea, .select select { background: var(--canvas); border-color: transparent; box-shadow: none; color: var(--ink); font-size: 14px; }
.input, .select select { border-radius: 18px; }
.textarea { border-radius: 18px; padding: 10px 14px; }
.input::placeholder, .textarea::placeholder { color: var(--mid-gray); }
.input:hover, .textarea:hover, .select select:hover { border-color: transparent; }
.input:focus, .textarea:focus, .select select:focus { background: var(--paper); border-color: var(--hairline); box-shadow: 0 0 0 3px rgba(10, 10, 10, 0.06); }
/* On a #EEE tile an input is white with a visible border, like the white buttons beside it. */
.formCard .input, .formCard .textarea, .formCard .select select, ul.rows .input, ul.rows .select select { background: var(--paper); border-color: var(--rule); }
.formCard .input:focus, .formCard .textarea:focus, .formCard .select select:focus, ul.rows .input:focus, ul.rows .select select:focus { border-color: var(--mid-gray); }
.input:disabled, .select select:disabled { opacity: 0.6; }
.select:not(.is-multiple):not(.is-loading)::after { border-color: var(--mid-gray); }
.checkbox input[type=checkbox], input[type=checkbox] { accent-color: var(--ink); }
.help { color: var(--mid-gray); font-size: 12px; }
@media (max-width: 768px) { .input, .textarea, .select select { font-size: 16px; } } /* no iOS zoom on focus */
/* A sneaky box (goal 5006, Ian 2026-11-14: "Across all products, when a textbox or textarea is meant to be sneaky-editable, and the field is not
   selected, change the background to be #F7F7F7 and change the placeholder text color to be #AAAAAA."): a text box or text area the member edits in
   place (.sneaky, or a title's .titleName) is #F7F7F7 behind, its placeholder #AAAAAA, until it is selected; selected, its product's look (white, a
   line). A product's sheet places a sneaky box and draws its edge, never this fill: the products' sheets load after this one and set it transparent,
   hence !important. Green (.saved) and red (.refused) still show over it; a read-only or disabled box is not one to edit. */
:is(input, textarea):is(.sneaky, .titleName):not(:focus, .saved, .refused, [readonly], :disabled, [type="checkbox"], [type="radio"]) { background-color: #F7F7F7 !important; }
:is(input, textarea):is(.sneaky, .titleName):not(:focus)::placeholder { color: #AAAAAA !important; }

/* ── badges ─────────────────────────────────────────────────────── */
.tag { border-radius: 18px; font-size: 12px; font-weight: 500; background: var(--canvas); color: var(--ink-soft); padding: 2px 8px; height: auto; }
a.tag:hover { background: var(--hairline); text-decoration: none; }

/* ── messages: red text on paper, never a chromatic fill ────────── */
.notification { background: var(--paper); border: 1px solid var(--hairline); color: var(--ink); box-shadow: var(--card-shadow); }
.notification.is-warning, .notification.is-danger { background: var(--paper); color: var(--ember); }
.notification.is-danger.is-light { color: var(--ink); }
.messageError:empty { display: none; }
/* A refusal, not a panel (goals 4193, 4201; Ian 2026-10-23: no panel saying what just happened, "if they're not [successful], then
   something on the page should be highlighted as to what's wrong"). A product's js/site.js refuse(): what the member used is
   outlined red (.refused) and one red sentence (.refusal) sits beside it: under its list row, at the foot of its form field, or
   after its buttons, its tile or the title. #message holds only why a page could not be read, in the same red. */
.refusal { color: var(--ember); font-size: 14px; }
p.refusal { margin-top: 8px; }
ul.rows > li > .refusal, .fieldRow > .refusal { flex: 1 0 100%; }
#message .refusal { margin: 0 0 16px; }
.button.refused, .select select.refused, input[type="checkbox"].refused, .input.refused:not(.sneaky):not(.titleName), .textarea.refused { outline: 2px solid var(--ember); outline-offset: 1px; }

/* ── header: the site's pill tabs left, the account pills right ─── */
.breadcrumb { font-size: 14px; }
.breadcrumb a { color: var(--mid-gray); }
.breadcrumb li.is-active a, .breadcrumb li:last-child a { color: var(--ink); }
.breadcrumb li + li::before { color: var(--mid-gray); content: "\203A"; }
.headerNavs { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 24px; }
.headerNavs > .tabs.pills { margin-bottom: 0; flex: 0 1 auto; min-width: 0; }
.headerNavs > .tabs.accountTabs { margin-left: auto; }
.tabs.accountTabs { justify-content: flex-end; }
.tabs ul { border-bottom: none; }
.tabs.pills ul { display: inline-flex; flex-grow: 0; flex-wrap: wrap; flex-shrink: 1; gap: 2px; padding: 3px; background: var(--paper); border: 1px solid var(--hairline); border-radius: 18px; }
.tabs.pills a { border: none; margin: 0; border-radius: 18px; padding: 5px 12px; color: var(--mid-gray); font-weight: 500; }
.tabs.pills a:hover { color: var(--ink); text-decoration: none; }
.tabs.pills li.is-active a { background: var(--tile); color: var(--ink); }
/* The home button is the favicon (goal 4789, Ian 2026-11-08: "Change all home buttons to just have the icon that is the current favicon"): the
   family script puts img.homeIcon in a home pill or breadcrumb that held words; a view may write it itself. As tall as a tab's words. */
.tabs.pills a > img.homeIcon, .breadcrumb a > img.homeIcon { display: block; width: 20px; height: 20px; }

/* ── a link to another product (goal 4200, Ian 2026-10-23: "Add a nice arrow icon within the button to the left of the "Village" text to hint
   that it'll be navigating to a different product. Make this same icon change to any link to other products across all the products") ── */
/* <a class="button toProduct" href="https://village.cheatsheet.life/" target="_blank" rel="noopener">Village</a>: an arrow out of a box before
   the words, one em square, drawn in the link's own colour (a mask over currentColor, so it follows the ink and its hover). */
.toProduct::before {
  content: ""; display: inline-block; flex: 0 0 auto; width: 1em; height: 1em; margin-right: 6px; vertical-align: -0.125em; background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 3H4.5A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5V9'/%3E%3Cpath d='M8 8l5-5M9.5 3H13v3.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 3H4.5A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5V9'/%3E%3Cpath d='M8 8l5-5M9.5 3H13v3.5'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain;
}

/* ── the grip that drags a row (goal 4733, Ian 2026-11-06: "I like the exact look of the 6 dots on the main page that visually indicate that things
   can be manually reordered ... They're allowed to be smaller, if the rows and font sizes are smaller ... But it should only look like a scaled up or
   down version of what's on this page") ── */
/* <span class="grip" role="button" tabindex="0" title="Drag to reorder"></span>, EMPTY (.dragHandle is the same grip under the hub's, process's and
   barter's name): Lucide's grip-vertical, six dots in two columns, as the hub's home drew it from its icon font (e0eb), now a mask over currentColor:
   grey, the ink under the pointer or the keyboard; one line tall, so a row keeps its height. 20px on a 14px row (the hub's home); its size follows the row's text, so a smaller row draws it
   smaller, never another shape. A product's sheet may place it (display, visibility, width, flex, margins, padding, grid, line-height, cursor) and
   set nothing else on it (testCheatsheetGrips). A sentence that names it (<span class="dragDots" role="img" aria-label="the grip"></span>, goal 3085)
   shows the same dots at the sentence's size, in the ink so they read. */
.grip, .dragHandle { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; margin: 0; padding: 0 0.1em; border: 0; border-radius: 0.3em;
  background: none; color: var(--mid-gray); font-size: 1.4286em; line-height: 1; cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none; }
.grip:hover, .grip:focus-visible, .dragHandle:hover, .dragHandle:focus-visible { color: var(--ink); }
.grip::before, .dragHandle::before, .dragDots {
  content: ""; display: inline-block; flex: 0 0 auto; width: 0.4167em; height: 1em; background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='7 0 10 24' fill='black'%3E%3Ccircle cx='9' cy='5' r='2'/%3E%3Ccircle cx='15' cy='5' r='2'/%3E%3Ccircle cx='9' cy='12' r='2'/%3E%3Ccircle cx='15' cy='12' r='2'/%3E%3Ccircle cx='9' cy='19' r='2'/%3E%3Ccircle cx='15' cy='19' r='2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='7 0 10 24' fill='black'%3E%3Ccircle cx='9' cy='5' r='2'/%3E%3Ccircle cx='15' cy='5' r='2'/%3E%3Ccircle cx='9' cy='12' r='2'/%3E%3Ccircle cx='15' cy='12' r='2'/%3E%3Ccircle cx='9' cy='19' r='2'/%3E%3Ccircle cx='15' cy='19' r='2'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
}
.dragDots { margin: 0 0.1em; font-size: 1.4286em; vertical-align: middle; color: var(--ink); }

/* ── the page's foot (goals 4383, 4386, Ian 2026-10-27: "Change the Leave a comment link to look identical to how it's displayed in the other
   products (namely, the cheatsheet.life product) ... I want it to be changed to be centered on the page across all pages and products") ── */
/* <footer class="pageFooter"><a href="{{commentUrl}}" id="leaveCommentLink" class="toProduct">Leave a comment</a></footer>, last on every page:
   14px, underlined, in the ink, centred 48px under the page. A product's own sheet may repeat the size and the gap; none sets text-align. */
.pageFooter { margin-top: 48px; font-size: 14px; text-align: center; }
.pageFooter a { text-decoration: underline; text-underline-offset: 2px; }

/* ── tiles and list rows ────────────────────────────────────────── */
.card-surface, ul.rows, .formCard {
  background: var(--tile); border: 1px solid var(--hairline); border-radius: 24px; box-shadow: var(--card-shadow);
}
.formCard { padding: 20px; }
.formCard > :last-child { margin-bottom: 0; }
.formCard + .buttons, ul.rows + .buttons { margin-top: 16px; }   /* a tile's action buttons sit under it, on their own */
.formCard > p:not(:last-child) { margin-bottom: 12px; }
.formCard + .formCard, ul.rows + .formCard, .formCard + ul.rows { margin-top: 16px; }
ul.rows { list-style: none; margin: 0; padding: 4px 20px; }
ul.rows > li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 0; border-bottom: 1px solid var(--rule); }
ul.rows > li:last-child { border-bottom-color: transparent; }   /* between items only; every row keeps its height */
ul.rows > li:not(:has(~ li:not(.is-hidden))) { border-bottom-color: transparent; }   /* also the last row shown when a filter hides the rest (.is-hidden); its own rule, so no :has() keeps the one above */
.rowActions { margin-left: auto; display: inline-flex; gap: 6px; }
.where { color: var(--mid-gray); font-size: 13px; }
.empty { color: var(--mid-gray); font-style: italic; list-style: none; }

/* ── the day's colours (goal 3848, Ian 2026-10-13) ───────────────── */
/* The day bar itself (goal 3906, Ian 2026-10-14) has its own sheet, css-lib/day-bar.css, drawn by js-lib/cheatsheet-life.js; this
   sheet only names the four default colours it falls back to, and the swatch of a part beside its name below. */
:root { --day-night: #1f2a44; --day-morning: #f2c14e; --day-afternoon: #5fa8d3; --day-evening: #8e6bbf; }
/* A part's colour beside its name (schedule.cheatsheet.life's settings and day): <span class="dayPart is-morning"></span>. */
.dayPart { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; background: var(--day-night); }
.dayPart.is-morning { background: var(--day-morning); }
.dayPart.is-afternoon { background: var(--day-afternoon); }
.dayPart.is-evening { background: var(--day-evening); }

/* ── links on a thing's page (goal 4284; Ian 2026-10-25, goal 4276: "a single button will make that shortlist appear and each one can
   have a little add button next to it to create the association") ── */
/* js-lib/cheatsheet-life.js linkPanel draws it: the Links heading with Add a link on its right, the tied links in a tile (name, the open
   icon, a black x), then the shortlist under its caption (name, a black Add, the filled star). The two icons are masks over currentColor,
   as .toProduct's arrow: links' open icon and its star, 18px in a 32px round target that turns white on hover. Every rule is scoped
   to .linkPanel: the links site has a .linkName of its own. */
.linkPanel { margin-top: 32px; }
.linkPanel[hidden], .linkPanel [hidden] { display: none !important; }
.linkPanel .linkHead { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
.linkPanel .linkHead h2.subtitle { margin: 0; }
.linkPanel .linkFailed { color: var(--ember); font-size: 14px; }   /* why the links could not be read: .refusal's red, its own class so no product's clearRefusal takes it */
.linkPanel .linkName { flex: 1 1 0; min-width: 0; overflow-wrap: anywhere; }   /* a long address wraps beside its buttons, never pushes them under it */
.linkPanel .linkShortlist { margin-top: 16px; }
.linkPanel .linkShortlist .caption { margin-bottom: 8px; }
/* The add mode's row (the create option, goal 5010): a wide address box, its edge drawn (off a tile a family .input has none), and a
   black Add on its right; a refusal takes the line under them. */
.linkPanel .linkNew { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; }
.linkPanel .linkNew .input { flex: 1 1 12rem; min-width: 0; background: var(--paper); border-color: var(--rule); }
.linkPanel .linkNew .button { flex: 0 0 auto; }
.linkPanel .linkNew > .refusal { flex: 1 0 100%; }
.linkPanel .linkOpen, .linkPanel .linkStar { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 18px; background: none; color: var(--mid-gray); cursor: pointer; }
.linkPanel .linkOpen:hover, .linkPanel .linkStar:hover { color: var(--ink); background: var(--paper); text-decoration: none; }
.linkPanel .linkStar { color: var(--ink); }
.linkPanel .button.linkOff { min-width: 30px; }
.linkPanel .linkGlyph { display: inline-block; width: 18px; height: 18px; background-color: currentColor; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain; }
.linkPanel .linkGlyph.isOpen {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 3h6v6'/%3E%3Cpath d='M10 14 21 3'/%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 3h6v6'/%3E%3Cpath d='M10 14 21 3'/%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3C/svg%3E");
}
.linkPanel .linkGlyph.isStar {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M12 2.8l2.8 5.8 6.4.9-4.6 4.5 1.1 6.3L12 17.3l-5.7 3 1.1-6.3-4.6-4.5 6.4-.9z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M12 2.8l2.8 5.8 6.4.9-4.6 4.5 1.1 6.3L12 17.3l-5.7 3 1.1-6.3-4.6-4.5 6.4-.9z'/%3E%3C/svg%3E");
}

/* ── points (goal 4616; Ian 2026-11-04: "text like this “+<number>” That's green and glowing and it fades in and out as it moves up from whatever
   button or input element the user just interacted with. Maybe the put button turns green as well. [...] little butterflies [...] They would
   have to be little because I don't want them to be annoying [...] magical looking too, like little Tinkerbell kind of animations. maybe options
   can have a green border or a green hue to them") ── */
/* js-lib/cheatsheet-life.js draws them all under <html> (kushim draws <body> again), placed by the CSSOM, and none takes a click. Green is the one
   colour a button wears besides black, white and grey (goal 3393), and only for the moment after a write earned: .pointsEarned. */
.pointsFloat { position: fixed; z-index: 2147483000; pointer-events: none; white-space: nowrap; transform: translate(-50%, 0);
  font: 800 20px/1 var(--bulma-family-primary); letter-spacing: 0.02em; color: #22c55e;
  text-shadow: 0 0 1px #ffffff, 0 0 4px #86efac, 0 0 10px #22c55e, 0 0 20px rgba(34, 197, 94, 0.75);
  animation: pointsRise 1.9s cubic-bezier(0.2, 0.7, 0.3, 1) forwards; }
@keyframes pointsRise {
  0% { opacity: 0; transform: translate(-50%, 6px) scale(0.6); }
  15% { opacity: 1; transform: translate(-50%, -14px) scale(1.18); }
  30% { transform: translate(-50%, -24px) scale(1); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -78px) scale(0.96); }
}
.pointsEarned, .button.pointsEarned, .button.is-primary.pointsEarned, a.pointsEarned { background-color: #16a34a !important; border-color: #16a34a !important; color: #ffffff !important;
  box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.35), 0 0 16px rgba(34, 197, 94, 0.8) !important; transition: background-color 0.15s, box-shadow 0.15s; }
input.pointsEarned, textarea.pointsEarned, select.pointsEarned { background-color: #f0fdf4 !important; color: inherit !important; }
/* Goal 4976 (Ian 2026-11-14: "Mouseover color [...] the 4 colors used on the hint pop-up [...] The webpages should now reference these values instead of being hardcoded"): the edge and the hint read the
   colours admin.cheatsheet.life/fairies deploys into each product's /fairies/fairies.css (js-lib/cheatsheet-life.js links it), each falling back to the colour it always was. */
.pointsInvite { outline: 2px solid color-mix(in srgb, var(--fairy-mouseover-color, #22c55e) 60%, transparent); outline-offset: 2px;
  box-shadow: 0 0 10px color-mix(in srgb, var(--fairy-mouseover-color, #22c55e) 35%, transparent); }
.pointsTip { position: fixed; z-index: 2147483001; pointer-events: none; max-width: 280px; padding: 8px 12px; border-radius: 8px;
  background: var(--fairy-hint-background, #052e16); color: var(--fairy-hint-text, #f0fdf4); font-family: var(--bulma-family-primary); font-size: 13px; line-height: 1.4; text-align: left;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--fairy-hint-border, #22c55e) 70%, transparent), 0 4px 16px rgba(0, 0, 0, 0.25); }
.pointsTip .pointsTipHow { display: block; }
.pointsTip .pointsTipPay { display: block; margin-top: 4px; font-weight: 700; color: var(--fairy-hint-points, #4ade80); text-shadow: 0 0 6px color-mix(in srgb, var(--fairy-hint-points, #4ade80) 60%, transparent); }
/* Goal 4979: the pointer on the control invited (the fairies leave it, js-lib/cheatsheet-life.js): its edge the whole Mouseover color. */
.pointsInvite.fairyOver { outline-color: var(--fairy-mouseover-color, #22c55e); box-shadow: 0 0 12px color-mix(in srgb, var(--fairy-mouseover-color, #22c55e) 60%, transparent); }
/* The fairies (goal 4979, in place of goal 4616's butterfly): window.fairies.onPage lays one sheet the window's size over the page, under the hint and the "+N", taking no click; its two canvases (what
   flies behind the control, with the control's shape cut out of it, and what flies in front) and the glass on the control are placed by the script (CSSOM), nothing on the page moves. */
.fairyPage { position: fixed; inset: 0; z-index: 2147482999; pointer-events: none; overflow: hidden; }
.fairyPage > canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.fairyPage > .fairyGlass { position: absolute; pointer-events: none; opacity: 0; }
/* An account pill first in the account bar (goal 4785): a people icon, white, and its menu under it. */
.tabs.pills li.stubPill { display: flex; align-items: center; }
.stubToggle { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: none; border-radius: 18px;
  background: var(--paper); color: var(--mid-gray); cursor: pointer; }
.stubToggle:hover, .stubToggle:focus-visible, .stubToggle[aria-expanded="true"] { background: var(--tile); color: var(--ink); }
.stubIcon { display: block; width: 18px; height: 18px; background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='6' cy='5.5' r='2.5'/%3E%3Cpath d='M1.5 13.5c0-2.5 2-4.2 4.5-4.2s4.5 1.7 4.5 4.2'/%3E%3Cpath d='M10.5 3.2a2.4 2.4 0 0 1 0 4.6'/%3E%3Cpath d='M12 9.6c1.5.5 2.5 1.9 2.5 3.9'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='6' cy='5.5' r='2.5'/%3E%3Cpath d='M1.5 13.5c0-2.5 2-4.2 4.5-4.2s4.5 1.7 4.5 4.2'/%3E%3Cpath d='M10.5 3.2a2.4 2.4 0 0 1 0 4.6'/%3E%3Cpath d='M12 9.6c1.5.5 2.5 1.9 2.5 3.9'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain; }
.stubMenu { position: absolute; z-index: 1000; display: flex; flex-direction: column; gap: 2px; min-width: 160px; max-width: 280px; padding: 4px;
  background: var(--paper); border: 1px solid var(--hairline); border-radius: 12px; box-shadow: var(--card-shadow); }
.stubItem { position: relative; display: block; width: 100%; padding: 6px 12px 6px 28px; border: none; border-radius: 8px; background: var(--paper);
  color: var(--ink); font: inherit; font-size: 14px; line-height: 1.43; text-align: left; overflow-wrap: anywhere; cursor: pointer; }
.stubItem:hover, .stubItem:focus-visible { background: var(--tile); }
.stubItem.is-current { font-weight: 600; }
.stubItem.is-current::before { content: ""; position: absolute; left: 11px; top: 50%; width: 5px; height: 9px; border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor; transform: translateY(-65%) rotate(45deg); }
.stubMenu[aria-busy="true"] .stubItem { opacity: 0.5; pointer-events: none; }
.stubRefusal { margin: 0; padding: 2px 12px; font-size: 13px; color: var(--ember); }
.stubRefusal:empty { display: none; }

/* ── a feature request from any page (goal 4953; Ian 2026-11-14: "on every page across all products, to the right of the “Leave a comment” link,
   should be another link “Make a feature request”. When selected, the cursor changes to something different, which makes it seem like something is
   being selected. Now, when the user moves their mouse, all the elements that have a feature associated with it gets highlighted when moused over. If
   there is no element, then it highlights the whole page. The next click creates a pop-up") ── */
/* js-lib/cheatsheet-life.js puts a.featureRequestLink right after Leave a comment (signed in) and marks the foot .featureRequestFoot: the two links
   side by side, centred, each on a centred line of its own when the screen is too narrow for both. While picking: a crosshair everywhere, the box round
   what the pointer is on with its name over it (round the whole page on nothing that has an entry), the hint at the foot of the screen; then the
   pop-up. All of it under <html> (kushim draws <body> again), placed by the CSSOM, in the ink: the family is monochrome. */
.pageFooter.featureRequestFoot { display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 8px 24px; }
.featureRequestLink { cursor: pointer; }
html.featurePicking, html.featurePicking * { cursor: crosshair !important; }
html.featurePicking .featurePickHint, html.featurePicking .featurePickHint * { cursor: default !important; }
html.featurePicking .featurePickHint .featurePickStop { cursor: pointer !important; }
.featurePickBox { position: fixed; z-index: 2147483002; pointer-events: none; box-sizing: border-box; border: 2px solid var(--ink); border-radius: 10px;
  background: rgba(10, 10, 10, 0.06); box-shadow: 0 0 0 2px var(--paper), 0 0 0 5px rgba(10, 10, 10, 0.12); }
.featurePickBox.isPage { left: 0; top: 0; width: 100%; height: 100%; border-width: 4px; border-radius: 0; background: rgba(10, 10, 10, 0.03); box-shadow: inset 0 0 0 2px var(--paper); }
.featurePickName { position: absolute; left: -2px; bottom: 100%; max-width: min(320px, 90vw); margin-bottom: 6px; padding: 2px 10px; border-radius: 18px;
  background: var(--ink); color: #fafafa; font: 500 12px/1.6 var(--bulma-family-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.featurePickBox.isTop .featurePickName { bottom: auto; top: 100%; margin: 6px 0 0; }
.featurePickBox.isPage .featurePickName { left: 50%; top: 24px; bottom: auto; margin: 0; transform: translateX(-50%); }
.featurePickHint { position: fixed; z-index: 2147483003; left: 50%; bottom: 24px; transform: translateX(-50%); display: flex; align-items: center; gap: 12px;
  box-sizing: border-box; width: max-content; max-width: calc(100vw - 32px); padding: 6px 6px 6px 16px; border-radius: 24px; background: var(--ink); color: #fafafa;
  box-shadow: var(--card-shadow); font: 500 14px/1.43 var(--bulma-family-primary); }
.featurePickHint .featurePickStop { flex: 0 0 auto; padding: 4px 14px; border: none; border-radius: 18px; background: var(--paper); color: var(--ink); font: inherit; }
.featurePickHint .featurePickStop:hover, .featurePickHint .featurePickStop:focus-visible { background: var(--tile); }
.featureRequestShade { position: fixed; inset: 0; z-index: 2147483004; display: flex; align-items: flex-start; justify-content: center; box-sizing: border-box;
  padding: 12vh 16px 16px; overflow-y: auto; background: rgba(10, 10, 10, 0.35); }
.featureRequest { box-sizing: border-box; width: 100%; max-width: 480px; padding: 24px; border-radius: 24px; background: var(--paper);
  box-shadow: var(--card-shadow), 0 16px 48px rgba(0, 0, 0, 0.2); color: var(--ink); font-family: var(--bulma-family-primary); font-size: 14px; line-height: 1.43; text-align: left; }
.featureRequest .featureRequestTitle { margin: 0 0 4px; font-size: 18px; line-height: 1.56; font-weight: 600; color: var(--ink); }
.featureRequest .featureRequestAbout { margin: 0 0 16px; color: var(--mid-gray); overflow-wrap: anywhere; }
.featureRequest .field { margin: 0; }
.featureRequest .textarea { display: block; width: 100%; min-height: 104px; resize: vertical; }
.featureRequest .featureRequestButtons { margin: 16px 0 0; }
.featureRequest .featureRequestButtons .button { margin-bottom: 0; }
.featureRequest > .refusal { margin: 8px 0 0; }
@media (prefers-reduced-motion: reduce) {
  .pointsFloat { animation: pointsFade 1.9s ease-out forwards; transform: translate(-50%, -20px); }
  .fairyPage { display: none; }
}
@keyframes pointsFade { 0% { opacity: 0; } 15%, 70% { opacity: 1; } 100% { opacity: 0; } }
