/* ================================================================
   EVERQR — "TOYSHOP" design system  ·  v2
   Hand-authored CSS. No framework, no utility classes, no presets.

   Rules of the system
   -------------------
   1. Nothing is a rectangle by default. Every frame is a hand-drawn
      SVG path injected by toyshop.js — jittered, stroked twice, the
      way you draw a box with a marker and go round again.
   2. Colour is flat. No gradients as decoration (only paper shading).
   3. Motion overshoots. Everything lands with a spring, never a
      linear fade. Presses squash; arrivals slap down like a sticker.
   4. Type: one fat display face, one plain body, one handwriting for
      margin notes. Numbers are always the fat face.
   5. Words are plain English. The novelty lives in the drawing, not
      in the labels.
   ================================================================ */

:root{
  /* --- paper & ink --- */
  --paper:      #e9f5e2;   /* pistachio page */
  --paper-2:    #fffdf6;   /* warm white panel */
  --paper-3:    #dcecd2;   /* shaded panel */
  --ink:        #2a1e3f;   /* grape, all text */
  --ink-2:      #5c5175;   /* secondary text */

  /* --- the four toys (flat, never blended) --- */
  --tomato:     #ff5b41;
  --tomato-dark:#d63f2b;
  /* the bright brand colours are fills; text and buttons use these darker
     twins so every label clears 4.5:1 against paper */
  --tomato-ink: #c1381f;
  --tomato-btn: #d63f2b;
  --tomato-btn-dark:#9e2716;
  --leaf-ink:   #0b7a52;
  --sun:        #ffcf3f;
  --sky:        #8ecbff;
  --leaf:       #12b177;
  --clay:       #e08b6a;

  /* --- rhythm --- */
  --u: 8px;
  --r: 22px;              /* the one radius, used sparingly */

  /* the fat face is for shouting (big headings, the logo) only; everything
     smaller uses a rounded face you can actually read at 1rem */
  --display:'Bagel Fat One', system-ui, sans-serif;
  --display-2:'Baloo 2', 'Figtree', system-ui, sans-serif;
  --body:'Figtree', system-ui, -apple-system, sans-serif;
  --hand:'Kalam', cursive;

  --spring: cubic-bezier(.34,1.56,.4,1);
  --ease: cubic-bezier(.22,.61,.36,1);
  /* how far the drawn outline sits outside its panel; gaps must clear it */
  --frame: 8px;
}

*{box-sizing:border-box;margin:0;padding:0}
/* anchors on the shop front glide; the app jumps, because its hash routing
   would otherwise animate the whole page on every screen change */
html:not(.app){scroll-behavior:smooth}

body{
  /* the paper fibre is part of the page background, not a blended overlay on
     top of it: a fixed blended layer repaints the whole viewport on scroll */
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23f)' opacity='.12'/%3E%3C/svg%3E") repeat,
    var(--paper);
  color:var(--ink);
  font-family:var(--body);
  font-size:17px;
  line-height:1.65;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}

/* the drifting paper blobs: one composited layer so scrolling never re-runs
   their turbulence filters */
.blobs{position:fixed;inset:0;z-index:-1;overflow:hidden;pointer-events:none;
  transform:translateZ(0);contain:strict}
/* on a phone the blobs sit right behind body copy, so they step back */
@media (max-width:760px){.blobs{opacity:.34}.blobs svg{transform:scale(.72)}}

a{color:var(--ink)}
.sheet a:not(.btn):not(.pill):not(.mini):not(.navlink),
main a:not(.btn):not(.pill):not(.mini):not(.rail a){text-decoration-thickness:1.5px;text-underline-offset:2px}

/* ---------------- type ---------------------------------------- */
h1,h2,h3,h4{font-family:var(--display);font-weight:400;letter-spacing:-.008em;
  text-wrap:balance;overflow-wrap:break-word}
h1{font-size:clamp(2.5rem,6.2vw,4.8rem);line-height:1.04}
h2{font-size:clamp(1.85rem,3.6vw,2.9rem);line-height:1.08}
h3,h4{font-family:var(--display-2);font-weight:700;letter-spacing:0}
h3{font-size:1.35rem;line-height:1.3}
h4{font-size:1.1rem;line-height:1.35}
p{text-wrap:pretty}
.hand{font-family:var(--hand);font-weight:700;line-height:1.15}
.note{font-family:var(--hand);font-size:1.28rem;color:var(--clay);transform:rotate(-2deg);display:inline-block}
.kicker{font-size:.9rem;font-weight:500;color:var(--ink-2);line-height:1.55}
.lede{font-size:1.12rem;line-height:1.58;color:var(--ink-2);max-width:52ch}
/* headings sit tight to the sentence they introduce, loose from what came before */
h3 + .kicker,h4 + .kicker,h2 + .kicker{margin-top:calc(var(--u)*1.2)}
.tomato{color:var(--tomato-ink)}
.leaf{color:var(--leaf-ink)}

