/* ==========================================================================
   Wrencloud Tools kit — the bench every tool is built on.

   Load with:  <link rel="stylesheet" href="../fonts/fonts.css">
               <link rel="stylesheet" href="tokens.css">
               <link rel="stylesheet" href="site.css">
               <link rel="stylesheet" href="kit.css">

   A tool is a sheet of paper on the page (.ob-app): an options column on the
   left, a bar of actions across the top, and the work underneath. Ink rules
   divide it; violet is anything you can press; mono labels name the parts.
   It stays paper-coloured in dark mode, like every sheet (tokens.css).

   Every colour, size and radius comes from tokens.css. Do not re-declare them.
   ========================================================================== */

/* Any author rule that sets `display` beats the browser's own
   `[hidden] { display: none }`, because a UA stylesheet always loses to an
   author one. Nearly every layout class below sets a display, so without this
   the `hidden` attribute silently does nothing on them — the element stays on
   screen and the bug looks like broken logic rather than broken CSS. This is
   the one place !important is the right tool. */
[hidden] { display: none !important; }

/* ---------- The bench: where the tool sits on the page ------------------- */

.wc-bench { padding-top: 24px; }

/* Tall enough to fill the window under the header when you scroll to it, so
   an editor gets the whole screen, and never so tall that a large monitor
   turns it into a corridor. */
.ob-app {
  display: flex;
  height: clamp(540px, calc(100vh - var(--hdr-h) - 32px), 940px);
  height: clamp(540px, calc(100dvh - var(--hdr-h) - 32px), 940px);
  min-height: 0;
  background: var(--sheet); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: var(--shadow);
  font: 400 var(--fs-ui)/1.5 var(--font);
  position: relative;
}
.ob-side {
  flex: 0 0 280px; width: 280px;
  background: var(--sheet-2);
  border-right: 1px solid var(--ink);
  overflow-y: auto; overscroll-behavior: contain;
  padding: 18px;
}
.ob-side.wide { flex-basis: 330px; width: 330px; }
.ob-main {
  flex: 1 1 auto; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.ob-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 22px; }
.ob-body.flush { padding: 0; }
.ob-split { display: flex; gap: 16px; height: 100%; min-height: 0; }
.ob-split > * { flex: 1 1 0; min-width: 0; }
.ob-col { display: flex; flex-direction: column; min-height: 0; gap: 8px; }
.ob-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ob-row.tight { gap: 6px; }
.ob-grow { flex: 1 1 auto; min-width: 0; }
.ob-spacer { flex: 1 1 auto; }

/* The bar of actions: the sheet's own head. */
.ob-bar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 12px 18px;
  background: var(--sheet);
  border-bottom: 1px solid var(--ink);
}
.ob-bar.bottom { border-bottom: 0; border-top: 1px solid var(--ink); }

/* Inside the hub, the hub draws the page around the tool: its own header,
   the tool's name and the way back. The tool page shows only its bench, so
   nothing appears twice. The h1 stays for screen readers. */
html.ob-framed, html.ob-framed body { height: 100%; overflow: hidden; }
.ob-framed body.wc { min-height: 0; display: block; }
.ob-framed .wc-skip, .ob-framed .wc-strip, .ob-framed .wc-hdr, .ob-framed .wc-side,
.ob-framed .wc-scrim, .ob-framed .wc-crumbs, .ob-framed .wc-sec, .ob-framed .wc-ftr { display: none !important; }
.ob-framed .wc-shell, .ob-framed .wc-col { display: block; height: 100%; min-height: 0; padding: 0; }
.ob-framed .wc-phead {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.ob-framed main { display: block; height: 100%; }
.ob-framed .wc-bench { padding: 0; max-width: none; height: 100%; }
.ob-framed .ob-app { height: 100%; border: 0; box-shadow: none; }

/* ---------- Type -------------------------------------------------------- */

.ob-h {
  margin: 0 0 10px;
  font: 700 var(--fs-body)/1.2 var(--display); font-stretch: 85%; color: var(--ink);
}
.ob-eyebrow {
  margin: 0 0 10px;
  font: 500 var(--fs-label)/1.2 var(--mono);
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2);
}
.ob-muted { color: var(--fg-2); }
.ob-mono { font-family: var(--mono); }
.ob-small { font-size: var(--fs-cap); }
.ob-hint {
  margin: 10px 0 0;
  font: 400 var(--fs-ui)/1.45 var(--serif); color: var(--fg-2);
}
.ob-hint code, .ob-hint .ob-mono { font-family: var(--mono); font-size: var(--fs-cap); }
.ob-err { color: var(--danger); }
.ob-ok { color: var(--ok); }

