/*
  Visual direction: the packing table.
  Type is monospace wherever the page shows data a seller has to scan - counts,
  order IDs, page numbers, sizes - because that is the vernacular of manifests,
  thermal receipts and barcodes. Prose is set in the system sans.
  The one bold element is the crop-mark frame: four registration ticks that
  bracket the drop zone and every detected label. It is the thing the tool does.
*/

/*
 * The hidden attribute must always win.
 *
 * The browser's own rule is `[hidden] { display: none }`, which any class
 * setting `display` outranks - so an element marked hidden in the markup stays
 * on screen the moment it also carries a layout class. That put a receipt with
 * em-dashes where the plan name should be in front of a seller who had just
 * paid, and it is the same trap as an invisible overlay that still swallows
 * taps. There are 166 display rules in this stylesheet; auditing them one by
 * one would fix today's instance and none of the next ones.
 *
 * !important is right here. This is not styling, it is the meaning of the
 * attribute, and there is no case where markup says hidden and we want it
 * seen. Anything that needs to animate out uses a class instead.
 */
[hidden] { display: none !important; }


:root {
  --paper:   #e9edf0;
  --card:    #ffffff;
  --ink:     #0d1b2a;
  --ink-2:   #5a6b7b;
  --ink-3:   #8c9ba8;
  --rule:    #c9d3db;
  --rule-2:  #dde4e9;
  --shimmer: rgba(255, 255, 255, 0.7);
  --signal:  #d62246;
  --ok:      #1e7a5a;
  --warn:    #9a6700;

  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  --step: 4px;
  --radius: 3px;
}

/*
  The theme does not follow the operating system. Sellers print from this in
  daylight and the tool pages are documents, so light is the default and dark is
  an explicit choice, remembered per browser. All dark values live under
  [data-theme="dark"] below.
*/

/* Explicit theme choice beats the OS preference, in both directions. The same
   tokens as above, so components never need to know which theme is active. */
:root[data-theme="dark"] {
    --paper:  #0b1218;
    --card:   #131c24;
    --ink:    #e6edf3;
    --ink-2:  #9fb0bd;
    --ink-3:  #6b7c8a;
    --rule:   #2a3742;
    --rule-2: #1e2933;
    --shimmer: rgba(255, 255, 255, 0.07);
    --signal: #ff5a72;
    --ok:     #4bbf8f;
    --warn:   #d4a017;
}
:root[data-theme="light"] {
  --paper:   #e9edf0;
  --card:    #ffffff;
  --ink:     #0d1b2a;
  --ink-2:   #5a6b7b;
  --ink-3:   #8c9ba8;
  --rule:    #c9d3db;
  --rule-2:  #dde4e9;
  --shimmer: rgba(255, 255, 255, 0.7);
  --signal:  #d62246;
  --ok:      #1e7a5a;
  --warn:    #9a6700;

  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  --step: 4px;
  --radius: 3px;
}

* { box-sizing: border-box; }

/* A panel wider than the screen must not make the whole page scroll
   sideways - on a phone that reads as the layout being broken. */
body { overflow-x: clip; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ---------- structural type ---------- */

.eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 8px;
}
.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}
.eyebrow .num { color: var(--signal); font-weight: 700; }

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------- shell ---------- */

.masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 24px;
  border-bottom: 1px solid var(--rule);
  background: var(--card);
}

.wordmark {
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin: 0;
}
.wordmark .bars {
  color: var(--signal);
  letter-spacing: -1px;
  margin-left: 6px;
}

.masthead p { margin: 0; font-size: 13px; color: var(--ink-2); }

.layout {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  gap: 0;
  align-items: stretch;
  min-height: calc(100vh - 140px);
}

.controls {
  border-right: 1px solid var(--rule);
  background: var(--card);
  padding: 20px 22px 40px;
  /* Full height and pinned: the rail should read as a side of the app, not as
     a card that runs out partway down the page. */
  align-self: start;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.stage { padding: 22px 26px 40px; min-width: 0; }

.block + .block { margin-top: 26px; }
.block > .eyebrow { margin-bottom: 12px; }

/* ---------- crop-mark frame: the signature ---------- */

.cropframe { position: relative; }
.cropframe::before,
.cropframe::after,
.cropframe > .tick-b::before,
.cropframe > .tick-b::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 2px solid var(--signal);
  transition: inset 160ms ease, opacity 160ms ease;
}
.cropframe::before      { top: -1px; left: -1px;  border-right: 0; border-bottom: 0; }
.cropframe::after       { top: -1px; right: -1px; border-left: 0;  border-bottom: 0; }
.cropframe > .tick-b::before { bottom: -1px; left: -1px;  border-right: 0; border-top: 0; }
.cropframe > .tick-b::after  { bottom: -1px; right: -1px; border-left: 0;  border-top: 0; }

/* ---------- drop zone ---------- */

.dropzone {
  aspect-ratio: 4 / 6;
  width: min(340px, 100%);
  margin: 4vh auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-align: center;
  padding: 24px;
  background: var(--card);
  border: 1px dashed var(--rule);
  cursor: pointer;
}
.dropzone:hover, .dropzone.is-over { border-color: var(--signal); }
.dropzone.is-over::before, .dropzone.is-over::after,
.dropzone.is-over > .tick-b::before, .dropzone.is-over > .tick-b::after { inset: auto; }
.dropzone.is-over::before { top: 7px; left: 7px; }
.dropzone.is-over::after  { top: 7px; right: 7px; }
.dropzone.is-over > .tick-b::before { bottom: 7px; left: 7px; }
.dropzone.is-over > .tick-b::after  { bottom: 7px; right: 7px; }

.dropzone h2 {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0;
}
.dropzone p { margin: 0; font-size: 13px; color: var(--ink-2); max-width: 24ch; }
.dropzone .ratio {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  letter-spacing: 0.1em;
}

.stage-intro { max-width: 46ch; margin: 0 auto; text-align: center; }
.stage-intro h1 {
  font-family: var(--mono);
  font-size: clamp(20px, 3vw, 28px);
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 10px;
}
.stage-intro p { color: var(--ink-2); margin: 0; }

/* ---------- file list ---------- */

