/* ══ The hero band and its ".psd in → HTML page out" mini were DELETED 2026-09-07
   when this pane moved onto the tool-page grammar: the header card replaces the band,
   so .psd-hm-* had no markup left anywhere (grepped) and dead CSS that still parses is
   dead weight every other tool downloads. The grammar section is at the END of this
   file; everything between here and there is the workspace, which an EDITOR keeps.
   ⚠ Every line-start class in this file must stay psd- prefixed — the test sweeps
   for it. ══ */
/* PSD → LANDING PAGE (tool #33) — redesigned 2026-08-25.
   ⚠ SCOPED, NOT BARE. Every tool sheet loads on every page in this shell, so a
   bare .card/.stage/.tabs rule here would restyle fourteen other tools.
   Everything is .psd- prefixed and lives under .psd-app.
   Palette follows the shell's own: indigo #4f46e5 action, slate neutrals. */
.psd-app{padding:22px;--psd-line:#e4e8f0;--psd-ink:#0f172a;--psd-mute:#64748b;--psd-card:#fff;--psd-well:#f1f4f9;--psd-accent:#4f46e5}

/* ── hero ─────────────────────────────────────────────────────────────── */
.psd-empty[hidden]{display:none}
.psd-drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;min-height:230px;
  padding:30px 22px;border:2px dashed #cbd5e1;border-radius:16px;background:var(--psd-well);text-align:center;cursor:pointer;
  transition:border-color .15s,background .15s,transform .12s}
