/* The small things every page shares: where work stands, Undo, a file
   from anywhere, the star, the report panel, an application loading, and
   what the page looks like on paper and in a high-contrast mode.

   Loaded by every page after theme.css (details.mjs writes the link), and
   built from theme.css's tokens only: its type sizes, corners, durations
   and colours, so a colourway or a change to the system reaches these too.
   Motion is the site's: tokens, and a fade alone with motion switched
   down (:root[data-motion="none"]). */

/* ------------------------------------------------------------ where work stands

   Saved, Saving…, Not saved (OBSCURA.work). Quiet when all is well; the
   danger colour only when a save has failed, which is the one time the
   person has to act. */
.ob-save {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font: 600 var(--text-2xs)/1.35 var(--font-ui);
  /* ink-soft, not ink-faint: on Plan's dark panel the faint tone was 3.7:1,
     and at this size the line has to be read, not just noticed. */
  color: var(--ink-soft);
  white-space: nowrap;
}
.ob-save::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--good);
  flex: none;
}
.ob-save[data-save-state="saving"]::before { background: var(--ink-faint); animation: ob-breathe var(--dur-sweep) var(--ease-standard) infinite alternate; }
.ob-save[data-save-state="unsaved"]::before { background: var(--warn); }
.ob-save[data-save-state="kept"]::before { background: var(--accent); }
.ob-save[data-save-state="failed"] { color: var(--danger); }
.ob-save[data-save-state="failed"]::before { background: var(--danger); }
@keyframes ob-breathe { from { opacity: 1; } to { opacity: 0.35; } }
:root[data-motion="none"] .ob-save::before { animation: none; }
/* In an application's bar on a phone the words would push its search off
   the screen: the dot stays, and the words are still read out. Contacts'
   bar has no room even for the dot; a failed save there still says so in
   its own message at the foot of the window. */
@media (max-width: 600px) {
  :is(#tkSaveState, #pnSaveState, #calSaveState) { font-size: 0; gap: 0; }
  #ctSaveState { display: none; }
}

/* -------------------------------------------------------------------- Undo

   The button OBSCURA.undoable and a draft's offer put into the notice at
   the foot of the window. The notice is ink on paper turned over, so the
   button takes its colours from the notice rather than the page. */
#obscuraNotice .ob-undo {
  flex: none;
  align-self: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 1px solid currentColor;
  border-radius: var(--radius-md);
  background: transparent;
  color: inherit;
  font: 700 var(--text-sm)/1 var(--font-ui);
  cursor: pointer;
  transition: background-color var(--dur-2) var(--ease-standard);
}
#obscuraNotice .ob-undo:hover { background: color-mix(in srgb, currentColor 14%, transparent); }
#obscuraNotice .ob-undo.is-quiet { border-color: transparent; font-weight: 600; }
#obscuraNotice .ob-undo:focus-visible { outline: 2px solid currentColor !important; outline-offset: 2px !important; }
@media (max-width: 480px) {
  #obscuraNotice:has(.ob-undo) { flex-wrap: wrap; }
}

/* ------------------------------------------------------- a file from anywhere */
.ob-drop-page {
  position: fixed;
  inset: 0;
  z-index: 2147482000;
  display: grid;
  place-items: center;
  padding: var(--space-5);
  background: color-mix(in srgb, var(--paper) 86%, transparent);
  animation: ob-drop-in var(--dur-3) var(--ease-standard) both;
  --os-fade: var(--dur-fade);
}
.ob-drop-card {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  width: min(460px, 100%);
  padding: var(--space-7) var(--space-5);
  border: 2px dashed var(--accent-strong);
  border-radius: var(--radius-lg);
  background: var(--paper-raised);
  box-shadow: var(--elev-2);
  text-align: center;
  pointer-events: none;
}
.ob-drop-card svg { width: 40px; height: 40px; color: var(--accent-strong); }
.ob-drop-say { margin: 0; font: 700 var(--text-xl)/1.2 var(--font-display); color: var(--ink); }
.ob-drop-sub { margin: 0; font-size: var(--text-sm); color: var(--ink-soft); }
@keyframes ob-drop-in { from { opacity: 0; } }


