:root{
  --bg:#f0ede6;
  --paper:#fff2d2;
  --panel:#f1e2bd;
  --line:rgba(70,60,40,.2);
  --text:#3a352c;
  --muted:#857a64;
  --accent:#e4572e;
  --good:#3f9b4f;
  --warn:#d39a2f;
  --bad:#c84e35;
  --map-star:#5f8049;
  --map-acorn:#b86e38;
  --ink:#3a352c;
  --serif:'Fraunces','Iowan Old Style','Palatino Linotype',Palatino,Georgia,serif;
  --sans:'Nunito','Avenir Next',Avenir,'Segoe UI',system-ui,-apple-system,sans-serif;
  --mono:'IBM Plex Mono','SF Mono',ui-monospace,'Cascadia Code','Roboto Mono',Menlo,Consolas,monospace;
  --road:#59616d;
  --single:#c8553d;
  --town:#b9803f;
  --pond:#1fc3cf;
  --tree:#2f8a3f;
  --outside:#243528;
  --grass:#8fce56;
  --grass-dk:#5ea83d;
  --valid:rgba(255,244,180,.95);
  --low:#c5d4b8;
  --water-deep:rgba(22,104,166,.95);
  --water-base:rgba(38,150,206,.92);
  --water-highlight:rgba(200,238,252,.66);
  --ui-paper:#fff8e9;
  --ui-paper-wash:rgba(255,252,242,.72);
  --ui-ink-line:rgba(83,73,54,.68);
  --ui-ink-soft:rgba(130,116,82,.18);
  --ui-bleed:rgba(132,188,112,.11);
}

/* ===== screen system + transitions ===== */
#screens{position:relative;min-height:100dvh;}
.screen{
  position:fixed; inset:0; z-index:40;
  display:flex; flex-direction:column;
  background:
    radial-gradient(120% 90% at 50% 22%, #f3eee0 0 48%, #e6ddc9 78%, #d8cfb6 100%);
  opacity:0; transform:translateY(10px) scale(.995);
  pointer-events:none;
  transition:opacity .5s ease, transform .5s ease;
}
.screen.show{opacity:1; transform:none; pointer-events:auto;}
.screen.leaving{opacity:0; transform:translateY(-8px) scale(.995); pointer-events:none;}
/* the game .app fades like a screen too */
.app{opacity:1; transition:opacity .5s ease, transform .5s ease;}
.app.hidden{opacity:0; transform:scale(.995); pointer-events:none; visibility:hidden;}
/* Keep the game chrome below menu screens until boot calls showScreen('game'). */
#screens:not(.in-game) .app{visibility:hidden; pointer-events:none;}
#screens.in-game .screen{pointer-events:none;}

/* ===== title ===== */
#titleScreen{
  align-items:center; justify-content:center; text-align:center; overflow:hidden;
  padding:
    calc(32px + env(safe-area-inset-top,0px))
    calc(22px + env(safe-area-inset-right,0px))
    calc(32px + env(safe-area-inset-bottom,0px))
    calc(22px + env(safe-area-inset-left,0px));
}
#titleScreen::before{
  content:""; position:absolute; inset:-20%; z-index:-1; pointer-events:none;
  background-color:var(--bg);
  background-image:
    linear-gradient(to right, rgba(70,60,40,.1) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(70,60,40,.1) 1px, transparent 1px);
  background-size:8px 8px;        /* micro grid → reads as a zoomed-out county zoning map */
  filter:blur(4px); opacity:.6;
}
#titleScreen .title-bg-grid{
  position:absolute; inset:0; z-index:-1; pointer-events:none;
  background:
    radial-gradient(ellipse at 20% 30%, rgba(63,155,79,.15) 0%, transparent 50%),
    radial-gradient(ellipse at 80% 70%, rgba(31,195,207,.15) 0%, transparent 60%),
    radial-gradient(ellipse at 60% 20%, rgba(89,97,109,.1) 0%, transparent 50%),
    radial-gradient(ellipse at 35% 82%, rgba(228,87,46,.08) 0%, transparent 45%);
}
#titleScreen > *{position:relative; z-index:1;}
.title-stage{
  position:relative;
  z-index:1;
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
}
/* Plain opacity fade-in on the real elements — no cloning, no clip-path growth.
   A cloned/animated "ink reveal" version of this lived here through a few
   iterations and never got positioning right (the clone was absolutely
   centered on the screen while the real stage sat in normal flex flow, so for
   the ~1s the animation ran you'd see a mismatched ghost copy floating over the
   real buttons). Rolled back to this simple, stable version — see
   docs/HANDOFF.md for the history if it comes up again. */
