/* ===========================================================
   The Big Head — Free Tools
   Layered on top of style.css; reuses its tokens.
   =========================================================== */

.tools-body{--tool-r:18px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.nav-links a.is-current{color:var(--txt)}

/* Same grid as .nav-inner / .section / .blog-wrap / .th-main. */
.tool-main{max-width:var(--maxw);margin:0 auto;padding:26px 24px 90px}
@media(max-width:760px){.tool-main{padding-inline:20px}}

/* ---------- Breadcrumbs ---------- */
.crumbs{font-size:.83rem;color:var(--muted-2);display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:22px}
.crumbs a{color:var(--muted);font-weight:600}
.crumbs a:hover{color:var(--accent-2)}
.crumbs span[aria-current]{color:var(--txt);font-weight:600}

/* ---------- Hub header ---------- */
/* Left-aligned to match /free-themes, /apps, /blog and the homepage.
   This was centred in a 780px column, so navigating between hubs threw
   the heading from one alignment to another. */
.hub-head{max-width:760px;margin:14px 0 40px}
.hub-head .kicker,.tool-head .kicker{display:inline-block;font-size:.76rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-2);margin-bottom:14px}
.hub-head h1{font-size:clamp(2.1rem,5.4vw,3.5rem);margin-bottom:16px}
/* ⚠️ `margin:0 auto` centred this 660px lead inside a LEFT-aligned 760px
   .hub-head, so the paragraph sat 50px right of the h1 above it and read as
   an accidental indent. The themes hub aligns its lead flush with the
   heading; this now matches. */
.hub-head .lead{color:var(--muted);font-size:1.03rem;max-width:660px;margin:0}

.hub-search{margin:28px auto 20px;max-width:520px}
.hub-search input{width:100%;padding:15px 20px;border-radius:999px;border:1px solid var(--border-strong);background:var(--panel-2);color:var(--txt);font-family:inherit;font-size:.98rem;outline:none;transition:border-color .18s,box-shadow .18s}
.hub-search input::placeholder{color:var(--muted-2)}
.hub-search input:focus{border-color: var(--accent-ink);box-shadow:0 0 0 4px var(--border)}

.hub-trust{display:flex;flex-wrap:wrap;justify-content:center;gap:10px}
.hub-trust span{font-size:.82rem;color:var(--muted);background:var(--panel-2);border:1px solid var(--border);padding:7px 14px;border-radius:999px}
.hub-trust strong{color:var(--success);font-weight:800}

/* ---------- Filters ---------- */
.hub-filters{display:flex;flex-wrap:wrap;gap:9px;justify-content:center;margin-bottom:42px}
.hub-filters .tab{background:var(--panel-2);border:1px solid var(--border);color:var(--muted);padding:9px 16px;border-radius:999px;font-family:inherit;font-weight:700;font-size:.86rem;cursor:pointer;transition:all .16s}
.hub-filters .tab:hover{color:var(--txt);border-color:var(--border-strong)}
/* ⚠️ Was a blue-to-orange gradient with a 26px glow — a dark-theme leftover
   that clashed with the paper design and did not match the identical filter
   bar on /free-themes/, which uses a flat accent pill. One control, two
   looks, on two pages a visitor moves between. Now they match. */
.hub-filters .tab.on{background:var(--accent);color:var(--bg);border-color:transparent;box-shadow:none}

.hub-empty{text-align:center;padding:60px 20px;color:var(--muted)}
.hub-empty p{font-weight:800;font-size:1.2rem;color:var(--txt);margin-bottom:6px}
.hub-empty a{color:var(--accent-2);font-weight:700}

/* ---------- Category blocks + cards ---------- */
.hub-cat{margin-bottom:52px}
.hub-cat[hidden]{display:none}
.hub-cat-head{margin-bottom:20px}
.hub-cat-head h2{font-size:1.5rem;display:flex;align-items:center;gap:10px}
.hub-cat-head p{color:var(--muted-2);font-size:.92rem;margin-top:5px}

.tool-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%, 258px),1fr));gap:16px}
.tool-card{display:flex;flex-direction:column;gap:8px;background:linear-gradient(160deg,var(--panel),var(--bg-soft));border:1px solid var(--border);border-radius:var(--tool-r);padding:22px 20px;transition:transform .18s ease,border-color .18s ease,box-shadow .18s ease;position:relative;overflow:hidden}
.tool-card:before{content:'';position:absolute;inset:0 0 auto;height:2px;background:linear-gradient(90deg,var(--accent),var(--accent-2));opacity:0;transition:opacity .2s}
.tool-card:hover{transform:none;border-color:var(--border-strong);box-shadow:0 20px 46px rgba(0,0,0,.32)}
.tool-card:hover:before{opacity:1}
.tool-card[hidden]{display:none}
.tc-ico{font-size:1.6rem;line-height:1;width:44px;height:44px;display:grid;place-items:center;border-radius:13px;background:var(--panel-2);border:1px solid var(--border);margin-bottom:4px}
.tool-card h3{font-size:1.06rem;letter-spacing:-.03em}
.tool-card p{color:var(--muted);font-size:.88rem;line-height:1.55;flex:1}
.tc-go{font-size:.82rem;font-weight:800;color:var(--accent-2);margin-top:4px}

/* ---------- Tool page header ---------- */
.tool-head{max-width:760px;margin-bottom:30px}
.tool-badge{display:inline-flex;align-items:center;gap:7px;font-size:.76rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--accent-2);background:var(--panel-2);border:1px solid var(--border-strong);padding:6px 13px;border-radius:999px;margin-bottom:16px}
.tool-head h1{font-size:clamp(1.95rem,4.6vw,3rem);margin-bottom:14px}
.tool-head .lead{color:var(--muted);font-size:1.01rem}
.tool-privacy{margin-top:14px;font-size:.85rem;color:var(--success);font-weight:600;display:flex;align-items:center;gap:7px}