/* Under a tool's options when they are as they were left (kit.js). */
.ob-opts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-3);
  margin: var(--space-3) 0 0;
  max-width: none;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--ink-soft);
}
.ob-opts-reset {
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--accent-strong);
  font: 600 var(--text-xs)/1 var(--font-ui);
  cursor: pointer;
}
.ob-opts-reset:hover { background: var(--paper-inset); }

/* The files last opened in this tool, by name (kit.js). Quiet: a line of
   names under the box, not a panel of its own. */
.ob-recent {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--ink-soft);
}
.ob-recent-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-3);
  margin: 0;
  max-width: none;
}
.ob-recent-head > span:first-child { font-weight: 600; color: var(--ink); }
.ob-recent-note { color: var(--ink-faint); }
.ob-recent-clear {
  min-height: 44px;
  margin-left: auto;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--accent-strong);
  font: 600 var(--text-xs)/1 var(--font-ui);
  cursor: pointer;
}
.ob-recent-clear:hover { background: var(--paper-inset); }
.ob-recent-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.ob-recent-list li { min-width: 0; max-width: 100%; }
.ob-recent-name { color: var(--ink); font-weight: 500; overflow-wrap: anywhere; }
.ob-recent-when { color: var(--ink-faint); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* A saved result, to drag out (Chrome and Edge only). */
.ob-dragout {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  color: var(--ink-soft);
}
.ob-dragout-chip {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  max-width: 100%;
  padding: 0 var(--space-3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-md);
  background: var(--paper-raised);
  color: var(--ink);
  font: 600 var(--text-sm)/1.2 var(--font-mono);
  text-decoration: none;
  overflow-wrap: anywhere;
  cursor: grab;
}
.ob-dragout-chip:hover { border-color: var(--accent); }
.ob-dragout-chip:active { cursor: grabbing; }

/* What was saved: its name, its size to the byte and its SHA-256, and
   where it was made (kit.js). A record rather than a message, so it is
   set like the tool's own inset panels and stays until the next save. */
.ob-receipt {
  margin: var(--space-3) 0 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  background: var(--paper-inset);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--ink-soft);
}
.ob-receipt p { margin: 0; max-width: none; }
.ob-receipt p + p { margin-top: var(--space-2); }
.ob-receipt-head b { margin-right: var(--space-1); color: var(--good); }
.ob-receipt-name { color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }
.ob-receipt-size { font-variant-numeric: tabular-nums; }
.ob-receipt-hash { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); }
.ob-receipt-algo { font: 600 var(--text-2xs)/1 var(--font-mono); letter-spacing: 0.06em; color: var(--ink-soft); }
.ob-receipt-sum {
  flex: 1 1 18em;
  min-width: 0;
  font: 500 var(--text-xs)/1.5 var(--font-mono);
  color: var(--ink);
  word-break: break-all;
}
.ob-receipt-copy {
  flex: none;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-md);
  background: var(--paper-raised);
  color: var(--ink);
  font: 600 var(--text-xs)/1 var(--font-ui);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-standard);
}
.ob-receipt-copy:hover { border-color: var(--accent); }

/* --------------------------------------------------------------- your tools */
/* A star at the top right of a tool's heading, level with the tool's name
   above it. The heading keeps the room for it from the first paint, so
   the star arriving (details.js is deferred) moves nothing. */
body[data-kind="tool"] :is(.page-header, main):has(> h1.page-title) { position: relative; }
body[data-kind="tool"] :is(.page-header, main) > h1.page-title { padding-right: 40px; }
.ob-star {
  position: absolute;
  top: -14px;
  right: -12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  transition: color var(--dur-2) var(--ease-standard);
}
/* A tool whose heading sits straight in <main class="wrap"> rather than in a
   .page-header: the wrap's own padding (34px above, 22px at the sides, 16px
   on a phone; theme.css) lies between its edge and the heading, so the star
   is set in by the same amount. Without this it sat 48px above the name and,
   on a phone, 12px past the right edge of the screen. */