.filelist { list-style: none; margin: 0; padding: 0; }
.filelist li {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule-2);
  font-size: 13px;
}
.filelist .fname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filelist .fpages { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

/* ---------- settings ---------- */

.setting {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 7px 0;
}
.setting label { font-size: 14px; cursor: pointer; }
.setting .hint { display: block; font-size: 12px; color: var(--ink-3); margin-top: 1px; }

/*
 * A .setting whose label needs something under it as well - the crop page's
 * "add this run to order scan check", where the full list of what leaves the
 * browser sits in a <details> that must not be inside the <label>, or its
 * summary would tick the box.
 */
.setting__body { min-width: 0; }
.carry-what > summary {
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
  margin-top: 4px;
  width: fit-content;
}
.carry-what > summary:hover { color: var(--ink); }
.carry-what .hint { margin-top: 4px; }
.setting input[type="checkbox"] { margin-top: 3px; accent-color: var(--signal); width: 15px; height: 15px; }

.setting-row { padding: 7px 0; }
.setting-row > span { display: block; font-size: 14px; margin-bottom: 5px; }

/*
 * `date` and `url` are in this list for the same reason `text` is: they sit in
 * the same form rails. Left out, a date field kept the browser's own look -
 * intrinsic width, no border, its own background - and was the one control on
 * the page that did not look like one.
 */
select, input[type="text"], input[type="number"],
input[type="date"], input[type="url"] {
  width: 100%;
  font: inherit;
  font-size: 14px;
  padding: 7px 9px;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
/*
 * The theme here is an explicit choice, not the OS preference - so the parts of
 * a date field the browser draws itself have to be told which one is active.
 * The calendar button and the picker come from color-scheme and not from our
 * `color`, so without this a dark page gets a black icon on a dark field.
 *
 * line-height is pinned because a date field's internal text box ignores
 * `normal` and comes out a few pixels shorter than the text inputs beside it.
 */
input[type="date"] { color-scheme: light; line-height: 1.25; }
:root[data-theme="dark"] input[type="date"] { color-scheme: dark; }
/*
 * :required gets no styling of its own, and :invalid gets none either.
 *
 * Safari's UA stylesheet draws a red glow around an empty required field from
 * the first paint - before anyone has touched it, which reads as an error
 * nobody made yet. Every error on this site is already said in words, through
 * .l-notice or a field's own .l-hint--bad, never through the browser's own
 * red ring - so this is a reset, not a design choice being overridden.
 */
input:invalid, select:invalid, textarea:invalid { box-shadow: none; }

/* ---------- buttons ---------- */

.btn {
  /*
   * inline-flex, because half of these are anchors.
   *
   * .btn set padding and .btn--full set a width, but nothing ever set a
   * display - so on a <button>, which is inline-block already, it worked, and
   * on an <a>, which is not, the width was ignored, the vertical margin was
   * ignored, and the padding was painted without making the line box any
   * taller. Seventy-eight anchors across thirty-nine pages were drawn that way
   * and all of them looked passable, because a landing page puts one button on
   * a line with room around it. app.html stacks two full-width ones, and there
   * the two boxes overlapped: "Android - get it on Google Play" was printed
   * through "iPhone - get it on the App Store".
   *
   * flex rather than inline-block so an icon beside a label is centred and
   * spaced by the gap, which is what download-fab.js was reaching for with its
   * own copy of these rules.
   */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* Same root cause as the display: an anchor brings its own underline, and
     every one of these was drawn with one through the label. */
  text-decoration: none;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 11px 16px;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--card);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.btn:hover:not(:disabled) { background: var(--signal); border-color: var(--signal); color: #fff; }
.btn:disabled { opacity: 0.35; cursor: not-allowed; }
.btn--full { width: 100%; }
/* Two stacked full-width buttons: the gap belongs to the group, not to an
   inline style on the second one. */
.btn--stack { display: grid; gap: 10px; }
.btn--quiet {
  background: transparent;
  color: var(--ink-2);
  border-color: var(--rule);
}
.btn--quiet:hover:not(:disabled) { color: var(--signal); border-color: var(--signal); background: transparent; }
.btn--tiny { padding: 4px 8px; font-size: 10px; }

:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }

/* ---------- stats strip ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-bottom: 22px;
}
.stat { background: var(--card); padding: 11px 13px; }
.stat b {
  display: block;
  font-family: var(--mono);
  font-size: 21px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.stat span {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---------- proof sheet ---------- */

.proof { display: block; }
.proofgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 18px;
}
.proofmore { display: block; margin: 20px auto 0; }
.proofmore.hidden { display: none; }

.thumb { background: var(--card); border: 1px solid var(--rule); padding: 9px; }
/* overflow:hidden is load-bearing: .cropmark dims the page with a 9999px
   box-shadow, which without clipping would darken the whole viewport once per
   thumbnail. */
.thumb .shot { position: relative; background: #fff; line-height: 0; overflow: hidden; }
.thumb canvas { width: 100%; height: auto; display: block; }
.thumb .meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 6px;
  margin-top: 7px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.badge { padding: 1px 5px; border: 1px solid currentColor; border-radius: 2px; }
.badge--label    { color: var(--ok); }
.badge--invoice  { color: var(--ink-3); }
.badge--combined { color: var(--warn); }
.badge--blank    { color: var(--signal); }

/* crimson rectangle showing exactly what will be kept */
.cropmark {
  position: absolute;
  border: 1.5px solid var(--signal);
  pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(13, 27, 42, 0.42);
}

/* ---------- manual crop editor ---------- */

.cropedit { background: var(--card); border: 1px solid var(--rule); padding: 16px; margin-bottom: 22px; }
.cropedit .surface {
  position: relative; display: inline-block; line-height: 0;
  cursor: crosshair; user-select: none; overflow: hidden;
}
.cropedit canvas { display: block; max-width: 100%; height: auto; }
.cropedit .hintbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-top: 12px;
  font-size: 13px; color: var(--ink-2);
}

/* ---------- notices ---------- */

.notice {
  border-left: 3px solid var(--signal);
  background: var(--card);
  padding: 10px 13px;
  font-size: 13px;
  margin-bottom: 16px;
}
.notice--ok { border-left-color: var(--ok); }

.progress { height: 3px; background: var(--rule); overflow: hidden; margin-top: 14px; }
.progress i { display: block; height: 100%; background: var(--signal); width: 0; transition: width 140ms linear; }
.progress-label { font-family: var(--mono); font-size: 11px; color: var(--ink-3); margin-top: 6px; letter-spacing: 0.06em; }

.privacy {
  font-size: 12px;
  color: var(--ink-3);
  border-top: 1px solid var(--rule-2);
  margin-top: 22px;
  padding-top: 12px;
}
.privacy b { color: var(--ink-2); font-weight: 600; }

/*
 * A link in the small print, styled - because nothing was styling it.
 *
 * .privacy is prose and some of it carries links: account.html points at Low
 * stock alert from here, and dashboard.html points at Order scan check. Both
 * were getting the browser's default blue, which is 2.01:1 against the dark
 * ground where 4.5:1 is the requirement - unreadable on exactly the theme most
 * of these pages are read in.
 *
 * --ink-2 rather than --signal: it clears 4.5:1 on both grounds in both themes
 * (8.46 and 7.73 dark, 4.66 and 5.49 light), where --signal is 4.27 against
 * light paper and would have been a new marginal case. The signal goes on the
 * underline and the hover instead, which is the pattern `.cat a` and
 * `.toolhead__crumbs a` already set - a link here should read as part of the
 * sentence it sits in, not as a button.
 */
.privacy a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--signal);
}
.privacy a:hover { color: var(--signal); }

/* A saved packing day that lost the file behind it. Same weight as the rest of
   the panel's small print, but coloured, because it is the one line here that
   asks the seller to do something. */
.privacy--warn {
  color: var(--warn);
  border-top-color: var(--warn);
  margin-top: 12px;
}

.hidden { display: none !important; }