.ob-sect { padding-bottom: 18px; margin-bottom: 18px; border-bottom: 1px solid var(--line2); }
.ob-sect:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }

/* ---------- Buttons ----------------------------------------------------- */

.ob-btn {
  font: 700 var(--fs-ui)/1.1 var(--display);
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--ink);
  border-radius: var(--r);
  min-height: max(36px, var(--tap));
  padding: 0 14px;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  white-space: nowrap;
  transition: background .13s, border-color .13s, color .13s, opacity .13s;
  -webkit-tap-highlight-color: transparent;
}
.ob-btn:hover:not(:disabled) { background: var(--sheet-2); }
.ob-btn:active:not(:disabled) { transform: translateY(1px); }
.ob-btn:disabled { opacity: .4; cursor: default; }
.ob-btn:focus-visible { outline: 3px solid var(--violet); outline-offset: 2px; }
.ob-btn svg { width: 15px; height: 15px; flex: none; }

.ob-btn.primary { background: var(--violet); border-color: var(--violet); color: var(--white); }
.ob-btn.primary:hover:not(:disabled) { background: var(--violet-hover); border-color: var(--violet-hover); }
.ob-btn.ghost { background: transparent; border-color: transparent; color: var(--ink-2); }
.ob-btn.ghost:hover:not(:disabled) { background: var(--sheet-2); color: var(--ink); }
.ob-btn.danger:hover:not(:disabled) { border-color: var(--danger); color: var(--danger); }
.ob-btn.block { width: 100%; }
.ob-btn.sm { min-height: max(28px, var(--tap)); padding: 0 10px; font-size: var(--fs-cap); }

/* Segmented control: the chosen one is inked in, like a switch thrown. */
.ob-seg {
  display: flex; background: var(--white);
  border: 1px solid var(--ink); border-radius: var(--r); overflow: hidden;
}
.ob-seg > button {
  flex: 1 1 0; min-width: 0;
  font: 600 var(--fs-ui)/1.15 var(--display);
  background: transparent; border: 0; color: var(--ink-2);
  padding: 9px 10px; cursor: pointer; white-space: nowrap;
  transition: background .13s, color .13s;
}
.ob-seg > button + button { border-left: 1px solid var(--rule); }
.ob-seg > button:hover { background: var(--sheet-2); color: var(--ink); }
.ob-seg > button.on { background: var(--ink); color: var(--sheet); }
.ob-seg > button:focus-visible { outline: 3px solid var(--violet); outline-offset: -3px; }
.ob-seg.vert { flex-direction: column; }
.ob-seg.vert > button { text-align: left; padding: 10px 12px; }
.ob-seg.vert > button + button { border-left: 0; border-top: 1px solid var(--rule); }

/* ---------- Inputs ------------------------------------------------------ */

.ob-field { margin-bottom: 14px; }
.ob-field:last-child { margin-bottom: 0; }
.ob-label {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-bottom: 6px; font-size: var(--fs-cap); font-weight: 500; color: var(--ink-2);
}
.ob-label output, .ob-label .val {
  font: var(--fs-label)/1 var(--mono); color: var(--ink);
  background: var(--white); border: 1px solid var(--rule);
  border-radius: var(--r); padding: 4px 6px;
}

.ob-input, .ob-textarea, .ob-select {
  width: 100%;
  font: var(--fs-ui)/1.5 var(--font);
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--ink);
  border-radius: var(--r);
  padding: 8px 10px;
}
.ob-input:focus-visible, .ob-textarea:focus-visible, .ob-select:focus-visible { outline: 3px solid var(--violet); outline-offset: 0; }
.ob-input:focus, .ob-textarea:focus, .ob-select:focus { border-color: var(--ink); }
.ob-input::placeholder, .ob-textarea::placeholder { color: var(--ink-3); }
.ob-input.mono, .ob-textarea.mono { font-family: var(--mono); font-size: var(--fs-cap); }
.ob-textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.ob-textarea.fill { height: 100%; min-height: 0; resize: none; flex: 1 1 auto; }
.ob-select { appearance: none; cursor: pointer; padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%),
                    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