body[data-kind="tool"] > main.wrap > .ob-star { top: calc(34px - 14px); right: calc(22px - 12px); }
@media (max-width: 768px) {
  body[data-kind="tool"] > main.wrap > .ob-star { right: calc(16px - 12px); }
}
.ob-star.is-inline { position: static; margin: 0 0 var(--space-2) -12px; }
.ob-star svg { width: 17px; height: 17px; flex: none; }
.ob-star:hover { color: var(--ink); }
.ob-star:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }
.ob-star[aria-pressed="true"] { color: var(--accent-strong); }
.ob-star[aria-pressed="true"] svg { fill: currentColor; }
.ob-star[aria-pressed="true"] svg { animation: ob-star-land var(--dur-3) var(--ease-spring); }
@keyframes ob-star-land { from { transform: scale(var(--os-pop, 0.6)); } }

.ob-yours { margin: var(--space-4) 0 var(--space-6); }
.ob-yours > .boot-count { margin: 0; text-align: left; }
.ob-yours .boot-grid { margin-top: var(--space-3); }

/* The search's star and its line saying how to use it. */
.cp-star {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: -8px -6px -8px 0;
  border-radius: var(--radius-md);
  color: var(--ink-faint);
  cursor: pointer;
}
.cp-star svg { width: 18px; height: 18px; }
.cp-star.is-on { color: var(--accent-strong); }
.cp-star.is-on svg { fill: currentColor; }
.cp-star:hover { color: var(--accent-strong); background: var(--paper-inset); }
/* Said to a screen reader when a star is pressed; nothing to see, since
   the star itself changes. */
.cp-said { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* --------------------------------------------------------- report a problem */
.ob-report {
  /* Centred in the window, which a page's own reset of margins undoes. */
  margin: auto;
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px);
  padding: var(--space-5);
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: var(--elev-2);
  overflow: auto;
}
.ob-report h2 { margin: 0 44px var(--space-2) 0; font: 700 var(--text-xl)/1.2 var(--font-display); }
.ob-report p { margin: 0 0 var(--space-3); font-size: var(--text-sm); line-height: var(--leading-prose); color: var(--ink-soft); }
.ob-diag {
  margin: 0 0 var(--space-4);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--paper-inset);
  color: var(--ink);
  font: var(--text-xs)/1.6 var(--font-mono);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  user-select: all;
}
.ob-report-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.ob-report .ob-report-row > a,
.ob-report .ob-report-row > button {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  font: 600 var(--text-sm)/1 var(--font-ui);
  text-decoration: none;
  cursor: pointer;
}
.ob-report .ob-report-row > a.btn-primary { background: var(--accent-strong); }
.ob-report-said { min-height: 1.6em; margin: var(--space-2) 0 0 !important; }
.ob-report-x {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--ink-soft);
  font-size: var(--text-xl);
  line-height: 1;
  cursor: pointer;
}
.ob-report-x:hover { background: var(--paper-inset); color: var(--ink); }

/* ---------------------------------------------------- an application loading

   The Photo Editor, the Engineering Suite, PDF Studio and Case, while
   their code arrives (pro-load.js). Their window is already drawn and
   cannot do anything yet, which on a slow connection looks like buttons
   that do not work; so the window stays in view, dimmed and out of reach,
   with a card over it: a bar that fills as the files do where there are
   several to count, and a bar that only says it is working where there is
   one large file and nothing honest to count. It waits --dur-wait before
   it shows, as .os-skel does, so a start from the device's own copy never
   flashes it, and it goes when the application starts. */