@media (max-width: 860px) {
  .layout { grid-template-columns: 1fr; }
  .controls { position: static; max-height: none; border-right: 0; border-bottom: 1px solid var(--rule); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============================================================
   Site shell: masthead, menu, home, tools directory
   ============================================================ */

.masthead {
  position: relative;
  z-index: 20;
  gap: 8px 24px;
  align-items: center;
}

.brand { text-decoration: none; color: inherit; flex: none; }
.brand .wordmark { display: inline-flex; align-items: baseline; }

/* The old masthead menu (.menu / .menutoggle / .menupanel) was replaced by the
   l-* header built in ui/nav.js. Its rules are gone; the mobile drawer now
   lives with the rest of that header in landing.css. */
/* ---------- home ---------- */

.home { padding: 0 24px 72px; }

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 48px;
  align-items: center;
  padding: 56px 0 44px;
  border-bottom: 1px solid var(--rule);
}
@media (max-width: 860px) { .hero { grid-template-columns: 1fr; gap: 32px; } }

.hero h1 {
  font-family: var(--mono);
  font-size: clamp(26px, 4.2vw, 44px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 14px;
  max-width: 18ch;
}
.hero h1 em { font-style: normal; color: var(--signal); }
.hero p { margin: 0 0 22px; font-size: 16px; color: var(--ink-2); max-width: 52ch; }
.hero .cta { display: flex; gap: 10px; flex-wrap: wrap; }

/* A 4:6 label standing in for the thing the whole site is about. */
.herolabel {
  width: 208px;
  aspect-ratio: 4 / 6;
  background: var(--card);
  border: 1px solid var(--rule);
  padding: 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.herolabel .rule { height: 1px; background: var(--rule-2); }
.herolabel .line { height: 6px; background: var(--rule-2); border-radius: 1px; }
.herolabel .line.short { width: 55%; }
.herolabel .line.mid { width: 78%; }
.herolabel .barcode { display: flex; align-items: flex-end; gap: 2px; height: 52px; margin-top: auto; }
.herolabel .barcode i { display: block; flex: 1; background: var(--ink); height: 100%; }
.herolabel .barcode i:nth-child(3n) { opacity: 0.35; }
.herolabel .barcode i:nth-child(4n) { opacity: 0.7; }
.herolabel .cap {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.catgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-top: 40px;
}
.cat { background: var(--card); padding: 20px 20px 22px; }
.cat h2 {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0 0 4px;
}
.cat > p { margin: 0 0 14px; font-size: 13px; color: var(--ink-3); }
.cat ul { list-style: none; margin: 0; padding: 0; }
.cat li { padding: 4px 0; font-size: 13.5px; border-bottom: 1px solid var(--rule-2); }
.cat li:last-child { border-bottom: 0; }
.cat a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--signal); }
.cat a:hover { color: var(--signal); }
.cat .muted { color: var(--ink-3); }
.cat .more { font-family: var(--mono); font-size: 11px; color: var(--ink-3); padding-top: 8px; display: block; }

/* ---------- tools directory ---------- */

.directory { padding: 28px 24px 72px; }
.directory > h1 {
  font-family: var(--mono);
  font-size: clamp(22px, 3vw, 30px);
  letter-spacing: -0.01em;
  margin: 0 0 6px;
}
.directory > p.lede { margin: 0 0 30px; color: var(--ink-2); max-width: 62ch; }

.dirsection { margin-bottom: 34px; }
.dirsection > p { margin: 0 0 12px; font-size: 13px; color: var(--ink-3); }

.toolgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
.toolcard {
  background: var(--card);
  padding: 14px 15px 16px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  text-decoration: none;
  color: inherit;
  border-left: 2px solid transparent;
}
a.toolcard:hover { border-left-color: var(--signal); }
.toolcard h3 { margin: 0; font-size: 14.5px; font-weight: 600; }
.toolcard p { margin: 0; font-size: 12.5px; color: var(--ink-3); line-height: 1.45; }
.toolcard.is-soon h3 { color: var(--ink-2); }
.toolcard .tag {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: auto;
  padding-top: 8px;
}
.toolcard.is-live .tag { color: var(--ok); }
.toolcard .tag.needs-server { color: var(--warn); }



/* settings: inline number field and pasted-list box */
.setting-row--inline {
  display: grid;
  grid-template-columns: 1fr 72px auto;
  align-items: center;
  gap: 8px;
}
.setting-row--inline > span:first-child { margin-bottom: 0; }
.setting-row--inline input { width: 100%; }
.setting-row--inline .suffix { font-size: 13px; color: var(--ink-3); }
.setting-row--inline .hint { grid-column: 1 / -1; }

.setting-row textarea {
  width: 100%;
  font: inherit;
  font-family: var(--mono);
  font-size: 12px;
  padding: 7px 9px;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  resize: vertical;
}

/* a setting this document has no data for */
.setting.is-unavailable label { color: var(--ink-3); cursor: not-allowed; }
.setting.is-unavailable .hint { color: var(--warn); }

/* ---------- theme toggle ---------- */

.themetoggle {
  width: 36px;
  height: 36px;
  flex: none;
  display: grid;
  place-items: center;
  padding: 0;
  cursor: pointer;
  color: var(--ink-2);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 8px;
  transition: color 120ms ease, border-color 120ms ease;
}
.themetoggle:hover { color: var(--signal); border-color: var(--signal); }
.themetoggle svg { width: 17px; height: 17px; }

/*
 * Light, dark, system - three radio options rather than a flip.
 *
 * A flip cannot express the third one: there is no order in which the three
 * follow each other that anybody could predict, so pressing twice to get back
 * where you were stops being true the moment "system" is in the cycle.
 */
.themepick { position: relative; display: inline-flex; }
.thememenu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 80;
  min-width: 132px;
  display: grid;
  gap: 1px;
  padding: 5px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 8px 22px rgba(13, 27, 42, 0.14);
}
.themeopt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 9px;
  font: inherit;
  font-size: 13px;
  text-align: left;
  color: var(--ink-2);
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  cursor: pointer;
}
.themeopt:hover { background: var(--rule-2); color: var(--ink); }
.themeopt.is-on { color: var(--signal); font-weight: 650; }
/* The tick is drawn from the state, so it cannot disagree with aria-checked. */
.themeopt.is-on::after { content: "\2713"; font-family: var(--mono); }

/* ---------- recent files ---------- */

.histlist { list-style: none; margin: 0; padding: 0; }
.histlist li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--rule-2);
}
.histlist li:last-child { border-bottom: 0; }

.histmain { min-width: 0; flex: 1; }
.histname {
  display: block;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.histmeta {
  display: block;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-3);
  margin-top: 2px;
}
/* Today / Yesterday / Earlier, between the rows they head. */
.histday {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 8px 0 2px;
}
.histday:first-of-type { padding-top: 0; }

.histactions, .histask { display: flex; align-items: center; gap: 4px; flex: none; }

/*
 * The file that was just saved, at the top of the working area.
 *
 * Same two actions as a row in the recent-files panel, in the one place the
 * seller is already looking when the export lands - the panel itself sits
 * below every setting the tool has, which on the cropper is several screens
 * away from the button that made the file.
 */
.lastfile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  margin-bottom: 12px;
  border: 1px solid var(--ok);
  border-radius: var(--radius);
  background: var(--card);
}
.lastfile__main { min-width: 0; flex: 1 1 auto; }
.lastfile__tag {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ok);
  margin-right: 6px;
}
.lastfile__name {
  font-size: 13px;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.lastfile__meta {
  display: block;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-3);
  margin-top: 2px;
}

/*
 * Icon buttons, sized for a thumb rather than a mouse. 36px is the smallest
 * target that is reliably hit on a phone; the glyph inside stays small so the
 * row does not grow with it.
 */
.histbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: none;
  color: var(--ink-2);
  cursor: pointer;
}
.histbtn svg { width: 17px; height: 17px; }
.histbtn:hover { color: var(--ink); border-color: var(--rule); background: var(--paper); }
.histbtn:focus-visible { outline: 2px solid var(--signal); outline-offset: 1px; }
.histbtn[disabled] { opacity: 0.45; cursor: default; }
.histbtn--risk:hover { color: var(--signal); border-color: var(--signal); }

.histask__q {
  font-size: 12px;
  color: var(--ink-2);
  margin-right: 2px;
}

.linkish {
  font: inherit;
  font-size: inherit;
  padding: 0;
  border: 0;
  background: none;
  color: var(--signal);
  text-decoration: underline;
  cursor: pointer;
}
.linkish:hover { color: var(--ink); }

/* ---------- floating download button ---------- */

/*
 * Back in the corner it was always meant to have.
 *
 * It was lifted to 90px to clear the chat bubble, which sat on top of it. The
 * bubble is in the header now, so the corner is free and the one control that
 * produces the file the seller came for can have it.
 */
.fab {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 14px 20px;
  cursor: pointer;
  color: #fff;
  background: var(--signal);
  border: 1px solid var(--signal);
  border-radius: 100px;
  box-shadow: 0 6px 16px rgba(13, 27, 42, 0.18), 0 18px 40px rgba(13, 27, 42, 0.16);
  transition: transform 140ms ease, opacity 140ms ease, background 140ms ease;
}
.fab svg { width: 17px; height: 17px; }
.fab:hover:not(.is-off) { transform: translateY(-2px); background: var(--ink); border-color: var(--ink); }

/* Present but obviously inert until the page has produced something. */
.fab.is-off {
  cursor: not-allowed;
  opacity: 0.45;
  color: var(--ink-2);
  background: var(--card);
  border-color: var(--rule);
  box-shadow: 0 2px 8px rgba(13, 27, 42, 0.1);
}

@media (max-width: 620px) {
  .fab { right: 14px; bottom: 14px; padding: 13px 17px; font-size: 11px; }
}
@media (prefers-reduced-motion: reduce) {
  .fab { transition: none; }
  .fab:hover:not(.is-off) { transform: none; }
}


/* ---------- tool header ---------- */