.ob-select option { background: var(--white); color: var(--ink); }

input[type=range].ob-range {
  --pct: 0%;
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: var(--tap);
  background: transparent; margin: 0; cursor: pointer;
}
input[type=range].ob-range::-webkit-slider-runnable-track {
  height: 3px; border-radius: 0;
  background: linear-gradient(90deg, var(--violet) 0 var(--pct), var(--rule) var(--pct) 100%);
}
input[type=range].ob-range::-webkit-slider-thumb {
  -webkit-appearance: none; width: 14px; height: 14px; margin-top: -5.5px;
  border-radius: var(--r); background: var(--ink); border: 0;
}
input[type=range].ob-range::-moz-range-track { height: 3px; background: var(--rule); }
input[type=range].ob-range::-moz-range-progress { height: 3px; background: var(--violet); }
input[type=range].ob-range::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: var(--r); background: var(--ink); border: 0;
}
input[type=range].ob-range:focus-visible { outline: 3px solid var(--violet); outline-offset: 2px; }

.ob-check { display: flex; align-items: center; gap: 9px; cursor: pointer; font-size: var(--fs-ui); }
.ob-check input { width: 16px; height: 16px; accent-color: var(--violet); cursor: pointer; flex: none; margin: 0; }

/* ---------- Targets ----------------------------------------------------- */

/* WCAG 2.2 §2.5.8: nothing you can press is smaller than 24×24. --tap is 24
   with a mouse and 44 under a coarse pointer (tokens.css), so a desktop keeps
   its density and a phone gets targets sized for a thumb. A checkbox's target
   is its whole label, which is why .ob-check carries the floor rather than the
   16px box inside it. Tool pages with controls of their own must meet the
   same floor — the conformance test in tests/index.html measures every page. */
.ob-seg > button, .ob-input, .ob-select, .ob-check { min-height: var(--tap); }
.ob-btn { min-width: var(--tap); }
@media (pointer: coarse) {
  button, select, summary, input[type=color] { min-height: var(--tap); }
  button { min-width: var(--tap); }
  summary { display: flex; align-items: center; }
}

/* ---------- Panels, cards, lists ---------------------------------------- */

.ob-panel {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 16px;
}
.ob-panel.flush { padding: 0; overflow: hidden; }

.ob-stat {
  background: var(--white); border: 1px solid var(--rule);
  border-radius: var(--r); padding: 10px 12px;
  flex: 1 1 auto; min-width: 92px;
}
.ob-stat .k {
  font: var(--fs-label)/1.2 var(--mono); letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-2); margin-bottom: 6px;
}
.ob-stat .v { font: 800 var(--fs-lead)/1.1 var(--display); font-stretch: 80%; color: var(--ink); word-break: break-all; }
.ob-stat .v.sm { font: 500 var(--fs-ui)/1.3 var(--mono); }

.ob-list { display: flex; flex-direction: column; gap: 6px; }
.ob-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  background: var(--white); border: 1px solid var(--rule);
  border-radius: var(--r);
  font-size: var(--fs-ui);
}
.ob-item .name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-item .meta { font: var(--fs-label)/1 var(--mono); color: var(--ink-3); flex: none; }

/* ---------- Dropzone ---------------------------------------------------- */

.ob-drop {
  border: 2px dashed var(--ink-3);
  border-radius: var(--r);
  padding: 36px 20px;
  text-align: center;
  color: var(--ink-2);
  background: var(--white);
  transition: border-color .13s, background .13s;
  cursor: pointer;
}
.ob-drop:hover { border-color: var(--violet); background: var(--sheet-hl); }
.ob-drop.over { border-color: var(--violet); border-style: solid; background: var(--accent-wash); color: var(--ink); }
.ob-drop .big { font: 800 var(--fs-lead)/1.15 var(--display); font-stretch: 80%; color: var(--ink); margin-bottom: 6px; }
.ob-drop .sub { font: 400 var(--fs-ui)/1.45 var(--serif); }

.ob-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; height: 100%; min-height: 200px;
  color: var(--ink-3); text-align: center; padding: 30px;
  font: 400 var(--fs-ui)/1.45 var(--serif);
}
.ob-empty .big { font: 800 var(--fs-lead)/1.15 var(--display); font-stretch: 80%; color: var(--ink-2); }