/* ---------- Tool UI kit ---------- */
.panel{background:linear-gradient(165deg,var(--panel),var(--bg-soft));border:1px solid var(--border);border-radius:var(--tool-r);padding:24px;margin-bottom:18px}
.panel h2{font-size:1.15rem;margin-bottom:6px}
.panel h3{font-size:1rem;margin-bottom:10px}
.panel > p.hint{color:var(--muted-2);font-size:.87rem;margin-bottom:16px}
.panel-split{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.row{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end}
.row > *{min-width:0}
.grow{flex:1}

.field{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.field label,.lbl{font-size:.8rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--muted-2)}
.field input,.field select,.field textarea,.inp{
  width:100%;padding:12px 14px;border-radius:12px;border:1px solid var(--border-strong);
  background:var(--panel-2);color:var(--txt);font-family:inherit;font-size:.95rem;outline:none;
  transition:border-color .16s,box-shadow .16s}
.field textarea,textarea.inp{resize:vertical;min-height:130px;line-height:1.6}
.field input:focus,.field select:focus,.field textarea:focus,.inp:focus{border-color: var(--accent-ink);box-shadow:0 0 0 4px var(--border)}
.field select,select.inp{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%23a9abc0' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;background-size:11px;padding-right:36px}
.field .help{font-size:.78rem;color:var(--muted-2);font-weight:500;text-transform:none;letter-spacing:0}
.field-inline{flex-direction:row;align-items:center;gap:10px}
.field-inline label{text-transform:none;letter-spacing:0;font-size:.9rem;font-weight:600;color:var(--txt)}
input[type=checkbox],input[type=radio]{width:17px;height:17px;accent-color: var(--accent-ink);cursor:pointer;flex:none}
input[type=range]{width:100%;accent-color: var(--accent-ink);cursor:pointer}
input[type=color]{width:100%;height:46px;padding:3px;cursor:pointer;background:var(--panel-2);border:1px solid var(--border-strong);border-radius:12px}
code.mono,.mono{font-family:ui-monospace,'SF Mono',Menlo,monospace}

.btn-row{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px}
.btn-mini{background:var(--panel-2);border:1px solid var(--border-strong);color:var(--txt);padding:9px 15px;border-radius:999px;font-family:inherit;font-weight:700;font-size:.85rem;cursor:pointer;transition:all .16s}
/* ⚠️ was color:var(--bg) — paper text on the paper-toned --panel-2, i.e. the
   label vanished the moment you hovered it. */
.btn-mini:hover{border-color:var(--accent-ink);color:var(--accent-ink);background:var(--panel-2)}
.btn-mini.on{background:var(--accent);border-color:transparent;color:var(--bg)}
button.btn{font-family:inherit}
button:disabled,.btn:disabled{opacity:.45;cursor:not-allowed;transform:none!important}

/* Drop zone */
.drop{border:2px dashed var(--border-strong);border-radius:var(--tool-r);padding:38px 22px;text-align:center;cursor:pointer;transition:all .18s;background:var(--panel-2)}
.drop:hover,.drop.over{border-color: var(--accent-ink);background:var(--panel-2)}
.drop strong{display:block;font-size:1.05rem;margin-bottom:5px}
.drop span{color:var(--muted-2);font-size:.86rem}
.drop input[type=file]{display:none}

/* Result / output blocks */
.out{background:rgba(0,0,0,.28);border:1px solid var(--border);border-radius:14px;padding:16px;font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:.88rem;line-height:1.65;white-space:pre-wrap;word-break:break-word;max-height:460px;overflow:auto;color:#d8e6ff}
.out:empty{display:none}
.stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%, 118px),1fr));gap:12px;margin-bottom:16px}
.stat{background:var(--panel-2);border:1px solid var(--border);border-radius:14px;padding:14px;text-align:center}
.stat b{display:block;font-family:'Bricolage Grotesque',sans-serif;font-size:1.55rem;font-weight:800;letter-spacing:-.04em;color:var(--txt);line-height:1.1}
.stat span{display:block;font-size:.74rem;color:var(--muted-2);text-transform:uppercase;letter-spacing:.08em;font-weight:700;margin-top:5px}
.stat.good b{color:var(--success)}
.stat.warn b{color:var(--accent-2)}   /* #ffcf6b was 1.3:1 on the paper panel */
.stat.bad b{color:var(--danger)}

.note{font-size:.85rem;color:var(--muted-2);margin-top:12px}
.err{color:var(--danger);font-size:.88rem;font-weight:600;margin-top:10px}
.ok{color:var(--success);font-size:.88rem;font-weight:600;margin-top:10px}

table.tbl{width:100%;border-collapse:collapse;font-size:.9rem}
table.tbl th,table.tbl td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--border)}
table.tbl th{font-size:.74rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted-2)}
table.tbl td.num,table.tbl th.num{text-align:right;font-variant-numeric:tabular-nums}

/* File list */
.filelist{display:flex;flex-direction:column;gap:9px;margin-top:16px}
.fileitem{display:flex;align-items:center;gap:12px;background:var(--panel-2);border:1px solid var(--border);border-radius:13px;padding:11px 13px}
.fileitem img{width:46px;height:46px;object-fit:cover;border-radius:9px;flex:none;background:#000}
.fileitem .fi-body{flex:1;min-width:0}
.fileitem .fi-name{font-weight:700;font-size:.9rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fileitem .fi-meta{font-size:.79rem;color:var(--muted-2)}
.fileitem .fi-meta .down{color:var(--success);font-weight:700}
.fileitem button{background:none;border:0;color:var(--muted-2);cursor:pointer;font-size:1.1rem;padding:4px 8px;font-family:inherit}
.fileitem button:hover{color:var(--danger)}
.fileitem.drag{opacity:.45}

/* ---------- FAQ / related / pitch ---------- */
.tool-faq{margin:52px 0 0;max-width:820px}
.tool-faq h2,.tool-related h2{font-size:1.5rem;margin-bottom:18px}
.tool-faq details{border:1px solid var(--border);border-radius:14px;padding:15px 18px;margin-bottom:10px;background:var(--panel-2)}
.tool-faq summary{cursor:pointer;font-weight:700;font-size:.98rem;list-style:none}
.tool-faq summary::-webkit-details-marker{display:none}
.tool-faq summary:before{content:'+';color:var(--accent-2);font-weight:800;margin-right:10px}
.tool-faq details[open] summary:before{content:'–'}
.tool-faq p{color:var(--muted);font-size:.93rem;margin-top:10px;padding-left:22px}

.tool-related{margin-top:56px}
.tool-allink{margin-top:20px}

.tool-pitch{margin-top:56px;background:var(--panel-2);border:1px solid var(--border-strong);border-radius:26px;padding:34px;display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.tool-pitch h2{font-size:1.5rem;margin-bottom:8px}
.tool-pitch p{color:var(--muted);font-size:.95rem;max-width:640px}
.tool-pitch > div{flex:1;min-width:260px}

.hub-why{margin-top:20px}
.hub-why h2{font-size:1.5rem;margin-bottom:20px}
.why-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%, 258px),1fr));gap:16px}
.why-grid > div{background:var(--panel-2);border:1px solid var(--border);border-radius:var(--tool-r);padding:22px}
.why-grid h3{font-size:1.02rem;margin-bottom:8px}
.why-grid p{color:var(--muted);font-size:.9rem;line-height:1.6}
.why-grid a{color:var(--accent-2);font-weight:700}

