/* Vision Board 2027 — digital kit. Phone-first; the board is the product. */

@font-face{font-family:Anton;src:url(fonts/Anton-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:"Archivo Black";src:url(fonts/ArchivoBlack-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:Archivo;src:url(fonts/Archivo-Regular.ttf)format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:Archivo;src:url(fonts/Archivo-Medium.ttf)format("truetype");font-weight:500;font-display:swap}
@font-face{font-family:Cinzel;src:url(fonts/Cinzel-Regular.ttf)format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:Cinzel;src:url(fonts/Cinzel-Bold.ttf)format("truetype");font-weight:700;font-display:swap}
@font-face{font-family:"Cormorant Garamond";src:url(fonts/CormorantGaramond-Regular.ttf)format("truetype");font-style:normal;font-display:swap}
@font-face{font-family:"Cormorant Garamond";src:url(fonts/CormorantGaramond-Italic.ttf)format("truetype");font-style:italic;font-display:swap}
@font-face{font-family:Inter;src:url(fonts/Inter-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:"IBM Plex Mono";src:url(fonts/IBMPlexMono-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:Jost;src:url(fonts/Jost-Regular.ttf)format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:Jost;src:url(fonts/Jost-Medium.ttf)format("truetype");font-weight:500;font-display:swap}
@font-face{font-family:"Playfair Display";src:url(fonts/PlayfairDisplay-Regular.ttf)format("truetype");font-style:normal;font-display:swap}
@font-face{font-family:"Playfair Display";src:url(fonts/PlayfairDisplay-Italic.ttf)format("truetype");font-style:italic;font-display:swap}
@font-face{font-family:Caveat;src:url(fonts/Caveat-Bold.ttf)format("truetype");font-display:swap}
@font-face{font-family:Parisienne;src:url(fonts/Parisienne-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:Yellowtail;src:url(fonts/Yellowtail-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:Arimo;src:url("fonts/Arimo[wght].ttf")format("truetype-variations");font-weight:400 700;font-display:swap}
@font-face{font-family:Tinos;src:url(fonts/Tinos-Regular.ttf)format("truetype");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:Tinos;src:url(fonts/Tinos-Bold.ttf)format("truetype");font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:Tinos;src:url(fonts/Tinos-Italic.ttf)format("truetype");font-weight:400;font-style:italic;font-display:swap}
@font-face{font-family:Cousine;src:url(fonts/Cousine-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:Montserrat;src:url("fonts/Montserrat[wght].ttf")format("truetype-variations");font-weight:100 900;font-display:swap}
@font-face{font-family:Oswald;src:url("fonts/Oswald[wght].ttf")format("truetype-variations");font-weight:200 700;font-display:swap}
@font-face{font-family:Lora;src:url("fonts/Lora[wght].ttf")format("truetype-variations");font-weight:400 700;font-display:swap}
@font-face{font-family:"Space Grotesk";src:url("fonts/SpaceGrotesk[wght].ttf")format("truetype-variations");font-weight:300 700;font-display:swap}
@font-face{font-family:"Dancing Script";src:url("fonts/DancingScript[wght].ttf")format("truetype-variations");font-weight:400 700;font-display:swap}
@font-face{font-family:"Bebas Neue";src:url(fonts/BebasNeue-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:Pacifico;src:url(fonts/Pacifico-Regular.ttf)format("truetype");font-display:swap}
@font-face{font-family:"Noto Sans Symbols 2";src:url(fonts/NotoSansSymbols2-Regular.ttf)format("truetype");font-display:swap}

:root{
  --ink:#22262B;--navy:#1C3A5E;--gold:#A9884E;--paper:#FBF8F3;
  --line:#DED8CD;--muted:#7C7568;--bar:60px;--safe-b:env(safe-area-inset-bottom,0px);
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{font:16px/1.5 ui-sans-serif,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  color:var(--ink);background:var(--paper);overscroll-behavior:none}
button{font:inherit;cursor:pointer}
/* display on a class beats the hidden attribute; without this, panels leak */
[hidden]{display:none!important}
.screen{min-height:100dvh}

input,select{font:inherit;padding:10px 12px;border:1px solid var(--line);
  border-radius:9px;background:#fff;color:inherit;max-width:100%}
input:focus-visible,button:focus-visible,select:focus-visible{outline:2px solid var(--navy);outline-offset:2px}
label{display:block;font-weight:600;font-size:13px;margin:14px 0 6px}
.row{display:flex;gap:8px;align-items:center}
.row.tight{gap:6px;margin-bottom:6px}
.row.end{justify-content:flex-end;margin-top:22px}
.row>input,.row>select{flex:1;min-width:0}
.btn{background:#fff;border:1px solid var(--line);border-radius:9px;padding:9px 13px;
  font-size:14px;font-weight:600;color:var(--ink);white-space:nowrap}
.btn:hover{border-color:#BDB4A5}
.btn.primary{background:var(--navy);border-color:var(--navy);color:#fff}
.btn.lg{padding:12px 20px}
.btn.sq{padding:8px 10px;min-width:38px}
.btn.danger{color:#B3261E;border-color:#E7C9C5}
.btn[aria-pressed=true]{background:#EEF2F6;border-color:var(--navy);color:var(--navy)}
.err{color:#B3261E;font-size:14px;margin-top:8px}
.ok{color:#2F6B52;font-size:14px;margin-top:8px}
.fine{color:var(--muted);font-size:12.5px;margin-top:12px}
.linkish{background:none;border:0;color:var(--navy);text-decoration:underline;margin-top:16px;font-size:14px}

/* ───────────── gate + setup cards ───────────── */
.gate{display:grid;place-items:center;padding:24px 16px calc(24px + var(--safe-b));
  background:radial-gradient(1200px 600px at 20% -10%,#EAF0F4 0,transparent 60%),
             radial-gradient(900px 500px at 100% 110%,#F3E9DE 0,transparent 60%),var(--paper)}
.card{width:min(680px,100%);background:#fff;border:1px solid var(--line);border-radius:18px;
  padding:30px 26px calc(30px + var(--safe-b));box-shadow:0 18px 50px rgba(28,58,94,.10)}
.card.narrow{width:min(560px,100%)}
.kicker{font-weight:700;letter-spacing:.34em;color:var(--gold);font-size:13px}
h1{font-size:clamp(24px,5vw,32px);line-height:1.15;margin:.35em 0 .5em;color:var(--navy)}
.lede{color:#4C525A}
.pills{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin:18px 0 4px}
.pills li{background:#F4F1EA;border:1px solid var(--line);border-radius:999px;padding:6px 12px;font-size:13.5px}
.pills b{color:var(--navy)}

.presets{display:flex;flex-wrap:wrap;gap:6px}
.preset{border:1px solid var(--line);background:#fff;border-radius:9px;padding:7px 11px;
  font-size:13px;font-weight:600;color:var(--muted)}
.preset[aria-pressed=true]{background:var(--navy);border-color:var(--navy);color:#fff}
.dims{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
.dims.two{grid-template-columns:repeat(2,1fr)}
.dims input,.dims select{width:100%}
.orient{display:flex;align-items:center;gap:8px;margin-top:16px;flex-wrap:wrap}
.pxout{color:var(--muted);font-size:13px;font-family:"IBM Plex Mono",monospace}

/* ───────────── setup ───────────── */
.setup{display:flex;flex-direction:column;height:100dvh;background:var(--paper)}
.setup-wrap{flex:1;min-height:0;overflow:auto;max-width:1100px;width:100%;margin:0 auto;
  padding:20px 18px calc(40px + var(--safe-b))}
.setup-head label{margin-top:0}
.opt{font-weight:500;color:var(--muted);text-transform:none;letter-spacing:0}
.groups{display:flex;gap:8px;overflow-x:auto;margin:22px 0 16px;scrollbar-width:none}
.groups::-webkit-scrollbar{display:none}
.group{flex:none;border:1px solid var(--line);background:#fff;border-radius:999px;
  padding:8px 16px;font-size:14px;font-weight:600;color:var(--muted)}
.group[aria-pressed=true]{background:var(--navy);border-color:var(--navy);color:#fff}
.preset-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:14px}
.pcard{border:1px solid var(--line);background:#fff;border-radius:14px;padding:14px 12px 12px;
  text-align:center;display:flex;flex-direction:column;align-items:center;gap:10px}
.pcard:hover{border-color:#BDB4A5}
.pcard[aria-pressed=true]{border-color:var(--navy);box-shadow:0 0 0 2px rgba(28,58,94,.16)}
.pshape{width:100%;height:96px;display:grid;place-items:center}
.pshape i{display:block;border-radius:3px;border:1px solid #DDD6C9;
  background:#EFEADF no-repeat center/34% url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23B4AC9C'%3E%3Cpath d='M3 5h18v14H3zm2.4 11.6h13.2l-4.1-5.6-3.1 4-2.2-2.7z'/%3E%3Ccircle cx='8.2' cy='9' r='1.7'/%3E%3C/svg%3E");
  box-shadow:0 3px 9px rgba(0,0,0,.12)}
.pcard[aria-pressed=true] .pshape i{border-color:var(--navy);
  box-shadow:0 0 0 2px rgba(28,58,94,.22),0 3px 9px rgba(0,0,0,.12)}
.pname{font-size:13.5px;font-weight:600;line-height:1.25}
.psize{font-size:11.5px;color:var(--muted);font-family:"IBM Plex Mono",monospace}
.pcard.custom .pshape i{background:none;border:2px dashed #B9B1A3;width:54px;height:66px}
.custom-panel{margin-top:18px;border:1px solid var(--line);background:#fff;
  border-radius:14px;padding:16px 16px 20px}

/* ───────────── gallery ───────────── */
.gal-wrap{max-width:1100px;margin:0 auto;padding:26px 18px calc(40px + var(--safe-b))}
.gal-title{font-size:22px;color:var(--navy);margin-bottom:14px}
.gal-filter{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:18px}
.gal-filter input{flex:1;min-width:180px}
.chips{display:flex;gap:6px;flex-wrap:wrap}
.chip{border:1px solid var(--line);background:#fff;border-radius:999px;padding:6px 13px;
  font-size:13px;font-weight:600;color:var(--muted)}
.chip[aria-pressed=true]{background:var(--navy);border-color:var(--navy);color:#fff}
.gal-cat{display:inline-block;font-size:11px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--gold);margin-bottom:2px}
.gal-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:16px}
.gal-card{border:1px solid var(--line);border-radius:14px;background:#fff;overflow:hidden;
  display:flex;flex-direction:column;text-align:left}
.gal-thumb{aspect-ratio:4/3;background:#EFE9DE;display:block;width:100%;object-fit:cover;
  border:0;padding:0;cursor:pointer}
.gal-body{padding:11px 12px;display:flex;align-items:center;gap:8px}
.gal-name{font-weight:600;font-size:14.5px;flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.gal-sub{color:var(--muted);font-size:12px;font-family:"IBM Plex Mono",monospace}
.icon-btn{border:0;background:none;color:var(--muted);padding:4px 6px;border-radius:6px}
.icon-btn:hover{background:#F2EEE7;color:#B3261E}
.empty-note{color:var(--muted);margin-top:14px}

/* ───────────── editor chrome ───────────── */
#app{height:100dvh;display:flex;flex-direction:column}
.bar{height:var(--bar);flex:none;display:flex;align-items:center;gap:10px;
  padding:0 12px;border-bottom:1px solid var(--line);background:#fff}
.brand{font-weight:800;color:var(--navy);white-space:nowrap;
  display:inline-flex;align-items:center;gap:8px}
.brand img{flex:none}
/* The word lives in one wrapper. A bare text node beside <span>form</span>
   becomes its own anonymous flex item, so the 8px gap meant to separate the
   mark from the name opened up inside it: "Vision form". */
.brand .wm{display:inline}
/* Same gold as the public pages. The old --gold (#A9884E) sat at 3.3:1,
   which is under AA for text this size. */
.brand span{color:#A2660F}
.name-input{border:1px solid transparent;background:none;font-weight:700;
  color:var(--navy);padding:7px 9px;min-width:110px;flex:1 1 260px;max-width:340px;
  text-overflow:ellipsis}
.name-input:focus{border-color:var(--navy);background:#fff}
.name-input.cat{font-weight:600;color:var(--gold);font-size:13px;flex:0 1 150px}
.name-input:hover{border-color:var(--line)}
.tools{margin-left:auto;display:flex;align-items:center;gap:8px}
.sel{display:flex;align-items:center;gap:6px;font-size:13px;margin:0}
.sel span{color:var(--muted);font-weight:600}
.sel select{padding:8px 10px}

.workspace{flex:1;min-height:0;display:flex}
.library{width:320px;flex:none;display:flex;flex-direction:column;
  border-right:1px solid var(--line);background:#fff;min-height:0}
.lib-head{padding:10px 10px 8px;border-bottom:1px solid var(--line)}
.lib-head select{padding:8px 9px;font-size:13.5px}
.lib-grid{flex:1;min-height:0;overflow:auto;display:grid;align-content:start;
  grid-template-columns:repeat(auto-fill,minmax(90px,1fr));gap:8px;padding:10px}
.lib-item{border:1px solid var(--line);border-radius:10px;background:#FCFAF6;padding:5px;
  height:90px;display:flex;align-items:center;justify-content:center;overflow:hidden;cursor:grab}
.lib-item img{width:100%;height:100%;object-fit:contain;pointer-events:none}
.lib-item:active{transform:scale(.97)}

/* uploads: tick-to-select, delete from the bar at the foot of the panel */
.up-tile{position:relative}
.up-pick{position:absolute;top:3px;right:3px;width:20px;height:20px;padding:0;
  border:1.5px solid var(--line);border-radius:50%;background:rgba(255,255,255,.92);
  display:grid;place-items:center;cursor:pointer;opacity:0;transition:opacity .12s}
.up-tile:hover .up-pick,.up-pick:focus-visible,.up-tile.picked .up-pick{opacity:1}
.up-pick svg{width:12px;height:12px;fill:none;stroke:var(--line);stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round}
.up-tile.picked .up-pick{background:var(--navy);border-color:var(--navy)}
.up-tile.picked .up-pick svg{stroke:#fff}
.up-tile.picked{outline:2px solid var(--navy);outline-offset:-1px;cursor:pointer}
.up-bar{flex:none;display:flex;align-items:center;gap:8px;padding:9px 10px;
  border-top:1px solid var(--line);background:#FCFAF6}
.up-bar #upSelCount{flex:1;font-size:13px;color:var(--muted)}
.btn.danger{background:#B4402F;border-color:#B4402F;color:#fff;display:inline-flex;
  align-items:center;gap:6px}
.btn.danger:hover{background:#9C3527;border-color:#9C3527}
.ico-trash{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}

.stage-wrap{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:8px;padding:16px;
  background:repeating-conic-gradient(#F2EEE7 0 25%,#F7F4EE 0 50%) 0 0/22px 22px}
.stage{position:relative;border-radius:10px;overflow:hidden;touch-action:none;
  box-shadow:0 14px 40px rgba(0,0,0,.14);background:#fff}
.stage[data-bg=cork]{background:#C9A06A url(assets/cork.svg)}
.stage[data-bg=linen]{background:#EFE9DE}
.stage[data-bg=white]{background:#fff}
.stage[data-bg=ink]{background:#14171A}
.stage[data-bg=sage]{background:#DCE5D8}
.stage[data-bg=blush]{background:#F3E3DC}
.stage-meta{font-family:"IBM Plex Mono",monospace;font-size:11.5px;color:var(--muted)}
.empty{position:absolute;inset:0;display:grid;place-content:center;gap:6px;
  text-align:center;color:#6B6355;pointer-events:none;padding:20px}
.empty strong{font-size:17px}
.stage.has-items .empty{display:none}

/* ───────────── elements ───────────── */
.el{position:absolute;transform-origin:center;cursor:grab;user-select:none;touch-action:none}
.el img{display:block;width:100%;height:100%;pointer-events:none;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.22))}
.el.img svg{display:block;width:100%;height:100%;overflow:visible;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.22))}
.el.txt{display:flex;align-items:center;justify-content:center;text-align:center;
  padding:2px 4px;line-height:1.12;white-space:pre-wrap;word-break:break-word}
.el.txt[data-outline="1"]{-webkit-text-stroke:.2em #fff;paint-order:stroke fill;
  filter:drop-shadow(0 2px 4px rgba(0,0,0,.25))}
.el.sel{outline:1.5px solid var(--navy);outline-offset:3px}
.el[contenteditable=true]{cursor:text;outline:2px solid var(--navy);user-select:text}

/* handles on all four corners, so the board can be resized from whichever
   side is reachable — on a phone the far corner often is not */
.h{position:absolute;width:16px;height:16px;border-radius:50%;background:#fff;
  border:2px solid var(--navy);box-shadow:0 1px 4px rgba(0,0,0,.3);touch-action:none;z-index:2}
.h[data-c=nw]{left:-9px;top:-9px;cursor:nwse-resize}
.h[data-c=ne]{right:-9px;top:-9px;cursor:nesw-resize}
.h[data-c=sw]{left:-9px;bottom:-9px;cursor:nesw-resize}
.h[data-c=se]{right:-9px;bottom:-9px;cursor:nwse-resize}
/* Rotate sits OUTSIDE the top-left corner and delete outside the top-right,
   the way Photoshop and Canva place them — far enough out that neither ever
   fights the corner resize handles. */
.h[data-c=rot]{left:-30px;top:-30px;width:22px;height:22px;background:var(--navy);
  border-color:#fff;cursor:grab;display:flex;align-items:center;justify-content:center}
.h[data-c=rot]::after{content:"⟳";color:#fff;font-size:13px;line-height:1;font-weight:700}
.h[data-c=rot]:active{cursor:grabbing}
.h[data-c=del]{right:-30px;top:-30px;width:22px;height:22px;background:#B3261E;
  border-color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center}
.h[data-c=del]::after{content:"🗑";font-size:11px;line-height:1;filter:grayscale(1) brightness(3)}
.h[data-c=del]:hover{background:#8F1D18}
.el:not(.sel) .h{display:none}

/* A 16px dot is a fine mouse target and a poor thumb one — the usual floor is
   44px. Grow the touch area with a transparent pseudo-element rather than the
   dot itself, so the handles stay small enough not to cover the artwork. This
   bit hardest with frames: a heart leaves its bounding-box corners empty, so
   the obvious place to grab is the art, which reads as a move. Must sit after
   the rot/del rules above — same specificity, so source order decides. */
@media (pointer:coarse){
  .h{width:20px;height:20px}
  /* Square, not round: a thumb comes at a corner handle diagonally, which is
     exactly where a circular halo has the least reach. */
  .h[data-c=nw]::before,.h[data-c=ne]::before,
  .h[data-c=sw]::before,.h[data-c=se]::before{
    content:"";position:absolute;inset:-12px}
  /* Only the corners get the halo. At 26px wide, rotate at -30px would centre
     on -17 — exactly the edge of that halo — so push both further out. */
  .h[data-c=rot],.h[data-c=del]{width:26px;height:26px;top:-36px}
  .h[data-c=rot]{left:-36px}
  .h[data-c=del]{right:-36px}
}

.selbar{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(12px + var(--safe-b));
  display:flex;gap:12px;align-items:stretch;background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:7px 9px;box-shadow:0 10px 28px rgba(0,0,0,.18);z-index:30;
  max-width:calc(100vw - 20px);overflow-x:auto}
.grp{display:flex;gap:8px;align-items:flex-end;padding-right:10px;
  border-right:1px solid var(--line)}
.grp:last-child{border-right:0;padding-right:0}
.grp-label{font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);align-self:center;writing-mode:vertical-rl;transform:rotate(180deg);
  padding:2px 0}
.fld{display:flex;flex-direction:column;gap:3px;margin:0}
.fld>span{font-size:10.5px;font-weight:600;color:var(--muted);letter-spacing:.02em}
.fld>span b{color:var(--navy);font-weight:700}
.btnrow{display:flex;gap:4px}
.grp select{padding:7px 8px;font-size:13px;max-width:130px}
.grp input[type=number]{width:62px;padding:7px 8px}
.grp input[type=color]{width:34px;height:34px;padding:2px;border-radius:8px}
.grp input[type=range]{width:86px}
.swatch{display:flex;align-items:center;gap:4px}
.nonebtn{font-size:15px;line-height:1;padding:8px;min-width:34px}
/* the swatch stays visible under "none" — it's the colour you come back to */
.fld.is-none input[type=color]{opacity:.3}
.mini{display:flex;align-items:center;gap:4px;margin:0;font-size:11.5px;color:var(--muted)}
.shape-pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(58px,1fr));gap:6px;
  padding:10px;border-bottom:1px solid var(--line);background:#FCFAF6}
.shape-pick button{border:1px solid var(--line);background:#fff;border-radius:9px;
  padding:6px;height:52px;display:grid;place-items:center}
.shape-pick svg{width:26px;height:26px;fill:var(--navy)}
.pick-group{grid-column:1/-1;margin:4px 0 0;font-size:10px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--gold)}
.pick-group:first-child{margin-top:0}
.el.shape svg{width:100%;height:100%;display:block;overflow:visible}

/* toast */
.toast{position:fixed;left:50%;bottom:calc(78px + var(--safe-b));transform:translateX(-50%);
  background:var(--navy);color:#fff;padding:10px 16px;border-radius:10px;font-size:14px;
  z-index:50;box-shadow:0 8px 24px rgba(0,0,0,.25)}

/* ───────────── phone ───────────── */
@media (max-width:820px){
  .workspace{flex-direction:column-reverse}
  .library{width:100%;height:40dvh;border-right:0;border-top:1px solid var(--line)}
  .stage-wrap{padding:10px}
  .lib-grid{grid-template-columns:repeat(auto-fill,minmax(76px,1fr))}
  .lib-item{height:76px}
  .dims{grid-template-columns:repeat(2,1fr)}
  .bar{gap:6px;padding:0 8px}
  .tools .sel{display:none}
  .btn{padding:9px 11px;font-size:13px}
  .name-input{flex:1 1 auto}
}

/* ───────────── print ───────────── */
@media print{
  @page{margin:.35in}
  .bar,.library,.selbar,.empty,.stage-meta,.toast{display:none!important}
  body,#app{height:auto;background:#fff}
  .workspace{display:block}
  .stage-wrap{padding:0;background:none;display:block}
  .stage{width:100%!important;height:auto!important;aspect-ratio:var(--ar);
    box-shadow:none;border-radius:0;break-inside:avoid;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
  .el.sel{outline:none}
  .h{display:none!important}
}

/* ════════════════════ editor shell: rail, panels, rulers ════════════════ */
.workspace{flex:1;min-height:0;display:flex}

.rail{width:74px;flex:none;background:#fff;border-right:1px solid var(--line);
  display:flex;flex-direction:column;gap:2px;padding:8px 6px;overflow-y:auto}
.rail-btn{border:0;background:none;border-radius:10px;padding:9px 4px;display:flex;
  flex-direction:column;align-items:center;gap:4px;font-size:10.5px;font-weight:600;
  color:var(--muted);line-height:1.1}
.rail-btn .ri{font-size:18px;line-height:1}
.rail-btn:hover{background:#F4F1EA}
.rail-btn[aria-pressed=true]{background:#EEF2F6;color:var(--navy)}
.rail-btn.create{background:var(--navy);color:#fff;margin-bottom:8px}
.rail-btn.create:hover{background:#16304F}

.panel-wrap{width:300px;flex:none;background:#fff;border-right:1px solid var(--line);
  display:flex;flex-direction:column;min-height:0}
.panel{flex:1;min-height:0;display:flex;flex-direction:column}
.panel-head{padding:10px;border-bottom:1px solid var(--line)}
.panel-head h3{font-size:14px;color:var(--navy)}
.describe{position:relative;margin-bottom:8px}
.describe .mag{position:absolute;left:11px;top:50%;transform:translateY(-50%);
  color:var(--muted);font-size:15px}
.describe input{width:100%;padding-left:31px}
.subtabs{display:flex;gap:5px;overflow-x:auto;margin-bottom:7px;scrollbar-width:none}
.subtabs::-webkit-scrollbar{display:none}
.subtab{flex:none;border:1px solid var(--line);background:#fff;border-radius:999px;
  padding:5px 11px;font-size:12.5px;font-weight:600;color:var(--muted)}
.subtab[aria-pressed=true]{background:var(--navy);border-color:var(--navy);color:#fff}
.lib-count{padding:8px 10px calc(8px + var(--safe-b));font-size:11.5px;color:var(--muted);
  border-top:1px solid var(--line);font-family:"IBM Plex Mono",monospace}
.stack{padding:10px;display:flex;flex-direction:column;gap:8px}
.stack .btn{width:100%;text-align:left}
.text-preset[data-font=Anton]{font-family:Anton;font-size:19px}
.text-preset[data-font=Jost]{font-family:Jost;font-weight:500;font-size:15px}
.hint{font-size:12px;color:var(--muted);margin-top:4px}
.drop{border:2px dashed var(--line);border-radius:12px;padding:20px 14px;text-align:center;
  display:flex;flex-direction:column;gap:5px;cursor:pointer;margin:0}
.drop:hover,.drop.over{border-color:var(--navy);background:#F6F9FC}
.drop strong{color:var(--navy);font-size:14px}
.drop span{font-size:12px;color:var(--muted);font-weight:400}
.proj{border:1px solid var(--line);border-radius:10px;padding:9px 11px;text-align:left;
  display:flex;flex-direction:column;gap:2px}
.proj b{font-size:13.5px}
.proj span{font-size:11.5px;color:var(--muted);font-family:"IBM Plex Mono",monospace}

/* ── canvas area with rulers ── */
.stage-outer{flex:1;min-width:0;position:relative;display:grid;
  grid-template-columns:22px 1fr;grid-template-rows:22px 1fr 34px;
  background:repeating-conic-gradient(#F2EEE7 0 25%,#F7F4EE 0 50%) 0 0/22px 22px}
.stage-outer.norulers{grid-template-columns:0 1fr;grid-template-rows:0 1fr 34px}
.ruler{background:#fff;border-color:var(--line);position:relative;overflow:hidden;
  font-family:"IBM Plex Mono",monospace;font-size:8px;color:var(--muted);user-select:none}
.ruler-h{grid-area:1/2;border-bottom:1px solid var(--line);cursor:ns-resize}
.ruler-v{grid-area:2/1;border-right:1px solid var(--line);cursor:ew-resize}
.ruler-corner{grid-area:1/1;background:#fff;border-right:1px solid var(--line);
  border-bottom:1px solid var(--line)}
.stage-outer.norulers .ruler,.stage-outer.norulers .ruler-corner{display:none}
.tick{position:absolute;background:#C9C2B4}
.ruler-h .tick{bottom:0;width:1px}
.ruler-v .tick{right:0;height:1px}
.tlab{position:absolute;color:#8C8676}
.ruler-h .tlab{top:1px;transform:translateX(2px)}
.ruler-v .tlab{left:1px;writing-mode:vertical-rl;transform:translateY(2px)}
.stage-wrap{grid-area:2/2;overflow:auto;display:grid;place-items:center;padding:14px}
.stage-foot{grid-area:3/1/4/3;display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding:0 12px;border-top:1px solid var(--line);background:#fff}
.zoomer{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);
  font-family:"IBM Plex Mono",monospace}

/* ── guides ── */
.guides{position:absolute;inset:0;pointer-events:none;z-index:9}
.guide{position:absolute;background:#12B5CB;pointer-events:auto}
/* gh/gv, not h/v — `.h` is the resize-handle class and was winning, which
   rendered every guide as a 9px dot instead of a line. */
.guide{width:auto;height:auto;border:0;box-shadow:none;border-radius:0}
.guide.gh{left:0;right:0;height:1.5px;cursor:ns-resize}
.guide.gv{top:0;bottom:0;width:1.5px;cursor:ew-resize}
.guide::after{content:"";position:absolute;inset:-4px}
.guide.drag{background:#F2545B}
.snapline{position:absolute;background:#F2545B;z-index:12;pointer-events:none}
.snapline.gh{left:0;right:0;height:1px}
.snapline.gv{top:0;bottom:0;width:1px}

/* ── docked toolbar ── */
.selbar.docked{position:static;transform:none;max-width:none;border-radius:0;
  border-left:0;border-right:0;border-bottom:0;box-shadow:none;flex:none;
  padding:8px 42px 8px 12px}
.selbar.floating{position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(14px + var(--safe-b));border-radius:12px;border:1px solid var(--line);
  box-shadow:0 10px 28px rgba(0,0,0,.2);max-width:calc(100vw - 20px);padding-right:42px}
.dockbtn{position:absolute;top:5px;right:7px;border:1px solid var(--line);background:#fff;
  border-radius:7px;width:26px;height:26px;font-size:12px;color:var(--muted);line-height:1}
.dockbtn:hover{border-color:var(--navy);color:var(--navy)}

@media (max-width:820px){
  .rail{width:100%;flex-direction:row;order:2;border-right:0;border-top:1px solid var(--line);
    overflow-x:auto;padding:6px}
  .rail-btn{flex:none;min-width:64px}
  .rail-btn.create{margin:0 6px 0 0}
  .workspace{flex-direction:column}
  .panel-wrap{width:100%;height:38dvh;order:3;border-right:0;border-top:1px solid var(--line)}
  .stage-outer{order:1;grid-template-columns:0 1fr;grid-template-rows:0 1fr 34px}
  .stage-outer .ruler,.stage-outer .ruler-corner{display:none}

  /* The bar can't hold brand + both names + units + five actions at phone
     widths, and the overflow was scrolling the whole page sideways. Drop what
     is redundant here (the rulers are hidden, so the unit picker is moot) and
     let the actions scroll inside the bar rather than the document. */
  .bar{padding:0 8px;gap:8px;min-width:0}
  .bar .brand{display:none}
  #rulerBtn,#unitFld{display:none}   /* rulers are hidden here, so both are moot */
  .name-input{flex:0 1 96px}
  .name-input.cat{display:none}   /* set at board setup; not worth the bar space */
  .tools{min-width:0;gap:6px;overflow-x:auto;scrollbar-width:none}
  .tools::-webkit-scrollbar{display:none}
  .tools>*{flex:none}
}
/* Nothing in the editor may scroll the document sideways. */
#app{overflow-x:hidden}
@media print{.rail,.panel-wrap,.ruler,.ruler-corner,.stage-foot{display:none!important}
  .stage-outer{display:block;background:none}}

/* ── save-as sheet ── */
.modal{position:fixed;inset:0;background:rgba(20,23,26,.45);display:grid;place-items:center;
  z-index:60;padding:18px}
.modal-card{width:min(460px,100%);background:#fff;border-radius:16px;padding:24px;
  box-shadow:0 24px 60px rgba(0,0,0,.3)}
.modal-card h3{font-size:19px;color:var(--navy);margin-bottom:6px}
.modal-card select{width:100%}
#bgCustom{width:34px;height:34px;padding:2px;border-radius:8px}
.stage[data-bg=custom]{background:#EFE9DE}

/* ── multi-select + right-click menu ── */
.multinote{position:absolute;top:7px;right:40px;font-size:11px;font-weight:700;
  color:var(--gold);letter-spacing:.06em;text-transform:uppercase}
.btn[disabled]{opacity:.35;pointer-events:none}
.ctx{position:fixed;z-index:70;background:#fff;border:1px solid var(--line);
  border-radius:12px;box-shadow:0 14px 40px rgba(0,0,0,.22);padding:8px;width:250px}
.ctx-sec{padding:6px;border-bottom:1px solid var(--line)}
.ctx-sec:last-child{border-bottom:0}
.ctx-sec .fld>span{font-size:10.5px}
.ctx-sec select,.ctx-sec input{width:100%}
.ctx-item{display:flex;justify-content:space-between;align-items:center;width:100%;
  border:0;background:none;text-align:left;padding:8px 8px;border-radius:7px;
  font-size:13.5px;font-weight:500}
.ctx-item:hover{background:#F4F1EA}
.ctx-item.danger{color:#B3261E}
.ctx-item kbd{font-family:"IBM Plex Mono",monospace;font-size:11px;color:var(--muted)}

/* ── icons: fill the button, not float in it ── */
.btn.sq{padding:7px;min-width:36px;height:36px;display:inline-flex;
  align-items:center;justify-content:center}
.btn.sq svg{width:20px;height:20px;fill:currentColor;display:block}
.btn.sq.tool svg{width:19px;height:19px}
.btn.danger svg{fill:#B3261E}
.toolsw{display:flex;gap:4px;padding-right:8px;border-right:1px solid var(--line)}
.tool[aria-pressed=true]{background:var(--navy);border-color:var(--navy);color:#fff}

/* ── menus ── */
.menu-wrap{position:relative}
.menu{position:absolute;top:calc(100% + 6px);right:0;z-index:65;background:#fff;
  border:1px solid var(--line);border-radius:12px;box-shadow:0 14px 40px rgba(0,0,0,.2);
  padding:6px;width:232px}
.menu-item{display:flex;align-items:center;gap:8px;width:100%;border:0;background:none;
  text-align:left;padding:8px 9px;border-radius:8px;font-size:13.5px;font-weight:500}
.menu-item:hover{background:#F4F1EA}
.menu-item .tick-on{width:14px;color:var(--navy);font-size:12px;visibility:hidden}
.menu-item[aria-checked=true] .tick-on{visibility:visible}
.menu-sep{height:1px;background:var(--line);margin:5px 2px}
.menu-row{display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:6px 9px;font-size:13px;color:var(--muted)}
.menu-row select{flex:0 0 88px;padding:6px 8px}

/* ── objects bar ── */
.objbar{grid-area:2/2;align-self:start;justify-self:center;margin-top:-6px;
  display:flex;align-items:center;gap:5px;background:#fff;border:1px solid var(--line);
  border-radius:11px;padding:5px 9px;box-shadow:0 6px 18px rgba(0,0,0,.12);
  position:relative;z-index:14}
.obj-label{font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);margin-right:3px}
.obj-sep{width:1px;height:22px;background:var(--line);margin:0 3px}
.obj-count{font-size:11px;color:var(--muted);font-family:"IBM Plex Mono",monospace;
  margin-left:4px}

/* ── handles: half the previous size ── */
.h{width:9px;height:9px;border-width:1.5px}
.h[data-c=nw]{left:-5px;top:-5px}
.h[data-c=ne]{right:-5px;top:-5px}
.h[data-c=sw]{left:-5px;bottom:-5px}
.h[data-c=se]{right:-5px;bottom:-5px}
.h[data-c=rot],.h[data-c=del]{width:20px;height:20px}
.h[data-c=rot]{left:-26px;top:-26px}
.h[data-c=del]{right:-26px;top:-26px}
.h[data-c=rot]::after,.h[data-c=del]::after{content:none}
.h svg{width:12px;height:12px;fill:#fff;display:block}

/* hand tool: whole board pans, nothing selectable */
.stage-wrap.panning{cursor:grab}
.stage-wrap.panning:active{cursor:grabbing}
.stage.panmode .el{pointer-events:none}

/* ── movable / dockable bars ── */
.bar-grip{cursor:grab;color:#B9B1A3;font-size:15px;letter-spacing:-2px;padding:0 4px;
  align-self:center;user-select:none;touch-action:none}
.bar-grip:active{cursor:grabbing}
.floatbar{transform:none!important;position:fixed!important;z-index:40;border-radius:12px;
  border:1px solid var(--line);box-shadow:0 12px 32px rgba(0,0,0,.22);background:#fff}
.dock-top{transform:none!important;position:fixed!important;top:var(--bar);border-radius:0;
  border-left:0;border-right:0;justify-content:safe center;overflow-x:auto}
.dock-bottom{transform:none!important;position:fixed!important;bottom:0;border-radius:0;
  border-left:0;border-right:0;justify-content:safe center;overflow-x:auto;
  padding-bottom:calc(8px + var(--safe-b))}
.dock-left{transform:none!important;position:fixed!important;left:0;right:auto;top:calc(var(--bar) + 8px);bottom:8px;
  flex-direction:column;align-items:flex-start;border-radius:0 12px 12px 0;overflow-y:auto;
  width:max-content;max-width:250px}
.dock-right{transform:none!important;position:fixed!important;right:0;left:auto;top:calc(var(--bar) + 8px);bottom:8px;
  flex-direction:column;align-items:flex-start;border-radius:12px 0 0 12px;overflow-y:auto;
  width:max-content;max-width:250px}
.dock-left .grp,.dock-right .grp{border-right:0;border-bottom:1px solid var(--line);
  padding:6px 0;width:100%}
.dock-left .grp-label,.dock-right .grp-label{writing-mode:horizontal-tb;transform:none}
.dropzone{position:fixed;background:rgba(28,58,94,.16);border:2px dashed var(--navy);
  z-index:39;pointer-events:none;border-radius:8px}

/* the properties bar is always present; it just says so when idle */
.selbar .idle{font-size:12.5px;color:var(--muted);padding:6px 4px}
.objbar{position:static;margin:0}

/* ── shape drawer: category rows ── */
.shape-pick{display:block;padding:8px 10px;overflow-y:auto;flex:1;min-height:0}
.cat-row{display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin:10px 2px 6px;font-size:12.5px}
.cat-row b{color:var(--navy)}
.cat-row .linkish{margin:0;font-size:12px}
.shape-row{display:flex;gap:6px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none}
.shape-row::-webkit-scrollbar{display:none}
.shape-row.wrap{flex-wrap:wrap;overflow:visible}
.shape-row button{flex:none;width:44px;height:44px;border:1px solid var(--line);
  background:#fff;border-radius:9px;display:grid;place-items:center;padding:5px}
.shape-row button:hover{border-color:var(--navy)}
.shape-row svg{width:100%;height:100%;fill:var(--ink)}

/* ── recently used ── */
.recent{padding:8px 10px;border-bottom:1px solid var(--line)}
.recent-head{display:flex;justify-content:space-between;align-items:center;
  font-size:12px;color:var(--muted);font-weight:600;margin-bottom:6px}
.recent-row{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none}
.recent-row::-webkit-scrollbar{display:none}
.recent-row .lib-item{flex:none;width:56px;height:56px}

/* ── grouped elements ── */
.el.grouped.sel{outline-color:#12B5CB}

/* ── page strip ── */
.pagestrip{grid-area:3/1/4/3;display:flex;align-items:center;gap:8px;padding:6px 10px;
  border-top:1px solid var(--line);background:#fff;overflow:hidden}
.pg-scroll{flex:1;min-width:0;display:flex;align-items:center;gap:8px;
  overflow-x:auto;scrollbar-width:thin;padding:2px 0}
.pg-scroll::-webkit-scrollbar{height:7px}
.pg-scroll::-webkit-scrollbar-thumb{background:#D8D1C4;border-radius:99px}
.pagestrip>.pg-add,.pagestrip>.pg-tools{flex:none}
.pagestrip::-webkit-scrollbar{display:none}
.stage-outer{grid-template-rows:22px 1fr 74px 34px;
  /* A docked bar is position:fixed, so it floats over the workspace and hid
     the page strip underneath it. Reserve its size instead of overlapping. */
  padding-bottom:var(--dock-b,0px);padding-top:var(--dock-t,0px);
  padding-left:var(--dock-l,0px);padding-right:var(--dock-r,0px)}
.stage-outer.norulers{grid-template-rows:0 1fr 74px 34px}
.stage-foot{grid-area:4/1/5/3}
.pg{flex:none;position:relative;width:60px;height:46px;border:1.5px solid var(--line);
  border-radius:7px;background:#F6F3EC center/cover no-repeat;cursor:pointer;padding:0}
.pg[aria-current=true]{border-color:var(--navy);box-shadow:0 0 0 2px rgba(28,58,94,.18)}
.pg .n{position:absolute;left:3px;bottom:2px;font-size:9px;font-weight:700;color:#fff;
  background:rgba(28,58,94,.75);border-radius:4px;padding:0 4px;font-family:"IBM Plex Mono",monospace}
.pg-add{flex:none;height:46px;border:1.5px dashed var(--line);border-radius:7px;
  background:#fff;padding:0 14px;font-size:13px;font-weight:600;color:var(--navy)}
.pg-add:hover{border-color:var(--navy)}
.pg-tools{display:flex;gap:5px;margin-left:auto}
.chk{display:flex;align-items:center;gap:8px;font-weight:500;margin:14px 0 0}
.chk input{width:auto}
@media print{.pagestrip{display:none!important}}

/* ── printing a multi-page board ── */
#printPages{display:none}
@media print{
  body.printing #app{display:none!important}
  body.printing #printPages{display:block}
  .printpage{display:block;width:100%;break-after:page;page-break-after:always}
  .printpage:last-child{break-after:auto;page-break-after:auto}
}

/* ── grid overlay ── */
.grid{position:absolute;inset:0;pointer-events:none;z-index:8}
.grid.on{background-image:
  linear-gradient(to right, rgba(28,58,94,.30) 1px, transparent 1px),
  linear-gradient(to bottom, rgba(28,58,94,.30) 1px, transparent 1px),
  linear-gradient(to right, rgba(28,58,94,.11) 1px, transparent 1px),
  linear-gradient(to bottom, rgba(28,58,94,.11) 1px, transparent 1px);}
.stage[data-bg=ink] .grid.on{background-image:
  linear-gradient(to right, rgba(255,255,255,.34) 1px, transparent 1px),
  linear-gradient(to bottom, rgba(255,255,255,.34) 1px, transparent 1px),
  linear-gradient(to right, rgba(255,255,255,.14) 1px, transparent 1px),
  linear-gradient(to bottom, rgba(255,255,255,.14) 1px, transparent 1px);}

/* ── text controls promoted into the top bar ── */
/* They were the most-reached-for tools yet lived in a bar at the far edge of
   the screen. In the header they sit where the eye already is, and the bottom
   bar stops fighting the page strip for the same 74px. */
.bar .topgrp{display:flex;align-items:center;gap:10px;padding:0 10px;margin-left:6px;
  border-left:1px solid var(--line);
  /* Hold size: the header is a flex row, and with min-width:0 the browser
     happily crushed this whole group to 22px. The board name gives way
     instead — a truncated name is readable, a 22px font picker is not. */
  flex:0 0 auto}
.bar .topgrp[hidden]{display:none}
.bar .topgrp .grp-label{display:none}
.bar .topgrp .fld{display:flex;align-items:center;gap:5px;margin:0}
.bar .topgrp .fld>span{font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);white-space:nowrap}
.bar .topgrp #fontSel{max-width:150px}
.bar .topgrp #sizeIn{width:58px}
.bar .topgrp #colorIn{width:30px;padding:2px}
.bar .topgrp .btnrow{display:flex;gap:3px}
@media (max-width:1100px){
  .bar .topgrp .fld>span{display:none}
  .bar .topgrp #fontSel{max-width:104px}
}

/* ── vertical docks: stack each group's controls so nothing is cut off ── */
.dock-left .fld,.dock-right .fld{flex-wrap:wrap}
.dock-left .idle,.dock-right .idle{white-space:normal;max-width:210px;line-height:1.45}
.dock-left .btnrow,.dock-right .btnrow{flex-wrap:wrap}
.dock-left select,.dock-right select,.dock-left input[type=number],.dock-right input[type=number]{
  max-width:190px}

/* Slower, quieter native tooltips are fine, but the icon-only tools deserve a
   visible affordance too — a hover ring so it is obvious they are buttons. */
.btn.sq:hover{border-color:var(--navy);background:#F4F7FB}

/* ── knockout ── */
/* The cutter stays on the board — you can still select and move it — but it
   must not paint over the hole it just made. */
.el.ko-cutter{opacity:0}
.el.ko-cutter.sel{opacity:.28}
.ko-canvas{display:block;width:100%;height:100%;pointer-events:none}
.obj-sep{width:1px;align-self:stretch;background:var(--line);margin:0 4px}

/* ── header property groups ── */
.bar .trashgrp{display:flex;align-items:center;padding-left:8px;margin-left:2px;
  border-left:1px solid var(--line)}
.bar .fld.topgrp{display:flex;align-items:center;gap:6px;margin:0 0 0 6px;
  padding-left:10px;border-left:1px solid var(--line);flex:0 0 auto}
.bar .fld.topgrp>span{font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);white-space:nowrap}
.bar .fld.topgrp input[type=range]{width:96px}

/* ── opacity slider ── */
/* A native range thumb is inset by half its own width at each end, so the
   accent-coloured fill stops short of the track and 100% reads as about 90%.
   Drawing the fill ourselves from the real value makes full mean full. */
input[type=range].fillbar{-webkit-appearance:none;appearance:none;height:22px;
  background:none;cursor:pointer}
input[type=range].fillbar::-webkit-slider-runnable-track{height:6px;border-radius:99px;
  background:linear-gradient(to right,var(--navy) var(--p,100%),#DDD6C9 var(--p,100%))}
input[type=range].fillbar::-moz-range-track{height:6px;border-radius:99px;
  background:linear-gradient(to right,var(--navy) var(--p,100%),#DDD6C9 var(--p,100%))}
input[type=range].fillbar::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  width:15px;height:15px;border-radius:50%;background:#fff;border:2px solid var(--navy);
  margin-top:-5px;box-shadow:0 1px 3px rgba(0,0,0,.25)}
input[type=range].fillbar::-moz-range-thumb{width:15px;height:15px;border-radius:50%;
  background:#fff;border:2px solid var(--navy);box-shadow:0 1px 3px rgba(0,0,0,.25)}

/* ── text effects panel ── */
.fx-head{font-weight:800;color:var(--navy);font-size:13px;margin:14px 10px 6px;
  display:flex;align-items:baseline;gap:8px}
.hint-inline{font-weight:500;font-size:11px;color:var(--muted)}
.fx-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:0 10px}
.fx-chip{display:flex;flex-direction:column;align-items:center;gap:6px;padding:10px 6px;
  border:1.5px solid var(--line);border-radius:11px;background:#fff;cursor:pointer;
  font-size:11.5px;font-weight:600;color:var(--muted)}
.fx-chip:hover{border-color:var(--navy)}
.fx-chip[aria-pressed=true]{border-color:var(--navy);background:#F4F7FB;color:var(--navy)}
/* Each swatch shows the effect itself — a named list told you nothing about
   what you were about to get. */
.fx-demo{font-family:Anton,system-ui;font-size:26px;line-height:1.1;color:var(--navy)}
.fx-d-shadow{text-shadow:2px 3px 4px rgba(0,0,0,.45)}
.fx-d-glow{text-shadow:0 0 5px #FFD873,0 0 11px #FFD873}
.fx-d-inner{color:#5E7BA6;text-shadow:0 1px 0 rgba(255,255,255,.85) inset;
  -webkit-text-stroke:.5px #24425F}
.fx-d-grad{background:linear-gradient(100deg,#A9884E,#F3E1B0 60%,#A9884E);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.fx-d-outline{-webkit-text-stroke:3px #fff;paint-order:stroke fill;color:var(--navy)}
.fx-opts{padding:10px;display:grid;gap:8px}
.fx-opts .fld{display:flex;align-items:center;justify-content:space-between;gap:8px;
  font-size:12px;color:var(--muted)}

/* ── text effects on the board ── */
.el.txt[data-grad="1"]{-webkit-background-clip:text;background-clip:text;
  color:transparent!important}

/* ── locked elements ── */
.el.locked{cursor:default}
.el.locked.sel{outline-style:dashed;outline-color:#8A8681}
.el.locked .h{display:none}          /* no resize handles on something locked */
.undogrp{display:flex;gap:3px;margin-left:4px}
.ctx-sep{height:1px;background:var(--line);margin:5px 0}

/* ── marquee selection ── */
.marquee{position:absolute;z-index:60;pointer-events:none;
  border:1.5px solid var(--navy);background:rgba(28,58,94,.10);border-radius:3px}
.stage[data-bg=ink] .marquee{border-color:#9FD4FF;background:rgba(159,212,255,.16)}

/* ── page setup ── */
.ps{padding:10px 12px 20px;display:grid;gap:10px}
.ps h4{margin:8px 0 0;font-size:12px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--muted)}
.ps-row{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.ps-row:has(select){grid-template-columns:1fr 1fr 1fr}
.ps .fld{display:grid;gap:3px;margin:0}
.ps .fld>span{font-size:11px;color:var(--muted);font-weight:600}
.ps .chk{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink)}
.ps-views{display:grid;gap:7px}
.pv{display:flex;align-items:center;gap:9px;padding:9px 11px;border:1.5px solid var(--line);
  border-radius:11px;background:#fff;cursor:pointer;font-size:12.5px;font-weight:600;
  color:var(--muted);text-align:left}
.pv:hover{border-color:var(--navy)}
.pv[aria-pressed=true]{border-color:var(--navy);background:#F4F7FB;color:var(--navy)}
.pv-art{display:flex;gap:1.5px}
.pv-art i{display:block;width:11px;height:15px;border:1.4px solid currentColor;border-radius:1.5px}
.pv-art.solo{margin-right:5px}

/* Margin guides are a drawing aid — dashed, never printed. */
.margins{position:absolute;inset:0;pointer-events:none;z-index:9;
  border:1px dashed rgba(180,98,60,.85)}
@media print{.margins{display:none!important}}

/* ── book / spread page strip ── */
.pg-spread{display:flex;gap:2px;padding:2px;border-radius:7px;background:#EFE9DD}
.pg-spread.solo{background:none;padding:2px 10px}

/* ── ruler unit menu ── */
.unitmenu{position:fixed;z-index:200;min-width:172px}
.menu-head{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);font-weight:700;padding:8px 12px 4px}
.unitmenu .menu-item[aria-checked=true]::after{content:'✓';margin-left:auto;color:var(--navy)}
.unitmenu .menu-item{display:flex;align-items:center}
.ruler{cursor:context-menu}

/* ── setup: document options ── */
.docopts{padding:14px 16px;border-top:1px solid var(--line);margin-top:6px}
.docopts h4{margin:0 0 10px;font-size:12px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--muted)}

/* ── resizable picture panel ── */
/* The grid is already auto-fill, so widening the panel adds columns on its
   own — the only thing missing was a way to widen it. */
.lib-resize{flex:none;width:7px;cursor:col-resize;background:transparent;
  border-right:1px solid var(--line);position:relative;z-index:20}
.lib-resize::after{content:'';position:absolute;left:2px;top:50%;transform:translateY(-50%);
  width:3px;height:34px;border-radius:2px;background:var(--line)}
.lib-resize:hover::after,.lib-resize.dragging::after{background:var(--navy)}
.lib-resize:focus-visible{outline:2px solid var(--navy);outline-offset:-2px}
body.lib-resizing{cursor:col-resize;user-select:none}
/* A one-column panel should still show a usable thumbnail, not a stamp. */
.panel-wrap.narrow .lib-grid{grid-template-columns:1fr}
.panel-wrap.narrow .lib-item{height:150px}
/* The picture grid should use whatever width it is given. */
.panel-wrap .lib-grid{grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}
@media (max-width:820px){ .lib-resize{display:none} }

/* ── effective-resolution readout ── */
.ctx-info{padding:8px 12px;margin-bottom:4px;border-bottom:1px solid var(--line);
  display:grid;gap:2px;max-width:280px}
.ctx-info b{font-size:12.5px}
.ctx-info span{font-size:11px;color:var(--muted)}
.ctx-info[data-level=good] b{color:#3F7A46}
.ctx-info[data-level=warn] b{color:#A9722E}
.ctx-info[data-level=bad] b{color:#B4423C}
.dpibadge{font-size:11px;font-weight:700;padding:4px 8px;border-radius:99px;
  white-space:nowrap;border:1px solid transparent}
.dpibadge[data-level=good]{color:#3F7A46;background:#EDF6EE;border-color:#CBE4CE}
.dpibadge[data-level=warn]{color:#A9722E;background:#FBF3E6;border-color:#EEDDBF}
.dpibadge[data-level=bad]{color:#B4423C;background:#FBEDEC;border-color:#EFCFCC}

/* ── bleed guide ── */
/* The page edge is the trim line; the bleed sits OUTSIDE it, which is the
   whole point — artwork has to run past the cut. Drawn as an outset frame so
   you can see how far to push a photo. */
.bleedline{position:absolute;pointer-events:none;z-index:8;
  border:1px dashed rgba(180,66,60,.9);border-radius:1px}
.bleed-tag{position:absolute;top:-8px;left:6px;font-size:9px;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;color:#B4423C;background:#fff;
  padding:0 4px;border-radius:3px;line-height:14px}
.stage{overflow:visible}
@media print{.bleedline{display:none!important}}

/* ── live DPI bubble ── */
/* Pinned to the element rather than parked in the toolbar: while you are
   dragging a corner your eyes are on the corner, not the header. */
.dpi-bubble{position:absolute;z-index:70;pointer-events:none;white-space:nowrap;
  font-size:11.5px;font-weight:800;padding:4px 9px;border-radius:99px;
  box-shadow:0 3px 10px rgba(0,0,0,.18);transform:translate(-50%,-140%)}
.dpi-bubble[data-level=good]{color:#255C2C;background:#DBF0DE;border:1px solid #A9D3AE}
.dpi-bubble[data-level=warn]{color:#7E5316;background:#FBEDD5;border:1px solid #E6C98D}
.dpi-bubble[data-level=bad]{color:#fff;background:#B4423C;border:1px solid #8E332E}

/* ── preflight ── */
.modal-card.wide{max-width:620px;width:min(620px,94vw)}
.flight-list{display:grid;gap:8px;max-height:46vh;overflow:auto;margin:10px 0}
.flight-row{display:grid;grid-template-columns:56px 1fr auto;gap:10px;align-items:center;
  padding:9px;border:1px solid var(--line);border-radius:11px;background:#FCFAF6}
.flight-row img{width:56px;height:46px;object-fit:cover;border-radius:7px;background:#EFE9DD}
.flight-row b{display:block;font-size:12.5px;color:#B4423C}
.flight-row span{display:block;font-size:11.5px;color:var(--muted)}
.outbox{display:block;padding:9px 10px;border:1px solid var(--line);border-radius:9px;
  background:#F7F4ED;font-size:13px;color:var(--ink)}

/* ── measurement inputs ── */
/* A bare 0.5 does not say what it is. The unit sits inside the field, the way
   every layout tool shows it, so the number is never ambiguous. */
.uin{position:relative;display:block}
.uin>input{width:100%;padding-right:26px}
.uin::after{content:attr(data-u);position:absolute;right:9px;top:50%;
  transform:translateY(-50%);font-size:11.5px;font-weight:700;color:var(--muted);
  pointer-events:none}
.uin[data-u=""]::after{content:none}

/* Page setup fields size to their content and wrap rather than overflowing a
   narrow panel — the panel is resizable now, so nothing may assume a width. */
.ps-row{display:flex;flex-wrap:wrap;gap:8px}
.ps-row:has(select){display:flex}
.ps .fld.sm{flex:1 1 92px;min-width:82px;max-width:150px}
.ps .fld:has(select){flex:1 1 108px;min-width:96px}
.ps .fld select,.ps .fld input{width:100%;min-width:0}
.ps .fld>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── projects list ── */
.proj{display:grid;grid-template-columns:64px 1fr;gap:10px;align-items:center;
  text-align:left;padding:8px;width:100%}
.proj-thumb{width:64px;height:52px;object-fit:cover;border-radius:8px;
  border:1px solid var(--line);background:#fff;display:block}
.proj-thumb.empty{display:flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:700;color:var(--muted);background:#F7F4ED}
.proj-meta{display:grid;gap:2px;min-width:0}
.proj-meta b{font-size:13px;color:var(--navy);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.proj-meta>span{font-size:11.5px;color:var(--muted)}

/* A docked bar spans the canvas area, so it must fill it rather than
   shrink-wrap and drift. */
.objbar.dock-top,.objbar.dock-bottom,.selbar.dock-top,.selbar.dock-bottom{
  width:auto;max-width:none}
.dock-top>*,.dock-bottom>*{flex:none}

/* ── elements hub & brand kit ── */
.el-scroll{flex:1;min-height:0;overflow-y:auto;padding-bottom:20px}
.el-sec{padding:12px 10px 4px}
.el-sec-head{display:flex;align-items:baseline;justify-content:space-between;
  margin:0 2px 8px;font-size:13px;font-weight:800;color:var(--navy)}
.tile-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}
.tile{border:0;background:none;padding:0;cursor:pointer;display:grid;gap:6px;
  justify-items:center;font-size:11.5px;font-weight:700;color:var(--ink)}
.tile img{width:100%;aspect-ratio:1;object-fit:contain;border-radius:12px;
  transition:transform .12s ease}
.tile:hover img{transform:translateY(-2px) scale(1.03)}
.swatch-row{display:flex;flex-wrap:wrap;gap:7px}
.bswatch{width:34px;height:34px;border-radius:9px;border:1.5px solid var(--line);
  cursor:pointer;position:relative;padding:0}
.bswatch .x{position:absolute;top:-6px;right:-6px;width:16px;height:16px;border-radius:50%;
  background:#fff;border:1px solid var(--line);font-size:10px;line-height:14px;color:#B4423C;
  display:none}
.bswatch:hover .x{display:block}
.tpl-social{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:9px;
  margin-bottom:10px}
.tpl-card{border:1px solid var(--line);border-radius:10px;background:#fff;padding:6px;
  cursor:pointer;display:grid;gap:5px;text-align:left}
.tpl-card:hover{border-color:var(--navy)}
.tpl-card .shot{width:100%;background:#F3EFE6;border-radius:6px;display:block;
  object-fit:cover;border:1px solid var(--line)}
.tpl-card b{font-size:11px;color:var(--navy);line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tpl-card span{font-size:10px;color:var(--muted)}

/* ── panel back link ── */
.panel-back{border:0;background:none;color:var(--navy);font-weight:700;font-size:12.5px;
  padding:9px 10px 4px;text-align:left;cursor:pointer;width:100%}
.panel-back:hover{text-decoration:underline}

/* ── background picker ── */
.bg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(78px,1fr));gap:8px}
.bg-tile{border:1.5px solid var(--line);border-radius:10px;height:56px;cursor:pointer;
  padding:0;position:relative;overflow:hidden}
.bg-tile[aria-pressed=true]{border-color:var(--navy);box-shadow:0 0 0 2px rgba(28,58,94,.18)}
.bg-tile span{position:absolute;left:0;right:0;bottom:0;font-size:10px;font-weight:700;
  background:rgba(255,255,255,.86);color:var(--ink);padding:2px 0}

/* ── grids ── */
.grid-pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(76px,1fr));gap:9px;padding:10px 12px 24px;
  overflow-y:auto;flex:1;min-height:0}
.grid-pick button{border:1.5px solid var(--line);border-radius:9px;background:#fff;padding:4px;
  cursor:pointer;aspect-ratio:1}
.grid-pick button:hover{border-color:var(--navy)}
.grid-pick svg{width:100%;height:100%;display:block}
.el.gridel{overflow:hidden}
.gcell{position:absolute;overflow:hidden;background:#EDE7DA;
  display:flex;align-items:center;justify-content:center}
.gcell img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none}
.gcell-empty::after{content:'+';font-size:22px;font-weight:800;color:#B9B1A2}
.gcell.over{outline:2.5px solid var(--navy);outline-offset:-2.5px;background:#DCE6F2}

/* ── rail icons ── */
/* .ri only ever set a font-size, and the inline SVGs carry no width or height,
   so every icon collapsed to nothing and the rail read as a list of words. */
.rail-btn .ri{display:block;width:22px;height:22px}
.rail-btn .ri svg{width:22px;height:22px;display:block;fill:currentColor}

/* ── application menu bar ── */
.appmark{border:0;background:none;padding:2px;cursor:pointer;display:flex;flex:none;
  border-radius:8px}
.appmark:hover{background:#F4F1EA}
.menubar{display:flex;gap:1px;flex:none}
.mb{border:0;background:none;padding:7px 10px;border-radius:8px;font-size:13.5px;
  font-weight:600;color:var(--ink);cursor:pointer}
.mb:hover{background:#F4F1EA}
.mb[aria-expanded=true]{background:#EEF2F6;color:var(--navy)}
.appmenu{position:fixed;z-index:210;min-width:264px;padding:6px}
.appmenu .menu-item{display:flex;align-items:center;gap:8px;width:100%}
.appmenu .menu-item kbd{margin-left:auto}
.appmenu .menu-item.danger{color:#B4423C}
.appmenu .menu-row{display:flex;justify-content:space-between;align-items:center;
  padding:6px 12px 2px;font-size:11.5px;font-weight:700;color:var(--muted)}
.appmenu input[type=range]{width:calc(100% - 24px);margin:2px 12px 6px}
.zoom-presets{display:grid;grid-template-columns:repeat(4,1fr);gap:4px;padding:0 8px 6px}
.zoom-presets button{border:1px solid var(--line);background:#fff;border-radius:7px;
  padding:5px 0;font-size:11.5px;font-weight:700;color:var(--ink);cursor:pointer}
.zoom-presets button:hover{border-color:var(--navy);color:var(--navy)}
.menu-item .tick-on{width:12px;opacity:0}
.menu-item[aria-checked=true] .tick-on{opacity:1}
#feedbackModal textarea{width:100%;font:inherit;padding:9px 10px;border:1px solid var(--line);
  border-radius:9px;resize:vertical}

/* ── header object tools ── */
.objgrp{display:flex;align-items:center;gap:4px;padding-left:8px;margin-left:4px;
  border-left:1px solid var(--line);flex:0 0 auto}
.objgrp .btn{padding:7px 9px;font-size:12.5px}
.ico-print svg{fill:#3F6C8E}
.ico-share svg{fill:#3F7A46}
.btn.sq.ico-print:hover,.btn.sq.ico-share:hover{background:#F1F5F9}

/* ── collapsing the page strip ── */
.strip-toggle{grid-area:3/1/4/3;justify-self:center;align-self:start;margin-top:-13px;
  width:44px;height:20px;border:1px solid var(--line);border-radius:0 0 9px 9px;
  background:#fff;cursor:pointer;font-size:11px;line-height:1;color:var(--muted);z-index:16;
  padding:0}
.strip-toggle:hover{color:var(--navy);border-color:var(--navy)}
.stage-outer.stripdown .pagestrip{display:none}
.stage-outer.stripdown{grid-template-rows:22px 1fr 0 34px}
.stage-outer.stripdown.norulers{grid-template-rows:0 1fr 0 34px}

/* ── collapsing the picture panel ── */
/* Anchored to the drag handle, so it is carried by the same layout that moves
   the panel edge. Positioning it from a JS pixel value made the handle's
   position a second source of truth, and the two drifted apart mid-drag. */
.panel-collapse{position:absolute;left:100%;top:50%;transform:translateY(-50%);
  z-index:22;width:18px;height:46px;border:1px solid var(--line);border-left:0;
  border-radius:0 8px 8px 0;background:#fff;cursor:pointer;color:var(--muted);
  font-size:13px;padding:0}
.panel-collapse:hover{color:var(--navy);border-color:var(--navy)}
/* With the panel hidden the handle stays — it is what the tab hangs off — but
   it collapses to nothing so only the tab shows. */
.workspace.panelhid .panel-wrap{display:none}
.workspace.panelhid .lib-resize{width:0;border-right:0;pointer-events:none}
.workspace.panelhid .lib-resize::after{display:none}
.workspace.panelhid .panel-collapse{pointer-events:auto}
.workspace{position:relative}

/* ── grid cell placeholder ── */
/* An empty frame shows a picture glyph rather than a bare box, so it reads as
   "a photo goes here" instead of "something failed to load". */
.gcell-empty{background:#E8E2D6}
.gcell-empty::after{content:'';position:absolute;inset:18%;
  background:no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23B4AC9C'%3E%3Cpath d='M3 5h18v14H3zm2.4 11.6h13.2l-4.1-5.6-3.1 4-2.2-2.7z'/%3E%3Ccircle cx='8.2' cy='9' r='1.7'/%3E%3C/svg%3E");
  opacity:.85}

/* ── shared "artwork goes here" placeholder ── */
/* One glyph for an empty grid cell and an unstarted template, so the two read
   as the same idea rather than two unrelated grey boxes. */
.shot.ph{background:#E8E2D6 no-repeat center/38% url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23B4AC9C'%3E%3Cpath d='M3 5h18v14H3zm2.4 11.6h13.2l-4.1-5.6-3.1 4-2.2-2.7z'/%3E%3Ccircle cx='8.2' cy='9' r='1.7'/%3E%3C/svg%3E")}
.frame-secs{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column}
.frame-secs .grid-pick{flex:0 0 auto;overflow:visible}

/* ── rotation readout ── */
/* Pinned above the element being turned, because that is where the eyes are —
   the same reasoning as the DPI bubble. */
.rot-bubble{position:absolute;z-index:72;pointer-events:none;white-space:nowrap;
  font-size:11.5px;font-weight:800;padding:4px 9px;border-radius:99px;
  background:var(--navy);color:#fff;box-shadow:0 3px 10px rgba(0,0,0,.22);
  transform:translate(-50%,-165%);font-variant-numeric:tabular-nums}
.rot-bubble.snap{background:#3F7A46}
.modal-card.narrow{max-width:320px}
.rot-presets{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin:10px 0 4px}
.rot-presets button{border:1px solid var(--line);background:#fff;border-radius:8px;
  padding:7px 0;font-size:12.5px;font-weight:700;color:var(--ink);cursor:pointer}
.rot-presets button:hover{border-color:var(--navy);color:var(--navy)}
.h[data-c=rot]{cursor:grab}

/* The pointer/hand switch sits at the left end of the bar, next to the menus —
   it is a mode for the whole canvas, not a property of a selection. */
.toolsw{display:flex;gap:3px;flex:0 0 auto;padding-left:8px;margin-left:4px;
  border-left:1px solid var(--line)}

/* A header that runs out of room must scroll, not clip. Everything in it is a
   control, and a control you cannot reach is a control you do not have. */
#app .bar{overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}
#app .bar::-webkit-scrollbar{height:6px}
#app .bar::-webkit-scrollbar-thumb{background:#D8D1C4;border-radius:99px}
#app .bar>*{flex-shrink:0}
#app .bar .name-input{flex:1 1 220px;min-width:130px;max-width:320px}
.objgrp .btn.sq{padding:6px}
.objgrp .btn.sq svg{width:18px;height:18px}

/* ── background removal ── */
/* A cutout takes a few seconds on a server; the element says so rather than
   sitting there looking broken. */
.el.working{position:relative}
.el.working::after{content:'';position:absolute;inset:0;border-radius:inherit;
  background:rgba(255,255,255,.55);
  background-image:repeating-linear-gradient(45deg,transparent 0 10px,rgba(28,58,94,.14) 10px 20px);
  animation:workpulse 1.1s linear infinite}
@keyframes workpulse{to{background-position:28px 0}}
#rmbgBtn{white-space:nowrap}

/* ── font picker ── */
.fontpick{position:relative;display:block}
#fontPick{width:100%;min-width:132px;max-width:170px;text-align:left;padding:8px 22px 8px 10px;
  border:1px solid var(--line);border-radius:9px;background:#fff;cursor:pointer;
  font-size:14px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#fontPick::after{content:'▾';position:absolute;right:8px;top:50%;transform:translateY(-50%);
  font-size:10px;color:var(--muted)}
#fontPick:hover{border-color:var(--navy)}
.fontmenu{position:fixed;z-index:220;width:270px;max-height:62vh;overflow-y:auto;padding:6px}
.fontmenu .fgroup{font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--muted);padding:9px 10px 4px}
.fontmenu button{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  width:100%;border:0;background:none;padding:8px 10px;border-radius:8px;cursor:pointer;
  text-align:left;color:var(--ink)}
.fontmenu button:hover{background:#F4F1EA}
.fontmenu button[aria-selected=true]{background:#EEF2F6;color:var(--navy)}
/* The name is set in its own face — that is the whole point of the control. */
.fontmenu .fname{font-size:19px;line-height:1.35;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.fontmenu .fnote{font-size:10.5px;color:var(--muted);font-family:Inter,system-ui;flex:none}

/* ── book: running foot and page number ── */
/* Drawn as a layer rather than as elements: a folio is a property of the
   document, so it cannot be dragged loose, deleted by accident, or left behind
   when pages are reordered. */
.folio{position:absolute;inset:0;pointer-events:none;z-index:7}
.folio span{position:absolute;white-space:nowrap;color:#57534B;line-height:1}
#flowText{width:100%;font:13px/1.5 Inter,system-ui;padding:9px 10px;border:1px solid var(--line);
  border-radius:9px;resize:vertical;margin-bottom:8px}
.book-ch{display:flex;justify-content:space-between;gap:8px;font-size:12px;padding:4px 2px;
  border-bottom:1px solid var(--line)}
.book-ch b{font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.book-ch .warn{color:#B4423C;font-weight:700}
.book-ch .ok{color:var(--muted)}

/* ── centring hints ── */
/* Shown only while a drag is actually sitting on the centre line, and removed
   the moment it is not — a guide that is always there is furniture, a guide
   that appears when it means something is information.
   Namespaced away from .h, which is the resize-handle class: that collision
   turned the ruler guides into 9px dots once already. */
.align-hint{position:absolute;top:0;bottom:0;width:0;pointer-events:none;z-index:64;
  border-left:1.5px dashed #C2456E}
.align-hint.h{left:0;right:0;top:auto;bottom:auto;width:auto;height:0;
  border-left:0;border-top:1.5px dashed #C2456E}
.align-hint::after{content:'';position:absolute;left:-3.5px;top:50%;width:7px;height:7px;
  margin-top:-3.5px;border-radius:50%;background:#C2456E}
.align-hint.h::after{left:50%;top:-3.5px;margin:0 0 0 -3.5px}

/* A text element is a frame: the words wrap to its width and sit at the top,
   so widening it gives them more room instead of magnifying them. */
.el.txt{align-items:flex-start}
.el.txt[data-align=center]{align-items:center}

/* ── text that does not fit ── */
/* InDesign puts a red plus on an overflowing frame and leaves you to find the
   next one. The text is already written; the useful thing is a button that
   makes somewhere for it to go. */
.overflow-tag{position:absolute;z-index:66;display:flex;align-items:center;gap:6px;
  background:#B4423C;color:#fff;border-radius:9px;padding:5px 7px;
  box-shadow:0 4px 12px rgba(0,0,0,.24);font-size:11.5px;font-weight:700;
  transform:translate(-100%,6px)}
.overflow-tag .ot-note{padding-left:3px}
.overflow-tag button{border:0;border-radius:6px;padding:4px 8px;cursor:pointer;
  font:inherit;background:rgba(255,255,255,.18);color:#fff}
.overflow-tag button:hover{background:rgba(255,255,255,.32)}

/* ── folio hints ── */
/* Greyed, dashed, and clickable — an invitation, not content. Excluded from
   print and never drawn into an export, so they cannot end up in a book. */
.folio-ghost{position:absolute;pointer-events:auto;cursor:pointer;white-space:nowrap;
  font:11px Inter,system-ui;color:#A9A296;border:1px dashed #C9C1B2;border-radius:6px;
  padding:2px 7px;background:rgba(255,255,255,.72)}
.folio-ghost:hover{color:var(--navy);border-color:var(--navy);background:#fff}
@media print{.folio-ghost{display:none!important}}

/* ── story frames ── */
/* Lines are placed by the layout engine, not by the browser's own wrapping, so
   what is on screen and what lands in the PDF cannot drift apart. */
.el.story{overflow:hidden}
.el.story .sline{position:absolute;left:0;right:0;white-space:pre;display:block}

/* ── desktop shell ── */
/* macOS draws its own traffic lights over the top-left, so the bar starts
   clear of them. The in-page menu bar stays: it is the same set of actions and
   people reach for whichever is nearer. */
.desktop #app .bar{padding-left:78px}
.desktop .appmark{display:none}
@media (max-width:820px){ .desktop #app .bar{padding-left:12px} }

/* ── crop mode ── */
/* The whole photo is shown dimmed with the keep-region cut out of the shade,
   so you are choosing from what exists rather than guessing at what is hidden. */
.cropper{position:absolute;inset:0;z-index:80}
.crop-shade{position:absolute;inset:0;background:rgba(20,22,26,.62);pointer-events:none}
.crop-win{position:absolute;cursor:move;box-shadow:0 0 0 9999px rgba(20,22,26,.62);
  outline:1.5px solid #fff}
/* Rule-of-thirds lines, the standard aid for deciding a crop. */
.crop-win::before,.crop-win::after{content:'';position:absolute;inset:0;pointer-events:none}
.crop-win::before{background:
  linear-gradient(to right,transparent 33.33%,rgba(255,255,255,.45) 33.33% calc(33.33% + 1px),
  transparent calc(33.33% + 1px),transparent 66.66%,rgba(255,255,255,.45) 66.66% calc(66.66% + 1px),
  transparent calc(66.66% + 1px))}
.crop-win::after{background:
  linear-gradient(to bottom,transparent 33.33%,rgba(255,255,255,.45) 33.33% calc(33.33% + 1px),
  transparent calc(33.33% + 1px),transparent 66.66%,rgba(255,255,255,.45) 66.66% calc(66.66% + 1px),
  transparent calc(66.66% + 1px))}
.crop-win .ch{position:absolute;width:16px;height:16px;border:2.5px solid #fff;background:none}
.crop-win .ch[data-c=nw]{left:-2px;top:-2px;border-right:0;border-bottom:0;cursor:nwse-resize}
.crop-win .ch[data-c=ne]{right:-2px;top:-2px;border-left:0;border-bottom:0;cursor:nesw-resize}
.crop-win .ch[data-c=sw]{left:-2px;bottom:-2px;border-right:0;border-top:0;cursor:nesw-resize}
.crop-win .ch[data-c=se]{right:-2px;bottom:-2px;border-left:0;border-top:0;cursor:nwse-resize}
.cropbar{position:fixed;left:50%;transform:translateX(-50%);bottom:26px;z-index:210;
  display:flex;align-items:center;gap:10px;background:#fff;border:1px solid var(--line);
  border-radius:12px;padding:9px 12px;box-shadow:0 10px 30px rgba(0,0,0,.22)}
.cropbar span{font-size:12.5px;color:var(--muted);padding-right:4px}
.el.cropping{outline:none!important}
.el.cropping .h{display:none}