.toolhead {
  background: var(--card);
  border-bottom: 1px solid var(--rule);
}
/*
  One row, not three stacked blocks. The tool is what the page is for; the
  header only has to say which tool this is and let you back out. The previous
  version spent ~130px of every screen on chrome above the controls.
*/
.toolhead__inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 9px 24px 10px;
  display: flex;
  align-items: baseline;
  gap: 4px 12px;
  flex-wrap: wrap;
}

.toolhead__crumbs { font-size: 12.5px; color: var(--ink-3); flex: none; }
.toolhead__crumbs a { color: var(--ink-2); text-decoration: none; }
.toolhead__crumbs a:hover { color: var(--signal); }
.toolhead__crumbs span { margin: 0 5px; opacity: 0.55; }

.toolhead__title {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0;
  flex: none;
}
.toolhead__lede {
  margin: 0;
  font-size: 12.5px;
  color: var(--ink-3);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The description is the first thing to go when the row gets tight. */
@media (max-width: 720px) { .toolhead__lede { display: none; } }

/* ---------- page picker, shared by the tools that pick pages ---------- */

.pagegrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 16px;
}
.pagecard { display: flex; flex-direction: column; gap: 7px; }

.pagecard__shot {
  position: relative;
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  line-height: 0;
}
.pagecard__shot canvas { width: 100%; height: auto; display: block; }

/* A dropped page stays on screen, greyed, so a mis-click is recoverable rather
   than a page silently disappearing from the grid. */
/* The page fades, its button does not. Dimming the whole shot took the undo
   button down with it, leaving a dropped page with no visible way back. */
.pagecard.is-out .pagecard__shot { border-style: dashed; }
.pagecard.is-out .pagecard__shot canvas { opacity: 0.3; filter: grayscale(1); }
.pagecard.is-out .pagecard__shot.is-waiting { opacity: 0.35; }
.pagecard.is-out .pagecard__cap { color: var(--ink-3); text-decoration: line-through; }

.pagecard__act {
  position: absolute;
  top: 6px; right: 6px;
  min-width: 24px; height: 24px;
  padding: 0 7px;
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  color: #fff;
  background: var(--signal);
  border: 0;
  border-radius: 100px;
  box-shadow: 0 1px 4px rgba(13, 27, 42, 0.3);
}
.pagecard__act:hover { background: var(--ink); }
.pagecard.is-out .pagecard__act { background: var(--ok); }

.pagecard__cap {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--ink-2);
  text-align: center;
}

.pagebar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule-2);
}
.pagebar__count {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-right: auto;
}

/* ---------- tool page footer ---------- */

.toolfoot {
  border-top: 1px solid var(--rule);
  background: var(--card);
  /* No top margin: the tool layout ends flush against it. A gap here showed a
     band of page background between the settings rail and the footer. */
  margin-top: 0;
}
.toolfoot__inner {
  max-width: 1200px;
  margin: 0 auto;
  /* One short row now that the promise paragraph has gone to the landing page,
     so it takes the height of a line of text rather than of a paragraph. */
  padding: 10px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
}


/*
 * .toolfoot__help is retired along with the footer WhatsApp link it styled -
 * see the note in nav.js's promise(). The floating button in whatsapp.js is
 * what every page uses now.
 */
.toolfoot__legal {
  font-size: 12.5px; color: var(--ink-3); text-decoration: none;
  padding: 9px 4px;
}
.toolfoot__legal:hover { color: var(--signal); text-decoration: underline; }

/* The old strip position is retired; the placeholder can stay empty. */
#site-promise:empty { display: none; }

/* several caveats about one file, in one box */
.notice__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.notice__list li { position: relative; padding-left: 14px; line-height: 1.5; }
.notice__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 8px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.4;
}

.proofnote {
  margin: 0 0 4px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  color: var(--ink-3);
}

/* ---------- loading ---------- */

/* A thumbnail that has not been drawn yet: a slow sweep so a waiting grid
   reads as "working" rather than as empty boxes. */
@keyframes shimmer {
  from { background-position: -160% 0; }
  to   { background-position: 260% 0; }
}
/* `.thumb .shot` sets a white ground at two-class specificity, so the waiting
   state has to match it or the sweep is cancelled out and a pending thumbnail
   looks like a finished blank page. */
.is-waiting,
.shot.is-waiting {
  min-height: 40px;         /* holds its space so the grid does not jump */
  /* A solid ground with the sweep passing over it. Putting both stops in the
     gradient let the pale one fill the box and the placeholder read as blank
     white paper rather than as something still loading. */
  background-color: var(--rule-2);
  background-image: linear-gradient(
    100deg,
    transparent 24%,
    var(--shimmer) 42%,
    transparent 60%
  );
  background-size: 220% 100%;
  animation: shimmer 1.5s linear infinite;
}

.spinner {
  display: inline-block;
  width: 13px;
  height: 13px;
  vertical-align: -2px;
  margin-right: 7px;
  border: 2px solid var(--rule);
  border-top-color: var(--signal);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.progress-label.is-busy { color: var(--ink-2); }

@media (prefers-reduced-motion: reduce) {
  .is-waiting,
  .shot.is-waiting { animation: none; background-image: none; }
  .spinner { animation: none; border-top-color: var(--rule); }
}

/* ---------- placeholders while a file is being read ---------- */

.skel {
  height: 12px;
  border-radius: 3px;
}
.skelgroup {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding-bottom: 16px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--rule-2);
}
.skelgroup:last-child { border-bottom: 0; margin-bottom: 0; }
.skelstat {
  display: flex;
  flex-direction: column;
  gap: 8px;
  justify-content: center;
}

/* Reading status, at the top of the stage where the file was dropped. */
.stagestatus {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0 0 20px;
  font-size: 13px;
  color: var(--ink-2);
}
.stagestatus .progress {
  flex: 1;
  min-width: 80px;
  margin-left: 10px;
}
.stagestatus.hidden { display: none; }

/* ---------- the tool on a phone: stage full screen, settings in a sheet ---------- */

.mobilebar { display: none; }
.sheet, .sheetscrim { display: none; }

/*
 * The `hidden` attribute has to win over the display rules below. A bare class
 * selector outranks the browser's own `[hidden] { display: none }`, so without
 * this the scrim stays laid out - invisible at opacity 0, inset 0, above
 * everything - and silently eats every tap on the page.
 */
.sheet[hidden], .sheetscrim[hidden] { display: none !important; }