/* ---------- Tool-specific ---------- */
/* Tier list */

/* Wheel */
.wheel-wrap{display:grid;place-items:center;gap:16px}
#wheelCanvas{max-width:100%;height:auto;filter:drop-shadow(0 18px 40px rgba(0,0,0,.45))}
.winner{font-family:'Bricolage Grotesque',sans-serif;font-size:1.9rem;font-weight:800;text-align:center;letter-spacing:-.04em;background:linear-gradient(135deg,var(--accent-3),var(--accent-2));-webkit-background-clip:text;background-clip:text;color:transparent;min-height:2.4rem}

/* Palette */
.palette{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%, 120px),1fr));gap:12px}
.swatch{border-radius:14px;overflow:hidden;border:1px solid var(--border);cursor:pointer;transition:transform .16s}
.swatch:hover{transform:none}
.swatch .sw-color{height:110px}
/* ⚠️ Was background:rgba(0,0,0,.35) — a dark-theme scrim. On the paper theme it
   lands as a mid grey the label text cannot survive: the shade numbers and hex
   codes measured 1.21:1, i.e. a palette tool whose palette you cannot read. */
.swatch .sw-meta{padding:10px;background:var(--panel-2);color:var(--txt);border-top:1px solid var(--border);font-family:ui-monospace,Menlo,monospace;font-size:.82rem;display:flex;justify-content:space-between;align-items:center;gap:6px}
.swatch .sw-lock{background:none;border:0;cursor:pointer;font-size:.9rem;padding:0}

/* Contrast preview */
.cc-preview{border-radius:14px;padding:26px;border:1px solid var(--border);margin-bottom:14px}
.cc-preview p{margin-bottom:10px}
.cc-preview .big{font-size:1.6rem;font-weight:800;font-family:'Bricolage Grotesque',sans-serif}
.badge{display:inline-block;padding:5px 11px;border-radius:999px;font-size:.75rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase}
.badge.pass{background:rgba(83,233,143,.16);color:var(--success);border:1px solid rgba(83,233,143,.35)}
.badge.fail{background:rgba(255,141,141,.13);color:var(--danger);border:1px solid rgba(255,141,141,.32)}

