@charset "utf-8";
/* ==========================================================================
   BlurMyPhoto — tool.css · the editor chrome, loaded only where there is one
   Sections: 12 dropzone · 13 stage · 13b workspace · 14 toolbar/modes ·
   15 progress · 16 status · 17 cold start · 18 step nav · 19 actionbar ·
   20 filecard · 21 export options
   Depends on the tokens in shell.css, which every page loads first.
   ========================================================================== */

/* --- 12 · TOOL UI · DROPZONE ---------------------------------------------- */
.dropzone {
  display: block; width: 100%; padding: var(--s-7) var(--s-4);
  background: var(--panel); border: 2px dashed var(--line); border-radius: var(--radius);
  text-align: center; cursor: pointer;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.dropzone:hover { border-color: var(--bar); background: var(--paper); }
.dropzone--over {
  border-style: solid; border-color: var(--bar);
  background: var(--paper); box-shadow: inset 0 0 0 3px var(--bar);
}
.dropzone__inner {
  display: grid; justify-items: center; gap: var(--s-3);
  max-width: 44ch; margin-inline: auto;
}
.dropzone__inner > :first-child { margin-top: 0; }

/* The site's mark, doubling as the one picture on an otherwise empty screen. */
.dropzone__mark {
  width: 60px; height: 30px; margin-bottom: var(--s-1);
  background: var(--bar); border-radius: 2px;
  box-shadow: inset -11px 0 0 var(--stamp);
}

/* The call to action has to look like something you press. A dashed rectangle
   with grey text inside it does not. */
.dropzone__cta {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: .7rem 1.6rem; border-radius: var(--radius);
  background: var(--bar); color: var(--paper);
  font-size: var(--fs-400); font-weight: 600; line-height: 1.2;
  transition: background-color var(--dur) var(--ease);
}
.dropzone:hover .dropzone__cta { background: var(--ink); }
.dropzone--over .dropzone__cta { background: var(--stamp); }

.dropzone__cta { font-size: var(--fs-500); min-height: 52px; padding: .8rem 2rem; }

.dropzone__hint {
  margin: 0; max-width: 38ch;
  font-size: var(--fs-300); line-height: 1.5; color: var(--ink-soft);
}
/* The promise sits inside the box where the decision is made, not in a second
   panel underneath it. */
.dropzone__safe {
  max-width: 42ch; margin-top: var(--s-2); padding-top: var(--s-3);
  border-top: var(--hair);
  font-size: var(--fs-300); line-height: 1.5; color: var(--ink);
}
.dropzone__formats {
  font-family: var(--font-mono); font-size: var(--fs-100);
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-soft);
}
.dropzone input[type="file"] {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; overflow: hidden; clip-path: inset(50%);
}

/* The sample offer sits under the box rather than inside it: the box is one
   decision and this is a different, smaller one, and a second call to action
   competing inside the same dashed rectangle would weaken both. */
.intake-sample {
  max-width: 52ch; margin: var(--s-3) auto 0;
  font-size: var(--fs-300); line-height: 1.55; color: var(--ink-soft);
  text-align: center;
}
.intake-sample__go {
  font-size: inherit; font-weight: 600; color: var(--ink);
  padding: 0; min-height: 0; vertical-align: baseline;
}

/* --- 13 · TOOL UI · CANVAS STAGE ------------------------------------------ */
.stage {
  display: grid; justify-items: center; align-content: center; gap: var(--s-3);
  min-height: clamp(260px, 50vh, 540px); margin-block: var(--s-4); padding: var(--s-3);
  background: var(--paper); border: var(--hair); border-radius: var(--radius);
  overflow: hidden; overscroll-behavior: contain;
}
.stage__canvas {
  display: block; max-width: 100%; max-height: min(70vh, 620px);
  touch-action: none;
  background: var(--panel); border-radius: 2px; box-shadow: 0 0 0 1px var(--line);
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}

/* The editor canvas must be sized by CSS, not by its own width/height
   attributes. Left to size itself it starts at the 300x150 default, and since
   the script derives the backing store from the laid-out box, it stayed a
   300x150 postage stamp on desktop and grew a step per resize on a HiDPI
   screen. A fixed CSS box breaks that loop. */
.stage--edit { justify-items: stretch; min-height: 0; }
.stage--edit .stage__frame { width: 100%; }
.stage--edit .stage__hint { justify-self: center; }
.stage__canvas--edit {
  width: 100%; height: clamp(260px, 52vh, 560px);
  max-width: 100%; max-height: none;
  cursor: crosshair; background: var(--paper);
}
.stage__hint {
  margin: 0; max-width: 44ch; text-align: center;
  font-family: var(--font-mono); font-size: var(--fs-100);
  line-height: 1.6; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-soft);
}