.os-appload {
  position: fixed;
  inset: 0;
  z-index: 2147481000;
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--paper) 62%, transparent);
  opacity: 0;
  animation: ob-appload-in var(--dur-3) var(--ease-standard) var(--dur-wait) forwards;
  --os-fade: var(--dur-fade);
}
:root[data-motion="none"] .os-appload { animation-delay: var(--dur-wait) !important; }
@keyframes ob-appload-in { to { opacity: 1; } }
.os-appload-card {
  display: grid;
  gap: var(--space-3);
  width: min(420px, 100%);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: var(--elev-2);
}
.os-appload-name { margin: 0; font: 700 var(--text-lg)/1.3 var(--font-display); color: var(--ink); }
.os-appload-say { margin: 0; font-size: var(--text-sm); color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.os-appload-bar {
  display: block;
  width: 100%;
  height: 6px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--paper-inset);
  overflow: hidden;
  appearance: none;
}
.os-appload-bar::-webkit-progress-bar { background: var(--paper-inset); border-radius: var(--radius-pill); }
.os-appload-bar::-webkit-progress-value { background: var(--accent-strong); border-radius: var(--radius-pill); transition: width var(--dur-3) var(--ease-standard); }
.os-appload-bar::-moz-progress-bar { background: var(--accent-strong); border-radius: var(--radius-pill); }
/* Nothing to count: the waiting tint and its light (theme.css's .os-skel),
   bar-shaped. */
.os-appload-card .os-skel { height: 6px; border-radius: var(--radius-pill); opacity: 1; animation: none; }
:root[data-pro-code="on"] .os-appload,
:root[data-pro-code="locked"] .os-appload,
:root[data-pro-code="refused"] .os-appload { display: none; }

/* A heavy library a tool fetches the first time (OCR, raw, PSD): a bar in
   the tool's own status line, from OBSCURA.loading in kit.js. */
.ob-libload { display: grid; gap: var(--space-1); margin: var(--space-2) 0; font-size: var(--text-xs); color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.ob-libload progress { width: 100%; height: 6px; appearance: none; border: 0; border-radius: var(--radius-pill); background: var(--paper-inset); overflow: hidden; }
.ob-libload progress::-webkit-progress-bar { background: var(--paper-inset); }
.ob-libload progress::-webkit-progress-value { background: var(--accent-strong); }
.ob-libload progress::-moz-progress-bar { background: var(--accent-strong); }

/* ------------------------------------------------------------------ paper

   A guide, the help, /pro, a tool's result or a report, printed: the words
   and the result, in dark ink on white whatever the colourway or mode,
   with none of the site around them. Three layers, each narrower:

     every page     white paper and dark ink, and the bar, the footer, the
                    notices and the panels this sheet draws taken away.
     a tool         its controls go too: a button, a box to drop a file
                    on, a sample to try. Not the applications (Docs, PDF,
                    the Photo Editor and the rest), and not a tool that
                    lays out its own sheet (labels, a CV, a badge), which
                    each print a page of their own with their own rules.
     a page to read where the pages break, and the address after a link in
                    running prose, since paper cannot be clicked. */
@media print {
  html:root:root:root:root {
    color-scheme: light;
    --paper: white !important;
    --paper-raised: white !important;
    --paper-inset: rgb(244 244 244) !important;
    --card-bg: white !important;
    --ink: black !important;
    --ink-soft: rgb(51 51 51) !important;
    --ink-mid: rgb(51 51 51) !important;
    --ink-faint: rgb(85 85 85) !important;
    --rule: rgb(204 204 204) !important;
    --rule-strong: rgb(153 153 153) !important;
    --hairline: rgb(204 204 204) !important;
    --hairline-strong: rgb(153 153 153) !important;
    --elev-1: none !important;
    --elev-2: none !important;
  }
  /* A dark mode's accent is a light tint, pale on white paper. */
  html:root:root:root:root[data-theme="dark"] {
    --accent: rgb(31 63 166) !important;
    --accent-strong: rgb(31 63 166) !important;
    --accent-soft: rgb(228 234 248) !important;
    --good: rgb(58 113 73) !important;
    --danger: rgb(166 67 47) !important;
    --warn: rgb(126 88 18) !important;
    /* The tints behind a warning, a verdict or a good result are dark in
       a dark mode, and printed as a dark box with dark words in it. */
    --good-soft: rgb(217 234 221) !important;
    --danger-soft: rgb(240 218 211) !important;
    --warn-soft: rgb(246 235 213) !important;
  }
  html, body { background: white !important; color: black !important; }

  .os-topbar, .os-footer, .boot-foot, .skip-link, .os-share, #obLicenceNote,
  #obscuraNotice, #cpWipeArm, #cpOverlay, #ppFile, .ob-drop-page, .ob-dragout, .ob-star, .ob-yours,
  .os-appload, .ob-report, .boot-search, .os-faq-link, .os-rel, #osToolNav, .gd-anchor, .boot-jump, .os-motion-offer, .os-letters,
  #ppBadge, .os-tour-offer, [id$="TourOffer"], [id$="CoachOffer"], #calFab, .os-speak, #obscura-save-notice {
    display: none !important;
  }

  body[data-kind="tool"]:not([class*="-app"]) main :is(button, [role="button"], input[type="file"], .ob-sample, .ob-next, .ob-libload, [data-drop]) {
    display: none !important;
  }

  body:not([data-kind="tool"]) main :is(h1, h2, h3, h4) { break-after: avoid; page-break-after: avoid; }
  body:not([data-kind="tool"]) main :is(table, figure, pre, blockquote, img, svg, .panel, .card, tr) { break-inside: avoid; page-break-inside: avoid; }
  body:not([data-kind="tool"]) main :is(p, li) { orphans: 3; widows: 3; }
  body:not([data-kind="tool"]) main thead { display: table-header-group; }
  body:not([data-kind="tool"]) main :is(button, [role="button"]) { display: none !important; }
  body:not([data-kind="tool"]) main :is(p, li, dd, td) a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    color: rgb(85 85 85);
    overflow-wrap: anywhere;
  }
  body:not([data-kind="tool"]) main :is(p, li, dd, td) a[href^="/"]:not([href="/"])::after {
    content: " (obscuraos.com" attr(href) ")";
    font-size: 0.85em;
    color: rgb(85 85 85);
    overflow-wrap: anywhere;
  }
  body:not([data-kind="tool"]) main a { color: black !important; text-decoration: underline; }
}