/* Meme / canvas previews */
.canvas-wrap{background:#0b0d18;border:1px solid var(--border);border-radius:14px;padding:14px;display:grid;place-items:center;overflow:auto}
.canvas-wrap canvas,.canvas-wrap img{max-width:100%;height:auto;border-radius:8px}

/* Invoice */

/* Favicon output */
.fav-grid{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end}
.fav-grid figure{text-align:center}
.fav-grid img{background:#fff;border-radius:6px;image-rendering:auto;display:block;margin:0 auto 6px}
.fav-grid figcaption{font-size:.74rem;color:var(--muted-2)}

/* ---------- Print (invoice) ---------- */
@media print{
  /* ⚠️ This list must include EVERY piece of page chrome. It was written before
     .tool-intro was split out of .tool-head and before the mobile .bottom-nav
     existed, so printing an invoice put the tool's lead paragraph, the
     "🔒 Runs entirely in your browser" note and the "Home Themes Blog Apps More"
     bar on top of the document. Anything added to the shell has to be added
     here too. */
  body{background:#fff!important;padding-bottom:0!important}
  .nav,.footer,.crumbs,.tool-head,.tool-intro,.tool-privacy,.tool-badge,
  .tool-faq,.tool-related,.tool-pitch,.site-noise,.bottom-nav,.skip,
  .no-print,.panel.no-print{display:none!important}
  .tool-main{padding:0;max-width:none}
  .panel{border:0;background:none;padding:0;margin:0;box-shadow:none}
  /* Browser page headers (date, title, URL) are a PRINT-DIALOG setting and
     cannot be removed from CSS. The tools that generate a real PDF print that
     file instead, which is the only way to be rid of them. */
  @page{margin:12mm}
}

/* ---------- Responsive ---------- */
@media (max-width:820px){
  .panel-split{grid-template-columns:1fr}
  .tool-pitch{padding:26px;text-align:left}
}
@media (max-width:640px){
  /* padding-block only — a shorthand here re-set the inline padding to 16px
     and knocked /free-tools off the shared 20px grid. */
  .tool-main{padding-block:20px 70px}
  .panel{padding:18px}
  
  
  .hub-cat{margin-bottom:38px}
  .tool-grid{grid-template-columns:1fr}
  .stat b{font-size:1.3rem}
}
@media (prefers-reduced-motion:reduce){
  .tool-card,.swatch{transition:none}
  .tool-card:hover,.swatch:hover{transform:none}
}

/* ===========================================================
   PHONE USABILITY PASS
   The tools were laid out desktop-first: on a 375px screen the
   preamble pushed the actual tool far below the fold (the picker
   wheel started ~1100px down), and primary actions were small.
   =========================================================== */
@media (max-width:700px){

  /* Get to the tool sooner. The lead copy is still there, just tighter. */
  .crumbs{margin-bottom:12px;font-size:.78rem}
  .tool-head{margin-bottom:18px}
  .tool-head h1{font-size:clamp(1.6rem,7.5vw,2.1rem);margin-bottom:10px}
  .tool-head .lead{font-size:.94rem;line-height:1.55}
  .tool-badge{margin-bottom:10px;padding:5px 11px;font-size:.7rem}
  .tool-privacy{font-size:.78rem;margin-top:10px}

  /* Primary actions are thumb-sized and full width. */
  .panel .btn,
  .btn-row > .btn{width:100%;justify-content:center;padding:15px 22px}
  .btn-row{gap:8px}
  .btn-row > .btn-mini{flex:1 1 auto;text-align:center;min-height:44px;display:inline-flex;align-items:center;justify-content:center}

  /* Fields are easier to hit, and 16px stops iOS zooming the page on focus. */
  .field input,.field select,.field textarea,.inp{font-size:16px;padding:13px 14px}
  .field{margin-bottom:16px}

  /* Drop zones do not need to be half the screen. */
  .drop{padding:26px 16px}
  .drop strong{font-size:.98rem}

  .panel{padding:16px}
  .stat-row{gap:8px}
}

/* ---------- Random picker ---------- */
/* The wheel now precedes the options in the DOM, so it is the first thing you see.
   Desktop restores the original left/right reading order with `order` alone.
   `order` works on grid items, so .panel-split stays the two-column GRID it has
   always been — switching it to flex made the two panels size to their own content
   instead of stretching to a shared height, which is a desktop layout change. */
@media (min-width:821px){
  .picker-split .panel:first-child{order:2}
  .picker-split .panel:last-child{order:1}
}
/* Deliberately not phone-only: draw() renders into a backing store scaled by
   devicePixelRatio, so the *display* size has to come from CSS instead of the
   width/height attributes. On desktop this still resolves to the original 420px. */
.wheel-wrap{width:100%}
#wheelCanvas{width:100%;max-width:420px;height:auto;aspect-ratio:1/1}
.spin-btn{min-width:180px}
@media (max-width:700px){
  .spin-btn{width:100%}
  .winner{font-size:1.6rem}
}

@media (max-width:700px){
  /* Rows keep a real label, a roomy drop area and compact controls that still
     clear 44px vertically across the three stacked buttons. */
  
  /* Row controls: ▲ ▼ ✕ stacked in 34px was a mis-tap waiting to happen. Wider
     column, taller buttons, and Delete is tinted so it is never confused with Move. */
  
  
  
  
  
  /* Bigger tiles: three still fit across a 375px row, and they are far easier to hit. */
  
  
  
}

/* ---------- Phone-first ordering ----------
   On a phone the tool itself comes immediately after the title. The explanatory lead,
   the privacy note, the FAQ and the related-tool grid all move BELOW it. Desktop keeps
   the normal reading order, where there is room for both. */
/* Base (all widths). These MUST stay above the phone block below: they used to sit
   after it, and because a media query adds no specificity the later `font-size:1.01rem`
   was silently beating the phone override, so `.tool-intro .lead` never got its .94rem
   on a phone. Desktop is unaffected — nothing else declares these two rules. */
.tool-intro .lead{color:var(--muted);font-size:1.01rem}
.tool-intro{margin-bottom:26px}

@media (max-width:700px){
  .tool-main{display:flex;flex-direction:column}
  .tool-main > *{order:2}          /* the tool's own panels */
  .crumbs{order:0}
  .tool-head{order:1}
  .tool-intro{order:5}
  .tool-faq{order:6}
  .tool-related{order:7}
  .tool-pitch{order:8}

  .tool-intro{
    border-top:1px solid var(--border);
    padding-top:18px;
    margin-top:8px;
  }
  .tool-intro .lead{font-size:.94rem;line-height:1.6;color:var(--muted)}
}

/* ===========================================================
   PHONE PASS — Image Compressor · Image Converter ·
                Image Resizer · Meme Generator
   Desktop is untouched: everything below is inside the phone
   query, and the markup only gained class names.
   Goals: the result sits next to the control that produces it,
   every field is one full-width column (nothing can exceed the
   screen), and sliders / icon buttons clear 44px.
   =========================================================== */
@media (max-width:700px){

  /* ---- shared: one field per line, grabbable sliders, real tap targets ---- */
  .ic-opts > .field,
  .cv-opts > .field,
  .rz-size > .field,
  .rz-opts > .field{flex:1 1 100%;margin-bottom:0}

  .ic-opts input[type=range],
  .cv-opts input[type=range],
  .mm-ctl input[type=range]{height:36px}

  /* min-height alone only made the ROW 44px — the checkbox stayed 17px and the label
     stayed one line tall, so the thing you could actually hit was still ~20px. Same
     treatment the other phone blocks use: bigger box, and the label fills the row. */
  .ic-opts .field-inline,
  .cv-opts .field-inline,
  .rz-size .field-inline,
  .mm-ctl .field-inline{min-height:44px;align-items:center}
  .ic-opts .field-inline input[type=checkbox],
  .cv-opts .field-inline input[type=checkbox],
  .rz-size .field-inline input[type=checkbox],
  .mm-ctl .field-inline input[type=checkbox]{width:22px;height:22px}
  .ic-opts .field-inline label,
  .cv-opts .field-inline label,
  .rz-size .field-inline label,
  .mm-ctl .field-inline label{flex:1;padding:11px 0;line-height:1.35}

  /* Per-file ⤓ / ✕ buttons were ~28px squares. */
  .ic-results .fileitem button,
  .cv-results .fileitem button{min-width:44px;min-height:44px;font-size:1.2rem;line-height:1}
  .ic-results .fileitem,
  .cv-results .fileitem{gap:10px;padding:10px}

  /* ---- Image Compressor: drop → savings → settings ----
     display:contents lifts the drop zone and the settings row out of the
     panel they share so the results card can slot between them; the settings
     row is given the panel's own card treatment so nothing looks orphaned.
     Old browsers without display:contents simply keep the desktop order. */
  .ic-setup{display:contents}
  .ic-setup > .drop{order:2;margin-bottom:18px}
  .ic-results{order:3}
  .ic-setup > .ic-opts{
    order:4;margin:0!important;padding:16px;
    background:linear-gradient(165deg,var(--panel),var(--bg-soft));
    border:1px solid var(--border);border-radius:var(--tool-r)}

  /* ---- Image Converter ----
     The output format deliberately stays ABOVE the drop zone: files are
     converted the moment they land, so the format has to be chosen first.
     It is instead the drop zone that gets the extra weight. */
  .cv-setup .drop{padding:30px 16px}
  .cv-note{margin-top:12px}

  /* ---- Image Resizer: preview + numbers before the fine print ---- */
  .rz-panel:not([hidden]){display:flex;flex-direction:column}
  .rz-h{order:1}
  .rz-presets{order:2}
  .rz-size{order:3;margin-bottom:2px}
  .rz-preview{order:4;margin-bottom:14px}
  .rz-stats{order:5}
  .rz-actions{order:6}
  .rz-opts{order:7;margin-top:6px}

  /* Presets as a tidy 2-up grid instead of a ragged wrap. */
  .rz-presets{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}
  .rz-presets .btn-mini{padding:10px 8px;font-size:.8rem}

  /* Width and Height belong side by side; the rest gets a full line. */
  .rz-size > .rz-half{flex:1 1 calc(50% - 6px)}

  /* A tall portrait resize must not push the controls off the screen. */
  .rz-preview{padding:10px}
  .rz-preview canvas{max-height:36vh;width:auto}

  /* Three tiles across so Original / New / File size read as one line and the
     Download button stays a single thumb-flick below the preview. The smaller
     type plus overflow-wrap means even "12000×16000" wraps rather than spills. */
  .rz-stats{grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:12px}
  .rz-stats .stat{padding:10px 5px}
  .rz-stats .stat b{font-size:.92rem;overflow-wrap:anywhere;letter-spacing:-.02em}
  .rz-stats .stat span{font-size:.63rem;letter-spacing:.04em;margin-top:4px}

  /* ---- Meme Generator: caption, then the live preview, then download ----
     The preview sits directly under the two text inputs so it stays on
     screen above the keyboard while you type. Styling controls move last. */
  
  
  
  
  
  
  
}

/* ===========================================================
   PHONE PASS — QR code generator, invoice generator,
                PDF merge/split, favicon generator.
   Scoped to `screen` on purpose: the invoice's whole output is a printed
   page, and a Letter page box is itself under 700px wide, so an unscoped
   max-width query would shrink the printed invoice too.
   =========================================================== */
@media screen and (max-width:700px){

  /* ---- QR code generator ----
     .panel-split stacks below 820px, which buried the finished code (and both
     download buttons) under the colour pickers and the size slider. `display:contents`
     on the input column promotes the panes, the preview and the styling options to
     siblings so they can be ordered: fields → code → styling. */
  .qr-kinds{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
  .qr-kinds .btn-mini{min-height:46px;padding:8px 6px;font-size:.82rem}
  .qr-split{gap:14px}
  .qr-split .qr-inputs{display:contents}
  .qr-split [data-pane]{order:1}
  .qr-split .qr-out{order:2}
  .qr-split .qr-style{order:3}
  .qr-out .canvas-wrap{padding:10px}
  /* draw() writes an inline 320px width/height; that is wider than a 375px screen can
     show, and the inline height was fighting `height:auto` and stretching the code. */
  #qrCanvas{width:auto!important;height:auto!important;max-width:100%}
  #qrInfo{font-size:.8rem}

  /* ---- Invoice generator ----
     Five columns of padded inputs cannot fit in 375px, so each line becomes a card:
     description on its own row, qty + unit price side by side, amount and remove last. */
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  /* .inv-items input was 0.9rem, which makes iOS zoom the page on focus. */
  
  /* Province / discount / currency kept their desktop min-widths and left ragged
     half-width boxes down the page; stack them full width instead. */
  
  /* The preview paper: 38px of padding left ~235px for a four-column table.
     Even at 18/14 the four columns have a hard floor of ~295px once an amount
     runs to "$1,494,009.00", so the paper scrolls its own overflow rather than
     spilling the last column past its right edge and widening the page. Height
     stays auto, so no vertical scrollbar appears. */
  
  /* Only the address blocks may break mid-word (long emails/URLs); letting the item
     table do it split "QTY" and "$1,250.00" across two lines. */
  
  
  
  
  
  
  
  

  /* ---- PDF merge & split ----
     Two-up mode switch, and file rows whose ↑ ↓ / ✕ controls are real tap targets. */
  .pd-modes{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .pd-modes .btn-mini{min-height:48px;padding:9px 8px;line-height:1.25}
  /* Scoped to #pdList: `.filelist` / `.fileitem` / `.fi-name` are shared with the
     image compressor and converter, which have their own phone sizing above. */
  #pdList.filelist .fileitem{gap:6px;padding:8px 10px}
  #pdList .fi-move{display:flex;flex:none;gap:2px}
  #pdList .fi-mv,#pdList .fi-rm{
    min-width:42px;min-height:44px;padding:0;font-size:1rem;
    display:grid;place-items:center;border-radius:10px;background:var(--panel-2)}
  #pdList .fi-mv{color:var(--txt)}
  #pdList .fi-name{font-size:.86rem}

  /* ---- Favicon generator ----
     A 16×16 preview is not a tap target; the whole tile is the download button now. */
  .fv-modes{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .fv-modes .btn-mini{min-height:48px}
  /* Emoji, colour and the rounded-corners toggle each get a full-width row instead of
     half-width boxes stranded by their desktop min-widths. */
  .fv-emoji-row > .field{flex:1 1 100%}
  .fav-grid{gap:10px;align-items:stretch}
  .fav-grid .fav-item{
    flex:1 1 84px;max-width:calc(33.333% - 7px);min-height:86px;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
    padding:10px 6px;border:1px solid var(--border);border-radius:14px;background:var(--panel-2)}
  .fav-grid .fav-item:active{border-color: var(--accent-ink)}
  .fav-grid img{margin:0;height:auto}   /* height attr + a shrunk width was squashing them */
  .fav-grid figcaption{font-size:.7rem}
  .fv-results .out{font-size:.78rem;padding:12px}
}

/* ===========================================================
   PHONE PASS — the four text tools
   word-counter · case-converter · lorem-ipsum-generator · slug-generator
   Markup only gained class names; everything below is phone-only, so the
   desktop layouts are untouched. Goal on a 375×812 screen: the thing you
   type into or press sits inside the first screenful, and its result is
   the next thing under it — no hunting, nothing wider than the screen.
   =========================================================== */
@media (max-width:700px){

  /* ---------- Word & Character Counter ----------
     Was: seven stat tiles (four rows deep on a phone) pushed the text box
     ~500px down. Now you land on the box, and the counts sit directly
     beneath it — box + counts together still fit above an open keyboard. */
  .wc-main{display:flex;flex-direction:column}
  .wc-input{order:1;margin-bottom:12px}
  .wc-stats{order:2;margin-bottom:0;grid-template-columns:repeat(3,1fr);gap:8px}
  .wc-actions{order:3;margin-top:14px}
  .wc-input textarea{height:150px;min-height:150px}
  .wc-stats .stat{padding:9px 5px;border-radius:12px}
  .wc-stats .stat b{font-size:1.12rem}
  .wc-stats .stat span{font-size:.62rem;letter-spacing:.04em;margin-top:3px}
  /* Seven tiles over three columns leaves one alone — let it span instead. */
  .wc-stats .stat:last-child:nth-child(3n+1){grid-column:1/-1}
  /* Both tables already sit in overflow-x wrappers, but each panel is a grid
     item whose default min-width:auto let one very long word (a pasted URL, a
     169-character "word") stretch the whole page to ~900px. min-width:0 hands
     the overflow back to the wrapper, and long tokens now wrap instead. */
  .wc-tables{gap:0}
  .wc-tables > .panel{min-width:0}
  .wc-tables table.tbl{font-size:.85rem}
  .wc-tables table.tbl th,.wc-tables table.tbl td{padding:9px 7px;overflow-wrap:anywhere}
  .wc-tables table.tbl th{font-size:.68rem;padding-left:7px}

  /* ---------- Text Case Converter ----------
     Was: 13 pills stretched to ragged widths by flex:1, and the Result
     panel started ~850px down. Now the options are a 3-up keypad of 46px
     targets (all 13 still visible, nothing squashed) and the shorter input
     brings the Result box up inside the first screenful. */
  .case-in .inp{height:96px;min-height:96px}
  /* minmax(0,1fr) rather than 1fr: a plain 1fr is minmax(auto,1fr), so the
     unbreakable labels ("PascalCase", "CONSTANT_CASE") set a ~113px floor for
     the middle column. That made the keypad ragged at 375px and, below ~345px,
     pushed the third column clean outside the panel. Zeroing the minimum keeps
     all three columns equal at every width; overflow-wrap lets the one label
     that still cannot fit break inside its own button instead of escaping it. */
  .case-keys{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
  .case-keys > .btn-mini{
    min-height:46px;padding:8px 4px;font-size:.74rem;line-height:1.2;
    white-space:normal;overflow-wrap:anywhere;border-radius:14px}
  /* A lone button on the final row spans the width instead of looking dropped. */
  .case-keys > .btn-mini:last-child:nth-child(3n+1){grid-column:1/-1}
  .case-out .inp{height:110px;min-height:110px}
  .case-out .note{overflow-wrap:anywhere}

  /* ---------- Lorem Ipsum Generator ----------
     Was: three min-width fields fighting over 311px, so "Style" squashed and
     the checkbox labels wrapped into each other. Now count + unit read as one
     line ("4 Paragraphs"), style spans the width, and the toggles are 44px rows. */
  .li-grid{display:grid;grid-template-columns:1fr 1.25fr;gap:12px;align-items:start}
  .li-grid > .field{margin-bottom:0;min-width:0 !important}
  .li-grid > .field:last-child{grid-column:1/-1}
  .li-grid input,.li-grid select{height:48px}   /* keeps the two labels on one line */
  .li-checks{display:block;margin-top:14px}
  .li-checks > .field-inline{margin-bottom:0;min-height:44px;align-items:center}
  .li-checks input[type=checkbox]{width:22px;height:22px}
  /* The label is the real target: pad it out to a 44px row you can thumb. */
  .li-checks label{line-height:1.35;padding:11px 0;flex:1}
  .li-actions{margin-top:12px}
  .li-out .out{max-height:340px;font-size:.86rem;padding:14px}

  /* ---------- URL Slug Generator ----------
     Was: two selects + two checkboxes crammed onto one wrapping row (the
     separator select ellipsised), and the long URL preview line ran off the
     screen. Now settings stack full width, the toggles pair up, and the
     finished slug + preview land inside the first screenful. */
  .sg-in .inp{height:88px;min-height:88px}
  .sg-opts{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:center}
  .sg-opts > .field{margin-bottom:0 !important;min-width:0 !important}
  .sg-opts > .field:nth-child(1),
  .sg-opts > .field:nth-child(2){grid-column:1/-1}
  .sg-opts > .field-inline{min-height:44px}
  .sg-opts input[type=checkbox]{width:22px;height:22px}
  .sg-opts .field-inline label{padding:11px 0;flex:1;line-height:1.35}
  .sg-out .inp{height:96px;min-height:96px}
  /* A long slug preview is one unbroken string — it must wrap, not overflow. */
  .sg-out .note{overflow-wrap:anywhere;word-break:break-word;line-height:1.5}
}

/* ===========================================================
   PHONE ERGONOMICS — Colour Palette Generator, Contrast Checker,
   Random Picker, Tier List Maker.
   Everything below is phone-only; desktop is untouched.
   =========================================================== */
@media (max-width:700px){

  /* ---------- Colour Palette Generator (.cp-*) ----------
     Every setting took a full row and the three copy buttons stacked, which pushed
     the palette — the whole point of the tool — well below the fold. Colour and hex
     now share a line and the copy buttons sit two-up, so on a 375px screen Reshuffle
     lands ~515px down with the first swatches immediately under it. */
  .cp-controls .row{gap:10px}
  .cp-controls .field{min-width:0!important;margin-bottom:10px}
  .cp-controls .cp-f-color,
  .cp-controls .cp-f-hex{flex:1 1 calc(50% - 5px)}
  .cp-controls .cp-f-harmony,
  .cp-controls .cp-f-count{flex:1 1 100%}
  .cp-controls input[type=color]{height:48px}
  .cp-controls input[type=range]{height:36px}
  .cp-kbd{display:none}                  /* no space bar on a phone */
  .cp-actions{margin-top:2px;gap:8px}
  .cp-actions > .btn-mini{flex:1 1 calc(50% - 4px);min-width:0;font-size:.78rem;padding:11px 8px;line-height:1.3}

  /* Two swatches per row, a hex you can read, and a lock that is a real target. */
  .cp-palette .palette{grid-template-columns:repeat(2,1fr);gap:10px}
  .cp-palette .sw-color{height:84px}
  .cp-palette .sw-meta{padding:4px 5px 4px 11px;min-height:50px;font-size:.81rem}
  .cp-palette .sw-lock{width:42px;height:42px;display:grid;place-items:center;font-size:1.05rem;flex:none}
  .cp-palette .swatch:hover{transform:none}   /* hover sticks after a tap */
  .cp-palette .note{margin-top:12px}

  /* The 50–900 ramp is reference material, so keep it short. */
  .cp-ramp .palette{grid-template-columns:repeat(2,1fr);gap:8px}
  .cp-ramp .sw-color{height:44px!important}
  .cp-ramp .sw-meta{padding:7px 9px;font-size:.75rem}
  .cp-ramp .swatch:hover{transform:none}

  /* ---------- Contrast Checker (.cc-*) ----------
     Each colour sits on one line with its hex; Swap becomes a full-width button
     instead of a 36px chip floating between the fields. */
  .cc-row{gap:10px}
  .cc-row .field{min-width:0!important;margin-bottom:12px}
  .cc-row .cc-f{flex:1 1 calc(50% - 5px)}
  .cc-row input[type=color]{height:52px}
  .cc-swapwrap{flex:1 1 100%;margin-bottom:12px!important}
  .cc-swap{margin-top:0!important;width:100%;min-height:46px;font-size:.9rem}

  /* The ratio IS the answer — full width, with the four pass/fail cards 2×2 below. */
  .cc-stats{grid-template-columns:1fr 1fr}
  .cc-stats .stat{padding:12px 8px}
  .cc-stats .stat span{font-size:.69rem;letter-spacing:.04em;margin-top:4px}
  .cc-stats .stat:first-child{grid-column:1 / -1}
  .cc-stats .stat:first-child b{font-size:1.9rem}
  .cc-preview{padding:18px}
  .cc-preview .big{font-size:1.35rem}

  /* Suggested fix: wide colour bar, then the note and the apply button under it. */
  .cc-fix #ctFix > .swatch{max-width:none!important;flex:1 1 100%}
  .cc-fix #ctFix > div:not(.swatch){min-width:0!important;padding:12px 0 0 0!important}
  .cc-levels .tbl-scroll{-webkit-overflow-scrolling:touch}
  .cc-levels table.tbl th,
  .cc-levels table.tbl td{padding:9px 8px}

  /* ---------- Random Picker (.rp-*) ----------
     Wheel first is already handled; this just uses the full panel width for it and
     makes the two option checkboxes something a thumb can actually hit. */
  .rp-wheel #wheelCanvas{max-width:min(88vw,360px)}
  .rp-wheel .wheel-wrap{gap:12px}
  .rp-opts .field-inline{min-height:44px;align-items:center;gap:12px;margin-bottom:8px}
  .rp-opts .field-inline input[type=checkbox]{width:22px;height:22px}
  .rp-opts .field-inline label{flex:1;padding:8px 0}

  
  
  
  
  
  
  
  /* The board itself (.tier-row / .tier-drop / .tier-ctl / .tile) is styled once,
     in the "Tier list on a phone" block above — do not re-declare it here. */
}

/* ===========================================================
   PHONE PASS — the four calculators
   gst-hst-calculator · mortgage-calculator · percentage-calculator · unit-converter
   Everything below is inside @media (max-width:700px), so the desktop
   layout of these four tools is byte-for-byte what it was.
   =========================================================== */
@media (max-width:700px){

  /* A big number must never push the page sideways, whatever the amount. */
  .gst-main .stat b,.mg-main .stat b,.pc-card .stat b,.uc-main .tbl td{overflow-wrap:anywhere}

  /* ---------- GST / HST calculator ---------- */
  /* Add vs Remove is the first decision on the page: give it two equal halves
     of a real segmented control instead of two pills squeezed onto one line. */
  .gst-mode{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .gst-mode .btn-mini{min-height:48px;padding:8px 10px;font-size:.82rem;line-height:1.25;border-radius:12px;white-space:normal}

  /* Province is a set-once choice (it is remembered), the amount is what you retype.
     Putting the province first lands the amount box directly above its own answer. */
  .gst-main .row > .field:last-child{order:-1}

  /* The answer reads like a receipt — label left, amount right, total last and largest. */
  .gst-main .stat-row{grid-template-columns:1fr;gap:8px;margin-bottom:0}
  .gst-main .stat{display:flex;align-items:baseline;justify-content:space-between;gap:12px;text-align:left;padding:12px 14px}
  .gst-main .stat span{order:-1;margin-top:0;flex:1 1 auto;min-width:0}
  /* flex:0 1 auto (not 0 0) so a very long amount on a 320px screen wraps inside
     its own tile instead of pushing the page sideways. Nothing shrinks at 375px. */
  .gst-main .stat b{flex:0 1 auto;min-width:0;text-align:right;font-size:1.3rem}
  .gst-main .stat.good b{font-size:1.55rem}
  #gstBreak{margin-top:12px}
  #gstBreak .tbl td{padding:9px 4px;font-size:.85rem}

  /* The provincial rate table is reference material: shrink it so it fits the
     screen instead of making people drag it sideways. */
  .gst-rates .tbl th,.gst-rates .tbl td{padding:9px 5px;font-size:.82rem}
  .gst-rates .tbl th{font-size:.67rem}

  /* ---------- Mortgage & loan calculator ---------- */
  /* Loan / down / rate / term, then the answer, then the optional settings.
     In DOM order the five results sat ~730px down: you typed a loan amount and
     saw nothing happen. Pure CSS ordering — the markup is unchanged. */
  .mg-main{display:flex;flex-direction:column}
  .mg-inputs{order:1}
  .mg-results{order:2}
  #mgSaving{order:3;margin:0 0 16px}
  .mg-extra{order:4}

  .mg-inputs,.mg-extra{gap:10px}
  .mg-inputs{align-items:flex-start}
  .mg-inputs > .field,.mg-extra > .field{min-width:0!important;flex:1 1 calc(50% - 6px)}
  .mg-extra > .field{flex:1 1 100%}
  /* Two lines are reserved for every label so a wrapped one ("Amortization (years)")
     cannot shunt its own box half an input lower than its neighbour. */
  .mg-inputs > .field > label{display:flex;align-items:flex-end;min-height:2.4em;line-height:1.2}

  .mg-results{grid-template-columns:1fr 1fr;gap:8px}
  .mg-results .stat{padding:12px 10px}
  .mg-results .stat b{font-size:1.05rem}
  .mg-results .stat:first-child{grid-column:1/-1}          /* the payment is the headline */
  .mg-results .stat:first-child b{font-size:1.9rem}

  .mg-amort .tbl th,.mg-amort .tbl td{padding:8px 5px;font-size:.79rem}
  .mg-amort .tbl th{font-size:.65rem}

  /* ---------- Percentage calculator ---------- */
  /* Six stacked calculators: the doubled gap (grid gap + panel margin) wasted
     roughly a screen and a half of scrolling. */
  .pc-grid{gap:12px}
  .pc-grid > .pc-card{margin-bottom:0}
  .pc-card h3{font-size:1.02rem;margin-bottom:12px}

  /* Two inputs per line at most — the tip splitter was three ~95px boxes. */
  .pc-card .row{gap:10px;margin-bottom:14px}
  .pc-card .row > .field{min-width:0!important;flex:1 1 calc(50% - 6px);margin-bottom:0}

  .pc-card .stat-row{grid-template-columns:repeat(auto-fit,minmax(min(100%, 88px),1fr));gap:8px}
  .pc-card .stat{padding:11px 8px}
  .pc-card .stat b{font-size:1.15rem}
  .pc-card > .stat{padding:14px}
  .pc-card > .stat b{font-size:1.7rem}                     /* the lone headline result */

  /* ---------- Unit converter ---------- */
  /* Eight categories as an even grid: wrapped, never squashed, every one 44px tall. */
  .uc-cats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
  .uc-cats .btn-mini{min-height:44px;padding:6px 6px;font-size:.78rem;border-radius:12px}

  /* "From" is picked once per category; the value is what gets retyped, so the
     number box sits directly above the table it drives. */
  .uc-inputs{gap:8px}
  .uc-inputs > .field{margin-bottom:8px}
  .uc-inputs > .field:last-child{order:-1}

  /* Every result row is a copy-to-clipboard target, so give it a thumb's height. */
  .uc-main .tbl th,.uc-main .tbl td{padding:13px 8px}
  .uc-main .tbl td:first-child{font-size:.86rem;line-height:1.35}
}

/* A long file name is clipped by CSS, never by JavaScript — same treatment as
   .fileitem .fi-name above. The tile keeps one line and the grid track has a
   fixed 118px minimum, so this cannot change any box; the full name is on the
   title attribute. */
#b6FileName{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ===========================================================
   PHONE PASS — JSON Formatter, Base64 Encoder/Decoder,
                Password Generator, Age & Date Calculator
   Everything here is phone-only (<=700px). Desktop is untouched;
   the markup only gained class names.
   =========================================================== */
@media (max-width:700px){

  /* ---- shared: a checkbox row you can actually hit with a thumb ----
     17px checkboxes inside a wrapping flex row were the worst target on
     these four pages. On a phone each option becomes its own 46px card. */
  .b6-opts .field-inline,
  .pg-opts .field-inline,
  .ag-dates .field-inline{
    min-height:46px;
    padding:0 12px;
    gap:12px;
    background:var(--panel-2);
    border:1px solid var(--border);
    border-radius:12px;
  }
  /* Spacing is per-tool: these two sit in a gap-ed grid, the age one is the last
     item of a flex row and keeps its own bottom margin (set further down). */
  .b6-opts .field-inline,
  .pg-opts .field-inline{margin-bottom:0}
  .b6-opts .field-inline label,
  .pg-opts .field-inline label,
  .ag-dates .field-inline label{flex:1;line-height:1.35;padding:8px 0}
  .b6-opts input[type=checkbox],
  .pg-opts input[type=checkbox],
  .ag-dates input[type=checkbox]{width:21px;height:21px}

  /* ---------- JSON Formatter ----------
     Was: five buttons and an indent picker before you reach the box you
     came to paste into. Now the textarea is the first thing under the
     title and the buttons sit under it, where your thumb already is. */
  .jf-io{display:flex;flex-direction:column}
  .jf-input{order:1}
  .jf-actions{order:2}
  .jf-status{order:3}
  #jfIn{height:180px}                       /* rows=10 is ~290px on a phone */
  .jf-actions{gap:8px}
  .jf-actions .btn-mini{
    flex:1 1 auto;min-height:44px;
    display:inline-flex;align-items:center;justify-content:center;text-align:center;
  }
  .jf-actions #jfFormat{order:1}
  .jf-actions #jfCopy{order:2}
  .jf-actions #jfMinify{order:3}
  .jf-actions #jfSort{order:4}
  .jf-actions #jfClear{order:5}
  /* label beside the select, not above it — buys back a row of height */
  .jf-indent{order:6;margin-left:0!important;min-width:0!important;flex:1 1 100%;
             flex-direction:row;align-items:center;gap:12px}
  .jf-indent label{flex:none}
  .jf-indent select{flex:1}
  #jfOut{max-height:60vh}
  /* an empty result panel is just a stray box on a small screen */
  .jf-result:has(#jfOut:empty){display:none}

  /* ---------- Base64 ----------
     Result and Copy now follow the input directly; the two advanced
     switches drop below the buttons instead of splitting input from output. */
  .b6-text{display:flex;flex-direction:column}
  .b6-mode{order:1}
  .b6-in{order:2}
  .b6-result{order:3}
  .b6-actions{order:4}
  .b6-errline{order:5}
  .b6-opts{order:6;display:grid;grid-template-columns:1fr;gap:8px;margin-top:4px}
  .b6-in textarea,.b6-result textarea{height:136px}   /* rows=7 -> two boxes + copy on one screen */
  #b6Uri{font-size:.8rem}

  /* ---------- Password generator ----------
     The password is already on screen when the page opens, so Copy is the
     real primary action on a phone — full width, first, and tinted. */
  #pgOut{font-size:1.05rem!important;padding:18px 12px!important;line-height:1.75}
  .pg-actions{gap:8px}
  .pg-actions #pgCopy{
    order:1;flex:1 1 100%;min-height:50px;font-size:.95rem;
    background:var(--panel-2);border-color: var(--accent-ink);color:var(--bg);
  }
  .pg-actions #pgNew{order:2}
  .pg-actions #pgBulk{order:3;flex:0 0 auto}
  .pg-stats .stat:first-child{grid-column:1/-1}

  .pg-opts .row{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .pg-random .field-inline:last-child{grid-column:1/-1}   /* "Avoid look-alikes" is long */
  .pg-phrase .field.grow{grid-column:1/-1;min-width:0!important;margin-bottom:6px}
  .pg-phrase .field-inline{margin-bottom:0!important}
  .pg-len input[type=range],
  .pg-phrase input[type=range]{height:40px}               /* a slider you can grab */
  #pgBulkOut{font-size:.85rem}

  /* ---------- Age & date calculator ----------
     min-width:180px left the date inputs stranded at 180px on a 375px
     screen. Full width, and the headline answer spans both columns. */
  .ag-dates{gap:0}
  .ag-dates .field{flex:1 1 100%;min-width:0!important}
  .ag-dates .field-inline{flex:1 1 100%;margin-bottom:16px!important}
  .ag-age .ag-stats .stat:first-child,
  .ag-diff .ag-stats .stat:first-child{grid-column:1/-1;padding:16px 14px}
  .ag-age .ag-stats .stat:first-child b{font-size:1.75rem}
  .ag-diff .ag-stats .stat:first-child b{font-size:1.75rem}
  #agNext{line-height:1.5}
}

@media (max-width: 700px) {
  /* Label above the tiles rather than beside them — a vertical label strip
     costs a third of the screen width on a phone. */
  

  

  

  
  

  

  /* The export controls are the point of the tool; keep them reachable. */
  
  
}


/* ═══════════════════ Touch targets (phone) ═══════════════════
   Measured across 87 pages at 390/320px: the back link, the wordmark, FAQ
   accordion rows and several inputs came in at 18–34px. 44px is the minimum a
   thumb can hit reliably, and every one of these is a primary action on the
   page it appears on. Height is added with padding and flex centring so
   nothing moves visually on desktop. */
@media (max-width:900px){
  .tool-main summary,
  .tool-faq summary{min-height:44px;display:flex;align-items:center;gap:8px}
  .tool-main input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),
  .tool-main select,
  .tool-main textarea{min-height:44px}
  .hub-search input{min-height:48px}
  .hub-filters .tab{min-height:44px}
}
