/* 365Lab 拼图 · 本站原创样式 · canonical: https://puzzle.365lab.top/ · © 365Lab，克隆请保留本行溯源。 */
:root{
  --brand:#4563f0; --brand-2:#7c5bd6; --brand-3:#37b3a6; --brand-4:#e0679b;
  /* Brand deepened from #4a6cf7 → #4563f0 (R10): #4a6cf7 on #fff was 4.39:1,
     just under WCAG AA 4.5:1 for normal text. #4563f0 on #fff is 4.89:1, so every
     brand-as-text label and white-on-brand fill (active tabs/segments, chips,
     lang button, nav CTA, card numbers) is now AA. Same hue family, near-identical
     visually. Mirrors the earlier --muted contrast fix. */
  --bg:#f5f7fb; --panel:#ffffff; --ink:#1b2333;
  /* #5b6577 instead of #6b7688: the old value only reached 4.0:1 on the
     #eef1f7 side panels, below the WCAG AA 4.5:1 floor. */
  --muted:#5b6577; --line:#e4e8f0; --line-2:#eef1f6;
  --chip:#f0f3f9; --shadow:0 1px 2px rgba(20,30,60,.05),0 8px 24px rgba(20,30,60,.06);
  --shadow-sm:0 1px 2px rgba(20,30,60,.06); --radius:14px; --radius-sm:10px;
  --checker:repeating-conic-gradient(#e6e8ee 0% 25%,#ffffff 0% 50%) 50%/18px 18px;
  --topbar-h:60px;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","PingFang SC","Microsoft YaHei",sans-serif;
  color:var(--ink);background:var(--bg);line-height:1.5;-webkit-font-smoothing:antialiased;font-size:15px}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
h1,h2,h3{line-height:1.25;margin:0}
.wrap{max-width:1220px;margin:0 auto;padding:0 18px}
.hidden,[hidden]{display:none!important}

/* ── top bar ── */
.topbar{position:sticky;top:0;z-index:40;height:var(--topbar-h);background:rgba(255,255,255,.86);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topbar .wrap{height:100%;display:flex;align-items:center;gap:16px}
.brand{display:flex;align-items:center;gap:10px;font-weight:800;font-size:18px;letter-spacing:.2px}
.brand .logo{width:30px;height:30px;border-radius:9px;background:linear-gradient(135deg,var(--brand),var(--brand-2) 55%,var(--brand-4));box-shadow:var(--shadow-sm);position:relative}
.brand .logo::after{content:"";position:absolute;inset:7px;border-radius:4px;background:
  linear-gradient(#fff,#fff) 0 0/45% 45% no-repeat,
  linear-gradient(#fff,#fff) 100% 0/45% 45% no-repeat,
  linear-gradient(#fff,#fff) 0 100%/45% 45% no-repeat,
  linear-gradient(#fff,#fff) 100% 100%/45% 45% no-repeat;opacity:.92}
.brand small{display:block;font-size:11px;font-weight:600;color:var(--muted);letter-spacing:0}
.topnav{margin-left:auto;display:flex;align-items:center;gap:6px}
.topnav a{padding:8px 12px;border-radius:9px;color:var(--muted);font-weight:600;font-size:14px}
.topnav a:hover{background:var(--chip);color:var(--ink)}
.langbtn{margin-left:6px;padding:8px 14px;border-radius:999px;border:1px solid var(--line);background:#fff;font-weight:700;font-size:13px;color:var(--brand)}
.langbtn:hover{border-color:var(--brand)}

/* ── hero ── */
.hero{padding:34px 0 10px}
.hero h1{font-size:clamp(26px,4.4vw,40px);font-weight:900;letter-spacing:-.4px}
.hero h1 .g{background:linear-gradient(120deg,var(--brand),var(--brand-2),var(--brand-4));-webkit-background-clip:text;background-clip:text;color:transparent}
.hero p{margin:12px 0 0;color:var(--muted);font-size:clamp(15px,1.6vw,18px);max-width:70ch}
.hero .badges{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.hero .badges span{background:#fff;border:1px solid var(--line);border-radius:999px;padding:6px 12px;font-size:13px;font-weight:600;color:#39435a;box-shadow:var(--shadow-sm)}

/* ── workbench ── */
.maker{padding:14px 0 30px}
.studio{display:grid;grid-template-columns:1fr 380px;gap:16px;align-items:start}
@media(min-width:981px){.studio{grid-template-columns:380px 1fr}}

/* stage (left) */
.stagewrap{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden;position:sticky;top:calc(var(--topbar-h) + 12px)}
.toolbar{display:flex;align-items:center;gap:6px;padding:8px 10px;border-bottom:1px solid var(--line-2);flex-wrap:wrap}
.modes{display:flex;gap:4px;background:var(--chip);padding:4px;border-radius:11px}
.mode-tab{padding:7px 14px;border-radius:8px;font-weight:700;font-size:13px;color:var(--muted)}
.mode-tab.on{background:#fff;color:var(--brand);box-shadow:var(--shadow-sm)}
.tb-actions{margin-left:auto;display:flex;gap:4px}
.iconbtn{width:36px;height:36px;border-radius:9px;border:1px solid var(--line);background:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:15px;color:#39435a}
.iconbtn:hover:not(:disabled){border-color:var(--brand);color:var(--brand)}
.iconbtn:disabled{opacity:.4;cursor:not-allowed}
.iconbtn.danger:hover{border-color:#d1523f;color:#d1523f}
.stage{position:relative;height:min(66vh,620px);background:
  linear-gradient(var(--line-2) 1px,transparent 1px) 0 0/100% 26px,
  linear-gradient(90deg,var(--line-2) 1px,transparent 1px) 0 0/26px 100%,
  #fbfcfe;display:grid;place-items:center;overflow:hidden;padding:14px}
.frame{position:relative;box-shadow:0 6px 26px rgba(20,30,60,.16);border-radius:6px;background:var(--checker)}
#previewCanvas{display:block;border-radius:6px}
.overlay{position:absolute;inset:0;pointer-events:none}
.overlay .cellframe{position:absolute;pointer-events:auto;border-radius:4px;z-index:3}
.overlay .cellframe.empty{border:2px dashed rgba(74,108,247,.5);background:rgba(74,108,247,.06);display:grid;place-items:center}
.overlay .cellframe:not(.empty){border:2px solid transparent}
.overlay .cellframe:not(.empty):hover{border-color:rgba(74,108,247,.6);cursor:pointer}
.cell-add{width:40px;height:40px;border-radius:50%;background:#fff;border:1px solid var(--line);color:var(--brand);font-size:22px;line-height:1;box-shadow:var(--shadow-sm);display:grid;place-items:center}
.cell-add:hover{border-color:var(--brand);transform:scale(1.06)}
.cell-badge{position:absolute;top:6px;left:8px;font-size:11px;font-weight:700;color:#fff;background:rgba(20,30,60,.4);border-radius:6px;padding:1px 6px}
.cell-tools{position:absolute;top:6px;right:6px;display:none;gap:4px}
.cellframe:not(.empty):hover .cell-tools{display:flex}
.cell-tools button{width:28px;height:28px;border-radius:8px;background:rgba(20,24,40,.72);color:#fff;font-size:13px;display:grid;place-items:center;backdrop-filter:blur(2px)}
.cell-tools button:hover{background:var(--brand)}
.droptarget{outline:3px solid var(--brand);outline-offset:-3px}
/* grid merge */
.gridbase{position:absolute;pointer-events:auto;z-index:2}
.gridu{border:2px dashed rgba(120,130,150,.4);border-radius:6px;background:rgba(255,255,255,.02)}
.gridu:hover{border-color:rgba(74,108,247,.6)}
.gridu.sel{background:rgba(74,108,247,.22);border-color:var(--brand)}
.cellframe.merged{border:2px solid rgba(74,108,247,.28);border-radius:8px;background:rgba(74,108,247,.05)}
.cellframe.merged:not(.empty){border-color:transparent}
/* free canvas */
#freeWrap{position:absolute;inset:0;display:none}
#freeWrap canvas{z-index:1}
body[data-mode="canvas"] #freeWrap{display:block}
.free-tools{position:absolute;left:50%;bottom:12px;transform:translateX(-50%);display:flex;gap:4px;background:rgba(255,255,255,.94);border:1px solid var(--line);border-radius:14px;padding:6px;box-shadow:var(--shadow);z-index:6;max-width:calc(100% - 16px);flex-wrap:wrap;justify-content:center}
/* phones: the shrink-to-fit pill collapses to a tall column — anchor full stage width instead */
@media(max-width:720px){.free-tools{left:8px;right:8px;transform:none;max-width:none;bottom:8px}}
.free-tools button{width:34px;height:34px;border-radius:9px;font-size:16px;color:#39435a}
.free-tools button:hover,.free-tools button.on{background:var(--brand);color:#fff}

.thumbs{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--line-2);overflow-x:auto;background:#fbfcfe;min-height:64px;align-items:center}
.thumb{position:relative;width:52px;height:52px;flex:0 0 auto;border-radius:10px;overflow:hidden;border:1px solid var(--line);cursor:grab;background:#fff}
.thumb img{width:100%;height:100%;object-fit:cover}
.thumb-x{position:absolute;top:2px;right:2px;width:18px;height:18px;border-radius:50%;background:rgba(20,24,40,.7);color:#fff;font-size:12px;line-height:1;display:grid;place-items:center}
.thumb-add{display:grid;place-items:center;font-size:24px;color:var(--brand);border-style:dashed;cursor:pointer}
.thumb-add:hover{border-color:var(--brand);background:#f6f8ff}

/* controls (right) */
.controls{display:flex;flex-direction:column;gap:12px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-sm);overflow:hidden}
.card .body{padding:12px 14px;display:flex;flex-direction:column;gap:12px}
.card.collapsed .body{display:none}

.dropzone{border:2px dashed var(--line);border-radius:12px;padding:16px;text-align:center;color:var(--muted);font-size:13px;transition:.15s;cursor:pointer}
.dropzone:hover,.dropzone.over{border-color:var(--brand);background:#f6f8ff;color:var(--brand)}

.fld{display:flex;flex-direction:column;gap:6px}
.fld>label{font-size:12.5px;font-weight:600;color:#46536b}
.fldrow{display:flex;align-items:center;gap:10px}
.fldrow input[type=range]{flex:1;accent-color:var(--brand);height:22px}
.fldrow output{min-width:52px;text-align:right;font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--muted);font-weight:600}
.fld-inline{flex-direction:row;align-items:center;gap:8px;flex-wrap:wrap}
.fld-inline>label{flex:1;min-width:80px}
.fld-label{font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-top:2px}
input[type=color]{width:34px;height:30px;border:1px solid var(--line);border-radius:8px;background:#fff;padding:2px;cursor:pointer}
input[type=number],input[type=text],select{border:1px solid var(--line);border-radius:9px;padding:8px 10px;font-size:14px;background:#fff;color:var(--ink);width:100%}
input:focus,select:focus{outline:2px solid rgba(74,108,247,.35);border-color:var(--brand)}
.chk{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:#46536b;cursor:pointer;user-select:none}
.chk input{width:17px;height:17px;accent-color:var(--brand)}
.switch{position:relative;width:40px;height:22px;flex:0 0 auto}
.switch input{opacity:0;width:0;height:0}
.switch span{position:absolute;inset:0;background:#cdd4e2;border-radius:999px;transition:.2s}
.switch span::before{content:"";position:absolute;width:18px;height:18px;left:2px;top:2px;background:#fff;border-radius:50%;transition:.2s;box-shadow:var(--shadow-sm)}
.switch input:checked+span{background:var(--brand)}
.switch input:checked+span::before{transform:translateX(18px)}

.seg{display:flex;gap:4px;background:var(--chip);padding:4px;border-radius:10px;flex-wrap:wrap}
.seg button{flex:1;min-width:52px;padding:7px 10px;border-radius:7px;font-weight:700;font-size:13px;color:var(--muted)}
.seg button.on{background:#fff;color:var(--brand);box-shadow:var(--shadow-sm)}
.seg.grow button{flex:0 0 auto}
.mini{padding:6px 10px;border-radius:8px;border:1px solid var(--line);background:#fff;font-size:12.5px;font-weight:600;color:#46536b}
.mini:hover{border-color:var(--brand);color:var(--brand)}
.chip{padding:5px 10px;border-radius:8px;border:1px solid var(--line);font-size:12.5px;font-weight:600;color:#46536b}
.chip.on{background:var(--brand);color:#fff;border-color:var(--brand)}
.presets{display:flex;flex-wrap:wrap;gap:6px}
.preset{padding:5px 9px;border-radius:8px;border:1px solid var(--line);font-size:12px;font-weight:600;color:#46536b;background:#fff}
.preset:hover{border-color:var(--brand);color:var(--brand)}

/* layout picker */
.lcats{display:flex;flex-wrap:wrap;gap:6px}
.lcat{padding:6px 11px;border-radius:999px;border:1px solid var(--line);font-size:12.5px;font-weight:700;color:var(--muted);background:#fff}
.lcat.on{background:var(--brand);color:#fff;border-color:var(--brand)}
.search{position:relative}
.search input{padding-left:34px}
.search::before{content:"🔍";position:absolute;left:10px;top:50%;transform:translateY(-50%);font-size:14px;opacity:.5}
.layouts{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;max-height:320px;overflow:auto;padding:2px}
.layout{aspect-ratio:1;border:1px solid var(--line);border-radius:10px;background:#fbfcfe;padding:6px;transition:.12s}
.layout:hover{border-color:var(--brand);transform:translateY(-2px)}
.layout.on{border-color:var(--brand);box-shadow:0 0 0 2px rgba(74,108,247,.25)}
.shapes{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px}
.shape{aspect-ratio:1;border:1px solid var(--line);border-radius:10px;background:#fff;font-size:16px;color:#46536b;display:grid;place-items:center}
.shape:hover{border-color:var(--brand);color:var(--brand)}
.shape.on{background:var(--brand);color:#fff;border-color:var(--brand)}
.ratios,.aspect{display:flex;flex-wrap:wrap;gap:6px}
.ratio{padding:5px 9px;border-radius:8px;border:1px solid var(--line);font-size:12.5px;font-weight:600;color:#46536b;background:#fff}
.ratio:hover{border-color:var(--brand);color:var(--brand)}

.gridrow{display:flex;align-items:center;gap:8px;font-size:13px;color:#46536b}
.gridrow input{width:64px}
.dl{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:#46536b}

.btn-primary{width:100%;padding:13px;border-radius:11px;background:linear-gradient(120deg,var(--brand),var(--brand-2));color:#fff;font-weight:800;font-size:15px;box-shadow:0 6px 18px rgba(74,108,247,.32);display:flex;align-items:center;justify-content:center;gap:8px;transition:.12s}
.btn-primary:hover{filter:brightness(1.05);transform:translateY(-1px)}
.btn-primary:disabled{opacity:.6;cursor:default;transform:none}
.btnrow{display:flex;gap:8px}
.btnrow .mini{flex:1;text-align:center}

/* edit modal */
.modal{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;padding:16px;background:rgba(16,22,40,.42);backdrop-filter:blur(2px)}
.modal.open{display:flex}
.modal .box{background:#fff;border-radius:18px;box-shadow:0 20px 60px rgba(10,18,40,.3);max-width:860px;width:100%;max-height:92vh;display:grid;grid-template-columns:340px 1fr;overflow:hidden}
.modal .preview{background:var(--checker);display:grid;place-items:center;padding:16px}
.modal .preview canvas{border-radius:10px;max-width:100%;height:auto;box-shadow:var(--shadow)}
.modal .side{display:flex;flex-direction:column;min-height:0}
.modal .side .mhead{display:flex;align-items:center;padding:14px 16px;border-bottom:1px solid var(--line-2)}
.modal .side .mhead h3{font-size:15px;font-weight:800}
.modal .side .mhead .x{margin-left:auto;width:32px;height:32px;border-radius:9px;font-size:20px;color:var(--muted)}
.modal .side .mhead .x:hover{background:var(--chip)}
.modal .side .mbody{padding:14px 16px;overflow:auto;display:flex;flex-direction:column;gap:12px}
@media(max-width:720px){.modal .box{grid-template-columns:1fr;max-height:94vh}.modal .preview{max-height:34vh}}

/* toast */
.toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);background:#1b2333;color:#fff;padding:11px 18px;border-radius:12px;font-size:14px;font-weight:600;box-shadow:0 12px 30px rgba(0,0,0,.28);opacity:0;pointer-events:none;transition:.22s;z-index:80;max-width:90vw}
.toast.show{opacity:1;transform:translate(-50%,0)}
.toast.ok{background:#177a4e}.toast.err{background:#c0432f}

/* ── content sections ── */
section.content{padding:52px 0;border-top:1px solid var(--line)}
section.content h2{font-size:clamp(22px,3vw,30px);font-weight:900;text-align:center;letter-spacing:-.3px}
section.content .sub{text-align:center;color:var(--muted);max-width:64ch;margin:10px auto 30px;font-size:16px}
.grid-feat{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
@media(max-width:820px){.grid-feat{grid-template-columns:1fr}}
.feat{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:22px;box-shadow:var(--shadow-sm);position:relative;overflow:hidden}
.feat::before{content:"";position:absolute;left:0;top:0;height:4px;width:100%;background:linear-gradient(90deg,var(--brand),var(--brand-2))}
.feat:nth-child(2)::before{background:linear-gradient(90deg,var(--brand-3),var(--brand))}
.feat:nth-child(3)::before{background:linear-gradient(90deg,var(--brand-4),var(--brand-2))}
.feat:nth-child(4)::before{background:linear-gradient(90deg,var(--brand-2),var(--brand-4))}
.feat:nth-child(5)::before{background:linear-gradient(90deg,var(--brand),var(--brand-3))}
.feat:nth-child(6)::before{background:linear-gradient(90deg,var(--brand-4),var(--brand))}
.feat .ic{font-size:26px}
.feat h3{margin:12px 0 6px;font-size:18px;font-weight:800}
.feat p{color:var(--muted);margin:0;font-size:14.5px}
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;counter-reset:s}
@media(max-width:820px){.steps{grid-template-columns:1fr}}
.step{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:22px;box-shadow:var(--shadow-sm)}
.step .num{width:34px;height:34px;border-radius:10px;background:var(--chip);color:var(--brand);font-weight:900;display:grid;place-items:center;font-size:16px;margin-bottom:10px}
.step h3{font-size:17px;font-weight:800;margin-bottom:6px}
.step p{color:var(--muted);font-size:14.5px;margin:0}
.faq{max-width:820px;margin:0 auto;display:flex;flex-direction:column;gap:10px}
.faq details{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:4px 18px;box-shadow:var(--shadow-sm)}
.faq summary{font-weight:700;cursor:pointer;padding:14px 0;list-style:none;display:flex;align-items:center;gap:10px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";margin-left:auto;font-size:22px;color:var(--brand);transition:.2s}
.faq details[open] summary::after{content:"–"}
.faq details p{color:var(--muted);margin:0 0 14px}

footer{background:#12172a;color:#c7cede;padding:38px 0 30px;margin-top:20px}
footer .wrap{display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start;justify-content:space-between}
footer .brand{color:#fff}footer .brand small{color:#8b96b5}
footer .fnav{display:flex;gap:18px;flex-wrap:wrap}
footer a:hover{color:#fff}footer a{color:#aeb8d2;font-size:14px}
footer .cp{width:100%;border-top:1px solid #232a44;padding-top:16px;color:#7f8aa8;font-size:13px}
footer .cp a{color:#9aa6c6}

/* mobile tweaks */
@media(max-width:980px){
  .stagewrap{position:static}
  .stage{height:min(52vh,420px)}
  .studio{grid-template-columns:1fr}
  .controls{order:2}
}
@media(max-width:520px){
  body{font-size:14px}
  .topnav a:not(.nav-cta){display:none}
  .layouts{grid-template-columns:repeat(3,minmax(0,1fr))}
  .stage{padding:8px}
}

/* ══ HOME PAGE ══ */
.nav-cta{background:var(--brand);color:#fff!important;border-radius:999px;padding:8px 16px;font-weight:700}
.nav-cta:hover{filter:brightness(1.06);background:var(--brand)}
.hero-home{padding:44px 0 26px}
.hero-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:30px;align-items:center}
.hero-home h1{font-size:clamp(28px,4.6vw,46px)}
.hero-home p{margin:16px 0 0;font-size:clamp(15px,1.7vw,19px);color:var(--muted);max-width:52ch}
.hero-actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:24px}
.btn-hero{display:inline-flex;align-items:center;gap:8px;padding:14px 26px;border-radius:13px;font-weight:800;font-size:16px;color:#fff;background:linear-gradient(120deg,var(--brand),var(--brand-2));box-shadow:0 10px 26px rgba(74,108,247,.34);transition:.14s}
.btn-hero:hover{transform:translateY(-2px);filter:brightness(1.05)}
.btn-hero.ghost{background:#fff;color:var(--brand);border:1px solid var(--line);box-shadow:var(--shadow-sm)}
.hero-home .badges{margin-top:22px}
.hero-visual{display:grid;place-items:center}
.mock{width:min(420px,90%);aspect-ratio:1/1;display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);gap:10px;transform:rotate(-3deg);filter:drop-shadow(0 20px 40px rgba(20,30,60,.18))}
.mock>div{border-radius:14px}
.mock-a{grid-column:1/3;grid-row:1/3;background:linear-gradient(135deg,#4a6cf7,#7c5bd6)}
.mock-b{background:linear-gradient(135deg,#e0679b,#e0a13a)}
.mock-c{background:linear-gradient(135deg,#37b3a6,#4a6cf7)}
.mock-d{grid-column:1/2;background:linear-gradient(135deg,#d1523f,#e0679b)}
.mock-e{grid-column:2/4;background:linear-gradient(135deg,#3f9d5a,#37b3a6)}
@media(max-width:860px){.hero-grid{grid-template-columns:1fr}.hero-visual{order:-1}.mock{width:min(320px,80%)}}
section.content.alt{background:linear-gradient(180deg,#fff,#f2f5fb)}
.center-cta{text-align:center;margin-top:26px}
/* .reveal hidden state is gated behind html.js (added by home.js) so content stays visible without JS */
html.js .reveal{opacity:0;transform:translateY(16px);transition:opacity .6s,transform .6s}
html.js .reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}

/* ══ TOOL PAGE (full-screen studio) ══ */
body.page-tool{overflow:hidden}
.tool-topbar{position:static}
.back-link{font-weight:700}
.tool-shell{height:calc(100vh - var(--topbar-h));height:calc(100dvh - var(--topbar-h));display:flex;min-height:0}
.tool-studio{width:100%;grid-template-columns:400px 1fr;gap:0;padding:0;max-width:none;grid-template-rows:minmax(0,1fr)}
/* Suppress first-screen CLS: keep the workspace hidden (visibility:hidden still keeps the
   layout box, so dependent sizes stay correct) until boot() has finished sizing it, then
   fade in. Elements that are not rendered do not contribute to layout-shift, so the
   shifts that happen while building the UI are never counted. */
body.preboot .tool-studio{visibility:hidden;opacity:0}
.tool-studio{transition:opacity .18s ease}
.tool-studio .controls{height:100%;overflow-y:auto;padding:14px;background:#eef1f7;border-right:1px solid var(--line)}
.tool-studio .stagewrap{position:static;height:100%;border-radius:0;border:none;box-shadow:none;display:flex;flex-direction:column;background:#fff}
.tool-studio .stage{height:100%;min-height:0;display:flex;flex-direction:column}
.tool-studio .thumbs{flex:0 0 auto}
@media(max-width:900px){
  body.page-tool{overflow:auto}
  .tool-shell{height:auto}
  .tool-studio{grid-template-columns:1fr}
  .tool-studio .controls{height:auto;overflow:visible;border-right:none;border-top:1px solid var(--line)}
  .tool-studio .stagewrap{height:auto}
  .tool-studio .stage{height:52vh}
}

/* crop widget */
.cropwrap{display:flex;flex-direction:column;gap:8px}
.cropcv{width:100%;max-width:280px;border-radius:10px;background:#0b0f1e;touch-action:none;cursor:crosshair;align-self:center}
.cropbar{display:flex;flex-wrap:wrap;gap:5px;justify-content:center}
.cropbar .mini{padding:5px 9px;font-size:12px}
.crop-empty{color:var(--muted);font-size:13px;text-align:center;padding:10px}

/* fullscreen modal */
.fullmodal{position:fixed;inset:0;z-index:70;display:none;background:rgba(8,11,22,.9);align-items:center;justify-content:center}
.fullmodal.open{display:flex}
.full-inner{display:grid;place-items:center}
.fullmodal canvas{border-radius:8px;box-shadow:0 20px 60px rgba(0,0,0,.5);background:var(--checker)}
.full-x{position:absolute;top:16px;right:20px;width:44px;height:44px;border-radius:12px;background:rgba(255,255,255,.14);color:#fff;font-size:24px}
.full-x:hover{background:rgba(255,255,255,.28)}

/* empty-state hint: an inline pill living in the thumbnail row (normal flow — the old
   full-face overlay on the frame collided with the empty cells' "+" buttons and badges) */
.stage-hint{display:flex;flex-direction:row;align-items:center;gap:10px;margin-left:8px;flex:0 0 auto;
  background:#fff;border:1px dashed #cfd9f2;border-radius:14px;padding:8px 14px 8px 8px;box-shadow:var(--shadow-sm);pointer-events:none;max-width:100%;text-align:left}
.stage-hint .sh-ic{width:34px;height:34px;border-radius:11px;flex:0 0 auto;display:grid;place-items:center;font-size:19px;
  background:linear-gradient(135deg,#eef3ff,#f6ecfb);box-shadow:inset 0 0 0 1px rgba(69,99,240,.14)}
.stage-hint .sh-t{font-weight:800;font-size:14px;color:#46536b;white-space:nowrap}
.stage-hint .sh-s{font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:560px){.stage-hint .sh-s{display:none}}
.thumb.droptarget{outline:2px solid var(--brand);outline-offset:2px}

/* ══ POLISH PASS ══ */
:root{--ring:0 0 0 3px rgba(74,108,247,.22)}
*{scrollbar-width:thin;scrollbar-color:#c4ccdb transparent}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:#c9d1df;border-radius:999px;border:3px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:#aeb8cc;background-clip:content-box}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* Dark surfaces need a light ring - a blue one is invisible there. */
.to-top:focus-visible,.full-x:focus-visible,.full-dl:focus-visible,.fullmodal :focus-visible{outline-color:#fff}

/* cards */
.card{border-radius:16px;transition:box-shadow .2s}
.card:hover{box-shadow:var(--shadow)}

/* buttons */
.mini,.chip,.preset,.ratio{border-radius:10px;transition:transform .1s,border-color .15s,background .15s,color .15s,box-shadow .15s}
.mini:hover,.chip:hover,.preset:hover,.ratio:hover{transform:translateY(-1px)}
.mini:active,.chip:active,.preset:active,.ratio:active{transform:translateY(0)}
.chip.on,.preset.on,.ratio.on{box-shadow:0 4px 12px rgba(74,108,247,.28)}
.btn-primary{border-radius:13px;letter-spacing:.3px}
.btn-primary:active{transform:translateY(0)}

/* range sliders */
input[type=range]{-webkit-appearance:none;appearance:none;background:transparent;height:24px;cursor:pointer}
input[type=range]::-webkit-slider-runnable-track{height:6px;border-radius:999px;background:linear-gradient(90deg,var(--brand) 0%,var(--brand) var(--fill,50%),#e2e7f0 var(--fill,50%),#e2e7f0 100%)}
input[type=range]::-moz-range-track{height:6px;border-radius:999px;background:#e2e7f0}
input[type=range]::-moz-range-progress{height:6px;border-radius:999px;background:var(--brand)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:18px;height:18px;margin-top:-6px;border-radius:50%;background:#fff;border:2px solid var(--brand);box-shadow:0 2px 6px rgba(20,30,60,.2);transition:transform .12s}
input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:#fff;border:2px solid var(--brand);box-shadow:0 2px 6px rgba(20,30,60,.2)}
input[type=range]:hover::-webkit-slider-thumb{transform:scale(1.12)}
input[type=range]:active::-webkit-slider-thumb{transform:scale(1.2)}

/* color inputs */
input[type=color]{-webkit-appearance:none;appearance:none;border:1px solid var(--line);border-radius:9px;padding:0;width:36px;height:32px;overflow:hidden;cursor:pointer}
input[type=color]::-webkit-color-swatch-wrapper{padding:3px}
input[type=color]::-webkit-color-swatch{border:none;border-radius:6px}

/* segmented */
.seg{background:#eef1f7;border-radius:12px}
.seg button{border-radius:9px;transition:.14s}
.seg button.on{box-shadow:0 2px 8px rgba(20,30,60,.1)}

/* layout picker */
.layout{background:linear-gradient(180deg,#fbfcfe,#f2f5fb);border-radius:12px;transition:transform .12s,box-shadow .15s,border-color .15s}
.layout:hover{transform:translateY(-3px);box-shadow:var(--shadow)}
.layout.on{border-color:var(--brand);box-shadow:0 0 0 2px rgba(74,108,247,.28),var(--shadow)}
.lcat{border-radius:999px;transition:.14s}
.lcat.on{box-shadow:0 4px 12px rgba(74,108,247,.3)}
.shape{border-radius:11px;background:#fff;transition:.14s}
.shape:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.shape.on{box-shadow:0 4px 12px rgba(74,108,247,.3)}

/* stage + toolbar */
.toolbar{background:linear-gradient(180deg,#fff,#f7f9fd)}
.modes{background:#eef1f7;border-radius:12px}
.mode-tab{border-radius:9px;transition:.14s}
.mode-tab.on{box-shadow:0 2px 8px rgba(74,108,247,.22)}
.iconbtn{border-radius:10px;transition:.14s}
.iconbtn:hover:not(:disabled){transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.stage{background:
  radial-gradient(circle at 1px 1px, #e3e8f1 1px, transparent 0) 0 0/22px 22px,
  linear-gradient(180deg,#fbfcfe,#f4f6fb)}
.frame{box-shadow:0 10px 40px rgba(20,30,60,.18)}

/* thumbnails */
.thumbs{background:linear-gradient(180deg,#f7f9fd,#eef1f7)}
.thumb{border-radius:12px;transition:transform .12s,box-shadow .15s}
.thumb:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
.thumb-add{border-radius:12px}

/* edit modal */
.modal .box{border-radius:20px}
.modal .preview{background:linear-gradient(135deg,#f3f5fa,#e9edf6)}
.modal .side .mhead{background:linear-gradient(180deg,#fbfcfe,#f5f7fc)}

/* topbar */
.topbar .brand .logo{box-shadow:0 4px 12px rgba(90,80,210,.35)}
.langbtn,.nav-cta{transition:.14s}
.langbtn:hover,.nav-cta:hover{transform:translateY(-1px)}

/* feature/step cards on home */
.feat,.step{transition:transform .18s,box-shadow .18s}
.feat:hover,.step:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
@media(prefers-reduced-motion:reduce){*{transition:none!important;scroll-behavior:auto!important}}

/* mobile: preview first, then controls */
@media(max-width:900px){
  .tool-studio .stagewrap{order:-1}
  .tool-studio .controls{order:2}
}
/* active cell highlight while editing */
.cellframe.editing{outline:3px solid var(--brand);outline-offset:-3px;border-radius:8px}
/* nicer dropzone */
.dropzone{background:linear-gradient(180deg,#fbfcff,#f5f8ff)}
.dropzone:hover,.dropzone.over{background:linear-gradient(180deg,#f3f7ff,#eaf1ff)}
/* toast pop */
.toast{animation:none}
.toast.show{animation:toastin .22s ease}
@keyframes toastin{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}

/* unplaced-photos notice */
.thumb-note{flex:0 0 auto;align-self:center;margin-left:6px;font-size:12px;font-weight:600;color:#8a5a12;background:#fff5e6;border:1px solid #f3d9ac;border-radius:999px;padding:6px 12px;white-space:nowrap}

/* back to top */
.to-top{position:fixed;right:22px;bottom:22px;width:46px;height:46px;border-radius:50%;background:linear-gradient(135deg,var(--brand),var(--brand-2));color:#fff;font-size:20px;font-weight:800;box-shadow:0 10px 26px rgba(74,108,247,.4);display:grid;place-items:center;opacity:0;transform:translateY(16px) scale(.9);pointer-events:none;transition:.24s;z-index:45}
.to-top.ontop{opacity:1;transform:none;pointer-events:auto}
.to-top:hover{filter:brightness(1.06);transform:translateY(-2px)}
@media(prefers-reduced-motion:reduce){.to-top{transition:none}}

/* tool topbar status chip */
.status-chip{font-size:12.5px;font-weight:700;color:var(--muted);background:var(--chip);border:1px solid var(--line);border-radius:999px;padding:6px 12px;margin-right:2px;white-space:nowrap;font-variant-numeric:tabular-nums}
@media(max-width:520px){.status-chip{display:none}}

/* scene presets */
.scenes{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.scene{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 6px;border:1px solid var(--line);border-radius:12px;background:linear-gradient(180deg,#fff,#f6f8fc);font-size:12px;font-weight:700;color:#46536b;transition:.14s}
.scene:hover{border-color:var(--brand);transform:translateY(-2px);box-shadow:var(--shadow)}
.scene .scene-ic{font-size:20px;line-height:1}
@media(max-width:420px){.scenes{grid-template-columns:repeat(2,1fr)}}

/* size guide table */

/* shortcuts modal */
.kbdmodal{position:fixed;inset:0;z-index:70;display:none;background:rgba(8,11,22,.5);backdrop-filter:blur(2px);align-items:center;justify-content:center;padding:20px}
.kbdmodal.open{display:flex}
.kbdbox{background:#fff;border-radius:18px;box-shadow:0 20px 60px rgba(10,18,40,.3);max-width:460px;width:100%;padding:22px 24px}
.kbdbox h3{margin:0 0 14px;font-size:18px;font-weight:900}
.kbdbox .krow{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line-2);font-size:14px;color:#46536b}
.kbdbox .krow:last-child{border-bottom:none}
kbd{background:#eef1f7;border:1px solid var(--line);border-bottom-width:2px;border-radius:6px;padding:2px 8px;font-size:12px;font-family:ui-monospace,monospace;color:#39435a}
.kbd-x{position:absolute;top:14px;right:16px;width:34px;height:34px;border-radius:9px;font-size:20px;color:var(--muted)}

/* touch devices: cell tools always visible + larger tap targets (≥40px) */
@media(hover:none){
  .cellframe:not(.empty) .cell-tools{display:flex}
  .cell-tools button{width:40px;height:40px;font-size:16px}
  .cell-add{width:48px;height:48px;font-size:26px}
  .overlay .cellframe:not(.empty){cursor:pointer}
}

/* caption position picker */
.posgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;max-width:180px}
.poscell{aspect-ratio:1;border:1px solid var(--line);border-radius:9px;background:#fbfcfe;display:grid;place-items:center;transition:.12s}
.poscell:hover{border-color:var(--brand)}
.poscell.on{border-color:var(--brand);background:#eef3ff;box-shadow:0 0 0 2px rgba(74,108,247,.2)}
.poscell .posdot{width:10px;height:10px;border-radius:3px;background:var(--brand);opacity:.55}
.poscell.on .posdot{opacity:1}

/* caption emoji quick-pick */
.emojirow{display:flex;flex-wrap:wrap;gap:4px}
.emoji{width:34px;height:34px;border:1px solid var(--line);border-radius:9px;background:#fff;font-size:18px;line-height:1;display:grid;place-items:center;transition:.12s}
.emoji:hover{border-color:var(--brand);transform:translateY(-2px) scale(1.08);box-shadow:var(--shadow-sm)}

/* active scene highlight */
.scene.on{border-color:var(--brand);background:#eef3ff;box-shadow:0 0 0 2px rgba(74,108,247,.28)}
.scene.on .scene-ic{color:var(--brand)}

/* first-run coach */
.coach{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:75;display:none;background:#fff;border-radius:18px;box-shadow:0 24px 70px rgba(10,18,40,.35);max-width:440px;width:calc(100% - 32px);padding:26px 26px 22px}
.coach.open{display:block}
.coach h3{margin:0 0 6px;font-size:20px;font-weight:900}
.coach .csteps{display:flex;flex-direction:column;gap:12px;margin:16px 0 20px}
.coach .cstep{display:flex;gap:12px;align-items:flex-start}
.coach .cstep .cn{flex:0 0 auto;width:26px;height:26px;border-radius:8px;background:linear-gradient(135deg,var(--brand),var(--brand-2));color:#fff;font-weight:800;font-size:13px;display:grid;place-items:center}
.coach .cstep b{font-size:14.5px}
.coach .cstep p{margin:2px 0 0;font-size:13px;color:var(--muted)}
.coach .cbg{position:fixed;inset:0;background:rgba(8,11,22,.5);z-index:-1}

/* stage file-drop highlight */
.frame.dropping{outline:3px dashed var(--brand);outline-offset:5px}
.frame.dropping::after{content:"";position:absolute;inset:0;background:rgba(74,108,247,.08);border-radius:6px;pointer-events:none}

/* annotation layer */
#annoWrap{position:absolute;inset:0;display:none;z-index:5}
body.anno-on #annoWrap{display:block}
.iconbtn.on{border-color:var(--brand);background:#eef3ff;color:var(--brand);box-shadow:0 0 0 2px rgba(74,108,247,.2)}
#annoStickers .emoji{width:38px;height:38px;font-size:20px}

/* ══ 3-column tool layout: templates · canvas · inspector ══ */
.page-tool .tool-studio{grid-template-columns:296px minmax(0,1fr) 344px}
.page-tool .tool-studio #paneControls{order:1;border-right:1px solid #dde3ee}
.page-tool .tool-studio .stagewrap{order:2}
.page-tool .tool-studio #paneInspector{order:3;border-left:1px solid #dde3ee;border-right:none}
/* NOTE: the old "@media(max-width:1200px){…inspector drops to a full-width row}"
 * block lived here but was always overridden by the (901px–1200px) block below,
 * so it never actually applied — removed rather than left as dead CSS. */

/* ══ tool layout fine-tune: widths · colors · spacing ══ */
.page-tool .tool-studio{grid-template-columns:296px minmax(0,1fr) 344px}
.page-tool .tool-studio #paneControls,.page-tool .tool-studio #paneInspector{background:linear-gradient(180deg,#edf0f7,#e7ecf5)}
.page-tool .tool-studio #paneControls{border-right:1px solid #dde3ee}
.page-tool .tool-studio #paneInspector{border-left:1px solid #dde3ee}
.page-tool .controls{padding:16px;gap:14px}
.page-tool .controls .card{border:1px solid #e3e8f1;border-radius:16px;box-shadow:0 1px 2px rgba(20,30,60,.04)}
.page-tool .controls .card .body{padding:15px 16px;gap:13px}
/* center canvas breathing room + separation from side panels */
.page-tool .stagewrap{box-shadow:inset 1px 0 0 #eef1f6,inset -1px 0 0 #eef1f6}
.page-tool .toolbar{padding:9px 14px;gap:8px}
.page-tool .stage{padding:20px}
.page-tool .thumbs{padding:11px 14px;gap:9px}
.page-tool .thumb{width:54px;height:54px}
/* Grid items default to min-width:auto, so a track can never shrink below its
 * content's min-content size — that pushed the controls pane ~26px past a
 * 320px viewport. Allowing zero min lets the columns actually collapse. */
.page-tool .tool-studio>*{min-width:0}
/* tablet widths */
@media(max-width:1500px) and (min-width:1201px){.page-tool .tool-studio{grid-template-columns:280px minmax(0,1fr) 320px}}

/* collapsible cards (headings promoted h3→h2 in R11; rules live in the R11 block) */

/* fix: responsive column overrides must win over the unscoped fine-tune base rule */
@media(max-width:1200px) and (min-width:901px){
  .page-tool .tool-studio{grid-template-columns:236px minmax(0,1fr) 276px}
  .page-tool .tool-studio #paneInspector{grid-column:auto;order:3;border-left:1px solid #dde3ee;border-top:none;height:100%;overflow-y:auto}
}
@media(max-width:900px){
  .page-tool .tool-studio{grid-template-columns:1fr}
  .page-tool .tool-studio .stagewrap{order:-1}
  .page-tool .tool-studio #paneControls{order:2;border-right:none;border-top:1px solid #dde3ee}
  .page-tool .tool-studio #paneInspector{order:3;grid-column:auto;border-left:none;border-top:1px solid #dde3ee;height:auto;overflow:visible}
  .page-tool .toolbar{flex-wrap:wrap}
  .page-tool .modes{flex:1 1 auto}
  .page-tool .tb-actions{flex:1 1 auto;margin-left:0;justify-content:flex-end}
  .page-tool .mode-tab{white-space:nowrap;padding:7px 10px}
}

/* ══ POLISH PASS 2 ══ */

/* Preview canvas fills the frame; the display box is owned by CSS (aspect-ratio
 * on .frame) so its size is stable and never shifts on (re)render — this killed
 * the first-screen CLS. The drawing buffer is still set by the renderer. */
#previewCanvas{width:100%;height:100%;display:block}

/* Toolbar: 9 action buttons overflow a 360px screen, which used to push
 * "Clear all" out of the (overflow:hidden) bar so it could not be tapped. */
.page-tool .tb-actions{flex-wrap:wrap;justify-content:flex-end}
@media(max-width:400px){
  .page-tool .toolbar{padding:8px 10px;gap:6px}
  .page-tool .iconbtn{width:32px;height:32px;font-size:14px}
  .page-tool .modes{padding:3px}
  .page-tool .mode-tab{padding:6px 9px;font-size:12px}
}

/* Background preset swatches */
.bgpresets{display:grid;grid-template-columns:repeat(8,1fr);gap:6px}
.bgsw{aspect-ratio:1;min-width:0;border:1px solid var(--line);border-radius:9px;box-shadow:var(--shadow-sm);transition:transform .12s,box-shadow .15s}
.bgsw:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
@media(max-width:520px){.bgpresets{grid-template-columns:repeat(4,1fr)}}

/* Fullscreen preview action bar */
.full-bar{position:absolute;left:50%;bottom:24px;transform:translateX(-50%);display:flex;align-items:center;gap:12px;z-index:2}
.full-dl{padding:12px 24px;border-radius:12px;background:#fff;color:var(--brand);font-weight:800;font-size:14px;box-shadow:0 10px 26px rgba(0,0,0,.35)}
.full-dl:hover{filter:brightness(1.04);transform:translateY(-1px)}
.full-tip{font-size:12px;color:rgba(255,255,255,.6)}
@media(max-width:520px){.full-bar{bottom:16px}.full-dl{padding:10px 18px;font-size:13px}.full-tip{display:none}}

/* Touch devices: raise every small control to a comfortable tap target.
 * The existing (hover:none) block only covered cell tools. */
@media(hover:none){
  .iconbtn{width:40px;height:40px}
  .emoji{width:44px;height:44px;font-size:20px}
  .lcat,.ratio,.chip,.mini{min-height:40px;display:inline-flex;align-items:center}
  .shape{min-height:44px}
  .mode-tab{min-height:40px;display:inline-flex;align-items:center}
  .thumb-x{width:28px;height:28px;font-size:14px}
  .free-tools button{width:40px;height:40px}
  .preset{min-height:38px;display:inline-flex;align-items:center}
  .seg button{min-height:36px}
  /* Native range inputs render ~22px tall, under the 24px WCAG 2.2 AA target
   * minimum and fiddly to drag with a thumb. Give them real height on touch. */
  input[type=range]{min-height:28px}
  /* Checkbox rows measured 23px — one pixel under the 24px minimum. */
  .chk{min-height:28px;display:inline-flex;align-items:center}
}

/* iPhone home-indicator / notch safe areas */
@supports (padding:env(safe-area-inset-bottom)){
  .page-tool .thumbs{padding-bottom:calc(11px + env(safe-area-inset-bottom))}
  .page-tool .toolbar{padding-left:calc(14px + env(safe-area-inset-left));padding-right:calc(14px + env(safe-area-inset-right))}
  .toast{bottom:calc(26px + env(safe-area-inset-bottom))}
  .full-bar{bottom:calc(24px + env(safe-area-inset-bottom))}
}

/* POLISH PASS 3 — motion a11y + print (R2: SEO/PWA/perf dimension) */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
}

/* Clean print for doc pages (about / legal) — hide chrome, save ink */
@media print{
  .topbar,.toolbar,.thumbs,.toast,.full-bar,.seg,.mode-tab,.btnrow,.footer,.back{display:none!important}
  .skip-link{display:none!important}
  body{background:#fff!important}
  .doc{max-width:100%!important;padding:0!important;color:#000!important}
  .doc h1,.doc h2,.doc p,.doc li,.doc .en{color:#000!important}
  .doc a{color:#000!important;text-decoration:underline}
  .cta{display:none!important}
  /* tool page: print only the collage, drop the whole control panel */
  .page-tool .controls,.page-tool .topnav,.free-tools,.cell-tools{display:none!important}
  .studio{grid-template-columns:1fr!important;gap:0!important}
  .stagewrap{position:static!important;border:0!important;box-shadow:none!important;background:#fff!important;overflow:visible!important}
  .stage{height:auto!important;min-height:0!important;background:#fff!important;border:0!important;box-shadow:none!important;padding:0!important}
  #previewCanvas{display:block!important;margin:0 auto!important;max-width:100%!important;height:auto!important}
  @page{margin:18mm}
}

/* ─═ POLISH PASS 4 — forced-colors / Windows High Contrast (R10) ═─
 * The custom controls below signal "selected/on" mainly through background
 * color, which the OS high-contrast engine flattens to a single system color.
 * Give the selected state a visible system-color border (Highlight, like native
 * selection) and outline every unselected control with CanvasText so the two
 * remain distinguishable. Also force focus rings to a system color — the brand
 * hex is invisible against an HC canvas. */
@media (forced-colors: active){
  /* unselected baseline outline so every control stays bounded */
  .mode-tab,.seg button,.chip,.lcat,.ratio,.preset,
  .shape,.scene,.layout,.iconbtn,.mini,.poscell{
    border:1px solid CanvasText;
  }
  /* selected/on state: thicker Highlight border + Highlight label */
  .mode-tab.on,.seg button.on,.chip.on,.lcat.on,.ratio.on,.preset.on,
  .shape.on,.scene.on,.layout.on,.iconbtn.on,.mini.on,.poscell.on{
    border:2px solid Highlight;
    color:Highlight;
  }
  /* focus rings must stay visible and use a system color in HC */
  :focus-visible{outline-color:Highlight}
  .to-top:focus-visible,.full-x:focus-visible,.full-dl:focus-visible,
  .fullmodal :focus-visible,.kbd-x:focus-visible{outline-color:Highlight}

  /* switch: outline the track, mark the checked state, keep the knob visible */
  .switch span{border:1px solid CanvasText;background:Canvas!important}
  .switch input:checked+span{border-color:Highlight}
  .switch span::before{background:ButtonText;border:1px solid CanvasText}

  /* range: let the OS render the track/thumb in system colors */
  input[type=range]{forced-color-adjust:auto}

  /* keep the collage frame visible against the HC canvas */
  .frame{border:2px solid CanvasText;background:Canvas!important}
  .stage{background:Canvas!important}

  /* preserve native rendering of these form controls */
  input[type=color],input[type=checkbox]{forced-color-adjust:auto}
}

/* High-contrast preference (prefers-contrast: more): strengthen a few mid-tone
 * surfaces so they read on low-contrast displays without changing the design. */
@media (prefers-contrast: more){
  .card{border-color:#c4ccdb}
  .tool-studio .controls,.tool-studio #paneControls,.tool-studio #paneInspector{background:#e7ecf5}
  .mode-tab.on,.seg button.on,.chip.on,.lcat.on,.shape.on,.scene.on,.layout.on{
    box-shadow:0 0 0 2px rgba(69,99,240,.4)
  }
}

/* ══ R11: screen-reader semantics ══
 * .sr-only: visually hidden but present in the accessibility tree (NOT display:none).
 * Tool-section headings were promoted from <h3> to <h2> for a correct heading
 * outline (h1 → h2 → h3); keep their previous <h3> visual treatment so nothing
 * shifts on screen. */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.card>h2{font-size:13px;font-weight:800;color:#39435a;padding:12px 14px;border-bottom:1px solid var(--line-2);display:flex;align-items:center;gap:8px;background:linear-gradient(180deg,#fbfcfe,#f5f7fc);letter-spacing:.2px}
.card>h2 .n{width:20px;height:20px;border-radius:6px;background:linear-gradient(135deg,var(--brand),var(--brand-2));color:#fff;font-size:12px;display:grid;place-items:center;box-shadow:0 3px 8px rgba(74,108,247,.35)}
.card>h2 .caret{margin-left:auto;color:var(--muted);transition:transform .2s;font-size:12px}
.card.collapsed>h2 .caret{transform:rotate(-90deg)}
.card.collapsed>h2{border-bottom-color:transparent}
.card>h2.card-toggle{cursor:pointer;user-select:none}
.card>h2.card-toggle:hover{background:linear-gradient(180deg,#f7f9fd,#eef2f9)}
.page-tool .controls .card>h2{padding:13px 16px;font-size:13px;background:linear-gradient(180deg,#fbfcfe,#f4f7fc)}
.page-tool .controls .card>h2 .n{width:22px;height:22px;border-radius:7px;font-size:12px}

/* ══ R12 (2026-09-21): dialog a11y completed + focus-within polish ══
 * Modals already had role="dialog" + aria-modal; this round wired the missing
 * accessible names (editModal→#editTitle, fullModal→i18n full.title,
 * kbdModal→#kbdTitle) and adds a subtle focus affordance so keyboard users can
 * see which field is active. No layout shift (box-shadow / color only). */
.page-tool .controls .fld:focus-within > label,
.page-tool .controls .fld-inline:focus-within > label,
.page-tool .controls .gridrow:focus-within > label{color:var(--brand)}
.page-tool .controls input[type=number]:focus,
.page-tool .controls input[type=text]:focus,
.page-tool .controls select:focus{box-shadow:0 0 0 3px rgba(74,108,247,.16);border-color:var(--brand)}

/* ══ R13 (2026-09-21): skip-to-content link for keyboard / screen-reader users ══
 * Visually hidden until focused; jumps to the page's <main> so keyboard users
 * don't have to tab through the whole nav first. Fixed so it stays in view at
 * any scroll position. High-contrast brand chip, sits above the topbar. */
.skip-link{position:fixed;left:12px;top:-64px;z-index:2000;background:var(--brand);color:#fff;padding:10px 16px;border-radius:9px;font-weight:800;font-size:14px;line-height:1;box-shadow:0 8px 22px rgba(20,30,60,.28);transition:top .15s ease}
.skip-link:focus,.skip-link:focus-visible{top:12px;outline:3px solid #fff;outline-offset:2px}

/* ══ R14 (2026-09-23): bolder visual pass — layered hero, colour domains, richer cards ══ */

/* hero: layered brand wash + faint grid, content lifted above it */
.hero-home{position:relative;overflow:hidden;padding:62px 0 42px;background:
  radial-gradient(52% 68% at 88% 6%, rgba(124,91,214,.16), transparent 60%),
  radial-gradient(46% 60% at 4% 20%, rgba(69,99,240,.14), transparent 60%),
  radial-gradient(38% 52% at 60% 100%, rgba(224,103,155,.10), transparent 60%),
  linear-gradient(180deg,#eef3ff 0%,#f7f9ff 58%,var(--bg) 100%)}
.hero-home::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(rgba(69,99,240,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(69,99,240,.05) 1px,transparent 1px);
  background-size:34px 34px;
  -webkit-mask-image:linear-gradient(180deg,#000,transparent 82%);mask-image:linear-gradient(180deg,#000,transparent 82%)}
.hero-grid{position:relative;z-index:1}
.hero-home h1{font-size:clamp(32px,5.4vw,54px);letter-spacing:-.8px}
.hero-home .badges span{border-color:#dbe3f5;box-shadow:0 6px 16px rgba(20,30,60,.07)}
.btn-hero{box-shadow:0 14px 32px rgba(69,99,240,.36)}

/* hero mock: bigger, glossy tiles + language-neutral floating chips */
.hero-visual{position:relative}
.mock{width:min(520px,94%);gap:12px;transform:none}
.mock>div{box-shadow:inset 0 0 0 1px rgba(255,255,255,.35),0 10px 24px rgba(20,30,60,.14)}
.hero-visual::before{content:"250+";position:absolute;top:4%;left:2%;z-index:2;background:#fff;color:var(--brand);
  font-weight:900;font-size:21px;padding:10px 16px;border-radius:14px;box-shadow:0 14px 30px rgba(69,99,240,.28)}
.hero-visual::after{content:"PNG · JPG · WebP";position:absolute;bottom:5%;right:0;z-index:2;background:#1b2333;color:#fff;
  font-weight:700;font-size:13px;padding:9px 14px;border-radius:12px;box-shadow:0 14px 30px rgba(20,30,60,.32)}
@media(max-width:860px){.hero-visual::before,.hero-visual::after{display:none}}

/* section headings: gradient underline bar, more air */
section.content{padding:64px 0}
section.content h2::after{content:"";display:block;width:64px;height:5px;border-radius:999px;
  background:linear-gradient(90deg,var(--brand),var(--brand-4));margin:14px auto 0}
section.content .sub{margin:14px auto 34px}

/* feature cards: icon tiles with per-domain tints */
.feat{padding:24px}
.feat .ic{width:52px;height:52px;border-radius:15px;display:grid;place-items:center;font-size:26px;
  background:linear-gradient(135deg,rgba(69,99,240,.14),rgba(124,91,214,.14));box-shadow:inset 0 0 0 1px rgba(69,99,240,.12)}
.feat:nth-child(3n+2) .ic{background:linear-gradient(135deg,rgba(55,179,166,.16),rgba(69,99,240,.12));box-shadow:inset 0 0 0 1px rgba(55,179,166,.14)}
.feat:nth-child(3n) .ic{background:linear-gradient(135deg,rgba(224,103,155,.16),rgba(224,161,58,.12));box-shadow:inset 0 0 0 1px rgba(224,103,155,.14)}
.feat h3{font-size:18.5px;margin:14px 0 8px}

/* guide: deep colour domain with glass step cards + connectors */
#guide{background:linear-gradient(135deg,#141d3a 0%,#232c5c 55%,#3a2b63 100%);border-top:none}
#guide h2,#guide .sub{color:#fff}
#guide h2::after{background:linear-gradient(90deg,#7c5bd6,#e0679b)}
#guide .sub{color:#b9c2e4}
#guide .step{position:relative;background:rgba(255,255,255,.97);border-color:transparent;box-shadow:0 18px 40px rgba(8,12,30,.35)}
#guide .step .num{background:linear-gradient(135deg,var(--brand),var(--brand-2));color:#fff;border-radius:12px;box-shadow:0 6px 14px rgba(69,99,240,.4)}
@media(min-width:821px){
  #guide .step:not(:last-child)::after{content:"";position:absolute;top:50%;right:-14px;width:10px;height:10px;z-index:2;
    border-top:3px solid rgba(255,255,255,.55);border-right:3px solid rgba(255,255,255,.55);transform:rotate(45deg)}
}

/* size table: pill ratios + zebra rows */

/* faq: open state lifts */
.faq details{border-radius:14px;transition:box-shadow .2s,border-color .2s}
.faq details[open]{box-shadow:var(--shadow);border-color:#d8e0f2}
.faq summary{font-size:15.5px}

/* about: tinted band with a floating white panel */
#about{background:linear-gradient(135deg,#eef3ff,#f7effc 60%,#eafaf7);border-top:1px solid var(--line)}
#about .wrap{background:#fff;border:1px solid #e2e8f6;border-radius:22px;box-shadow:var(--shadow);padding:40px 28px}

/* footer: gradient navy + brand hairline */
footer{position:relative;background:linear-gradient(135deg,#10162b,#1b2347 60%,#251b3f)}
footer::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--brand),var(--brand-2),var(--brand-4),var(--brand-3))}

/* tool page topbar: subtle depth */
.page-tool .topbar{background:linear-gradient(180deg,#ffffff,#f6f8fd)}

/* ══ R25 (2026-09-25): stage contain-fit + inspector cards must not shrink-clip ══ */
.tool-studio .stage{justify-content:center;align-items:center}
.page-tool .controls .card{flex:0 0 auto}

/* R26: recently-used layouts row above the category chips */
.recent-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:8px}
.recent-row[hidden]{display:none}
.recent-lab{font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-right:2px}
.recent-tile{width:34px;height:34px;padding:4px;border:1px solid var(--line);border-radius:9px;background:#fff;transition:transform .12s,border-color .15s,box-shadow .15s}
.recent-tile:hover{border-color:var(--brand);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.recent-tile.on{border-color:var(--brand);box-shadow:0 0 0 2px rgba(74,108,247,.25)}
.recent-tile svg{display:block}
/* R26: my saved layouts row (grid mode) */
.my-layouts{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:10px}
.my-layouts[hidden]{display:none}
.myl-hint{font-size:11px;color:var(--muted);width:100%;order:-1}
/* R29: recent-exports strip in the export card */
.export-history{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:12px}
.export-history[hidden]{display:none}
.exh-thumb{width:56px;height:56px;padding:0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#fff;flex:0 0 auto;transition:transform .12s,border-color .15s,box-shadow .15s}
.exh-thumb img{display:block;width:100%;height:100%;object-fit:cover}
.exh-thumb:hover{border-color:var(--brand);transform:translateY(-2px);box-shadow:var(--shadow-sm)}

/* ══ R31 (2026-09-25): home brush-play demo banner (SVG stroke animation) ══ */
.brush-banner{display:flex;align-items:center;gap:22px;margin-top:26px;padding:22px 26px;border-radius:18px;
  background:linear-gradient(120deg,#eef3ff,#f7f0ff 55%,#fdeef5);border:1px solid #e2e8f6;box-shadow:var(--shadow-sm)}
.brush-banner svg{width:132px;height:99px;flex:0 0 auto}
.bb-line{fill:rgba(69,99,240,.07);stroke:var(--brand);stroke-width:2.5;stroke-linecap:round;stroke-dasharray:340;animation:bbdraw 3.4s ease-in-out infinite alternate}
.bb-ph{opacity:0;animation:bbpop 4.4s ease-in-out infinite}
.bb-1{animation-delay:.5s;fill:#4a6cf7}.bb-2{animation-delay:1.1s;fill:#e0679b}.bb-3{animation-delay:1.7s;fill:#37b3a6}
@keyframes bbdraw{from{stroke-dashoffset:340}to{stroke-dashoffset:0}}
@keyframes bbpop{0%,8%{opacity:0;transform:scale(.7)}22%,86%{opacity:.92;transform:scale(1)}100%{opacity:0}}
.bb-copy{flex:1;min-width:0}
.bb-copy b{display:block;font-size:17px;font-weight:900;letter-spacing:-.2px}
.bb-copy p{margin:5px 0 0;color:var(--muted);font-size:14px}
.brush-banner .btn-hero{padding:11px 18px;font-size:14.5px;flex:0 0 auto}
@media(max-width:720px){.brush-banner{flex-direction:column;text-align:center;gap:14px}.brush-banner .btn-hero{width:100%;justify-content:center}}
@media(prefers-reduced-motion:reduce){.bb-line{animation:none;stroke-dashoffset:0}.bb-ph{animation:none;opacity:.92}}

/* R32: editor prev/next cell stepper (same shape as the sibling close button) */
.mhead .mnav{margin-left:auto;display:flex;gap:2px}
.mhead #editClose{margin-left:2px}
.mnav .x:disabled{opacity:.35;cursor:default}
.mnav .x:disabled:hover{background:none}
/* R32: tray highlight while a cell photo is dragged over it (drop = remove from cell) */
.thumbs.tray-drop{background:#e9efff;outline:2px dashed var(--brand);outline-offset:-4px}



/* ══ R24 (2026-09-25): guide step glyphs · glossy mock tiles · footer link lift ══ */
.mock>div{position:relative;overflow:hidden}
.mock>div::after{content:"";position:absolute;inset:0;border-radius:inherit;background:linear-gradient(150deg,rgba(255,255,255,.34),rgba(255,255,255,0) 46%);pointer-events:none}
footer .fnav a{transition:color .15s,transform .15s}
footer .fnav a:hover{color:#fff;transform:translateY(-1px)}


/* ══ R15 (2026-09-23): scroll-spy nav · layout showcase · richer empty state ══ */

/* nav active section pill (driven by home.js scroll-spy) */
.topnav a.on{background:#e9efff;color:var(--brand)}

/* layout showcase */
.show-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
@media(max-width:820px){.show-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:460px){.show-grid{grid-template-columns:1fr}}
#showcase .show{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:14px;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;gap:12px;transition:transform .16s,box-shadow .16s,border-color .16s}
.show:hover{transform:translateY(-4px);box-shadow:var(--shadow);border-color:#cfd9f2}
.show b{font-size:15px;font-weight:800;text-align:center;color:#39435a}
.ml{display:grid;gap:5px;aspect-ratio:4/3;background:linear-gradient(180deg,#fbfcfe,#f1f4fa);border:1px solid var(--line-2);border-radius:12px;padding:10px}
.ml i{border-radius:6px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.35)}
.ml i:nth-child(4n+1){background:linear-gradient(135deg,#4a6cf7,#7c5bd6)}
.ml i:nth-child(4n+2){background:linear-gradient(135deg,#e0679b,#e0a13a)}
.ml i:nth-child(4n+3){background:linear-gradient(135deg,#37b3a6,#4a6cf7)}
.ml i:nth-child(4n){background:linear-gradient(135deg,#d1523f,#e0679b)}
.ml-3x3{grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr)}
.ml-lr{grid-template-columns:2fr 1fr;grid-template-rows:1fr 1fr}
.ml-lr i:first-child{grid-row:1/3}
.ml-tb{grid-template-columns:repeat(3,1fr);grid-template-rows:2fr 1fr}
.ml-tb i:first-child{grid-column:1/4}
.ml-4{grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr}
.ml-cine{grid-template-columns:1fr 1fr;grid-template-rows:2fr 1fr}
.ml-cine i:first-child{grid-column:1/3}
.ml-strip{grid-template-columns:repeat(3,1fr)}

/* tool page empty-state icon: compact gradient tile inside the bottom pill */
.stage-hint .sh-ic{width:34px;height:34px;border-radius:11px;display:grid;place-items:center;font-size:19px;opacity:1;
  background:linear-gradient(135deg,#eef3ff,#f6ecfb);box-shadow:inset 0 0 0 1px rgba(69,99,240,.14)}
.stage-hint .sh-t{font-size:14px}

/* print: showcase tiles print as bordered blocks, keep them compact */
@media print{.show-grid{grid-template-columns:repeat(3,1fr)}.show{box-shadow:none}}

/* scroll-spy is JS-driven; without JS the nav keeps its plain hover-only look */

/* print bug fix: .reveal elements never scrolled into view were opacity:0 on paper — blank pages */
@media print{
  html.js .reveal{opacity:1!important;transform:none!important}
  footer{display:none!important}
}

/* ══ R16 (2026-09-23): FAQ two-column ══ */
@media(min-width:981px){
  .faq{max-width:960px;display:block;columns:2;column-gap:16px}
  .faq details{break-inside:avoid;margin-bottom:10px}
}

/* about stats band */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:28px 0 6px}
@media(max-width:560px){.stats{grid-template-columns:repeat(2,1fr)}}
.stat{background:linear-gradient(180deg,#fff,#f7f9ff);border:1px solid #e2e8f6;border-radius:16px;padding:18px 10px;text-align:center;box-shadow:var(--shadow-sm)}
.stat b{display:block;font-size:clamp(28px,3.4vw,38px);font-weight:900;letter-spacing:-.5px;line-height:1.1;
  background:linear-gradient(120deg,var(--brand),var(--brand-2) 60%,var(--brand-4));-webkit-background-clip:text;background-clip:text;color:transparent}
.stat span{display:block;margin-top:4px;font-size:13.5px;font-weight:600;color:var(--muted)}

/* PWA install pill — same shape as the sibling badges, brand-tinted */
.install-btn{background:linear-gradient(120deg,var(--brand),var(--brand-2));color:#fff;border:none;border-radius:999px;padding:6px 14px;font-size:13px;font-weight:700;font-family:inherit;cursor:pointer;box-shadow:0 8px 20px rgba(69,99,240,.32);transition:.14s}
.install-btn:hover{transform:translateY(-1px);filter:brightness(1.05)}

/* FAQ tools row */
.faq-tools{display:flex;justify-content:center;margin:-14px 0 18px}
.faq-tools .mini{min-width:110px;text-align:center}





/* ══ R21: shared doc-page panel — about + legal use ONE source (inline <style> blocks removed) ══ */
body.page-doc{background:
  radial-gradient(52% 55% at 90% 4%, rgba(124,91,214,.14), transparent 60%),
  radial-gradient(46% 50% at 4% 20%, rgba(69,99,240,.12), transparent 60%),
  linear-gradient(180deg,#eef3ff,#f7f9ff 45%,var(--bg))}
body.page-doc .doc{position:relative;max-width:860px;margin:34px auto 60px;padding:40px 44px 56px;background:#fff;border:1px solid #e2e8f6;border-radius:22px;box-shadow:0 24px 60px rgba(20,30,60,.10)}
body.page-doc .doc::before{content:"";position:absolute;top:0;left:26px;right:26px;height:4px;border-radius:999px;background:linear-gradient(90deg,var(--brand),var(--brand-2),var(--brand-4),var(--brand-3))}
body.page-doc .doc h1{font-size:32px;font-weight:900;margin-bottom:8px;letter-spacing:-.4px}
body.page-doc .doc h1 .en{font-size:18px;font-weight:700;color:var(--muted)}
body.page-doc .doc h2{font-size:21px;font-weight:800;margin:30px 0 10px;display:flex;align-items:center;gap:10px}
body.page-doc .doc h2::before{content:"";width:8px;height:22px;border-radius:999px;background:linear-gradient(180deg,var(--brand),var(--brand-2))}
body.page-doc .doc p,body.page-doc .doc li{color:#39435a;font-size:15.5px;line-height:1.8}
body.page-doc .doc ul{padding-left:22px}
body.page-doc .doc li::marker{color:var(--brand)}
body.page-doc .doc .en{color:#6b7688;font-size:14px}
body.page-doc .doc .updated{color:#6b7688;margin-bottom:24px}
body.page-doc .back{display:inline-flex;align-items:center;gap:6px;margin-bottom:20px;color:var(--brand);font-weight:700;background:#eef3ff;border-radius:999px;padding:8px 16px;box-shadow:inset 0 0 0 1px rgba(69,99,240,.16)}
body.page-doc .back:hover{background:#e3ebff}
body.page-doc .cta{display:inline-block;margin-top:24px;padding:13px 26px;border-radius:13px;background:linear-gradient(120deg,var(--brand),var(--brand-2));color:#fff;font-weight:800;box-shadow:0 12px 26px rgba(69,99,240,.35);transition:.14s}
body.page-doc .cta:hover{transform:translateY(-2px);filter:brightness(1.05)}
@media(max-width:640px){body.page-doc .doc{padding:28px 20px 40px;margin-top:18px}}

/* tool topbar status chip: brand dot + tinted pill (flat tint keeps backgroundColor readable by the contrast gate) */
.status-chip{color:#39435a;background:#eef1f7;padding:6px 12px 6px 10px;display:inline-flex;align-items:center;gap:7px}
.status-chip::before{content:"";width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:linear-gradient(135deg,var(--brand),var(--brand-2));box-shadow:0 0 0 3px rgba(69,99,240,.14)}
/* re-declare the small-screen hide INSIDE this appended layer — media queries add no specificity (lesson 97) */
@media(max-width:520px){.status-chip{display:none}}

/* ══ R22 (2026-09-23): tool workspace colour domains — the four numbered zones each carry a hue
   (blue · purple · teal · pink) on the step chip and header tint. No border weight changes. ══ */
#uploadSection{--acc1:#4563f0;--acc2:#7c5bd6;--accTint:#f2f5ff}
#layoutSection,#sceneSection,#gridSection,#freeSection{--acc1:#7c5bd6;--acc2:#b8407a;--accTint:#f7f3ff}
#styleSection,#captionSection,#annoSection{--acc1:#1f7a6e;--acc2:#4563f0;--accTint:#eefaf7}
#exportSection{--acc1:#b8407a;--acc2:#a86413;--accTint:#fdf3f7}
.page-tool .controls .card>h2{background:linear-gradient(180deg,#fff,var(--accTint,#f4f7fc))}
.page-tool .controls .card>h2 .n{background:linear-gradient(135deg,var(--acc1,var(--brand)),var(--acc2,var(--brand-2)));box-shadow:0 3px 8px rgba(20,30,60,.22)}

/* ══ R23 (2026-09-24): tips section becomes a numbered rail — visually distinct from the feature grid ══ */
#tips .grid-feat{counter-reset:tip}
#tips .feat{counter-increment:tip;padding:22px 22px 22px 92px}
#tips .feat::after{content:"0" counter(tip);position:absolute;left:22px;top:20px;font-size:34px;font-weight:900;line-height:1;
  background:linear-gradient(135deg,var(--brand),var(--brand-2));-webkit-background-clip:text;background-clip:text;color:transparent;opacity:.9}
#tips .feat h3{margin:2px 0 6px}
@media(max-width:820px){#tips .feat{padding:22px 22px 22px 92px}}


/* R34: gallery clear chip on the tray strip (grid/free modes) */
.thumb-clear{width:auto;min-width:52px;padding:0 12px;display:grid;place-items:center;font-size:12px;font-weight:700;color:#b3423a;border-style:dashed;border-color:#e0b4b0;background:#fff;cursor:pointer}
.thumb-clear:hover{background:#fdf1f0;border-color:#b3423a}

/* R35: touch-drag merge on phones (browser must not steal the gesture) */
.gridbase,.gridu{touch-action:none}

/* R36: per-cell add affordance + drag may start inside an empty merged block */
.gridu{display:grid;place-items:center}
.gridu-plus{pointer-events:none;font-size:22px;font-weight:300;color:rgba(74,108,247,.55);line-height:1}
.gridu:hover .gridu-plus{color:var(--brand)}
.overlay .cellframe.empty{pointer-events:none}
.overlay .cellframe.empty .cell-add,.overlay .cellframe.empty .cell-badge,.overlay .cellframe.empty .cell-split{pointer-events:auto}
/* R37: always-visible unmerge chip on merged blocks */
.cell-split{position:absolute;bottom:6px;right:6px;height:26px;padding:0 9px;border-radius:8px;background:#fff;border:1px solid #e0b4b0;color:#b3423a;font-size:12px;font-weight:700;display:flex;align-items:center;gap:3px;box-shadow:var(--shadow-sm);cursor:pointer}
.cell-split:hover{border-color:#b3423a;background:#fdf1f0}
/* R40: every grid cell carries its number (empty 1×1 tiles included) */
.gridu{position:relative}
.gridu-badge{position:absolute;top:4px;left:6px;font-size:10px;font-weight:700;color:#8a93a8;background:rgba(255,255,255,.85);border:1px solid var(--line);border-radius:6px;padding:1px 6px;line-height:1.4}
.gridu:hover .gridu-badge{color:var(--brand);border-color:var(--brand)}

/* R42: category dropdown + recent-row clear */
.lcat-select{width:100%;padding:9px 12px;border-radius:10px;border:1px solid var(--line);background:#fff;font-size:13px;font-weight:700;cursor:pointer;margin:2px 0 8px}
.lcat-select:hover{border-color:var(--brand)}
.recent-clear{margin-left:auto;border:0;background:none;color:var(--brand);font-size:12px;font-weight:700;cursor:pointer;padding:4px 6px}
.recent-clear:hover{filter:brightness(1.2)}

/* R46: photo-count badge on every layout thumbnail */
.layouts .layout{position:relative}
.lay-n{position:absolute;top:3px;right:4px;min-width:16px;font-size:10px;font-weight:800;color:#fff;background:rgba(20,30,60,.58);border-radius:6px;padding:1px 4px;line-height:1.3;text-align:center}
.layout.on .lay-n{background:var(--brand)}

/* R48: UX — active icon toggle, annotation-mode banner, filled-cell flash */
.iconbtn.on{border-color:var(--brand);background:var(--brand);color:#fff;box-shadow:0 3px 10px rgba(74,108,247,.35)}
.anno-banner{display:none;position:absolute;left:50%;bottom:12px;transform:translateX(-50%);z-index:6;align-items:center;gap:12px;max-width:92%;padding:9px 14px;border-radius:999px;background:rgba(20,24,40,.86);color:#fff;font-size:12.5px;font-weight:600;box-shadow:0 8px 22px rgba(10,15,30,.35);backdrop-filter:blur(4px)}
body.anno-on .anno-banner{display:flex}
.anno-banner .mini{background:#fff;color:#25304a;border:0;font-weight:700;padding:5px 12px;flex:0 0 auto}
.cellframe.flash{animation:celflash .85s ease-out}
@keyframes celflash{0%{outline:3px solid var(--brand);outline-offset:3px;background:rgba(74,108,247,.22)}100%{outline:0 solid transparent;outline-offset:0;background:transparent}}

/* R49: boot loader, spinner, copy/export busy, dropzone processing state */
.boot-loader{display:none;position:fixed;inset:0;z-index:60;align-items:center;justify-content:center;gap:12px;background:#f6f8fc;color:#5a6478;font-size:14px;font-weight:700}
body.preboot .boot-loader{display:flex}
.spin{width:22px;height:22px;border-radius:50%;border:3px solid rgba(74,108,247,.22);border-top-color:var(--brand);animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(1turn)}}
.fullmodal.loading::after{content:"";position:fixed;left:50%;top:50%;width:28px;height:28px;margin:-14px 0 0 -14px;border-radius:50%;border:3px solid rgba(255,255,255,.35);border-top-color:#fff;animation:spin .8s linear infinite;z-index:2}
.dropzone.busy{border-color:var(--brand);color:var(--brand);background:#eef2ff}

/* R52: denser shape grid on desktop (8 cols, tighter gaps); touch targets stay >=44px on phones */
@media(min-width:641px){.shapes{grid-template-columns:repeat(8,minmax(0,1fr));gap:5px}.shape{border-radius:9px;font-size:15px}}
/* R53: inspector tab bar - one card visible at a time, kills the long scroll */
.rtabs{position:sticky;top:8px;z-index:6;display:flex;gap:4px;padding:4px;border-radius:13px;background:var(--line-2);border:1px solid var(--line);box-shadow:var(--shadow-sm);margin-bottom:10px}
.rtab{flex:1;min-height:34px;border:0;border-radius:9px;background:transparent;color:var(--muted);font-weight:700;font-size:13px;cursor:pointer;transition:.14s}
.rtab:hover{color:var(--ink)}
.rtab.on{background:linear-gradient(135deg,#4a6cf7,#6a52e0);color:#fff;box-shadow:0 2px 8px rgba(74,108,247,.35)}
.rtab:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
@media (hover:none){.rtab{min-height:40px}}
/* R54: slider rows are one line (name | slider | editable value); spinners appear only while focused */
.fld:has(> .fldrow){flex-direction:row;align-items:center;gap:8px}
.fld:has(> .fldrow)>label{flex:0 0 auto;min-width:5.2em}
.fldrow{flex:1;min-width:0}
output.sync-out{display:none}
.numwrap{display:inline-flex;align-items:center;gap:2px;flex:0 0 auto}
input.numin{width:48px;padding:3px 5px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--ink);font-weight:700;font-size:12.5px;text-align:right;font-variant-numeric:tabular-nums}
input.numin::-webkit-inner-spin-button,input.numin::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
input.numin:focus::-webkit-inner-spin-button{opacity:1;-webkit-appearance:auto}
input.numin:focus{outline:2px solid var(--brand);outline-offset:1px}
input.numin:disabled{opacity:.45}
.unit{font-style:normal;color:var(--muted);font-size:11.5px;min-width:1em}
@media(hover:none){input.numin{min-height:34px;width:56px}}
/* R54b: at foldable-narrow widths the one-line slider row wraps instead of overflowing */
@media(max-width:420px){.fld:has(> .fldrow){flex-wrap:wrap}.fld:has(> .fldrow)>label{min-width:0;flex:1 1 auto}}
.fld input[type=range],.fldrow input[type=range]{min-width:0}
.fld input[type=range],.fldrow input[type=range]{min-width:40px}
@media(min-width:421px){.fld input[type=range],.fldrow input[type=range]{min-width:40px}}
@media(max-width:420px){.fld input[type=range],.fldrow input[type=range]{min-width:0}}
/* R55: editable hex code box beside every color swatch */
.hexwrap{display:inline-flex;align-items:center;flex:0 0 auto}
input.hexin{width:78px;padding:3px 6px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--ink);font-weight:700;font-size:12px;font-family:ui-monospace,Consolas,monospace;text-align:center;text-transform:lowercase}
input.hexin:focus{outline:2px solid var(--brand);outline-offset:1px}
.fld-inline>label.clab{flex:0 0 auto;min-width:auto}
@media(hover:none){input.hexin{min-height:34px;width:88px}}
/* R56: related controls share one labelled box inside inspector cards */
.grp{border:1px solid var(--line);border-radius:12px;padding:8px 9px 10px;display:flex;flex-direction:column;gap:7px;background:linear-gradient(180deg,rgba(74,108,247,.05),rgba(124,91,214,.025) 55%,rgba(124,91,214,0))}
.grp>.fld-label{margin-top:0;color:var(--brand);font-weight:800}
@media(max-width:420px){.fld input[type=range],.fldrow input[type=range]{min-width:24px}}
/* R59: width and height inputs share one row */
.fld-inline:has(#outW)>label{flex:0 0 auto;min-width:auto}
.fld-inline:has(#outW)>input{flex:1 1 0;min-width:0;max-width:none !important}
/* R64: coarse-pointer hit floor for new controls */
@media(hover:none){#capAdd{min-height:44px}#capFont{min-height:40px}input.numin,input.hexin{min-height:40px}}
/* == R68 (2026-09-26): unified popup family - one token set for scrim, card, title, close, entrance == */
:root{--pop-r:20px;--pop-card:linear-gradient(180deg,#fff,#fbfcff);--pop-line:1px solid var(--line);--pop-shadow:0 24px 70px rgba(10,18,40,.32),0 2px 8px rgba(10,18,40,.12);--pop-scrim:rgba(16,22,40,.5);--pop-blur:blur(6px)}
@keyframes popin{from{opacity:0;transform:translateY(12px) scale(.97)}to{opacity:1;transform:none}}
@keyframes bannerin{from{opacity:0;transform:translateX(-50%) translateY(10px)}to{opacity:1;transform:translateX(-50%)}}
/* scrims: identical tint + frost behind every dialog */
.modal{background:var(--pop-scrim);-webkit-backdrop-filter:var(--pop-blur);backdrop-filter:var(--pop-blur)}
.kbdmodal{background:var(--pop-scrim);-webkit-backdrop-filter:var(--pop-blur);backdrop-filter:var(--pop-blur)}
.coach .cbg{background:var(--pop-scrim);-webkit-backdrop-filter:var(--pop-blur);backdrop-filter:var(--pop-blur)}
/* cards: same radius / border / shadow / entrance for every popup surface */
.modal .box{border-radius:var(--pop-r);border:var(--pop-line);box-shadow:var(--pop-shadow);background:var(--pop-card)}
.modal.open .box{animation:popin .22s ease}
.kbdbox{border-radius:var(--pop-r);border:var(--pop-line);box-shadow:var(--pop-shadow);background:var(--pop-card)}
.kbdmodal.open .kbdbox{animation:popin .22s ease}
.coach{border-radius:var(--pop-r);border:var(--pop-line);box-shadow:var(--pop-shadow);background:var(--pop-card)}
.coach.open{animation:popin .22s ease}
/* one title style and one close-button style across the family */
.modal .side .mhead h3,.kbdbox h3,.coach h3{font-size:17px;font-weight:900;color:var(--ink)}
.modal .side .mhead .x,.kbd-x{width:34px;height:34px;border-radius:10px;font-size:19px;line-height:1;color:var(--muted);display:grid;place-items:center}
.modal .side .mhead .x:hover,.kbd-x:hover{background:var(--chip);color:var(--ink)}
/* annotation banner joins the card family (was a dark pill clashing with the light UI) */
.anno-banner{border-radius:14px;background:rgba(255,255,255,.94);border:var(--pop-line);color:var(--ink);box-shadow:var(--pop-shadow);-webkit-backdrop-filter:var(--pop-blur);backdrop-filter:var(--pop-blur);padding:8px 10px 8px 14px}
body.anno-on .anno-banner{animation:bannerin .24s ease}
.anno-banner .mini{background:linear-gradient(135deg,#4a6cf7,#6a52e0);color:#fff;font-weight:800;padding:6px 14px;border-radius:9px;border:0;box-shadow:0 2px 8px rgba(74,108,247,.35)}
.anno-banner .mini:hover{filter:brightness(1.08)}
/* toast + fullscreen viewer speak the same shadow/entrance language */
.toast{border-radius:14px;box-shadow:0 14px 36px rgba(10,18,40,.28)}
.fullmodal{background:rgba(8,11,22,.92);-webkit-backdrop-filter:var(--pop-blur);backdrop-filter:var(--pop-blur)}
.fullmodal .full-inner{animation:popin .22s ease}
@media(prefers-reduced-motion:reduce){.modal.open .box,.kbdmodal.open .kbdbox,.coach.open,body.anno-on .anno-banner,.fullmodal .full-inner{animation:none}}
/* == R69 (2026-09-26): inspector tabs - groove track + per-domain active gradients == */
.rtabs{padding:5px;gap:5px;border-radius:14px;background:linear-gradient(180deg,#eaeef6,#e2e7f1);box-shadow:inset 0 1px 3px rgba(20,30,60,.1),var(--shadow-sm)}
.rtab{min-height:38px;border-radius:10px;font-weight:800;letter-spacing:.04em;color:#5b6577;transition:.16s ease}
.rtab:hover{color:var(--ink);background:rgba(255,255,255,.65)}
.rtab.on{color:#fff;text-shadow:0 1px 1px rgba(10,18,40,.18)}
.rtab.on[data-t="styleSection"]{background:linear-gradient(135deg,#4a6cf7,#6a52e0);box-shadow:0 3px 10px rgba(74,108,247,.4),inset 0 1px 0 rgba(255,255,255,.28)}
.rtab.on[data-t="captionSection"]{background:linear-gradient(135deg,#1f7a6e,#37b3a6);box-shadow:0 3px 10px rgba(31,122,110,.4),inset 0 1px 0 rgba(255,255,255,.28)}
.rtab.on[data-t="annoSection"]{background:linear-gradient(135deg,#7c5bd6,#b8407a);box-shadow:0 3px 10px rgba(124,91,214,.42),inset 0 1px 0 rgba(255,255,255,.28)}
.rtab.on[data-t="exportSection"]{background:linear-gradient(135deg,#b8407a,#a86413);box-shadow:0 3px 10px rgba(184,64,122,.42),inset 0 1px 0 rgba(255,255,255,.28)}
@media(max-width:420px){.rtab{font-size:12px;letter-spacing:0}}
@media (hover:none){.rtab{min-height:40px}}
/* == R72 (2026-09-26): the tab bar no longer floats - settings content must never scroll behind it == */
.rtabs{position:static;z-index:auto;margin:0 0 12px}
/* == R79 (2026-09-26): keep 透明 on the 背景色 line - it was pushed to a second row by a 3px shortfall == */
.fld-inline:has(#ckBgTransparent){gap:6px;flex-wrap:nowrap}
.fld-inline:has(#ckBgTransparent) input.hexin{width:70px}
.fld-inline:has(#ckBgTransparent) .chk{flex:0 0 auto}
/* == R80 (2026-09-26): pinned tab band + card header — opaque, gutter-wide, content scrolls beneath == */
.rtabspin{position:sticky;top:-16px;z-index:8;background:#eef1f7;margin:0 -16px;padding:16px 16px 6px;box-shadow:0 8px 10px -8px rgba(20,30,60,.16)}
.controls .card{overflow:clip}
.controls .card>h2{position:sticky;top:54px;z-index:7}
/* == R81 (2026-09-26): checkboxes shrink-wrap so three fit one row (the generic .fld-inline>label flex:1/min-80 made each .chk 80px wide) == */
.fld-inline>label.chk{flex:0 1 auto;min-width:auto}
/* == R83 (2026-09-26): self-hosted OFL webfonts — lazy-downloaded only when a text block uses them == */
@font-face{font-family:'ZCOOL KuaiLe';src:url('../fonts/zcool-kuaile.woff2') format('woff2');font-display:swap}
@font-face{font-family:'ZCOOL QingKe HuangYou';src:url('../fonts/zcool-huangyou.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Ma Shan Zheng';src:url('../fonts/ma-shan-zheng.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Dancing Script';src:url('../fonts/dancing-script-700.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Pacifico';src:url('../fonts/pacifico-400.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Bangers';src:url('../fonts/bangers-400.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Playfair Display';src:url('../fonts/playfair-display-800.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Montserrat';src:url('../fonts/montserrat-700.woff2') format('woff2');font-display:swap}
@font-face{font-family:'Caveat';src:url('../fonts/caveat-700.woff2') format('woff2');font-display:swap}
/* == R84 (2026-09-26): sticker grid = 5 equal columns (fixed-tile flex left ragged right space; now both side gaps match) == */
#annoStickers{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px}
#annoStickers .emoji{width:auto;height:44px}
/* == R87 (2026-09-26): custom image stickers — upload tile + crop canvas == */
.st-up{font-size:12px;font-weight:800;color:var(--brand);background:#f2f5ff;border-style:dashed}
.st-up:hover{border-color:var(--brand);background:#eef2ff}
#stCropCv{border:1px solid var(--line);touch-action:none}
/* == R90 (2026-09-26): hero badges — ONE frame per pill (the old descendant rule framed the inner span too) + brand check chips == */
.hero .badges{gap:10px;margin-top:18px}
.hero .badges>span{display:inline-flex;align-items:center;gap:7px;background:linear-gradient(180deg,#fff,#f6f8fd);border:1px solid #dbe3f5;border-radius:999px;padding:6px 14px 6px 7px;font-size:13px;font-weight:700;color:#39435a;box-shadow:0 6px 16px rgba(20,30,60,.07)}
.hero .badges>span>i.ck{flex:0 0 auto;width:19px;height:19px;border-radius:50%;display:grid;place-items:center;font-style:normal;font-size:11px;color:#fff;background:linear-gradient(135deg,var(--brand),var(--brand-2));box-shadow:0 2px 6px rgba(74,108,247,.35)}
.hero .badges>span>span{background:none;border:0;border-radius:0;padding:0;box-shadow:none;font-weight:700}
.hero .badges>span:hover{border-color:var(--brand)}
/* == R91 (2026-09-26): feature/tips cards - title sits beside the icon (.feat-hd flex row), top gradient bars removed, card skin refreshed == */
.feat::before{content:none;display:none}
.feat{background:linear-gradient(180deg,#fff 55%,#f4f7ff);border:1px solid #e2e8f6;border-radius:18px;box-shadow:0 3px 14px -6px rgba(20,30,60,.10)}
.feat-hd{display:flex;align-items:center;gap:13px}
.feat-hd>h3{margin:0 !important;font-size:17.5px;line-height:1.35}
.feat-hd .ic{width:52px;height:52px;border-radius:16px;box-shadow:inset 0 0 0 1px rgba(69,99,240,.12),0 5px 12px -5px rgba(20,30,60,.22)}
.feat p{margin-top:12px}
.feat:hover{border-color:#c7d4f7;box-shadow:0 18px 34px -18px rgba(69,99,240,.32)}
@media(max-width:560px){.feat-hd{gap:10px}.feat-hd .ic{width:46px;height:46px;font-size:22px}}


/* == R93 (2026-09-26): guide steps - no glyph tiles before titles; title sits right of the number chip == */
.step-hd{display:flex;align-items:center;gap:12px}
.step .num{margin-bottom:0}
.step-hd>h3{margin-bottom:0}
.step-hd+p{margin-top:10px}
/* == R95 (2026-09-26): doc pages - FAQ accordions, one-click mail copy, keyboard table == */
body.page-doc .doc details{background:#f7f9fe;border:1px solid #e2e8f6;border-radius:12px;padding:2px 18px;margin:10px 0}
body.page-doc .doc summary{font-weight:800;cursor:pointer;padding:13px 0;list-style:none;display:flex;align-items:center;gap:10px;color:#25304a}
body.page-doc .doc summary::-webkit-details-marker{display:none}
body.page-doc .doc summary::after{content:"+";margin-left:auto;font-size:20px;color:var(--brand);transition:.18s}
body.page-doc .doc details[open] summary::after{content:"-"}
body.page-doc .doc details p{margin:0 0 13px}
.mailcopy{border:1px dashed #b9c6ea;background:#eef3ff;color:var(--brand);font-weight:800;font-size:15px;border-radius:999px;padding:8px 18px;cursor:pointer;font-family:ui-monospace,Consolas,monospace;transition:.14s}
.mailcopy:hover{border-style:solid;background:#e3ebff}
.mailcopy:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.mailnote{margin-left:10px;font-weight:800;color:#1f7a6e}
.mailnote.bad{color:#b3423a}
body.page-doc kbd{display:inline-block;min-width:20px;text-align:center;background:#fff;border:1px solid #cdd7ee;border-bottom-width:2px;border-radius:6px;padding:1px 6px;font-family:ui-monospace,Consolas,monospace;font-size:12.5px;color:#39435a}
.kbd-table{width:100%;border-collapse:collapse;font-size:14.5px;margin-top:6px}
.kbd-table th,.kbd-table td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line-2)}
.kbd-table thead th{background:#f3f6fc;font-weight:800;color:#39435a}
.kbd-table tbody tr:last-child td{border-bottom:none}
@media(hover:none){.mailcopy{min-height:44px}}
/* == R98 (2026-09-27): footer copyright row - right-aligned free/private tagline == */
footer .cp{display:flex;align-items:center;justify-content:space-between;gap:6px 18px;flex-wrap:wrap}
/* R103: space-between + raw text nodes scattered the copyright into loose anonymous items —
   rows WITH a tail get exactly two flow units (cp-left + tail pinned right); rows without: plain inline flow */
footer .cp:has(> .cp-tail){justify-content:flex-start;align-items:baseline}
footer .cp:not(:has(> .cp-tail)){display:block}
footer .cp .cp-tail{margin-left:auto}
footer .cp .cp-tail{color:#9aa6c4;font-weight:700;letter-spacing:.2px}
@media(max-width:560px){footer .cp{justify-content:flex-start}footer .cp .cp-tail{margin-left:0}}
/* == R101 (2026-09-27): tool page top menu = same five entries as the rest of the site, but the bar spans the FULL viewport width == */
.page-tool .topbar .wrap{max-width:none;width:100%}
/* == R102 (2026-09-27): tool page docks the same copyright line under the workspace; shell shrinks so nothing overflows the first screen == */
.page-tool footer{margin-top:0;padding:14px 0 15px}
.page-tool footer .wrap{display:block}
.page-tool footer .cp{border-top:0;padding-top:0}
/* the shell-height compensation is DESKTOP-only: ≤900px uses height:auto page flow (lesson 97) */
@media(min-width:901px){.page-tool .tool-shell{height:calc(100vh - var(--topbar-h) - 50px);height:calc(100dvh - var(--topbar-h) - 50px)}}

/* == R104 (2026-09-27): doc pages show ONE language at a time (pairs marked .zh/.en) == */
html[lang="zh-CN"] .doc .en{display:none}
html[lang="en"] .doc .zh{display:none}

/* == R105 (2026-09-27): left pane has no sticky tab strip above its cards - the 54px pin offset (tuned for the inspector rtabspin band) left a blank card-white band over the upload card; pin it to 0 == */
#paneControls .card>h2{top:0}

/* == R106 (2026-09-27): toolbar actions share ONE monochrome symbol family (BMP text glyphs, no colour emoji) == */
.tb-actions .iconbtn{font-size:17px;font-weight:700;line-height:1;color:#4a5570;font-family:"Segoe UI Symbol","DejaVu Sans","Noto Sans Symbols2",system-ui,sans-serif}
.tb-actions .iconbtn:hover:not(:disabled){color:var(--brand)}
.tb-actions .iconbtn.on{color:#fff}
.tb-actions .iconbtn.on:hover:not(:disabled){color:#fff}
.tb-actions .iconbtn.danger{color:#b3423a}
.tb-actions .iconbtn.danger:hover:not(:disabled){border-color:#b3423a;color:#b3423a}
@media(max-width:400px){.tb-actions .iconbtn{font-size:15px}}

/* == R107 (2026-09-27): caption emoji row = six equal columns (fixed 34px flex tiles parked all slack on the right) == */
#capEmoji{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:6px}
#capEmoji .emoji{width:auto;height:40px;font-size:19px}

/* == R108 (2026-09-27): sticker upload slot = dashed brand-tinted add tile with a visible label == */
#annoStickers .st-up{border:1.5px dashed #9db4f0;background:linear-gradient(180deg,#f4f7ff,#eef3ff);color:var(--brand);font-weight:800;font-size:14px;font-family:inherit}
#annoStickers .st-up:hover{border-style:solid;border-color:var(--brand);background:#e7eeff;color:var(--brand)}

/* == R110 (2026-09-27): edit modal — sliders two per row, transparent WYSIWYG cell preview, crop cursors == */
#editBody{display:grid;grid-template-columns:1fr 1fr;gap:0 16px;align-items:start}
#editBody>*{grid-column:1/-1}
#editBody>.fld:not(.fld-inline):has(> label){grid-column:auto}
#editBody .cellstyle{display:flex;flex-direction:column;gap:7px;border:1px solid var(--line);border-radius:12px;padding:8px 9px 10px;background:linear-gradient(180deg,rgba(74,108,247,.05),rgba(124,91,214,.02) 55%,rgba(124,91,214,0))}
.modal .preview canvas{border-radius:0;box-shadow:none;background:none}
.cropcv{cursor:crosshair}
@media(max-width:720px){#editBody{grid-template-columns:1fr}}
/* R111: sr-only status chip must really collapse (later .status-chip padding used to out-specify .sr-only) */
#status.sr-only{padding:0;border:0;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);background:none;box-shadow:none;white-space:nowrap;position:absolute}
/* R114: free-canvas toolbar — monochrome family + docked below the canvas (never over it) */
#freeToolSlot{display:none}
body[data-mode="canvas"] #freeToolSlot{display:block}
#freeToolSlot .free-tools{position:relative;left:auto;right:auto;bottom:auto;transform:none;margin:10px auto 12px;width:max-content;max-width:calc(100% - 24px)}
.free-tools button{font-family:"Segoe UI Symbol","DejaVu Sans","Noto Sans Symbols2",system-ui,sans-serif;font-weight:700;font-size:16px;line-height:1;color:#4a5570;border:1px solid transparent}
.free-tools button.danger{color:#b3423a}
.free-tools button.txt{width:auto;padding:0 12px;font-family:inherit;font-size:12.5px;font-weight:800}
.free-tools button:hover,.free-tools button.on{background:var(--brand);border-color:var(--brand);color:#fff}
/* == R129 (2026-09-27): the edit modal side column pushed its 1fr grid track out to min-content (603px), overflowing the 860px shell so the 填充方式 chips were clipped. Grid/flex items default to min-width:auto — pin it to 0 and let the rows inside shrink & wrap == */
.modal .side{min-width:0}
#editBody,#editBody>*{min-width:0}
#editBody .fld-inline .seg{flex:0 1 auto;max-width:100%}
/* == R133 (2026-09-27): Safari<=17 needs the -webkit- prefix on the two rules that predate the token layer; the shortcuts table must scroll sideways on phones instead of squashing == */
.topbar{-webkit-backdrop-filter:blur(10px)}
.cell-tools button{-webkit-backdrop-filter:blur(2px)}
@media(max-width:560px){.kbd-table{display:block;overflow-x:auto;max-width:100%}}
/* == R136 (2026-09-27): project save/open moved under the export block — one equal-width button row == */
.projrow{display:flex;gap:8px;margin-top:8px}
.projrow .mini{flex:1;text-align:center;padding:10px 6px}