@media (max-width: 860px) {
  /*
   * The rail is lifted out of the grid into a bottom sheet, so the stage gets
   * the whole screen. Its desktop height of 100vh with its own scrollbar is
   * what made a phone open the tool on a wall of settings that trapped the
   * scroll.
   */
  .controls {
    height: auto;
    overflow-y: visible;
    position: static;
    border-right: 0;
    border-bottom: 0;
    padding: 4px 0 0;
    background: none;
  }
  .layout { grid-template-columns: 1fr; min-height: 0; }
  .stage { padding: 16px 14px 24px; }

  /* Room for the fixed bar, plus the phone's own home indicator. */
  body.has-mobilebar { padding-bottom: calc(66px + env(safe-area-inset-bottom, 0px)); }
  body.sheet-open { overflow: hidden; }

  .mobilebar {
    display: flex;
    align-items: center;
    gap: 10px;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 70;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--card);
    border-top: 1px solid var(--rule);
  }
  .mobilebar__settings {
    flex: 1;
    min-height: 46px;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink);
    background: none;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    cursor: pointer;
  }
  .mobilebar__settings[aria-expanded="true"] { border-color: var(--signal); color: var(--signal); }

  /* In the bar, not floating over the preview. */
  .mobilebar .fab {
    position: static;
    flex: 1;
    justify-content: center;
    min-height: 46px;
    padding: 13px 14px;
    box-shadow: none;
    transform: none;
  }
  .mobilebar__settings { flex: 0 0 auto; padding: 0 18px; }

  .sheetscrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 80;
    background: rgba(13, 27, 42, 0.45);
    opacity: 0;
    transition: opacity 0.2s ease;
  }
  .sheetscrim.is-open { opacity: 1; }

  .sheet {
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 90;
    max-height: 86vh;
    background: var(--card);
    border-top: 1px solid var(--rule);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -8px 30px rgba(13, 27, 42, 0.22);
    transform: translateY(100%);
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
  }
  .sheet.is-open { transform: translateY(0); }

  .sheet__grab {
    flex: none;
    width: 40px;
    height: 4px;
    margin: 9px auto 3px;
    border-radius: 3px;
    background: var(--rule);
  }
  .sheet__head {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 16px 10px;
    border-bottom: 1px solid var(--rule-2);
    touch-action: none;          /* so the drag-to-dismiss gesture is ours */
  }
  .sheet__title {
    margin: 0;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-2);
  }
  .sheet__body {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 14px 16px calc(20px + env(safe-area-inset-bottom, 0px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .sheet, .sheetscrim { transition: none; }
}

/* ---------- touch targets ---------- */

/*
 * Keyed on the pointer, not the width: a 24px control is too small for a thumb
 * on any size of touch screen.
 */
@media (pointer: coarse) {
  .pagecard__act { min-width: 36px; height: 36px; padding: 0 11px; font-size: 12px; }
  .themetoggle { min-width: 42px; min-height: 42px; }
  .btn--tiny { min-height: 38px; }
  .l-catsbtn, .l-navpanel a { min-height: 44px; }
}

/* ---------- image tools ---------- */

.setting-label { display: block; font-size: 14px; margin-bottom: 5px; }
.setting-hint { margin: 5px 0 0; font-size: 12px; color: var(--ink-3); line-height: 1.45; }
.setting-check {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 7px 0;
  font-size: 14px;
  cursor: pointer;
}
.setting-check input { margin-top: 2px; flex: none; }

.pagecard__shot img { width: 100%; height: auto; display: block; }
.pagecard.is-out .pagecard__shot img { opacity: 0.3; filter: grayscale(1); }
.pagecard__cap--dim { color: var(--ink-3); }

/* The one crop box, dragged on the first image and used on all of them. */
.cropstage { margin-bottom: 20px; }
.cropwrap {
  position: relative;
  display: inline-block;
  max-width: 100%;
  line-height: 0;
  cursor: crosshair;
  touch-action: none;          /* the drag gesture is ours, not the page's */
  user-select: none;
}
.cropwrap img { max-width: 100%; max-height: 420px; width: auto; display: block; }
.cropdrag {
  position: absolute;
  border: 1px solid var(--signal);
  box-shadow: 0 0 0 9999px rgba(13, 27, 42, 0.45);
  cursor: move;
}

.renamepreview { margin-bottom: 18px; }
.renamepreview__row {
  margin: 0 0 5px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}
.renamepreview__from { color: var(--ink-3); }

/* ---------- GSTIN check ---------- */

.gstin-input {
  width: 100%;
  font-family: var(--mono);
  font-size: 19px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 14px 12px;
}
.gstin-verdict {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  margin-bottom: 18px;
  border: 1px solid var(--rule);
  border-left-width: 3px;
  border-radius: var(--radius);
  font-size: 15px;
}
.gstin-verdict.is-ok { border-left-color: var(--ok); color: var(--ok); }
.gstin-verdict.is-bad { border-left-color: var(--signal); color: var(--signal); }
.gstin-parts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; }
.gstin-part { padding: 12px 14px; background: var(--card); border: 1px solid var(--rule-2); }
.gstin-part b { display: block; font-family: var(--mono); font-size: 15px; margin-bottom: 3px; }
.gstin-part span { font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); }
.gstin-bulk { width: 100%; min-height: 150px; font-family: var(--mono); font-size: 13px; padding: 11px; }
.gstin-row { display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--rule-2); font-size: 13px; }
.gstin-row code { font-family: var(--mono); flex: none; }
.gstin-row.is-ok code { color: var(--ok); }
.gstin-row.is-bad code { color: var(--signal); }

.toolfoot__by { margin: 0; font-size: 12.5px; color: var(--ink-3); }
.toolfoot__brand { color: var(--ink-2); font-weight: 600; text-decoration: none; }
.toolfoot__brand:hover { color: var(--signal); text-decoration: underline; }

/* ---------- the sign-in gate ---------- */

.gate {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(13, 27, 42, 0.5);
}
.gate__box {
  width: 100%;
  max-width: 380px;
  padding: 26px 24px 22px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  box-shadow: 0 18px 50px rgba(13, 27, 42, 0.28);
}
.gate__title { margin: 0 0 10px; font-size: 19px; }
.gate__text { margin: 0 0 16px; color: var(--ink-2); line-height: 1.55; }
.gate__note {
  margin: -6px 0 16px;
  padding: 9px 11px;
  font-size: 13px;
  color: var(--warn);
  background: var(--paper);
  border-radius: var(--radius);
}
.gate__fine { margin: 14px 0 0; font-size: 12px; color: var(--ink-3); text-align: center; }

/* ---------- the sign-in wall on a tool page ---------- */

/*
 * While we are finding out whether this browser is signed in.
 *
 * visibility, not display: the tools measure elements as they boot, and
 * display:none gives every one of them a zero-size box. This keeps the layout
 * intact and only stops it being seen - which is the whole requirement, since
 * a tool that flashes up and is then replaced reads as a fault.
 *
 * Scoped to <main> so the header stays: on a slow connection a blank page with
 * a masthead is a page that is loading, and a completely blank one is broken.
 */
/* ---- while we work out whether this visitor may be here ----
 *
 * The class is stamped onto <html> by scripts/build.js on every gated page, so
 * this stylesheet - render-blocking, in <head> - applies before the browser
 * draws anything. require-signin.js removes it once it knows.
 *
 * Adding the class from a script at the bottom of <body> was too late: by then
 * the drop zone and the settings rail had already been painted, which is the
 * flash this replaces.
 */
.pc-authcheck main { visibility: hidden; }

/*
 * The tool's furniture lives outside <main>: sheet.js moves the settings rail
 * onto document.body on a narrow screen, download-fab.js adds the floating
 * export button, and the footer carries the help link. Hiding only <main> left
 * an Export button floating over a page that had not decided yet.
 */
.pc-authcheck .fab,
.pc-authcheck .sheet,
.pc-authcheck .sheetscrim,
.pc-authcheck .mobilebar,
.pc-authcheck .toolfoot,
.pc-authcheck body > .controls { visibility: hidden; }

/*
 * A preloader, not an empty page. Nothing is drawn for a moment either way,
 * and the difference between "loading" and "broken" is entirely whether
 * something is there to say so.
 *
 * Built from body's two pseudo-elements so it needs no markup: there is no
 * element to stamp into 22 pages, nothing to remove afterwards, and it cannot
 * be left behind by a script that failed to run.
 */
.pc-authcheck body::before,
.pc-authcheck body::after {
  position: fixed;
  left: 0;
  right: 0;
  text-align: center;
  pointer-events: none;
  z-index: 40;
  /* Late enough not to flicker on a fast connection, where the answer arrives
     before anyone has registered a wait. */
  animation: pc-preload-in 260ms ease-out 220ms both,
             pc-preload-out 0s linear 6s forwards;
}

/* The mark, because it is already the thing on the tab and in the header. */
.pc-authcheck body::before {
  content: "";
  top: 50%;
  margin-top: -46px;
  height: 34px;
  background: center / 34px 34px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='6' y='7' width='3.5' height='18' rx='1.25' fill='%23d62246'/%3E%3Crect x='12.5' y='7' width='7' height='18' rx='1.25' fill='%23d62246'/%3E%3Crect x='23.5' y='7' width='2.5' height='18' rx='1.25' fill='%23d62246'/%3E%3C/svg%3E");
}