/* --- 13b · TOOL UI · WORKSPACE --------------------------------------------
   Stacked on a phone. On a desktop the photo breaks out of the reading column
   and its controls move to a rail beside it, so the picture and everything you
   can do to it are on one screen without scrolling.
   -------------------------------------------------------------------------- */
.workspace { display: grid; gap: var(--s-4); }
.workspace__stage { min-width: 0; }

@media (min-width: 1140px) {
  /* With a photo open the mount takes the site's wide column instead of the
     reading one, so the step strip, the heading, the file card, the photo and
     the status line all keep the same left edge. */
  #tool-mount.is-editing { max-width: var(--wrap-max); }
  .is-editing .workspace {
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--s-5); align-items: start;
  }
  .is-editing .workspace__side { position: sticky; top: var(--s-4); display: grid; gap: var(--s-3); }
  .workspace__side .toolbar { flex-direction: column; align-items: stretch; margin: 0; }
  .workspace__side .toolbar__group {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2);
  }
  .workspace__side .toolbar__group + .toolbar__group {
    padding: var(--s-3) 0 0; border-left: 0; border-top: var(--hair);
  }
  .workspace__side .toolbar__label,
  .workspace__side .modes,
  .workspace__side .toolbar__wide { grid-column: 1 / -1; }
  .workspace__side .modes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .workspace__side .actionbar { flex-direction: column; align-items: stretch; margin: 0; }
  .workspace__side .region-count { justify-self: start; }
  .workspace__side .export-alt { display: grid; justify-items: start; }
}

/* Repeat-save links, shown only after a file has actually been handed over. */
.export-alt { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }
.export-alt:empty { display: none; }

/* Zoom sits on the photo, bottom right, out of the controls entirely. */
.stage__frame { position: relative; display: block; min-width: 0; }
.stage__zoom {
  position: absolute; right: var(--s-2); bottom: var(--s-2); z-index: 2;
  display: flex; gap: 2px; padding: 3px;
  background: rgba(255, 255, 255, .93);
  border: var(--hair); border-radius: var(--radius);
}
.stage__zoom .btn { min-width: var(--tap); padding-inline: .55rem; }

/* --- 14 · TOOL UI · TOOLBAR & MODES --------------------------------------- */
.toolbar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-3) var(--s-4); margin-block: var(--s-4);
  padding: var(--s-3); background: var(--panel);
  border: var(--hair); border-radius: var(--radius);
}
.toolbar__group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
/* Every group says what it does. Eleven identical grey buttons in a row is a
   wall, not a toolbar. */
.toolbar__label,
.toolbar__group > .mono, .toolbar__group > label {
  font-family: var(--font-mono); font-size: var(--fs-100); font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-soft);
  white-space: nowrap;
}
.toolbar .mode-btn { min-height: var(--tap); }
@media (min-width: 700px) {
  .toolbar__group + .toolbar__group { padding-left: var(--s-4); border-left: var(--hair); }
}

/* Slot the tool fills with a progress bar and the export panel. */
.tool-extras:empty { display: none; }

/* Segmented mode selector: solid / pixelate / blur. */
.modes {
  display: inline-flex; flex-wrap: wrap;
  background: var(--panel); border: var(--hair);
  border-radius: var(--radius); overflow: hidden;
}
.mode-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); min-width: var(--tap); padding: .6rem .9rem;
  background: var(--panel); color: var(--ink-soft);
  border: 0; border-right: var(--hair);
  font-family: var(--font-mono); font-size: var(--fs-100); font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; text-decoration: none;
  cursor: pointer; touch-action: manipulation;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.mode-btn:last-child { border-right: 0; }
.mode-btn:hover { background: var(--paper); color: var(--ink); }
.mode-btn[aria-pressed="true"], .mode-btn[aria-checked="true"],
.mode-btn[aria-current="true"] { background: var(--bar); color: var(--paper); }
.mode-btn[disabled] { opacity: .5; cursor: not-allowed; }

/* --- 15 · TOOL UI · PROGRESS ----------------------------------------------
   .progress paints the groove, .progress__bar the fill (inline width or
   --pct). .progress__label works inside the wrapper or beside it.
   -------------------------------------------------------------------------- */