@media (prefers-reduced-motion: no-preference){
  #titleScreen.show .title-main{ animation:fadeUp .6s ease-out .25s both; }
  #titleScreen.show .title-sub{ animation:fadeUp .6s ease-out .5s both; }
  #titleScreen.show .title-actions{ animation:fadeUp .6s ease-out .7s both; }
  @keyframes fadeUp{ from{opacity:0; transform:translateY(8px);} to{opacity:1; transform:none;} }
}
.title-main{font-family:var(--serif); font-weight:700; font-size:3.85rem; letter-spacing:.01em; color:var(--ink); line-height:.95; margin-bottom:10px; text-shadow:0 2px 0 rgba(255,255,255,.45);}
.title-version{
  font-family:var(--mono); font-size:.56rem; letter-spacing:.12em;
  color:#9a9080; opacity:.72; margin:14px 0 0; text-align:center;
}
.title-sub{font-family:var(--serif); font-style:italic; color:#5a5141; font-size:1.02rem; max-width:330px; margin-bottom:26px;}
.title-actions{display:flex; flex-direction:column; gap:11px; align-items:center; width:min(260px,80vw);}
#playBtn,#tutorialBtn{ min-height:52px; display:flex; align-items:center; justify-content:center; }
.title-actions .btn.big,
.title-audio-row .btn{
  overflow:hidden;
}
/* Title-screen buttons: flat color + the same static grain texture already used
   on <body> (see the `body{background:...}` rule below) layered on top via
   background-blend-mode — no gradients, no per-button procedural color blobs.
   Replaces an earlier version that painted unique per-button SVG "color blob"
   shapes at runtime; that read as busy/mottled rather than flat, and is gone now.
   Deliberately scoped to these specific IDs/classes (all title-screen-only,
   verified via grep) rather than the shared .btn/.btn.emerald/.btn.ghost rules,
   so nothing outside the title screen (submit button, approval screen, etc.)
   is affected. */
#playBtn{
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='t'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23t)' opacity='0.5'/></svg>"),
    #3f8f4f;
  background-blend-mode:overlay;
  color:#fffaf1;
  border-color:rgba(42,108,49,.32);
  text-shadow:0 1px 0 rgba(30,60,28,.22);
}
#playBtn:hover{ background-color:#458f54; }
#tutorialBtn{
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='t'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23t)' opacity='0.5'/></svg>"),
    #f2e9cd;
  background-blend-mode:overlay;
  color:#5f5340;
  border-color:rgba(139,122,84,.3);
}
#tutorialBtn:hover{ background-color:#eee2c2; }
.btn-label-text{
  position:relative;
  z-index:3;
  pointer-events:none;
}
/* Bank picker */
.bank-group{ max-width:520px; margin:0 auto 22px; }
.bank-group-head{ font-family:var(--serif,serif); font-weight:700; font-size:1.05rem; color:var(--ink,#26303b); margin:0 0 9px; display:flex; align-items:baseline; gap:8px; }
.bank-group-head .bank-count{ font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.1em; text-transform:uppercase; color:#8a7f63; font-weight:700; }
.bank-levels{ display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:9px; }
.bank-lot{ display:flex; flex-direction:column; gap:3px; text-align:left; padding:11px 12px; border-radius:11px; border:1px solid #c8bda0; background:#fbf6ea; cursor:pointer; font-family:inherit; transition:transform .1s, border-color .15s, box-shadow .15s; }
.bank-lot:active{ transform:translateY(1px); }
.bank-lot:hover{ border-color:#4a90e2; box-shadow:0 2px 8px rgba(40,80,140,.1); }
.bank-lot .bl-name{ font-weight:650; font-size:.92rem; color:var(--ink,#26303b); }
.bank-lot .bl-meta{ font-family:var(--mono,monospace); font-size:.6rem; color:#8a7f63; letter-spacing:.03em; }
.bank-lot .bl-stars{ font-size:.8rem; color:#e3b23c; letter-spacing:1px; margin-top:2px; }
.bank-lot .bl-stars.beat{ color:#d8a33a; font-weight:700; }
.btn.big{font-size:.9rem; padding:15px 22px; width:100%; border-radius:999px;}
.btn.emerald{
  --button-line:rgba(42,108,49,.72);
  --button-tick:rgba(31,87,38,.34);
  background:
    radial-gradient(ellipse at 28% 24%, rgba(255,255,255,.09) 0 28%, transparent 62%),
    radial-gradient(ellipse at 78% 80%, rgba(45,120,52,.08) 0 44%, transparent 72%),
    #43a253;
  background-blend-mode:normal,normal,normal;
  color:#fffaf1;
  border-color:rgba(42,108,49,.30);
  text-shadow:0 1px 0 rgba(45,80,42,.18);
  box-shadow:0 1px 2px rgba(48,82,43,.16);
}
.btn.emerald:hover{
  background:
    radial-gradient(ellipse at 28% 24%, rgba(255,255,255,.12) 0 34%, transparent 64%),
    radial-gradient(ellipse at 78% 80%, rgba(45,120,52,.09) 0 44%, transparent 72%),
    #46a858;
  background-blend-mode:normal,normal,normal;
}
.btn.ghost{background:transparent; border-color:#b3a888; color:#6a5f49; width:100%;}
.btn.ghost:hover{background:rgba(255,255,255,.4);}
.title-actions .btn.big,
.title-audio-row .btn{
  --sketch-tilt:-.44deg;
  --button-tick:rgba(76,66,48,.34);
}
.title-actions .btn.big::before,
.title-audio-row .btn::before{
  inset:-2px;
  border-width:2px;
  opacity:.94;
  box-shadow:
    1px .5px 0 rgba(83,73,54,.18),
    -1px -.5px 0 rgba(255,250,235,.28);
}
.title-actions .btn.big::after,
.title-audio-row .btn::after{
  inset:-6px 18px;
  opacity:.5;
  background:
    linear-gradient(90deg, transparent 0 5%, var(--button-tick) 5% 18%, transparent 18% 42%, var(--button-tick) 42% 47%, transparent 47% 72%, var(--button-tick) 72% 86%, transparent 86%) top/100% 1px no-repeat,
    linear-gradient(90deg, var(--button-tick) 0 10%, transparent 10% 28%, var(--button-tick) 28% 36%, transparent 36% 64%, var(--button-tick) 64% 74%, transparent 74% 100%) bottom/100% 1px no-repeat;
}
.title-actions .btn.big:hover::after,
.title-audio-row .btn:hover::after{ opacity:.68; }
.btn.link{background:none; border:0; box-shadow:none; color:var(--muted); text-transform:none; letter-spacing:.04em; font-weight:800; font-size:.72rem; margin-top:20px; cursor:pointer;}
.btn.link:hover{color:var(--ink);}
.title-audio-row{display:flex;gap:11px;width:min(260px,80vw);}
.btn.title-audio{
  flex:1; font-size:.68rem; padding:10px 8px; border-radius:999px;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='t'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23t)' opacity='0.5'/></svg>"),
    #efe6cc;
  background-blend-mode:overlay;
  border-color:rgba(139,122,84,.28); color:#6a5f49;
  letter-spacing:.06em;
}
.btn.title-audio.on{
  color:var(--good); border-color:rgba(63,155,79,.55);
  --button-line:rgba(63,155,79,.60);
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='t'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23t)' opacity='0.5'/></svg>"),
    #dcecd6;
  background-blend-mode:overlay;
}

/* ===== map ===== */
#mapScreen{padding:0;}
.map-head{position:relative; display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:calc(12px + env(safe-area-inset-top)) 14px 11px; background:#e9e2cf; border-bottom:1.5px solid #b9ad8e;}
.map-title{
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  z-index:1;
  font-family:var(--serif); font-weight:600; font-size:1.05rem; color:var(--ink);
  text-align:center;
  max-width:min(46vw,300px);
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.district-title-btn{
  appearance:none;border:0;background:transparent;margin:0;padding:4px 9px;border-radius:999px;
  cursor:pointer; line-height:1.1; max-width:min(42vw,260px); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.district-title-btn:hover,.district-title-btn[aria-expanded="true"]{background:rgba(255,250,238,.55); box-shadow:inset 0 0 0 1px rgba(150,135,100,.22);}
.district-picker{
  position:absolute; left:50%; top:calc(100% - 4px); transform:translateX(-50%);
  width:min(330px,86vw); max-height:min(420px,58vh); overflow:auto; z-index:30;
  padding:8px; border:1.5px solid #c4b896; border-radius:18px; background:rgba(249,244,232,.98);
  box-shadow:0 14px 36px rgba(70,55,30,.20), inset 0 0 0 1px rgba(255,255,255,.55);
}
.district-picker[hidden]{display:none;}
.district-picker-row{
  width:100%; border:0; background:transparent; color:var(--ink); text-align:left; border-radius:12px;
  padding:8px 10px; display:flex; align-items:center; justify-content:space-between; gap:10px; cursor:pointer;
  font-family:var(--sans); font-weight:800; letter-spacing:.02em;
}
.district-picker-row:hover{background:rgba(225,214,184,.55);}
.district-picker-row.current{background:rgba(186,211,166,.48); color:#365e36;}
.map-rep{font-family:var(--serif); font-size:.78rem; color:var(--map-star); letter-spacing:.04em; display:flex; align-items:center; gap:4px; justify-content:flex-end; margin-left:auto; position:relative; z-index:2;}
.map-star-summary{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;}
.map-star-count{font-variant-numeric:tabular-nums; font-weight:800;}
.map-of{font-size:.68em;font-weight:700;letter-spacing:.03em;color:#6f6654;}
.map-crown{color:var(--map-acorn);filter:drop-shadow(0 1px 2px rgba(130,75,48,.18));}
.map-crown-badge{
  display:inline-flex;align-items:center;gap:3px;margin-left:4px;
  color:#70874e;font-family:var(--sans);font-size:.72rem;font-weight:900;
  padding:2px 7px;border-radius:999px;background:rgba(250,238,197,.74);
  border:1px solid rgba(207,161,75,.72);
  box-shadow:0 1px 4px rgba(125,98,44,.16), inset 0 0 0 1px rgba(255,255,255,.42);
}
.map-body{flex:1; min-height:0; overflow:auto; padding:20px 16px; display:flex; align-items:center; justify-content:center;}
.map-body.district-body{position:relative; align-items:center; justify-content:center; flex-direction:column; padding-bottom:12px;}
.district-stack{display:flex; flex-direction:column; align-items:center; gap:8px;}
.map-canvas{
  position:relative; width:min(440px,94vw); aspect-ratio:3/4;
  background:radial-gradient(circle at 50% 45%, #f6f1e4 0%, #ece4d2 100%);
  border:1.5px solid #c4b896; border-radius:8px;
  box-shadow:inset 0 0 50px rgba(120,100,60,.12);
  overflow:hidden;
}
.map-canvas.tutorial-complete-warm{
  box-shadow:inset 0 0 58px rgba(218,165,58,.28), 0 0 0 2px rgba(214,164,54,.34), 0 12px 34px rgba(116,84,28,.18);
  transition:box-shadow .75s ease;
}
.tutorial-gold-wipe{
  position:absolute; top:-20%; bottom:-20%; left:-48%; width:40%; z-index:12; pointer-events:none;
  background:linear-gradient(105deg,rgba(255,239,184,0),rgba(255,226,126,.76),rgba(255,239,184,0));
  filter:blur(2px); transform:skewX(-12deg);
  animation:tutorialGoldWipe 1.45s cubic-bezier(.4,0,.25,1) forwards;
}
@keyframes tutorialGoldWipe{ from{ left:-48%; } to{ left:118%; } }
/* hand-drawn connecting path between nodes */
.map-canvas svg.map-links{position:absolute; inset:0; width:100%; height:100%; pointer-events:none;}
/* ---- District View: a zoomed-out parcel grid with viable-site markers ---- */
.district-canvas{
  position:relative; width:min(440px,94vw); aspect-ratio:3/4;
  background:radial-gradient(circle at 50% 45%, #f6f1e4 0%, #ece4d2 100%);
  border:1.5px solid #c4b896; border-radius:8px;
  box-shadow:inset 0 0 50px rgba(120,100,60,.12);
  overflow:hidden;
}
.district-canvas::after{
  content:""; position:absolute; inset:0; z-index:6; pointer-events:none;
  background:radial-gradient(120% 95% at 50% 40%, rgba(255,235,168,0) 35%, rgba(226,178,72,.25) 100%);
  opacity:0; transition:opacity .7s ease;
}
.district-canvas.district-complete::after{ opacity:1; animation:districtGoldSettle 1.7s ease-out both; }
@keyframes districtGoldSettle{
  0%{ opacity:0; filter:brightness(1); }
  42%{ opacity:.72; filter:brightness(1.12); }
  100%{ opacity:1; filter:brightness(1); }
}
/* Brighter/whiter than the .42-opacity cream used for done/submitted/draft —
   this is the "come tap me, this site is open" state, so it should read as
   the lightest, most inviting cell on the map, not just another status tier. */
.map-parcel-slot{
  position:absolute; box-sizing:border-box; z-index:2;
  border:none; border-radius:2px;
  background:rgba(255,252,240,.55);
  cursor:pointer; -webkit-tap-highlight-color:transparent;
  transform:none;
  box-shadow:0 0 0 1px rgba(255,255,255,.22) inset;
}
/* Inset outline so adjacent parcel borders don't stack into thick corners.
   Solid by default — this is the "come tap me, this site is open" state, so
   it needs to read as a site card, not a zoning line. A green dashed line at
   rest blended into the map's own grass/wetland patches and looked like a
   map artifact rather than an invitation. Dashed is now reserved for .draft
   below (a provisional, in-progress state), so the line style itself carries
   meaning instead of every status using the same dash. (A resting green
   glow was tried here too and dropped — didn't match the game's style; the
   brighter cell background above carries the "open" signal instead.) */
.map-parcel-slot::before{
  content:""; position:absolute; inset:1px; border-radius:1px; pointer-events:none;
  border:2.5px solid #4f7f4d;
}
/* Amber for the interactive response rather than a brighter green — with the
   resting border already solid moss, a green hover would barely read as a
   change ("green fighting green"). */
.map-parcel-slot:hover{ background:rgba(255,248,225,.55); box-shadow:0 0 0 2px rgba(213,154,64,.18), 0 0 12px rgba(213,154,64,.18); }
.map-parcel-slot:hover::before{ border-style:solid; border-color:#c58a38; }
.map-parcel-slot.done,
.map-parcel-slot.submitted,
.map-parcel-slot.draft{ background:rgba(246,241,227,.55); overflow:hidden; }
.district-canvas .map-parcel-slot.done,
.district-canvas .map-parcel-slot.submitted,
.district-canvas .map-parcel-slot.draft{ overflow:visible; }
.map-parcel-slot.done::before{ border-style:solid; border-color:#5b8f54; box-shadow:none; }
.map-parcel-slot.submitted::before{ border-style:solid; border-color:#789661; box-shadow:none; }
.map-parcel-slot.draft::before{ border-style:dashed; border-color:rgba(83,126,71,.56); box-shadow:none; }
.map-parcel-slot.locked::before{ border-color:#b3a888; box-shadow:none; }
.map-parcel-slot.locked{ cursor:not-allowed; background:rgba(230,223,205,.55); }
.map-parcel-slot .parcel-lv{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-family:var(--serif); font-weight:700; font-size:.95rem; color:var(--ink); pointer-events:none;
}
.map-parcel-slot .parcel-lv.parcel-name{
  font-size:.48rem; line-height:1.15; padding:0 2px; text-align:center;
  text-transform:none; letter-spacing:.02em; font-family:var(--sans); font-weight:800;
}
.map-head-actions{ display:flex; align-items:center; gap:8px; }
.map-head-actions .btn.ghost{ font-size:.62rem; padding:7px 11px; border-radius:999px; white-space:nowrap; }

.map-parcel-slot .vs-thumb{ position:absolute; inset:2px; border-radius:1px; overflow:hidden; pointer-events:none; display:flex; align-items:center; justify-content:center; }
.map-parcel-slot .vs-thumb svg{ width:100%; height:100%; display:block; object-fit:contain; }
.map-parcel-slot.done .vs-thumb svg{ filter:saturate(.52) brightness(1.06); opacity:.82; }
.map-parcel-slot.submitted .vs-thumb svg{ filter:saturate(.38) brightness(1.08); opacity:.68; }
.map-parcel-slot.draft .vs-thumb svg{ filter:saturate(.24) brightness(1.12); opacity:.52; }
.map-node{
  position:absolute; z-index:3; cursor:pointer;
}
@keyframes bounceDown{
  0%,100%{ transform:translateX(-50%) translateY(0); }
  50%{ transform:translateX(-50%) translateY(5px); }
}
.map-pointer{
  position:absolute; left:50%; top:-14px; transform:translateX(-50%);
  font-size:1rem; line-height:1; color:var(--good);
  text-shadow:0 1px 0 rgba(255,255,255,.65), 0 2px 8px rgba(63,155,79,.35);
  pointer-events:none; z-index:4;
  animation:bounceDown 1.1s ease-in-out infinite;
}
.map-parcel-slot .lock-icon{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:24px; height:24px; opacity:.72; pointer-events:none;
}
/* Survey-benchmark mark on an open, untouched plat — echoes the parcel's own
   moss border color so it reads as "this site's reference point," not a
   separate decoration. */
.map-parcel-slot .parcel-benchmark{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  color:#4f7f4d; opacity:.5; pointer-events:none;
}
.map-parcel-slot .parcel-stars{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:1px;
  font-size:.62rem; color:var(--map-star); pointer-events:none; opacity:0; transition:opacity .35s ease;
}
.map-canvas .map-parcel-slot.done .parcel-stars,
.district-canvas .map-parcel-slot.done .parcel-stars{
  inset:auto auto auto 50%;
  top:calc(100% + 3px);
  transform:translateX(-50%);
  z-index:5;
  padding:1px 4px;
  border-radius:999px;
  background:rgba(250,247,238,.84);
  box-shadow:0 1px 3px rgba(80,65,40,.14);
  text-shadow:0 1px 0 rgba(255,255,255,.7);
  white-space:nowrap;
}
/* Simple round pips at this scale — the leaf/acorn shapes read fine as one big
   icon (see .star-row/.rating-branch-svg on the approval card) but turn into
   illegible noise once you're looking at a whole district's worth of tiny
   per-site indicators at once. Dots stay readable at any size. */
.parcel-leaf,
.parcel-acorn{
  display:inline-block;
  width:6px;
  height:6px;
  border-radius:50%;
  flex:0 0 auto;
  background:rgba(96,128,73,.28);
  border:1px solid rgba(96,128,73,.4);
}
.parcel-leaf.on{
  background:rgba(96,128,73,.92);
  border-color:rgba(66,96,50,.8);
}
.parcel-acorn{
  margin-left:2px;
  background:rgba(184,110,56,.92);
  border-color:rgba(104,74,46,.7);
}
.map-canvas .map-parcel-slot.stars-above .parcel-stars,
.district-canvas .map-parcel-slot.stars-above .parcel-stars{
  top:auto;
  bottom:calc(100% + 3px);
}
.map-parcel-slot.show-stars .parcel-stars{ opacity:1; }
.map-rep, .map-rep .map-star-count{ cursor:pointer; }
.district-nav-row{
  display:flex; align-items:center; justify-content:center; gap:10px; width:min(520px,96vw);
}
.district-nav-row .district-canvas{ flex:1 1 auto; width:auto; min-width:0; max-width:min(440px,72vw); }
/* 48px square rather than min-width:44px + text padding — at the old size
   these read as small punctuation marks, not page-turn buttons. Background
   opacity and border bumped up to actually show as a cream pill at rest,
   not just on interaction. */
.district-nav-btn{
  position:relative;
  isolation:isolate;
  --button-line:var(--ui-ink-line);
  --button-tick:rgba(83,73,54,.18);
  flex:0 0 auto; font-size:1.1rem; border-radius:999px;
  width:48px; height:48px;
  display:inline-flex; align-items:center; justify-content:center;
  background:
    radial-gradient(ellipse at 24% 22%, rgba(255,255,255,.28) 0 30%, transparent 64%),
    linear-gradient(180deg, rgba(255,248,233,.86), rgba(244,236,214,.86));
  background-blend-mode:normal,normal;
  border:1.5px solid rgba(139,122,84,.48); color:#5f5340;
  box-shadow:0 1px 2px rgba(70,55,30,.08);
  line-height:1;
}
.district-nav-btn::before{
  content:""; position:absolute; inset:-1px; border-radius:inherit; pointer-events:none;
  z-index:2;
  border:1.4px solid var(--button-line);
  transform:rotate(var(--sketch-tilt,.16deg));
  opacity:.76;
}
.district-nav-btn:disabled{ opacity:.35; cursor:not-allowed; }
.district-nav-btn.nav-hidden{ visibility:hidden; pointer-events:none; }
.district-nav-btn.next-ready{
  --button-line:rgba(63,155,79,.62);
  color:var(--good); border-color:rgba(63,155,79,.62);
  background:
    radial-gradient(ellipse at 50% 50%, rgba(132,188,112,.16) 0 54%, transparent 74%),
    linear-gradient(180deg, rgba(236,247,226,.94), rgba(221,238,204,.94));
  background-blend-mode:normal,normal;
  animation:nextDistrictGlow 2.2s ease-in-out infinite;
}
@keyframes nextDistrictGlow{
  0%,100%{ box-shadow:0 1px 2px rgba(70,55,30,.08); }
  50%{ box-shadow:0 0 0 5px rgba(132,188,112,.10), 0 1px 2px rgba(70,55,30,.08); }
}
.share-button{
  position:relative;
  isolation:isolate;
  --button-line:var(--ui-ink-line);
  --button-tick:rgba(83,73,54,.20);
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  min-height:42px; padding:10px 18px; border-radius:999px;
  border:1px solid rgba(139,122,84,.28);
  background:
    radial-gradient(ellipse at 24% 22%, rgba(255,255,255,.34) 0 30%, transparent 64%),
    linear-gradient(180deg, rgba(255,249,235,.96), rgba(248,241,222,.96));
  background-blend-mode:normal,normal;
  color:#514936;
  font-family:var(--sans); font-size:.68rem; font-weight:800;
  letter-spacing:.07em; text-transform:uppercase;
  box-shadow:0 1px 2px rgba(70,55,30,.10); cursor:pointer;
  transition:opacity .3s ease, transform .3s ease, background .2s ease;
}
.share-button::before{
  content:""; position:absolute; inset:-1px; border-radius:inherit; pointer-events:none;
  z-index:2;
  border:1.45px solid var(--button-line);
  transform:rotate(var(--sketch-tilt,-.14deg));
  opacity:.82;
}
.share-button::after{
  content:""; position:absolute; inset:5px 12px; border-radius:inherit; pointer-events:none;
  z-index:1;
  background:
    linear-gradient(90deg, var(--button-tick) 0 9px, transparent 9px calc(100% - 9px), var(--button-tick) calc(100% - 9px)) top/100% 1px no-repeat,
    linear-gradient(90deg, transparent 0 22%, var(--button-tick) 22% 29%, transparent 29% 70%, var(--button-tick) 70% 78%, transparent 78%) bottom/100% 1px no-repeat,
    transparent;
  background-blend-mode:normal,normal,normal;
  opacity:.26; transition:opacity .18s ease;
}
.share-button:hover{ background:#fffaf0; transform:translateY(-1px); box-shadow:0 0 0 4px var(--ui-bleed), 0 1px 2px rgba(70,55,30,.10); }
.share-button:hover::after{ opacity:.4; }
.share-button svg{ flex:0 0 auto; }
.share-button[hidden]{ display:none !important; }
.district-share-button{
  position:absolute; left:50%; bottom:18px; z-index:8;
  margin:0; transform:translateX(-50%); white-space:nowrap;
}
.district-share-button:hover{ transform:translate(-50%,-1px); }
@media (prefers-reduced-motion: no-preference){
  /* tutorial town: all nodes visible immediately */
  #mapScreen.show .map-canvas{ animation:none; opacity:1; transform:none; }
  #mapScreen.show .map-links path{ opacity:var(--op,.9); animation:none; }
  #mapScreen.show .map-node{ animation:none; opacity:1; transform:none; }
  @keyframes nodePop{ from{opacity:0; transform:translate(-50%,-50%) scale(.4);} to{opacity:1; transform:translate(-50%,-50%) scale(1);} }
}
.map-parcel-label{
  position:absolute; left:50%; top:calc(100% + 3px); transform:translateX(-50%);
  font-size:.56rem; font-weight:700; text-transform:uppercase; letter-spacing:.08em;
  color:#6a5f49; max-width:84px; text-align:center; line-height:1.2; pointer-events:none;
}
.map-node .map-parcel-slot{ inset:0; width:auto; height:auto; }
.map-node.locked .map-parcel-slot{ cursor:not-allowed; }
#req-road,#req-trail,#req-sf,#req-park{ display:none !important; }

/* howto modal list */
.howto-step{display:flex; gap:10px; align-items:flex-start; margin-top:9px; font-size:.78rem; line-height:1.42;}
.howto-num{flex:0 0 auto; width:20px; height:20px; border-radius:50%; background:var(--accent); color:#fbf3e6; font-size:.62rem; font-weight:700; text-align:center; line-height:20px; font-family:var(--sans);}
*{box-sizing:border-box;margin:0;padding:0;font-family:var(--sans);}
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);color:var(--text);}
body{
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='t'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23t)' opacity='0.09'/></svg>"),
    radial-gradient(circle at 22% 10%, rgba(255,250,235,.5), transparent 42%),
    radial-gradient(circle at 84% 88%, rgba(120,100,60,.18), transparent 55%),
    var(--bg);
}
.app{
  height:100dvh;
  width:100vw;
  max-width:980px;        /* expand on web */
  margin:0 auto;
  position:relative;      /* anchor the absolute objective overlay */
  display:grid;
  grid-template-rows:auto minmax(0,1fr) auto;  /* topbar · board · tray */
  background:rgba(246,237,216,.06);
  overflow:hidden;
  --topbar-h:48px;
}
/* Full-bleed flat bar by default, matching the bottom tool tray's own
   treatment (edge-to-edge, single border line, no pill) — this is what
   actually ships to real devices, which are narrow. The rounded-pill
   look is reserved for the ≥768px "desktop preview frame" below, where
   there's enough width for the drawer to visibly nest between the pill's
   rounded ends instead of looking like a mismatched width overhang. */
.topbar{
  margin:calc(4px + env(safe-area-inset-top)) 0 0;
  padding:6px 10px 6px;
  display:grid;
  grid-template-columns:1fr auto 1fr;
  align-items:center;
  gap:8px;
  background:rgba(233,226,207,.94);
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  border-bottom:1.5px solid rgba(185,173,142,.85);
  box-shadow:0 3px 10px rgba(80,65,40,.14);
  position:relative; z-index:60;
}
.kicker{font-size:.46rem;font-weight:700;text-transform:uppercase;letter-spacing:.24em;color:var(--accent);display:flex;align-items:center;gap:5px;}
.kicker::before{
  content:"";
  width:7px;height:9px;
  background:var(--accent);
  clip-path:polygon(0 0, 100% 28%, 0 56%, 0 100%, 0 0);
  box-shadow:inset 0 0 0 4px var(--accent);
}
.title{font-family:var(--serif);font-weight:700;font-size:1.05rem;letter-spacing:.01em;white-space:nowrap;color:var(--ink);}
.actions{display:flex;gap:8px;align-items:center;}
.btn{
  position:relative;
  isolation:isolate;
  --button-line:var(--ui-ink-line);
  --button-tick:rgba(83,73,54,.20);
  border:1px solid rgba(139,122,84,.24);
  background:
    radial-gradient(ellipse at 24% 22%, rgba(255,255,255,.32) 0 30%, transparent 64%),
    linear-gradient(180deg, rgba(255,248,233,.96), rgba(248,240,219,.96));
  background-blend-mode:normal,normal;
  color:var(--ink);
  font-weight:800;
  font-size:.72rem;
  text-transform:uppercase;
  letter-spacing:.1em;
  padding:10px 16px;
  border-radius:10px 9px 11px 8px;
  box-shadow:0 1px 2px rgba(70,55,30,.10);
  cursor:pointer;
  transition:background .14s, transform .1s, box-shadow .14s, color .14s;
  -webkit-tap-highlight-color: transparent;
}
.btn{mix-blend-mode:normal;}
.btn:not(.link)::before{
  content:""; position:absolute; inset:-1px; border-radius:inherit; pointer-events:none;
  z-index:2;
  border:1.45px solid var(--button-line);
  transform:rotate(var(--sketch-tilt,-.12deg));
  opacity:.82;
}
.btn:not(.link)::after{
  content:""; position:absolute; inset:5px 10px; border-radius:inherit; pointer-events:none;
  z-index:1;
  background:
    linear-gradient(90deg, var(--button-tick) 0 8px, transparent 8px calc(100% - 8px), var(--button-tick) calc(100% - 8px)) top/100% 1px no-repeat,
    linear-gradient(90deg, transparent 0 18%, var(--button-tick) 18% 25%, transparent 25% 72%, var(--button-tick) 72% 80%, transparent 80%) bottom/100% 1px no-repeat,
    transparent;
  background-blend-mode:normal,normal,normal;
  opacity:.24; transition:opacity .18s ease;
}
.btn:hover{
  background:
    radial-gradient(ellipse at 24% 22%, rgba(255,255,255,.38) 0 30%, transparent 64%),
    linear-gradient(180deg, rgba(255,251,240,.98), rgba(250,243,224,.96));
  box-shadow:0 0 0 4px rgba(132,188,112,.08), 0 1px 2px rgba(70,55,30,.10);
}
.btn:hover::after{ opacity:.38; }
.btn:active{transform:translateY(1px);background:#f2e8cf; box-shadow:0 1px 1px rgba(70,55,30,.12);}
.btn.primary{
  --button-line:rgba(143,70,43,.72);
  --button-tick:rgba(92,42,27,.24);
  background:
    radial-gradient(ellipse at 22% 24%, rgba(255,232,196,.18) 0 34%, transparent 64%),
    linear-gradient(180deg, #ea7647 0%, var(--accent) 100%);
  background-blend-mode:normal,normal;
  color:#fffaf1;
  border-color:rgba(157,74,45,.28);
  box-shadow:0 1px 2px rgba(139,72,43,.16);
}
.btn.primary:hover{background:radial-gradient(ellipse at 22% 24%, rgba(255,232,196,.2) 0 34%, transparent 64%), linear-gradient(180deg, #f08351 0%, #e96538 100%); background-blend-mode:normal,normal;}
.btn.primary:active{background:linear-gradient(180deg, #df6d42 0%, #cf582e 100%);}
.btn.dark{background:linear-gradient(180deg, rgba(250,242,223,.96), rgba(242,233,208,.96)); border-radius:999px;}
/* requirement chip beneath each tool button (progressive disclosure) */
.tool-req{
  font-family:var(--mono);
  font-size:.5rem;
  font-weight:800;
  letter-spacing:.04em;
  margin-top:2px;
  min-height:.7rem;
  color:#8a7c61;
  font-variant-numeric:tabular-nums;
  transition:color .2s;
}
.tool-req.met{ color:var(--good); }
.tool-req.met::after{ content:" ✓"; }
.tool.active .tool-req{ color:var(--ink); }
.tool.active .tool-req.met{ color:var(--good); }
/* clean top bar — sits above the drawer so the accordion tucks under it */
.topbar-center{ grid-column:2; display:flex; flex-direction:column; align-items:center; gap:1px; min-width:0; max-width:min(60vw, 340px); justify-self:center; }
.topbar-title{ width:100%; text-align:center; font-family:var(--serif); font-weight:700; font-size:1.05rem; letter-spacing:.01em; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.topbar-sub{
  display:flex; align-items:center; justify-content:center; gap:10px;
  font-family:var(--mono); font-size:.58rem; letter-spacing:.06em; text-transform:uppercase;
  color:#8a7f63; font-weight:800;
}
.hud-metric{
  display:grid; grid-template-rows:auto 6px; gap:2px; min-width:92px;
}
.hud-metric-head{ display:flex; align-items:baseline; justify-content:space-between; gap:7px; }
/* Own explicit size/tracking rather than inheriting .topbar-sub's — the
   mobile override used to drop this to .48rem (7.68px), too small to read
   comfortably; pinned to 9.6px everywhere and a narrower, more legible
   tracking than the wide mono-font default. */
.hud-label{ color:#8a7f63; font-size:.6rem; letter-spacing:.06em; }
.hud-numbers{ display:inline-flex; align-items:baseline; gap:3px; white-space:nowrap; }
.hud-numbers b{ color:var(--ink); font-weight:900; font-size:.92rem; transition:color .2s, transform .2s; }
.hud-numbers .hud-target{ font-size:.72rem; color:#7f735d; }
.hud-of{ font-size:.48rem; opacity:.72; letter-spacing:.04em; text-transform:none; }
.hud-bar-row{ display:flex; align-items:center; gap:4px; min-width:0; }
.hud-bar{
  display:block; flex:1 1 auto; min-width:0; height:5px; border-radius:999px; overflow:hidden;
  background:rgba(70,60,40,.10);
  box-shadow:inset 0 0 0 1px rgba(70,60,40,.06);
}
.hud-fill{
  display:block; height:100%; width:0%; border-radius:999px;
  transition:width .28s ease;
}
.hud-fill-homes{
  background:
    linear-gradient(90deg,
      #d85e43 0%,
      #e98a43 24%,
      #e6b94d 44%,
      #5aae91 66%,
      #3f8fc2 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28);
}
.hud-fill-parks{
  background:
    linear-gradient(90deg, rgba(95,142,67,.88), rgba(135,184,92,.92) 58%, rgba(180,203,124,.9));
}
.topbar-sub .ga-homes.met b,
.topbar-sub .ga-parks.met b{ color:#4f7a43; }
.topbar-sub .ga-homes.over b,
.topbar-sub .ga-parks.over b{ transform:scale(1.08); }
.topbar-sub .hud-metric.met .hud-of,
.topbar-sub .hud-metric.met .hud-target{ display:none; }
.topbar-sub .hud-metric.met .park-target-wrap{ gap:2px; }
.topbar-sub .hud-metric.met .park-pips{ display:none; }
.topbar-sub .goal-check{
  display:none; margin-right:2px; color:#4f7a43; font-weight:900;
}
.topbar-sub .met .goal-check{ display:inline; }
.hud-bonus{
  display:none; flex:0 0 auto; min-width:18px; height:16px; padding:0 5px; margin-left:3px;
  border-radius:5px;
  align-items:center; justify-content:center;
  background:#d9a139;
  color:#fff9e8;
  font-family:var(--sans); font-size:.54rem; font-weight:900; line-height:16px;
  box-shadow:0 1px 3px rgba(120,80,20,.22);
}
.hud-bonus.show{ display:inline-flex; }
.park-target-wrap{
  position:relative; display:inline-flex; align-items:center; gap:3px;
  margin-left:1px; padding-right:1px;
}
.park-pips{
  display:inline-flex; align-items:center; gap:3px; height:12px; margin-left:3px;
}
.park-pips i{
  display:block; width:3px; height:11px; border-radius:999px;
  background:rgba(255,255,255,.22);
  box-shadow:inset 0 0 0 1.25px rgba(70,152,184,.34);
  transform:rotate(11deg) skewX(-5deg);
  transition:background .22s ease, transform .22s ease, box-shadow .22s ease, opacity .22s ease;
}
.park-pips i.on{
  background:linear-gradient(180deg,#8ed7e3,#4baec9);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.42);
  transform:translateY(-.5px) rotate(11deg) skewX(-5deg);
}
.park-target-plus{
  position:absolute; right:-7px; top:-8px; transform:translate(0,0) scale(.7);
  color:#8a6038; font-family:var(--sans); font-size:.62rem; font-weight:900;
  opacity:0; pointer-events:none;
  text-shadow:0 1px 3px #fff8e9, 0 -1px 3px #fff8e9;
}
.park-target-wrap.pop .park-target-plus{ animation:parkTargetPlus 1.15s cubic-bezier(.22,1,.36,1) forwards; }
.park-target-wrap.pop .hud-target{ animation:parkTargetBump .42s ease-out; }
@keyframes parkTargetPlus{
  0%{ opacity:0; transform:translate(0,0) scale(.65); }
  18%{ opacity:1; transform:translate(0,-9px) scale(1.15); }
  72%{ opacity:1; transform:translate(0,-15px) scale(1); }
  100%{ opacity:0; transform:translate(0,-23px) scale(.82); }
}
@keyframes parkTargetBump{
  0%,100%{ transform:scale(1); }
  45%{ transform:scale(1.22); }
}
.topbar-sub .ga-code{ margin-left:4px; opacity:.6; letter-spacing:.12em; font-size:.56rem; }
.topbar-sub .ga-code:empty{ display:none; }
.back-btn{ grid-column:1; justify-self:start; }
.topbar .actions{ grid-column:3; justify-self:end; }
/* objective drawer drops OVER the board, anchored to the viewport below the measured topbar. */
.objective-overlay{
  position:fixed; top:var(--topbar-bottom, calc(env(safe-area-inset-top, 0px) + 56px)); left:0; right:0; z-index:50;
  pointer-events:none;
}
/* the drawer body lives in a grid-clip so it genuinely collapses (height 0) when closed,
   keeping the tab — which sits below it — flush under the topbar */
.drawer-clip{
  margin:0 auto; width:100%;
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .42s cubic-bezier(.4,0,.15,1);
}
.drawer-clip.open{ grid-template-rows:1fr; }
.objective-slider{
  overflow:hidden;        /* required for the 0fr collapse */
  display:flex; flex-direction:column; align-items:center;
}
.objective-drawer{
  pointer-events:auto; width:100%; box-sizing:border-box;
  background:linear-gradient(#fbf7ec, #f3ecda);
  border-bottom:1.5px solid rgba(185,173,142,.7);
  box-shadow:0 8px 16px rgba(80,65,40,.16);
  padding:12px 16px 14px;
  border-radius:0 0 16px 16px;   /* round the drawer bottom to echo the topbar pill */
}
/* tab is OUTSIDE the clip — always visible, peeking just under the topbar */
.objective-tab{
  pointer-events:auto; position:relative; z-index:2;
  display:flex; align-items:center; justify-content:center; gap:5px;
  margin:-1px auto 0;
  background:rgba(233,226,207,.97);
  border:1.5px solid rgba(185,173,142,.85); border-top:none;
  border-radius:0 0 12px 12px; padding:4px 22px 5px; cursor:pointer;
  box-shadow:0 5px 9px rgba(80,65,40,.16); -webkit-tap-highlight-color:transparent;
  transition:background .15s;
}
.objective-tab:hover{ background:rgba(240,233,214,1); }
.objective-tab .ot-chev{ font-size:.7rem; line-height:1; color:var(--accent); font-weight:800; transition:transform .3s ease; }
.drawer-clip.open ~ .objective-tab .ot-chev{ transform:rotate(180deg); }
.objective-drawer .od-head{ display:flex; align-items:baseline; justify-content:space-between; gap:8px; margin-bottom:5px; }
.objective-drawer .od-title{ font-family:var(--serif); font-weight:700; font-size:1rem; color:var(--ink); }
.objective-drawer .od-level{ font-family:var(--mono); color:var(--accent); font-size:.52rem; letter-spacing:.16em; font-weight:700; text-transform:uppercase; }
.objective-drawer .od-body{ font-family:var(--serif); font-style:italic; color:#5a5141; font-size:.84rem; line-height:1.4; }
.objective-drawer .od-rules{ display:inline-block; margin-top:9px; font-family:var(--sans); font-style:normal; font-size:.6rem; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:var(--accent); cursor:pointer; }
.objective-drawer .od-meta{
  margin-top:8px;
  padding-top:6px;
  border-top:1px solid rgba(73,61,42,.12);
  font-family:var(--mono);
  font-size:.49rem;
  line-height:1.35;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:rgba(73,61,42,.42);
  overflow-wrap:anywhere;
}
.park-progress-ring{ position:relative; display:inline-grid; place-items:center; flex:0 0 auto; width:30px; height:30px; }
.park-progress-ring svg{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; transform:rotate(-90deg); }
.park-ring-track,.park-ring-fill{ fill:none; stroke-width:2.6; }
.park-ring-track{ stroke:rgba(255,255,255,.45); }
.park-ring-fill{ stroke:#f2cf61; stroke-linecap:round; stroke-dasharray:1; stroke-dashoffset:1; transition:stroke-dashoffset .32s ease; }
.park-ring-number{ position:relative; z-index:1; font-family:var(--sans); font-size:.62rem; font-weight:900; line-height:1; color:#fff; font-variant-numeric:tabular-nums; }
/* settings row inside the drawer (grid / sound / music) */
.od-settings{ display:flex; gap:5px; margin-top:8px; padding-top:8px; border-top:1px dashed rgba(150,135,100,.35); flex-wrap:wrap; }
/* Was .54rem (8.64px) — genuinely too small for a tap label. Bumped toward
   10px and given a touch-target-appropriate min-height to match. */
.od-toggle{
  flex:1 1 72px; min-width:0; min-height:34px;
  display:flex; align-items:center; justify-content:center; gap:4px;
  font-family:var(--sans); font-size:.64rem; font-weight:800; letter-spacing:.03em; text-transform:uppercase;
  padding:8px 6px; border-radius:8px; cursor:pointer;
  background:#fbf7ec; border:1.5px solid rgba(185,173,142,.7); color:#6f634d;
  -webkit-tap-highlight-color:transparent; transition:background .15s, color .15s, border-color .15s;
}
/* var(--good) (#3f9b4f) on this background was ~2.5:1 contrast — a real fail
   for text this small (needs 4.5:1). Darkened just the toggle's own text/dot
   color rather than touching --good itself, which is used elsewhere at sizes
   where it already reads fine. */
.od-toggle.on{ background:#e6efd8; color:#2f6f3c; border-color:rgba(47,111,60,.45); }
.od-toggle .od-tg-dot{ position:relative; flex:0 0 auto; width:7px; height:7px; border-radius:50%; background:currentColor; opacity:.5; }
.od-toggle.on .od-tg-dot{ opacity:1; }
.od-toggle.studio-toggle{ background:#f3ead3; color:#725925; border-color:rgba(150,135,100,.42); }
.od-toggle.studio-toggle.locked .od-tg-dot{
  width:13px; height:13px;
  background:conic-gradient(from -18deg, #d66f45 0 24%, #e1b64b 24% 49%, #69a9bd 49% 74%, #78ad68 74% 100%);
  opacity:1;
  box-shadow:0 1px 2px rgba(81,65,35,.18);
  transform:rotate(-10deg);
}
.od-toggle.studio-toggle.locked .od-tg-dot::after{
  content:"";
  position:absolute; inset:4px; border-radius:50%;
  background:#f7f0dc;
}
.od-toggle.studio-toggle.unlocked .od-tg-dot{ display:none; }
.studio-mode .topbar::after{
  content:"STUDIO";
  position:absolute;
  right:8px;
  bottom:-9px;
  padding:2px 7px;
  border-radius:999px;
  background:rgba(246,233,194,.94);
  color:#7a5c20;
  border:1px solid rgba(150,135,100,.34);
  font:800 .5rem/1 var(--mono);
  letter-spacing:.14em;
  box-shadow:0 3px 10px rgba(60,45,20,.12);
}
.studio-free-build .topbar::after{ content:"STUDIO · FREE BUILD"; }
.studio-panel{ display:flex; flex-direction:column; gap:14px; }
.studio-lock-panel{ gap:13px; }
.studio-note{
  margin:0;
  color:#665d4c;
  font-family:var(--serif);
  font-size:.92rem;
  line-height:1.42;
}
.studio-note code{
  font-family:var(--mono);
  font-size:.72rem;
  background:rgba(255,250,238,.72);
  border:1px solid rgba(150,135,100,.22);
  border-radius:6px;
  padding:1px 5px;
}
.studio-sales-copy{ font-size:1rem; color:#484235; }
.studio-disclaimer{
  margin:0;
  padding:10px 12px;
  border-radius:14px;
  background:rgba(255,250,238,.58);
  border:1px dashed rgba(150,135,100,.28);
  color:#746a56;
  font-family:var(--serif);
  font-size:.86rem;
  font-style:italic;
  line-height:1.35;
}
.studio-purchase-note{
  min-height:1em;
  color:#7b705d;
  font-family:var(--sans);
  font-size:.72rem;
  line-height:1.35;
}
.studio-swatch-row{
  display:flex;
  gap:8px;
  align-items:center;
  padding:2px 0 0;
}
.studio-swatch-row span{
  width:38px;
  height:20px;
  border-radius:999px 14px 999px 14px;
  background:var(--sw);
  border:1.5px solid rgba(78,74,55,.18);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.32),0 5px 14px rgba(70,55,25,.10);
  transform:rotate(var(--rot,-2deg));
}
.studio-swatch-row span:nth-child(2){ --rot:2deg; }
.studio-swatch-row span:nth-child(3){ --rot:-1deg; }
.studio-swatch-row span:nth-child(4){ --rot:3deg; }
.studio-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:10px;
}
.studio-grid-two{ grid-template-columns:repeat(2,minmax(0,1fr)); }
.studio-grid label{
  display:flex;
  flex-direction:column;
  gap:5px;
  color:#81765f;
  font:800 .62rem/1 var(--mono);
  letter-spacing:.12em;
  text-transform:uppercase;
}
.studio-grid select{
  min-width:0;
  border:1px solid rgba(150,135,100,.35);
  border-radius:12px;
  background:#fffaf0;
  color:var(--ink);
  padding:9px 10px;
  font:700 .88rem/1.1 var(--sans);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.65);
}
.studio-actions{ display:flex; flex-wrap:wrap; gap:8px; padding-top:2px; }
.studio-footer-actions{ gap:8px; flex-wrap:wrap; }
.studio-footer-actions .btn[disabled]{ opacity:.62; cursor:default; transform:none; }
@media (max-width:700px){
  .studio-grid{ grid-template-columns:1fr; }
}
.back-btn{ flex:0 0 auto; }
.topbar .btn-label{ white-space:nowrap; }
.topbar .submit-icon{ flex:0 0 auto; display:none; }
/* topbar buttons read as clean pills aligned to the bar's rounded shape */
.topbar .back-btn, .topbar #submitBtn{
  border-radius:999px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:42px;
  white-space:nowrap;
}
.topbar .post-review-btn{
  border-radius:999px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:42px;
  min-width:98px;
  padding:10px 18px;
  white-space:nowrap;
  background:
    radial-gradient(ellipse at 24% 22%, rgba(255,255,255,.30) 0 30%, transparent 64%),
    linear-gradient(180deg, rgba(255,248,233,.96), rgba(248,240,219,.96));
  border:1px solid rgba(139,122,84,.24);
  color:#514936;
  box-shadow:0 1px 2px rgba(70,55,30,.10);
}
.topbar .post-review-btn[hidden]{ display:none !important; }
.topbar .post-review-btn:hover{ background:#fffaf0; }
.topbar #submitBtn.plan-again{ gap:6px; min-width:132px; padding-inline:18px; }
.topbar #submitBtn .submit-label{ white-space:nowrap; }
.topbar #submitBtn .redo-icon{ flex:0 0 auto; }
.topbar #submitBtn.submit-pulse{
  animation:toolPulse 1.45s ease-in-out infinite;
}
.ghost-icon{ flex:0 0 auto; padding:8px 9px; }
.story-toast{
  position:absolute;
  left:10px;right:10px;top:10px;
  background:#f5f0e2;
  border:1.5px solid #9a8d6f;
  border-radius:4px;
  box-shadow:0 0 0 4px #f5f0e2, 0 0 0 5px #c4b896, 0 10px 26px rgba(40,32,18,.35);
  padding:10px 12px;
  font-size:.72rem;
  line-height:1.44;
  z-index:12;
  opacity:0;
  transform:translateY(-6px);
  pointer-events:none;
  transition:opacity .25s, transform .25s;
}
.story-toast.show{opacity:1;transform:none;pointer-events:auto;}
.story-toast .st-head{
  display:flex;justify-content:space-between;align-items:baseline;gap:8px;
  margin-bottom:4px;
}
.story-toast .st-head>span:first-child{font-family:var(--serif);font-weight:600;font-size:.84rem;color:var(--ink);}
.story-toast .st-level{color:var(--accent);font-size:.52rem;letter-spacing:.18em;font-weight:700;}
.story-toast .st-body{font-family:var(--serif);font-style:italic;color:#5a5141;}
.story-toast .st-rules{
  display:inline-block;margin-top:6px;
  font-size:.54rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;
  color:var(--accent);text-decoration:underline;cursor:pointer;
}
/* Extra top padding so the board never sits flush under the objective-drawer
   tab — the tab was reading as part of the board rather than the HUD above
   it. Board sizing is already dynamic (min-height:0 + flex), so this costs a
   sliver of board scale rather than breaking layout. */
.board-wrap{
  position:relative;
  min-height:0;
  width:100%;
  overflow:hidden;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:16px 6px 6px;
}
.board-card{
  position:relative;
  flex:0 0 auto;
  min-height:0;
  overflow:visible;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:18px 16px 20px 15px / 16px 18px 15px 20px;
  background:
    radial-gradient(120% 90% at 50% 38%, #fcf6e9 0 55%, #f3ecda 80%, #e7dec7 100%);
  border:2px solid #cdbf97;
  box-shadow:0 12px 32px rgba(60,50,30,.16), 0 2px 6px rgba(60,50,30,.1), inset 0 0 60px rgba(120,100,60,.05);
  padding:10px;
  box-sizing:border-box;
}
/* board-aligned pencil grid: lives on .board, so it matches the actual cell geometry */
.board::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:2;
  background-image:
    linear-gradient(rgba(70,60,40,.22) 1px, transparent 1px),
    linear-gradient(90deg, rgba(70,60,40,.22) 1px, transparent 1px);
  background-size:calc(100% / var(--gridCols,7)) calc(100% / var(--gridRows,7));
  background-position:0 0;
  mix-blend-mode:multiply; opacity:0;
  transition:opacity .2s ease;
}
.board.show-grid::after{ opacity:.38; }
/* slow drifting cloud shadows over the board */
.cloud-shadows{
  position:absolute; inset:10px;
  pointer-events:none; z-index:2; border-radius:4px;
  background:
    radial-gradient(38% 30% at 30% 40%, rgba(40,45,35,.10) 0 40%, transparent 72%),
    radial-gradient(46% 36% at 70% 65%, rgba(40,45,35,.08) 0 40%, transparent 70%);
  background-size:150% 150%, 160% 160%;
  background-position:18% 34%, 74% 66%;
  mix-blend-mode:multiply;
}
@media (prefers-reduced-motion: no-preference){
  .cloud-shadows{ animation:clouds 38s ease-in-out infinite alternate; }
  @keyframes clouds{
    0%{ background-position:18% 34%, 74% 66%; }
    50%{ background-position:32% 44%, 62% 54%; }
    100%{ background-position:42% 30%, 52% 70%; }
  }
}
.board{
  position:relative;
  display:grid;
  touch-action:none;
  user-select:none;
  flex:0 0 auto;
  background:transparent;
  border:0;
  border-radius:4px;
  overflow:visible;
  cursor:crosshair;
  box-sizing:border-box;
}
/* Landscape sites get rotated 90° clockwise for display on a portrait viewport
   (fitBoard() in js/main.js decides when and sizes #board/.board-card for it) —
   presentation only, nothing about the underlying grid changes, so tap handling
   (which resolves via elementFromPoint + each cell's data-x/data-y, not manual
   coordinate math) needs no changes to work correctly through the rotation. */
.board.board-rotated{
  transform:rotate(90deg);
}
/* the SVG art layer sits under the interactive cell grid */
.board .artlayer{
  position:absolute; inset:0; width:100%; height:100%;
  pointer-events:none; overflow:visible; z-index:0;
  transition:filter 1.1s ease-out;
}
/* "Golden Hour" sun shimmer — a ONE-SHOT cinematic light sweep on approval. It
   does NOT permanently change the board colours; it's a brief overlay that pans
   warm gold + white bands across with a blend mode, so jewel water and roofs glow
   as the light passes, then it's gone. No lasting filter = no flicker/revert. */
/* Foil shimmer — NO blend mode (it gets trapped by the card's transform/opacity
   stacking context). A plain bright overlay: an interactive tilt/mouse highlight at
   rest, plus a one-shot bright diagonal sweep on approval. z-index above the art. */
.sun-shimmer{
  position:absolute; inset:0; pointer-events:none; z-index:8; border-radius:6px;
  overflow:hidden; opacity:0; transition:opacity .4s ease;
  background:radial-gradient(circle at var(--shine-x,50%) var(--shine-y,40%),
    rgba(255,255,255,.34) 0%, rgba(255,250,230,.10) 38%, transparent 68%);
}
.sun-shimmer.animating-approval{
  opacity:1;
  background:linear-gradient(105deg,
    transparent 28%, rgba(255,247,220,.65) 46%, rgba(255,255,255,.95) 50%,
    rgba(255,236,180,.65) 54%, transparent 72%);
  background-size:260% 260%;
  animation:shimmerSweep 1.6s cubic-bezier(.4,0,.2,1) forwards;
}
@keyframes shimmerSweep{
  0%{ background-position:175% 50%; opacity:0; }
  12%{ opacity:1; }
  86%{ opacity:1; }
  100%{ background-position:-75% 50%; opacity:0; }
}
.cell{
  position:relative;
  border:0;
  background:transparent;
  display:flex;
  align-items:center;
  justify-content:center;
  z-index:3;
}
.cell.outside{ pointer-events:auto; cursor:not-allowed; }
.cell.outside::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:repeating-linear-gradient(135deg, rgba(90,85,75,.06) 0 4px, transparent 4px 8px);
}
.artlayer .wc{ mix-blend-mode:normal; }
.artlayer .tex{ mix-blend-mode:multiply; }
/* alive board: a very subtle, occasional tree sway (mostly still, gentle tilt now and then) */
@media (prefers-reduced-motion: no-preference){
  .artlayer .breathe{ animation:sway 11s ease-in-out infinite; }
  @keyframes sway{
    0%, 70%, 100%{ transform:rotate(0deg); }   /* still most of the time */
    80%{ transform:rotate(0.8deg); }
    90%{ transform:rotate(-0.6deg); }
  }
}
/* Water motion is intentionally tiny. Each shape receives a negative delay tied
   to the document clock, so editing the plan does not visibly restart the motion. */
.water-shore{
  animation:waterShore 11s ease-in-out infinite alternate;
}
.water-base{
  animation:waterBase 9s ease-in-out infinite alternate;
}
.water-deep{
  animation:waterDeep 13s ease-in-out infinite alternate;
}
.water-ripple{
  animation:waterSparkle 12s ease-in-out infinite;
  stroke-dasharray:3 9;
}
@keyframes waterShore{
  from{ opacity:.88; }
  to{ opacity:.94; }
}
@keyframes waterBase{
  from{ opacity:.90; }
  to{ opacity:.96; }
}
@keyframes waterDeep{
  from{ opacity:.68; }
  to{ opacity:.80; }
}
@keyframes waterSparkle{
  0%,70%,100%{ opacity:.06; stroke-dashoffset:0; }
  82%{ opacity:.22; }
  94%{ opacity:.10; stroke-dashoffset:-12; }
}
/* Rare "sunlight caught the water" glint — mostly invisible, briefly flashes once
   per its (long, per-instance) animation-duration. duration/delay are set inline
   per sparkle instance in js/art.js so each one flashes at an unpredictable time;
   this rule only needs to describe the shape of one cycle. */
.water-sparkle{
  transform-box:fill-box;
  transform-origin:center;
  animation-name:waterGlint;
  animation-timing-function:ease-in-out;
  animation-iteration-count:infinite;
}
@keyframes waterGlint{
  0%,88%,100%{ opacity:0; transform:scale(.6); }
  92%{ opacity:.85; transform:scale(1); }
  96%{ opacity:.3; transform:scale(.85); }
}
@media (prefers-reduced-motion: reduce){
  .water-shore,.water-base,.water-deep,.water-ripple{ animation:none; }
  .water-sparkle{ animation:none; opacity:0; }
}
.artlayer{ will-change:filter; }
/* board load: one uniform reveal keeps off-grid access art synchronized with the site */
@keyframes boardWipe{
  from{ opacity:.12; }
  to{ opacity:1; }
}
.artlayer.draw{ animation:boardWipe .85s cubic-bezier(.4,0,.15,1) both; }

/* ===== COMPLETION RITUAL / PRESENTATION MODE ===== */
/* fade away the UI chrome so the finished plan reads as a painting */
.app.view-only .tray,
.app.view-only .topbar .actions,
.app.view-only .objective-overlay{ display:none !important; }
.app.view-only .board{ pointer-events:none; cursor:default; }
.app.replay-mode .tray{ pointer-events:none; }
.app.replay-mode .board{ pointer-events:none; cursor:default; }
.board.view-only{ pointer-events:none; }
.hide-for-capture{
  opacity:0 !important; visibility:hidden; pointer-events:none !important;
  transition:opacity .55s ease, transform .55s cubic-bezier(.2,.7,.2,1), visibility 0s linear .55s !important;
}
.tray.hide-for-capture,
.objective-overlay.hide-for-capture,
.onboarding-float.hide-for-capture{ transform:translateY(6px); }
.topbar-center.hide-for-capture,
.topbar .actions.hide-for-capture{ transform:translateY(-4px); }
.board-card{ transition:transform .7s cubic-bezier(.2,.75,.2,1), box-shadow .7s ease; }
.app.approved-gallery .board-card{
  transform:scale(1.018);
  box-shadow:0 18px 42px rgba(60,50,30,.18), 0 2px 6px rgba(60,50,30,.1), inset 0 0 60px rgba(120,100,60,.05);
}
.app.approved-gallery .topbar{
  background:transparent; border-color:transparent; box-shadow:none;
  transition:background .55s ease, border-color .55s ease, box-shadow .55s ease;
}
.app.replay-mode .board-wrap{ overflow:visible; }
.level-share-button{
  position:absolute; left:50%; top:calc(100% + 10px); z-index:30;
  transform:translateX(-50%); white-space:nowrap;
}
.level-share-button:hover{ transform:translate(-50%,-1px); }
.approval-actions{
  display:grid;
  gap:12px;
  margin:16px auto 0;
  flex:0 0 auto;
  width:100%;
  padding:0 2px 2px;
}
.approval-actions .share-button,
.approval-actions .btn{
  width:100%;
  min-height:56px;
  border-radius:999px !important;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  /* !important because a later, unrelated global .btn.big rule (font-size:1.05rem)
     otherwise wins the specificity tie against this selector for the "District
     Map" button specifically (it has both .btn and .big), while "Share Plat"
     only matches .share-button — the two ended up rendering at different sizes
     even though this rule intends them to match. */
  font-size:1.05rem !important;
  letter-spacing:.1em;
  box-sizing:border-box;
}
.modal.approval-modal .modal-card{
  display:flex; flex-direction:column; overflow:hidden;
  /* Leaves room for the safe-area insets (notch/front camera up top, gesture bar
     down below) — the old calc(100dvh - 24px) ignored them entirely, so a tall
     card (lots of notes) could run right up against a camera cutout on phones
     with one. */
  max-height:calc(100dvh - 24px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px));
}
.modal.approval-modal .modal-head{ flex:0 0 auto; }
.modal.approval-modal #modalBody{
  display:flex; flex-direction:column; min-height:0;
  /* Was overflow:hidden — on a short/landscape screen with a full set of notes,
     content taller than the capped modal-card was silently clipped, which could
     hide the Share Plat / District Map buttons entirely with no way to reach
     them. Scrolls instead now, so nothing is ever unreachable. */
  overflow-y:auto;
  padding:0 4px 4px;
}
.approval-review{ min-height:0; overflow:hidden; }
.approval-review .approval-note-extra{ display:none; }
.approval-review .approval-note-extra[hidden]{ display:none !important; }
.approval-review.expanded{
  max-height:min(31dvh,240px); overflow-y:auto; padding-right:5px;
  scrollbar-width:thin; scrollbar-color:rgba(111,99,77,.45) transparent;
}
.approval-review .approval-note-extra.shown{ display:flex !important; }
.approval-more{
  display:flex; align-items:center; justify-content:center; gap:5px;
  width:100%; margin-top:7px; padding:6px 10px; border:0; border-radius:999px;
  background:rgba(111,99,77,.09); color:var(--accent); cursor:pointer;
  font-size:.62rem; font-weight:900; letter-spacing:.04em;
}
.approval-more:hover{ background:rgba(111,99,77,.15); }
.app.presentation-mode .board-card.hide-grid::after,
.app.presentation-mode .board.show-grid::after{ opacity:0 !important; }
.board-card.presenting .board::after{ opacity:0 !important; transition:opacity .5s; } /* drop pencil grid */
/* golden-hour light sweep bar */
.light-sweep{
  position:absolute; inset:0; z-index:6; pointer-events:none; border-radius:10px; overflow:hidden; opacity:0;
}
.light-sweep.run{ opacity:1; }
.light-sweep::before{
  content:""; position:absolute; top:-20%; left:-60%; width:50%; height:140%;
  background:linear-gradient(105deg, rgba(255,240,200,0) 0%, rgba(255,238,196,.55) 45%, rgba(255,228,170,.75) 50%, rgba(255,240,200,0) 100%);
  transform:skewX(-12deg);
  filter:blur(2px);
}
.light-sweep.run::before{ animation:sweepAcross 1.5s cubic-bezier(.45,0,.3,1) forwards; }
@keyframes sweepAcross{ from{ left:-60%; } to{ left:120%; } }
/* warm "built / golden hour" tint that settles over the board after the sweep */
.built-glow{
  position:absolute; inset:0; z-index:5; pointer-events:none; border-radius:10px; opacity:0;
  background:radial-gradient(120% 100% at 50% 30%, rgba(255,236,186,.0) 0%, rgba(255,224,160,.18) 70%, rgba(214,150,70,.16) 100%);
  mix-blend-mode:multiply;
  transition:opacity 1.1s ease;
}
.built-glow.show{ opacity:1; }
@media (prefers-reduced-motion: reduce){
  .light-sweep,.light-sweep::before{ animation:none !important; }
  .light-sweep.run{ opacity:0; }
}
/* newly placed item: strict 2-stage sequence — ink draws, THEN wash bleeds (no parent fade) */
.artlayer .just-drawn{ animation:none; opacity:1; }
/* Stage 1 — structural ink lines draw in swiftly */
.artlayer .just-drawn .ink{
  stroke-dasharray:100; stroke-dashoffset:100;
  animation:drawInk .45s cubic-bezier(.25,1,.5,1) forwards;
}
/* Stage 2 — watercolor wash bleeds in only AFTER the ink finishes (0.3s delay) */
.artlayer .just-drawn .marker-wash{
  opacity:0; transform-box:fill-box; transform-origin:center;
  animation:bleedWash .5s ease-out .3s forwards;
  mix-blend-mode:multiply;
}
@keyframes drawInk{ to{ stroke-dashoffset:0; } }
@keyframes bleedWash{ from{ opacity:0; transform:scale(.92); } to{ opacity:1; transform:scale(1); } }
.artlayer .place-flash{ pointer-events:none; }
.artlayer .place-flash .draw-stroke{
  stroke-dasharray:1; stroke-dashoffset:1;
  animation:flashInk .28s cubic-bezier(.22,.82,.35,1) var(--fx-age,0s) both;
}
.artlayer .place-flash .draw-wash{
  opacity:0; transform-box:fill-box; transform-origin:center;
  animation:featureWash .38s cubic-bezier(.18,.78,.28,1) calc(var(--fx-age,0s) + .10s) both;
  mix-blend-mode:multiply;
  filter:url(#feature-sketch);
}
@keyframes flashInk{
  0%{ stroke-dashoffset:1; opacity:.10; }
  18%{ opacity:.82; }
  100%{ stroke-dashoffset:0; opacity:1; }
}
.eraser-fade{
  transform-origin:center;
  animation:eraserFade .62s ease-out forwards;
}
@keyframes eraserFade{
  0%{ opacity:.55; }
  100%{ opacity:0; }
}
.eraser-scrub{
  transform-origin:center;
  animation:eraserScrub .62s ease-in-out forwards;
}
@keyframes eraserScrub{
  0%{ transform:rotate(-10deg); opacity:.65; }
  35%{ transform:rotate(5deg); opacity:.75; }
  70%{ transform:rotate(-3deg); opacity:.45; }
  100%{ transform:rotate(-10deg); opacity:0; }
}
.objective-drawer.od-settings-only{ padding:10px 16px 12px; }
.objective-drawer.od-settings-only .od-settings{ margin-top:0; padding-top:0; border-top:none; }
/* ===== FEATURE PLACEMENT: ink -> watercolor -> details ===== */
.artlayer .feature-created{
  pointer-events:none;
  opacity:0;
  animation:featureFadeIn .16s ease-out var(--fx-age,0s) both;
}
.artlayer .feature-created.feature-legacy-draw .feature-ink,
.artlayer .feature-created.feature-legacy-draw .ink{
  stroke-dasharray:500; stroke-dashoffset:500;
  animation:featureInk .28s cubic-bezier(.22,.82,.35,1) var(--fx-age,0s) both;
}
.artlayer .feature-created.feature-legacy-draw .feature-wash,
.artlayer .feature-created.feature-legacy-draw .marker-wash{
  opacity:0;
  transform-box:fill-box;
  transform-origin:center;
  animation:featureWash .40s cubic-bezier(.18,.78,.28,1) calc(var(--fx-age,0s) + .08s) both;
  filter:url(#feature-sketch);
}
.artlayer .feature-created.feature-home{
  opacity:0;
  transform-box:fill-box;
  transform-origin:center;
  clip-path:circle(12% at 50% 50%);
  animation:homeBlotReveal .24s cubic-bezier(.18,.78,.24,1) var(--fx-age,0s) both;
}
.artlayer .feature-created.feature-home .ink,
.artlayer .feature-created.feature-home .feature-ink{
  stroke-dasharray:none;
  stroke-dashoffset:0;
  animation:none;
}
.artlayer .feature-created.feature-home .marker-wash,
.artlayer .feature-created.feature-home .feature-wash,
.artlayer .feature-created.feature-home .feature-detail,
.artlayer .feature-created.feature-home .feature-tree,
.artlayer .feature-created.feature-home .wc{
  animation:none;
  filter:none;
}
.artlayer .feature-created.feature-legacy-draw .feature-detail,
.artlayer .feature-created.feature-legacy-draw .feature-tree{
  opacity:0;
  animation:featureDetail .24s ease-out calc(var(--fx-age,0s) + .27s) both;
}
.artlayer .feature-created.feature-legacy-draw .feature-detail .wc,
.artlayer .feature-created.feature-legacy-draw .feature-tree .wc,
.artlayer .feature-created.feature-legacy-draw .feature-detail .ink,
.artlayer .feature-created.feature-legacy-draw .feature-tree .ink{
  animation:none;
  opacity:1;
  stroke-dashoffset:0;
  transform:none;
}
.artlayer .feature-created.feature-legacy-draw.feature-park .wc:not(.ink):not(.feature-ink){
  opacity:0;
  transform-box:fill-box;
  transform-origin:center;
  animation:featureWash .46s cubic-bezier(.18,.78,.28,1) calc(var(--fx-age,0s) + .08s) both;
  filter:url(#feature-sketch);
}
.artlayer .feature-created.feature-legacy-draw.feature-park .feature-detail .wc,
.artlayer .feature-created.feature-legacy-draw.feature-park .feature-tree .wc{
  animation:none;
  opacity:1;
  transform:none;
  filter:none;
}
.artlayer .feature-created.feature-legacy-draw.feature-park .feature-wash,
.artlayer .feature-created.feature-legacy-draw.feature-park .marker-wash{ animation-duration:.46s; }
.artlayer .feature-created.just-drawn-home .marker-wash{ mix-blend-mode:multiply; }
.artlayer .road-wipe{
  display:none;
}
.artlayer .road-wipe.vertical{ transform-origin:center top; }
@keyframes homeBlotReveal{
  0%{ opacity:0; clip-path:circle(10% at 50% 50%); }
  52%{ opacity:.86; clip-path:circle(74% at 50% 50%); }
  100%{ opacity:1; clip-path:circle(145% at 50% 50%); }
}
@keyframes featureFadeIn{
  0%{ opacity:0; }
  100%{ opacity:1; }
}
@keyframes featureInk{
  0%{ stroke-dashoffset:500; opacity:.10; }
  18%{ opacity:.82; }
  100%{ stroke-dashoffset:0; opacity:1; }
}
@keyframes featureWash{
  0%{ opacity:0; transform:scale(.982); }
  58%{ opacity:1; transform:scale(1); }
  100%{ opacity:1; transform:scale(1); }
}
@keyframes homeMaterialWash{
  0%{ opacity:.18; transform:scale(.992); filter:none; }
  55%{ opacity:1; transform:scale(1); filter:url(#feature-sketch); }
  100%{ opacity:1; transform:scale(1); filter:url(#feature-sketch); }
}
@keyframes homeDraftLite{
  0%{ opacity:.18; transform:translateY(.45px) scale(.996); }
  58%{ opacity:1; transform:translateY(0) scale(1); }
  100%{ opacity:1; transform:translateY(0) scale(1); }
}
@media (pointer:coarse), (max-width:760px){
  .artlayer .feature-created.feature-home{
    animation-duration:.16s;
  }
}
@supports not (clip-path:circle(50% at 50% 50%)){
  .artlayer .feature-created.feature-home{
    clip-path:none;
    animation:featureFadeIn .14s ease-out var(--fx-age,0s) both;
  }
}
@keyframes homeDraftMobile{
  0%{ opacity:.32; }
  100%{ opacity:1; }
}
@keyframes roadCellWipe{
  0%{ opacity:0; transform:scaleX(.05); }
  48%{ opacity:.24; transform:scaleX(1); }
  100%{ opacity:0; transform:scaleX(1); }
}
.artlayer .road-wipe.vertical{
  animation-name:roadCellWipeVertical;
}
@keyframes roadCellWipeVertical{
  0%{ opacity:0; transform:scaleY(.05); }
  48%{ opacity:.24; transform:scaleY(1); }
  100%{ opacity:0; transform:scaleY(1); }
}
@keyframes featureDetail{
  0%{ opacity:0; transform:translateY(-.6px); }
  100%{ opacity:1; transform:translateY(0); }
}
@media (prefers-reduced-motion: reduce){
  .artlayer .feature-created .feature-ink,
  .artlayer .feature-created .feature-wash,
  .artlayer .feature-created .feature-detail,
  .artlayer .feature-created .feature-tree,
  .artlayer .feature-created .ink,
  .artlayer .feature-created .marker-wash,
  .artlayer .feature-created .wc,
  .artlayer .place-flash .draw-stroke,
  .artlayer .place-flash .draw-wash,
  .artlayer .road-wipe{
    animation:none !important;
    opacity:1 !important;
    stroke-dashoffset:0 !important;
    transform:none !important;
  }
  .artlayer .road-wipe{ opacity:0 !important; }
}
/* invalid-action feedback: cell headshake + floating reason toast */
@keyframes headshake{
  0%,100%{ transform:translateX(0); }
  20%{ transform:translateX(-3px); }
  40%{ transform:translateX(3px); }
  60%{ transform:translateX(-2px); }
  80%{ transform:translateX(2px); }
}
.cell.error-shake{ animation:headshake .3s cubic-bezier(.36,.07,.19,.97) both; }
.cell.error-shake::after{ content:""; position:absolute; inset:8%; border-radius:4px; background:rgba(194,89,58,.18); z-index:4; pointer-events:none; }
.err-toast{
  position:fixed; z-index:120; transform:translate(-50%,0);
  font-family:var(--mono); font-size:.84rem; font-weight:800; letter-spacing:.01em;
  color:#fff; background:rgba(150,60,45,.94); padding:7px 11px; border-radius:7px 6px 8px 6px;
  box-shadow:0 4px 12px rgba(120,50,35,.35); pointer-events:none; white-space:nowrap;
  animation:errToastFloat 3.0s ease-out forwards;
}
@keyframes errToastFloat{
  0%{ opacity:0; transform:translate(-50%,4px) scale(.92); }
  18%{ opacity:1; transform:translate(-50%,-2px) scale(1); }
  82%{ opacity:1; transform:translate(-50%,-14px); }
  100%{ opacity:0; transform:translate(-50%,-26px); }
}
@keyframes toastFloat{
  0%{opacity:0;transform:translate(-50%,6px);}
  12%{opacity:1;transform:translate(-50%,0);}
  80%{opacity:1;}
  100%{opacity:0;transform:translate(-50%,-4px);}
}
.save-toast{
  display:none !important;
  position:fixed;left:12px;bottom:calc(12px + env(safe-area-inset-bottom,0px));z-index:9000;
  width:27px;height:27px;padding:0;border-radius:50%;overflow:hidden;
  background:rgba(58,53,44,.76);color:#f7f2e6;font-family:var(--sans);font-size:0;font-weight:800;
  pointer-events:none;opacity:0;transform:scale(.88);transition:opacity .2s ease,transform .2s ease;
  box-shadow:0 2px 8px rgba(40,35,25,.16);border:1px solid rgba(255,255,255,.26);
}
.save-toast::before{content:"✓";display:grid;place-items:center;width:100%;height:100%;font-size:.72rem;line-height:1;}
.save-toast.show{opacity:.72;transform:scale(1);}
.save-toast[data-state="synced"]::before{content:"↥";}
.save-toast[data-state="offline"]::before{content:"○";font-size:.9rem;}
.save-toast[data-state="error"]::before{content:"!";}
.save-toast.warn{background:rgba(140,78,60,.78);}
.zen-toast{
  position:fixed;left:50%;top:42%;z-index:130;transform:translate(-50%,-50%);
  font-family:var(--serif);font-size:.92rem;font-weight:600;font-style:italic;
  color:#3d6b48;background:rgba(232,245,228,.94);padding:14px 22px;border-radius:12px;
  border:1px solid rgba(74,124,67,.28);box-shadow:0 10px 28px rgba(50,90,55,.18);
  pointer-events:none;max-width:min(88vw,320px);text-align:center;line-height:1.45;white-space:pre-line;
  animation:zenToastFade 4s ease-out forwards;
}
@keyframes zenToastFade{
  0%{opacity:0;transform:translate(-50%,-46%) scale(.96);}
  12%{opacity:1;transform:translate(-50%,-50%) scale(1);}
  72%{opacity:1;transform:translate(-50%,-50%);}
  100%{opacity:0;transform:translate(-50%,-54%);}
}
.cell.homeInvalid::after{content:"";position:absolute;inset:8%;border:2px dashed #c0473a;border-radius:4px;background:rgba(200,70,58,.12);z-index:3;pointer-events:none;}
.cell.homeInvalid::before{
  content:"!";
  position:absolute;
  top:1px;
  right:2px;
  font-size:.48rem;
  color:#fff;
  background:rgba(207,92,102,.82);
  border-radius:50%;
  width:11px;height:11px;line-height:11px;text-align:center;z-index:3;
}
/* a park with no road/trail connection gets the same "needs a connection" warning as homes */
.cell.parkInvalid::after{content:"";position:absolute;inset:8%;border:2px dashed #c0473a;border-radius:4px;background:rgba(200,70,58,.10);z-index:3;pointer-events:none;}
.cell.parkInvalid::before{
  content:"!";
  position:absolute;
  top:1px;
  right:2px;
  font-size:.48rem;
  color:#fff;
  background:rgba(207,92,102,.82);
  border-radius:50%;
  width:11px;height:11px;line-height:11px;text-align:center;z-index:3;
}
/* hover note on a disconnected home/park: a small red bubble like the occupied-cell message */
.cell[data-warn]{ cursor:help; }
.cell .warn-note{
  position:absolute; left:50%; bottom:108%; transform:translateX(-50%) translateY(4px);
  white-space:nowrap; font-family:var(--sans); font-size:.56rem; font-weight:700;
  color:#fff; background:#c0473a; padding:3px 7px; border-radius:6px;
  box-shadow:0 3px 8px rgba(120,40,30,.35); z-index:21; pointer-events:none;
  opacity:0; transition:opacity .12s, transform .12s;
}
.cell[data-warn]:hover{ z-index:20; }
.cell[data-warn]:hover .warn-note{ opacity:1; transform:translateX(-50%) translateY(0); }
.cell.valid-dot::before,
.cell.valid-dot-road::before,
.cell.valid-dot-road-neutral::before{
  content:"";
  position:absolute;
  inset:0;
  margin:auto;
  width:56%; height:56%;
  border-radius:50%;
  z-index:5;
  pointer-events:none;
  animation:validDotPulse 2.2s ease-in-out infinite;
  animation-delay:var(--pulse-delay,0s);
}
.cell.valid-dot::before{
  border:1.6px dashed var(--good);
  background:radial-gradient(circle at 50% 50%, rgba(74,124,67,.14) 0 55%, transparent 70%);
  box-shadow:0 0 6px rgba(74,124,67,.25);
}
.cell.valid-dot-road::before{
  /* Warmed toward gold (was reading orange-red) — higher green, lower red/blue. */
  border:2px dashed rgba(199,152,42,.78);
  background:radial-gradient(circle at 50% 50%, rgba(212,164,48,.18) 0 55%, transparent 72%);
  box-shadow:0 0 0 3px rgba(212,164,48,.08), 0 0 9px rgba(199,152,42,.24);
}
.cell.valid-dot-road-neutral::before{
  border:1.7px dashed rgba(95,99,97,.62);
  background:radial-gradient(circle at 50% 50%, rgba(100,106,102,.09) 0 55%, transparent 72%);
  box-shadow:0 0 0 3px rgba(90,90,82,.035);
}
@media (prefers-reduced-motion: no-preference){
  @keyframes validDotPulse{
    0%,100%{ transform:scale(.92); opacity:.7; }
    50%{ transform:scale(1.04); opacity:1; }
  }
  @keyframes dotPulse{
    0%,100%{ transform:translate(-50%,-50%) scale(.92); opacity:.7; }
    50%{ transform:translate(-50%,-50%) scale(1.04); opacity:1; }
  }
}
/* selected objects use a soft survey/markup halo, not a hard black debug box */
.cell.selected{outline:0;z-index:6;border-radius:8px;}
.cell.selected::after{display:none;}
.arrow{display:none!important;}
.home-label{
  position:absolute;
  left:1px;
  bottom:1px;
  color:#fff7e6;
  background:rgba(40,30,18,.5);
  border-radius:2px;
  padding:0 2px;
  font-size:.34rem;
  letter-spacing:.03em;
  z-index:3;
}
.town-count{
  position:absolute;
  top:1px;
  left:1px;
  color:#fff7e6;
  background:rgba(40,30,18,.5);
  border-radius:2px;
  padding:0 2px;
  font-size:.34rem;
  font-weight:800;
  z-index:2;
}

.tray{
  background:rgba(238,232,216,.9);
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  border-top:1px solid rgba(185,173,142,.6);
  padding:12px 10px calc(12px + env(safe-area-inset-bottom));
  box-shadow:0 -6px 18px rgba(80,65,40,.10);
  overflow:visible;          /* don't clip card shadows / badges */
}
.tool-grid{
  display:flex;
  gap:9px;
  justify-content:center;
  flex-wrap:wrap;            /* wrap neatly instead of clipping/scroll */
  padding:2px;
}
.tool-card{
  position:relative;
  isolation:isolate;
  --button-line:rgba(83,73,54,.34);
  flex:0 0 auto;
  width:78px;
  min-height:78px;
  border:1px solid rgba(150,135,100,.20);
  border-radius:13px;
  background:
    radial-gradient(ellipse at 24% 20%, rgba(255,255,255,.30) 0 30%, transparent 64%),
    linear-gradient(180deg,#fdfbf5,#f7f0df);
  background-blend-mode:normal,normal;
  padding:9px 8px 8px;
  display:flex; flex-direction:column; align-items:center; gap:5px;
  cursor:pointer;
  box-shadow:0 1px 2px rgba(70,55,30,.10);
  transition:transform .4s cubic-bezier(0.34,1.56,0.64,1), box-shadow .4s ease, background .14s;
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
  user-select:none;
}
/* Invisible hit-area expansion, bleeding into (up to half of) the .tool-grid gap
   so a tap that lands just outside the visible card still registers — the card
   itself already meets the 44px+ touch-target guideline, but taps landing in the
   gap between cards (very easy to do on a tray this dense) were simply missing
   everything. A plain <span> child rather than ::before/::after since both of
   those pseudo-elements are already used on this button for the sketch border
   and the "picked up" glow. */
.tool-card .tap-pad{
  position:absolute;
  inset:-4px;
}
.tool-card::before{
  content:""; position:absolute; inset:-1px; border-radius:inherit; pointer-events:none;
  z-index:2;
  border:1.35px solid var(--button-line);
  transform:rotate(var(--sketch-tilt,.12deg));
  opacity:.72;
}
.tool-card:hover{ transform:translateY(-3px); box-shadow:0 0 0 4px rgba(132,188,112,.06), 0 1px 2px rgba(70,55,30,.10); }
.tool-card:active{ transform:translateY(-1px); }
/* selected = "picked up" lift, no red outline */
.tool-card.active{
  transform:translateY(-10px) scale(1.05);
  --button-line:rgba(83,73,54,.48);
  background:
    radial-gradient(ellipse at 50% 86%, rgba(132,188,112,.12) 0 42%, transparent 72%),
    radial-gradient(ellipse at 24% 20%, rgba(255,255,255,.34) 0 32%, transparent 64%),
    linear-gradient(180deg,#fffdf7,#f7f0df);
  background-blend-mode:normal,normal,normal;
  border-color:rgba(125,112,78,.52);
  box-shadow:0 0 0 5px rgba(132,188,112,.08), 0 1px 3px rgba(70,55,30,.12);
}
.tool-card.active::after{ /* card-pickup soft glow under it */
  content:""; position:absolute; left:14%; right:14%; bottom:-7px; height:8px; border-radius:50%;
  background:radial-gradient(ellipse, rgba(132,188,112,.22) 0%, transparent 70%); z-index:-2;
}
.tool-card.tool-pulse{
  animation:toolPulse 1.6s ease-in-out infinite;
}
@keyframes toolPulse{
  0%,100%{ box-shadow:0 1px 2px rgba(70,55,30,.10), 0 0 0 0 rgba(132,188,112,0); }
  50%{ box-shadow:0 1px 2px rgba(70,55,30,.10), 0 0 0 5px rgba(132,188,112,.12); }
}
.onboarding-float{
  position:absolute; z-index:30; left:0; right:0; bottom:10px;
  display:flex; justify-content:center;
  margin:0 auto; padding:0 10px; pointer-events:none;
}
.onboarding-float.submit-ready{
  position:fixed;
  left:auto;
  right:calc(10px + env(safe-area-inset-right, 0px));
  top:calc(var(--topbar-bottom, 58px) + 8px);
  bottom:auto;
  width:min(300px, 74vw);
  justify-content:flex-end;
  z-index:70;
}
.onboarding-float.submit-ready .action-hint{
  text-align:left;
  position:relative;
  max-width:100%;
}
.onboarding-float.submit-ready .action-hint::before{
  content:"";
  position:absolute;
  top:-7px;
  right:26px;
  width:13px;
  height:13px;
  background:rgba(58,53,44,.94);
  transform:rotate(45deg);
  border-left:1px solid rgba(255,255,255,.08);
  border-top:1px solid rgba(255,255,255,.08);
}
.action-hint{
  display:none;
  max-width:min(420px, 94vw);
  padding:10px 14px;
  border-radius:12px;
  background:rgba(58,53,44,.94);
  color:#f7f2e6;
  font-family:var(--sans);
  font-size:.78rem;
  font-weight:700;
  line-height:1.35;
  text-align:center;
  box-shadow:0 8px 22px rgba(40,35,25,.22);
  border:1px solid rgba(255,255,255,.08);
}
.action-hint.show{ display:block; }
.action-hint.fade-out{ opacity:0; transition:opacity .8s ease; }
.tc-icon{
  width:46px; height:46px; border-radius:11px; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  box-shadow:inset 0 0 0 1px rgba(70,60,40,.1);
}
.tc-icon svg{ width:100%; height:100%; display:block; }
/* Was 12x7px (10x6 on mobile) — easy to miss entirely next to the trail
   icon, which is exactly what made the trail-bridge budget read as "no
   icon" even when it was technically rendering. Sized up meaningfully
   rather than just nudging it. */
.bridge-pips{
  display:none;
  align-items:center;
  justify-content:center;
  gap:4px;
  height:13px;
  margin:-1px 0 0;
}
.bridge-pips.show{ display:flex; }
.bridge-pip{
  position:relative;
  width:20px;
  height:11px;
  border:2.5px solid #8a6038;
  border-bottom:0;
  border-radius:20px 20px 0 0;
  box-sizing:border-box;
  opacity:.96;
}
.bridge-pip::after{
  content:"";
  position:absolute;
  left:50%;
  bottom:-3px;
  width:5px;
  height:5px;
  border-radius:50%;
  background:#5ab8c7;
  transform:translateX(-50%);
  box-shadow:0 0 0 1.5px rgba(255,255,255,.5);
}
.bridge-pip.used{
  border-color:#c9c1ab;
  opacity:.46;
}
.bridge-pip.used::after{ background:#9ccbd0; opacity:.58; }
.tc-name{ font-family:var(--sans); font-size:.6rem; font-weight:800; text-transform:uppercase; letter-spacing:.06em; color:#3a352c; }
/* count as a pill badge — bottom-left so it clears thumb + canvas, blueprint blue */
.tc-count{ font-family:var(--sans); font-size:.56rem; font-weight:800; color:#9a8f78; min-height:.7rem; letter-spacing:.02em; font-variant-numeric:tabular-nums; }
.tc-count.depleted{ color:var(--accent); }
/* Road/Trail budget badge: a small "tiles left" pill on the tool card. */
.tc-tool .tc-count:not(:empty){
  display:inline-flex; align-items:center; justify-content:center;
  min-width:18px; height:18px; padding:0 5px; border-radius:9px;
  background:#4a90e2; color:#fff; font-size:.72rem; line-height:1;
  box-shadow:0 1px 3px rgba(40,80,140,.3);
}
.tc-tool .tc-count.depleted{
  background:var(--accent); color:#fff;
}
.tool-card.budget-out{ animation:budgetPulse 1.1s ease-in-out infinite; }
@keyframes budgetPulse{ 0%,100%{ box-shadow:0 0 0 0 rgba(200,70,50,0); } 50%{ box-shadow:0 0 0 4px rgba(200,70,50,.18); } }
/* met objective: desaturate the card body (icon + name) so it's clearly "done / out of cards",
   but keep the emerald ✓ badge bright so completion still reads as a positive. */
.tool-card.flatten .tc-icon{ filter:saturate(.3) brightness(1.03); opacity:.72; }
.tool-card.flatten .tc-name{ color:#a59c88; }
.tool-card.depleted{ opacity:1; }
/* a brief badge pop when a requirement increases */
@keyframes cardAdded{ 0%{ transform:scale(1); } 35%{ transform:scale(1.28) translateY(-2px); } 100%{ transform:scale(1); } }
.tc-count.bump{ animation:cardAdded .45s cubic-bezier(.3,1.4,.5,1); }
.helpbar{
  display:none;
}
.hint{min-width:0;font-size:.6rem;font-weight:700;color:#837660;}

.modal{
  position:fixed; inset:0; z-index:220; display:none; align-items:center; justify-content:center;
  padding:16px; background:rgba(44,39,35,.68); backdrop-filter:blur(3px);
}
.modal.show{display:flex;}
.modal-card{
  width:min(420px,94vw); max-height:88dvh; overflow:auto;
  border-radius:4px;
  background:rgba(243,238,224,.92);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  box-shadow:
    0 0 0 1px #9a8d6f,
    0 0 0 7px #f3eee0,
    0 0 0 8px #b9ad8e,
    0 24px 70px rgba(40,32,18,.45);
  border:0;
  padding:0 18px 18px;
}
.modal-head{
  display:flex;justify-content:space-between;gap:12px;align-items:center;
  margin:0 -18px 14px;
  padding:13px 16px 11px;
  background:#e9e2cf;
  border-bottom:1.5px solid #b9ad8e;
}
.modal-title{font-family:var(--serif);font-size:1.08rem;font-weight:600;color:var(--ink);letter-spacing:.01em;}
.modal-kicker{font-size:.5rem;text-transform:uppercase;letter-spacing:.24em;color:var(--accent);font-weight:700;margin-bottom:4px;}
.modal-kicker:empty{display:none;}
.approval-title-approved{color:var(--good);font-weight:700;}
.approval-title-rest{color:var(--ink);}
.close{
  border:1.7px solid #8d7854;
  background:#f7f0dc;
  color:#5f4b32;
  border-radius:50%;
  width:42px;height:42px;min-width:42px;min-height:42px;flex:0 0 42px;
  aspect-ratio:1/1;
  cursor:pointer;display:grid;place-items:center;padding:0;
  box-shadow:0 2px 5px rgba(70,55,30,.10);
  touch-action:manipulation;
}
.close svg{width:18px;height:18px;display:block;stroke:currentColor;stroke-width:2.35;stroke-linecap:round;}
.close:hover{background:#fff8e9;}
.close:active{transform:translateY(1px);}
.brief-story{
  font-family:var(--serif);
  font-size:.84rem;
  line-height:1.5;
  font-style:italic;
  color:#5a5141;
  background:rgba(255,255,255,.4);
  border-left:2.5px solid var(--accent);
  border-radius:0 3px 3px 0;
  padding:10px 12px;
  margin-top:2px;
}
.brief-list{display:grid;gap:7px;margin-top:10px;}
.brief-item{
  display:flex;gap:9px;align-items:flex-start;
  background:rgba(255,255,255,.45);
  border:1px solid rgba(70,60,40,.16);
  border-radius:4px;padding:9px 11px;
  font-size:.74rem;line-height:1.42;
}
.brief-item .b-swatch{flex:0 0 auto;width:16px;height:16px;border-radius:3px;border:1px solid rgba(70,60,40,.35);margin-top:2px;}
.progress-pill{
  display:inline-block;
  font-size:.56rem;font-weight:600;letter-spacing:.02em;
  border-radius:3px;padding:2px 8px;margin-top:5px;
  background:rgba(91,143,84,.14);border:1px solid rgba(91,143,84,.35);color:#4a7642;
}
.progress-pill.none{background:rgba(64,48,34,.07);border-color:rgba(64,48,34,.2);color:var(--muted);}
.score-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin:10px 0;}
.score-box{background:rgba(255,255,255,.5);border:1px solid rgba(70,60,40,.2);border-radius:4px;padding:10px;}
.score-box .slabel{font-size:.5rem;text-transform:uppercase;letter-spacing:.12em;font-weight:700;color:var(--muted);}
.score-box .sval{font-family:var(--serif);font-size:1.1rem;font-weight:600;margin-top:2px;color:var(--ink);}
.profit-big{
  position:relative;
  background:rgba(91,143,84,.07);
  border:1.5px solid rgba(91,143,84,.55);
  border-radius:4px;
  padding:16px 18px;
  margin:8px 0 10px;
  text-align:center;
}
.profit-big::after{ display:none; }
.profit-big.revise{
  background:rgba(200,85,61,.07);
  border-color:rgba(200,85,61,.6);
}
.profit-big.revise::after{ display:none; }
.profit-big .slabel{font-size:.52rem;text-transform:uppercase;letter-spacing:.14em;color:var(--muted);font-weight:700;}
.profit-big .sval{font-family:var(--serif);font-size:1.7rem;font-weight:600;margin-top:2px;color:var(--good);}
.star-row{
  display:flex;justify-content:center;align-items:center;
  line-height:1;margin-bottom:4px;min-height:112px;
}
.star-row.organic-rating{ padding:2px 0; }
.rating-branch-svg{
  width:min(430px,96%);
  height:auto;
  overflow:visible;
  filter:drop-shadow(0 1px 2px rgba(70,55,35,.14));
}
.branch-shadow,
.branch-twig,
.branch-stem{
  fill:none;
  stroke-linecap:round;
  stroke-linejoin:round;
}
.branch-shadow{
  stroke:rgba(50,43,35,.16);
  stroke-width:5.2;
  transform:translateY(2px);
}
.branch-twig{
  stroke:#3f392f;
  stroke-width:3.4;
  opacity:.9;
}
.branch-twig-under{
  stroke-width:1.35;
  opacity:.45;
}
.branch-stem{
  stroke:#4a4438;
  stroke-width:2.3;
  opacity:.82;
}
.branch-leaf .leaf-wash{
  fill:#cfc8aa;
  opacity:.42;
}
.branch-leaf.on .leaf-wash{
  fill:#78a766;
  opacity:.9;
}
.branch-leaf .leaf-ink{
  fill:none;
  stroke:#6f7657;
  stroke-width:2.2;
  stroke-linejoin:round;
  opacity:.58;
}
.branch-leaf.on .leaf-ink{
  stroke:#3f6f3b;
  opacity:.95;
}
.branch-leaf .leaf-vein{
  fill:none;
  stroke:#4f6845;
  stroke-width:1.6;
  stroke-linecap:round;
  opacity:.5;
}
.branch-leaf.off .leaf-vein{ stroke:#8f8973; opacity:.28; }
.branch-acorn-badge{ filter:drop-shadow(0 3px 5px rgba(130,75,48,.24)); }
.branch-acorn-ring{
  fill:rgba(255,248,230,.82);
  stroke:#b88a52;
  stroke-width:3;
}
.branch-acorn .acorn-cap,
.rating-acorn .acorn-cap{ fill:#8a6840; stroke:#684a2e; stroke-width:1.05; stroke-linejoin:round; }
.branch-acorn .acorn-body,
.rating-acorn .acorn-body{ fill:#c47b3b; stroke:#684a2e; stroke-width:1.05; stroke-linejoin:round; }
.branch-acorn .acorn-shine,
.rating-acorn .acorn-shine{ fill:none; stroke:#f2d9a0; stroke-width:1.25; stroke-linecap:round; opacity:.65; }
@media (prefers-reduced-motion: no-preference){
  .rating-branch-svg .branch-twig,
  .rating-branch-svg .branch-stem{
    stroke-dasharray:360;
    stroke-dashoffset:360;
    animation:branchInkDraw .62s ease-out both;
  }
  .rating-branch-svg .branch-stem{ animation-delay:.12s; }
  .rating-branch-svg .branch-leaf{
    opacity:0;
    animation:leafFadeSettle .36s ease-out both;
  }
  .rating-branch-svg .leaf-1{animation-delay:.22s;}
  .rating-branch-svg .leaf-2{animation-delay:.32s;}
  .rating-branch-svg .leaf-3{animation-delay:.42s;}
  .rating-branch-svg .branch-acorn-badge{
    opacity:0;
    transform-box:fill-box;
    transform-origin:center;
    animation:acornBadgePop .42s cubic-bezier(.2,.8,.24,1) .52s both;
  }
}
@media (prefers-reduced-motion: reduce){
  .rating-branch-svg .branch-twig,
  .rating-branch-svg .branch-stem,
  .rating-branch-svg .branch-leaf,
  .rating-branch-svg .branch-acorn-badge{ animation:none !important; opacity:1; stroke-dashoffset:0; }
}
@keyframes branchInkDraw{to{stroke-dashoffset:0;}}
@keyframes leafFadeSettle{0%{opacity:0;}100%{opacity:1;}}
@keyframes acornBadgePop{0%{opacity:0;transform:scale(.72) rotate(-8deg);}75%{opacity:1;transform:scale(1.08) rotate(2deg);}100%{opacity:1;transform:scale(1) rotate(0);}}
.approval-metrics{
  width:min(460px,100%);
  margin:16px auto 6px;
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:14px;
}
.approval-metric{
  display:grid; gap:7px;
  padding:10px 12px;
  border-radius:12px;
  background:rgba(255,248,233,.54);
  box-shadow:inset 0 0 0 1px rgba(150,135,100,.18);
}
.approval-metric-head{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.approval-label{
  font-family:var(--mono); font-size:.56rem; letter-spacing:.14em; text-transform:uppercase;
  color:#8a7f63; font-weight:800;
}
.approval-numbers{ display:flex; align-items:baseline; gap:4px; white-space:nowrap; }
.approval-numbers b{
  font-family:var(--serif); font-size:1.55rem; line-height:1; color:var(--ink); font-weight:800;
}
.approval-numbers .approval-target{ font-size:1.08rem; color:#7f735d; }
.approval-of{
  font-family:var(--mono); font-size:.58rem; color:#8a7f63; text-transform:lowercase; font-weight:800;
}
.approval-metric .goal-check{ display:none; color:#4f7a43; font-family:var(--sans); font-size:.95rem; font-weight:900; }
.approval-metric.met .goal-check{ display:inline; }
.approval-bar-row{ display:flex; align-items:center; gap:6px; }
.approval-bar{
  flex:1 1 auto; height:6px; border-radius:999px; overflow:hidden;
  background:rgba(70,60,40,.10); box-shadow:inset 0 0 0 1px rgba(70,60,40,.06);
}
.approval-fill{ display:block; height:100%; border-radius:999px; }
.approval-fill-homes{ background:linear-gradient(90deg,#d85e43,#e98a43 24%,#e6b94d 44%,#5aae91 66%,#3f8fc2); }
.approval-fill-parks{ background:linear-gradient(90deg,rgba(95,142,67,.88),rgba(135,184,92,.92) 58%,rgba(180,203,124,.9)); }
.approval-bonus{
  min-width:22px; height:18px; padding:0 5px; border-radius:6px;
  display:inline-flex; align-items:center; justify-content:center;
  background:#d9a139; color:#fff9e8; font-family:var(--sans); font-size:.62rem; font-weight:900;
  box-shadow:0 1px 3px rgba(120,80,20,.22);
}
.star-row .star{color:#cbbf9f;transition:transform .2s;}
.star-row .star.on{color:#7ea85f;text-shadow:0 1px 2px rgba(74,104,45,.22);}
.align-line{font-family:var(--serif);}
.align-line .align-num{font-size:1.5rem;font-weight:600;color:var(--good);}
.align-line .align-lbl{font-size:.62rem;text-transform:uppercase;letter-spacing:.16em;color:var(--muted);}
.rep-sub{font-size:.66rem;color:var(--muted);margin-top:3px;letter-spacing:.03em;}
.map-star{color:var(--map-star);}
.profit-big.revise .sval{color:var(--accent);}
.review-list,.site-list{display:grid;gap:8px;margin-top:8px;}
.review-item.qc-item{
  display:flex;align-items:center;gap:8px;
  padding:6px 9px;font-size:.74rem;font-weight:500;
}
.review-item .review-title{font-weight:800;color:var(--ink);}
.review-item .review-body{font-weight:500;color:#4d4639;}
.qc-glyph{
  flex:0 0 auto;width:16px;height:16px;line-height:16px;text-align:center;
  border-radius:50%;font-size:.6rem;font-weight:700;color:#fbf3e6;
}
.qc-item.good .qc-glyph{background:var(--good);}
.qc-item.bad .qc-glyph{background:#8a7f63;}
.qc-item.warn .qc-glyph{background:#8a7f63;}
.review-list.qc{gap:5px;}
.qc-section{
  margin-top:12px;
  font-size:.5rem;font-weight:700;text-transform:uppercase;letter-spacing:.2em;
  color:var(--accent);
}
.qc-checks{
  display:flex; flex-wrap:wrap; gap:6px; margin-top:7px;
}
.qc-check{
  display:flex; align-items:center; gap:4px;
  font-family:var(--sans); font-size:.66rem; font-weight:700;
  padding:4px 9px; border-radius:999px;
  background:#e8efd9; color:#4a7a3f; border:1px solid rgba(74,124,67,.3);
}
.qc-check.bad{ background:#f4e2dc; color:#a8472f; border-color:rgba(168,71,47,.3); }
.qc-check-glyph{ font-weight:800; }
.qc-sep{
  margin-top:12px;
  border-top:1px dashed rgba(70,60,40,.35);
}
.review-item{padding:10px;border-radius:4px;background:rgba(255,255,255,.5);border:1px solid rgba(70,60,40,.18);font-size:.76rem;line-height:1.36;}
.review-item.good{border-left:5px solid var(--good);}
.review-item.warn{border-left:5px solid #b7a36d;}
.review-item.bad{border-left:5px solid #b7a36d;}
.review-item .rc-who{
  display:inline-block; font-weight:800; font-size:.58rem; letter-spacing:.06em;
  text-transform:uppercase; margin-right:6px; padding:1px 5px; border-radius:4px;
}
.review-item.rc-agency .rc-who{ background:rgba(90,130,170,.18); color:#4a6278; }
.review-item.rc-client .rc-who{ background:rgba(200,120,70,.15); color:#8a5530; }
.site-card{
  position:relative;
  border:1.5px solid #9a8d6f;
  background:#f6f1e3;
  border-radius:4px;
  padding:11px 11px 11px 30px;
  transition:background .12s;
  cursor:pointer;
  box-shadow:0 3px 0 #4a3a28;
  overflow:hidden;
}
.site-card:hover{background:#fffaf0;}
.site-card:active{transform:translateY(1px);background:#ece5d3;}
.site-card::before{
  content:"";
  position:absolute;
  left:0;top:0;bottom:0;width:18px;
  background:
    linear-gradient(180deg, #9cc47f 0 32%, #b6afa0 32% 48%, #a9cf8f 48% 66%, #6fae9c 66% 84%, #c2cf9e 84% 100%);
  border-right:1.5px solid #9a8d6f;
}
.site-card strong{display:block;font-family:var(--serif);font-weight:600;font-size:.9rem;margin-bottom:3px;color:var(--ink);}
.quirk-note{font-family:var(--sans);font-style:normal;font-size:.56rem;font-weight:700;color:var(--accent);letter-spacing:.04em;}
.site-card span{display:block;font-size:.7rem;color:var(--muted);line-height:1.35;}
.footer-note{margin-top:12px;font-size:.68rem;color:var(--muted);line-height:1.45;}
.compare-panel{
  margin-top:10px;
  padding:10px;
  border-radius:6px;
  background:rgba(255,255,255,.62);
  border:1px solid rgba(78,68,58,.1);
  font-size:.74rem;
  line-height:1.38;
}
.compare-panel strong{font-weight:800;}
.compare-actions{display:flex;gap:8px;margin-top:10px;}
.compare-actions .btn{font-size:.64rem;padding:8px 10px;}
.reset-confirm-copy{
  margin:10px 0 4px;
  font-family:var(--serif);
  font-size:.92rem;
  line-height:1.45;
  color:#5a5141;
}
.reset-confirm-actions{
  align-items:center;
  justify-content:center;
  flex-wrap:nowrap;
  gap:10px;
  margin-top:16px;
}
.reset-confirm-actions .btn{
  min-height:46px;
  min-width:118px;
  border-radius:999px;
  font-size:.72rem;
  justify-content:center;
}
.reset-confirm-actions .reset-yes{
  background:#fbf6ea;
  color:#5a5141;
  border-color:#c8bda0;
}
.reset-confirm-actions .reset-no{
  width:auto;
  flex:0 0 auto;
}
@media (max-height:690px){
  .title{font-size:.76rem}
  .topbar{padding-top:calc(4px + env(safe-area-inset-top));}
  .metric{padding:4px 3px 3px;}
  .tool{min-width:58px;padding:5px 5px;}
}
/* ===== Mobile / narrow: compact chrome, icon buttons, hide map labels ===== */
@media (max-width: 560px){
  .topbar{
    margin:calc(2px + env(safe-area-inset-top)) 0 0;
    padding:5px 8px;
    gap:6px;
  }
  .topbar-title{ font-size:.9rem; }
  .topbar-center{ max-width:min(62vw, 260px); }
  .topbar-sub{ gap:6px; font-size:.5rem; letter-spacing:.04em; }
  .hud-metric{ min-width:66px; grid-template-rows:auto 3px; }
  .hud-metric-head{ gap:4px; }
  .hud-numbers b{ font-size:.7rem; }
  .hud-numbers .hud-target{ font-size:.58rem; }
  .hud-of{ font-size:.4rem; }
  /* .hud-label no longer shrinks on mobile — its own base rule already pins
     a legible 9.6px everywhere; the old .48rem (7.68px) override here was
     the actual worst-offender size flagged in the accessibility review. */
  .park-pips{ height:10px; }
  .park-pips i{ width:2.5px; height:8px; }
  .approval-metrics{ grid-template-columns:1fr; gap:9px; margin-top:12px; }
  .topbar .back-btn, .topbar #submitBtn{ min-width:0; padding:8px 10px; }
  .topbar .post-review-btn{ min-width:82px; padding:8px 11px; font-size:.6rem; letter-spacing:.08em; }
  .topbar .back-btn .btn-label{ display:none; }
  .topbar .back-btn svg{ margin-right:0 !important; }
  .topbar #submitBtn:not(.plan-again){ padding:8px 11px; }
  .topbar #submitBtn:not(.plan-again) .submit-label{ display:none; }
  .topbar #submitBtn:not(.plan-again) .submit-icon{ display:block; }
  .topbar #submitBtn.plan-again{ min-width:104px; padding:8px 12px; }
  .topbar #submitBtn.plan-again .submit-label{ display:inline; }
  .topbar #submitBtn.plan-again .redo-icon{ display:none; }
  .tool-grid{ gap:6px; }
  .tool-card{ width:62px; min-height:62px; padding:7px 5px 5px; gap:2px; border-radius:12px; }
  .tool-card .tap-pad{ inset:-3px; } /* smaller gap here (6px) — stay under half so adjacent pads don't overlap */
  .tc-icon{ width:38px; height:38px; border-radius:10px; }
  .bridge-pips{ height:11px; gap:3px; margin:-1px 0 0; }
  .bridge-pip{ width:16px; height:9px; border-width:2.1px; border-bottom:0; }
  .tray{ padding:8px 8px calc(8px + env(safe-area-inset-bottom)); }
  .helpbar{ display:none; }
  .map-parcel-slot .parcel-lv.parcel-name{ display:none; }
  .map-head .btn.dark{ font-size:.62rem; padding:7px 10px; }
  .map-head .btn.dark span.map-back-label{ display:none; }
  .district-nav-row{ width:min(100%, 96vw); }
  .objective-overlay{ left:12px; right:12px; width:auto; }
  .drawer-clip{ width:100%; border-radius:0 0 16px 16px; overflow:hidden; }
  .objective-drawer{ border-left:1.5px solid rgba(185,173,142,.45); border-right:1.5px solid rgba(185,173,142,.45); }
}
/* ===== Immersive / fullscreen: maximize board inside iframe or native FS ===== */
body.plats-immersive{ overflow:hidden; }
.app.is-immersive{
  position:fixed; inset:0; z-index:10000;
  width:100vw !important; max-width:none !important;
  height:100dvh !important;
  margin:0 !important;
  border-radius:0 !important;
  box-shadow:none !important;
  padding:calc(4px + env(safe-area-inset-top)) 6px calc(6px + env(safe-area-inset-bottom));
  gap:6px;
  background:linear-gradient(160deg,#f4f1ea,#e9e5db);
}
.app.is-immersive .immersive-exit{
  display:inline-flex;
}
.app:fullscreen, .app:-webkit-full-screen{
  max-width:none; width:100vw; height:100dvh; margin:0; border-radius:0;
  padding:calc(4px + env(safe-area-inset-top)) 8px calc(8px + env(safe-area-inset-bottom));
}
.immersive-exit{
  display:none; align-items:center; justify-content:center;
  position:fixed; top:calc(6px + env(safe-area-inset-top)); right:8px; z-index:10001;
  padding:6px 10px; border-radius:999px;
  background:rgba(233,226,207,.94); border:1.5px solid rgba(185,173,142,.85);
  color:#6a5f49; font-size:.58rem; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
  box-shadow:0 4px 12px rgba(80,65,40,.16); cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
/* title button tag/badge */
.btn .btn-tag{ font-size:.55rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; opacity:.7; margin-left:6px; }
.btn .btn-badge{ font-size:.5rem; font-weight:800; letter-spacing:.08em; text-transform:uppercase; margin-left:7px; padding:2px 6px; border-radius:6px; background:rgba(120,105,75,.18); color:#7a6e52; }
.btn.big{ font-size:1.05rem; padding:13px 22px; }
.btn[disabled]{ opacity:.5; cursor:not-allowed; }

/* ===== Tablet/Desktop: float the UI over a drafting-table canvas ===== */
@media (min-width: 768px){
  body{ display:flex; align-items:center; justify-content:center; }
  .app{
    height:min(100dvh, 940px);
    border-radius:18px;
    box-shadow:0 24px 60px rgba(60,50,30,.16);
    position:relative;
    /* keep normal grid flow: topbar · board · tray — far more robust than absolute floats */
    grid-template-rows:auto minmax(0,1fr) auto;
    padding:14px;
    gap:12px;
    background:linear-gradient(160deg,#f4f1ea,#e9e5db);
  }
  /* floating pill header — rounded to match the inner button pills */
  .topbar{
    align-self:center;
    width:min(620px, 100%);
    margin:0 auto;
    border-radius:999px;
    border:1.5px solid rgba(185,173,142,.7);
    box-shadow:0 8px 22px rgba(80,65,40,.14);
    padding:8px 14px;
  }
  /* Map and Submit share one width so the bar reads symmetrically */
  .topbar .back-btn, .topbar #submitBtn{ min-width:104px; justify-content:center; }
  .topbar .post-review-btn{ min-width:82px; }
  .topbar #submitBtn.plan-again .submit-label{ display:inline; }
  .topbar #submitBtn.plan-again .redo-icon{ display:none; }
  /* drawer overlay aligns flush under the centered pill (uses measured topbar position).
     Deliberately narrower than the topbar's own 620px cap — it's meant to
     fit between the arcs of the pill's rounded ends, not span full width
     under it. */
  .objective-overlay{ top:var(--topbar-bottom, calc(env(safe-area-inset-top, 0px) + 64px)); width:min(560px,94%); left:50%; right:auto; transform:translateX(-50%); }
  .drawer-clip{ border-radius:0 0 18px 18px; overflow:hidden; }
  .objective-drawer{ border-radius:0 0 18px 18px; }
  /* board: a big sheet of paper, sized by aspect ratio so it never squishes.
     Smaller top buffer than desktop (vertical space is already tight on
     short/landscape phones) but not zero, for the same reason as above. */
  .board-wrap{ padding:10px 0 0; align-items:center; justify-content:center; }
  .board-card{
    border-radius:14px;
    box-shadow:0 14px 34px rgba(60,50,30,.14);
  }
  .board-card .board{ width:100%; height:100%; }
  /* floating detached tool dock — centered, sized to content, never full width */
  .tray{
    align-self:center;
    width:max-content; max-width:100%;
    margin:0 auto;
    border-radius:20px;
    border:1.5px solid rgba(185,173,142,.7);
    box-shadow:0 12px 28px rgba(80,65,40,.18);
  }
  .tray .tool-grid{ flex-wrap:nowrap; }
}