/* ---------- Output surfaces --------------------------------------------- */

.ob-out {
  font: var(--fs-cap)/1.7 var(--mono);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  overflow: auto;
  margin: 0;
}
.ob-out.fill { flex: 1 1 auto; min-height: 0; }

.ob-tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 7px; border-radius: var(--r);
  font: 500 var(--fs-label)/1.3 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  border: 1px solid var(--ink); color: var(--ink);
  white-space: nowrap;
}
.ob-tag.ok { color: var(--ok); border-color: var(--ok); }
.ob-tag.err { color: var(--danger); border-color: var(--danger); }
.ob-tag.warn { color: var(--warn); border-color: var(--warn); }

/* ---------- Toast ------------------------------------------------------- */

#ob-toast {
  position: fixed; left: 50%; bottom: 22px;
  transform: translate(-50%, 12px);
  display: flex; align-items: center; gap: 10px;
  padding: 12px 18px;
  background: var(--ink); border: 1px solid var(--ink);
  border-radius: var(--r); color: var(--sheet);
  font: 500 var(--fs-ui)/1.4 var(--font);
  box-shadow: 0 18px 40px -18px rgba(22, 20, 15, .6);
  opacity: 0; pointer-events: none;
  transition: opacity .17s, transform .17s;
  z-index: 9999; max-width: min(88vw, 460px);
}
#ob-toast.show { opacity: 1; transform: translate(-50%, 0); }
#ob-toast::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--sheet); flex: none;
}
#ob-toast.err::before { background: var(--marker); }
#ob-toast.ok::before { background: #5FD3A4; }

/* ---------- Scrollbars -------------------------------------------------- */

.ob-app * { scrollbar-width: thin; scrollbar-color: var(--rule) transparent; }
.ob-app *::-webkit-scrollbar { width: 10px; height: 10px; }
.ob-app *::-webkit-scrollbar-thumb { background: var(--rule); border-radius: var(--r); border: 3px solid transparent; background-clip: content-box; }
.ob-app *::-webkit-scrollbar-thumb:hover { background: var(--ink-3); background-clip: content-box; }
.ob-app *::-webkit-scrollbar-corner { background: transparent; }

/* ---------- Motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .ob-btn:active:not(:disabled) { transform: none; }
}

/* ---------- Responsive -------------------------------------------------- */

/* The options button only exists on phones; kit.js injects it into .ob-bar
   whenever a tool has a sidebar. */
.ob-sheet-toggle { display: none; }
.ob-sheet-backdrop { display: none; }

@media (max-width: 780px) {
  .wc-bench { margin-inline: calc(var(--gutter) * -1); padding-top: 20px; }
  .ob-app {
    flex-direction: column;
    height: calc(100vh - 24px); height: calc(100svh - 24px);
    min-height: 520px;
    border-left: 0; border-right: 0;
  }

  /* The options column becomes a sheet pulled up from the bottom, out of the
     flow, so the tool itself gets the whole screen and the options are one
     tap away. */
  .ob-side, .ob-side.wide {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    flex: none; width: 100%;
    max-height: 76vh; max-height: 76dvh;
    border: 0; border-top: 2px solid var(--ink);
    box-shadow: 0 -24px 50px -20px rgba(22, 20, 15, .45);
    padding: 20px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    transform: translateY(101%);
    transition: transform .22s ease;
    visibility: hidden;
  }
  .ob-app.sheet-open .ob-side,
  .ob-app.sheet-open .ob-side.wide { transform: translateY(0); visibility: visible; }

  /* The grab handle, drawn rather than added as an element so no tool markup
     has to change. */
  .ob-side::before {
    content: ""; position: sticky; top: -6px; display: block;
    width: 40px; height: 4px; margin: -8px auto 14px;
    background: var(--ink-3);
  }

  .ob-sheet-backdrop {
    display: block; position: fixed; inset: 0; z-index: 55;
    background: rgba(22, 20, 15, .45);
    opacity: 0; pointer-events: none; transition: opacity .22s;
    border: 0; padding: 0;
  }
  .ob-app.sheet-open .ob-sheet-backdrop { opacity: 1; pointer-events: auto; }

  .ob-sheet-toggle { display: inline-flex; }

  .ob-split { flex-direction: column; }
  .ob-body { padding: 16px; }
  .ob-bar { padding: 10px 12px; }
}