.progress {
  display: block; width: 100%; margin-block: var(--s-4); border-radius: var(--radius);
  background-image: linear-gradient(var(--line), var(--line));
  background-repeat: no-repeat; background-position: left top; background-size: 100% 10px;
}
.progress__bar {
  display: block; height: 10px; width: var(--pct, 0%); max-width: 100%;
  background: var(--bar); border-radius: var(--radius);
  transition: width .18s linear;
}
.progress__label {
  display: block; margin-top: var(--s-2);
  font-family: var(--font-mono); font-size: var(--fs-100);
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-soft);
}

/* --- 16 · TOOL UI · STATUS (aria-live target) ------------------------------
   Every variant carries a glyph as well as a colour, so meaning never
   rests on the red alone.
   -------------------------------------------------------------------------- */
.status {
  display: flex; align-items: flex-start; gap: .6rem;
  margin-block: var(--s-3); padding: .65rem .85rem;
  border: 1px solid transparent; border-left-width: 4px; border-radius: var(--radius);
  font-size: var(--fs-300); line-height: 1.5; color: var(--ink);
}
.status:empty { padding: 0; margin-block: 0; border-color: transparent; }
.status::before { flex: none; font-family: var(--font-mono); font-weight: 700; line-height: 1.5; }

.status--ok { background: var(--panel); border-color: var(--line); border-left-color: var(--bar); }
.status--ok::before { content: "\2713"; color: var(--bar); }

.status--err { background: var(--panel); border-color: var(--line); border-left-color: var(--stamp); }
.status--err::before { content: "!"; color: var(--stamp); }

.status--busy {
  background: var(--panel); border-color: var(--line);
  border-left-color: var(--ink-soft); color: var(--ink-soft);
}
.status--busy::before {
  content: "\25A0"; color: var(--ink-soft);
  animation: status-pulse 1.1s ease-in-out infinite;
}
@keyframes status-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* --- 17 · TOOL UI · COLD START PANEL -------------------------------------- */
.cold-start {
  display: grid; gap: var(--s-3); justify-items: start;
  margin-block: var(--s-5); padding: var(--s-5);
  background: var(--panel); border: var(--hair); border-left: 4px solid var(--bar);
  border-radius: var(--radius);
}
.cold-start > :is(h2, h3, p) { margin-top: 0; }
.cold-start :is(h2, h3) { font-size: var(--fs-600); }
.cold-start p { max-width: 52ch; color: var(--ink-soft); }

/* --- 18 · TOOL UI · STEP NAVIGATION --------------------------------------- */
/* The markup is <nav class="step-nav"><ol><li>…, so the row is laid out on
   whichever element actually holds the items: the <ol> when there is one, the
   <nav> when the items are direct children.

   The row wraps. It used to scroll sideways behind a fade, which on a phone
   put steps 3 and 4 past the edge of a component whose whole job is to say how
   many steps there are and which one you are on. Two short rows beat one row
   with half of it hidden. */
.step-nav,
.step-nav > ol,
.step-nav > ul {
  display: flex; flex-wrap: wrap; gap: var(--s-2); list-style: none;
  margin: 0; padding: 0;
}
.step-nav { margin-block: var(--s-4); padding-bottom: var(--s-2); }
.step-nav > ol, .step-nav > ul { flex: 1 1 auto; min-width: 0; align-items: stretch; }
.step-nav li { display: flex; flex: none; }

/* Equal heights across the row: the tick and the caret are glyphs with their
   own line box, and left alone they made the done and current steps taller
   than the rest. */
.step-nav li > * { flex: 1 1 auto; }
.step-nav__item::before { line-height: 1; font-size: .95em; }
.step-nav__item {
  display: inline-flex; align-items: center; gap: .45rem;
  min-height: var(--tap); padding: .5rem .8rem; line-height: 1.2;
  background: var(--panel); border: var(--hair); border-radius: var(--radius);
  font-family: var(--font-mono); font-size: var(--fs-100); font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em;
  text-decoration: none; white-space: nowrap; color: var(--ink-soft);
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}
.step-nav__n {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 1.25rem; height: 1.25rem; margin-right: .1rem;
  border: 1px solid currentColor; border-radius: 2px;
  font-size: var(--fs-100); letter-spacing: 0; opacity: .75;
}
.step-nav__item:hover { border-color: var(--ink-soft); color: var(--ink); }
.step-nav__item[data-state="done"] { color: var(--ink); border-color: var(--bar); }
.step-nav__item[data-state="done"]::before { content: "\2713"; color: var(--bar); }
/* A step you have not reached is still a step you need to be able to count.
   The dashed hairline it used to carry was 1.47:1 against the chip, so the row
   read as one filled box and some whitespace. */