.pc-authcheck body::after {
  content: "Checking your account";
  top: 50%;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

@keyframes pc-preload-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pc-preload-out { to { opacity: 0; visibility: hidden; } }

/* The bars read left to right, the way a scanner passes over them. */
@media (prefers-reduced-motion: no-preference) {
  .pc-authcheck body::before { animation:
      pc-preload-in 260ms ease-out 220ms both,
      pc-scan 1100ms ease-in-out 480ms infinite,
      pc-preload-out 0s linear 6s forwards; }
}
@keyframes pc-scan {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}

/*
 * Never leave a page hidden because a script did not arrive.
 *
 * Hiding by default trades a visible flash for a possible blank page: if
 * require-signin.js is blocked by an extension, or a deploy is half-done, the
 * class is never removed and the tool is invisible forever. These animations
 * are the failsafe - they run without JavaScript and reveal the page six
 * seconds in. A working gate has decided long before that, so this only fires
 * when the gate did not run at all.
 *
 * Showing a tool to someone who has not signed in is a business problem. A
 * blank page is a broken product, which is worse, and the server-side check is
 * what should be relied on for the first one regardless.
 */
@keyframes pc-authcheck-failsafe { to { visibility: visible; } }
.pc-authcheck main,
.pc-authcheck .fab,
.pc-authcheck .sheet,
.pc-authcheck .mobilebar,
.pc-authcheck .toolfoot,
.pc-authcheck body > .controls { animation: pc-authcheck-failsafe 0s linear 6s forwards; }

/*
 * With JavaScript off entirely, none of this will ever run. The tools need it
 * anyway, so the honest thing is to show the page and let it say so.
 */
@media (scripting: none) {
  .pc-authcheck main, .pc-authcheck .fab, .pc-authcheck .sheet,
  .pc-authcheck .mobilebar, .pc-authcheck .toolfoot,
  .pc-authcheck body > .controls { visibility: visible; animation: none; }
  .pc-authcheck body::before, .pc-authcheck body::after { content: none; }
}

/* ---- the stage: what went in, and what comes out ----
   The grid on the left is the file; the panel on the right is the result of
   the current settings, composed by the real exporter. Before this, every
   setting below Cropping changed something nobody could see. */
.stagesplit { display: grid; grid-template-columns: 1fr 380px; gap: 22px; align-items: start; }
.stagesplit__title {
  margin: 0 0 10px; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3);
}
.stagesplit__out {
  position: sticky; top: 16px;
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius);
  /* Room at the foot for the floating export button, which is fixed to the
     bottom-right and otherwise sits on top of the last page shown here. */
  padding: 14px 14px 76px;
}
.result__note { margin: 0 0 12px; font-size: 12px; color: var(--ink-3); line-height: 1.5; }
.result__page { margin: 0 0 14px; }
.result__page canvas {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--rule); border-radius: 2px; background: #fff;
}
.result__page figcaption {
  margin-top: 5px; font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3);
}

/* On a narrow screen the result comes FIRST: it is the answer to the question
   someone is actually asking while they change a setting. */
@media (max-width: 860px) {
  .stagesplit { grid-template-columns: 1fr; }
  .stagesplit__out { position: static; order: -1; }
}

/* ---------- leading with one job ---------- */

/*
 * The fold-away for the half of a tool you did not come for. Styled as a line
 * of text with a rule above rather than a button, because it is an offer, not
 * the thing the page is for - and the page already has a primary button.
 */
.block--aside { padding-top: 0; }
.toolmode__open {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 10px 0 0;
  border: 0;
  border-top: 1px solid var(--rule-2);
  background: none;
  color: var(--ink-2);
  cursor: pointer;
}
.toolmode__open b {
  display: block;
  font-size: 13px;
  color: var(--signal);
}
.toolmode__open b::after { content: ' \2192'; }
.toolmode__open span {
  display: block;
  font-size: 11.5px;
  margin-top: 2px;
}
.toolmode__open:hover b { text-decoration: underline; }
.toolmode__open:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }


/* ---------------------------------------------------------------------------
   The WhatsApp button, bottom-right of every page.

   Replaced the Tawk widget, which brought its own iframe, fonts and websocket.
   This is an anchor, a circle and one keyframe, so it costs nothing on the 3G
   phone in a warehouse that the rest of this stylesheet is written for.

   z-index 70 clears everything else here (the highest was 60, the tool rail).
   --------------------------------------------------------------------------- */
/*
 * Support, in the header.
 *
 * It was a circle fixed to the bottom-right corner with a pulsing ring, and
 * what that cost was a corner every page had to steer around: the floating
 * download button was stacked above it to stay reachable, and on the dashboard
 * it still covered a rupee figure, so a seller read "Rs 27,9" where the number
 * was 27,96,000. In the header it is beside the other two header controls,
 * where a person looks for help, and no page has to plan around it.
 *
 * The green is the channel's own, on both grounds, because that glyph is only
 * recognisable in it - it is the one colour on this site that is not ours.
 */