/* a word with a hand-drawn underline (the swoosh is drawn in JS) */
.marked{position:relative;display:inline-block;white-space:nowrap}
.marked svg{position:absolute;left:-4%;width:108%;bottom:-.22em;height:.42em;overflow:visible}
.marked svg path{fill:none;stroke:var(--tomato);stroke-width:9;stroke-linecap:round;
  stroke-dasharray:600;stroke-dashoffset:600;animation:ink-in 1s .35s var(--spring) forwards}
@keyframes ink-in{to{stroke-dashoffset:0}}

/* ---------------- layout -------------------------------------- */
.sheet{max-width:1180px;margin:0 auto;padding:0 calc(var(--u)*4)}
.duo{display:grid;grid-template-columns:1.42fr 1fr;gap:calc(var(--u)*7);align-items:center}
@media (max-width:940px){.duo{grid-template-columns:1fr}}

/* ---------------- hand-drawn frames --------------------------- */
/* .drawn gets an SVG outline injected behind it by toyshop.js.
   The element itself keeps NO css border — that is the whole point. */
.drawn{position:relative;background:var(--paper-2);border-radius:var(--r);padding:calc(var(--u)*4)}
.drawn > svg.frame{position:absolute;inset:calc(var(--frame) * -1);
  width:calc(100% + var(--frame) * 2);height:calc(100% + var(--frame) * 2);
  pointer-events:none;overflow:visible;z-index:0}
.drawn > svg.frame path{fill:none;stroke:var(--ink);stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}
.drawn > *:not(svg.frame):not(.tape):not(.step){position:relative;z-index:1}
.drawn > .tape{z-index:4}
.drawn > .step{z-index:3}
.drawn--sun{background:var(--sun)}
.drawn--sky{background:var(--sky)}
.drawn--white{background:var(--paper-2)}
.drawn--shade{background:var(--paper-3)}

/* a second sheet of colour peeking out underneath, like layered paper.
   It matches the inked outline's box so the colour reads as a sheet behind the
   card rather than a stray stroke cutting through the outline. */
.under{position:relative}
.under::before{content:'';position:absolute;inset:calc(var(--frame) * -1);
  border-radius:calc(var(--r) + 4px);
  background:var(--sun);transform:translate(10px,12px) rotate(-1deg);z-index:-1}
@media (max-width:760px){
  /* the second sheet would poke past the screen edge on a phone */
  .under::before{transform:translate(6px,8px) rotate(-.6deg)}
}
.under--sky::before{background:var(--sky)}
.under--tomato::before{background:var(--tomato)}
.under--leaf::before{background:#a8e8c9}

/* masking tape holding things down */
.tape{position:absolute;width:104px;height:26px;background:rgba(255,207,63,.72);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.05);transform:rotate(-6deg);z-index:3;
  clip-path:polygon(2% 12%,99% 0,98% 88%,1% 100%)}
.tape--r{transform:rotate(5deg)}