.step-nav__item[data-state="todo"] {
  color: var(--ink-soft); border-style: dashed; border-color: var(--line-strong);
}
.step-nav__item[data-state="current"], .step-nav__item[aria-current="step"],
.step-nav__item[aria-current="page"], .step-nav__item[aria-current="true"] {
  background: var(--bar); border-color: var(--bar); color: var(--paper);
}
.step-nav__item[data-state="current"]::before,
.step-nav__item[aria-current]::before { content: "\25B8"; color: var(--paper); }

/* --- 19 · TOOL UI · ACTION BAR --------------------------------------------
   Sticky to the bottom of the viewport under 700px so the primary action
   stays under the thumb; a normal inline row above that.
   -------------------------------------------------------------------------- */
.actionbar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-3); margin-block: var(--s-5);
}
@media (max-width: 699.98px) {
  /* Sticky so the primary action stays under the thumb. It deliberately does
     NOT bleed to the viewport edges with negative margins: this bar is mounted
     into an unpadded panel, so a bleed would push the page 32px wider than the
     screen and give every tool page a horizontal scrollbar. */
  .actionbar {
    position: sticky; bottom: 0; z-index: 40;
    flex-wrap: nowrap; gap: var(--s-2);
    margin-bottom: 0;
    padding: var(--s-2) 0 calc(var(--s-2) + env(safe-area-inset-bottom, 0px));
    background: var(--panel); border-top: var(--hair);
  }
  .actionbar .btn { flex: 1 1 0; min-width: 0; padding-inline: .6rem; font-size: var(--fs-300); }
  .actionbar .btn--text { flex: 0 1 auto; }
}

/* --- 20 · TOOL UI · FILE CARD --------------------------------------------- */
.filecard {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: .15rem var(--s-3);
  margin-block: var(--s-4); padding: var(--s-3) var(--s-4);
  background: var(--panel); border: var(--hair); border-radius: var(--radius);
}
.filecard::before {
  content: ""; grid-row: 1 / span 2; align-self: center;
  width: 34px; height: 20px; background: var(--bar); border-radius: 2px;
}
.filecard__name {
  grid-column: 2; grid-row: 1;
  min-width: 0; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere;
}
/* Swapping the photo belongs next to the photo's name, not buried in a row of
   buttons at the far end of the page. */
.filecard__change { grid-column: 3; grid-row: 1 / span 2; align-self: center; white-space: nowrap; }
/* On a phone there is no room for a third column: taking one squeezed the
   dimensions into five lines. Put the action on its own row instead. */
@media (max-width: 599.98px) {
  .filecard { grid-template-columns: auto minmax(0, 1fr); }
  .filecard__change { grid-column: 1 / -1; grid-row: 3; justify-self: start; }
}
/* Never nowrap: the dimensions plus the file size ran straight out of the
   right-hand edge of the card. */
.filecard__meta {
  grid-column: 2; grid-row: 2; min-width: 0;
  font-family: var(--font-mono); font-size: var(--fs-100);
  text-transform: uppercase; letter-spacing: .08em; line-height: 1.5;
  color: var(--ink-soft);
}

/* --- 21 · TOOL UI · EXPORT OPTIONS & REGION COUNT -------------------------- */
.export-opts {
  display: grid; gap: var(--s-4);
  margin-block: var(--s-5); padding: var(--s-4) var(--s-5);
  background: var(--panel); border: var(--hair); border-radius: var(--radius);
}
.export-opts label {
  display: block; margin-bottom: .4rem;
  font-family: var(--font-mono); font-size: var(--fs-100);
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-soft);
}
.export-opts :is(select, input[type="number"], input[type="text"]) {
  width: 100%; min-height: var(--tap); padding: .5rem .6rem;
  background: var(--panel); border: var(--hair); border-radius: var(--radius);
  font-size: var(--fs-300);
}
.export-opts input[type="range"] { width: 100%; min-height: var(--tap); accent-color: var(--bar); }
.export-opts :is(input[type="checkbox"], input[type="radio"]) {
  width: 22px; height: 22px; accent-color: var(--bar);
}
.export-opts p { margin-top: .35rem; font-size: var(--fs-300); color: var(--ink-soft); }
@media (min-width: 560px) { .export-opts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.region-count {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 34px; padding: .25rem .65rem;
  background: var(--panel); border: var(--hair); border-radius: var(--radius);
  font-family: var(--font-mono); font-size: var(--fs-100); font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink);
}
.region-count::before {
  content: ""; width: 14px; height: 9px; background: var(--bar); border-radius: 1px;
}