.wa {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 11px;
  color: var(--ink-2);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  white-space: nowrap;
}
.wa:hover, .wa:focus-visible { color: var(--ink); border-color: #25D366; }
.wa svg { width: 17px; height: 17px; flex: none; color: #25D366; }
.wa__label { font-size: 13px; }

/* The word goes at 1100px, in landing.css with the rest of the header's
   surrenders, so the whole sequence is written down in one place. */
@media (max-width: 1100px) { .wa { padding: 0 9px; } }

/* ---------------------------------------------------------------------------
   Download app
   --------------------------------------------------------------------------- */
.appqr { position: relative; display: inline-flex; }
.l-navpill {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 11px;
  font: inherit;
  font-size: 13px;
  color: var(--ink-2);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  white-space: nowrap;
}
.l-navpill:hover { color: var(--signal); border-color: var(--signal); }
.appqr__card {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 80;
  width: 208px;
  padding: 13px;
  text-align: center;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 8px 22px rgba(13, 27, 42, 0.14);
}
.appqr__card .appqr__code { display: block; margin: 0 auto 9px; border-radius: 2px; }
.appqr__card b { display: block; font-size: 13px; margin-bottom: 3px; }
.appqr__card p { margin: 0 0 9px; font-size: 12px; color: var(--ink-3); }
.appqr__stores { display: grid; gap: 5px; }
.appqr__stores a {
  padding: 6px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
}
.appqr__stores a:hover { color: var(--signal); border-color: var(--signal); }
.appqr__tail {
  display: block;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-3);
}

/* Never on paper. */
@media print { .wa, .appqr { display: none; } }
/* ---------------------------------------------------------------------------
   THE SIGNED-IN SHELL: a left rail, and the header above it.

   Rewritten in one piece. It had grown three designs deep - an edge tab, a
   brand box, a chevron in a header - each patched onto the last, and the
   rules had started to contradict each other. What follows is one model.

   The model is BillingPie's, because that is the product this is meant to
   feel like: 250px open, 70px as icons, submenus that fly out beside the
   icons at the narrow width, and below 768px the whole rail slides off-canvas
   over the page with a dimmed backdrop rather than squeezing the content.
   Those two widths are its --vz-vertical-menu-width and -width-sm, read out
   of its stylesheet rather than guessed from a screenshot.

   The shape is theirs; the colours are ours. A hardcoded #5ea3cb would be the
   one thing on the page that ignores dark mode.

   Three states, driven by classes on <html>:
     .pc-railed        the rail exists (signed in, gated page)
     .pc-rail--icons   collapsed to 70px
     .pc-rail--open    the off-canvas rail is showing, under 768px only

   The logo and the collapse control both live in the HEADER, not in here, so
   the rail is only ever the menu.
   --------------------------------------------------------------------------- */

:root { --pc-railw: 250px; --pc-railw-sm: 70px; --pc-headerh: 51px; }

/* ---- the row: rail beside page ---- */

.pc-shell { display: flex; align-items: stretch; min-height: 0; }
.pc-shell > main { flex: 1; min-width: 0; }

.pc-rail {
  flex: none;
  width: var(--pc-railw);
  display: flex;
  flex-direction: column;
  background: var(--card);
  border-right: 1px solid var(--rule);
  position: sticky;
  /* Under the header, which is sticky at 0 - see .pc-railed .l-nav. */
  top: var(--pc-headerh);
  align-self: flex-start;
  /*
   * The viewport MINUS the header above it. Plain 100vh was wrong by exactly
   * the header's height - it is in normal flow here, so the rail starts below
   * it and a 100vh box then ends that far under the fold, which is why the
   * account block at the foot was half off-screen. rail.js measures the
   * header and publishes --pc-headerh.
   */
  height: calc(100vh - var(--pc-headerh));
  /*
   * Visible, not auto. The flyout at the collapsed width leaves this box, and
   * a box that scrolls on one axis clips the other. .pc-rail__scroll takes
   * the scrolling instead.
   */
  overflow: visible;
  z-index: 40;
  transition: width 140ms ease;
}

.pc-rail--icons .pc-rail { width: var(--pc-railw-sm); }

/*
  The rail always takes its own width out of the row, on every screen above
  768px - it never lies over the page.

  It used to overlay on a tool page, on the argument that widening the menu
  mid-task should not reflow the seller's settings column. In practice an
  opened menu sitting on top of the controls reads as broken rather than as
  considered: you cannot see what you are about to go back to. Pushing is
  what every application with a collapsible sidebar does, and it is what the
  seller expects when they press a button labelled "show the menu".

  Below 768px it IS an overlay, because there is no width to give - see the
  off-canvas block at the end of this file.
*/

/* ---- the scrolling middle ---- */

.pc-rail__scroll {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 0 12px;
  overflow-y: auto;
  overflow-x: hidden;
  /* Reserved, so rows do not shift sideways when the bar appears. Given back
     at 70px, where 12px is the difference between an icon centred in its
     column and one shoved against the edge. */
  /*
   * No stable gutter. It reserved ~12px whether or not a scrollbar was
   * showing, and at 250px that is a visible strip of dead space down the
   * right of every menu row - the rows stopped short of their own column and
   * it read as a mistake. The rail scrolls rarely enough that the shift when
   * a bar does appear is the cheaper cost.
   */
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.pc-rail:hover .pc-rail__scroll,
.pc-rail:focus-within .pc-rail__scroll { scrollbar-color: var(--rule) transparent; }
.pc-rail__scroll::-webkit-scrollbar { width: 6px; }
.pc-rail__scroll::-webkit-scrollbar-track { background: transparent; }
.pc-rail__scroll::-webkit-scrollbar-thumb { background: transparent; border-radius: 3px; }
.pc-rail:hover .pc-rail__scroll::-webkit-scrollbar-thumb,
.pc-rail:focus-within .pc-rail__scroll::-webkit-scrollbar-thumb { background: var(--rule); }
.pc-rail--icons .pc-rail__scroll { scrollbar-gutter: auto; }

/*
 * A flyout escapes this box, and a box that scrolls clips whatever leaves it.
 *
 * So while one is open the scrolling is given up - there is nothing to scroll
 * to anyway, because the panel beside it is what is being read. rail.js sets
 * the class rather than :has() doing it, so the rule is deterministic and
 * does not depend on selector support.
 */
.pc-rail--flyout .pc-rail__scroll { overflow: visible; }

/* ---- section labels ---- */

.pc-rail__label {
  padding: 12px 18px 5px;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.pc-rail--icons .pc-rail__label { visibility: hidden; height: 12px; padding: 6px 0 0; }

/* ---- rows ---- */
/*
 * One explicit full-width column. Without grid-template-columns the implicit
 * one sized to its content, so every row sat short of the rail's right edge -
 * 44px of row in a 70px column, icons hugging the left with dead space beside
 * them. minmax(0, 1fr) fills the group and lets a long tool name ellipsis
 * rather than push the column wider.
 */
.pc-rail__group {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  padding: 0 10px;
}
.pc-rail__cat { display: block; min-width: 0; position: relative; }

.pc-rail__row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border-radius: var(--radius);
  font: inherit;
  font-size: 13.5px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  background: transparent;
  border: 0;
  text-align: left;
  cursor: pointer;
}
.pc-rail__row:hover { background: var(--rule-2); color: var(--ink); }
.pc-rail__row.is-on,
.pc-rail__head.is-here { background: var(--rule-2); color: var(--signal); font-weight: 600; }

.pc-rail__ico { width: 17px; height: 17px; flex: none; opacity: 0.85; }
.pc-rail__row.is-on .pc-rail__ico,
.pc-rail__head.is-here .pc-rail__ico { opacity: 1; }
.pc-rail__name { overflow: hidden; text-overflow: ellipsis; }
.pc-rail__caret {
  margin-left: auto;
  font-size: 15px;
  line-height: 1;
  opacity: 0.5;
  transition: transform 120ms ease;
}
.pc-rail__cat.is-open > .pc-rail__head .pc-rail__caret { transform: rotate(90deg); }

/*
 * An open category stays marked, but in a quieter register than the tool.
 *
 * Two things are true at once and the rail has to say both: you are in Label
 * tools, AND the page is Amazon. Giving them the same crimson made it read
 * as two pages being open; taking the category's marking away entirely lost
 * the section, which is the thing you scan for first. So the section keeps
 * the pill and goes bold in ordinary ink, and the crimson belongs to the one
 * row that is actually on screen.
 *
 * Only while the fold-out is OPEN. Collapsed, and at 70px, that tool row is
 * not visible - there the category is the only marker there is and takes the
 * crimson back.
 */
html:not(.pc-rail--icons) .pc-rail__cat.is-open > .pc-rail__head.is-here {
  background: var(--rule-2);
  color: var(--ink);
  font-weight: 650;
}
html:not(.pc-rail--icons) .pc-rail__cat.is-open > .pc-rail__head.is-here .pc-rail__ico {
  opacity: 1;
}

/* At 70px a row is its icon, centred, and nothing else. */
.pc-rail--icons .pc-rail__name,
.pc-rail--icons .pc-rail__caret { display: none; }
.pc-rail--icons .pc-rail__row { justify-content: center; padding: 10px 0; gap: 0; }
.pc-rail--icons .pc-rail__group { padding: 0 10px; }

/* ---- fold-out tools ---- */

.pc-rail__sub { display: none; }
.pc-rail__cat.is-open .pc-rail__sub { display: grid; gap: 1px; padding: 1px 0 5px; }
.pc-rail__subh { display: none; }

.pc-rail__tool {
  display: block;
  padding: 6px 10px 6px 38px;
  border-radius: var(--radius);
  font-size: 12.5px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pc-rail__tool:hover { background: var(--rule-2); color: var(--ink); }
.pc-rail__tool.is-on { color: var(--signal); font-weight: 600; }
.pc-rail__tool.is-soon { color: var(--ink-3); cursor: default; }
.pc-rail__tool.is-soon small {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.08em;
  text-transform: uppercase; margin-left: 6px;
}
.pc-rail__all { color: var(--ink-3); font-style: italic; }

/* ---- the flyout, at 70px ---- */
/*
 * The same fold-out, opened BESIDE the rail. Five icons that all went to the
 * same directory page was an icon rail nobody could use.
 *
 * Anchored to the rail's right edge via --pc-railw-sm, NOT to the row's, and
 * that distinction was a bug: `calc(100% + 6px)` resolves against the category
 * wrapper, which is narrower than the rail, so the panel opened on top of the
 * rail's own icons.
 */
.pc-rail--icons .pc-rail__cat.is-open .pc-rail__sub {
  position: absolute;
  left: calc(var(--pc-railw-sm) - 10px + 6px);
  top: -6px;
  z-index: 70;
  min-width: 210px;
  padding: 7px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.22);
}
.pc-rail--icons .pc-rail__subh {
  display: block;
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--ink-3); padding: 2px 8px 6px;
}
.pc-rail--icons .pc-rail__tool { padding-left: 8px; }
.pc-rail--icons .pc-rail__cat.is-open > .pc-rail__head {
  background: var(--rule-2); color: var(--signal);
}

/* ---- the foot: who is signed in ---- */
/*
 * A sibling of the scrolling box, not a child. Inside it, margin-top: auto
 * only reached the bottom while the menu was shorter than the rail - open two
 * fold-outs and the account block went below the fold.
 */
.pc-rail__foot {
  flex: none;
  padding: 10px 14px;
  border-top: 1px solid var(--rule-2);
  display: grid;
  gap: 7px;
}
.pc-rail__who { display: flex; align-items: center; gap: 9px; min-width: 0; }
.pc-rail__av {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  background: var(--rule-2); color: var(--ink-2);
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 10px;
}
.pc-rail__whoin { min-width: 0; }
.pc-rail__whoin b,
.pc-rail__whoin span {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pc-rail__whoin b { font-size: 12px; line-height: 1.3; }
.pc-rail__whoin span { font-family: var(--mono); font-size: 9px; color: var(--ink-3); }
.pc-rail__links { display: flex; gap: 12px; font-size: 11.5px; }
.pc-rail__links a,
.pc-rail__links button {
  font: inherit; color: var(--ink-2); text-decoration: none;
  background: transparent; border: 0; padding: 0; cursor: pointer;
}
.pc-rail__links a:hover, .pc-rail__links button:hover { color: var(--ink); }
.pc-rail__links a.is-on { color: var(--signal); }

.pc-rail--icons .pc-rail__whoin,
.pc-rail--icons .pc-rail__links { display: none; }
.pc-rail--icons .pc-rail__foot { padding: 10px 0; justify-items: center; }

/* ---- every other scrollbar in the signed-in app ---- */
/*
  The rail themes its own above. This does the rest: the tool's settings
  column, its stage, and the document itself, all of which were still drawing
  the platform's default bar - 16px of light grey down a dark column, which
  reads as a seam between two panels rather than as a control.

  Scoped to .pc-railed so the marketing site keeps the plain bar a visitor
  expects. Two mechanisms because no single one covers every engine we have:
  the standard scrollbar-* properties (Firefox, Chrome 121+) and the WebKit
  pseudo-elements (Safari, and Chrome before that). They may disagree by a
  pixel; both are a thin thumb in the rule colour on no track.
*/
.pc-railed,
.pc-railed .controls,
.pc-railed .stage,
.pc-railed .layout > * {
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}
.pc-railed ::-webkit-scrollbar,
.pc-railed::-webkit-scrollbar { width: 10px; height: 10px; }
.pc-railed ::-webkit-scrollbar-track,
.pc-railed::-webkit-scrollbar-track { background: transparent; }
.pc-railed ::-webkit-scrollbar-thumb,
.pc-railed::-webkit-scrollbar-thumb {
  background: var(--rule);
  border-radius: 6px;
  /* Inset by a transparent border, so the thumb floats in the gutter rather
     than filling it edge to edge. */
  border: 2px solid transparent;
  background-clip: content-box;
}
.pc-railed ::-webkit-scrollbar-thumb:hover,
.pc-railed::-webkit-scrollbar-thumb:hover {
  background-color: var(--ink-3);
  background-clip: content-box;
}
.pc-railed ::-webkit-scrollbar-corner { background: transparent; }

/* ---- the header above it ---- */

/*
  The header stays put, and the rail hangs off the bottom of it.

  It was static, which looked right until the page scrolled: the header went
  away, the sticky rail stayed pinned at top: 0, but it was still sized
  100vh MINUS the header - so the last 51px of the viewport had no rail in
  it and the column simply stopped, a different shade, mid-screen.

  Sticky at the top, with the rail sticking below it, keeps the two agreeing
  at every scroll position. Together they are exactly the viewport.
*/
.pc-railed .l-nav {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--card);
}
.pc-railed .l-nav__inner { max-width: none; padding: 7px 16px; gap: 10px; }
/* The brand is half the row on the website so the centred menu stays centred.
   There is no centred menu here, and that flex: 1 stretched it across 900px
   and stranded the collapse control in the middle of the header. */
.pc-railed .l-nav__inner > .l-brand { flex: none; }
.pc-railed .l-navactions { margin-left: auto; }
/* The account corner goes because the rail's foot answers the same question
   along with Settings and Sign out. The Dashboard button goes because on this
   side of signing in you are already in it. */
.pc-railed .l-navauth,
.pc-railed .l-drawerlogin,
.pc-railed .l-dashtab,
.pc-railed .l-navmenu,
.pc-railed .l-navburger { display: none; }

/*
  The collapse control, beside the logo.

  Third home for this control and the one that holds: a chevron inside the
  rail said nothing, a round tab on the rail's border overlapped the tool
  column beside it, and a brand box at the top of the rail put the logo
  somewhere it was not wanted. Next to the mark it is beside the thing it
  belongs to and inside nothing it can overlap.
*/
.pc-rail__shrink {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; padding: 0;
  border-radius: var(--radius);
  color: var(--ink-3); background: transparent;
  border: 1px solid var(--rule);
  cursor: pointer;
}
.pc-rail__shrink:hover { color: var(--signal); border-color: var(--signal); }
.pc-rail__shrink .pc-rail__ico { width: 16px; height: 16px; opacity: 1; }

/* ---- under 768px: off-canvas, over the page ---- */
/*
 * BillingPie's model exactly: the rail slides out from -100% and lies over
 * the content with a dimmed backdrop, rather than taking width away from a
 * screen that has none to give. The collapse control becomes the thing that
 * opens it, so one button does both jobs at both sizes.
 */
.pc-rail__veil {
  display: none;
  position: fixed; inset: 0;
  background: rgba(13, 27, 42, 0.45);
  z-index: 45;
}

@media (max-width: 767.98px) {
  .pc-rail {
    position: fixed;
    top: var(--pc-headerh);
    left: 0;
    width: var(--pc-railw);
    height: calc(100vh - var(--pc-headerh));
    margin-left: -100%;
    transition: margin-left 180ms ease;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
    z-index: 50;
  }
  /* The width classes stop applying: at this size it is one width, shown or
     hidden. An icon rail on a phone is a column of mysteries. */
  .pc-rail--icons .pc-rail { width: var(--pc-railw); }
  .pc-rail--icons .pc-rail__name,
  .pc-rail--icons .pc-rail__caret { display: revert; }
  .pc-rail--icons .pc-rail__row { justify-content: flex-start; padding: 9px 10px; gap: 11px; }
  .pc-rail--icons .pc-rail__whoin,
  .pc-rail--icons .pc-rail__links { display: revert; }
  .pc-rail--icons .pc-rail__foot { padding: 10px 14px; justify-items: stretch; }
  .pc-rail--icons .pc-rail__label { visibility: visible; height: auto; padding: 12px 18px 5px; }
  .pc-rail--icons .pc-rail__cat.is-open .pc-rail__sub { position: static; box-shadow: none;
    border: 0; padding: 1px 0 5px; min-width: 0; background: transparent; }
  .pc-rail--icons .pc-rail__subh { display: none; }
  .pc-rail--icons .pc-rail__tool { padding-left: 38px; }

  .pc-rail--open .pc-rail { margin-left: 0; }
  .pc-rail--open .pc-rail__veil { display: block; }

  /* The page keeps its full width; the rail is over it, not beside it. */
  .pc-shell { display: block; }
  .pc-shell > main { width: 100%; }
}

@media print { .pc-rail, .pc-rail__veil, .pc-rail__shrink { display: none; } }

/* ---- the tool-page breadcrumb, on a signed-in page ---- */
/*
  Gone. toolhead.js draws "Home / Label tools / Amazon label crop" above every
  tool, which earned its place when the only navigation was a header menu. The
  rail now names the category you are in and marks the tool inside it, so the
  trail repeats what is already on screen and costs a strip of vertical space
  on the one screen where vertical space is the work.

  Only on a railed page: signed out there is no rail, and the trail is then
  the only thing saying where you are.
*/
.pc-railed .toolhead { display: none; }

/* ---- the footer, on a signed-in page ---- */
/*
  Gone. nav.js draws it under every tool - the tool categories again, the
  legal pages, the company line - and that belongs under a page somebody is
  READING, not under a tool somebody is using. The rail reaches all of it,
  and Settings and Sign out sit at its foot.

  Only on a railed page, so the website keeps its footer in full. That is
  also where it earns its keep: those links are internal linking a crawler
  follows, and a crawler never sees this side.
*/
.pc-railed .toolfoot { display: none; }