/* ---------------- buttons ------------------------------------- */
.btn{
  font-family:var(--display-2);font-weight:700;font-size:1.06rem;letter-spacing:.01em;cursor:pointer;border:0;
  display:inline-flex;align-items:center;gap:.5em;text-decoration:none;color:#fff;
  padding:calc(var(--u)*2.1) calc(var(--u)*3.6);background:var(--tomato-btn);
  border-radius:999px;box-shadow:0 6px 0 var(--tomato-btn-dark);
  transition:transform .16s var(--spring),box-shadow .16s var(--spring);
  position:relative;isolation:isolate;
}
.btn:hover{transform:translateY(-3px) rotate(-.6deg);box-shadow:0 10px 0 var(--tomato-dark)}
.btn:active{transform:translateY(5px) scaleY(.94);box-shadow:0 1px 0 var(--tomato-dark)}
.btn--grape{background:var(--ink);box-shadow:0 6px 0 #170f2a}
.btn--grape:hover{box-shadow:0 10px 0 #170f2a}
.btn--grape:active{box-shadow:0 1px 0 #170f2a}
.btn--sm{font-size:.88rem;padding:11px 20px;box-shadow:0 4px 0 var(--tomato-dark)}
.btn--sm:active{box-shadow:0 1px 0 var(--tomato-dark)}
/* little squares fly out of the button when it is pressed */
.spark{position:fixed;width:7px;height:7px;background:var(--ink);z-index:150;pointer-events:none;border-radius:1px}

/* ---------------- inputs -------------------------------------- */
.field{width:100%;font-family:var(--body);font-size:1.05rem;font-weight:600;color:var(--ink);
  background:var(--paper-3);border:0;border-radius:16px;padding:calc(var(--u)*2);outline:0;
  transition:box-shadow .18s ease}
.field::placeholder{color:#96a58f}
.field:hover:not(:focus){background:#e2efdb}
.field:focus{box-shadow:0 0 0 4px rgba(142,203,255,.85)}
.field[disabled]{opacity:.55;cursor:not-allowed}
/* one keyboard ring for everything that can be tabbed to */
:focus-visible{outline:3px solid var(--ink);outline-offset:3px;border-radius:6px}
/* keyboard users get past the header in one tab, without it showing for anyone else */
.skip{position:fixed;left:calc(var(--u)*2);top:calc(var(--u)*2);z-index:60;transform:translateY(-200%);
  background:var(--ink);color:var(--paper);font-weight:700;padding:10px 16px;border-radius:999px;
  text-decoration:none;transition:transform .18s var(--spring)}
.skip:focus{transform:translateY(0)}
.field:focus-visible{outline-offset:1px}
select.field{cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1.6 1.7 C4 4 5.6 6.4 7 7.2 C8.5 6.3 10 4 12.4 1.5' fill='none' stroke='%232a1e3f' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center;padding-right:38px;
  -webkit-appearance:none;appearance:none}

.slider{-webkit-appearance:none;appearance:none;width:100%;height:16px;background:transparent;cursor:grab}
.slider::-webkit-slider-runnable-track{height:8px;border-radius:99px;background:var(--paper-3)}
.slider::-webkit-slider-thumb{-webkit-appearance:none;width:26px;height:26px;margin-top:-9px;border-radius:50%;
  background:var(--tomato);box-shadow:0 3px 0 var(--tomato-dark),0 0 0 3px var(--paper-2)}
.slider::-webkit-slider-thumb{transition:transform .14s var(--spring)}
.slider:hover::-webkit-slider-thumb{transform:scale(1.06)}
.slider:active{cursor:grabbing}
.slider:active::-webkit-slider-thumb{transform:scale(1.12)}
.slider:focus-visible{outline:0}
.slider:focus-visible::-webkit-slider-thumb{box-shadow:0 3px 0 var(--tomato-dark),0 0 0 3px var(--paper-2),0 0 0 6px var(--ink)}

/* a finger cannot hover, so a tapped control must not keep the lifted look */
@media (hover:none){
  .btn:hover,.mini:hover,button.pill:hover,a.pill:hover,.tabs button:hover,
  .pick:hover,.preset:hover,.swatch:hover,.row:hover,.drawn.slap:hover{transform:none}
  .btn:hover{box-shadow:0 6px 0 var(--tomato-dark)}
  .mini:hover{background:var(--paper-3)}
}

/* ---------------- pills / states ------------------------------ */
.pill{display:inline-flex;align-items:center;gap:7px;background:var(--paper-2);border-radius:999px;
  padding:7px 15px;font-size:.83rem;font-weight:700;box-shadow:0 2px 0 rgba(42,30,63,.16);
  color:var(--ink);text-decoration:none;border:0;font-family:var(--body);cursor:default}
button.pill,a.pill{cursor:pointer;transition:transform .16s var(--spring),box-shadow .16s var(--spring)}
button.pill:hover,a.pill:hover{transform:translateY(-2px);box-shadow:0 4px 0 rgba(42,30,63,.2)}
button.pill:active,a.pill:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(42,30,63,.2)}
.pill--live{background:var(--leaf-ink);color:#fff}
.pill--warn{background:var(--sun)}
.pill--dead{background:#ffdfd8;color:#b8341c}
.dot{width:8px;height:8px;border-radius:50%;background:currentColor;animation:blip 1.6s var(--spring) infinite}
@keyframes blip{0%,100%{transform:scale(1)}50%{transform:scale(.5)}}

/* a row of headline numbers that never wraps mid-figure */
.figures{display:grid;grid-template-columns:repeat(3,auto);gap:calc(var(--u)*5);justify-content:start}
.figures .kicker{max-width:22ch;text-wrap:balance}
@media (max-width:620px){.figures{grid-template-columns:auto;gap:calc(var(--u)*2.5)}}

/* ---------------- numbers ------------------------------------- */
.stat{font-family:var(--display-2);font-weight:700;font-size:2.8rem;line-height:.98}
.stat--big{font-size:clamp(2.6rem,5vw,4rem)}

/* ---------------- QR ------------------------------------------ */
.qr{display:block;width:100%;height:auto}
.qr .mod{animation:drop .4s var(--spring) backwards}
@keyframes drop{from{opacity:0;transform:translateY(-5px) scale(.45)}}

/* ---------------- sticker slap-in on scroll ------------------- */
.slap{opacity:0;transform:translateY(22px) rotate(-1.8deg) scale(.975);
  transition:opacity .34s var(--ease),transform .46s var(--spring)}
.slap.in{opacity:1;transform:none}

/* ---------------- torn paper divider -------------------------- */
.torn{display:block;width:100%;height:46px}

/* ---------------- marquee of drawn icons ---------------------- */
.belt{overflow:hidden;padding:calc(var(--u)*1.5) 0;background:var(--ink);color:var(--paper)}
/* three identical sets, shifted by exactly one: the seam never shows a gap,
   and two sets always remain on screen however wide the window is */
.belt__row{display:flex;width:max-content;white-space:nowrap;animation:belt 34s linear infinite;
  font-family:var(--display-2);font-weight:700;font-size:.98rem;align-items:center;will-change:transform}
.belt__set{display:flex;gap:calc(var(--u)*5);align-items:center;padding-right:calc(var(--u)*5)}
.belt:hover .belt__row{animation-play-state:paused}
@keyframes belt{from{transform:translateX(0)}to{transform:translateX(calc(-1 * var(--belt-shift, 33.3333%)))}}

/* ---------------- ledger (dashboard) -------------------------- */
.rows{display:grid;gap:calc(var(--frame) * 2 + var(--u) * 1.5)}
.row{display:grid;grid-template-columns:auto 1fr auto auto;gap:calc(var(--u)*3);align-items:center;
  background:var(--paper-2);border-radius:var(--r);padding:calc(var(--u)*2.2);
  transition:transform .18s var(--spring)}
.row:hover{transform:translateY(-3px) rotate(-.35deg)}
@media (max-width:860px){.row{grid-template-columns:auto 1fr}}
.bars{display:flex;align-items:flex-end;gap:4px;height:44px}
.bars i{width:7px;border-radius:4px 4px 2px 2px;background:var(--ink);display:block;
  animation:rise .5s var(--spring) backwards}
.bars i:hover{background:var(--tomato)}
@keyframes rise{from{height:0!important}}

/* ---------------- mascot -------------------------------------- */
.buddy{cursor:pointer}
.buddy .body{animation:bob 3.6s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0) rotate(-1deg)}50%{transform:translateY(-6px) rotate(1.5deg)}}
.buddy.happy .body{animation:jump .6s var(--spring)}
@keyframes jump{0%{transform:translateY(0)}35%{transform:translateY(-22px) scale(1.06)}100%{transform:translateY(0)}}
.buddy .lid{transform-origin:center;animation:blink 5.2s steps(1) infinite}
@keyframes blink{0%,96%{transform:scaleY(0)}97%,99%{transform:scaleY(1)}100%{transform:scaleY(0)}}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  .slap{opacity:1;transform:none}
}

/* circled step number, pinned to the corner of its card */
.step{position:absolute;top:-24px;left:-18px;z-index:3;transform:rotate(-6deg)}
.drawn > .step{position:absolute;z-index:3}

/* the section links go, but signing in must never be more than one tap away */
@media (max-width:820px){
  .navlink{display:none}
  .navlink--keep{display:inline-block;white-space:nowrap}
  header nav{gap:calc(var(--u)*2)}
}
/* at phone width the three header items have to shrink, not collide */
@media (max-width:440px){
  header.sheet{padding-left:calc(var(--u)*2)!important;padding-right:calc(var(--u)*2)!important;gap:calc(var(--u)*1.5)}
  header.sheet > a strong{font-size:1.1rem!important}
  header.sheet .mark{width:34px}
  header nav{gap:calc(var(--u)*1.5);font-size:.9rem}
  header nav .btn--sm{padding:calc(var(--u)*1.2) calc(var(--u)*2);font-size:.92rem}
}

/* ================================================================
   THE WORKSHOP — dashboard surfaces, same hand as the shop front.
   ================================================================ */

.shell{display:grid;grid-template-columns:232px 1fr;gap:calc(var(--u)*4);
  max-width:1420px;margin:0 auto;padding:calc(var(--u)*3) calc(var(--u)*4) calc(var(--u)*10)}
@media (max-width:900px){.shell{grid-template-columns:1fr;gap:calc(var(--u)*2)}}
.shell > main{min-width:0}

.rail{position:sticky;top:calc(var(--u)*3);align-self:start;display:grid;gap:6px}
@media (max-width:900px){
  .rail{position:static;display:flex;gap:6px;overflow-x:auto;padding-bottom:6px;scrollbar-width:none}
  .rail::-webkit-scrollbar{display:none}
}
.rail a{display:flex;align-items:center;gap:9px;padding:10px 14px;border-radius:14px;text-decoration:none;
  color:var(--ink);font-weight:700;font-size:.95rem;white-space:nowrap;
  transition:transform .16s var(--spring),background .16s ease}
.rail a:hover{background:var(--paper-3);transform:translateX(3px)}
@media (max-width:900px){.rail a:hover{transform:translateY(-2px)}}
.rail a[aria-current='page']{background:var(--ink);color:var(--paper)}
.rail a[aria-current='page'] .ic{filter:invert(1)}
.ic{width:18px;height:18px;flex:0 0 18px}

.bar{display:flex;align-items:flex-end;justify-content:space-between;gap:calc(var(--u)*2);flex-wrap:wrap;
  margin-bottom:calc(var(--u)*3.5)}
/* the title and its one-line explanation read as a pair */
.bar > div:first-child{min-width:0;max-width:62ch}
/* a bar inside a card is a section head, not a page head, so it sits closer */
.drawn > .bar{align-items:center;margin-bottom:calc(var(--u)*1.5)}
.bar h2 + .kicker{margin-top:calc(var(--u)*.75)}
.split{display:grid;grid-template-columns:minmax(0,1fr) 400px;gap:calc(var(--u)*4);align-items:start}
@media (max-width:1080px){.split{grid-template-columns:minmax(0,1fr)}}
/* every gap between drawn panels has to clear the outline on both sides */
.stack{display:grid;gap:calc(var(--frame) * 2 + var(--u) * 2)}
/* the column count follows the number of cards, so a row never ends with one
   lonely stretched card next to empty space */
.cols:has(> :nth-child(2):last-child),
.cols:has(> :nth-child(4):last-child),
.cols:has(> :nth-child(8):last-child){grid-template-columns:repeat(2,minmax(0,1fr))}
.cols:has(> :nth-child(3):last-child),
.cols:has(> :nth-child(6):last-child),
.cols:has(> :nth-child(9):last-child){grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:700px){
  .cols:has(> :nth-child(3):last-child),
  .cols:has(> :nth-child(9):last-child){grid-template-columns:minmax(0,1fr)}
  .cols:has(> :nth-child(6):last-child),
  .cols:has(> :nth-child(8):last-child){grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* two panels side by side squeeze labels and inputs on a phone, so they stack */
@media (max-width:560px){
  .cols:not(.cols--stats):has(> :nth-child(2):last-child),
  .cols:not(.cols--stats):has(> :nth-child(4):last-child),
  .cols:not(.cols--stats):has(> :nth-child(6):last-child),
  .cols:not(.cols--stats):has(> :nth-child(8):last-child){grid-template-columns:minmax(0,1fr)}
}
.cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:calc(var(--frame) * 2 + var(--u) * 1.5)}
.split > *,.stack > *,.cols > *{min-width:0}
/* headline numbers are small cards, so they stand in one row instead of a fat block */
.cols.cols--stats{gap:calc(var(--frame) * 2 + var(--u) * .5)}
.cols.cols--stats,
.cols--stats:has(> :nth-child(4):last-child){grid-template-columns:repeat(4,minmax(0,1fr))}
.cols--stats:has(> :nth-child(3):last-child){grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:900px){
  .cols.cols--stats,
  .cols--stats:has(> :nth-child(4):last-child){grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* three across is fine while they fit; below that they stack, never 2 + 1 */
@media (max-width:620px){
  .cols--stats:has(> :nth-child(3):last-child){grid-template-columns:minmax(0,1fr)}
}
.sticky{position:sticky;top:calc(var(--u)*3)}
@media (max-width:1080px){.sticky{position:static}}

label.lbl{display:block;font-size:.82rem;font-weight:700;color:var(--ink-2);margin:0 0 5px;letter-spacing:.01em}
.hintline{font-size:.8rem;color:var(--ink-2);margin-top:5px}
select.field,textarea.field{font-family:var(--body)}
textarea.field{min-height:92px;resize:vertical;line-height:1.5}
input.field[type=color]{padding:4px;height:46px;cursor:pointer}
.inline{display:flex;gap:var(--u);align-items:center;flex-wrap:wrap}
.inline > .field{flex:1 1 130px;min-width:0}
.check{display:flex;align-items:center;gap:9px;font-weight:600;font-size:.92rem;cursor:pointer}
.check input{width:20px;height:20px;accent-color:var(--tomato);cursor:pointer}

/* tab strip drawn like paper file tabs */
.tabs{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:calc(var(--frame) + var(--u))}
.tabs button{font-family:var(--body);font-weight:700;font-size:.9rem;cursor:pointer;border:0;
  background:var(--paper-3);color:var(--ink-2);padding:9px 16px;border-radius:14px 14px 4px 4px;
  transition:transform .16s var(--spring)}
.tabs button:hover{transform:translateY(-2px)}
.tabs button:active{transform:translateY(1px)}
.tabs button[aria-selected='true']{background:var(--ink);color:var(--paper)}

/* shape / preset choosers: little drawn buttons holding a sample */
.picks{display:grid;grid-template-columns:repeat(auto-fill,minmax(58px,1fr));gap:7px}
.pick{background:var(--paper-2);border:0;border-radius:14px;padding:7px;cursor:pointer;
  box-shadow:0 2px 0 rgba(42,30,63,.18);transition:transform .16s var(--spring),box-shadow .16s var(--spring)}
.pick:hover{transform:translateY(-3px) rotate(-1.5deg);box-shadow:0 5px 0 rgba(42,30,63,.2)}
.pick:active{transform:translateY(1px) rotate(0);box-shadow:0 1px 0 rgba(42,30,63,.2)}
.pick[aria-pressed='true']{background:var(--sun);box-shadow:0 3px 0 #c9a11f}
.pick svg{display:block;width:100%;height:auto}
.pick small{display:block;font-size:.62rem;font-weight:700;margin-top:3px;color:var(--ink-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pick[aria-pressed='true'] small{color:var(--ink)}

.swatches{display:flex;gap:6px;flex-wrap:wrap}
.swatch{width:30px;height:30px;border-radius:9px;border:0;cursor:pointer;box-shadow:0 2px 0 rgba(42,30,63,.25);
  transition:transform .16s var(--spring),box-shadow .16s var(--spring)}
.swatch:hover{transform:translateY(-2px);box-shadow:0 4px 0 rgba(42,30,63,.25)}
.swatch:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(42,30,63,.25)}

/* preset cards */
.presetlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:9px;
  max-height:340px;overflow:auto;padding:2px;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.preset{background:var(--paper-2);border:0;border-radius:16px;padding:9px;cursor:pointer;text-align:left;
  box-shadow:0 3px 0 rgba(42,30,63,.16);transition:transform .16s var(--spring)}
.preset:hover{transform:translateY(-3px) rotate(-1deg)}
.preset:active{transform:translateY(1px) rotate(0)}
.preset[aria-pressed='true']{background:var(--sky)}
.preset b{display:block;font-family:var(--display-2);font-weight:700;font-size:.92rem}
.preset span{display:block;font-size:.72rem;color:var(--ink-2);line-height:1.35}

/* verdict strip: the honest answer about printability */
.verdicts{display:grid;gap:7px;margin-top:calc(var(--u)*2)}
/* one label column for every row, so the sentences all start on the same line */
.verdict{display:grid;grid-template-columns:82px minmax(0,1fr);gap:10px;align-items:baseline;
  background:var(--paper-3);border-radius:14px;padding:10px 13px;
  font-size:.86rem;font-weight:600;line-height:1.45}
.verdict b{font-family:var(--display-2);font-weight:700;text-wrap:balance}
@media (max-width:420px){.verdict{grid-template-columns:minmax(0,1fr);gap:2px}}
.verdict--great{background:#d8f5e6}
.verdict--risky{background:#ffeec9}
.verdict--fail{background:#ffdfd8;color:#8f2214}

/* code rows in the ledger */
.codeline{display:grid;grid-template-columns:64px 1fr auto;gap:calc(var(--u)*2);align-items:center}
@media (max-width:640px){.codeline{grid-template-columns:52px 1fr}}
.codeline img,.codeline svg{width:100%;height:auto;background:#fff;border-radius:10px}
.mono{font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:.82rem}
.trunc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
.tools{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.mini{font-family:var(--body);font-weight:700;font-size:.85rem;cursor:pointer;border:0;background:var(--paper-3);
  color:var(--ink);padding:7px 12px;border-radius:999px;text-decoration:none;display:inline-flex;align-items:center;gap:5px;
  transition:transform .16s var(--spring)}
.mini:hover{transform:translateY(-2px);background:var(--sun)}
.mini:active{transform:translateY(1px)}
.mini--bad:hover{background:#ffdfd8;color:#8f2214}
.mini[disabled],.btn[disabled],.pill[disabled]{opacity:.5;pointer-events:none}

/* analytics */
.chart{display:flex;align-items:flex-end;justify-content:space-between;gap:3px;height:120px;
  padding:var(--u) 3px 0;border-bottom:1.5px dashed rgba(42,30,63,.26)}
.chart i{flex:1 1 0;min-width:2px;max-width:18px;background:var(--ink);border-radius:4px 4px 2px 2px;display:block;
  animation:rise .5s var(--spring) backwards}
.chart i:hover{background:var(--tomato)}
.chartscale{display:flex;justify-content:space-between;gap:var(--u);margin-top:7px;
  font-size:.76rem;font-weight:600;color:var(--ink-2)}
.chartscale span:nth-child(2){text-align:center}
.chartscale span:last-child{text-align:right}
.meter{display:grid;grid-template-columns:1fr 3fr auto;gap:10px;align-items:center;font-size:.88rem;
  font-weight:600;margin:5px 0}
.meter u{display:block;height:9px;border-radius:99px;background:var(--sun);text-decoration:none}
.meter em{font-style:normal;color:var(--ink-2);font-size:.82rem}

/* toast + modal */
.toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:400;display:grid;gap:8px;
  width:min(460px,calc(100vw - 32px))}
.toast > div{background:var(--ink);color:var(--paper);border-radius:16px;padding:12px 16px;font-weight:600;
  font-size:.92rem;box-shadow:0 8px 0 rgba(23,15,42,.35);animation:pop .4s var(--spring)}
.toast > div.bad{background:#8f2214;box-shadow:0 8px 0 #5c1409}
.toast > div.good{background:var(--leaf-ink);box-shadow:0 8px 0 #075c3d}
@keyframes pop{from{opacity:0;transform:translateY(16px) scale(.94)}}

.veil{position:fixed;inset:0;background:rgba(42,30,63,.55);z-index:300;display:grid;place-items:center;padding:18px;
  animation:fade .2s ease}
@keyframes fade{from{opacity:0}}
.modal{background:var(--paper-2);border-radius:24px;padding:calc(var(--u)*4);width:min(520px,100%);
  max-height:88vh;overflow:auto;box-shadow:0 12px 0 rgba(23,15,42,.3);animation:pop .34s var(--spring)}

/* repeating field groups (menu sections, links, specs) */
.repeat{display:grid;gap:9px}
.repeat > div{background:var(--paper-3);border-radius:16px;padding:10px;display:grid;gap:7px}
.repeat .inline .mini{align-self:center}

/* the workshop QR stage */
.stage{background:var(--paper-2);border-radius:20px;padding:calc(var(--u)*2);display:grid;place-items:center;
  min-height:220px}
.stage svg,.stage img{width:100%;max-width:280px;height:auto}
.gate{max-width:430px;margin:calc(var(--u)*8) auto}
/* the sign-in card reads as label/field pairs, not one undifferentiated list */
.gate .kicker:first-of-type{margin-top:calc(var(--u)*1.5)}
.gate .lbl{margin-top:calc(var(--u)*3)}
.gate .hintline{margin-top:calc(var(--u)*1)}
/* landing-page card rows. Fixed column counts, so a row never ends with one
   lonely card while its neighbours stretch. */
.trio,.feat,.tiers{display:grid;gap:calc(var(--u)*5);margin-top:calc(var(--u)*6)}
.trio{grid-template-columns:repeat(3,minmax(0,1fr))}
.feat{grid-template-columns:repeat(3,minmax(0,1fr));gap:calc(var(--u)*4)}
.tiers{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:1080px){.tiers{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:860px){.trio{grid-template-columns:1fr}}
@media (max-width:860px){.feat{grid-template-columns:1fr}}
@media (max-width:620px){.tiers{grid-template-columns:1fr}}

.plans{display:grid;gap:calc(var(--frame) * 2 + var(--u) * 1.5)}
.planrow{display:grid;grid-template-columns:1fr auto;gap:var(--u);align-items:center;
  background:var(--paper-2);border-radius:18px;padding:calc(var(--u)*2)}
.spin{display:inline-block;width:16px;height:16px;border-radius:50%;border:3px solid var(--paper-3);
  border-top-color:var(--tomato);animation:spin .7s linear infinite;vertical-align:-3px}
.btn .spin{border-color:rgba(255,255,255,.38);border-top-color:#fff}
[data-busy]{cursor:progress}
@keyframes spin{to{transform:rotate(360deg)}}
.empty{text-align:center;padding:calc(var(--u)*5) calc(var(--u)*2);color:var(--ink-2)}
.empty h3{margin:0 0 calc(var(--u)*.75);color:var(--ink)}
.empty p{margin:0 auto;max-width:44ch}
.empty .btn{margin-top:calc(var(--u)*2.5)}
.wrapline{overflow-wrap:anywhere}

/* ================= the signed-in app ================= */
body.app{padding-bottom:calc(var(--u)*8)}
.apphead{display:flex;align-items:center;gap:calc(var(--u)*2);
  padding:calc(var(--u)*2) calc(var(--u)*4);max-width:1420px;margin:0 auto}
.apphead .brand{display:flex;align-items:center;gap:9px;text-decoration:none;color:inherit}
.mark{display:block;height:auto;transition:transform .22s var(--spring)}
a:hover > .mark{transform:rotate(-5deg) scale(1.06)}
.apphead .brand strong{font-family:var(--display);font-weight:400;font-size:1.2rem}
#menu{display:none}
@media (max-width:900px){#menu{display:inline-flex}}
/* on a phone the header has to stay one line: no wrapped ‘Menu’, no wrapped link */
.apphead .mini{white-space:nowrap}
@media (max-width:520px){
  .apphead{gap:var(--u);padding:calc(var(--u)*1.5) calc(var(--u)*2)}
  .apphead .brand strong{font-size:1.05rem}
  .apphead .mini{padding:7px 10px;font-size:.76rem}
}

.planbox{margin-top:calc(var(--u)*2);background:var(--paper-3);border-radius:16px;padding:calc(var(--u)*1.5);
  display:grid;gap:5px;font-size:.82rem}
.planbox b{font-family:var(--display-2);font-weight:700;font-size:.98rem;text-transform:capitalize}
.planbox span{color:var(--ink-2)}
/* the storage bar needs a label and a home, or it reads as a stray line */
.usage{display:grid;grid-template-columns:auto minmax(120px,240px) auto;gap:10px;align-items:center;
  background:var(--paper-2);border-radius:14px;padding:9px 14px;width:max-content;max-width:100%;
  font-size:.82rem;font-weight:700;color:var(--ink-2);margin-bottom:calc(var(--u)*2)}
.usage b{font-family:var(--display-2);font-weight:700;color:var(--ink)}
.gauge{height:9px;border-radius:99px;background:var(--paper);overflow:hidden}
.gauge i{display:block;height:100%;background:var(--sun);border-radius:99px}

/* a row of label + number, used all over the reports */
.line{display:flex;align-items:center;justify-content:space-between;gap:var(--u);
  padding:7px 0;border-bottom:1.5px dashed rgba(42,30,63,.16);font-size:.9rem;font-weight:600}
.line:has(u){display:grid;grid-template-columns:minmax(0,1fr) 68px auto}
/* a quiet share bar so the biggest row is obvious without reading every number */
.line u{display:block;height:7px;border-radius:99px;background:var(--paper-3);overflow:hidden;text-decoration:none}
.line u::after{content:'';display:block;height:100%;width:var(--share,0%);border-radius:99px;background:var(--leaf);
  animation:grow .5s var(--spring) backwards}
@keyframes grow{from{width:0}}
@media (max-width:520px){.line:has(u){grid-template-columns:minmax(0,1fr) auto}.line u{display:none}}
.line:last-child{border-bottom:0}
.line b{font-family:var(--display-2);font-weight:700}
.small{font-size:.78rem}

/* one printed code, as a card in the ledger */
.codecard{display:flex;align-items:center;gap:calc(var(--u)*2);flex-wrap:wrap}
.codecard .thumb{background:#fff;border-radius:12px;padding:4px;flex:0 0 72px}
.codecard .grow{flex:1 1 220px;min-width:0;display:grid;gap:3px}
.codecard .grow b{font-family:var(--display-2);font-weight:700;font-size:1.06rem}
.codecard .grow a{color:var(--ink-2)}
.codecard .tools{align-items:center}
.codecard .tools > b{font-family:var(--display-2);font-weight:700;font-size:1.2rem;margin-right:-2px}
/* a phone-width card reads top to bottom: pick, code, name, then its actions */
@media (max-width:560px){
  .codecard{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--u) calc(var(--u)*1.5);align-items:start}
  .codecard > .check{grid-row:1;align-self:center}
  .codecard .thumb{grid-row:1;width:64px}
  .codecard .grow{grid-column:1/-1}
  .codecard .tools{grid-column:1/-1;justify-content:flex-start;
    border-top:1.5px dashed rgba(42,30,63,.16);padding-top:var(--u)}
  .codecard .tools .mini{flex:1 1 auto;justify-content:center}
}

.chip{display:inline-block;background:var(--paper-3);border-radius:99px;padding:1px 9px;font-size:.72rem;
  font-weight:700;margin-left:5px}
.chip--frozen{background:var(--sky)}
.chip--bad{background:#ffdfd8;color:#8f2214}

.mini-stat{text-align:center;display:grid;gap:2px;padding:calc(var(--u)*2)}
/* four single-file cards waste a phone screen; two across reads better */

.mini-stat b{font-family:var(--display-2);font-weight:700;font-size:1.9rem;line-height:1.1}
.mini-stat span{color:var(--ink-2);font-size:.82rem;font-weight:600}

.plans{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.plancard{display:grid;gap:9px;grid-template-rows:auto auto 1fr auto;padding:calc(var(--u)*3)}
.plancard .inline,.plancard > .btn,.plancard > .mini{align-self:end}
.plancard--current{background:var(--sun)}
.plancard h4{margin:0;font-family:var(--display-2);font-weight:700;font-size:1.3rem}
/* align-content keeps the bullets evenly spaced instead of stretching to fill
   the card when a plan has fewer lines than its neighbours */
.plancard ul{margin:0;padding-left:18px;display:grid;align-content:start;gap:6px;
  font-size:.88rem;line-height:1.45;color:var(--ink-2)}
.plancard .price{margin:0 0 calc(var(--u)*.5);font-weight:800}

/* smart-routing rule rows */
.rule{display:grid;grid-template-columns:1fr 1fr 1.4fr auto;gap:6px;align-items:center}
@media (max-width:900px){.rule{grid-template-columns:1fr 1fr}}

@media (max-width:900px){
  .shell #rail{display:none}
  /* opened by the ☰ button: a proper vertical menu card, not a cramped
     horizontal strip that runs off the side of the screen */
  body.rail-open .shell #rail{display:block}
  body.rail-open .shell #rail .rail{display:grid;gap:4px;overflow:visible;
    background:var(--paper-2);border-radius:var(--r);padding:calc(var(--u)*1.5);
    box-shadow:0 6px 0 rgba(42,30,63,.12)}
  body.rail-open .shell #rail .rail a{white-space:normal}
  body.rail-open .shell #rail .rail a:hover{transform:translateX(3px)}
  body.rail-open .shell #rail .planbox{margin-top:var(--u)}
}
.rail a svg{width:20px;height:20px;flex:0 0 20px}

/* dashboard headings are working titles, not billboards */
/* the app is read all day, so even its page titles use the readable face */
body.app h1,body.app h2{font-family:var(--display-2);font-weight:700;letter-spacing:0}
body.app h1{font-size:clamp(1.7rem,3.1vw,2.4rem);line-height:1.2;overflow-wrap:anywhere}
body.app h2{font-size:clamp(1.45rem,2.4vw,1.9rem);line-height:1.24}
body.app .bar{align-items:flex-start;row-gap:var(--u)}
body.app .bar > *{min-width:0}
body.app .bar .tools{justify-content:flex-start}
/* the shop-front display sizes are set in vw, which a narrow rail would
   otherwise stretch; the app never needs them that big */
body.app .stat,body.app .stat--big{font-size:2.1rem}
body.app main a[href^="http"]{color:var(--ink-2);overflow-wrap:anywhere}

/* leave room for the outlines of the first and last panel in a column, and
   keep every stacked panel far enough apart that the outlines never touch */
body.app main{padding:var(--frame) 0}
body.app main > * + *{margin-top:calc(var(--frame) * 2 + var(--u) * 2)}
body.app main > .bar + *{margin-top:0}
.codecard .grow a,.wrapline,.line span{overflow-wrap:anywhere}