/* ----------------------------------------------- Windows high-contrast mode

   With forced colours on, the system replaces every colour and removes
   every shadow, so anything that was shown by a fill or a shadow alone
   needs a line the system can colour: a card, a page, a list, an event, a
   button with no border of its own, a focus ring drawn as a shadow, and a
   selected tab or row, which is marked with an outline in Highlight (an
   outline, not a fill, so the words inside keep the system's colours and
   stay readable). System colour names only: Highlight for what is
   selected, CanvasText for edges, ButtonText for controls. Found by
   drawing each application with forced colours emulated and looking for
   surfaces with nothing but a fill (details-test.mjs keeps them). */
@media (forced-colors: active) {
  :focus-visible, *:focus-visible { outline: 2px solid Highlight !important; outline-offset: 2px !important; }

  /* Surfaces that were a fill or a shadow. */
  .panel, .card, .boot-tile, .os-row, .ob-report, .ob-drop-card, #obscuraNotice, .ob-dragout-chip, .ob-receipt, .os-topbar, .os-nav-tabs,
  .tk-list, .tk-card, .tk-board-head, .doc-sheet, .slide-frame, .slide-thumb, .thumb-frame, .tg-event, .event-pill,
  .ec-card, .pe-panel, .pe-coach-card, .eng-vgroup, .eng-coach-offer, .fd-empty, .ps-drop, .pdf-stage canvas, .pe-home-thumb {
    border: 1px solid CanvasText !important;
  }
  /* A control drawn as a filled shape with no border: the system draws the
     words, so the shape needs an edge to read as something to press. */
  :is(button, [role="button"], .btn, .btn-primary, .btn-secondary, .btn-pro, .btn-search, .btn-settings, .btn-signin, .btn-account) {
    border-style: solid !important;
    border-width: 1px !important;
    border-color: ButtonText !important;
  }

  /* What is selected: a tab, a row, an option, a pressed toggle. */
  .nav-tab-btn.active, [aria-selected="true"], [aria-current="page"], [aria-pressed="true"],
  :is(a, button, li, summary, [role], [tabindex], [class*="row"], [class*="tab"], [class*="item"], [class*="day"]):is(.on, .active, .is-on, .is-active, .selected, .is-selected, .in-range) {
    outline: 2px solid Highlight !important;
    outline-offset: -2px !important;
  }
  .ob-star[aria-pressed="true"] svg, .cp-star.is-on svg { fill: Highlight; }

  /* Small marks that were colour alone. */
  .ob-save::before { forced-color-adjust: none; background: CanvasText; }
  .ob-save[data-save-state="failed"]::before, .ob-save[data-save-state="unsaved"]::before, .ob-save[data-save-state="kept"]::before { background: Mark; }
  .os-skel { border: 1px dashed CanvasText; }
  .os-appload-bar, .ob-libload progress { border: 1px solid CanvasText; }
  .os-appload-bar::-webkit-progress-value, .ob-libload progress::-webkit-progress-value { background: Highlight; }
  .os-appload-bar::-moz-progress-bar, .ob-libload progress::-moz-progress-bar { background: Highlight; }
  dialog::backdrop { background: rgb(0 0 0 / 0.6); }
}