.psd-drop:hover,.psd-drop.is-over{border-color:var(--psd-accent);background:#eef2ff}
.psd-drop.is-over{transform:scale(1.006)}
.psd-drop-ic{font-size:30px;color:var(--psd-accent);line-height:1;margin-bottom:2px}
.psd-drop b{font-size:16.5px;color:var(--psd-ink)}
.psd-drop small{font-size:12px;color:var(--psd-mute)}
.psd-drop-btn{margin-top:8px;background:var(--psd-accent);color:#fff;font-size:12.5px;font-weight:700;padding:9px 18px;border-radius:9px}
.psd-drop input{display:none}
.psd-steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px;margin:18px 0 0;padding:0;list-style:none;counter-reset:psd}
.psd-steps li{counter-increment:psd;position:relative;padding:14px 16px 14px 44px;border:1px solid var(--psd-line);border-radius:12px;background:var(--psd-card)}
.psd-steps li::before{content:counter(psd);position:absolute;left:14px;top:14px;width:20px;height:20px;border-radius:50%;
  background:var(--psd-accent);color:#fff;font-size:11px;font-weight:800;display:grid;place-items:center}
.psd-steps b{display:block;font-size:13px;margin-bottom:3px;color:var(--psd-ink)}
.psd-steps span{font-size:12px;line-height:1.6;color:var(--psd-mute)}

.psd-status{margin:16px 0 0;padding:11px 14px;border-radius:10px;font-size:12.5px;line-height:1.55;
  background:#eef2ff;border:1px solid #c7d2fe;color:#3730a3;display:flex;align-items:center;gap:9px}
.psd-status::before{content:"";width:13px;height:13px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;
  animation:psdSpin .7s linear infinite;flex:none}
.psd-status.is-bad{background:#fef2f2;border-color:#fecaca;color:#991b1b}
.psd-status.is-bad::before{display:none}
/* ⚠ THE SPINNER IS THE DEFAULT LOOK, so every state that is NOT still running has
   to say so explicitly. `is-bad` did; `is-good` did not exist at all, so the
   "Optimized 10 of 13 images…" result sat under a ring that span forever and read
   as "still working" long after the file had downloaded (owner, 2026-08-26:
   "output optimized, I downloaded but loader icon keep showing"). A finished
   message gets a tick, not a spinner. */
.psd-status.is-good{background:#ecfdf5;border-color:#a7f3d0;color:#065f46}
.psd-status.is-good::before{content:"\2713";width:auto;height:auto;border:0;border-radius:0;
  animation:none;font-size:13px;font-weight:900;line-height:1}
.psd-status[hidden]{display:none}
/* the export toggle — reads as a setting attached to the button below it, so it
   is quiet: no card, no accent fill, just the control and what it does. */
/* the reflow verdict — a sentence, not a banner: it sits under the switch it is
   about and only appears once there is a measured design to judge. The recommending
   case earns colour; "not needed" stays quiet so it reads as reassurance rather
   than another thing to act on. */
.psd-reco{margin:8px 0 0;padding:8px 10px;border-radius:8px;font-size:11.5px;line-height:1.5;
  color:#5b6478;background:#f6f7fb;border:1px solid #e6e8f2}
.psd-reco b{color:#3b4256;font-weight:800}
.psd-reco.is-reco{color:#8a4b00;background:#fff8ec;border-color:#f4dcb4}
.psd-reco.is-reco b{color:#7a4200}
.psd-reco[hidden]{display:none}
html.dark .psd-reco{color:#9aa3b8;background:#161b2b;border-color:#2b3450}
html.dark .psd-reco b{color:#dfe5f2}
html.dark .psd-reco.is-reco{color:#f0c98a;background:#2a2113;border-color:#5c4526}
html.dark .psd-reco.is-reco b{color:#ffd9a0}
.psd-opt{display:flex;align-items:flex-start;gap:9px;margin:0 0 10px;padding:9px 11px;cursor:pointer;
  border:1px solid #e2e6f3;border-radius:10px;background:#fbfcff}
.psd-opt:hover{border-color:#cfd8f0;background:#f6f8ff}
.psd-opt input{margin:1px 0 0;width:15px;height:15px;accent-color:#0d5fe8;flex:none;cursor:pointer}
.psd-opt span{display:flex;flex-direction:column;gap:1px;min-width:0}
.psd-opt b{font-size:12.5px;font-weight:700;color:#1a2440;line-height:1.3}
.psd-opt small{font-size:11px;color:#5b6478;line-height:1.4}
html.dark .psd-opt{background:#161b2b;border-color:#2b3450}
html.dark .psd-opt:hover{background:#1b2236;border-color:#3a4568}
html.dark .psd-opt b{color:#e8ecf6}
html.dark .psd-opt small{color:#9aa3b8}
@keyframes psdSpin{to{transform:rotate(360deg)}}

/* ── workspace ────────────────────────────────────────────────────────── */
.psd-work{display:grid;grid-template-columns:288px minmax(0,1fr);gap:18px;align-items:start}
.psd-work[hidden]{display:none}
.psd-side{position:sticky;top:12px;display:flex;flex-direction:column;gap:12px}
.psd-card{border:1px solid var(--psd-line);border-radius:13px;background:var(--psd-card);padding:14px 15px}
.psd-card h3{margin:0 0 9px;font-size:10.5px;font-weight:800;letter-spacing:.9px;text-transform:uppercase;color:var(--psd-mute)}
.psd-src{display:flex;align-items:center;gap:11px}
.psd-src-ic{display:grid;place-items:center;width:36px;height:36px;border-radius:9px;background:#eef2ff;color:var(--psd-accent);font-size:15px;flex:none}
.psd-src-txt{min-width:0}
.psd-src-txt b{display:block;font-size:13px;color:var(--psd-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.psd-src-txt small{display:block;font-size:11.5px;color:var(--psd-mute);margin-top:1px}
.psd-stats{margin:0;padding:0;list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:9px}
.psd-stats li{background:var(--psd-well);border-radius:9px;padding:9px 10px}
.psd-stats b{display:block;font-size:17px;font-weight:800;color:var(--psd-ink);line-height:1.15}
.psd-stats span{font-size:11px;color:var(--psd-mute)}
.psd-switch{display:flex;align-items:flex-start;gap:9px;cursor:pointer}
.psd-switch input{margin-top:2px;flex:none}
.psd-switch b{display:block;font-size:12.5px;color:var(--psd-ink)}
.psd-switch small{display:block;font-size:11.5px;line-height:1.55;color:var(--psd-mute);margin-top:2px}
.psd-warn{background:#fffbeb;border-color:#fde68a;color:#92400e;font-size:12px;line-height:1.6}
.psd-warn h3{color:#b45309}
.psd-warn ul{margin:0;padding-left:16px}
.psd-warn li{margin:3px 0}
.psd-warn[hidden]{display:none}
.psd-acts{display:flex;flex-direction:column;gap:8px}

/* ⚠ LONGHANDS, NEVER `font:700 12.5px/1 inherit` — the lesson outlives the rules
   it was written on (.psd-btn / .psd-seg button / .psd-tabs button, all replaced by
   the grammar's .dl-btn / .dl-seg / .dl-tabs on 2026-09-07 and DELETED here so no
   dead bytes ship). A CSS-wide keyword (inherit / initial / unset / revert) is not a
   legal component of a shorthand, so that declaration is INVALID and the parser
   throws the WHOLE thing away — weight, size and line-height with it. It looked fine
   because the `font-family:inherit` that followed still landed, so buttons quietly
   rendered at the UA's default 13.33px/400 instead of the 12.5px/700 written. */

/* ── main: toolbar + panes ────────────────────────────────────────────── */
.psd-main{min-width:0}
.psd-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 12px}
.psd-sp{flex:1 1 auto}
.psd-px{font-style:normal;font-size:10px;font-weight:700;opacity:.6}
.psd-n{font-style:normal;background:var(--psd-accent);color:#fff;font-size:10px;font-weight:800;border-radius:8px;padding:1px 6px}
.psd-n:empty{display:none}
.psd-pane[hidden]{display:none}

/* the stage scales the DEVICE, so the page inside always sees its REAL width —
   a 1440 desktop render must never be squeezed into an 800px frame, or the
   page's own 1024px breakpoint fires and "Desktop" silently shows mobile */
.psd-stage{border:1px solid var(--psd-line);border-radius:13px;background:var(--psd-well);padding:16px;overflow:auto;
  display:flex;justify-content:center;min-height:420px}
/* 🔴 THE BOX IS THE VISUAL SIZE; THE INNER IS SCALED (fixed 2026-09-07, measured).
   This element used to carry BOTH `transform:scale(s)` and `height: frameHeight × s`,
   with overflow:hidden. Those fight: the box clipped the 1920px frame at 991px and
   then scaled what was left, so at Fit zoom the preview showed only the top ~52% of
   the page and the stage kept 480px of empty air under it. Measured on a 1200×1600
   design at 1440: device rect 743×511 against a frame rect of 743×991.
   Now .psd-device is sized to the FINISHED size and .psd-device-in — frame plus the
   layer highlight, so both scale together — is the only thing transformed. */
.psd-device{position:relative;flex:none;border-radius:8px;overflow:hidden;background:#fff;box-shadow:0 8px 30px rgba(15,23,42,.16)}
.psd-device-in{position:relative;transform-origin:top left}
.psd-frame{display:block;border:0;background:#fff}
.psd-cap{margin:9px 0 0;text-align:center;font-size:11.5px;color:var(--psd-mute)}

/* ── images ───────────────────────────────────────────────────────────── */
.psd-assets{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}
.psd-asset{border:1px solid var(--psd-line);border-radius:11px;background:var(--psd-card);overflow:hidden;cursor:pointer;transition:border-color .14s}
.psd-asset:hover{border-color:var(--psd-accent)}
.psd-asset-img{display:grid;place-items:center;height:104px;background:
  linear-gradient(45deg,#eef1f6 25%,transparent 25%,transparent 75%,#eef1f6 75%) 0 0/16px 16px,
  linear-gradient(45deg,#eef1f6 25%,#fff 25%,#fff 75%,#eef1f6 75%) 8px 8px/16px 16px}
.psd-asset-img img{max-width:100%;max-height:100%;object-fit:contain}
.psd-asset-txt{padding:8px 10px;border-top:1px solid var(--psd-line)}
.psd-asset-txt b{display:block;font-size:11.5px;color:var(--psd-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.psd-asset-txt small{font-size:10.5px;color:var(--psd-mute)}

/* ── code ─────────────────────────────────────────────────────────────── */
.psd-codebar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px}
.psd-code{margin:0;padding:16px;border:1px solid var(--psd-line);border-radius:13px;background:#0f172a;color:#cbd5e1;
  font:12px/1.65 ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto;max-height:62vh;white-space:pre-wrap;word-break:break-word}

/* ── dark ─────────────────────────────────────────────────────────────── */
html.dark .psd-app{--psd-line:#333a4e;--psd-ink:#e6e9f2;--psd-mute:#98a1b8;--psd-card:#1d2230;--psd-well:#161b27}
html.dark .psd-drop{border-color:#3a4257}
html.dark .psd-drop:hover,html.dark .psd-drop.is-over{background:#1b2133}
html.dark .psd-src-ic{background:#262c48}
html.dark .psd-status{background:#1e2438;border-color:#33406b;color:#c7d2fe}
html.dark .psd-status.is-bad{background:#3a1f26;border-color:#7a3a4b;color:#f2c9d2}
html.dark .psd-status.is-good{background:#12291f;border-color:#2c5c45;color:#a7f3d0}
html.dark .psd-warn{background:#3a3020;border-color:#7a5f2a;color:#f5d99b}
html.dark .psd-warn h3{color:#f0c46a}
html.dark .psd-asset-img{background:linear-gradient(45deg,#20242f 25%,transparent 25%,transparent 75%,#20242f 75%) 0 0/16px 16px,
  linear-gradient(45deg,#20242f 25%,#161b27 25%,#161b27 75%,#20242f 75%) 8px 8px/16px 16px}

/* ── narrow ───────────────────────────────────────────────────────────── */
@media (max-width:1080px){
  .psd-work{grid-template-columns:1fr}
  .psd-side{position:static}
  .psd-stats{grid-template-columns:repeat(4,1fr)}
}
@media (max-width:760px){
  .psd-app{padding:16px}
  .psd-stats{grid-template-columns:1fr 1fr}
  .psd-toolbar{gap:8px}
}
/* the export allowance, beside the buttons it governs */
.psd-quota{margin:0 0 2px;padding:9px 11px;border-radius:9px;background:#eef2ff;border:1px solid #c7d2fe;
  color:#3730a3;font-size:11.5px;line-height:1.5;text-align:center}
.psd-quota.is-out{background:#fff7ed;border-color:#fed7aa;color:#9a3412}
.psd-quota[hidden]{display:none}
html.dark .psd-quota{background:#1e2438;border-color:#33406b;color:#c7d2fe}
html.dark .psd-quota.is-out{background:#3a2a1c;border-color:#7a5326;color:#f7c99b}
/* a benign note reads as information, not as a warning */
.psd-warn-ok{list-style:none;margin-left:-18px;padding-left:0}
.psd-warn-ok::before{content:"\2713  ";color:#059669;font-weight:800}
.psd-beta{font-style:normal;font-size:9px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;background:#eef2ff;color:#4f46e5;border:1px solid #c7d2fe;border-radius:7px;padding:1px 6px;vertical-align:2px;margin-left:4px}
html.dark .psd-beta{background:#262c48;border-color:#3d4a7a;color:#a5b4fc}

/* ══════════════════════════════════════════════════════════════════════════════════
   PSD → WEB — THE GRAMMAR PAGE (2026-09-07, owner mock 10-psd-to-web.png).
   This tool is an EDITOR: the working workspace (inspector rail | preview stage with
   its device / zoom / tab controls) is untouched. What changed:
     1. the hero band became the grammar's header card;
     2. the toolbar's home-made .psd-seg / .psd-tabs became .dl-seg / .dl-tabs;
     3. a LAYER TREE joined the rail — read out of the page the engine just wrote
        (data-layer + the .psd-group/.psd-text/.psd-image classes + the percentage
        box in each style attribute), never invented, and it highlights the layer
        over the preview.
   The tool keeps ITS OWN colour: the indigo #4f46e5 it has used since launch. The
   sheet's old --psd-* variables are re-pointed at the grammar tokens, so every card,
   border and surface in the workspace above inherits the grammar's light/dark
   surfaces without a rewrite of rules an editor is supposed to leave alone.
   ══════════════════════════════════════════════════════════════════════════════════ */
.tool .app.psd-app{
  --dl-acc:#4f46e5;--dl-acc-hover:#4338ca;--dl-acc-ink:#fff;--dl-acc-soft:#eef2ff;--dl-acc-line:#c7d2fe;
  --psd-accent:var(--dl-acc);--psd-line:var(--dl-line);--psd-ink:var(--dl-ink);
  --psd-mute:var(--dl-mut);--psd-card:var(--dl-panel);--psd-well:var(--dl-raised);
  padding:0 18px}
html.dark .tool .app.psd-app{
  --dl-acc:#a5b4fc;--dl-acc-hover:#c7d2fe;--dl-acc-ink:#15181d;--dl-acc-soft:rgba(165,180,252,.16);--dl-acc-line:rgba(165,180,252,.38)}
.tool .app.psd-app .psd-title-accent{color:var(--dl-acc);-webkit-text-fill-color:var(--dl-acc);background:none}
.tool .app .psd-head .dl-page-title h2{white-space:nowrap}
/* the empty state is the workspace until a page exists — it sits in a card now */
.tool .app .psd-empty{display:flex;flex-direction:column;gap:0}
.tool .app .psd-drop{border-color:var(--dl-line);background:var(--dl-raised)}
.tool .app .psd-drop:hover,.tool .app .psd-drop.is-over{border-color:var(--dl-acc);background:var(--dl-acc-soft)}
.tool .app .psd-drop b{color:var(--dl-ink)}
.tool .app .psd-drop small{color:var(--dl-mut)}
.tool .app .psd-drop-btn{background:var(--dl-acc);color:var(--dl-acc-ink)}
.tool .app .psd-steps li{border-color:var(--dl-line);background:var(--dl-panel)}
.tool .app .psd-steps li::before{background:var(--dl-acc);color:var(--dl-acc-ink)}
/* the toolbar runs the grammar's segmented control + tabs now */
.tool .app .psd-toolbar .dl-seg>button i.psd-px{font-size:10px;font-weight:700;opacity:.7;font-style:normal}
.tool .app .psd-toolbar .dl-tabs{border-bottom:0;gap:2px}
.tool .app .psd-mode{flex:none}

/* ── THE LAYER TREE ──────────────────────────────────────────────────────────────
   Everything here is READ from the built page: the row's name is the engine's own
   data-layer, the badge is the class it gave the element, and the numbers in the
   inspector are its percentage box multiplied back out by the design's own size.
   Nothing in this panel is a value this file invented. */
.tool .app .psd-layers{display:flex;flex-direction:column;gap:9px}
.tool .app .psd-layers-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tool .app .psd-layers-head h3{margin:0;flex:none}
.tool .app .psd-lay-find{flex:1 1 110px;min-width:0;font:inherit;font-size:12px;font-weight:600;height:28px;padding:0 9px;
  border-radius:8px;border:1px solid var(--dl-line);background:var(--dl-panel);color:var(--dl-ink)}
.tool .app .psd-lay-find::placeholder{color:var(--dl-faint);font-weight:500}
.tool .app .psd-lay-find:focus{outline:none;border-color:var(--dl-acc);box-shadow:0 0 0 3px var(--dl-acc-soft)}
html.dark .tool .app .psd-lay-find{background:var(--dl-panel)!important;border-color:var(--dl-line)!important;color:var(--dl-ink)}
.tool .app .psd-tree{display:flex;flex-direction:column;gap:1px;max-height:264px;overflow:auto;margin:0 -4px;padding:0 4px}
.tool .app .psd-lay-row{display:flex;align-items:stretch;gap:2px;min-width:0}
.tool .app .psd-lay-fold{flex:none;width:20px;border:0;border-radius:6px;background:transparent;color:var(--dl-faint);
  font-size:10px;line-height:1;cursor:pointer;display:grid;place-items:center;padding:0}
.tool .app .psd-lay-fold:hover{background:var(--dl-acc-soft);color:var(--dl-acc)}
.tool .app .psd-lay-fold i{transition:transform var(--dl-t,140ms)}
.tool .app .psd-lay-fold.is-shut i{transform:rotate(-90deg)}
.tool .app .psd-lay{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:7px;padding:5px 7px;border:1px solid transparent;
  border-radius:7px;background:transparent;font:inherit;font-size:12px;font-weight:600;color:var(--dl-ink-2);cursor:pointer;text-align:left}
.tool .app .psd-lay:hover{background:var(--dl-raised);border-color:var(--dl-hair)}
.tool .app .psd-lay.is-on{background:var(--dl-acc-soft);border-color:var(--dl-acc-line);color:var(--dl-acc)}
.tool .app .psd-lay-ic{flex:none;width:13px;text-align:center;font-size:11px;color:var(--dl-faint)}
.tool .app .psd-lay.is-on .psd-lay-ic{color:var(--dl-acc)}
.tool .app .psd-lay-nm{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tool .app .psd-lay-tag{flex:none;font-size:9.5px;font-weight:700;letter-spacing:.02em;color:var(--dl-mut);
  background:var(--dl-hair);border-radius:5px;padding:1px 5px}
.tool .app .psd-lay.is-on .psd-lay-tag{color:var(--dl-acc);background:var(--dl-panel)}
.tool .app .psd-lay-empty{margin:2px 0;font-size:11.5px;color:var(--dl-mut)}
.tool .app .psd-lay-note{margin:0;font-size:11px;line-height:1.5;color:var(--dl-warn);background:var(--dl-warn-soft);
  border-radius:8px;padding:6px 9px}
.tool .app .psd-lay-info{border-top:1px solid var(--dl-hair);padding-top:9px;display:flex;flex-direction:column;gap:5px}
.tool .app .psd-lay-txt{margin:0;font-size:11.5px;line-height:1.5;color:var(--dl-ink);background:var(--dl-raised);
  border:1px solid var(--dl-hair);border-radius:7px;padding:6px 8px;max-height:64px;overflow:auto;white-space:pre-wrap;word-break:break-word}
.tool .app .psd-lay-facts{margin:0;padding:0;display:grid;grid-template-columns:auto 1fr;gap:3px 10px;font-size:11.5px}
.tool .app .psd-lay-facts dt{color:var(--dl-mut)}
.tool .app .psd-lay-facts dd{margin:0;color:var(--dl-ink);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tool .app .psd-lay-sw{display:inline-block;width:9px;height:9px;border-radius:3px;border:1px solid var(--dl-line);
  vertical-align:-1px;margin-right:5px}

/* the highlight, drawn over the preview inside .psd-device-in so it carries the same
   scale as the frame; the label counter-scales so it stays readable at Fit zoom */
.tool .app .psd-hl{position:absolute;z-index:2;pointer-events:none;border:2px solid var(--dl-acc);
  box-shadow:0 0 0 1px rgba(255,255,255,.75),0 0 0 9999px rgba(15,23,42,.10);border-radius:2px}
.tool .app .psd-hl-lbl{position:absolute;left:-2px;bottom:100%;transform-origin:left bottom;display:inline-block;
  margin-bottom:3px;padding:2px 6px;border-radius:5px;background:var(--dl-acc);color:var(--dl-acc-ink);
  font-size:11px;font-weight:700;line-height:1.5;white-space:nowrap;max-width:280px;overflow:hidden;text-overflow:ellipsis}