/* The line under a free tool naming the application of the site's own
   that does the same work at full size (app-bridge.mjs). A sentence, not
   a box: the page's quiet type under a hairline, so it reads as a note. */
.os-bridge {
  max-width: 700px;
  margin: var(--space-7) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--rule);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.os-bridge a { color: var(--ink); font-weight: 500; text-decoration: underline; text-decoration-color: var(--rule-strong); text-underline-offset: 0.18em; }
.os-bridge a:hover { color: var(--accent); text-decoration-color: currentColor; }
/* The question is what the reader is asked, in the ink of the page; the
   price closes the sentence in the same quiet tone as the rest, so the
   line says what it costs without shouting it. */
.os-bridge-lead { color: var(--ink); font-weight: 600; }
.os-bridge-price { font-variant-numeric: tabular-nums; }
/* Inside a window of the desktop the page is the tool and nothing else
   (theme.css hides the line in a <main>; FORMS's main region is a div). */
html[data-in-os] body[data-kind="tool"] .os-bridge { display: none; }
@media print { .os-bridge { display: none; } }

/* ----------------------------------------------------------- how it works
   The reading that used to sit above and below a free tool, in one fold
   under it, shut (tool-fold.mjs). The summary is a quiet row between two
   hairlines; opened, the panels inside it lose their boxes and read as
   plain prose at the measure of a paragraph. */
.tool-about { max-width: 700px; margin: var(--space-6) 0 0; border-top: 1px solid var(--rule); }
.tool-about > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 48px;
  list-style: none;
  cursor: pointer;
  font: 600 var(--text-sm)/1.3 var(--font-ui);
  color: var(--ink-soft);
}
.tool-about > summary::-webkit-details-marker { display: none; }
.tool-about > summary::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin: 0 4px 0 2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--dur-2) var(--ease-standard);
}
.tool-about[open] > summary::before { transform: rotate(45deg); }
.tool-about > summary:hover { color: var(--ink); }
.tool-about > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }
.tool-about-body { padding: 0 0 var(--space-5); font-size: var(--text-sm); line-height: var(--leading-prose, 1.65); color: var(--ink); }
.tool-about-body > :is(.panel, .card, section, div) { margin: 0 0 var(--space-5); padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.tool-about-body :is(h2, h3) { margin: var(--space-4) 0 var(--space-2); font: 600 var(--text-md)/1.35 var(--font-ui); letter-spacing: 0; }
.tool-about-body > :first-child, .tool-about-body > :first-child > :first-child { margin-top: 0; }
.tool-about-body p, .tool-about-body li { max-width: var(--measure, 68ch); }
.tool-about-body p { margin: 0 0 var(--space-3); }
.tool-about-body :is(ul, ol) { margin: 0 0 var(--space-3); padding-left: 1.2em; }
.tool-about-body .os-intro { margin: 0 0 var(--space-4); font-size: inherit; color: inherit; }
.tool-about-body a { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 2px; }
/* The application's line follows the fold, under the fold's own hairline. */
.tool-about + .os-bridge { margin-top: 0; border-top: 1px solid var(--rule); }
html[data-in-os] .tool-about { display: none; }
@media print { .tool-about { display: none; } }
