/* Inter 4.1 subset, SIL OFL 1.1 (ui/fonts/OFL.txt, source in ui/fonts/README.md). Self-hosted; used by --font-ui / --font-num
   everywhere except Apple devices, which keep their system font. */
@font-face{font-family:"Inter MB";src:url("fonts/InterMB-Variable.woff2?v=ac867f87") format("woff2");font-weight:400 900;font-style:normal;font-display:swap}
:root{--sat:env(safe-area-inset-top,0px);--sar:env(safe-area-inset-right,0px);--sab:env(safe-area-inset-bottom,0px);--sal:env(safe-area-inset-left,0px);
 
 --bg:#a89d90; --panel:#bdb2a4; --zone:#b2a698; --zone2:#c6bba9; --sand:#cdbd9f; --taupe:#8c8074;
 --text:#2e2620; --muted:#382f28; --bronze:#a8742f; --bronze2:#c4975a; --line:#8a7d70;
 --red:#9e2b25; --blue:#2f5f8a; --green:#3d7a4a; --green-ink:#2f6b3c;   /* --green-ink: green TEXT on the #d7e6cf "Play here" fill, 4.90:1 (AA; A23) */
 /* Tall classic cards: header, then a framed 16:9 art box spanning the card width, then rules text, then the stat footer.
    Vertical space is the scarce resource, so the card HEIGHT is derived from the viewport height and the width follows from it.
    --fix = page header + opp hand + 2 zone rows + Dominion + 8 grid gaps + #app padding (see grid-template-rows). */
 /* ---- design tokens (style pass 2026-10): ONE font set, a 5-step type scale (+ a micro size for compact card faces only),
    spacing steps, line heights, radii and text tiers. Every component reads these; display titles (24px+) stay bespoke. */
 /* Apple devices use their own system font (SF Pro); everything else gets Inter, a bundled OFL look-alike
    (ui/fonts/, self-hosted, see ui/fonts/README.md) so desktop matches the iOS look. */
 --font-ui:-apple-system,BlinkMacSystemFont,"Inter MB","Noto Sans","DejaVu Sans",system-ui,sans-serif;
 --font-display:"DejaVu Serif",Georgia,"Times New Roman",serif;
 --font-cond:"Barlow Semi Condensed","Roboto Condensed","Arial Narrow","Liberation Sans Narrow","Noto Sans",sans-serif;
 --font-num:-apple-system,BlinkMacSystemFont,"Inter MB","DejaVu Sans","Noto Sans",system-ui,sans-serif;   /* numbers: one face, bold, tabular figures */
 --fs-2xs:10px;  /* compact card faces only (stat pills, labels on 844x390 cards); 10px is the mobile floor (AUD-A11Y-5) */
 --fs-xs:10.5px; /* sub text, captions, supplemental info */
 --fs-sm:12px;   /* secondary UI text, labels */
 --fs-md:13.5px; /* body text */
 --fs-lg:16px;   /* section headings, key numbers */
 --fs-xl:20px;   /* page / panel titles */
 --lh-tight:1.15; --lh-snug:1.3; --lh-body:1.45;
 --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px;
 --r-sm:4px; --r-md:8px; --r-lg:12px;
 --text-1:var(--text);   /* primary text */
 /* text tiers (audit AUD-A11Y-1): every tier keeps WCAG AA 4.5:1 on all four parchment surfaces (--bg, --panel, --zone,
    --zone2); the hierarchy comes from size, weight and case (sub text is smaller), not from washed-out color.
    --text-2 #382f28: 4.9 on --bg, 5.5 on --zone, 6.3 on --panel, 6.9 on --zone2. --text-3 #3d342d: 4.6 / 5.1 / 5.8 / 6.4. */
 --text-2:#382f28;       /* secondary: labels, sub text */
 --text-3:#3d342d;       /* tertiary: hints, captions */
 --text-on-dark-1:#f6e7c1; --text-on-dark-2:#d8cab0cc;
 --fix:324px;   /* (+32: the two Reach rows' 16px label strips, owner 2026-10-19) */
 /* compact hand card = header + art (stats strip overlaid on the art's lower edge): height = art + 38 */
 --hh:clamp(98px,calc(100vh*.1),116px);
 --hw:calc((var(--hh) - 38px)*16/9 + 12px);
 /* board card (Main/Assets) = header + art + 4 lines of rules text: height = art + 90; art width = card width - 12 */
 --ch:clamp(150px,calc((100vh - var(--fix) - var(--hh) - 12px)/4 - 6px),232px);
 --cw:min(calc((var(--ch) - 90px)*16/9 + 12px),calc((100vw - 680px)/3));
}
*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;font-family:var(--font-ui);background:var(--bg);color:var(--text);font-size:var(--fs-md);overflow:auto;min-width:1000px}
.sym{font-family:"DejaVu Sans","Noto Sans Symbols 2","Noto Sans Symbols","Segoe UI Symbol",sans-serif}
header{min-height:46px;flex-wrap:wrap;padding-top:4px!important;padding-bottom:4px!important;display:flex;align-items:center;justify-content:space-between;padding:0 12px;background:#665b51;border-bottom:2px solid var(--bronze);gap:8px}  /* darker than --taupe so the light labels pass AA (5.6:1) */
h1{margin:0;font-size:var(--fs-xl);color:#f3ebe0;letter-spacing:.5px;white-space:nowrap}h1 span{font-weight:400;color:#ecd7b0;font-size:var(--fs-md);margin-left:6px}
#setup{display:flex;gap:7px;align-items:center;flex-wrap:wrap;white-space:nowrap}
#setup label{color:#f3ebe0;font-size:var(--fs-sm)}
select,input,button{font:inherit;font-size:var(--fs-sm);background:#e8dfd2;color:var(--text);border:1px solid var(--line);border-radius:var(--r-md);padding:4px 8px}
#seed{width:80px}
button{cursor:pointer}button:hover{background:#f3ead9;border-color:var(--bronze)}
button.primary{background:#946526;color:#fff;border-color:#7d5420}button.primary:hover{background:#7d5420}  /* white text AA: 5.1:1 (6.6:1 hovered); was --bronze (4.0:1) */
#watchctl{display:inline-flex;gap:6px;align-items:center;white-space:nowrap;color:#f3ebe0;font-size:var(--fs-sm)}
#watchctl input[type=range]{width:90px;padding:0}

#app{min-height:calc(100vh - 50px);display:grid;gap:4px;padding:5px;
 grid-template-columns:230px minmax(0,1fr) 300px;
 grid-template-rows:minmax(34px,auto) 46px calc(var(--ch) + 22px) calc(var(--ch) + 6px) minmax(66px,auto) calc(var(--ch) + 6px) calc(var(--ch) + 22px) 46px minmax(calc(var(--hh) + 12px),1fr);
 grid-template-areas:"s1 opphand log" "s1 oppzone log" "s1 oppassets log" "s1 oppmain log" "btw btw log" "s0 mymain log" "s0 myassets log" "s0 myzone log" "s0 myhand log"}
body.nolog #app{grid-template-columns:230px minmax(0,1fr) 0}
body.nolog #logpanel{display:none}
#stats1{grid-area:s1}#stats0{grid-area:s0}#r-opphand{grid-area:opphand}#r-oppzone{grid-area:oppzone}#r-oppassets{grid-area:oppassets}
#r-oppmain{grid-area:oppmain}#dominion{grid-area:btw}#r-mymain{grid-area:mymain}#r-myassets{grid-area:myassets}#r-myzone{grid-area:myzone}#r-myhand{grid-area:myhand}
#logpanel{grid-area:log;contain:size}#stats1,#stats0{contain:size}  /* a long log or action list must not stretch the board rows; they scroll inside */
.row{display:flex;gap:8px;align-items:center;justify-content:center;background:var(--zone);border-radius:var(--r-md);padding:0 8px;min-height:0;position:relative}
.row{padding-left:84px!important}
.row::before{content:attr(data-label);position:absolute;left:6px;top:50%;transform:translateY(-50%);width:70px;font-size:var(--fs-2xs);line-height:var(--lh-snug);text-transform:uppercase;letter-spacing:.6px;color:var(--text-2);white-space:normal;pointer-events:none}
.mainrow{background:var(--zone2)}
.handrow.mine{align-items:center;padding-top:6px;padding-bottom:6px;overflow-x:auto;overflow-y:hidden;justify-content:safe center}
.zonerow,.handrow:not(.mine){justify-content:flex-start;overflow-x:auto;overflow-y:hidden}
.active-side{box-shadow:inset 0 0 0 2px var(--bronze)}

/* stats */
.stats-panel{background:var(--panel);border-radius:var(--r-lg);padding:8px;display:flex;flex-direction:column;gap:6px;min-height:0;overflow:auto;border:1px solid var(--line)}
.stats-panel.turn{border:2px solid var(--bronze);box-shadow:0 0 10px #a8742f66}
.pname{font-weight:700;font-size:var(--fs-lg);display:flex;justify-content:space-between;align-items:center;gap:6px;white-space:nowrap}
.pname>span:first-child{overflow:hidden;text-overflow:ellipsis;min-width:0}
.turnflag{white-space:nowrap;flex:none;font-size:var(--fs-xs);background:#946526;color:#fff;border-radius:var(--r-md);padding:1px 6px}
.statgrid{display:grid;grid-template-columns:1fr 1fr;gap:5px}
.st{background:var(--zone2);border-radius:var(--r-md);padding:4px 6px;cursor:help}
.st small{display:block;font-size:var(--fs-xs);font-weight:700;color:var(--text-2)}  /* a stat label: bold, with its colon ("Life:"); the +N/turn sub text stays smaller and regular */
.st .subtext>small{display:inline;font:inherit;color:inherit;letter-spacing:inherit}  /* the "/turn" of "+N/turn": part of the sub text, same size as before (its own element only so the device-sideways layout can show just "+N") */
.st b{font-size:var(--fs-lg)}.st.life b{color:#86211c}.st.inf b{color:#8a5a12}
.emb.hollow-emb{display:inline-flex;align-items:center;justify-content:center;padding:1px}
.emb.hollow-emb img{width:1.05em;height:1.05em;display:block}
/* Hollow faction frame stays the flat live colours. No stripe, texture, or ::before ornament. */
.fg-mark{display:block;margin:1px 0 0;font-size:var(--fs-2xs);font-weight:700;letter-spacing:.02em;color:#5a3a0e;line-height:1.1}
.st.click{cursor:pointer;text-decoration:underline dotted}
.shieldbox{display:flex;align-items:center;gap:8px;background:var(--zone2);border-radius:var(--r-md);padding:4px 6px;cursor:help}
.shield{width:34px;height:40px;clip-path:polygon(50% 0,100% 15%,92% 60%,50% 100%,8% 60%,0 15%);background:linear-gradient(#7aa3c4,#2f5f8a);color:#fff;font-weight:800;display:flex;align-items:center;justify-content:center;font-size:var(--fs-lg)}
.shield.off{background:#c9c2b8;color:#3b332b}   /* switched off: 7.02:1 (A23; was #ece6dc on #9c958c, 2.39:1) */
.shieldbox .sdec{font-style:normal;font-size:var(--fs-xs);font-weight:800;color:#722b10;margin-left:-4px;align-self:flex-end}.shieldbox .sdec-t{font-weight:600;color:#722b10}
.shieldbox .lbl{font-size:var(--fs-sm);line-height:var(--lh-snug)}
.conqbar{height:9px;background:#9c8f80;border-radius:var(--r-sm);overflow:hidden}.conqbar i{display:block;height:100%;background:linear-gradient(90deg,var(--bronze),#e1b864)}
.facline{display:flex;gap:4px;flex-wrap:wrap}
.actions{display:flex;flex-direction:column;gap:3px;overflow:auto;min-height:0}
.actions button{text-align:left;padding:4px 7px;font-size:13px}
.actions button.attack{border-left:4px solid var(--red)}.actions button.claim{border-left:4px solid var(--bronze)}
.actions button.play{border-left:4px solid var(--green)}.actions button.ward{border-left:4px solid var(--blue)}.actions button.end{border-left:4px solid var(--muted);font-weight:700;font-size:13px}
.actions button.veil{border-left:4px solid var(--line);font-weight:700;font-size:13px}
.hint{font-size:var(--fs-sm);color:#6b3f0e;background:#e9dcc4;border-radius:var(--r-md);padding:4px 6px}

/* emblem */
.emb{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:var(--c1);color:var(--c2);border:2px solid var(--c3);font-size:var(--fs-sm);line-height:1;flex:none}
.facchip{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-sm);background:var(--zone2);border-radius:var(--r-lg);padding:1px 7px 1px 1px;border:1px solid var(--c1)}

/* cards */
.card{width:var(--cw);height:var(--ch);border-radius:var(--r-md);border:3px solid var(--c1);background:var(--c1);display:flex;flex-direction:column;overflow:hidden;position:relative;flex:none;
 --cs:0 2px 4px #0003;box-shadow:var(--cs);transition:transform .15s}
.card .hd{display:flex;align-items:center;gap:2px;padding:0 2px 0 3px;min-height:24px;flex:none;background:var(--c1);color:var(--t1);border-bottom:2px solid var(--c3)}
.card .hd .emb{width:16px;height:16px;font-size:var(--fs-2xs);border-width:1.5px}
.card .nm{flex:1;font-weight:700;font-size:var(--fs-sm);line-height:12px;display:block;min-width:0;overflow-wrap:normal;word-break:normal}  /* no clamp, no ellipsis, no mid-word breaks: fitName() sizes it to 2 lines */
.card .nm .seg{display:inline-block;max-width:100%}  /* name fitter: break after a comma, not mid-phrase */
.card .nm.cond{font-family:var(--font-cond);font-stretch:condensed}
/* compact header: a slightly smaller cost disc gives long names a little more width */
.card:not(.lg) .cost{width:17px;height:17px;font-size:var(--fs-xs)}
/* a long name that can't fit at the 8.5px floor (narrow hand cards at 844x390): fitName() tucks the header. .tuck: the
   emblem steps aside (the frame colors show the faction); .tuck2: the cost disc moves onto the art's top-left corner */
.card:not(.lg) .hd.tuck .emb{display:none}
.card:not(.lg) .hd.tuck2 .cost{position:absolute;left:4px;top:28px;z-index:3;box-shadow:0 1px 3px #000a}
.card .nm.long{font-size:var(--fs-2xs);line-height:11px}.card .nm.xl{font-size:var(--fs-2xs);line-height:10.5px;letter-spacing:-.15px}.card.lg .nm.xl{letter-spacing:0}
.card .cost{width:19px;height:19px;border-radius:50%;background:#f7efdf;color:#3b2a12;font-weight:800;display:flex;align-items:center;justify-content:center;border:2px solid var(--bronze);font-size:var(--fs-sm);flex:none}
.gem{width:8px;height:8px;transform:rotate(45deg);border:1px solid #2228;flex:none}.gem.common{background:#d8d2c8}.gem.uncommon{background:#3fae6e}.gem.rare{background:#3a72c9}.gem.legendary{background:#f0a12a;box-shadow:0 0 5px #ffcb6b}
.card .banner{font-size:var(--fs-xs);font-weight:700;text-transform:uppercase;letter-spacing:.6px;padding:1px 5px;background:var(--c3);color:var(--t3);display:flex;justify-content:space-between;white-space:nowrap;overflow:hidden;gap:6px}
.card .banner span:first-child{overflow:hidden;text-overflow:ellipsis;min-width:0}
.card:not(.lg) .banner{display:none}  /* compact cards: faction = emblem + colors, element/type sits in the footer/tooltip */
.card .tb{flex:1;background:#fbf7f0;color:#1d1814;padding:2px 4px;font-size:var(--fs-xs);line-height:var(--lh-snug);overflow:hidden;min-height:0;position:relative;margin:0 3px;border-radius:2px 2px 0 0}
.card .tb.long{font-size:var(--fs-2xs);line-height:var(--lh-snug);letter-spacing:-.1px}
.card .tb .kw{font-weight:700;color:#4a2f0e}
.card .tb.clip::after{content:"\2026";position:absolute;right:0;bottom:0;padding:0 3px 0 14px;font-weight:700;line-height:var(--lh-snug);background:linear-gradient(90deg,#fbf7f000,#fbf7f0 45%)}
.card .ft{display:flex;justify-content:space-between;align-items:center;gap:2px;padding:1px 2px;min-height:17px;background:var(--c1);white-space:nowrap}
.card .ft.nc{justify-content:center;gap:4px}
.card .ft .ty{font-size:var(--fs-2xs);font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--t1)}
/* compact cards: the stats strip sits on the lower edge of the framed art (inside the frame), so the text box gets the height */
.card:not(.lg) .art{order:1}.card:not(.lg) .tb{order:3}
.card:not(.lg) .ft{order:2;position:relative;z-index:1;height:16px;min-height:0;margin:-21px 6px 5px;padding:0;background:none}
.card:not(.lg) .ft .badge{box-shadow:0 0 0 1px #3b2a1299,0 1px 3px #0008;padding:0 3px}
.badge small{font-size:.78em;font-weight:700;letter-spacing:-.2px}.card.lg .badge small{font-size:1em;font-weight:800;letter-spacing:0}
.card:not(.lg) .ft .sup,.card:not(.lg) .ft .ty,.card:not(.lg) .ft .pill{background:var(--c1);color:var(--t1);border-radius:var(--r-md);padding:0 3px;line-height:14px;box-shadow:0 0 0 1px #3b2a1299}
.card:not(.lg) .ft .pill.new{background:#3d5a7a;color:#e8f1f8}
.card:not(.lg) .ft .ty{font-size:var(--fs-2xs);letter-spacing:.4px}
.card:not(.lg) .hd .gem{position:absolute;top:34px;right:9px;z-index:1;box-shadow:0 0 0 1px #fff8,0 1px 2px #000a}
.badge{font-weight:800;font-size:var(--fs-xs);line-height:14px;border-radius:var(--r-sm);padding:0 4px;background:#fbf7f0;flex:none}
.badge.a{color:var(--red)}.badge.d{color:var(--blue)}.badge.d.hurt{color:#b8460f}
.card .ft .sup{font-size:var(--fs-2xs);color:var(--t1);white-space:nowrap;min-width:0}
/* stat footer that would overflow its card (fitStats() in app.js, AUD-UI-3): first tighter labels, then numbers + arrows
   only. The modifier arrows and a hurt "hp/def" are never cut off. */
.card:not(.lg) .ft.tight{gap:1px}.card:not(.lg) .ft.tight .badge{padding:0 2px;letter-spacing:-.2px}.card:not(.lg) .ft.tight .badge small{letter-spacing:-.4px}
.card:not(.lg) .ft.tighter .badge small{display:none}
.card:not(.lg) .ft i{display:none}  /* compact: "↻" and "+2/+1"; the long forms show in the discard viewer, the tooltip has the rest */
.pill i{font-style:normal}
.pill{font-size:var(--fs-2xs);font-weight:700;border-radius:var(--r-md);padding:1px 6px;background:#2e2620;color:#ffe2a8;white-space:nowrap}
.pill.new{background:#3d5a7a;color:#e8f1f8}
.card.exhausted{filter:saturate(.55) brightness(.92)}
.card.hand{cursor:default;width:var(--hw);height:var(--hh)}
.card.hand .tb{display:none}.card.hand .art{margin-bottom:3px}  /* compact hand card: art + name + cost + stats; full text in the hover tooltip */
.card.hand .art{flex:none}
.card.playable{cursor:pointer;--cs:0 0 0 3px #3d7a4a,0 3px 10px #3d7a4a88;box-shadow:var(--cs)}
/* the playable highlight follows the lift class (ui/fx.js .fx-hov), not :hover, so it stays on in the strip the lifted
   card leaves under the pointer; with Effects off there is no lift, so plain hover keeps it */
.card.playable.fx-hov,body.fx-off .card.playable:hover{filter:brightness(1.08)}
.card.selected{--cs:0 0 0 4px #e1b864,0 0 16px 4px #a8742f;box-shadow:var(--cs)}
.target{outline:4px solid var(--red);outline-offset:2px;cursor:crosshair;animation:pulse 1s infinite}
@keyframes pulse{50%{outline-color:#9e2b2544}}
.slotbox{width:var(--cw);height:var(--ch);text-align:center;border:2px dashed var(--line);border-radius:var(--r-md);display:flex;align-items:center;justify-content:center;color:var(--text-2);font-size:13px;flex:none}
.slotbox.target-slot{border:3px solid var(--green);background:#d7e6cf;color:var(--green-ink);font-weight:700;cursor:pointer}
.slotcap{position:absolute;bottom:2px;font-size:var(--fs-2xs);color:var(--text-2);text-transform:uppercase}
.slotwrap{position:relative;display:flex;flex-direction:column;align-items:center}
.ascended{animation:ascend 1.6s ease-out}
@keyframes ascend{0%{box-shadow:0 0 0 6px #e1b864,0 0 30px #e1b864}100%{box-shadow:0 2px 4px #0003}}
.ghost{position:fixed;z-index:50;pointer-events:none;animation:die 1.3s ease-in forwards}
.ghost::after{content:"DESTROYED";position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-weight:900;color:#fff;background:#9e2b25aa;font-size:var(--fs-lg);letter-spacing:1px;border-radius:var(--r-md)}
@keyframes die{0%{transform:scale(1)}15%{transform:translate(-4px,0) rotate(-2deg)}30%{transform:translate(4px,0) rotate(2deg)}100%{transform:scale(.6) rotate(8deg);opacity:0}}

/* framed art box: bronze frame + inner shadow; the faction gradient + glyph underneath is the missing-art placeholder */
.art{position:relative;flex:none;overflow:hidden;aspect-ratio:16/9;margin:3px 3px 3px;border-radius:var(--r-sm);
 border:2px solid var(--bronze2);box-shadow:0 0 0 1px #3b2a12b3,0 1px 3px #0005;
 background:radial-gradient(ellipse at 50% 38%,color-mix(in srgb,var(--c1) 55%,#fff) 0%,var(--c1) 58%,color-mix(in srgb,var(--c3) 70%,#000) 135%)}
.art::after{content:"";position:absolute;inset:0;border-radius:1px;box-shadow:inset 0 0 7px 1px #000b,inset 0 0 0 1px #ffffff2e;pointer-events:none}
.art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;display:block;user-select:none}
.art .ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--c2);opacity:.6;font-size:var(--fs-xl);text-shadow:0 1px 3px #0006}
.art.mini{width:48px;height:30px;aspect-ratio:auto;margin:0 1px 0 0;border-width:1.5px}.art.mini .ph{font-size:var(--fs-md)}
.art.mini::after{box-shadow:inset 0 0 4px #000a}
.art.realm{width:88px;height:55px;aspect-ratio:auto;margin:0}.art.realm .ph{font-size:28px}
#dominion .info.hasart{display:flex;align-items:center;gap:9px}
.art.tipart{width:100%;height:auto;aspect-ratio:16/9;margin:2px 0 7px}.art.tipart .ph{font-size:56px}
#tip.withart{width:330px;max-width:330px}
/* large classic layout (discard viewer): header, then a big 16:10 art box, then type line + rules text */
.card.lg{width:224px;height:auto;min-height:290px}
.card.lg .hd{min-height:28px;padding:2px 4px;gap:4px;border-bottom:0}.card.lg .hd .emb{width:20px;height:20px;font-size:var(--fs-sm);border-width:2px}
.card.lg .cost{width:21px;height:21px;font-size:var(--fs-sm)}.card.lg .gem{width:10px;height:10px}
.card.lg .art{aspect-ratio:16/10;margin:4px 5px 5px}.card.lg .art .ph{font-size:48px}
.card.lg .nm,.card.lg .nm.long{font-size:var(--fs-md);line-height:var(--lh-tight)}.card.lg .tb{min-height:64px;font-size:var(--fs-sm);line-height:var(--lh-snug);padding:3px 5px;margin:0;border-radius:0}
.card.lg .ft.nc{display:none}.card.lg .badge{font-size:var(--fs-md);padding:0 6px}.card.lg .ft .sup{font-size:var(--fs-xs)}.card.lg .ft{padding:1px 5px}
.modal-box .cards{align-items:flex-start}

/* chips (zone rows, opp hand) */
.chip{height:40px;min-width:110px;max-width:220px;border-radius:var(--r-md);border:2px solid var(--c1);background:#fbf7f0;padding:2px 6px;font-size:var(--fs-sm);display:flex;align-items:center;gap:5px;cursor:help;flex:none}
.chip .t{font-size:13px;text-transform:uppercase;color:var(--text-2);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chip>span{min-width:0}
.chip b{display:block;white-space:normal;overflow-wrap:normal;line-height:1.1;max-width:125px}  /* a card name: whole words, fitText() keeps it to 2 lines (no ellipsis) */
.chip.facedown{background:repeating-linear-gradient(135deg,#8c8074,#8c8074 6px,#9b8e80 6px,#9b8e80 12px);color:#f3ebe0;border-color:#5a4e44;justify-content:center;font-weight:700;font-size:13px}
.card.facedown{background:#3a2c1f;color:#f3ebe0;border-color:#5a4e44}
.card.facedown .hd,.card.facedown .banner,.card.facedown .tb{color:#f3ebe0}
.card.facedown .nm{color:#f3ebe0}
.art.veilback,.cb-art.veilback{background:repeating-linear-gradient(135deg,#3a2c1f,#3a2c1f 6px,#4a3826 6px,#4a3826 12px)}
.card.facedown.veiled .art.veilback{flex:1 1 auto;aspect-ratio:auto;height:auto;min-height:0;margin:4px}
.card.facedown .art.veilback .ph,.cb-art.veilback .ph{color:#e1b864;opacity:.9}
.cbadge.stat.veil{background:#3a2c1f;color:#f3ebe0}
.back{width:26px;height:34px;border-radius:var(--r-sm);background:repeating-linear-gradient(135deg,#8c8074,#8c8074 5px,#a39686 5px,#a39686 10px);border:2px solid var(--bronze);flex:none}

/* the Dominion */
#dominion{background:linear-gradient(90deg,var(--taupe),var(--sand) 30%,var(--sand) 70%,var(--taupe));border:2px solid var(--bronze);border-radius:var(--r-lg);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;padding:4px 14px;gap:12px}
#dominion .mid{text-align:center}
#dominion .title{font-size:var(--fs-lg);font-weight:800;letter-spacing:1px;color:#3b2a12}
#dominion .holder{font-size:var(--fs-md)}#dominion .holder b{color:#7d3e0e}
#dominion .cq{display:flex;flex-direction:column;gap:3px;font-size:var(--fs-sm)}
#dominion .cq .conqbar{height:11px}
#dominion .info{font-size:var(--fs-sm);color:#3b2a12}
#dominion .over{background:#2e2620;color:#ffe2a8;border-radius:var(--r-md);padding:3px 10px;font-weight:700;display:inline-block;margin-top:2px}

/* log */
#logpanel{background:var(--panel);border-radius:var(--r-lg);display:flex;flex-direction:column;min-height:0;border:1px solid var(--line)}
.loghead{display:flex;justify-content:space-between;align-items:center;padding:6px 8px;border-bottom:1px solid var(--line)}
#log{flex:1;overflow:auto;font-size:var(--fs-sm);padding:4px 8px;scrollbar-color:var(--taupe) var(--zone);scrollbar-width:thin}
#log::-webkit-scrollbar{width:9px}#log::-webkit-scrollbar-track{background:var(--zone)}#log::-webkit-scrollbar-thumb{background:var(--taupe);border-radius:var(--r-sm)}
#log div{padding:2px 0;border-bottom:1px solid #a89d9055}
#log .turn{font-weight:700;color:#3b2a12;margin-top:5px;border-bottom:1px solid var(--bronze)}
#log .death{color:#7a1a16;font-weight:600}#log .ascend{color:#7d5420;font-weight:700}#log .claim{color:#6b4a10}#log .dmg{color:#5a3a2a}
#log .issue{color:#fff;background:#9e2b25;padding:2px 4px}#log .over{font-weight:800;background:#2e2620;color:#ffe2a8;padding:3px 5px}
#log .trap{font-size:13px}
#log .fresh{animation:fresh 1.5s}@keyframes fresh{0%{background:#e9cf96}100%{background:transparent}}

/* modal + tooltip */
#modal{position:fixed;inset:0;background:#2e262088;z-index:80;display:flex;align-items:center;justify-content:center}
.modal-box{background:#efe7da;color:var(--text);border-radius:var(--r-lg);border:2px solid var(--bronze);max-width:860px;width:92vw;max-height:86vh;overflow:auto;padding:16px 22px;position:relative}
.modal-box h2{margin-top:0;color:#5a3a0e}.modal-box h3{margin:12px 0 4px;color:#7d5420}.modal-box p,.modal-box li{line-height:var(--lh-body);font-size:var(--fs-md)}
.modal-box .close{position:absolute;right:10px;top:10px}
.modal-box .cards{display:flex;flex-wrap:wrap;gap:8px}
.welcome{display:flex;gap:10px;margin-top:10px}
/* Story reward badges. The 72x64 cap lives here, not only in the after-match sheet, so the fallback modal stays a thumbnail. */
.story-rewards.am-badges{display:flex;flex-direction:column;gap:8px;max-width:100%;max-height:none;overflow:visible}
.story-rewards .am-badge{display:grid;grid-template-columns:72px minmax(0,1fr);gap:4px 12px;align-items:center;min-height:72px;text-align:left}
.story-rewards .sr-art,.story-rewards .mb-back,.am-badge .mb-back,.story-rewards .sr-frame,.story-rewards .sr-spirit{width:72px;height:64px;aspect-ratio:auto;flex:none}
.story-rewards .sr-art{display:block}
.story-rewards .am-badge:has(.sr-spirit){grid-template-columns:108px minmax(0,1fr);align-items:center}
.story-rewards .sr-art:has(.sr-spirit){width:108px;height:auto;background:transparent}
.story-rewards .sr-spirit{width:auto;height:auto;max-width:108px;max-height:min(220px,calc(100dvh - 168px));object-fit:contain;object-position:left center;border-radius:6px;background:transparent}
.story-rewards .sr-frame{display:block;box-sizing:border-box;border-radius:6px;border:3px solid var(--el-edge,#e1b864);background:var(--el-scrim,#241c16),var(--el-tex) center/cover}
.story-rewards .sr-frame.el-storm{--el-edge:#5d86ff;--el-scrim:linear-gradient(#0b1424cc,#0b1424aa);--el-tex:url("cosmetics/frames/assets/tex_storm.webp")}
.story-rewards .sr-frame.el-frost{--el-edge:#7fb6dc;--el-scrim:linear-gradient(#1f5f9acc,#13497ecc);--el-tex:url("cosmetics/frames/assets/tex_frost.webp")}
.story-rewards .sr-frame.el-verdant{--el-edge:#6fae4a;--el-scrim:linear-gradient(#0a180ccc,#0a180caa);--el-tex:url("cosmetics/frames/assets/tex_verdant.webp")}
.story-rewards .sr-frame.el-jade{--el-edge:#2fd39a;--el-scrim:linear-gradient(#00140ccc,#00140caa);--el-tex:url("cosmetics/frames/assets/tex_jade.webp")}
.story-rewards .sr-frame.el-sun{--el-edge:#ffd56a;--el-scrim:linear-gradient(#3a2000cc,#3a2000aa);--el-tex:url("cosmetics/frames/assets/tex_sun.webp")}
.story-rewards .sr-frame.el-spirit{--el-edge:#b48cff;--el-scrim:linear-gradient(#120626cc,#120626aa);--el-tex:url("cosmetics/frames/assets/tex_spirit.webp")}
.story-rewards .sr-frame.el-shade{--el-edge:#B89B4C;--el-scrim:linear-gradient(#0a0908ee,#141210ee);--el-tex:url("cosmetics/shade/tex_shade.jpg")}
.story-rewards .am-badge b{display:block;margin:0;font-family:var(--font-ui);font-size:var(--fs-lg);line-height:var(--lh-tight);color:#5a3a0e}
.story-rewards .am-badge small{display:block;font-size:var(--fs-md);color:#5a4636}
.scr-aftermatch .story-rewards .am-badge b{color:#f6e7c1}
.scr-aftermatch .story-rewards .am-badge small{color:var(--ink2)}
.legend{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.legend .lf{border:3px solid var(--c1);border-radius:var(--r-md);padding:6px;background:#fbf7f0}
.legend .lf .hd{display:flex;align-items:center;gap:6px;font-weight:700}
.sw{display:inline-block;width:16px;height:12px;border:1px solid #0004;margin-right:2px}
.cycle{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-weight:700;margin:6px 0}
#tip{position:fixed;z-index:90;max-width:320px;background:#2e2620;color:#f6eddc;font-size:var(--fs-sm);line-height:var(--lh-body);padding:7px 9px;border-radius:var(--r-md);pointer-events:none;box-shadow:0 4px 12px #0005;border:1px solid var(--bronze)}
.hidden{display:none!important}

.playbtn{position:absolute;left:50%;top:52%;transform:translate(-50%,-50%);z-index:3;font-weight:800;background:var(--green);color:#fff;border:2px solid #fff;border-radius:var(--r-lg);padding:3px 12px;box-shadow:0 2px 6px #0006;white-space:nowrap}
.playbtn:hover{background:#4f9a5e}
.card.target-own{outline:4px solid var(--green);outline-offset:2px;cursor:pointer;animation:pulseg 1s infinite}
@keyframes pulseg{50%{outline-color:#3d7a4a44}}
.zonedrop{height:40px;border:3px solid var(--green);background:#d7e6cf;color:var(--green-ink);font-weight:700;border-radius:var(--r-md);padding:0 10px;display:flex;align-items:center;cursor:pointer;flex:none}
.actions button.disabled{opacity:.6;cursor:not-allowed;border-left:4px solid #9c958c;background:#ddd5c8}
@media (max-width:1300px){
 #app{grid-template-columns:210px minmax(0,1fr);grid-template-areas:"s1 opphand" "s1 oppzone" "s1 oppassets" "s1 oppmain" "btw btw" "s0 mymain" "s0 myassets" "s0 myzone" "s0 myhand" "log log"}
 #app{grid-template-rows:minmax(34px,auto) 46px calc(var(--ch) + 22px) calc(var(--ch) + 6px) minmax(66px,auto) calc(var(--ch) + 6px) calc(var(--ch) + 22px) 46px calc(var(--hh) + 12px) 240px}
 body.nolog #app{grid-template-columns:210px minmax(0,1fr)}
 :root{--cw:min(calc((var(--ch) - 90px)*16/9 + 12px),calc((100vw - 360px)/3))}
}
/* chips with mini art may shrink (names ellipsize) instead of scrolling the 44px opponent-hand / zone rows */
.handrow:not(.mine) .chip,.zonerow .chip{flex:0 1 auto;min-width:100px}

/* ======================= v4 (Phase 3): the living map, Belief, legends, fusions, Codex ======================= */
.gem.mythic{background:conic-gradient(#e9d9a6,#b9c6d6,#f2c96b,#c9b2e0,#e9d9a6);box-shadow:0 0 6px #fff3c0}
/* faction artefact frames: an ornament band drawn inside the colored border; one motif per faction */
.card::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:2;border-radius:var(--r-sm)}
.card.fr-greek::before{box-shadow:inset 0 0 0 1px #f3ead6aa;  /* meander key (bottom edge, so header text stays clear) */
 background:repeating-linear-gradient(90deg,var(--c3) 0 3px,transparent 3px 6px) bottom/100% 2px no-repeat,repeating-linear-gradient(90deg,transparent 0 3px,var(--c3) 3px 6px) bottom 2px left/100% 1px no-repeat}
.card.fr-norse::before{  /* knotwork bands */
 background:repeating-linear-gradient(45deg,var(--c3) 0 2px,transparent 2px 5px) left/2px 100% no-repeat,repeating-linear-gradient(-45deg,var(--c3) 0 2px,transparent 2px 5px) right/2px 100% no-repeat}
.card.fr-celtic::before{  /* triskele beads */
 background:radial-gradient(circle,var(--c3) 1.2px,transparent 1.6px) bottom left/6px 3px repeat-x,radial-gradient(circle,var(--c3) 1.2px,transparent 1.6px) left top/3px 6px repeat-y,radial-gradient(circle,var(--c3) 1.2px,transparent 1.6px) right top/3px 6px repeat-y}
.card.fr-meso::before,.card.fr-mesoamerican::before{  /* step-fret */
 background:linear-gradient(90deg,var(--c3) 50%,transparent 0) bottom/8px 2px repeat-x,linear-gradient(90deg,transparent 50%,var(--c3) 0) bottom 2px left/8px 2px repeat-x}
.card.fr-egyptian::before{  /* papyrus columns */
 background:repeating-linear-gradient(180deg,var(--c3) 0 4px,var(--c2) 4px 5px) left/2px 100% no-repeat,repeating-linear-gradient(180deg,var(--c3) 0 4px,var(--c2) 4px 5px) right/2px 100% no-repeat}
.card.fr-japanese::before{  /* seigaiha waves */
 background:radial-gradient(circle at 50% 100%,transparent 2px,var(--c3) 2.5px,transparent 3.2px) bottom left/6px 3px repeat-x}
.card.lgd{border-color:color-mix(in srgb,var(--c1) 60%,#e1b864)}
.card.lgd .hd{background:linear-gradient(90deg,var(--c1),color-mix(in srgb,var(--c1) 70%,#e1b864),var(--c1))}
/* mythic split frame: faction A on the left, faction B on the right, an electrum seam */
.card.fr-mythic{border-color:transparent;background:linear-gradient(115deg,var(--c1) 0 49%,#efe0b0 49% 51%,var(--d1) 51%) border-box;--cs:0 0 8px #f2d27a88;box-shadow:var(--cs)}
.card.fr-mythic .hd{background:linear-gradient(115deg,var(--c1) 0 55%,var(--d1) 55%);color:var(--t1)}
.card.fr-mythic .ft{background:linear-gradient(115deg,var(--c1) 0 50%,var(--d1) 50%)}
.card.fr-mythic::before{box-shadow:inset 0 0 0 1px #f6e7b8}
.emb.dual{background:linear-gradient(115deg,var(--c1) 50%,var(--d1) 50%);color:#fff6d8;border-color:#e6cf8a}
.tb .kw.sig{color:#7a4c06}
.art.fusionart .half{position:absolute;inset:0;overflow:hidden;
 background:radial-gradient(ellipse at 50% 38%,color-mix(in srgb,var(--c1) 55%,#fff) 0%,var(--c1) 58%,color-mix(in srgb,var(--c3) 70%,#000) 135%)}
.art.fusionart .half.h0{clip-path:polygon(0 0,62% 0,38% 100%,0 100%)}
.art.fusionart .half.h1{clip-path:polygon(62% 0,100% 0,100% 100%,38% 100%)}
.art.fusionart .half.h0 .ph{justify-content:flex-start;padding-left:12%}.art.fusionart .half.h1 .ph{justify-content:flex-end;padding-right:12%}
.art.fusionart>img{z-index:1}
.art.fusionart .seam{position:absolute;inset:0;background:linear-gradient(112deg,transparent 49.3%,#f6e7b8 49.6% 50.4%,transparent 50.7%);pointer-events:none}
.art.fusionart>img~.seam{display:none}
/* states */
.card.awakened{--cs:0 0 0 2px #f2d27a,0 0 14px 3px #e9b84c99;box-shadow:var(--cs)}
.card.awakened .art::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:radial-gradient(ellipse at 50% 30%,#ffe9a833,transparent 70%)}
.card.fading{filter:saturate(calc(1 - var(--fd,.2))) brightness(.95)}
.card.fade1{--fd:.25}.card.fade2{--fd:.45}.card.fade3{--fd:.65;opacity:.88}
.target-own.card,.card.target-own{outline:4px solid var(--green)}
.card.target-fuse{outline:4px solid #e1b864;outline-offset:2px;cursor:pointer;animation:pulsef 1s infinite;--cs:0 0 18px 4px #f2d27a;box-shadow:var(--cs)}
@keyframes pulsef{50%{outline-color:#e1b86444}}
.card.target-warn{outline:4px dashed #c0612a;outline-offset:2px;cursor:pointer}
/* Main row side panel */
.mainside{display:flex;flex-direction:column;gap:5px;width:170px;flex:none;align-self:center}
.belief{background:var(--zone);border-radius:var(--r-md);padding:3px 6px;cursor:help}
.belief small{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.5px;color:var(--text-2)}
.pips{display:flex;gap:4px;margin-top:2px}
.pip{width:18px;height:18px;border-radius:50%;background:#9c8f80;border:2px solid #7d7064;position:relative}
.pip.on{background:radial-gradient(circle at 40% 35%,#fff3c8,#e1b864 55%,#a8742f);border-color:#7d5420;box-shadow:0 0 5px #e1b86499}
/* the tier numbers (2 / 4 / 6) sit in their own strip under the dots (owner 2026-10-19: they were cramped and the dots'
   rims and glow covered them): 4px below the dot's outer edge, 11px figures, the strip reserved by the row's padding */
.pip.tier::after{content:attr(data-t);position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);font-size:11px;line-height:1;font-style:normal;color:#4a2f08;font-weight:800}
body:not(.land) .pips{gap:6px;padding-bottom:16px}
.pip.tier{border-color:#5a3a0e}
.fadebadge{font-size:var(--fs-sm);font-weight:700;color:#fff;background:#5d5560;border-radius:var(--r-md);padding:2px 6px;cursor:help;margin-top:6px}
.fadebadge.warn{background:#c9bcaa;color:#5a3a0e;font-weight:600}
.reqchip{position:relative;font-size:13px;font-weight:700;background:#efe3c8;border:1px solid var(--bronze);border-radius:var(--r-md);padding:2px 6px;overflow:hidden;cursor:help}
.reqchip i{position:absolute;left:0;bottom:0;height:3px;background:var(--bronze)}
.reqchip.done{background:#f6e2a6;color:#6b4a10;box-shadow:0 0 6px #e1b864}
.reqchip.cor{background:#e9dcc4}
.powerbtn{font-weight:700;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:13px}
.powerbtn:disabled{opacity:.6;cursor:default}
.powerbtn.lit{border-color:#e1b864}
.powerbtn.ready{background:linear-gradient(90deg,#e1b864,#f3dfa8);border-color:#7d5420;box-shadow:0 0 8px #e1b864}
.powerbtn.selected{outline:3px solid var(--red)}
.actions button.fuse{border-left:4px solid #e1b864;background:#f6ecd0;font-weight:700}
.actions button.replace_main{border-left:4px dashed #c0612a}
.actions button.invoke{border-left:4px solid #b88a2a}
/* the Reaches: three columns that line up between the two sides of the table */
.assetsrow{gap:6px}
.reach{position:relative;flex:1 1 0;max-width:calc(var(--cw) + 30px);height:100%;display:flex;align-items:center;justify-content:center;border-radius:var(--r-md);padding-top:16px;
 background:linear-gradient(180deg,#ffffff10,#00000010);border:1px dashed #8a7d7088}
.reach.washed{background:linear-gradient(180deg,color-mix(in srgb,var(--w0c1) 30%,transparent),color-mix(in srgb,var(--w1c1,var(--w0c1)) 22%,transparent));border:1px solid color-mix(in srgb,var(--w0c1) 60%,transparent)}
/* the Reach name sits in the slot's own 16px top strip (desktop): clear of the slot's border line and of the card,
   even of a target card's 6px outline */
.reach .rlabel{position:absolute;left:6px;top:2px;line-height:1;font-size:var(--fs-2xs);text-transform:uppercase;letter-spacing:.6px;color:var(--text-2);z-index:3;pointer-events:none}
.reach .saltmark{position:absolute;right:4px;top:1px;z-index:4;font-size:10px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:#6d6248;background:#f4f0e4;border:1px solid #b7a88a;border-radius:3px;padding:0 3px;line-height:1.3;pointer-events:none}
.placepop{position:fixed;z-index:40;left:50%;bottom:calc(var(--dockh, 0px) + 12px);transform:translateX(-50%);width:min(420px, calc(100vw - 24px));background:#fbf7f0;color:#2c2416;border:2px solid #8a6a3b;border-radius:8px;padding:8px 10px;font-size:13px;line-height:1.35;box-shadow:0 6px 18px #1d171266}
.placepop .kind{font-size:11px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:#6d5428}
.placepop p{margin:3px 0 0}.placepop .lbl{font-weight:700}
body.land .placepop{left:auto;right:108px;bottom:10px;transform:none;width:min(360px, calc(100vw - 140px));font-size:12px}
body.land .reach .rlabel{display:block;top:1px;font-size:13px;letter-spacing:.15px;line-height:1}
.reach .ink{position:absolute;left:50%;width:2px;height:6px;background:var(--bronze2);opacity:.6;pointer-events:none}
#r-oppassets .reach .ink{bottom:-5px}#r-myassets .reach .ink{top:-5px}
.reach .layers{position:absolute;right:3px;top:2px;display:flex;flex-direction:column;gap:2px;z-index:4;align-items:flex-end}
.reach .zonedrop.small{position:absolute;left:4px;bottom:4px;z-index:5}
.layer{display:flex;align-items:center;gap:3px;background:#fbf7f0e6;border:1.5px solid var(--c1);border-radius:var(--r-sm);padding:1px 4px 1px 1px;font-size:var(--fs-2xs);cursor:help;max-width:150px}
.layer .art.mini{width:28px;height:18px}.layer b{white-space:normal;overflow-wrap:normal;line-height:1.1;padding-right:1px}  /* (1px: fitText needs the text to end inside its box, or a one-line name shrinks to the floor) */
.zonedrop.small{height:24px;font-size:var(--fs-sm);padding:0 6px;border-width:2px}
/* the Heart dais */
#dominion .heart{border-radius:40px;padding:4px 22px;background:radial-gradient(ellipse at 50% 50%,#f3e6c6,#cdbd9f 70%);border:2px solid var(--bronze);box-shadow:inset 0 0 12px #a8742f55}
#dominion .heart.h0{box-shadow:inset 0 0 14px #3d6f9a88,0 0 10px #3d6f9a66;border-color:#3d6f9a}
#dominion .heart.h1{box-shadow:inset 0 0 14px #9e2b2588,0 0 10px #9e2b2566;border-color:#9e2b25}
#dominion .cq{flex-direction:row;gap:10px}
#dominion .rr{display:flex;flex-direction:column;align-items:center;font-size:var(--fs-xs);cursor:help}
.ring{width:40px;height:40px}.ring .bg{fill:#efe3c8;stroke:#9c8f80;stroke-width:4}
.ring .seg{fill:none;stroke:#b7aa98;stroke-width:4}.ring.p0 .seg.on{stroke:#3d6f9a}.ring.p1 .seg.on{stroke:#9e2b25}
.ring text{font-size:var(--fs-sm);font-weight:800;text-anchor:middle;fill:#3b2a12}
#dominion .info{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
#dominion .info .layers{display:flex;gap:4px}
/* the Heart strip's numbers (owner 2026-10-19): three different stats, three colors from the board's own palette, each
   on a small solid parchment pill so the contrast never depends on where the strip's gradient sits (ratios: PR body) */
#dominion .hinfo{display:flex;flex-direction:column;align-items:flex-end;gap:3px;min-width:0}
#dominion .hrules{display:block}
#dominion .hstats{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:4px}
.hstat{display:inline-flex;align-items:baseline;gap:3px;padding:1px 7px;border-radius:999px;background:#efe3c8;border:1px solid;white-space:nowrap;line-height:var(--lh-snug)}
.hstat .lbl,.hstat .num{color:inherit}
.hstat .subtext{color:#3d342d}
.hstat.hs-atk{color:#8a1c14;border-color:#b5523f}
.hstat.hs-claim{color:#5e4300;border-color:#b88a2a}
.hstat.hs-turn{color:#1d4b78;border-color:#6f93b8}
/* desktop: the realm laid on the Heart is a readable tile (owner 2026-10-19: it was a 28x18 thumbnail with a 7px name);
   hover shows the full card tooltip with its art, Enter / click opens it, as on every other realm badge */
@media (min-width:901px) and (min-height:501px){
 #dominion{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr)}
 #dominion .cq > .layers{margin-left:auto;display:flex;gap:6px;min-width:0}
 #dominion .layer.hl{gap:6px;padding:2px 8px 2px 2px;max-width:220px;border-width:2px;font-size:var(--fs-sm)}
 #dominion .layer.hl .art.mini{width:88px;height:50px;margin:0}   /* 16:9, the Dominion row keeps its 66px */
 #dominion .layer.hl b{font-size:var(--fs-sm);line-height:var(--lh-tight);max-width:110px}
 #dominion .info .hinfo{font-size:var(--fs-md)}   /* (13.5px: the realm rule line and the three stats) */
}
/* fusion reveal + Codex */
.reveal{text-align:center;position:relative}
.reveal .cards{justify-content:center;margin:8px 0}
.reveal h2{font-size:24px;letter-spacing:1px}
.reveal .burst{position:absolute;inset:-16px;background:radial-gradient(circle at 50% 45%,#f6e2a6aa,transparent 60%);pointer-events:none;animation:burst 1.6s ease-out}
@keyframes burst{0%{opacity:0;transform:scale(.6)}40%{opacity:1}100%{opacity:.5;transform:scale(1)}}
.codextag{font-weight:800;color:#7a4c06;letter-spacing:.5px}
.codex{display:flex;flex-wrap:wrap;gap:8px}
.cx{display:flex;flex-direction:column;align-items:center;gap:2px}
.cx .cxs{font-size:var(--fs-sm);font-weight:700;color:#5a3a0e}.cx.mastered .cxs{color:#7a4c06}
.cx.silhouette{width:110px;height:150px;border-radius:var(--r-md);justify-content:center;cursor:help;padding:6px;text-align:center;
 background:linear-gradient(115deg,color-mix(in srgb,var(--c1) 40%,#2e2620) 50%,color-mix(in srgb,var(--d1) 40%,#2e2620) 50%);color:#d8ccb4;border:2px solid #5a4e44}
.cx.silhouette .sym{font-size:44px;opacity:.6}.cx.silhouette small{font-size:var(--fs-xs);line-height:var(--lh-snug)}
@media (prefers-reduced-motion:reduce){
 *,*::before,*::after{animation:none!important;transition:none!important}
}

/* ======================= Main menu, New Game, deck builder, rules, settings (ui/menu.js) ======================= */
/* Settings: animation speed scales the board effects; reduced motion switches them off */
.ghost{animation-duration:calc(1.3s * var(--anim,1))}
.ascended{animation-duration:calc(1.6s * var(--anim,1))}
#log .fresh{animation-duration:calc(1.5s * var(--anim,1))}
.reveal .burst{animation-duration:calc(1.6s * var(--anim,1))}
.target,.card.target-own,.card.target-fuse{animation-duration:calc(1s * var(--anim,1))}
body.reduced-motion *,body.reduced-motion *::before,body.reduced-motion *::after{animation:none!important;transition:none!important}
body.inmenu{overflow:hidden}
#menubtn,#morebtn,#newgame,#codexbtn,#legendbtn,#rulesbtn,#logbtn,#modalclose{font-size:13px}
#menubtn{font-weight:700;background:#2a211b;color:#f1dfb8;border-color:var(--bronze)}#menubtn:hover{background:#3a2e25}

.screen{--ink:#eadfca;--ink2:#b9a98f;--gold:#e1b864;--panelbg:#1b1612e6;position:fixed;inset:0;z-index:60;overflow:auto;color:var(--ink);
 background:radial-gradient(ellipse at 50% 0%,#2b221b,#0e0b09 70%);font-family:var(--font-ui)}
.screen .muted{color:var(--ink2)}
.screen a{color:var(--gold)}
.screen button,.screen select,.screen input{background:#2a221c;color:var(--ink);border:1px solid #6d5a44;border-radius:var(--r-md)}
.screen button:hover:not(:disabled){background:#3a2f26;border-color:var(--gold)}
.screen button.primary{background:linear-gradient(#b8843a,#8a5d22);color:#fff8ea;border-color:#e1b864}
#st-collectibles{font-size:13px}
.screen button.primary:hover:not(:disabled){background:linear-gradient(#cc9649,#9b6a29)}
.screen button:disabled{opacity:.45;cursor:not-allowed}
.screen h1,.screen h2,.screen h3{font-family:var(--font-display);font-weight:700;letter-spacing:.5px}
/* title screen */
.mn-bg{position:absolute;inset:0;overflow:hidden;background:#0e0b09}
.mn-slide{position:absolute;inset:-4%;background-size:cover;background-position:center;opacity:1;animation:none;filter:saturate(1.05) contrast(1.05)}
.mn-vignette{position:absolute;inset:0;background:linear-gradient(90deg,#0b0907f2 0%,#0b0907c4 34%,#0b090733 70%,#0b090799 100%),radial-gradient(ellipse at 70% 40%,transparent 30%,#000a 100%)}
.mn-wrap{position:relative;z-index:2;height:100%;display:flex;flex-direction:column;justify-content:center;padding:0 7vw;gap:28px;max-width:640px}
.mn-crest{display:flex;gap:6px;margin-bottom:6px}.mn-crest .emb{width:26px;height:26px;font-size:var(--fs-md);box-shadow:0 0 8px #0008}
.mn-title h1{margin:0;font-size:64px;line-height:1;color:#f6e7c1;text-shadow:0 2px 0 #5a3a0e,0 0 24px #e1b86466;letter-spacing:3px}
.mn-title h2{margin:6px 0 10px;font-size:var(--fs-xl);font-weight:400;color:var(--gold);letter-spacing:6px;text-transform:uppercase}
.mn-title p{margin:0;color:#d8cab0;font-size:var(--fs-md);line-height:var(--lh-body);max-width:440px;text-shadow:0 1px 2px #000}
.mn-nav{display:flex;flex-direction:column;gap:8px;width:320px}
.mn-btn{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:9px 16px!important;border-radius:var(--r-sm)!important;text-align:left;
 background:linear-gradient(90deg,#1f1813ee,#1f181399)!important;border:1px solid #6d5a44!important;border-left:4px solid var(--gold)!important;transition:transform .15s,background .15s}
.mn-btn b{font-family:var(--font-display);font-size:var(--fs-lg);letter-spacing:1px;color:#f6e7c1}
.mn-btn small{font-size:var(--fs-sm);color:var(--ink2)}
.mn-btn:hover:not(:disabled){transform:translateX(6px);background:linear-gradient(90deg,#3a2c1fee,#3a2c1f99)!important}
.mn-btn.primary{background:linear-gradient(90deg,#7a5420ee,#3a2a17aa)!important;border-color:#e1b864!important}
.mn-foot{position:absolute;bottom:14px;left:7vw;z-index:2;font-size:var(--fs-sm);color:#a8977b;letter-spacing:1px}
/* desktop/tablet: centre the title and buttons in the space ABOVE the absolute footer, so Exit never reaches the
   footer line; on shorter screens (768/720 px high) the same layout with tighter spacing so all 8 buttons still fit */
@media (min-width:481px) and (min-height:501px){
 .mn-wrap{box-sizing:border-box;padding-top:12px;padding-bottom:64px}
}
@media (min-width:481px) and (min-height:501px) and (max-height:820px){
 .mn-wrap{gap:16px}
 .mn-nav{gap:6px}
 .mn-btn{padding:6px 16px!important}
 .mn-crest{margin-bottom:4px}
 .mn-title h1{font-size:56px}
 .mn-title h2{margin:4px 0 8px}
}
@media (min-width:481px) and (min-height:501px) and (max-height:740px){
 .mn-wrap{gap:12px}
 .mn-nav{gap:4px}
 .mn-btn{padding:4px 16px!important}
 .mn-title h1{font-size:48px}
}
.bye{position:relative;z-index:2;height:100%;display:flex;flex-direction:column;justify-content:center;padding:0 8vw;max-width:640px;gap:6px}
.bye h1{font-size:48px;margin:0;color:#f6e7c1}.bye .mn-btn{width:260px;margin-top:10px}
/* generic page (settings, rules, new game) */
.pg{max-width:1000px;margin:0 auto;padding:18px 24px 40px}.pg.wide{max-width:1180px}
.pg-head{display:flex;align-items:center;gap:16px;margin-bottom:14px;border-bottom:1px solid #6d5a44;padding-bottom:10px}
.pg-head h1{margin:0;font-size:28px;color:#f6e7c1}
.pg-head .tabs{margin-left:auto}
.pg-back{font-weight:700}
.pg-card{background:var(--panelbg);border:1px solid #6d5a44;border-radius:var(--r-lg);padding:14px 18px;box-shadow:0 6px 24px #0007}
.tabs{display:inline-flex;gap:0}.tabs button{border-radius:0;margin-left:-1px}.tabs button:first-child{border-radius:var(--r-md) 0 0 6px}.tabs button:last-child{border-radius:0 6px 6px 0}
.tabs button.on{background:#6d4c1f;border-color:var(--gold);color:#fff3d6;font-weight:700}
.st-row{display:flex;justify-content:space-between;align-items:center;gap:20px;padding:12px 0;border-bottom:1px solid #3a3028}
.st-row b{display:block;font-size:var(--fs-lg)}.st-row small{color:var(--ink2);font-size:var(--fs-sm)}
.st-row select{min-width:160px}.st-row input[type=range]{width:160px;vertical-align:middle}.st-val{display:inline-block;width:44px;text-align:right}
.st-foot{display:flex;gap:10px;align-items:center;padding-top:12px}
.switch{position:relative;display:inline-block;width:46px;height:24px}.switch input{opacity:0;width:0;height:0}
.switch span{position:absolute;inset:0;background:#3a3028;border:1px solid #6d5a44;border-radius:var(--r-lg);cursor:pointer;transition:.2s}
.switch span::before{content:"";position:absolute;left:3px;top:3px;width:16px;height:16px;border-radius:50%;background:#b9a98f;transition:.2s}
.switch input:checked+span{background:#7a5420;border-color:var(--gold)}.switch input:checked+span::before{left:25px;background:#fff3d6}
/* rules */
.rl-body.withtoc{display:grid;grid-template-columns:220px 1fr;gap:16px;align-items:start}
.rl-toc{position:sticky;top:10px;display:flex;flex-direction:column;gap:2px;background:var(--panelbg);border:1px solid #6d5a44;border-radius:var(--r-lg);padding:10px}
.rl-sec{display:none}   /* (small screens only: the Sections drop-down, see the mobile block) */
.rl-toc a{text-decoration:none;font-size:var(--fs-md);padding:3px 6px;border-radius:var(--r-sm)}.rl-toc a:hover{background:#3a2f26}
.rl-text{line-height:var(--lh-body);font-size:var(--fs-md)}.rl-text h2{color:#f6e7c1;margin:0 0 8px;font-size:24px}.rl-text h3{color:var(--gold);margin:18px 0 6px;font-size:var(--fs-xl)}.rl-text h4{color:#e9cf96;margin:12px 0 4px}
.rl-text p,.rl-text li{font-size:var(--fs-md);line-height:var(--lh-body)}.rl-text code{background:#2e261f;padding:0 4px;border-radius:var(--r-sm);font-size:var(--fs-sm);color:#f1d59a}
.rl-text b{color:#fff1d0}.rl-text .md-table{overflow:auto}
.rl-text table{border-collapse:collapse;margin:6px 0;font-size:var(--fs-sm)}.rl-text th,.rl-text td{border:1px solid #4d4033;padding:4px 7px;text-align:left}.rl-text th{background:#2e261f}
.rl-text .cycle,.rl-text .legend{color:var(--text)}.rl-text .legend .lf{color:#1d1814}.rl-text .cycle{color:var(--ink)}
.rl-text p.md-note{font-size:var(--fs-sm);line-height:1.45;color:#b9ab93;margin:2px 0 10px;padding-left:10px;border-left:2px solid #4d4033}
.rl-text :is(h2,h3,h4){scroll-margin-top:90px}
/* new game */
.ng{display:grid;grid-template-columns:1.4fr 1fr;gap:16px;align-items:start}
.ng h3{margin:0 0 10px;color:var(--gold)}
.ng-list{display:flex;flex-direction:column;gap:6px;max-height:calc(100vh - 210px);overflow:auto;padding-right:4px}
.ng-group{margin:8px 2px 0;color:var(--gold);font-size:13px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}
.ng-deck{display:flex;align-items:center;gap:10px;padding:7px 10px;border:1px solid #4d4033;border-radius:var(--r-md);cursor:pointer;background:#231c17}
.ng-deck:has(input:checked){border-color:var(--gold);background:#3a2c1f;box-shadow:0 0 0 1px var(--gold)}
.ng-deck.invalid{opacity:.5;cursor:not-allowed}
.ng-deck b{display:block}.ng-deck small{color:var(--ink2);font-size:var(--fs-sm)}
.ng-embs{display:flex;gap:2px;min-width:46px}
.ng-opts{display:flex;flex-direction:column;gap:12px}.ng-opts label{display:flex;flex-direction:column;gap:4px;font-size:var(--fs-sm);color:var(--ink2)}
.ng-opts select,.ng-opts input{font-size:var(--fs-md);padding:6px 8px}
.ng-err{color:#ff9a8a;font-size:var(--fs-md);min-height:1em}
/* deck builder */
.scr-deck{overflow:hidden}
.db{height:100vh;display:flex;flex-direction:column}
.db-top{display:flex;align-items:center;gap:10px;padding:8px 96px 8px 12px;border-bottom:1px solid #6d5a44;background:linear-gradient(#211a15,#16120f);position:relative;min-height:62px}
.db-top h1{margin:0;font-size:var(--fs-xl);color:#f6e7c1;white-space:nowrap}
#db-name{width:190px;font-size:var(--fs-md);padding:5px 8px}
.db-actions{display:flex;gap:5px;flex-wrap:wrap}.db-actions button,.db-actions select{padding:4px 9px}
.db-main{flex:1;min-height:0;display:grid;grid-template-columns:1fr 330px}
.db-left{display:flex;flex-direction:column;min-height:0;border-right:1px solid #4d4033}
.db-filters{padding:8px 12px 6px;display:flex;flex-direction:column;gap:5px;border-bottom:1px solid #3a3028;background:#17130fcc}
.frow{display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.frow #db-q{width:250px;padding:5px 8px}.frow .tabs{margin-left:8px}
.flabel{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.7px;color:var(--ink2);width:50px}
.frow .flabel+.fchip{margin-left:0}.frow .fchip+.flabel{margin-left:14px}
.fchip{display:inline-flex;align-items:center;gap:4px;padding:2px 9px 2px 3px!important;border-radius:var(--r-lg)!important;font-size:var(--fs-sm);text-transform:capitalize}
.fchip[data-f=cost]{padding:2px 9px!important;min-width:30px;justify-content:center}.fchip[data-f=type]{padding-left:8px!important}
.fchip .emb{width:18px;height:18px;font-size:var(--fs-xs)}
.fchip.on{background:#6d4c1f!important;border-color:var(--gold)!important;color:#fff3d6;box-shadow:0 0 6px #e1b86466}
/* the filter picker (owner, UI round 3): a group list, that group's values and Add; each active value is a chip that
   removes it (the same .fchip and handler as before). Native selects (iOS shows its own picker), 44 px tap targets */
.db-fpick{flex-wrap:nowrap;font-size:var(--fs-md)}
.db-fpick select,#db-fadd{font-size:var(--fs-md);min-height:44px}
#db-ftype{flex:0 1 auto;min-width:0}#db-fval{flex:0 1 220px;min-width:0}#db-fadd{flex:none;padding:0 16px}
.db-fact:empty{display:none}
.db-fact .fchip>span[aria-hidden]{margin-left:3px;font-size:var(--fs-md);line-height:1}
.db-grid{flex:1;overflow:auto;padding:10px 12px 30px;display:flex;flex-wrap:wrap;gap:12px 10px;align-content:flex-start;--ch:182px;--cw:166px}
.db-cell{position:relative;cursor:pointer;border-radius:var(--r-md)}
/* hover lifts the card only: the cell (and its - / + row) stays put, so the pointer never slips off the lifted box */
.db-cell .card{transition:transform .12s}
.db-cell:hover .card{transform:translateY(-3px);box-shadow:0 0 0 2px var(--gold),0 6px 16px #000a}
.db-cell.indeck .card{box-shadow:0 0 0 2px #7fc28e,0 3px 10px #000a}
.db-cell.maxed .card{filter:saturate(.55) brightness(.75)}
body.touch-ui .db-cell:hover .card{transform:none}
.db-guide{flex:1;overflow:auto;padding:12px 14px 30px}
.tg-intro{display:grid;grid-template-columns:1fr 1fr;gap:6px 18px;background:#241c16;border:1px solid #6d5a44;border-radius:var(--r-md);padding:10px 14px;margin-bottom:12px;font-size:var(--fs-md);line-height:var(--lh-body)}
.tg-intro b{color:var(--gold)}
.tg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:10px}
.tg-card{background:var(--panelbg);border:1px solid #4d4033;border-left:4px solid var(--gold);border-radius:var(--r-md);padding:8px 12px}
.tg-card h3{margin:0 0 4px;font-size:var(--fs-lg);color:#f6e7c1;display:flex;align-items:center;gap:8px}
.tg-card h3 small{margin-left:auto;font-family:var(--font-ui);font-weight:400;font-size:var(--fs-sm);color:var(--ink2);letter-spacing:0}
.tg-ic{display:inline-flex;width:24px;height:24px;border-radius:50%;background:#3a2c1f;border:1px solid var(--gold);align-items:center;justify-content:center;font-size:var(--fs-md);color:var(--gold)}
.tg-card p{margin:4px 0;font-size:var(--fs-sm);line-height:var(--lh-body)}.tg-card p b{color:var(--gold)}
.db-right{display:flex;flex-direction:column;min-height:0;padding:10px 12px;gap:8px;background:#15110ecc;overflow:auto}
.dp-head{display:flex;align-items:center;gap:10px}
.dp-count{font-size:var(--fs-lg);color:var(--ink2)}.dp-count b{font-size:30px;color:#f6e7c1;font-family:var(--font-display)}.dp-count.full b{color:#9fe0ad}
.dp-facs{display:flex;gap:4px;flex-wrap:wrap}.dp-facs .facchip{background:#2a221c;color:var(--ink)}
.dp-valid{border-radius:var(--r-md);padding:6px 9px;font-size:var(--fs-sm);line-height:var(--lh-body)}
.dp-valid.ok{background:#1f3a26;border:1px solid #6fbf80;color:#c9f2d1;font-weight:700}
.dp-valid.bad{background:#3a1d1a;border:1px solid #c0645a;color:#ffd4cc}
.dp-local{border-radius:var(--r-md);padding:5px 9px;margin-bottom:6px;font-size:var(--fs-sm);line-height:var(--lh-body);background:#3a311a;border:1px solid #c9a14a;color:#ffe9b8}
.dp-local[hidden]{display:none}
.dp-stats{display:flex;flex-direction:column;gap:7px}
.dp-curve small{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.6px;color:var(--ink2)}
.dp-curve .bars{display:flex;gap:5px;height:70px;align-items:flex-end;padding-top:12px}
.dp-curve .bar{flex:1;height:100%;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;position:relative}
.dp-curve .bar i{width:100%;background:linear-gradient(#e1b864,#8a5d22);border-radius:var(--r-sm) 3px 0 0;min-height:2px}
.dp-curve .bar b{position:absolute;top:-2px;font-size:var(--fs-sm);color:#f6e7c1}
.dp-curve .bar span{font-size:var(--fs-xs);color:var(--ink2);margin-top:2px}
.dp-types{display:flex;flex-wrap:wrap;gap:4px}
.tchip{font-size:var(--fs-sm);background:#2a221c;border:1px solid #4d4033;border-radius:var(--r-lg);padding:1px 7px;cursor:help;white-space:nowrap}
.tchip b{color:#f6e7c1}.tchip small{color:var(--ink2)}.tchip.bad{border-color:#e07062;background:#4a1f1a}
.dp-facbar{display:flex;height:10px;border-radius:var(--r-sm);overflow:hidden;background:#2a221c;gap:1px}
.dp-faclegend{display:flex;gap:8px;flex-wrap:wrap;font-size:var(--fs-sm)}.dp-faclegend .emb{width:16px;height:16px;font-size:var(--fs-2xs)}
.dp-list{display:flex;flex-direction:column;gap:6px;padding-bottom:20px}
.dl-group h4{margin:4px 0 3px;font-size:var(--fs-sm);text-transform:uppercase;letter-spacing:.7px;color:var(--gold);display:flex;align-items:center;gap:5px;cursor:help}
.dl-group h4 b{margin-left:auto;color:var(--ink)}.dl-group h4 b.bad{color:#ff9a8a}
.dl-row{display:flex;align-items:center;gap:5px;padding:2px 4px 2px 2px;border-radius:var(--r-sm);background:linear-gradient(90deg,color-mix(in srgb,var(--c1) 45%,#1b1612),#1b1612 70%);border:1px solid #3a3028;margin-bottom:2px;font-size:var(--fs-sm)}
.dl-row:hover{border-color:var(--gold)}
.dl-cost{width:18px;height:18px;border-radius:50%;background:#f7efdf;color:#3b2a12;font-weight:800;font-size:var(--fs-xs);display:flex;align-items:center;justify-content:center;border:1.5px solid var(--bronze);flex:none}
.dl-row .emb{width:16px;height:16px;font-size:var(--fs-2xs)}
.dl-nm{flex:1;min-width:0;white-space:normal;overflow-wrap:normal;line-height:1.15}
.dl-n{font-weight:700;color:#f6e7c1}
.dl-row button{width:24px;height:24px;padding:0!important;font-weight:800;line-height:1;position:relative}
/* touch targets (audit AUD-A11Y-3): with a mouse the deck-list -/+ stay compact (24px, the WCAG 2.5.8 minimum); any touch
   screen (also a touch laptop) gets real 44x44px buttons, see .touch-ui below and the any-pointer rule */
@media (any-pointer:coarse){.dl-row button{width:44px;height:44px}.db-minus::after{content:"";position:absolute;inset:-10px;border-radius:50%}}  /* (the grid's - keeps its 24px badge look; a 44px hit area) */
.db-toast{position:fixed;left:50%;bottom:22px;transform:translate(-50%,30px);opacity:0;z-index:70;background:#1f3a26;border:1px solid #6fbf80;color:#e6ffe9;padding:8px 16px;border-radius:var(--r-md);font-size:var(--fs-md);transition:all .25s;pointer-events:none}
.db-toast.show{opacity:1;transform:translate(-50%,0)}.db-toast.bad{background:#4a1f1a;border-color:#e07062;color:#ffe1db}
.db-preview{position:fixed;z-index:75;pointer-events:none;filter:drop-shadow(0 10px 24px #000c)}
.db-preview .card.lg{width:260px}
.db-more,.db-morepanel{display:none}   /* (devices held sideways only: see the landscape block) */
/* the faction wheel glyph (deck builder corner) */
.wheel-box{position:absolute;right:10px;top:3px;z-index:20}
.wheel-mini{width:58px;height:58px;cursor:zoom-in;border-radius:50%;transition:transform .15s}
.wheel-mini:hover{transform:scale(1.08)}
.wheel{width:100%;height:100%;display:block}
.wh-disc{fill:#1b1612;stroke:#a8742f;stroke-width:3}
.wh-ring{fill:none;stroke:#6d5a44;stroke-width:1.5}
.wh-arrow{fill:none;stroke:#e1b864;stroke-width:3.2}
.wheel.big .wh-arrow{stroke-width:2.2}
.wh-opp{stroke:#c9b79a;stroke-width:1.4;stroke-dasharray:4 4;opacity:.45}
.wh-node.dim{opacity:.42}
.wh-lbl{fill:#d8cab0;font-size:var(--fs-xs);font-weight:700;letter-spacing:.5px}
.wh-mid{fill:#b9a98f;font-size:var(--fs-2xs)}
.wheel-pop{display:none;position:absolute;right:0;top:64px;width:420px;background:#17130ff7;border:1px solid var(--gold);border-radius:var(--r-lg);padding:12px 16px;box-shadow:0 14px 40px #000c}
.wheel-box:hover .wheel-pop,.wheel-box.pinned .wheel-pop{display:block}
.wheel-pop h3{margin:0 0 4px;color:#f6e7c1;font-size:var(--fs-lg)}
.wheel-pop .wheel{width:260px;height:260px;margin:0 auto}
.wh-key{display:flex;flex-direction:column;gap:3px;font-size:var(--fs-sm);color:#d8cab0;margin:4px 0 8px}
.wh-key i{display:inline-block;width:22px;height:0;vertical-align:middle;margin-right:7px}
.wh-key .k-arrow{border-top:3px solid #e1b864}.wh-key .k-opp{border-top:2px dashed #c9b79a}.wh-key .k-on{width:12px;height:12px;border:2px solid #f2d27a;border-radius:50%;box-shadow:0 0 6px #f2d27a}
.wh-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.wh-list li{display:flex;gap:8px;align-items:flex-start;font-size:var(--fs-sm);line-height:var(--lh-snug);color:#cbbda4;padding:3px 5px;border-radius:var(--r-sm)}
.wh-list li.on{background:#3a2c1f;color:#fff1d0;box-shadow:inset 3px 0 0 #f2d27a}
.wh-list .emb{width:18px;height:18px;font-size:var(--fs-xs);margin-top:1px}
@media (max-width:1150px){.db-main{grid-template-columns:1fr 290px}.db-actions button{padding:3px 6px}}
/* first-launch notice, decline screen, legal reader, loading screen */
.ln-wrap{min-height:100%;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box}
.ln-box{max-width:620px;width:100%;padding:26px 32px}
.ln-box h1{margin:4px 0 0;font-size:40px;color:#f6e7c1;letter-spacing:3px;text-shadow:0 2px 0 #5a3a0e,0 0 24px #e1b86444}
.ln-box h2{margin:2px 0 14px;font-size:var(--fs-md);font-weight:400;color:var(--gold);letter-spacing:5px;text-transform:uppercase}
.ln-box h3{margin:6px 0 8px;color:var(--gold);font-size:var(--fs-xl)}
.ln-box p{line-height:var(--lh-body);font-size:var(--fs-md)}
.ln-list{margin:0 0 10px;padding-left:20px;line-height:var(--lh-body);font-size:var(--fs-md)}.ln-list li{margin:6px 0}.ln-list b{color:#fff1d0}
.ln-btns{display:flex;gap:10px;margin-top:16px}.ln-btns .mn-btn{flex:1}
.ln-ver{font-size:var(--fs-sm);margin:14px 0 0}.ln-dev{font-size:var(--fs-sm)}
.mn-legal{margin-top:4px;letter-spacing:.3px}.mn-legal a{color:#c9b48c;text-decoration:none}.mn-legal a:hover{color:var(--gold);text-decoration:underline}
.st-legal{margin-top:14px}.st-links a{white-space:nowrap}
.screen button.danger{background:#5a1f17;border-color:#b5523f;color:#ffe2d8}.screen button.danger:hover:not(:disabled){background:#74291f;border-color:#ff9a8a}
.lg-text{max-width:860px;margin:0 auto}.lg-text a{color:var(--gold)}
.lg-web{margin:18px 0 2px;padding-top:10px;border-top:1px solid #4d4033;font-size:var(--fs-sm)}
.ld-box{max-width:520px;width:100%;padding:26px 32px;text-align:left}
.ld-bar{height:12px;border-radius:var(--r-md);background:#2a221c;border:1px solid #6d5a44;overflow:hidden;margin:14px 0 8px}
.ld-bar i{display:block;height:100%;width:0;background:linear-gradient(90deg,#8a5d22,#e1b864);transition:width .25s}
.ld-bar.indet i{width:30%!important;animation:ldindet 1.2s infinite ease-in-out}
@keyframes ldindet{0%{transform:translateX(-100%)}100%{transform:translateX(340%)}}
.ld-stage{font-size:var(--fs-lg);color:#fff1d0}.ld-detail{font-size:var(--fs-sm);color:var(--ink2);min-height:1.2em}
.ld-err{color:#ff9a8a;font-size:var(--fs-md);white-space:pre-wrap}
.ld-err[data-stall]{color:#f3d9a8}  /* the stall notice (bridge.js): a hint with Try again, not an error */

/* ======================= Opponent styles (lore names) ======================= */
.ailine{font-size:var(--fs-sm);color:var(--text-2);font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:help;margin-top:-4px}
.ng-ai{display:flex;flex-direction:column;gap:6px}
.ng-lbl{font-size:var(--fs-sm);color:var(--ink2)}
.ng-ailist{display:flex;flex-direction:column;gap:5px}
.ng-opts label.ng-aiopt{flex-direction:row;align-items:flex-start;gap:9px;padding:7px 10px;border:1px solid #4d4033;border-radius:var(--r-md);background:#231c17;cursor:pointer;color:var(--ink)}
.ng-aiopt:has(input:checked){border-color:var(--gold);background:#3a2c1f;box-shadow:0 0 0 1px var(--gold)}
.ng-aiopt input{margin:3px 0 0;accent-color:#e1b864;flex:none}
.ng-aiopt b{color:#f6e7c1;font-family:var(--font-display);font-size:var(--fs-md);letter-spacing:.3px}
.ng-tag{color:var(--gold);font-size:var(--fs-sm);white-space:nowrap}
.ng-aiopt small{display:block;color:var(--ink2);font-size:var(--fs-sm);line-height:var(--lh-snug);margin-top:2px}
.ng-legacy summary{cursor:pointer;color:var(--ink2);font-size:var(--fs-sm);padding:4px 0;list-style:none}
.ng-legacy summary::-webkit-details-marker{display:none}
.ng-legacy summary::before{content:"\25B8";display:inline-block;width:1.2em;color:var(--gold);font-family:"DejaVu Sans","Noto Sans Symbols 2",sans-serif}
.ng-legacy[open] summary::before{content:"\25BE"}
.ng-legacy .ng-ailist{margin-top:5px}
.ng-aidesc{font-size:var(--fs-sm);line-height:var(--lh-snug);color:var(--ink2)}

/* ======================= Touch + small screens (phones, tablets) =======================
   Desktop (mouse, window wider than 900px and taller than 500px) is untouched: everything below is either hidden
   there (.mobile-only, #sheet, #actdock), keyed on body.touch-ui (no hover), or inside the compact media query. */
.mobile-only{display:none}
button,a,select,input,label,summary,textarea,.card,.chip,.slotbox,.zonedrop,.db-cell,.dl-row,.wheel-mini,.st,.reach{touch-action:manipulation}  /* no double-tap zoom delay; pinch zoom stays */
/* Long-press on touch (iOS Safari, Android Chrome): no text selection, no copy / look-up / save-image callout and no
   image drag on the game UI, cards, board, hand, buttons, deck builder and chips. body.touched is set by the first
   touch (covers touch laptops that also have a mouse). The readers (rules, terms, privacy), card detail text and
   text inputs stay selectable. */
.touch-ui,.touched{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
.touch-ui img,.touched img{-webkit-user-drag:none;-webkit-touch-callout:none}
/* T39 step 3: card art offers no long-press "Save image" callout or drag, touch or not (deterrence, not DRM) */
.art,.art img,img[data-art],.fx-ftile img,.cb-art,.cb-art img{-webkit-touch-callout:none;-webkit-user-drag:none;-webkit-user-select:none;user-select:none}
img[data-pend]{visibility:hidden}
.touch-ui :is(input,textarea,[contenteditable],.rl-text,.lg-text,.ln-box p,.ln-list,.sheet-text,#modal-body p,#modal-body li),
.touched :is(input,textarea,[contenteditable],.rl-text,.lg-text,.ln-box p,.ln-list,.sheet-text,#modal-body p,#modal-body li){-webkit-touch-callout:default;-webkit-user-select:text;user-select:text}
/* card detail sheet (tap a card on a touch screen) */
#sheet{position:fixed;inset:0;z-index:95;background:#2e2620aa;display:flex;align-items:flex-end;justify-content:center}
.sheet-box{position:relative;width:100%;max-width:520px;max-height:calc(100dvh - 16px - env(safe-area-inset-top));overflow:auto;overscroll-behavior:contain;background:#efe7da;color:var(--text);
 border-radius:var(--r-lg) 16px 0 0;border:2px solid var(--bronze);border-bottom:0;padding:10px calc(14px + env(safe-area-inset-right)) calc(14px + env(safe-area-inset-bottom)) calc(14px + env(safe-area-inset-left));box-shadow:0 -8px 30px #0008;animation:sheetup .22s ease-out}
@keyframes sheetup{from{transform:translateY(40px);opacity:.4}}
.sheet-close{position:sticky;top:0;float:right;z-index:4;min-height:44px;min-width:44px;font-weight:700;font-size:var(--fs-md);box-shadow:0 2px 6px #0003}
.sheet-card{display:flex;justify-content:center;clear:both;padding-top:4px}
.sheet-card .card.lg{width:min(300px,100%);min-height:0}
.sheet-text p{margin:6px 0;font-size:var(--fs-lg);line-height:var(--lh-body);overflow-wrap:anywhere}
.sheet-ctl{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:10px;position:sticky;bottom:-14px;background:#efe7da;padding:8px 0 10px;font-size:var(--fs-lg)}
.sheet-ctl button{min-height:48px;min-width:112px;font-size:var(--fs-lg);font-weight:700}
.sheet-ctl button.danger{background:#7d2620;color:#fff;border-color:#4d1410}
.sheet-ctl button:disabled{opacity:.45}
.sheet-note{font-size:var(--fs-md);color:#7d2620;margin:4px 0 0}
.infobtn{position:absolute;right:3px;top:26px;z-index:4;width:44px;height:44px;padding:0;border-radius:50%;font-size:var(--fs-xl);line-height:1;background:#fbf7f0;border:2px solid var(--bronze);box-shadow:0 2px 6px #0006}
/* deck builder on touch: Add / Remove bar under each card replaces the tiny corner buttons */
.db-ctl{display:flex;align-items:center;justify-content:space-between;gap:4px;margin-top:5px}
.db-ctl button{width:52px;min-height:44px;padding:0!important;font-size:var(--fs-xl);font-weight:800;line-height:1}
.screen .db-ctl .db-ctl-add:not(:disabled){background:#2f6b3d;border-color:#9fe0ad;color:#fff}
.db-ctl-n{font-weight:700;color:var(--ink2);font-size:var(--fs-md)}.db-cell.indeck .db-ctl-n{color:#9fe0ad}
.touch-ui .db-count{display:none}
.touch-ui .db-cell:hover{transform:none}
.touch-ui .wheel-box:not(.pinned):hover .wheel-pop{display:none}
.touch-ui .mn-btn:hover:not(:disabled){transform:none}
.touch-ui #tip{z-index:100;max-width:min(340px,calc(100vw - 16px))}
.touch-ui .dl-row button{width:44px;height:44px}
.touch-ui .dl-row{min-height:46px}

@media (max-width:900px),(max-height:500px){
 :root{
  --cw:clamp(92px,calc((100vw - 46px - env(safe-area-inset-left) - env(safe-area-inset-right))/3 - 6px),180px);
  --ch:calc((var(--cw) - 12px)*.5625 + 92px);
  --hh:128px;--hw:calc((var(--hh) - 38px)*16/9 + 12px)}
 html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-padding-bottom:calc(var(--dockh,0px) + 8px)}
 *{-webkit-tap-highlight-color:#e1b86433}
 body{min-width:0;font-size:var(--fs-md)}
 .mobile-only{display:inline-flex;align-items:center}
 button,select,input:not([type=range]):not([type=checkbox]):not([type=radio]){min-height:44px;font-size:var(--fs-md)}
 button{min-width:44px}
 input[type=range]{min-height:44px}
 .modal-box .close,#modalclose{min-width:44px;min-height:44px}

 /* header: menu + "Game" drawer (mode, AIs, seed, new game, codex, factions, rules, log) */
 header{padding:calc(4px + env(safe-area-inset-top)) calc(8px + env(safe-area-inset-right)) 4px calc(8px + env(safe-area-inset-left))!important;gap:6px}
 header h1{font-size:var(--fs-lg)}
 #setup{white-space:normal;gap:6px;flex:1 1 auto;justify-content:flex-end}
 body:not(.setup-open) #setup>:not(#menubtn):not(#morebtn):not(#watchctl){display:none}
 body.setup-open #setup{flex-basis:100%;justify-content:flex-start}
 body.setup-open #setup label{display:flex;flex-direction:column;gap:2px;flex:1 1 150px}
 body.setup-open #setup label select,body.setup-open #setup label input{width:100%}
 #seed{width:100%}
 #watchctl{flex-wrap:wrap;white-space:normal}
 #watchctl input[type=range]{width:120px}

 /* the board: one column, cards sized from the screen width */
 #app{display:flex;flex-direction:column;gap:6px;min-height:0;
  padding:6px calc(6px + env(safe-area-inset-right)) calc(var(--dockh,0px) + 14px + env(safe-area-inset-bottom)) calc(6px + env(safe-area-inset-left))}
 #stats1{order:1}#r-opphand{order:2}#r-oppzone{order:3}#r-oppassets{order:4}#r-oppmain{order:5}#dominion{order:6}
 #r-mymain{order:7}#r-myassets{order:8}#r-myzone{order:9}#stats0{order:10}#r-myhand{order:11}#logpanel{order:12}
 #logpanel,#stats1,#stats0{contain:none}
 .row{padding:17px 6px 6px!important;min-height:0}
 .row::before{top:3px;left:8px;transform:none;width:auto;font-size:var(--fs-2xs);white-space:nowrap}
 .assetsrow::before{display:none}
 .assetsrow{padding-top:6px!important;gap:4px}
 .zonerow,.handrow:not(.mine){min-height:62px}
 .reach{height:auto;min-height:calc(var(--ch) + 22px);padding:16px 0 4px;max-width:none}
 .reach .rlabel{top:3px}
 .mainrow{gap:8px;padding-bottom:8px!important}
 .mainside{width:auto;flex:1 1 0;min-width:0;max-width:240px}
 .powerbtn{min-height:44px;white-space:normal;text-align:left}
 .slotbox{font-size:var(--fs-sm);padding:4px}
 .handrow.mine{min-height:calc(var(--hh) + 30px);padding-bottom:10px!important;scroll-snap-type:x proximity;overscroll-behavior-x:contain;justify-content:flex-start}
 .handrow.mine .card.hand{scroll-snap-align:center}
 .card.hand .playbtn{min-height:44px;font-size:var(--fs-lg)}
 .stats-panel{display:grid;grid-template-columns:1fr 1fr;align-items:center;padding:7px 8px;gap:6px}
 .stats-panel>.pname,.stats-panel>.ailine,.stats-panel>.facline,.stats-panel>.statgrid,.stats-panel>.hint,.stats-panel>.actions{grid-column:1/-1}
 .statgrid{grid-template-columns:repeat(4,minmax(0,1fr))}
 .st{padding:3px 6px}.st b{font-size:var(--fs-lg)}.st.inf>span{display:block;font-size:var(--fs-sm)}
 .shieldbox .lbl{font-size:var(--fs-sm)}
 #dominion{grid-template-columns:auto minmax(0,1fr);gap:4px 10px;padding:6px 8px}
 #dominion .mid{order:-1;grid-column:1/-1}
 #dominion .info{justify-content:flex-start;gap:2px 8px;line-height:var(--lh-snug)}
 #dominion .title{font-size:var(--fs-md);letter-spacing:.5px}
 #dominion .heart{padding:4px 12px}
 #dominion .info a{display:inline-flex;align-items:center;min-height:44px;padding:0 6px}
 #logpanel{height:260px}
 #logclose{min-width:44px}
 /* the action dock: hint + action buttons fixed to the bottom of the screen */
 #actdock{position:fixed;left:0;right:0;bottom:0;z-index:45;display:flex;flex-direction:column;gap:5px;max-height:45vh;
  background:#e9dfcff2;border-top:2px solid var(--bronze);box-shadow:0 -4px 14px #0004;
  padding:6px calc(8px + env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) calc(8px + env(safe-area-inset-left))}
 #actdock .hint{font-size:var(--fs-md);line-height:var(--lh-snug)}
 #actdock .hint a{display:inline-block;padding:0 4px}
 #actdock .actions{flex-direction:row;overflow-x:auto;overflow-y:hidden;gap:6px;padding-bottom:2px;overscroll-behavior-x:contain;flex:none}
 #actdock .actions button{flex:none;min-height:44px;max-width:72vw;white-space:normal;line-height:var(--lh-snug);font-size:var(--fs-md)}
 #actdock .actions button.end{order:-1}
 /* modals + tooltips */
 #modal{align-items:flex-end}
 .modal-box{width:100%;max-width:none;max-height:calc(100dvh - 8px - env(safe-area-inset-top));border-radius:var(--r-lg) 14px 0 0;
  padding:10px calc(12px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) calc(12px + env(safe-area-inset-left))}
 .modal-box .close{position:sticky;top:0;float:right;z-index:6;right:auto}
 .modal-box h2{font-size:var(--fs-xl)}
 .modal-box .cards .card.lg{width:calc(50% - 4px);min-height:0}
 .reveal .cards .card.lg{width:min(260px,80vw)}
 .codex .cx{width:calc(50% - 4px)}.codex .cx .card.lg{width:100%;min-height:0}
 .codex .cx.silhouette{width:calc(50% - 4px);height:140px}
 .legend{grid-template-columns:repeat(2,minmax(0,1fr))}
 .welcome{flex-wrap:wrap}
 #tip{max-width:calc(100vw - 16px)}#tip.withart{width:min(330px,calc(100vw - 16px))}

 /* menu screens */
 .screen{padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)}
 .mn-wrap{height:auto;min-height:calc(100% - 70px);max-width:none;padding:28px 20px 14px;gap:20px}
 .mn-title h1{font-size:clamp(40px,12vw,64px);letter-spacing:2px}
 .mn-title h2{font-size:var(--fs-md);letter-spacing:4px}
 .mn-title p{font-size:var(--fs-md)}
 .mn-nav{width:100%;max-width:440px}
 .mn-btn{min-height:52px}
 .mn-foot{position:relative;left:auto;bottom:auto;z-index:2;padding:4px 20px 16px;letter-spacing:.3px;line-height:var(--lh-body)}
 .mn-legal a{display:inline-flex;align-items:center;min-height:44px;padding:0 4px}
 .bye{padding:24px 20px}.bye h1{font-size:34px}.bye .mn-btn{width:100%;max-width:360px}
 .pg{padding:10px 10px 32px}
 .pg-head{flex-wrap:wrap;gap:8px 12px}
 .pg-head h1{font-size:var(--fs-xl)}
 .pg-head .tabs{margin-left:0;width:100%;display:flex;flex-wrap:wrap}
 .pg-head .tabs button{flex:1 1 auto}
 .pg-card{padding:12px}
 .st-row{flex-wrap:wrap;gap:8px 16px}
 .st-row>div:first-child{flex:1 1 220px}
 .st-row>div:last-child{display:flex;align-items:center;gap:8px;flex:1 1 auto;justify-content:flex-end;flex-wrap:wrap}
 .st-row input[type=range]{flex:1 1 120px;width:auto}
 .switch{width:58px;height:32px}.switch::after{content:"";position:absolute;inset:-7px -2px}
 .switch span{border-radius:var(--r-lg)}.switch span::before{width:24px;height:24px}.switch input:checked+span::before{left:29px}
 .st-foot{flex-wrap:wrap}
 .st-links a{display:inline-flex;align-items:center;min-height:44px}
 .rl-body.withtoc{grid-template-columns:minmax(0,1fr)}
 .rl-toc{position:sticky;top:0;z-index:2;flex-direction:row;overflow-x:auto;gap:4px;padding:6px;border-radius:var(--r-md)}
 .rl-toc a{flex:none;display:inline-flex;align-items:center;min-height:44px;white-space:nowrap;border:1px solid #4d4033;padding:0 10px}
 .rl-text{font-size:var(--fs-lg);padding:12px 14px;overflow-wrap:anywhere}
 .rl-text p,.rl-text li{font-size:var(--fs-lg)}
 .rl-text h2{font-size:var(--fs-xl)}.rl-text h3{font-size:var(--fs-xl)}
 .rl-text .md-table{max-width:100%}
 .rl-text table{overflow-wrap:normal}
 /* Rules (Quick guide and Full rules): the header (Menu, Tutorial, Guide / Full rules) and the contents strip stay put;
    only the rules panel scrolls, inside the safe area (.screen pads the insets). The screen itself no longer scrolls,
    so iOS Safari can't drag the header away or rubber-band the page (owner item 6; desktop unchanged). */
 .scr-rules{overflow:hidden;overscroll-behavior:none}
 .scr-rules>.pg{height:100%;display:flex;flex-direction:column;min-height:0;padding-bottom:6px}
 .scr-rules .pg-head{flex:none}
 .scr-rules .pg-head .pg-tut{min-height:44px}
 .scr-rules .rl-body,.scr-rules .rl-body.withtoc{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:6px;align-items:stretch}   /* (not the desktop grid's start: the article keeps the column width, its tables scroll in their own box) */
 .scr-rules .rl-toc{flex:none;position:relative}
 .scr-rules .rl-text{flex:1 1 auto;min-height:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
 .scr-rules .rl-text :is(h2,h3,h4){scroll-margin-top:8px}
 /* Full rules: one Sections drop-down instead of the chip row (it ran off the right edge); ui/menu.js rulesSectionsHTML */
 .scr-rules .rl-toc{display:none}
 .scr-rules .rl-sec{display:block;position:relative;z-index:5;flex:none;align-self:flex-start;max-width:100%}
 .rl-secbtn{display:inline-flex;align-items:center;gap:8px;min-height:44px;max-width:100%;padding:0 14px;font-weight:700;color:#f1d59a;border-color:#6d5a44}
 .rl-secbtn[aria-expanded=true]{background:#6d4c1f;border-color:var(--gold);color:#fff3d6}
 #rl-seccur{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
 .rl-secarr{flex:none}
 .rl-seclist{position:absolute;left:0;top:calc(100% + 4px);margin:0;padding:6px;list-style:none;display:flex;flex-direction:column;gap:2px;
  width:max-content;min-width:240px;max-width:min(420px,calc(100vw - 40px - env(safe-area-inset-left) - env(safe-area-inset-right)));
  max-height:calc(100vh - 150px);max-height:calc(100dvh - 150px);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
  border:1px solid var(--gold);border-radius:var(--r-lg);box-shadow:0 14px 40px #000c;
  /* fully opaque (the rules text must not show through), with scroll shadows: a dark edge appears at the top/bottom only while
     there is more list that way (the 'local' covers scroll with the content and hide the 'scroll' shadows at either end) */
  background:linear-gradient(#1b1612 40%,#1b161200) top/100% 40px no-repeat local,linear-gradient(#1b161200,#1b1612 60%) bottom/100% 40px no-repeat local,
   linear-gradient(#000,#0000) top/100% 26px no-repeat scroll,linear-gradient(#0000,#000) bottom/100% 30px no-repeat scroll,#1b1612}
 /* ...and the list stops part-way into an item so the cut-off row also says 'more below' */
 .rl-seclist{max-height:calc(100vh - 168px);max-height:calc(100dvh - 168px)}
 .rl-seclist[hidden]{display:none}
 .rl-seclist li{display:flex;align-items:center;min-height:44px;padding:0 12px;border-radius:var(--r-sm);font-size:var(--fs-md);color:#d8cab0;cursor:pointer}
 .rl-seclist li[aria-selected=true]{background:#3a2c1f;color:#fff1d0;box-shadow:inset 3px 0 0 #f2d27a}
 .rl-seclist li:focus{outline:2px solid var(--gold);outline-offset:-2px}
 /* the header row fits the narrowest landscape screen: the title gives way first (ellipsis), the controls never clip */
 .scr-rules .pg-head{gap:8px}
 .scr-rules .pg-head h1{min-width:0;overflow:hidden;text-overflow:ellipsis}
 .scr-rules .pg-head>button{flex:none}
 .scr-rules .pg-head .tabs{flex:none}.scr-rules .pg-head .tabs button:first-child{margin-left:0}   /* (the joined-border -1px stays inside the row) */
 .ln-wrap{padding:12px}
 .ln-box,.ld-box{padding:18px 16px}
 .ln-box h1{font-size:32px}.ln-box h2{font-size:var(--fs-sm);letter-spacing:3px}
 .ln-btns{flex-direction:column}
 .ln-box a{display:inline-block;padding:6px 0}
 .ng{grid-template-columns:minmax(0,1fr)}
 .ng-list{max-height:min(50vh,440px)}
 .ng-deck{min-height:52px}
 .ng-opts label.ng-aiopt{min-height:52px}
 .ng-legacy summary{min-height:44px;padding:12px 0;line-height:20px}
 #ng-build{display:inline-flex;align-items:center;min-height:44px}

 /* deck builder: Cards / Deck / Guide tabs, sticky count + validation, filters in a drawer */
 .db{height:100%}
 .db-top{flex-wrap:wrap;padding:6px 70px 6px 8px;gap:6px;min-height:0}
 .db-top h1{font-size:var(--fs-lg)}
 #db-name{flex:1 1 140px;width:auto;min-width:0}
 .db-actions{flex-wrap:nowrap;overflow-x:auto;width:100%;padding-bottom:2px;overscroll-behavior-x:contain}
 .db-actions>*{flex:none}
 .db-mbar{display:flex;flex-direction:column;gap:5px;padding:6px 8px;background:#16120f;border-bottom:1px solid #6d5a44;z-index:3}
 .db-mtabs{display:flex;width:100%}.db-mtabs button{flex:1}
 /* one joined group (owner, UI round 3; = the Challenges pair): outer corners rounded, inner joins square, the -1px join
    inside the row, the active tab's border on top */
 .db-mtabs button:first-child{margin-left:0;border-radius:var(--r-md) 0 0 var(--r-md)}
 .db-mtabs button:last-child{border-radius:0 var(--r-md) var(--r-md) 0}
 .db-mtabs button.on{position:relative;z-index:1}
 #mt-count{font-weight:400;font-size:var(--fs-sm);margin-left:4px;opacity:.85}
 .db-sum{font-size:var(--fs-md);line-height:var(--lh-snug);padding:5px 8px;border-radius:var(--r-md);white-space:normal;overflow-wrap:break-word;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
 .db-sum.ok{background:#1f3a26;border:1px solid #6fbf80;color:#c9f2d1}
 .db-sum.bad{background:#3a1d1a;border:1px solid #c0645a;color:#ffd4cc}
 .db-sum b{font-family:var(--font-display);color:#fff1d0;margin-right:4px}
 .db-main{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr)}
 .db[data-mtab=deck] .db-left{display:none}
 .db:not([data-mtab=deck]) .db-right{display:none}
 .db-left{border-right:0}
 .db-filters{padding:6px 8px}
 .db.filters-open .db-filters{max-height:55%;overflow:auto}
 .db:not(.filters-open) .db-filters .frow:not(:first-child){display:none}
 .frow #db-q{flex:1 1 140px;width:auto;min-width:0}
 .frow .tabs{display:none}
 .flabel{width:100%}.frow .fchip+.flabel{margin-left:0}
 .fchip{min-height:44px}.fchip[data-f=cost]{min-width:44px}
 #db-clearf{display:inline-flex;align-items:center;min-height:44px;padding:0 4px}
 .db-grid{--cw:clamp(136px,calc((100vw - 42px - env(safe-area-inset-left) - env(safe-area-inset-right))/2),190px);--ch:calc((var(--cw) - 12px)*.5625 + 96px);
  padding:10px 8px calc(30px + env(safe-area-inset-bottom));gap:12px 10px;justify-content:center}
 .db-guide{padding:10px 10px 30px}
 .tg-intro{grid-template-columns:minmax(0,1fr)}
 .tg-grid{grid-template-columns:minmax(0,1fr)}
 .db-right{padding:10px 10px calc(24px + env(safe-area-inset-bottom))}
 .db-toast{bottom:calc(22px + env(safe-area-inset-bottom));max-width:92vw}
 .wheel-box{right:8px;top:6px}
 .wheel-mini{width:52px;height:52px}
 .wheel-pop{position:fixed;left:calc(8px + env(safe-area-inset-left));right:calc(8px + env(safe-area-inset-right));top:calc(64px + env(safe-area-inset-top));width:auto;max-height:calc(100dvh - 80px - env(safe-area-inset-top));overflow:auto;z-index:30}
 .wheel-pop .wheel{width:min(260px,68vw);height:auto;aspect-ratio:1}
 .wh-close{display:block;position:absolute;right:8px;top:8px;min-width:44px;min-height:44px;padding:0}
 .wh-list li{font-size:var(--fs-md)}
}
/* deck builder on a device held upright: the actions wrap onto rows (none hidden off the edge), the search takes the
   full width, only the name row leaves room for the faction wheel */
@media (orientation:portrait) and (max-width:600px){
 .db-top{padding-right:8px}
 #db-name{margin-right:62px}
 .db-actions{flex-wrap:wrap;overflow-x:visible;padding-bottom:0}
 .frow #db-q{flex-basis:100%}
}
@media (max-width:480px){
 header h1 span{display:none}
 .legend{grid-template-columns:minmax(0,1fr)}
}
/* ======================= Dominion world view =======================
   While a player holds the Heart (G.dominion.controller), the board backdrop crossfades to a soft, darkened, blurred
   view of that player's faction realm (ui/app.js updateWorld). No holder: the neutral board color. */
#worldbg{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden;background:var(--bg)}
#worldbg .wb-slide{position:absolute;inset:-40px;background-size:cover;background-position:center;opacity:0;
 filter:blur(6px) saturate(.9) brightness(.72);transform:scale(1.04);transition:opacity 1.4s ease,transform 6s ease-out;will-change:opacity}
#worldbg .wb-slide.on{opacity:1;transform:scale(1)}
#worldbg .wb-veil{position:absolute;inset:0;opacity:0;transition:opacity 1.4s ease;
 background:radial-gradient(ellipse at 50% 45%,#a89d9026 0%,#2a211a66 70%,#140f0bb3 100%),linear-gradient(#a89d9033,#a89d9033)}
body.world #worldbg .wb-veil{opacity:1}
body.reduced-motion #worldbg .wb-slide,body.reduced-motion #worldbg .wb-veil{transition-duration:.5s}
body.inmenu #worldbg{display:none}
/* rows go slightly translucent so the world shows through, still light enough to read */
body.world .row{background:color-mix(in srgb,var(--zone) 70%,transparent)}
body.world .mainrow{background:color-mix(in srgb,var(--zone2) 80%,transparent)}
body.world .stats-panel{background:color-mix(in srgb,var(--panel) 92%,transparent)}
body.world #logpanel{background-color:color-mix(in srgb,var(--panel) 96%,transparent)}
body.world header{background-color:color-mix(in srgb,var(--panel) 92%,transparent)}
body.world .slotbox:not(.target-slot),body.world .reach.empty .slotbox:not(.target-slot){color:#f1e6d0cc;border-color:#f1e6d066}
body.world .row::before{color:#3b2f25}

/* ======================= Phones held sideways (landscape-first) =======================
   Height up to 500, width 560+: the board is a two-sided table (opponent across the top, you across the bottom, the
   Heart in the band between, your hand sticky along the bottom edge) with the essentials in a slim rail on the right
   and everything secondary in its More drawer; menu, deck builder, New Game, Settings and the modals go side by side.
   Board cards drop their rules text (long-press = detail sheet). The board scrolls vertically rather than cramming. */
@media (max-height:500px) and (min-width:560px) and (orientation:landscape){
 /* Sizes come from the screen WIDTH: the board scrolls vertically (page scroll, native momentum) instead of squeezing
    every row into one screen, so cards and rows get room on short screens (iPhone 14 with Safari's bars: ~340 px). */
 /* (T81 D3: the stats column and the Main's Belief panel give the four board cards a little more width, so long
    names stay above the fitter's floor with the notch insets too) */
 :root{--railw:calc(98px + env(safe-area-inset-right));--sw:clamp(76px,10vw,100px);--ms:clamp(82px,11.5vw,112px);
  --cw:clamp(84px,calc((100vw - var(--railw) - var(--sw) - var(--ms) - 70px - env(safe-area-inset-left))/4),140px);
  --ch:calc((var(--cw) - 12px)*.5625 + 38px);
  --hh:clamp(80px,22vh,96px);--hw:calc((var(--hh) - 38px)*16/9 + 12px - min(4px,env(safe-area-inset-left)))}

 /* header: hidden; More > Game setup opens it as a drawer over the board */
 header{display:none!important}
 body.setup-open:not(.inmenu) header{display:flex!important;position:fixed;z-index:70;top:0;left:0;right:var(--railw);max-height:100vh;max-height:100dvh;overflow:auto;box-shadow:0 8px 24px #0009}

 /* the table: natural height, scrolls with the page */
 html{scroll-padding-bottom:calc(var(--hh) + 16px)}
 /* (rows 4 px apart: on a notched phone the hand tray grows by the home-indicator inset, and at 6 px it covered the
    bottom of your Discard counter's 44 px tap area; real-inset ui-screens check, #31 review) */
 #app{display:grid;gap:4px 6px;min-height:100vh;min-height:100dvh;box-sizing:border-box;height:auto;overflow-x:clip;
  /* The middle track used to be `auto`, so a long opponent hand widened it and squeezed the
     Reaches down to a few pixels. Those cards then stuck out into the rail, on top of Back to results.
     The Reaches keep room for three cards; the hand scrolls. */
  grid-template-columns:var(--sw) minmax(0,1fr) minmax(calc(3 * var(--cw) + 28px),1.5fr);
  grid-template-rows:auto auto auto auto auto auto;
  /* (PR-C: your panel starts beside the Heart band, not under it, so its Shield / Conquest row ends well above the Hand
    tab that sits over the closed hand bar at the bottom left; that corner of the stats column is left empty for it) */
  grid-template-areas:"s1 opphand oppzone" "s1 oppmain oppassets" "s0 btw btw" "s0 mymain myassets" "s0 myzone myzone" "myhand myhand myhand";
  align-content:start;
  padding:6px calc(var(--railw) + 6px) 0 calc(6px + env(safe-area-inset-left))}
 body.nolog #app{grid-template-columns:var(--sw) auto minmax(0,1fr)}
 /* the match log: a side panel beside the rail, hidden by default (More > Match log) */
 #logpanel,body.nolog #logpanel{display:none}
 body.showlog #logpanel{display:flex;position:fixed;z-index:60;top:0;bottom:0;right:var(--railw);width:min(340px,52vw);height:auto;border-radius:var(--r-lg) 0 0 10px;box-shadow:-6px 0 22px #0007;
  padding-top:env(safe-area-inset-top);padding-bottom:env(safe-area-inset-bottom)}
 body.showlog #log{-webkit-overflow-scrolling:touch;overscroll-behavior:contain;font-size:var(--fs-sm)}
 #logclose{min-width:44px;min-height:44px}
 .row{padding:3px 5px!important;border-radius:var(--r-md);gap:5px}
 .row::before{display:none}
 /* chip rows (hands of the opponent, traps / ongoing): quiet, single line, scroll sideways */
 .zonerow,.handrow:not(.mine){min-height:0;height:34px;overflow-x:auto;overflow-y:hidden;flex-wrap:nowrap;overscroll-behavior-x:contain}
 .zonerow .chip,.handrow:not(.mine) .chip{height:auto;min-height:28px;flex:none;min-width:0;max-width:160px;font-size:13px;padding:1px 5px 1px 2px;gap:3px}
 .chip .art.mini{width:30px;height:20px}.chip .t{font-size:13px}.chip b{max-width:100px;font-size:13px}
 /* your / the opponent's traps and ongoing effects: the label ("Ongoing: 1 turn left") and the card name both show in
    full (T81 D1: at 28 px the name was pushed out of the chip and the label ended in "LE…"); the row grows to fit */
 .zonerow{height:auto;min-height:34px}
 .zonerow .chip:not(.facedown){height:auto;min-height:0;max-width:210px;padding:0 6px 0 2px}  /* hugs label + name (keeps the name clear of the closed hand bar) */
 .zonerow .chip b{line-height:1.05}
 body.hand-closed #r-myzone .chip .t{transform:translateY(-3px)}
 body.hand-closed #r-myzone .chip b{transform:translateY(-6px)}
 .zonerow .chip .t{overflow:visible;text-overflow:clip}
 .zonerow .chip b{max-width:160px}
 /* AI vs AI only (owner's option A, 2026-10-18): the opponent-hand and zone-strip chip names stay on one line at the CSS
    size and are cut with an ellipsis (ui/app.js skips its shrink-to-fit for exactly these); every other name stays whole */
 body.aivai .zonerow .chip b,body.aivai .handrow:not(.mine) .chip b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
 .zonerow>span,.handrow:not(.mine)>span{font-size:var(--fs-xs)!important;white-space:nowrap;color:var(--text-2)}
 .back{width:14px;height:20px;border-width:1.5px;border-radius:var(--r-sm);flex:none}
 /* the player panels: name + Life + Influence stand out; deck, discard, shield and conquest stay quiet */
 .stats-panel{padding:3px 6px;gap:3px;border-radius:var(--r-md);overflow:visible;contain:none;align-content:start;align-self:start;font-size:var(--fs-sm)}
 .stats-panel .ailine,.stats-panel .facline{display:none}
 .pname{font-size:var(--fs-sm)}
 .turnflag{font-size:0;width:9px;height:9px;padding:0;border-radius:50%;box-shadow:0 0 0 2px #e1b86488}  /* (a dot: the rail and the row outline say whose turn it is) */
 .statgrid{grid-template-columns:minmax(0,1fr);gap:1px}
 .st{padding:1px 5px;display:flex;align-items:center;justify-content:space-between;gap:4px;min-width:0;line-height:18px;background:transparent}
 .st small{font-size:var(--fs-2xs);letter-spacing:.3px}.st b{font-size:var(--fs-sm);margin-left:auto;color:var(--ink2,#4a3b2c)}
 .st.life,.st.inf{background:var(--zone2)}.st.life b,.st.inf b{font-size:var(--fs-lg)}.st.life b{color:#86211c}.st.inf b{color:#8a5a12}
 .st.life.guarded{flex-wrap:wrap;row-gap:0}
 .st.life.guarded .fg-mark{flex:1 0 100%;margin:0;text-align:right;line-height:12px}
 /* Influence with its income as "+N" (the "/turn" is dropped here). "Influence:" alone fills the narrow column (it
    used to push the number past the row's border), so the label takes its own short line and "+N" and the number
    (right-aligned, like Life's) share the next, all inside the row (the rail's YOU / OPP boxes that showed the income are gone, PR-C). The panel
    is packed a little tighter (padding, gaps, Shield height) so both panels still fit beside the board and above
    the Hand tab without pushing the board down. */
 .st.inf{flex-wrap:wrap;row-gap:0}.st.inf>small{flex:1 0 100%;line-height:13px;order:-2}.st.inf .subtext{order:-1;font-size:var(--fs-2xs);line-height:12px;color:var(--text-2);white-space:nowrap}.st.inf .subtext>small{display:none}
 .st.deck b,.st.click b{color:var(--text-2)}  /* (de-emphasised by color, not opacity: AA contrast, AUD-A11Y-1) */
 .shieldbox{padding:0 3px;gap:3px;justify-content:flex-start}.shield{width:24px;height:28px;font-size:13px}.shieldbox .lbl{display:none}
 .stats-panel>div:last-child small{font-size:var(--fs-2xs);white-space:nowrap;color:var(--text-2);overflow:hidden;text-overflow:ellipsis;display:block;min-width:0}
 .stats-panel>div:last-child{min-width:0}.conqbar{height:5px}
 .stats-panel>div:last-child small .lbl{display:none}  /* narrow column: "0/7" over the Conquest bar (the label was being cut to "Conqu…"; the tooltip names it) */
 /* the Main row: the Main card + a column with Belief (prominent), the power, and small status chips. The row grows
    with its content, so the Belief / Grace / Awakened / power stack never overlaps the row edge or the next row */
 .mainrow{gap:6px;padding:4px 5px!important;justify-content:flex-start;align-items:center;min-height:calc(var(--ch) + 10px)}
 .mainside{flex:0 0 var(--ms);width:var(--ms);max-width:none;gap:3px;display:flex;flex-direction:column;align-self:center}
 .mainside>*{flex:none;max-width:100%;min-width:0;box-sizing:border-box}  /* the legend panel always stacks: Belief, then Grace/Fading, Awakening, Coronation, then the power; nothing shrinks or sits side by side */
 .mainside .pips{flex-wrap:wrap}.fadebadge,.reqchip,.powerbtn{overflow-wrap:anywhere}
 .belief{padding:2px 5px}.belief small{font-size:var(--fs-2xs);font-weight:700;color:#6b4a10}.pips{gap:3px;margin-top:1px}.pip{width:12px;height:12px;border-width:1.5px}.pip.tier::after{display:none}
 .fadebadge,.reqchip{font-size:13px;padding:1px 5px;margin-top:0;line-height:var(--lh-snug);white-space:normal}
 .powerbtn{min-height:44px;font-size:13px;padding:2px 6px;white-space:normal;line-height:var(--lh-tight);overflow:visible}
 /* the Reaches: filled ones read as cards on the map; empty ones are soft outlines */
 .assetsrow{padding:4px 5px!important;gap:5px;justify-content:space-around;align-items:stretch}
 /* A hand or a Heart full of realm tiles is wider than the table. Without min-width:0 that
    min-content widens the grid under the rail, and the rightmost card or tile sits on Back to results. */
 #r-opphand,#r-oppzone,#r-oppassets,#r-oppmain,#dominion,#r-mymain,#r-myassets,#r-myzone,#r-myhand{min-width:0}
 .reach{min-height:calc(var(--ch) + 8px);height:auto;padding:0;max-width:none;align-self:stretch}
 .reach.empty{border-color:#8a7d7040;background:transparent}
 .reach.empty .slotbox{border:1.5px dashed #8a7d7055;color:var(--text-3);font-size:13px;background:transparent}
 .reach.empty .slotbox.target-slot{border:3px solid var(--green);background:#d7e6cf;color:var(--green-ink);font-size:13px}
 .reach .rlabel{display:none}
 .reach.washed{justify-content:center}
 .reach .layers{right:auto;left:2px;top:2px;flex-direction:column;align-items:flex-start}.layer{padding:1px}.layer b{display:none}.layer .art.mini{width:22px;height:15px}
 #dominion .info .layer b{display:inline;max-width:96px;font-size:13px}
 .slotbox{font-size:13px;padding:2px;line-height:var(--lh-snug)}
 /* board cards: name, art, cost and stats (like hand cards); the full text is a long-press away */
 #app .card:not(.lg):not(.hand) .tb{display:none}
 #app .card:not(.lg):not(.hand) .art{margin-bottom:3px;flex:none}
 #app .card.facedown.veiled .art.veilback{flex:1 1 auto;aspect-ratio:auto;margin:4px}
 #app .card:not(.lg) .hd .gem{top:30px}
 /* hierarchy: your Main leads; the opponent's half is a step quieter than yours */
 #r-mymain>.card{box-shadow:0 3px 10px #3b2a1244,0 0 0 1px #a8742f55}
 #r-opphand,#r-oppzone,#r-myzone{background:transparent;border-color:transparent}
 #r-oppmain,#r-oppassets{background:color-mix(in srgb,var(--zone2) 55%,transparent)}
 #r-oppmain .card,#r-oppassets .card{filter:saturate(.85)}
 #stats1{opacity:1}  /* (was .9: it pulled the Life number under AA contrast, AUD-A11Y-1) */
 .active-side{box-shadow:inset 0 0 0 1.5px #a8742fbb}
 /* the Heart band: one line, quiet chrome; turn, costs and the Codex count live in the More drawer */
 #dominion{grid-template-columns:auto auto minmax(0,1fr);gap:2px 10px;padding:2px 8px;border-radius:var(--r-md);border-width:1.5px;
  background:linear-gradient(90deg,color-mix(in srgb,var(--taupe) 55%,var(--sand)),var(--sand) 30%,var(--sand) 70%,color-mix(in srgb,var(--taupe) 55%,var(--sand)))}
 /* (T81 D2) title and holder share one line while they fit; once realms lie on the Heart (or its drop target shows)
    the title sits over the holder line, so the band stays one row high and the realm tiles keep real room on its
    right: before, title + holder + faction pill took the whole width and the realm tiles (and the
    "Lay … on the Heart" drop target) were clipped, or hidden entirely with the notch insets */
 #dominion .mid{order:0;grid-column:auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:0 8px;text-align:center;min-width:0}
 #dominion:has(.info .layer,.info .zonedrop) .mid{flex-direction:column;flex-wrap:nowrap}
 #dominion .heart{padding:0 10px}
 #dominion .title{font-size:var(--fs-sm);letter-spacing:.3px;white-space:nowrap;line-height:1}
 #dominion .holder{font-size:var(--fs-sm);white-space:nowrap;line-height:16px}
 #dominion .holder b{font-size:13px}
 #dominion .heartfac{height:auto;line-height:18px;font-size:13px;vertical-align:top}
 #dominion .heartfac .emb{transform:none;margin:0;font-size:13px;width:16px;height:16px}
 #dominion .over{font-size:var(--fs-sm);padding:1px 8px;margin:0}
 #dominion .cq{flex-direction:row;gap:6px}
 #dominion .rr span{display:none}.ring{width:26px;height:26px}
 #dominion .info{font-size:var(--fs-xs);line-height:var(--lh-snug);justify-content:safe flex-end;min-width:0;display:flex;align-items:center;gap:6px;white-space:nowrap;
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
 #dominion .info::-webkit-scrollbar{display:none}
 /* the realm tiles keep their size (a name on 1-2 lines, whole words) and scroll sideways if there are many; never clipped */
 #dominion .info .layers{flex:none;display:flex;gap:4px}
 #dominion .info .layer,#dominion .info .zonedrop{flex:none}
 #dominion .info .zonedrop.small{height:28px}   /* the "Lay … on the Heart" target: as tall as the band allows */
 #dominion .info>div:last-child{display:none}
 /* your hand: sticky along the bottom edge while the board scrolls above it */
 .handrow.mine{position:sticky;bottom:0;z-index:8;min-height:0;height:auto;padding:4px 6px calc(4px + env(safe-area-inset-bottom))!important;gap:6px;justify-content:flex-start;
  margin:0 -6px 0 calc(-6px - env(safe-area-inset-left));border-radius:var(--r-lg) 10px 0 0;background:color-mix(in srgb,var(--zone2) 92%,#fff 8%);
  box-shadow:0 -4px 12px #3b2a1226;border-top:1.5px solid #a8742f88;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
 .handrow.mine .card.hand{flex:none}
 /* (T81 D5) the tray's background runs under the notch, its toggle and first card start after it (with the notch the
    hand cards are 4 px narrower, --hw above, so a six-card hand still fits beside the rail) */
 .handrow.mine{padding-left:max(6px,env(safe-area-inset-left))!important}
 .card.hand .playbtn{min-height:44px;font-size:var(--fs-md);padding:2px 10px}
 /* collapsible hand: expanded = the full sticky hand; collapsed = a peek bar with the tops of the cards (name + cost).
    The height animates (~250 ms); the cards keep their size and position, so long-press, deal-in and effects still
    find them. A tap on the peek bar (or the toggle) opens it. */
 .handrow.mine{height:calc(var(--hh) + 10px + env(safe-area-inset-bottom));align-items:flex-start;transition:height .25s ease,box-shadow .25s ease}
 .handrow.mine,body.world .handrow.mine{background:color-mix(in srgb,var(--zone2) 92%,#fff 8%)}
 body.world #r-opphand,body.world #r-oppzone,body.world #r-myzone{background:color-mix(in srgb,var(--zone) 62%,transparent)}
 body.world .zonerow>span,body.world .handrow:not(.mine)>span{color:#3b2f25}
 /* PR #124: closed, the bar is a slim 28 px strip (the card names + costs peek out) so it no longer covers the bottom of
   the board (your ongoing chip's name at 844x390). The hand toggle is a plain chevron at the bar's left end, inside the
   bar (no label, no tab): it points up while the hand is closed, down while it is open, and the cards start to its right.
  Owner fix: the bar keeps the same left padding open and closed (the toggle stays in the row, sticky, in both states),
  so expanding / collapsing only changes the bar's height and the cards never move sideways */
body.hand-closed .handrow.mine{height:calc(28px + env(safe-area-inset-bottom));padding-top:1px!important;box-shadow:0 -3px 8px #3b2a121f;cursor:pointer}
 body.hand-closed .handrow.mine .card.hand{transition:transform .25s ease}
 body.hand-closed .handrow.mine .card.hand .playbtn,body.hand-closed .handrow.mine .card.hand .infobtn{display:none}
 /* open: a 44 x 44 square at the bottom of the bar's left end (where it sat while closed, so it stays clear of your
    panel's progress row above the bar), sticky at the left while the cards scroll, in the bar's own color */
 .handtog{position:sticky;left:0;z-index:3;flex:none;align-self:flex-end;width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  margin:0;padding:0;border:0;border-radius:0;background:inherit;box-shadow:none;color:#5a3a0e;cursor:pointer;-webkit-tap-highlight-color:transparent}
 .handtog .chev{display:flex;align-items:center;justify-content:center;width:100%;height:28px;pointer-events:none}
 .handtog svg{display:block;width:22px;height:12px;transition:transform .25s ease}
 .handtog[aria-expanded=true] svg{transform:rotate(180deg)}
 .handtog:hover{background:inherit;color:#3b2a12}.handtog:focus-visible{outline:2px solid #a8742f;outline-offset:-3px}
 /* closed: still in the row (no fixed overhang above the strip), stretched over the whole strip below the top border and
   down to the bar's bottom edge (through the home-indicator inset), so every part of it is inside the bar; the chevron
   is centred in the visible strip above the inset. With no inset (28 px strip) the tap area is 44 x 26.5 px; the
   whole closed strip also opens the hand on a tap */
 body.hand-closed .handtog{align-self:stretch;height:auto;min-height:0;margin:-1px 0 calc(-4px - env(safe-area-inset-bottom));
  flex-direction:column;align-items:stretch;padding-bottom:env(safe-area-inset-bottom)}
 body.hand-closed .handtog .chev{flex:1 1 auto;height:auto}
 html{scroll-padding-bottom:calc(var(--hh) + 16px)}
 body.hand-closed{scroll-padding-bottom:64px}
 .infobtn{top:auto;bottom:2px;right:2px;width:44px;height:44px;font-size:var(--fs-xl)}

 /* the rail: More and the turn's actions (End Turn pinned at the bottom) */
 #actdock.rail{left:auto;top:0;bottom:0;right:0;width:var(--railw);max-height:none;gap:4px;border-top:0;border-left:2px solid var(--bronze);box-shadow:-4px 0 14px #0004;
  padding:calc(5px + env(safe-area-inset-top)) calc(5px + env(safe-area-inset-right)) calc(5px + env(safe-area-inset-bottom)) 5px;background:#e9dfcffa;display:flex;flex-direction:column}
 .rail-more{flex:none;min-height:44px;display:flex;align-items:center;justify-content:center;gap:6px;padding:0 6px;font-weight:700}
 .rail-more .sym{font-size:var(--fs-lg);line-height:1}.rail-more small{font-size:var(--fs-sm)}
 .rail-more[aria-expanded=true]{background:#6d4c1f;color:#fff3d6;border-color:#e1b864}
 .rail-main{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:3px;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
 #actdock.rail .hint{font-size:var(--fs-sm);line-height:var(--lh-snug);white-space:normal;padding:1px 5px}
 #actdock.rail .hint a{display:inline-flex;align-items:center;min-height:32px;padding:0 2px}
 /* tight spacing so more of the turn's actions fit above End Turn without scrolling; taps stay >= 44 px */
 #actdock.rail .actions{flex-direction:column;overflow:visible;gap:3px;flex:1 0 auto;padding:0}
 #actdock.rail .actions button{flex:none;max-width:none;width:100%;min-width:0;font-size:13px;line-height:var(--lh-tight);padding:3px 4px;min-height:44px;
  overflow-wrap:anywhere;hyphens:manual;text-wrap:balance}   /* 13px clears the readability floor; anywhere keeps a long label inside the rail */
 /* more actions below the fold: the list fades out at its bottom edge (app.js railCue) */
 .rail-main.more-below{-webkit-mask-image:linear-gradient(#000 calc(100% - 22px),#0003);mask-image:linear-gradient(#000 calc(100% - 22px),#0003)}
 #actdock.rail .actions button.claim{background:linear-gradient(180deg,#f3dfa8,#e1b864);border-color:#7d5420;font-weight:800}
 #actdock.rail .rail-foot{flex:none;display:flex;flex-direction:column;gap:3px}   /* End Turn: below the scrolling list */
 #actdock.rail .actions button.end{order:99;position:static;min-height:48px;font-size:var(--fs-md);font-weight:800;
  background:linear-gradient(180deg,#7a5420,#5a3a14);color:#fff3d6;border-color:#3b2a12}
 /* the More drawer: a panel beside the rail (menu, game setup, log, Codex, rules, fullscreen + status details) */
 #raildrawer{position:fixed;z-index:62;top:0;bottom:0;right:var(--railw);width:min(330px,56vw);background:#efe7da;border-left:2px solid var(--bronze);
  box-shadow:-8px 0 24px #0006;border-radius:var(--r-lg) 0 0 12px;display:flex;flex-direction:column;animation:drawerin .18s ease-out;
  padding:env(safe-area-inset-top) 0 env(safe-area-inset-bottom) 0}
 @keyframes drawerin{from{transform:translateX(24px);opacity:.5}}
 .dr-scroll{flex:1;overflow:auto;padding:8px 10px 12px;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
 .dr-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(92px,1fr));gap:6px}
 .dr-grid button{min-height:52px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;padding:4px 2px;line-height:var(--lh-tight)}
 .dr-grid .sym{font-size:var(--fs-xl);line-height:20px}.dr-grid small{font-size:var(--fs-sm);text-align:center}
 .dr-grid button[aria-pressed=true],.dr-grid button[aria-expanded=true]{background:#6d4c1f;color:#fff3d6;border-color:#e1b864}
 .dr-status h4{margin:12px 0 4px;font-size:var(--fs-sm);text-transform:uppercase;letter-spacing:.6px;color:#6b4a10;border-bottom:1px solid #cdbd9f;padding-bottom:2px}
 .dr-li{display:flex;justify-content:space-between;gap:10px;font-size:var(--fs-md);line-height:var(--lh-body)}.dr-li .lbl{flex:none;font-weight:700}.dr-li span{text-align:right;min-width:0}
 .dr-note{margin:2px 0 6px;font-size:var(--fs-sm);line-height:var(--lh-body);color:#4a3b2c}
 body.drawer-open #logpanel{display:none}

 /* modals, card sheets: centred, two columns where it helps, scrolling inside */
 #modal{align-items:center}
 .modal-box{width:min(820px,calc(100vw - 24px - var(--sal) - var(--sar)));max-height:calc(100vh - 12px);max-height:calc(100dvh - 12px);border-radius:var(--r-lg);padding:8px 14px 12px}
 .modal-box h2{font-size:var(--fs-xl);margin-bottom:4px}
 .modal-box .cards .card.lg{width:calc(25% - 6px)}
 .codex .cx,.codex .cx.silhouette{width:calc(25% - 6px)}
 .reveal .cards .card.lg{width:min(190px,30vw)}
 #sheet{align-items:center}
 .sheet-box{max-width:min(760px,calc(100vw - 24px - env(safe-area-inset-left) - env(safe-area-inset-right)));max-height:calc(100vh - 12px);max-height:calc(100dvh - 12px);border-radius:var(--r-lg);border-bottom:2px solid var(--bronze);padding:8px 12px 10px}
 #sheet-body{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px 16px;align-items:start}
 .sheet-card{clear:none;grid-row:1/span 3;padding-top:0}
 .sheet-card .card.lg{width:min(220px,30vw)}
 .sheet-text,.sheet-ctl,.sheet-note{grid-column:2}
 .sheet-text p{font-size:var(--fs-md);margin:4px 0}
 .sheet-ctl{bottom:-10px}

 /* title screen: two columns that never overlap. The title column scales its heading to its own width (container
    units); the button grid has a set width; both sit centred in the space above the footer, inside the safe area. */
 .scr-menu{display:flex;flex-direction:column;padding:0;--mn-nav-w:clamp(272px,44vw,400px);--mn-padx:16px}
 .scr-menu .mn-wrap{flex:1 0 auto;display:grid;grid-template-columns:minmax(0,1fr) var(--mn-nav-w);align-items:center;align-content:center;
   column-gap:clamp(16px,3.5vw,40px);width:100%;max-width:980px;margin:0 auto;box-sizing:border-box;height:auto;min-height:0;
   padding:max(10px,var(--sat)) calc(var(--mn-padx) + var(--sar)) 4px calc(var(--mn-padx) + var(--sal))}
 .mn-title{min-width:0;container-type:inline-size}
 .mn-crest{margin-bottom:4px}.mn-crest .emb{width:22px;height:22px;font-size:var(--fs-sm)}
 .mn-title h1{font-size:clamp(28px,5.2vw,52px);font-size:clamp(28px,14.2cqi,52px);letter-spacing:.04em;white-space:nowrap}
 .mn-title h2{font-size:clamp(10px,1.5vw,12px);letter-spacing:.32em;margin:4px 0 6px}
 .mn-title p{font-size:var(--fs-sm);line-height:var(--lh-body);max-width:34em}
 .mn-nav{width:var(--mn-nav-w);display:grid;grid-template-columns:1fr 1fr;gap:6px}
 .mn-btn{min-height:48px;padding:5px 12px!important;justify-content:center;min-width:0}.mn-btn small{display:none}.mn-btn b{font-size:clamp(13.5px,1.9vw,15px);white-space:nowrap}
 .mn-count{font-size:var(--fs-sm);padding:0 6px;right:8px}
 .mn-nav.no-exit>.mn-btn:last-child:nth-child(odd){grid-column:1/-1}   /* no Exit (touch devices): the grid stays even */
 #mn-challenges .mn-ct-tot{display:none}   /* the phone menu: the badge count alone, so "Challenges" fits */
 .scr-menu .mn-foot{position:static;flex:0 0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;column-gap:16px;
   width:100%;max-width:980px;margin:0 auto;box-sizing:border-box;font-size:var(--fs-sm);line-height:var(--lh-snug);
   padding:0 calc(var(--mn-padx) + var(--sar)) max(2px,var(--sab)) calc(var(--mn-padx) + var(--sal))}
 .scr-menu .mn-legal{margin:0}.scr-menu .mn-legal a{min-height:44px}
 /* the one-time Codex note (PR 13b) sits above the button grid in its column, so the note, every button and the
    footer fit the phone screen; without the note the grid is unchanged */
 .scr-menu .mn-wrap:has(> .mn-codex-note){grid-template-rows:auto auto;row-gap:6px}
 .scr-menu .mn-wrap:has(> .mn-codex-note) .mn-title{grid-column:1;grid-row:1/span 2}
 .scr-menu .mn-wrap > .mn-codex-note{grid-column:2;grid-row:1;align-self:end;margin:0;padding:5px 10px;font-size:var(--fs-sm)}
 .scr-menu .mn-wrap:has(> .mn-codex-note) .mn-nav{grid-column:2;grid-row:2;align-self:start}
 /* + Story: with the note, five rows of buttons (nine or more) close up to 44 px taps so the footer still fits */
 .scr-menu .mn-wrap:has(> .mn-codex-note) .mn-nav:has(> .mn-btn:nth-child(9)){gap:4px}
 .scr-menu .mn-wrap:has(> .mn-codex-note) .mn-nav:has(> .mn-btn:nth-child(9)) > .mn-btn{min-height:44px}
 .bye{padding:16px 24px}

 /* pages */
 .pg{padding:6px 10px 12px}
 .pg-head{margin-bottom:6px;padding-bottom:6px;flex-wrap:nowrap}
 .pg-head h1{font-size:var(--fs-xl);white-space:nowrap}
 .pg-head .tabs{width:auto;margin-left:auto;flex-wrap:nowrap;overflow-x:auto}
 .ng{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:10px}
 .ng .pg-card{padding:8px 10px}
 .ng h3{margin-bottom:6px;font-size:var(--fs-lg)}
 .ng-list{max-height:calc(100vh - 150px);max-height:calc(100dvh - 150px)}
 .ng-opts{max-height:calc(100vh - 66px);max-height:calc(100dvh - 66px);overflow:auto;gap:8px;overscroll-behavior:contain}
 #ng-start{position:sticky;bottom:0;flex:none;box-shadow:0 -8px 14px #1b1612;background:linear-gradient(90deg,#7a5420,#3a2a17)!important}
 .scr-settings .pg>.pg-card:not(.st-legal){display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:22px}
 .scr-settings .st-foot{grid-column:1/-1}
 .scr-settings .pg>.pg-card{row-gap:0;align-items:start}
 .st-row{padding:8px 0;flex-wrap:nowrap;align-items:start}
 .st-row>div:first-child{flex:1 1 auto;min-width:0}
 .st-row>div:last-child{flex:0 0 auto;max-width:48%}
 /* one 132 px control column (select, slider, switch), so the descriptions line up and read at the small size */
 .st-row>div:last-child:has(>select,>input[type=range],>.switch){flex:0 0 132px;max-width:none;justify-content:flex-end;flex-wrap:nowrap}
 .st-row select{width:132px;min-width:0;max-width:none}
 .st-row input[type=range]{width:0;flex:1 1 0;min-width:0}
 .scr-settings .st-row b{font-size:var(--fs-md)}
 .scr-settings .st-row small{font-size:var(--fs-sm);display:block;margin-top:2px}
 .ln-wrap{padding:8px calc(12px + env(safe-area-inset-right)) 8px calc(12px + env(safe-area-inset-left))}

 /* deck builder: the card grid and the deck side by side; Cards / Guide tabs back in the filter row. One clean top bar
    inside the safe area: Menu, name, Load, Save, Play, More, the faction wheel (in the row, 44 px, never over a button);
    the other actions in the More panel (ui/menu.js placeDbActions). Every control 44 px tall (owner item 8). */
 .db-top{flex-wrap:nowrap;gap:6px;padding:4px 8px}.db-top h1{display:none}   /* (.screen already pads the safe-area insets) */
 .db-top .pg-back{flex:none;padding:0 10px}
 .db-actions{width:auto;flex:0 1 auto;min-width:0;flex-wrap:nowrap;gap:6px;overflow:visible;padding:0}
 .db-actions>*{flex:none}
 .db-actions button{padding:0 12px}
 #db-load{flex:0 1 150px;min-width:0;max-width:150px}
 #db-name{flex:1 1 150px;min-width:90px}
 .db-more{display:inline-flex;align-items:center;justify-content:center;flex:none;padding:0 12px}
 .db.more-open .db-more{background:#6d4c1f;border-color:var(--gold);color:#fff3d6}
 .db.more-open .db-morepanel{display:grid}
 .db-morepanel{position:absolute;z-index:25;top:calc(100% + 4px);right:calc(8px + env(safe-area-inset-right));grid-template-columns:repeat(3,minmax(110px,auto));gap:6px;
  padding:8px;background:#17130ff7;border:1px solid var(--gold);border-radius:var(--r-lg);box-shadow:0 14px 40px #000c}
 .db-morepanel button{min-height:44px;padding:0 12px}
 .wheel-box{position:relative;right:auto;top:auto;flex:none;z-index:20}
 .wheel-mini{width:44px;height:44px}
 .db-mbar{display:none!important}
 .frow .tabs{display:inline-flex;flex:none}.frow .tabs button{min-height:44px;padding:0 8px}
 .frow:first-child{flex-wrap:nowrap}.frow #db-q{flex:1 1 140px;min-width:120px}.frow .tabs button{font-size:var(--fs-md);padding:0 7px;white-space:nowrap}#db-clearf{white-space:nowrap}#db-shown{display:none}#db-ftoggle,#db-clearf{flex:none}
 .db-main{grid-template-columns:minmax(0,1fr) clamp(220px,32vw,300px)}
 .db[data-mtab=deck] .db-left{display:flex}
 .db:not([data-mtab=deck]) .db-right{display:flex}
 .db-left{border-right:1px solid #4d4033}
 .db-filters{padding:4px 8px}
 .db.filters-open .db-filters{max-height:60%}
 .db-grid{--cw:clamp(118px,calc((100vw - clamp(220px,32vw,300px) - 64px - env(safe-area-inset-left) - env(safe-area-inset-right))/3),170px);padding:8px 8px calc(20px + env(safe-area-inset-bottom))}
 .db-right{padding:8px calc(8px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) 8px}
}
.mn-btn{position:relative}
.mn-count,.mn-count-wait{position:absolute;right:14px;top:50%;transform:translateY(-50%);font-family:var(--font-display);font-size:var(--fs-md);color:var(--gold);border:1px solid #6d5a44;border-radius:var(--r-lg);padding:1px 8px;background:#0e0b09b3}
.mn-count-wait{opacity:.55}   /* the Challenges chip before its count arrives (menu.js challengesBtnHTML) */
@media (max-height:500px) and (min-width:560px) and (orientation:landscape){.mn-count-wait{font-size:var(--fs-sm);padding:0 6px;right:8px}}   /* = the landscape .mn-count */

/* ======================= Rotate prompt (phones held upright) =======================
   Phones in portrait get a full-screen "rotate" card; the first-launch notice, its decline screen, the legal
   reader and the Rules stay readable upright. Settings -> "Allow portrait on small devices" switches it off. */
#rotate{display:none;position:fixed;inset:0;z-index:300;align-items:center;justify-content:center;text-align:center;touch-action:none;
 padding:calc(24px + env(safe-area-inset-top)) calc(22px + env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) calc(22px + env(safe-area-inset-left));
 background:radial-gradient(ellipse at 50% 32%,#2b221b,#0e0b09 72%);color:#eadfca;font-family:var(--font-ui)}
.rot-box{max-width:340px;display:flex;flex-direction:column;align-items:center;gap:12px}
.rot-box .mn-crest{justify-content:center;margin:0}
.rot-icon{width:168px;height:168px;filter:drop-shadow(0 0 18px #e1b86433)}
.rot-dev{transform-box:view-box;transform-origin:60px 60px;animation:rotdev 3.4s ease-in-out infinite}
@keyframes rotdev{0%,16%{transform:rotate(0)}42%,74%{transform:rotate(-90deg)}100%{transform:rotate(0)}}
#rotate h2{font-family:var(--font-display);color:#f6e7c1;font-size:27px;margin:2px 0 0;letter-spacing:1px;text-shadow:0 2px 0 #5a3a0e,0 0 20px #e1b86455}
#rotate p{margin:0;color:#d8cab0;font-size:var(--fs-lg);line-height:var(--lh-body)}
#rot-keep{min-height:44px;margin-top:8px;background:#2a221c;color:#eadfca;border:1px solid #6d5a44;border-radius:var(--r-md);padding:8px 18px;font-size:var(--fs-md)}
#rotate small{color:#b9a98f;font-size:var(--fs-sm);line-height:var(--lh-body)}
@media (orientation:portrait) and (max-width:600px) and (hover:none) and (pointer:coarse){
 body:not(.allow-portrait):not([data-screen=notice]):not([data-screen=declined]):not([data-screen=legal]):not([data-screen=rules]) #rotate{display:flex}
}
/* touch browsers (iOS Safari especially) draw native light select boxes over the dark menu pages: draw our own. The
   Challenges category filter uses it everywhere (desktop Safari paints a native menulist white under the light text) */
.touch-ui .screen select,.screen .ch-filter select{-webkit-appearance:none;appearance:none;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23e1b864'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;background-size:10px 6px}

/* ======================= Visual effects (ui/fx.js; Settings > Effects: Full / Reduced / Off) ======================= */
/* overlay layers: never take input */
#fxlayer{position:fixed;inset:0;z-index:56;pointer-events:none;overflow:hidden}
#fxcanvas{position:fixed;left:0;top:0;width:100vw;height:100vh;z-index:55;pointer-events:none}  /* under #fxlayer: numbers, banners and ghosts sit on top */
/* the soft element layer: screen-blended so element flair only ever lightens the art beneath it (never covers it) */
#fxsoft{position:fixed;left:0;top:0;width:100vw;height:100vh;z-index:55;pointer-events:none;mix-blend-mode:screen}
#fxlayer *{pointer-events:none!important}
.fx-ghost,.fx-deal,.fx-orbit,.fx-fusion{position:fixed;will-change:transform,opacity}
.fx-ghost>.card,.fx-deal>.card,.fx-deal>.chip,.fx-deal>.back{margin:0!important;box-sizing:border-box}
.fx-deal{z-index:3;transform-style:preserve-3d}
.fx-cardback{position:absolute;inset:0;border-radius:var(--r-md);border:3px solid #a8742f;
 background:radial-gradient(circle at 50% 50%,#e1b86455 0 18%,transparent 19%),repeating-linear-gradient(135deg,#3a2c1f 0 6px,#4a3826 6px 12px);box-shadow:inset 0 0 0 2px #e1b86488}
.fx-flash{position:absolute;inset:0;z-index:5;pointer-events:none;mix-blend-mode:screen;border-radius:var(--r-sm)}
.st .fx-flash{border-radius:var(--r-md)}
.fx-num{position:fixed;z-index:4;font-weight:900;font-family:var(--font-ui);white-space:nowrap;letter-spacing:.5px;
 text-shadow:0 2px 0 #0009,0 0 8px #000a,0 0 2px #000;will-change:transform,opacity}
.fx-num.dmg{color:#ff5a48;-webkit-text-stroke:1px #4a0d08}
.fx-num.heal{color:#7dff8e;-webkit-text-stroke:1px #0b3a12}
.fx-num.blocked{color:#cfe3ff;font-size:var(--fs-lg)!important;-webkit-text-stroke:.6px #102030}
/* item 13: the powered-legend aura (a slow breathing halo in the legend's element color) */
body:not(.fx-off) #app .card.fx-aura{--cs:0 0 0 3px var(--aura),0 0 18px 6px color-mix(in srgb,var(--aura) 75%,transparent);box-shadow:var(--cs);animation:fxaura 2.4s ease-in-out infinite}
body:not(.fx-off) #app .card.fx-aura-awake{animation-duration:1.8s}
@keyframes fxaura{0%,100%{box-shadow:0 0 0 2px var(--aura),0 0 12px 4px color-mix(in srgb,var(--aura) 70%,transparent),var(--hs)}
 50%{box-shadow:0 0 0 3px color-mix(in srgb,var(--aura) 80%,#fff),0 0 26px 10px color-mix(in srgb,var(--aura) 85%,transparent),0 0 52px 16px color-mix(in srgb,var(--aura) 35%,transparent),var(--hs)}}
body:not(.fx-off) #app .card.fx-aura::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;border-radius:var(--r-sm);
 background:linear-gradient(115deg,transparent 30%,color-mix(in srgb,var(--aura) 35%,transparent) 48%,transparent 66%);background-size:250% 100%;animation:fxsheen 3.6s ease-in-out infinite}
@keyframes fxsheen{0%,40%{background-position:120% 0}100%{background-position:-120% 0}}
body.fx-reduced #app .card.fx-aura,body.fx-reduced #app .card.fx-aura::after{animation:none}
/* item 1: hover lift + scale + shadow (mouse only); touch: a small press lift. Nothing here touches user-select / callout.
   Reworked 2026-10-19 (owner: no blur on hover, and a steady shadow). No filter and no 3D: the old perspective()/rotate
   tilt made Chromium raster the card once at scale 1 and stretch that bitmap (soft text and art), and the drop-shadow
   filter forced the card onto its own filtered surface and was REPLACED by any other filter (an exhausted card lost its
   grey, a playable card swapped filter lists, which can't be interpolated, so the shadow popped). Now: a flat 2D
   translate + scale (re-rastered at its final size, so it stays sharp) and the shadow as an extra box-shadow (--hs)
   added to the card's own state shadow (--cs). The lifted state is the .fx-hov class that ui/fx.js keeps on the card
   under the pointer, measured against the card's RESTING box (with :hover the raised card slid out from under a
   pointer near its bottom edge, dropped, and rose again: the flicker; and a re-render's new node lost the hover). */
#app .card{--hs:0 0 0 0 transparent,0 0 0 0 transparent}
@media (hover:hover) and (pointer:fine){
 body.fx-full #app .card:not(.lg){transition:transform .18s cubic-bezier(.2,.8,.3,1),box-shadow .18s ease-out}
 body.fx-full #app .card.fx-hov:not(.lg){transform:translateY(-6px) scale(1.04);z-index:8;
  --hs:0 12px 18px -4px #0007,0 0 10px 1px color-mix(in srgb,var(--c1) 70%,#fff);box-shadow:var(--cs),var(--hs)}
 body.fx-full #app .card.hand.fx-hov{transform-origin:50% 100%;transform:translateY(-3px) scale(1.04)}
 body.fx-reduced #app .card.fx-hov:not(.lg){--hs:0 0 0 0 transparent,0 0 9px 2px color-mix(in srgb,var(--c1) 70%,#fff);box-shadow:var(--cs),var(--hs)}
 body:not(.fx-off) #app .card.defending.fx-hov:not(.lg){box-shadow:var(--cs),var(--hs)!important}
}
body:not(.fx-off) #app .card.fx-press{transform:translateY(-3px) scale(1.03);transition:transform .12s ease-out;z-index:8}
body.fx-reduced #app .card.fx-press{transform:none;filter:brightness(1.08)}
/* item 14: fusion swirl */
.fx-veil{position:fixed;inset:0;background:radial-gradient(ellipse at 50% 50%,#0000 20%,#0b0806cc 75%);opacity:0}
.fx-ftile{position:relative;width:100%;height:100%;border-radius:var(--r-md);overflow:hidden;border:3px solid #e1b864;background:#2a2018;box-shadow:0 0 18px 4px #ffe08a88}
.fx-ftile img{width:100%;height:100%;object-fit:cover;display:block}
.fx-fusion .fx-ftile.big{height:auto;aspect-ratio:16/9;box-shadow:0 0 0 2px #fff6d6,0 0 34px 10px #ffd770aa,0 0 80px 20px #ffb34755}
.fx-fname{margin-top:6px;text-align:center;font:700 15px/1.2 "DejaVu Serif",Georgia,serif;color:#fff3cf;letter-spacing:1.5px;text-shadow:0 0 8px #000,0 0 14px #b8862f}
.fx-bloom{position:fixed;width:320px;height:320px;border-radius:50%;background:radial-gradient(circle,#fffef5 0,#ffe9a8cc 22%,#ffcf6a66 45%,transparent 70%);mix-blend-mode:screen}
/* item 17: turn banner + end titles */
.fx-banner{position:fixed;left:0;right:0;top:50%;height:74px;margin-top:-37px;display:flex;align-items:center;justify-content:center}
.fx-band{position:absolute;inset:0;overflow:hidden;background:linear-gradient(90deg,transparent,#120d0ae6 12%,#120d0ae6 88%,transparent);border-top:1px solid #e1b86499;border-bottom:1px solid #e1b86499}
.fx-banner.theirs .fx-band{background:linear-gradient(90deg,transparent,#1c0b0ae6 12%,#1c0b0ae6 88%,transparent);border-color:#d2604f99}
.fx-sheen{position:absolute;top:0;bottom:0;left:0;width:22vw;background:linear-gradient(90deg,transparent,#ffe9a833,transparent)}
.fx-btxt{position:relative;text-align:center;color:#f6e2a6;text-transform:uppercase;letter-spacing:.18em}
.fx-btxt b{display:block;font:700 28px/1.1 "DejaVu Serif",Georgia,serif;text-shadow:0 0 12px #b8862f,0 2px 0 #000}
.fx-btxt small{display:block;font-size:var(--fs-sm);letter-spacing:.3em;color:#c9b48c;margin-top:3px}
.fx-banner.theirs .fx-btxt b{color:#ffd2c4;text-shadow:0 0 12px #a8382a,0 2px 0 #000}
.fx-end{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at 50% 48%,#0b080622,#0b0806c4 70%)}
.fx-endrays{position:absolute;left:50%;top:48%;width:170vmax;height:170vmax;transform:translate(-50%,-50%);opacity:.55;
 background:repeating-conic-gradient(from 0deg,#ffe08a2e 0 6deg,transparent 6deg 18deg);-webkit-mask:radial-gradient(circle,#000 0,#0008 25%,transparent 60%);mask:radial-gradient(circle,#000 0,#0008 25%,transparent 60%)}
.fx-endtxt{position:relative;text-align:center;text-transform:uppercase}
.fx-endtxt b{display:block;padding:0 4vw;font:700 clamp(26px,min(6.4vw,15vh),88px)/1.05 "DejaVu Serif",Georgia,serif;letter-spacing:.14em;color:#ffe9a8;
 background:linear-gradient(180deg,#fffbe6,#f2cf6f 55%,#b9822c);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;filter:drop-shadow(0 3px 0 #0009) drop-shadow(0 0 18px #c99a3c)}
.fx-endtxt small{display:block;margin-top:10px;font-size:clamp(11px,1.8vw,16px);letter-spacing:.35em;color:#eadfca;text-shadow:0 1px 4px #000}
.fx-endtxt em{display:block;margin-top:16px;font-style:normal;font-size:var(--fs-sm);letter-spacing:.3em;color:#b9a98f99}
.fx-end.claim .fx-endtxt b::before{content:"\265B";display:block;font-size:.45em;margin-bottom:6px;-webkit-text-fill-color:#f2cf6f}
.fx-end.defeat{background:radial-gradient(ellipse at 50% 48%,#2a0a0644,#0b0606dd 70%)}
.fx-end.defeat .fx-endrays{display:none}
.fx-end.defeat .fx-endtxt b{background:linear-gradient(180deg,#e8d6d0,#9a6a62 60%,#4a2420);-webkit-background-clip:text;background-clip:text;filter:drop-shadow(0 3px 0 #000a) drop-shadow(0 0 16px #6a1c14)}
.fx-end.draw .fx-endrays{opacity:.25}
/* ---- trap trigger / Fusion Breaker response prompt (G.decision) ---- */
#decision.hidden{display:none}
.decide{position:fixed;inset:0;z-index:85;background:#1d1712b0;display:flex;align-items:center;justify-content:center;padding:max(8px,env(safe-area-inset-top)) max(10px,env(safe-area-inset-right)) max(8px,env(safe-area-inset-bottom)) max(10px,env(safe-area-inset-left))}
.decide-box{background:#efe7da;color:var(--text);border:2px solid var(--bronze);border-radius:var(--r-lg);box-shadow:0 10px 40px #000a;max-width:900px;width:100%;max-height:100%;overflow:auto;padding:12px 16px;display:grid;grid-template-columns:1fr;gap:8px}
.decide.breaker .decide-box{border-color:#7d1f1a;background:linear-gradient(180deg,#f3e2d6,#efe7da 40%)}
.decide h2{margin:0;color:#5a3a0e;font-size:var(--fs-xl)}.decide.breaker h2{color:#7d1f1a}
.decide p{margin:4px 0;font-size:var(--fs-md);line-height:var(--lh-body)}.decide .dsub{color:var(--text-2);font-size:var(--fs-md)}
.decide .dcards{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;align-items:flex-start}
.decide .dopt{display:flex;flex-direction:column;align-items:center;gap:6px}
.decide .dopt.dsrc small{font-weight:700;color:var(--red);text-transform:uppercase;letter-spacing:.06em;font-size:var(--fs-sm)}
.decide .dopt.dsrc .card{filter:saturate(.9);opacity:.95}
.decide button{min-height:44px;min-width:44px;padding:8px 16px;font-size:var(--fs-lg);border-radius:var(--r-md)}
.decide .dopt button{width:100%}
.decide .dfoot{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.decide .dfoot .pass{min-width:180px}.decide .dfoot .danger{background:#7d1f1a;color:#fff;border-color:#5a1410}
.decide .dmin{background:transparent;border:1px dashed var(--line);color:var(--text-2)}
.decide .dpay{justify-content:center;min-width:180px;align-self:center}
.decide .dcq{display:flex;flex-direction:column;align-items:center;padding:10px 18px;border:2px solid var(--bronze);border-radius:50%;width:110px;height:110px;justify-content:center;background:#f6ecd6}
.decide .dcq .sym{color:var(--bronze);font-size:var(--fs-xl)}.decide .dcq b{font-size:30px;line-height:1}.decide .dcq small{font-size:var(--fs-xs);line-height:var(--lh-tight);text-align:center;color:var(--text-2);max-width:72px}
.decide.min{inset:auto 0 auto 0;top:max(6px,env(safe-area-inset-top));background:none;pointer-events:none}
.decide-bar{pointer-events:auto;display:flex;gap:12px;align-items:center;background:#efe7da;border:2px solid var(--bronze);border-radius:var(--r-lg);padding:4px 6px 4px 14px;box-shadow:0 4px 16px #0008}
.decide.breaker .decide-bar{border-color:#7d1f1a}
/* landscape phones: text + buttons on the left, the cards side by side on the right, everything inside 390 px */
body.land .decide-box{grid-template-columns:minmax(220px,1fr) auto;grid-template-rows:auto 1fr;padding:8px 12px;gap:6px 12px;max-width:820px}
body.land .decide .dhead{grid-column:1;grid-row:1}
body.land .decide .dfoot{grid-column:1;grid-row:2;flex-direction:column;justify-content:flex-end;align-items:stretch}
body.land .decide .dcards{grid-column:2;grid-row:1/3;flex-wrap:nowrap;gap:8px}
body.land .decide h2{font-size:var(--fs-lg)}body.land .decide p{font-size:var(--fs-sm);line-height:var(--lh-snug);margin:2px 0}body.land .decide .dsub{font-size:var(--fs-sm)}
body.land .decide .card.lg{width:150px;min-height:0}
body.land .decide .card.lg .tb{min-height:0;font-size:var(--fs-sm);line-height:var(--lh-snug)}
body.land .decide .card.lg .art{aspect-ratio:16/8}
body.land .decide .dopt button{font-size:var(--fs-md);padding:6px 8px}
body.land .decide .dcq{width:88px;height:88px;padding:6px}body.land .decide .dcq b{font-size:24px}
body.land .decide .dpay{min-width:150px}

/* ---- guided tutorial: coach callout + highlight ring ---- */
#coach.hidden,#tutring.hidden{display:none}
#coach{position:fixed;z-index:120;width:min(330px,calc(100vw - 16px));background:#1d1712f2;color:#f3e8d2;border:2px solid #e1b864;border-radius:var(--r-lg);
  box-shadow:0 8px 28px #000c;padding:9px 12px 10px;font-size:var(--fs-md);line-height:var(--lh-snug);transition:left .25s ease,top .25s ease}
#coach .co-top{display:flex;justify-content:space-between;color:#e1b864;font-size:var(--fs-sm);letter-spacing:.08em;text-transform:uppercase}
#coach b{display:block;font-family:var(--font-display);font-size:var(--fs-lg);margin:2px 0 3px;color:#ffe9a8}
#coach p{margin:0 0 8px}
#coach .co-btns{display:flex;gap:8px;align-items:center;justify-content:space-between}
#coach button{min-height:44px;min-width:44px;padding:6px 14px;border-radius:var(--r-md);font-size:var(--fs-md)}
#coach .co-skip{background:transparent;color:#cdbb98;border:1px solid #6d5a44}
#coach button.primary{background:linear-gradient(#b8843a,#8a5d22);color:#fff8ea;border:1px solid #e1b864;margin-left:auto}
#coach .co-wait{margin-left:auto;font-size:var(--fs-sm);color:#e1b864;font-style:italic}
#tutring{position:fixed;z-index:119;pointer-events:none;border:3px solid #ffd76a;border-radius:var(--r-lg);box-shadow:0 0 0 3px #0008,0 0 22px 4px #ffd76acc;animation:tutpulse 1.4s ease-in-out infinite}
@keyframes tutpulse{50%{box-shadow:0 0 0 3px #0008,0 0 34px 10px #ffd76a88}}
body.reduced-motion #tutring{animation:none}
.decide .dtut{background:#fff3c8;border:1px solid #e1b864;border-radius:var(--r-md);padding:4px 8px;font-size:var(--fs-md)}
body.land #coach{width:min(300px,calc(100vw - 16px));font-size:var(--fs-sm);padding:7px 10px 8px}
body.land #coach b{font-size:var(--fs-md)}body.land #coach p{margin-bottom:6px}

/* ---- Add to Home Screen ---- */
.mn-install{margin-top:12px;min-height:44px;padding:6px 16px!important;border-radius:22px!important;background:#2a211bcc!important;border:1px solid #e1b864!important;color:#f6e7c1!important;font-size:var(--fs-md);display:inline-flex;align-items:center;gap:8px}
#install-nudge{position:fixed;z-index:70;left:50%;transform:translateX(-50%);bottom:max(10px,calc(var(--sab) + 6px));width:min(620px,calc(100vw - 20px - var(--sal) - var(--sar)));
  display:flex;align-items:center;gap:10px;background:#1d1712f2;border:2px solid #e1b864;border-radius:var(--r-lg);padding:8px 10px;box-shadow:0 8px 30px #000c;color:#f3e8d2}
#install-nudge>span:nth-child(2){flex:1;min-width:0}#install-nudge b{display:block;color:#ffe9a8}#install-nudge small{display:block;font-size:var(--fs-sm);color:#cdbb98;line-height:var(--lh-snug)}
#install-nudge button{min-height:44px;min-width:64px;padding:6px 14px}
.in-ic{display:inline-flex;width:40px;height:40px;flex:0 0 40px;align-items:center;justify-content:center;color:#2f6fd6}
#install-nudge .in-ic{color:#e1b864}.in-ic svg{width:100%;height:100%}.in-ic.sm{width:26px;height:26px;flex-basis:26px;vertical-align:middle;margin-right:6px;color:var(--green)}
.in-steps{list-style:none;padding:0;margin:8px 0;display:grid;gap:8px}
.in-step{display:flex;align-items:center;gap:12px;background:#fff8ea;border:1px solid #d8c6a4;border-radius:var(--r-lg);padding:8px 12px;font-size:var(--fs-md)}
.in-n{width:26px;height:26px;flex:0 0 26px;border-radius:50%;background:#8a5d22;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700}
.in-pill{font-weight:700;color:#2f6fd6;border:2px solid #2f6fd6;border-radius:var(--r-md);padding:2px 8px;font-size:var(--fs-md)}
.in-note{font-size:var(--fs-md)}
body.land .in-steps{grid-template-columns:repeat(3,1fr)}body.land .in-step{flex-direction:column;text-align:center;gap:4px;padding:6px 8px;font-size:var(--fs-sm)}
body.land .in-sheet h2{font-size:var(--fs-xl);margin-bottom:2px}body.land .in-sheet p{margin:4px 0;font-size:var(--fs-md)}
.pg-head .pg-tut{margin-left:auto;min-height:44px;border-color:#e1b864!important}

/* ---- overlay stacking (body.ovl is set by ui/fx.js whenever a modal-like overlay is open: card sheet, modal, trap /
   breaker prompt, More drawer, match log panel, game setup, settings / Codex / menus, install suggestion). Board
   effects never show through: the fx canvases and layer are hidden (the combat pop-up keeps its own effects), card
   auras, target pulses and hover lifts stop, and every overlay gets an opaque-enough, blurred backdrop on its own
   compositing layer (WebKit draws 3D-transformed cards above fixed siblings unless the overlay is promoted too). */
body.ovl #fxcanvas,body.ovl #fxsoft{visibility:hidden}
body.ovl-m #coach,body.ovl-m #tutring{visibility:hidden}
body.ovl #fxlayer>:not(.cbpop):not(.fx-end){visibility:hidden}
body.ovl #app .card.fx-aura,body.ovl #app .card.fx-aura::after,body.ovl #app .card.target,body.ovl #app .card.target-own,body.ovl #app .card.target-fuse,
body.ovl #tutring{animation-play-state:paused!important}
body.ovl #app .card.fx-aura{box-shadow:0 0 0 2px var(--aura)!important}
body.ovl #app .card.fx-aura::after{opacity:0}
body.ovl #app .card:hover,body.ovl #app .card.fx-hov,body.ovl #app .card.fx-press{transform:none!important;filter:none!important;z-index:auto!important}
#modal,#sheet,.decide,#coach,#screen,#raildrawer,body.showlog #logpanel,#cbpop{transform:translateZ(0)}
#modal{background:#1d1712c4;-webkit-backdrop-filter:blur(3px) saturate(.7);backdrop-filter:blur(3px) saturate(.7)}
#sheet{background:#1d1712c4;-webkit-backdrop-filter:blur(3px) saturate(.7);backdrop-filter:blur(3px) saturate(.7)}
.decide{background:#1d1712d6;-webkit-backdrop-filter:blur(3px) saturate(.7);backdrop-filter:blur(3px) saturate(.7)}
.decide.min{background:none;-webkit-backdrop-filter:none;backdrop-filter:none}
#coach{background:#1d1712}
/* the More drawer lives in the action rail (z 45): lift the rail above the fx layers while it is open */
body.drawer-open #actdock{z-index:64}
body.ovl.drawer-open #app::after,body.ovl.showlog.land #app::after{content:"";position:fixed;inset:0;z-index:57;background:#1d17124d;pointer-events:none}

/* ---- the 1v1 combat pop-up (ui/fx.js combatPopup): attacker left, defender right, bars, clash, result */
.cbpop{position:fixed;inset:0;z-index:78;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(4px,1.6vh,12px);
 padding:max(6px,var(--sat,0px)) max(10px,var(--sar,0px)) max(6px,var(--sab,0px)) max(10px,var(--sal,0px));cursor:pointer;-webkit-user-select:none;user-select:none;
 --cbw:clamp(118px,min(24vw,42vh),230px);color:#f3e8d2;font-family:var(--font-ui)}
.cb-back{position:absolute;inset:0;background:radial-gradient(ellipse at 50% 45%,#2a2018f0,#120d0af7 75%);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.cb-stage{position:relative;display:flex;align-items:center;justify-content:center;gap:clamp(8px,3vw,40px);width:100%}
.cb-side{position:relative;display:flex;flex-direction:column;align-items:center;gap:4px;width:calc(var(--cbw) + 40px)}
.cb-tag{font-size:var(--fs-sm);letter-spacing:.12em;text-transform:uppercase;color:#e1b864;font-weight:700;white-space:nowrap}
.cb-card{position:relative;width:var(--cbw);aspect-ratio:3/3.3;border-radius:var(--r-lg);border:3px solid var(--c1,#a8742f);background:var(--c3,#2e2620);
 box-shadow:0 10px 26px #000c,0 0 0 1px #0008;overflow:visible}
.cb-art{position:absolute;inset:0 0 26px 0;border-radius:var(--r-md) 7px 0 0;overflow:hidden;background:linear-gradient(160deg,var(--c1,#555),var(--c3,#222));background-size:cover;background-position:center}
.cb-art img{width:100%;height:100%;object-fit:cover;display:block}
.cb-name{position:absolute;left:0;right:0;bottom:0;min-height:26px;line-height:1.15;display:flex;align-items:center;justify-content:center;text-align:center;padding:0 6px;font-weight:800;font-size:clamp(10.5px,1.6vw,12.5px);
 color:var(--t1,#fff);background:var(--c1,#a8742f);border-radius:0 0 7px 7px;white-space:normal;overflow:visible}  /* whole words, fitText() keeps it to 2 lines (AUD-UI-1/2) */
.cb-glow{position:absolute;inset:-14px;border-radius:18px;background:radial-gradient(ellipse at 50% 50%,color-mix(in srgb,var(--cbc) 55%,transparent),transparent 70%);z-index:-1;opacity:.75}
.cbpop.reduced .cb-glow{opacity:.45}
.cb-hit{position:absolute;inset:-10%;border-radius:50%;pointer-events:none;opacity:0;mix-blend-mode:screen;
 background:radial-gradient(circle,var(--hh,#fff) 0,var(--hc,#ffd24a) 22%,color-mix(in srgb,var(--hc,#ffd24a) 40%,transparent) 45%,transparent 70%)}
.cb-spark{position:absolute;left:50%;top:45%;width:7px;height:7px;border-radius:50%;pointer-events:none;box-shadow:0 0 8px currentColor}
.cb-float{position:absolute;left:50%;top:40%;font-weight:900;font-size:clamp(22px,4.4vh,34px);white-space:nowrap;pointer-events:none;
 text-shadow:0 2px 0 #0009,0 0 8px #000a;-webkit-text-stroke:1px #3a0b06}
.cb-float.dmg{color:#ff5a48}.cb-float.big{font-size:clamp(28px,6vh,44px)}
.cb-float.cbsh{color:#fff;-webkit-text-stroke:0;text-shadow:0 1px 2px #000;font-size:var(--fs-sm);font-weight:800;top:0;height:15px;line-height:15px;padding:0 8px;border-radius:var(--r-md);background:#2f6fa8;box-shadow:0 0 0 2px #cfe3ff,0 0 12px #6fb0ff;z-index:4}
.cb-bars{position:relative}
.cb-dead{position:absolute;left:50%;top:42%;z-index:3;padding:3px 10px;border:2px solid #ff8a7a;border-radius:var(--r-md);background:#3a0d08e6;color:#ffd9d2;font-weight:900;
 letter-spacing:.12em;text-transform:uppercase;font-size:var(--fs-md);white-space:nowrap}
.cb-side.dead .cb-glow{opacity:0}
.cb-stats{display:flex;gap:6px;align-items:center;justify-content:center;min-height:18px;font-size:var(--fs-sm)}
.cb-atk{background:#7d1f1a;color:#fff;padding:1px 8px;border-radius:var(--r-md);font-weight:700;white-space:nowrap}
.cb-adv{font-size:var(--fs-sm);font-weight:800;opacity:0;white-space:nowrap}.cb-adv.up{color:#8ff0a0}.cb-adv.down{color:#ffab9e}
.cb-bars{display:flex;flex-direction:column;gap:3px;width:calc(var(--cbw) + 10px)}
.cb-sh,.cb-hp{position:relative;height:15px;border-radius:var(--r-md);background:#0008;border:1px solid #fff3;overflow:hidden}
.cb-sh.none{opacity:.35}
.cb-sh i,.cb-hp i{position:absolute;left:0;top:0;bottom:0;transition:width .42s cubic-bezier(.2,.7,.3,1)}
.cb-sh i{background:linear-gradient(#9cc6ea,#2f6fa8)}
.cb-hp i.lag{background:#ffd1a8;transition-duration:.6s}
.cb-hp i.cur{background:linear-gradient(#7fdc8a,#2f8a45)}
.cb-side.losing .cb-hp i.cur{background:linear-gradient(#ff8a7a,#a8261a)}
.cb-sh span,.cb-hp span{position:relative;display:block;text-align:center;font-size:var(--fs-xs);line-height:15px;font-weight:700;text-shadow:0 1px 2px #000}
.cb-mid{position:relative;width:clamp(78px,13vw,150px);display:flex;align-items:center;justify-content:center;align-self:stretch}
.cb-vs{font:700 clamp(20px,5vh,34px)/1 "DejaVu Serif",Georgia,serif;color:#e1b864;letter-spacing:.08em;text-shadow:0 2px 6px #000;transition:opacity .2s}
.cb-trap{position:absolute;left:50%;top:44%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:3px;width:clamp(66px,11vw,128px)}
.cb-trap small{font-weight:900;color:#ffb36a;letter-spacing:.12em;text-transform:uppercase;font-size:var(--fs-sm)}
.cb-tcard{position:relative;width:100%;aspect-ratio:3/3.3;border-radius:var(--r-md);border:2px solid var(--c1,#7d1f1a);box-shadow:0 0 18px #ff9a4a99,0 6px 16px #000b;background:var(--c3,#222)}
.cb-tcard .cb-art{bottom:26px}.cb-tcard .cb-name{font-size:var(--fs-2xs);white-space:normal;text-align:center}
.cb-stamp{position:absolute;left:50%;top:50%;padding:3px 9px;border:3px solid #ff8a5a;color:#ffd3b8;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
 font-size:clamp(12px,2.6vh,17px);background:#3a1508cc;border-radius:var(--r-md);opacity:0;white-space:nowrap;pointer-events:none}
.cb-clash{position:absolute;left:50%;top:50%;width:120px;height:120px;border-radius:50%;pointer-events:none;mix-blend-mode:screen;
 background:radial-gradient(circle,#fff 0,var(--hc,#ffd24a) 25%,transparent 65%)}
.cb-result{position:relative;min-height:clamp(30px,8vh,46px);text-align:center;opacity:0}
.cb-result b{display:block;font:700 clamp(17px,4.4vh,26px)/1.15 "DejaVu Serif",Georgia,serif;letter-spacing:.06em;color:#ffe9a8;text-shadow:0 2px 6px #000}
.cb-result.bad b{color:#ffb3a6}.cb-result.good b{color:#c9f5b8}
.cb-result small{display:block;font-size:var(--fs-sm);color:#d8cab0}
.cb-skip{position:absolute;right:max(12px,var(--sar,0px));bottom:max(8px,var(--sab,0px));font-size:var(--fs-sm);color:#b9a98f;letter-spacing:.06em}
body.cb-open #coach,body.cb-open #tutring,body.cb-open #tip{visibility:hidden}
@media (max-height:360px){.cbpop{--cbw:clamp(100px,min(22vw,38vh),150px);gap:3px}.cb-tag{font-size:var(--fs-xs)}.cb-stats{min-height:15px}.cb-sh,.cb-hp{height:13px}.cb-sh span,.cb-hp span{line-height:13px;font-size:var(--fs-2xs)}}

/* click lock: the action buttons in a board card's sheet (the confirm step) */
.sheet-acts{display:flex;flex-direction:column;gap:8px;margin:8px 0 4px}
.sheet-act{min-height:44px;font-size:var(--fs-lg);font-weight:800;border-radius:var(--r-lg);padding:8px 14px;border:0;color:#fff;background:linear-gradient(#5a7a3a,#3f5a26);box-shadow:0 2px 0 #0004;cursor:pointer;text-align:center}
.sheet-act.attack{background:linear-gradient(#c0412e,#8e2a1c)}
.sheet-act.invoke{background:linear-gradient(#8a6a2a,#6a4c16)}
.sheet-act.fuse{background:linear-gradient(#d9ad4f,#a77a22);color:#2a1d08}
.sheet-act.replace_main,.sheet-act.replace_follower{background:linear-gradient(#c0612a,#8f4419)}
@media (orientation:landscape) and (max-height:500px){.sheet-acts{margin:0 0 4px}.sheet-act{min-height:40px;font-size:var(--fs-md);padding:6px 12px}}

/* revive picker: the valid creatures in your discard pile (tap one, then confirm) */
.decide.revive .decide-box{border-color:#8a6a2a}
.rv-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(118px,1fr));grid-auto-rows:max-content;gap:8px;max-height:min(52vh,420px);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:4px 2px}
.rv-tile{position:relative;box-sizing:border-box;flex-shrink:0;min-height:max-content;display:flex;flex-direction:column;align-items:stretch;gap:2px;padding:4px 4px 6px;min-height:0;border-radius:var(--r-lg);border:2px solid var(--c1,#8a6a2a);background:linear-gradient(180deg,var(--c3,#efe7da) 0,#fbf6ec 60%);color:var(--text);cursor:pointer;text-align:center;font:inherit}
.rv-tile:focus-visible{outline:3px solid #2f6fa8}
.rv-tile .rv-art{position:relative;flex:none;width:100%;height:96px;aspect-ratio:auto;border-radius:var(--r-md);overflow:hidden}
.rv-tile .rv-art img{width:100%;height:100%;object-fit:cover}
.rv-tile .rv-cost{position:absolute;top:6px;left:6px;width:22px;height:22px;border-radius:50%;background:#1d1712d9;color:#f6e7c1;font-weight:800;font-size:var(--fs-sm);line-height:22px}
.rv-tile .rv-n{position:absolute;top:6px;right:6px;padding:0 5px;border-radius:var(--r-md);background:#1d1712d9;color:#fff;font-size:var(--fs-sm);font-weight:800;line-height:18px}
.rv-tile .rv-nm{font-size:var(--fs-sm);line-height:var(--lh-tight);display:block;min-height:2.3em}
.rv-tile .rv-st{display:flex;gap:4px;justify-content:center}.rv-tile .rv-st i{font-style:normal;font-weight:800;font-size:var(--fs-sm);padding:0 5px;border-radius:var(--r-md);color:#fff}
.rv-tile .rv-st .a{background:#9b2c1f}.rv-tile .rv-st .d{background:#2f5f8a}
.rv-tile .rv-kw{font-size:var(--fs-xs);color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rv-tile.on{outline:4px solid #e1b864;outline-offset:1px;box-shadow:0 0 16px 3px #f2d27a;transform:translateY(-2px)}
.decide .revive[disabled]{opacity:.55}
body.land .decide.revive .decide-box{grid-template-columns:minmax(200px,250px) minmax(0,1fr);max-width:860px;height:100%}
body.land .decide .rv-grid{grid-column:2;grid-row:1/3;max-height:none;height:100%;min-height:0;grid-template-columns:repeat(auto-fill,minmax(112px,1fr));align-content:start}
body.land .rv-tile .rv-art{height:70px}

/* full-hand burn picker: the drawn card (marked "Drawn") + the 8 hand cards; tap one, then confirm */
.decide.full_hand .decide-box{border-color:#9b2c1f}
.bn-grid{grid-template-columns:repeat(auto-fill,minmax(104px,1fr))}
.bn-tile .bn-tag{position:absolute;top:6px;right:6px;padding:0 6px;border-radius:var(--r-md);background:#2f6fa8;color:#fff;font-size:var(--fs-xs);font-weight:800;line-height:18px;letter-spacing:.04em;text-transform:uppercase;box-shadow:0 1px 3px #0007}
.bn-tile.bn-drawn{border-color:#2f6fa8;box-shadow:0 0 0 2px #2f6fa8aa,0 0 10px 1px #4f86b8aa}
.bn-tile.bn-drawn.on{box-shadow:0 0 16px 3px #f2d27a}
.rv-tile .rv-st .t{background:#6b5a4a}
.rv-nm .nw{white-space:nowrap}
.decide.full_hand .dsub{font-size:var(--fs-sm)}
body.land .decide.full_hand .dsub{font-size:var(--fs-xs)}
body:not(.land) .decide .bn-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
.decide .dfoot .burn{background:linear-gradient(#c0412e,#8e2a1c);color:#fff;border-color:#7a2116;min-width:150px}
.decide .burn[disabled]{opacity:.55}
body.land .decide.full_hand .decide-box{grid-template-columns:minmax(190px,230px) minmax(0,1fr);max-width:900px;height:100%}
body.land .decide .bn-grid{grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}
body.land .bn-tile .rv-art{height:56px}

/* opponent action banner (top): what the AI just did, in plain words */
#oppbanner{position:fixed;top:max(6px,env(safe-area-inset-top));left:50%;z-index:59;display:flex;align-items:center;gap:10px;max-width:min(620px,calc(100vw - 24px));
 padding:7px 16px 7px 10px;border-radius:var(--r-lg);background:#2a1712f0;color:#fbeedd;border:2px solid #c0412e;box-shadow:0 6px 22px #000a;
 transform:translate(-50%,-140%);opacity:0;transition:transform .22s cubic-bezier(.2,.7,.3,1),opacity .22s;pointer-events:none;cursor:pointer}
#oppbanner.show{transform:translate(-50%,0);opacity:1;pointer-events:auto}
#oppbanner .ob-ic{flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;background:#c0412e;color:#fff;font-size:var(--fs-lg);font-weight:900}
#oppbanner .ob-tx{display:flex;flex-direction:column;min-width:0}
/* one size for both lines on every banner (AI and online): --ob-fs (16px desktop, 13.5px landscape phone) */
#oppbanner{--ob-fs:var(--fs-lg)}
#oppbanner b,#oppbanner .ob-sub{display:block;font-size:var(--ob-fs);line-height:var(--lh-snug);overflow-wrap:normal;word-break:normal;white-space:normal}
#oppbanner b{font-weight:700}
#oppbanner .ob-sub{font-weight:400;color:#f3c9a8}
#oppbanner.ob-shield,#oppbanner.ob-trap{border-color:#4f86b8}#oppbanner.ob-shield .ob-ic,#oppbanner.ob-trap .ob-ic{background:#2f6fa8}
#oppbanner.ob-claim,#oppbanner.ob-fuse{border-color:#d4a843}#oppbanner.ob-claim .ob-ic,#oppbanner.ob-fuse .ob-ic{background:#a77a22}
#oppbanner.ob-end{border-color:#8c7b6a}#oppbanner.ob-end .ob-ic{background:#6b5a4a}
body.land #oppbanner{left:calc(50% - 56px);max-width:min(560px,calc(100vw - 150px));padding:5px 14px 5px 8px}
body.land #oppbanner{--ob-fs:var(--fs-md)}body.land #oppbanner .ob-ic{width:26px;height:26px;font-size:var(--fs-md)}
body.ovl #oppbanner,body.inmenu #oppbanner{visibility:hidden;opacity:0;pointer-events:none}

/* Defense stance: a steel shield token on the Main (the card stays upright; see DEF_TOKEN in app.js) */
.card.defending{--cs:0 0 0 3px #8fb4d8,0 0 14px 4px #5d8fc4aa;box-shadow:var(--cs)!important}
.card.defending .art{filter:saturate(.8) brightness(.92)}
.def-token{position:absolute;z-index:4;left:50%;top:48%;transform:translate(-50%,-50%);width:44px;height:50px;pointer-events:none;
 display:flex;align-items:center;justify-content:center;filter:drop-shadow(0 2px 3px #0009)}
.def-token svg{position:absolute;inset:0;width:100%;height:100%}
.def-token svg path{fill:#3d6d9e;stroke:#e6eef7;stroke-width:1.6}
.def-token svg path.ln{fill:none;stroke:#cfe0f2;stroke-width:1.4;opacity:.55}
.def-token b{position:relative;margin-top:2px;font-size:var(--fs-xs);font-weight:900;letter-spacing:.04em;color:#fff;text-shadow:0 1px 2px #000}
.card.lg .def-token{top:90px;width:60px;height:68px}.card.lg .def-token b{font-size:var(--fs-md)}
/* only when the card has just started defending (app.js render adds .def-new), not on every re-render */
@media (prefers-reduced-motion:no-preference){.card.defending .def-token.def-new{animation:defin .35s cubic-bezier(.2,.8,.3,1.3) both}}
@keyframes defin{from{transform:translate(-50%,-50%) scale(.3);opacity:0}to{transform:translate(-50%,-50%) scale(1);opacity:1}}
.sheet-act.defend{background:linear-gradient(#4f7fae,#2f5a86)}
.sheet-note{margin:0;font-size:var(--fs-sm);line-height:var(--lh-snug);color:var(--text-2)}
#oppbanner.ob-defend .ob-ic{color:#8fb4d8}

/* opening redraw prompt */
.decide.redraw .decide-box{border-color:#2f5a86}
.rd-hand{display:flex;gap:6px;justify-content:center;flex-wrap:nowrap;overflow-x:auto;padding:4px 2px;--hh:116px;--hw:calc((var(--hh) - 38px)*16/9 + 12px)}
.rd-hand .card.hand{flex:none}
.decide .dfoot .redraw{background:linear-gradient(#4f7fae,#2f5a86);color:#fff;border-color:#24496f;min-width:150px}
body.land .decide.redraw .decide-box{grid-template-columns:minmax(220px,300px) minmax(0,1fr)}
body.land .decide .rd-hand{grid-column:2;grid-row:1/3;flex-wrap:wrap;align-content:center;--hh:104px}
.sheet-note.conq{color:#8a5a00;font-weight:600}

/* ======================================================================================================
   Style system (2026-10 style pass). Shared rules on top of the tokens in :root.
   - one font set (--font-ui body, --font-display headings), numbers in --font-num, bold, tabular figures
   - labels: bold + colon ("Belief: 3"), visibly distinct from body text; sub text smaller and lower contrast
   ====================================================================================================== */
body{font-family:var(--font-ui);font-size:var(--fs-md);line-height:var(--lh-snug);font-variant-numeric:tabular-nums}
h1,h2,h3,h4,.pg-head h1{font-family:var(--font-display);font-weight:700;line-height:var(--lh-tight);letter-spacing:.2px}
.pg h1,.pg-head h1{font-size:var(--fs-xl)}
.pg h2,.modal-box h2,#modal-body h2{font-size:var(--fs-xl)}
.pg h3,.modal-box h3,#modal-body h3,.sheet-text h3{font-size:var(--fs-lg);margin:var(--sp-4) 0 var(--sp-2)}
.pg p,.modal-box p,#modal-body p,.lg-text p,.rl-text p,.sheet-text p{line-height:var(--lh-body)}
/* numbers: Life, Influence, Belief, Shield, Conquest, costs, ATK/DEF, counters */
.num,.badge,.badge b,.cost,.st b,.shield,.ring text,.cb-stats b,.cb-bars b,.cb-num,.mn-count,.dl-n,.dl-cost,.db-count,.conqbar+*,.cbadge b{
 font-family:var(--font-num);font-weight:700;font-variant-numeric:tabular-nums lining-nums;letter-spacing:0}
.badge b{font-weight:800;font-size:1em}
/* labels and sub text */
.lbl,b.lbl{font-weight:700;color:inherit}
.subtext,.sheet-note,.hint,.pg-sub,.st-row small,.ng-tag{font-size:var(--fs-xs);color:var(--text-3);font-weight:400;line-height:var(--lh-snug)}
/* the dark menu screens: the secondary/tertiary tiers become the screens' light secondary ink (AA on the dark panels;
   the parchment values above would be dark-on-dark there, AUD-A11Y-1) */
.screen{--text-2:var(--ink2);--text-3:var(--ink2)}
.st small{font-weight:700;text-transform:none;letter-spacing:0;color:var(--text-2)}
.belief small,.stats-panel small{text-transform:none;letter-spacing:0}
.belief small .lbl,.stats-panel small .lbl{color:var(--text-2)}
.belief small .num,.stats-panel small .num{color:var(--text-1)}
.shieldbox .lbl{line-height:var(--lh-snug)}
.shieldbox .lbl .subtext{display:inline-block;margin-top:2px}
/* tooltip and detail sheet: name, sub line, labelled lines */
#tip .tip-h{font-weight:700;font-size:var(--fs-md);margin-bottom:2px}
#tip .tip-l{font-size:var(--fs-sm);line-height:var(--lh-snug)}
#tip .tip-l+.tip-l{margin-top:2px}
#tip .subtext{color:inherit;opacity:.72}
.sheet-text p{margin:0 0 var(--sp-1);font-size:var(--fs-md)}
.sheet-text p .subtext{font-size:var(--fs-sm)}
.sheet-text .lbl{color:var(--text-1)}
/* Card stat modifiers: no centre pill between ATK and DEF any more. Buffed numbers turn green with a small up marker,
   reduced ones orange with a down marker; the base vs modifier is in the details panel. */
.card .ft{justify-content:space-between}
.badge .mk{font-style:normal;font-size:.72em;margin-left:1px;vertical-align:1px}
.card:not(.lg) .ft .badge .mk{display:inline}
.badge.a.up,.badge.d.up{color:#1f6b33}
.badge.a.down,.badge.d.down{color:#b8460f}
.badge.d.hurt.up{color:#b8460f}
/* corner badges on the art: a follower's support for the Main (top-left), status New / Exhausted (top-right) */
.art .cbadge{z-index:2}
.cbadge{position:absolute;top:3px;display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:15px;border-radius:var(--r-sm);
 background:#211a14e6;color:#f6e7c1;font-size:var(--fs-2xs);font-weight:700;line-height:15px;white-space:nowrap;box-shadow:0 1px 3px #0009;pointer-events:auto}
.cbadge.sup{left:3px}.cbadge.stat{right:3px}.cbadge.stat.new{background:#2f4f70e6;color:#e8f1f8}
.cbadge i{font-style:normal;font-weight:600;opacity:.8}
.card:not(.lg) .cbadge i{display:inline}
.card.lg .cbadge{font-size:var(--fs-sm);height:20px;line-height:20px;top:6px;padding:0 6px}
.card.lg .cbadge.sup{left:6px}.card.lg .cbadge.stat{right:6px}
/* card names: whole words only (the fitter shrinks the font so names fit in 2 lines; no hyphenation) */
.card .nm,.cb-name,.rv-name,.cx-name,.db-cell .nm,.dl-nm{hyphens:manual;-webkit-hyphens:manual;word-break:normal;overflow-wrap:normal}
/* Heart holder: faction chip next to "Held by" */
.heartfac{display:inline-flex;align-items:center;gap:3px;margin-left:6px;padding:0 6px 0 2px;border-radius:999px;background:var(--c1);color:var(--t1);
 font-size:13px;font-weight:700;line-height:18px;vertical-align:1px}
.heartfac .emb{font-size:13px;width:16px;height:16px}
/* Dominion world view (Heart holder's realm): faint image under a dark scrim, faction-color edge tint; the board panels
   stay nearly opaque so cards, text and numbers keep their contrast */
#worldbg .wb-slide{filter:blur(7px) saturate(.75) brightness(.62)}
#worldbg .wb-slide.on{opacity:.42}
#worldbg .wb-veil{background:linear-gradient(#2a211a59,#2a211a59)}
#worldbg::after{content:"";position:absolute;inset:0;opacity:0;transition:opacity 1.4s ease;pointer-events:none;
 box-shadow:inset 0 0 90px 18px color-mix(in srgb,var(--wtint,transparent) 70%,transparent),inset 0 0 0 3px color-mix(in srgb,var(--wtint,transparent) 75%,transparent)}
body.world #worldbg::after{opacity:1}
body.world .row{background:color-mix(in srgb,var(--zone) 84%,transparent)}
body.world .mainrow{background:color-mix(in srgb,var(--zone2) 88%,transparent)}
/* (the old .brk mid-word fallback and the -webkit-line-clamp ellipsis are gone: names are fitted, never cut, AUD-UI-1/2) */
/* collapsed hand (peek bar): the rarity gem leaves the narrow header so names keep 2 lines; it is back when the hand opens */
body.hand-closed #r-myhand .card:not(.lg) .hd .gem{display:none}body.hand-closed #r-myhand .card:not(.lg) .hd{gap:1px;padding:0 1px 0 2px}
/* Heart holder's faction, made obvious without touching legibility: a faction-colored ring and glow on the Heart
   banner and a faint faction tint along the board's outer edge (the realm view itself stays faint behind the rows) */
body.world .mid.heart.held{box-shadow:0 0 0 2px color-mix(in srgb,var(--wtint) 85%,transparent),0 0 16px 2px color-mix(in srgb,var(--wtint) 50%,transparent)}
#worldbg::after{box-shadow:inset 0 0 140px 28px color-mix(in srgb,var(--wtint,transparent) 62%,transparent),inset 0 0 0 4px color-mix(in srgb,var(--wtint,transparent) 80%,transparent)}
/* ---- online play (ui/online.js, docs/multiplayer/SCOPE_SUPABASE.md M1): sign-in, profile setup, profile.
   Only ever shown when online play is configured. Reuses the page tokens (.pg, .pg-card, --fs-*, --sp-*, --r-*). */
.on-pg{max-width:760px}
.on-card{display:flex;flex-direction:column;gap:var(--sp-3)}
.on-card h2{margin:0;font-size:var(--fs-xl);color:#f6e7c1}
.on-card p{margin:0}
.on-lead{font-size:var(--fs-lg)}
.on-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:var(--sp-5);align-items:center}
.on-intro{display:flex;flex-direction:column;gap:var(--sp-2)}
.on-form{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0}
.on-field{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.on-field>span,.on-crests legend{font-weight:700;font-size:var(--fs-sm);color:var(--ink);letter-spacing:.3px}
/* 16px inputs: iOS Safari zooms the page into any focused field smaller than that */
.screen .on-field input{font-size:16px;min-height:44px;padding:8px 12px;width:100%}
.screen .on-field input:focus{outline:2px solid var(--gold);outline-offset:1px}
.on-field .subtext{color:var(--ink2)}.on-field .subtext.bad{color:#ffb4a4}
.screen .on-submit,.on-actions button,.on-foot button{min-height:44px;padding:8px 16px;font-size:var(--fs-md);font-weight:700}
/* "Continue with Google": Google's light-theme button (white, #747775 border, #1F1F1F Roboto Medium text, standard G) */
.screen .on-google{display:inline-flex;align-items:center;justify-content:center;gap:10px;align-self:flex-start;min-height:44px;padding:0 16px 0 12px;
 background:#fff;border:1px solid #747775;border-radius:4px;color:#1f1f1f;font:500 15px/20px Roboto,"Google Sans",Arial,sans-serif;letter-spacing:.25px;
 box-shadow:none;text-shadow:none;cursor:pointer}
.screen .on-google:hover:not(:disabled){background:#f2f2f2;box-shadow:0 1px 2px #3c40434d,0 1px 3px 1px #3c404326}
.screen .on-google:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.screen .on-google:disabled{background:#ffffff61;border-color:#1f1f1f1f;color:#1f1f1f61;cursor:default}
.screen .on-google:disabled .on-g{opacity:.38}
.on-g{flex:none;width:20px;height:20px}
.on-err{margin:0;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);background:#5a1f17cc;border:1px solid #b5523f;color:#ffe2d8;font-size:var(--fs-sm);line-height:var(--lh-snug)}
.on-err[hidden]{display:none}
.on-actions{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-1)}
/* profile setup: names on the left, the crest picker on the right, Save underneath (outside the scroll) */
.on-setup{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0}
.on-prof-scroll{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-3) var(--sp-5);align-items:start;min-width:0}
.on-col{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0}
.on-crests{border:0;margin:0;padding:0;gap:var(--sp-1)}
.on-crests legend{padding:0;margin-bottom:var(--sp-1)}
.on-crest-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--sp-1)}
.on-crest{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:56px;padding:6px 2px;
 border:1px solid #6d5a44;border-radius:var(--r-md);background:#2a221c;cursor:pointer;font-size:var(--fs-xs);color:var(--ink2);text-align:center;line-height:var(--lh-tight)}
.on-crest input{position:absolute;opacity:0;pointer-events:none}
.on-crest .emb{width:28px;height:28px;font-size:var(--fs-md)}
.on-crest span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.on-crest:hover{border-color:var(--gold)}
.on-crest:has(input:checked){background:#6d4c1f;border-color:var(--gold);color:#fff3d6;font-weight:700;box-shadow:0 0 0 1px var(--gold)}
.on-crest:has(input:focus-visible){outline:2px solid var(--gold);outline-offset:1px}
.on-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--sp-2)}
.on-foot .on-err{flex:1 1 100%}
/* profile */
.on-who{display:flex;align-items:center;gap:var(--sp-4)}
.on-bigcrest .emb{width:64px;height:64px;font-size:30px;border-width:3px;box-shadow:0 0 18px #e1b86444}
.on-handle{color:var(--gold);font-weight:700}
.on-soon{padding:var(--sp-2) var(--sp-3);border:1px dashed #6d5a44;border-radius:var(--r-md);color:var(--ink2);font-size:var(--fs-sm);line-height:var(--lh-snug)}
.on-soon b{color:var(--ink)}
/* delete account: secondary + danger on the profile card (outlined, set apart on the right), a red confirm in the dialog */
.screen .on-actions .on-del{margin-left:auto;background:transparent;border-color:#b5523f;color:#ffb4a4;font-weight:600}
/* real hover only: on touch screens a tap leaves :hover stuck on whatever ends up under the finger */
@media (hover:hover){.screen .on-actions .on-del:hover:not(:disabled){background:#5a1f17;border-color:#ff9a8a;color:#ffe2d8}}
.screen .on-actions .on-del:focus-visible{outline:2px solid #ff9a8a;outline-offset:2px}
.on-delbox{display:flex;flex-direction:column;gap:var(--sp-2);max-width:560px}
/* waiting room (online.js showWaitingRoom, M5): one status line in big type, the buttons under it (44 px targets) */
.on-room-status{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-3) var(--sp-4);border:1px solid #6d5a44;border-radius:var(--r-md);background:#231c17}
.on-room-status h2{margin:0;font-size:var(--fs-xl);color:#f6e7c1;line-height:1.2}
.on-room-status p{margin:0;font-size:var(--fs-md);color:var(--ink);line-height:var(--lh-snug)}
.on-room[data-phase=here] .on-room-status,.on-room[data-phase=started] .on-room-status{border-color:#6f9a5a;background:#1f2c1b}
.on-room[data-phase=cancelled] .on-room-status,.on-room[data-phase=maintenance] .on-room-status,.on-room[data-phase=rate_limited] .on-room-status,
.on-room[data-phase=offline] .on-room-status,.on-room[data-phase=lost] .on-room-status,.on-room[data-phase=error] .on-room-status{border-color:#b5843f;background:#2e2316}
.on-room-actions button{min-width:44px}
.screen .on-room-actions button:disabled{opacity:.55;cursor:not-allowed}
.on-delbox h2{margin:0;color:#7a2216}
.on-delbox p,.on-delbox ul{margin:0}
.on-dellist{padding-left:1.2em;display:flex;flex-direction:column;gap:2px}
.on-delnote{font-size:var(--fs-sm);color:#4d4339}
.on-delfield{display:flex;flex-direction:column;gap:var(--sp-1);font-size:var(--fs-sm);font-weight:600;color:var(--text)}
.on-delfield b{font-family:ui-monospace,Menlo,Consolas,monospace;color:#7a2216}
/* 16px: no iOS focus zoom */
#modal-body .on-delfield input{font-size:16px;min-height:44px;padding:8px 12px;width:100%;box-sizing:border-box;background:#fffaf2;border:1px solid #8a7a66}
#modal-body .on-delfield input:focus{outline:2px solid #b5523f;outline-offset:1px}
.on-delbox .on-err{background:#fbe3dd;border-color:#b5523f;color:#7a2216}
/* "We couldn't confirm. Checking…" after a delete without an answer: neutral, not an error (AUD-REL-1) */
.on-delbox .on-err.on-neutral{background:#efe9dc;border-color:#8a7a58;color:#3a3326}
.on-delbtns{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-1)}
.on-delbtns button{min-height:44px;padding:8px 16px;font-size:var(--fs-md);font-weight:700}
.on-delbtns .on-delgo{background:#8f2a1d;border-color:#6e1d13;color:#fff}
.on-delbtns .on-delgo:hover:not(:disabled){background:#a63322}
.on-delbtns .on-delgo:disabled{background:#c9a59d;border-color:#b0877e;color:#fff;cursor:not-allowed}
.on-delbtns button:disabled{cursor:not-allowed}
/* Cancel (and the dialog's ×) while a deletion runs: dimmed like the other disabled buttons */
.on-delbtns button:not(.on-delgo):disabled{opacity:.45}
.modal-box .close:disabled{opacity:.45;cursor:not-allowed}
.on-ok{padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);background:#24361fcc;border:1px solid #6f9a5a;color:#e2f3d6;font-size:var(--fs-md)}
/* M3 hub: profile + tabs (Friends, Requests, Invites, Results); landscape phones put the profile in a left column */
.on-hub{gap:var(--sp-3)}
.on-danger{margin-top:var(--sp-3)}
.on-me{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0}
.on-main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0}
.on-tabs{display:flex;gap:4px;border-bottom:1px solid #6d5a44;overflow-x:auto;scrollbar-width:none}
.screen .on-tab{flex:1 1 0;min-width:0;min-height:44px;padding:6px 8px;border:0;border-bottom:3px solid transparent;border-radius:var(--r-md) var(--r-md) 0 0;
 background:transparent;color:var(--ink2);font-weight:700;font-size:var(--fs-sm);white-space:nowrap}
.screen .on-tab.on{color:#f6e7c1;border-bottom-color:var(--gold);background:#2a221c}
.screen .on-tab small{color:var(--ink2);font-weight:400}
.on-badge{display:inline-block;min-width:18px;padding:0 5px;border-radius:9px;background:#b5523f;color:#fff;font-size:var(--fs-xs);line-height:18px;text-align:center}
.on-hubbody{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0}
.on-hubbody h3{margin:var(--sp-1) 0 0;font-size:var(--fs-sm);color:var(--gold);letter-spacing:.3px}
.on-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.on-row{display:flex;align-items:center;gap:var(--sp-2);padding:6px 0;border-bottom:1px solid #3d3229;min-width:0}
.on-row:last-child{border-bottom:0}
.on-rowmain{display:flex;align-items:center;gap:var(--sp-2);flex:1 1 auto;min-width:0;flex-wrap:wrap}
.screen button.on-rowmain{background:transparent;border:0;padding:4px 0;text-align:left;color:inherit;cursor:pointer;flex-wrap:nowrap}
.screen button.on-rowmain:hover:not(:disabled){background:transparent}
.screen button.on-rowmain:hover b{color:var(--gold)}
.on-rowtxt{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}
/* friend and deck names: whole words on at most 2 lines, then an ellipsis (the full name is in the title) */
.on-rowtxt b{color:var(--ink);white-space:normal;overflow-wrap:break-word;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.on-rowtxt small{color:var(--ink2);font-size:var(--fs-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.on-sub{flex:1 1 100%;color:var(--ink2);font-size:var(--fs-xs);padding-left:52px}
.on-rowbtns{display:flex;gap:6px;flex:none;align-items:center}
.screen .on-rowbtns button{min-height:44px;padding:6px 12px;font-size:var(--fs-sm);font-weight:700}
.on-crest-sm{flex:none;display:inline-flex}
.on-crest-sm .emb{width:34px;height:34px;font-size:var(--fs-md)}
/* friend-list crest is a nested span: 44px hit, 34px art */
.on-rowmain .on-crest-hit{width:44px;height:44px;min-width:44px;min-height:44px;align-items:center;justify-content:center}
.on-crest-hit{padding:0;border:0;background:transparent;cursor:pointer;border-radius:50%;line-height:0;display:inline-flex}
.screen button.on-crest-hit{min-height:0;min-width:0;padding:0;border:0;background:transparent}
.screen button.on-crest-hit:hover:not(:disabled){background:transparent;border-color:transparent}
.on-crest-hit img,.on-crest-sm img,.on-bigcrest img{border-radius:50%;display:block;object-fit:cover}
.on-crest-sm img{width:34px;height:34px}
.on-bigcrest img{width:64px;height:64px;box-shadow:0 0 18px #e1b86444}
.on-hub .on-bigcrest img{width:44px;height:44px}
.on-title{color:var(--gold);font-size:var(--fs-sm);margin:2px 0 0}
.on-badge-grid{max-height:220px;overflow:auto;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));grid-auto-rows:min-content;align-items:start;align-content:start;flex:none}
.on-badge-grid img{width:28px;height:28px;border-radius:50%;display:block;margin:0 auto 2px}
.on-badge-set .on-crest{height:auto;overflow:visible}
.on-badge-set .on-crest span{white-space:normal;line-height:1.15;overflow:visible;text-overflow:clip;flex:none}
.on-tag{font-size:var(--fs-xs);color:var(--ink2);padding:2px 8px;border:1px solid #6d5a44;border-radius:10px;white-space:nowrap}
.on-empty{color:var(--ink2);font-size:var(--fs-sm);padding:6px 0}
.on-found{padding:2px 8px;border:1px dashed #6d5a44;border-radius:var(--r-md)}
.on-addf{display:flex;gap:var(--sp-2)}
.screen form.on-addf input[type=text]{flex:1 1 auto;min-width:0;font-size:16px;min-height:44px;padding:8px 12px}
.screen form.on-addf input[type=text]:focus{outline:2px solid var(--gold);outline-offset:1px}
.screen .on-addf button{min-height:44px;padding:8px 16px;font-weight:700}
.on-banner{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;padding:6px 10px;border:1px solid var(--gold);border-radius:var(--r-md);background:#3a2c18;color:#f6e7c1;font-size:var(--fs-sm)}
.screen .on-banner button{margin-left:auto;min-height:44px;padding:4px 14px}
.on-note{font-size:var(--fs-sm)}
.on-blocked-list summary{cursor:pointer;color:var(--ink2);font-size:var(--fs-sm);padding:6px 0;min-height:32px}
.on-res{flex:none;min-width:64px;text-align:center;padding:3px 8px;border-radius:10px;font-weight:700;font-size:var(--fs-xs);border:1px solid}
.on-res-won{background:#24361f;border-color:#6f9a5a;color:#d7f0c6}.on-res-lost{background:#3d1d17;border-color:#b5523f;color:#ffd0c4}
.on-res-draw,.on-res-aborted{background:#2a221c;border-color:#6d5a44;color:var(--ink)}
.on-friend h3{margin:var(--sp-1) 0 0;font-size:var(--fs-md);color:var(--gold)}
/* deck picker (modal, light) */
.on-decks{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
.on-deck{display:flex;align-items:center;gap:8px;min-height:48px;padding:6px 10px;border:1px solid #b9ab95;border-radius:var(--r-md);background:#fffaf2;cursor:pointer;color:var(--text)}
.on-deck input{flex:none;width:20px;height:20px;margin:0;accent-color:#8a5d22}
.on-deck:has(input:checked){border-color:#8a5d22;box-shadow:0 0 0 2px #8a5d2255;background:#f6ead2}
.on-deck[data-off]{background:#e4ddd2;border-style:dashed;cursor:not-allowed;color:#5f554b}   /* P2: a saved deck that can't go online (the reason is under its name) */
.on-deckname{display:flex;flex-direction:column;min-width:0;flex:1}.on-deckoff{font-size:13px;line-height:1.25}   /* P2: a saved deck's name + reason */
#modal-body .on-deckbox h3{margin:8px 0 4px;font-size:var(--fs-md)}   /* P2: "Your saved decks" (not an .on-delnote: stays when an error shows) */
#modal-body .on-deckbox .on-delbtns{margin-bottom:env(safe-area-inset-bottom)}   /* P2: the longer list must not push Send / Cancel into the home-indicator band */
@media (max-height:500px) and (min-width:560px) and (orientation:landscape){   /* T58: an error in the deck picker (844x390): only the deck list scrolls, */
 #modal-body .on-deckbox.has-err{max-height:calc(100vh - 36px);max-height:calc(100dvh - 36px)}   /* so the error and Send / Cancel stay in view (= the .modal-box inner height) */
 #modal-body .on-deckbox.has-err > [role=radiogroup]{min-height:0;overflow-y:auto}
}
.on-deckembs{display:inline-flex;gap:2px;flex:none}
.on-deckembs .emb{width:24px;height:24px;font-size:var(--fs-sm)}
.on-deck b{min-width:0;white-space:normal;overflow-wrap:break-word;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.on-deckbox{max-width:none}
/* match ready */
.on-vs{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;font-size:var(--fs-lg)}
.on-vs-x{color:var(--gold);font-weight:700;padding:0 4px}
.on-matchid{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;font-size:var(--fs-sm)}
.on-matchid code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-xs);color:var(--ink);background:#2a221c;padding:4px 6px;border-radius:6px;word-break:break-all}
.screen .on-matchid button{min-height:44px;padding:4px 12px}
@media (max-width:420px){
 .on-decks{grid-template-columns:1fr}
 .on-hub .on-actions button{flex:1 1 auto}
 .screen .on-actions .on-del{flex:1 1 100%}
}
/* age gate + consent */
.on-age{max-width:620px}
.on-dob{display:grid;grid-template-columns:1.4fr .8fr 1fr;gap:var(--sp-2)}
.screen .on-field select{font-size:16px;min-height:44px;padding:6px 10px;width:100%}
.screen .on-field select:focus{outline:2px solid var(--gold);outline-offset:1px}
.on-check{display:flex;align-items:flex-start;gap:var(--sp-2);font-size:var(--fs-sm);line-height:var(--lh-snug);color:var(--ink);cursor:pointer}
.screen .on-check input{flex:none;width:22px;height:22px;margin:0;accent-color:#b8843a}
.on-check a{font-weight:700}
.on-blocked{max-width:620px}
@media (max-width:640px){
 .on-split,.on-prof-scroll{grid-template-columns:1fr}
}
/* phones held sideways (e.g. iPhone 14, 844x390): everything above the fold, inside the safe area, no tall gaps */
@media (max-height:500px) and (min-width:560px) and (orientation:landscape){
 /* .screen already insets every online page by the safe areas (the menu screens rule above), so no second inset here */
 .on-pg{max-width:none;padding:6px 12px 8px}
 .on-card{gap:var(--sp-2);padding:10px 14px}
 .on-card h2{font-size:var(--fs-lg)}
 .on-intro p{font-size:var(--fs-sm)}
 .on-split{gap:var(--sp-4)}
 .on-setup{gap:6px}
 .on-prof-scroll{gap:6px 16px}
 .on-col{gap:var(--sp-2)}
 /* Edit Profile on a sideways device (~844x390): the form body scrolls, Save stays on screen */
 .scr-online-edit,.scr-online-setup{overflow:hidden;display:flex;flex-direction:column;height:100%;height:100dvh}
 .scr-online-edit .on-pg,.scr-online-setup .on-pg{flex:1 1 auto;min-height:0;width:100%;height:auto;max-height:none;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box}
 .scr-online-edit .pg-head,.scr-online-setup .pg-head{flex:none;margin-bottom:4px;padding-bottom:4px}
 #on-prof{flex:1 1 auto;min-height:0;overflow:hidden;gap:6px}
 #on-prof .on-prof-scroll{flex:1 1 auto;min-height:0;overflow:auto;align-content:start}
 #on-prof .on-col{grid-column:1;grid-row:1 / span 2}
 #on-prof .on-crests:not(.on-badge-set){grid-column:2;grid-row:1}
 #on-prof .on-badge-set{grid-column:2;grid-row:2;min-height:0}
 #on-prof .on-foot{flex:none;position:sticky;bottom:0;z-index:1;padding-top:4px;background:#16120f}
 /* Edit Profile: .screen already insets the page by the safe areas, so no second inset here; no dark band behind Save */
 .scr-online-edit .on-pg{padding:6px 12px 8px}
 #on-prof .on-foot{background:none}
 #on-prof .on-badge-grid{max-height:88px;grid-template-columns:repeat(2,minmax(0,1fr))}
 /* Edit profile: the crest and badge tiles keep clear of the scroll bars (a reserved gutter where the bar takes space,
    padding where it floats over the content, e.g. iOS) */
 .scr-online-edit #on-prof .on-prof-scroll,.scr-online-edit #on-prof .on-badge-grid{scrollbar-gutter:stable;padding-right:10px}
 #on-prof .subtext{font-size:var(--fs-xs);line-height:1.2}
 #on-prof .on-crest{min-height:44px;padding:2px 2px}
 .screen .on-field input{min-height:40px;padding:6px 10px}
 .on-crest{min-height:50px;padding:4px 2px}
 .on-crest .emb{width:24px;height:24px;font-size:var(--fs-sm)}
 .screen .on-submit,.on-actions button,.on-foot button{min-height:44px;padding:6px 14px}
 .screen .on-google{min-height:40px}
 .screen .on-field select{min-height:40px}
 .on-age,.on-blocked{max-width:640px;margin:0 auto}
 .on-hub{display:grid;grid-template-columns:minmax(200px,250px) minmax(0,1fr);gap:var(--sp-4);align-items:start}
 .on-hub .on-me{gap:var(--sp-2)}
 .on-hub .on-who{gap:var(--sp-2);align-items:flex-start;flex-direction:column}
 .on-hub .on-bigcrest .emb{width:44px;height:44px;font-size:22px}
 .on-hub .on-actions{flex-direction:column;align-items:stretch}
 .screen .on-tab{min-height:44px;padding:4px 8px}   /* touch target: 44 px tall on phones too */
 .screen form.on-addf input[type=text],.screen .on-addf button{min-height:44px}
 .on-row{padding:4px 0}
 .on-decks{grid-template-columns:repeat(3,minmax(0,1fr))}
 .on-deck{min-height:44px}
 .on-deck b{white-space:normal;line-height:1.15}
}
/* Google Identity Services: Google's own button (an iframe, theme "outline" = the same white light-theme button as
   .on-google), the quiet fallback link under it, and the note shown when Google's script can't load */
.on-gbox{display:flex;flex-direction:column;align-items:flex-start;gap:var(--sp-1);min-width:0}
.on-gis{width:100%;max-width:400px;min-height:44px;color-scheme:light}
.on-gis[hidden],.screen .on-google[hidden]{display:none}
.on-gis.busy{opacity:.55;pointer-events:none}
.on-gnote{font-size:var(--fs-xs);color:var(--ink2);line-height:var(--lh-snug)}
.on-gnote[hidden],.on-alt[hidden]{display:none}
.on-alt{margin:0}
.screen .on-link{background:none;border:0;box-shadow:none;padding:6px 0;min-height:32px;color:var(--ink2);font-size:var(--fs-xs);
 text-decoration:underline;text-underline-offset:2px;cursor:pointer}
.screen .on-link:hover:not(:disabled),.screen .on-link:focus-visible{color:var(--gold)}
.screen .on-link:focus-visible{outline:2px solid var(--gold);outline-offset:2px;border-radius:2px}

/* ---- keyboard focus (audit AUD-A11Y-2 / AUD-A11Y-4): the cards, chips, drop targets and deck-builder cells made
   keyboard-reachable get a clear ring (inset on cards, so a row's overflow can't clip it); the modal box itself only
   takes focus as a fallback and draws no ring. */
.card[tabindex]:focus-visible,.db-cell[tabindex]:focus-visible{outline:3px solid #1f5f99;outline-offset:-3px}
.chip[tabindex]:focus-visible,.layer[tabindex]:focus-visible,div[data-act][tabindex]:focus-visible,[data-discard][tabindex]:focus-visible{outline:3px solid #1f5f99;outline-offset:1px}
.modal-box:focus,.modal-box:focus-visible{outline:none}

/* ui/framebust.js (audit AUD-SEC-4): inside a foreign frame, show nothing but the "open it on its own" notice */
html.mb-framed body>*:not(#mb-framed){display:none!important}
#mb-framed{padding:24px;color:#eadfca;background:#16120f;font-size:16px}
#mb-framed a{color:#f3c97a}

/* touch: 44px-tall hit areas for two small text controls whose look stays as is (AUD-A11Y-3): the Discard counter
   (it overlaps half of the info-only Deck row above it) and the hint's "Cancel" link */
@media (any-pointer:coarse){
 .st.click{position:relative}.st.click::after{content:"";position:absolute;left:0;right:0;top:-12px;bottom:-12px;z-index:1}
 #desel{position:relative}#desel::after{content:"";position:absolute;left:-3px;right:-3px;top:-7px;bottom:-7px}
}

/* text for screen readers only (the event log's live announcements, AUD-A11Y-6) */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* Storage-full warning (web/bridge.js, progression plan PR 5): the device ledger couldn't be saved to localStorage. */
#mb-storage-full{position:fixed;z-index:2000;left:calc(8px + var(--sal));right:calc(8px + var(--sar));bottom:calc(8px + var(--sab));
 max-width:560px;margin:0 auto;display:flex;gap:10px;align-items:center;background:#efe7da;color:#2a1f14;border:2px solid #b4442c;
 border-radius:12px;padding:8px 10px;box-shadow:0 6px 24px #0008;font-size:14px;line-height:1.35}
#mb-storage-full p{margin:0;flex:1}
#mb-storage-full .btn{min-width:64px;min-height:44px;flex:none}

/* the Challenges screen (progression plan PR 7; switch-on builds only) */
.ch-head{display:grid;grid-template-columns:auto 1fr auto;gap:8px 18px;align-items:center;margin-bottom:12px}
.ch-lv{display:flex;flex-direction:column}.ch-level{font-family:var(--font-display);font-size:var(--fs-xl);color:#f6e7c1}
.ch-title{font-size:var(--fs-md);color:var(--gold)}
.ch-xp small{display:block;font-size:var(--fs-md);color:var(--ink2);margin-top:3px}
.ch-bar{height:10px;border-radius:6px;background:#0e0b09b3;border:1px solid #6d5a44;overflow:hidden}.ch-bar i{display:block;height:100%;background:linear-gradient(90deg,#a8742f,#e1b864)}
.ch-count{text-align:right;font-size:var(--fs-md)}.ch-count b{font-size:var(--fs-xl);color:var(--gold)}.ch-count small{display:block;font-size:var(--fs-md);color:var(--ink2)}
.ch-titles{grid-column:1/-1;font-size:var(--fs-md)}.ch-titles summary{min-height:44px;display:flex;align-items:center;cursor:pointer;font-weight:700}
.ch-titles p{margin:2px 0 4px}.ch-titles small{font-size:var(--fs-md);color:var(--ink2)}
/* the group filter (one category at a time) and the challenge cards: name, description, tier targets, then one badge
   slot per tier right under them (earned: the art; not yet: an empty outline), progress and festival dates */
.ch-filter{display:flex;align-items:center;flex-wrap:wrap;gap:6px 12px;margin:0 0 6px;padding-bottom:10px;border-bottom:1px solid #6d5a44}
.ch-filter label{font-weight:700;font-size:var(--fs-md);color:var(--gold)}
/* 16px: iOS Safari zooms the page when a select under 16px gets focus. The arrow is the shared .touch-ui .screen select
   rule above (one arrow everywhere) */
.ch-filter select{min-height:44px;font-size:16px;padding:6px 10px;min-width:min(240px,100%);max-width:100%}
.ch-filter select:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.ch-row{display:flex;flex-direction:column;align-items:stretch;gap:4px;padding:10px 0;border-bottom:1px solid #6d5a4455;min-width:0}
.ch-row:last-child{border-bottom:0}
/* words never break in the middle (iPhone 14 portrait and landscape, desktop): wrap between words only */
.ch-name,.ch-req,.ch-tiers,.ch-t,.ch-meta{overflow-wrap:normal;word-break:normal;-webkit-hyphens:manual;hyphens:manual;min-width:0}
.ch-name{font-weight:700;font-size:var(--fs-lg);line-height:var(--lh-snug)}
.ch-tag{display:inline-block;white-space:nowrap;font-size:var(--fs-md);font-weight:700;color:#9fd0ff;border:1px solid #3d6f9a;border-radius:var(--r-md);padding:0 6px;vertical-align:1px}
.ch-req{font-size:var(--fs-md);color:var(--ink2);line-height:var(--lh-snug)}
.ch-tiers{display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;font-size:var(--fs-md);margin-top:2px}
.ch-tlbl{color:var(--ink2);margin-right:2px}
.ch-nw{white-space:nowrap}
.ch-t{white-space:nowrap;flex:none;padding:1px 8px;border:1px solid #6d5a44;border-radius:var(--r-md);color:var(--ink2)}
.ch-t b{color:var(--ink)}.ch-t.own{border-color:var(--gold);color:var(--gold)}.ch-t.own b{color:var(--gold)}
.ch-badges{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.ch-badge{position:relative;flex:none;padding:0!important;width:48px;height:48px;min-width:48px;min-height:48px;border-radius:50%!important;display:flex;align-items:center;justify-content:center;background:#0e0b09b3}
.ch-badge img{width:44px;height:44px;border-radius:50%}
.ch-slot{flex:none;box-sizing:border-box;width:48px;height:48px;border-radius:50%;border:2px solid #6d5a44;background:#0e0b0966}
.ch-meta{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:var(--fs-md)}
.ch-upd{color:#e1a35a}.ch-fest{color:var(--ink2)}
.ch-dots{position:absolute;bottom:-4px;left:0;right:0;text-align:center;font-style:normal;font-size:13px;letter-spacing:1px;color:var(--gold);line-height:1}
.ch-empty{font-size:var(--fs-md);margin:6px 0}
.ch-match{display:grid;grid-template-columns:64px 1fr auto auto;grid-template-areas:"res vs fac turns" "res date date date";gap:2px 12px;align-items:center;padding:8px 0;border-bottom:1px solid #6d5a4455;font-size:var(--fs-md)}
.ch-res{grid-area:res;font-weight:800;font-size:var(--fs-lg)}.ch-res.win{color:#8fd18b}.ch-res.loss{color:#e48b7a}
.ch-mvs{grid-area:vs;text-transform:capitalize}.ch-mfac{grid-area:fac;text-transform:capitalize}.ch-mturns{grid-area:turns}.ch-mdate{grid-area:date;color:var(--ink2)}
/* the badge screen (openBadge, in #modal): art centred, then badge name, tier, challenge and description. The art
   shrinks with the height so the text stays on screen at 390 px tall; the close button sits in the corner instead of
   floating (a float pushed the art off centre on the bottom sheet); a both-edges gutter keeps it centred if it scrolls */
.modal-box:has(.ch-bigwrap){scrollbar-gutter:stable both-edges}
.modal-box:has(.ch-bigwrap) .close{position:absolute;float:none;top:8px;right:8px;z-index:6;min-width:44px;min-height:44px}
/* device-sized layouts (the bottom sheet and the landscape modal): the × stays pinned while the sheet scrolls (a long
   description, bigger text). Sticky, not floated (a float would push the art off centre again), and a -44px bottom
   margin so it takes no height: the art starts at the top, centred, clear of the × in the corner */
@media (max-width:900px),(max-height:500px){
 .modal-box:has(.ch-bigwrap) .close{position:sticky;top:0;right:auto;float:none;display:block;width:44px;height:44px;margin:0 -4px -44px auto;z-index:6}
}
.ch-bigwrap{clear:both;display:flex;flex-direction:column;align-items:center;text-align:center;max-width:460px;margin:0 auto;padding:4px 0 2px}
.ch-bigwrap>*{max-width:100%;overflow-wrap:normal;word-break:normal;-webkit-hyphens:manual;hyphens:manual}
.ch-big{display:flex;justify-content:center;width:100%}
.ch-big img{display:block;width:min(384px,70vw,max(120px,calc(100vh - 230px)));width:min(384px,70vw,max(120px,calc(100dvh - 230px)));max-width:100%;height:auto;aspect-ratio:1;border-radius:50%}
#modal-body .ch-bigname{margin:10px 0 2px;line-height:var(--lh-snug)}
#modal-body .ch-bigtier{margin:0;font-weight:700;color:#7d5420;line-height:var(--lh-snug)}
#modal-body .ch-bigch{margin:8px 0 0;font-weight:700;line-height:var(--lh-snug)}
#modal-body .ch-bigdesc{margin:2px 0 0;color:var(--muted);line-height:var(--lh-snug)}
@media (min-width:901px) and (min-height:501px),(max-height:500px) and (min-width:560px) and (orientation:landscape){
 .modal-box:has(.ch-bigwrap){width:min(560px,calc(100vw - 24px))}
}
.scr-challenges .tabs button{font-size:var(--fs-md);min-height:44px}
/* the joined tab pair: starts inside the row (no -1px), the same radius as the other buttons, and the active tab's gold border on top of its neighbour's */
.scr-challenges .pg-head .tabs button:first-child{margin-left:0}
.scr-challenges .tabs button:first-child{border-radius:var(--r-md) 0 0 var(--r-md)}
.scr-challenges .tabs button:last-child{border-radius:0 var(--r-md) var(--r-md) 0}
.scr-challenges .tabs button.on{position:relative;z-index:1}
@media (max-width:900px),(max-height:500px){
 /* (no extra notch padding here: .screen already insets every screen by the safe areas, like Rules and Settings; S34-1) */
 .ch-head{grid-template-columns:auto 1fr;gap:4px 12px}.ch-count{grid-column:1/-1;text-align:left;display:flex;gap:8px;align-items:baseline}.ch-count small{display:inline}
 .ch-name{font-size:var(--fs-md)}
 .ch-match{grid-template-columns:52px 1fr auto;grid-template-areas:"res vs turns" "res fac date"}
}
/* progress sync (PR 13b): the Settings row (ui/online.js progSyncRow) and the Challenges header's account label */
.scr-settings .pg>.pg-card.st-psync{display:block;margin-top:14px}
.st-psync .st-row{border-bottom:0}
.st-psync .st-psync-msg,.st-psync .st-psync-out{margin:4px 0 0;font-size:var(--fs-md);color:var(--ink2);line-height:var(--lh-snug)}
.st-psync .st-psync-ctl{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}

/* ---- live online match (ui/liveplay.js, plan M5 #6/#8): clock pill, presence, waiting / end lines, dialogs ---- */
.lv-clock{display:inline-flex;align-items:center;gap:3px;padding:1px 8px;border-radius:999px;background:#3a2c18;color:#f6e7c1;
  font-size:13px;font-weight:700;line-height:1.5;white-space:nowrap;vertical-align:middle;font-variant-numeric:tabular-nums}
.lv-clock.low{background:#7d1f1a;color:#fff}
.lv-clock .sym{font-size:13px}
/* T60: the frozen clock ("Paused", no number) is wider than m:ss; the narrow phone rail drops the stopwatch icon so it fits */
#actdock.rail .lv-clock.paused{max-width:100%}
#actdock.rail .lv-clock.paused .sym{display:none}
.hint.lv-mine{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.lv-pres{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:4px 8px;border-radius:var(--r-md);
  background:#5a1f17;color:#ffe2d8;font-size:13px;line-height:1.3}
.lv-pres .num{font-weight:800;font-variant-numeric:tabular-nums;white-space:nowrap}
.hint.lv-wait,.hint.lv-end{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap;font-size:13.5px;padding:6px 8px}
#actdock.rail .hint.lv-wait,#actdock.rail .hint.lv-end,#actdock.rail .lv-pres,#actdock.rail .hint.lv-mine{font-size:13px}
.lv-end b{font-size:14px}
.actions button[data-live=exit]{min-height:44px;text-align:center}
.lv-dialog{max-width:440px}
.lv-dialog p{font-size:14px}
.lv-left{font-size:13.5px;margin:6px 0 0;overflow-wrap:break-word}
.lv-dialog .lv-btns{flex-wrap:wrap}
.lv-dialog .lv-btns button{min-height:44px;padding:6px 16px;font-size:14px}
.lv-dialog .lv-btns button.danger{background:#7d1f1a;color:#fff;border-color:#5a1410}
.lv-dialog .lv-btns button.danger:hover{background:#94261f}
/* online: no AI / seed / new game controls in the header (single-player keeps them) */
body.online-match #setup>label,body.online-match #newgame,body.online-match #morebtn,body.online-match #watchctl{display:none!important}
/* the disconnect rule before a match (waiting room, deck picker) */
.on-rule{font-size:13px;line-height:1.4;margin:8px 0 0;padding:6px 10px;border-left:3px solid var(--gold);background:rgba(58,44,24,.08);color:inherit}
.screen .on-room .on-rule{color:var(--ink2,#e9dcc4);background:rgba(246,231,193,.07)}
#modal-body .on-rule{color:#4d4339;background:#f1e6d1}
.lv-pres .lv-gone{font-weight:700}
#actdock.rail .lv-pres{flex-direction:column;align-items:flex-start;gap:1px;padding:3px 4px;min-width:0}
#actdock.rail .lv-pres .lv-who{display:flex;flex-direction:column;line-height:1.2;min-width:0;max-width:100%}
/* the rail is ~86 px inside: nothing in it may be wider than that with any font (CI's DejaVu Sans is wider than this box's
   Noto Sans or the iPhone's SF). A long name wraps at whole words on at most 2 lines, then an ellipsis (full name in the
   title; a word longer than the rail still breaks, as min-width:0 / max-width:100% cap it); "dis-connected" breaks at its
   soft hyphen only if it must; the waiting label is regular weight ("Resolving…" fits) (PR #45 review M1). */
#actdock.rail .lv-pres b{min-width:0;max-width:100%;white-space:normal;overflow-wrap:break-word;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
#actdock.rail .lv-pres .lv-gone{font-weight:600;hyphens:manual;overflow-wrap:break-word;min-width:0;max-width:100%}
#actdock.rail .hint.lv-wait{padding:3px 4px;min-width:0}
#actdock.rail .hint.lv-wait>b{font-weight:400;overflow-wrap:break-word;min-width:0;max-width:100%}
#actdock.rail .hint.lv-end>b{overflow-wrap:break-word;min-width:0;max-width:100%}
#actdock.rail .rail-main>*{min-width:0;max-width:100%}
#modal-body .on-deckbox .on-rule{margin:0;padding:4px 8px;line-height:1.3}
.on-banner.on-maint{font-size:13px}
/* the deck picker on a short screen (iPhone landscape): tighter, and with an error showing the "Premade decks" note
   gives its room to the error so Send invite / Cancel stay above the home indicator (PR #45 review M1) */
@media (max-height:500px){
 #modal-body .on-deckbox{gap:5px}
 #modal-body .on-deckbox.has-err .on-delnote{display:none}
 #modal-body .on-deckbox .on-err{margin:0;padding:4px 8px;line-height:1.3}
 #modal-body .on-deckbox .on-delbtns{margin-top:0}
}
/* desktop: whose move it is, the clock and the friend's presence in the header during a live match (ui/liveplay.js
   barHTML; the board's action panel can be below the fold at 1280x800). Phones show the same in the rail. */
.lv-bar{display:flex;align-items:center;gap:10px;margin:0 auto 0 12px;color:#f6e7c1;font-size:14px;min-width:0}
.lv-bar[hidden],.lv-bar:empty{display:none}
.lv-bar-state{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.lv-bar-pres{display:inline-flex;align-items:center;gap:5px;padding:2px 10px;border-radius:999px;background:#5a1f17;color:#ffe2d8;white-space:nowrap}
.lv-bar-pres .num{font-weight:800;font-variant-numeric:tabular-nums}
@media (max-width:900px),(max-height:500px){.lv-bar{display:none!important}}
/* the friend's grace countdown reads "12 s to return": it may wrap (whole words) in the narrow phone rail */
#actdock.rail .lv-pres .num{white-space:normal;overflow-wrap:break-word;min-width:0;max-width:100%}
/* desktop: the friend's banner sits below the header (app.js onlineBar sets --lvtop to the header's bottom), so it never
   covers the turn / clock line or the header buttons (PR #45 re-review C); same breakpoints as .lv-bar */
@media (min-width:901px) and (min-height:501px){body.online-match #oppbanner{top:var(--lvtop,58px)}}
/* "lost con-nection" in the ~86 px rail: regular weight, and it breaks only at its soft hyphen if it must */
#actdock.rail .lv-pres .lv-gone{font-weight:400;overflow-wrap:normal}

/* PR 13b: one-time Codex refreshed note after the 2.0 clear */
.mn-codex-note,.cx-note{margin:0 0 10px;padding:8px 12px;border-radius:var(--r-md);background:rgba(11,9,7,.88);color:#f6e7c1;border:1px solid #6d5a44;font-size:var(--fs-md);line-height:var(--lh-snug);text-shadow:0 1px 2px #000a}
.cx-note{margin:0 0 8px}
/* desktop/tablet with the one-time note: tighter gaps and centred above the absolute footer, so Exit never reaches
   the footer links; without the note the menu is unchanged (the phone layout has its own rules above) */
@media (min-width:481px) and (min-height:501px){
 .mn-wrap:has(> .mn-codex-note){gap:8px;padding-bottom:64px;box-sizing:border-box}
 .mn-wrap > .mn-codex-note{margin:0;padding:5px 10px;font-size:var(--fs-sm)}
 .mn-wrap:has(> .mn-codex-note) .mn-nav{gap:4px}
}
/* + Match logs (9 buttons with Challenges): on 768/720 px high screens the note's menu is a touch tighter still */
@media (min-width:481px) and (min-height:501px) and (max-height:820px){
 .mn-wrap:has(> .mn-codex-note) .mn-btn{padding:4px 16px!important}
}
@media (min-width:481px) and (min-height:501px) and (max-height:740px){
 .mn-wrap:has(> .mn-codex-note) .mn-btn{padding:3px 16px!important;gap:0}
}
/* + Story: ten buttons (with Challenges and Exit, or Resume Game) close up a step at each height, so the crest, the
   title, every button and the footer still fit; nine or fewer keep the spacing above */
@media (min-width:481px) and (min-height:501px){
 .mn-nav:has(> .mn-btn:nth-child(10)){gap:6px}
}
@media (min-width:481px) and (min-height:501px) and (max-height:820px){
 .mn-wrap:has(> .mn-nav > .mn-btn:nth-child(10)){gap:10px}
 .mn-nav:has(> .mn-btn:nth-child(10)){gap:4px}
 .mn-nav:has(> .mn-btn:nth-child(10)) > .mn-btn{padding:4px 16px!important}
}
@media (min-width:481px) and (min-height:501px) and (max-height:740px){
 .mn-wrap:has(> .mn-nav > .mn-btn:nth-child(10)){gap:8px}
 .mn-nav:has(> .mn-btn:nth-child(10)){gap:3px}
 .mn-nav:has(> .mn-btn:nth-child(10)) > .mn-btn{padding:3px 16px!important;gap:0}
 .mn-wrap:has(> .mn-codex-note):has(> .mn-nav > .mn-btn:nth-child(10)){gap:5px}
 .mn-wrap:has(> .mn-codex-note):has(> .mn-nav > .mn-btn:nth-child(10)) .mn-title h1{font-size:42px}
}
/* ten buttons with the one-time Codex note: a step tighter again at each height */
@media (min-width:481px) and (min-height:501px){
 .mn-wrap:has(> .mn-codex-note) .mn-nav:has(> .mn-btn:nth-child(10)){gap:3px}
 .mn-wrap:has(> .mn-codex-note) .mn-nav:has(> .mn-btn:nth-child(10)) > .mn-btn{padding:6px 16px!important}
}
@media (min-width:481px) and (min-height:501px) and (max-height:820px){
 .mn-wrap:has(> .mn-codex-note) .mn-nav:has(> .mn-btn:nth-child(10)) > .mn-btn{padding:3px 16px!important;gap:0}
}
@media (min-width:481px) and (min-height:501px) and (max-height:740px){
 .mn-wrap:has(> .mn-codex-note) .mn-nav:has(> .mn-btn:nth-child(10)){gap:2px}
}

/* ======================= Replay (T74 PR3, ui/replay.js): a saved match on the real board, read-only =======================
   The game header gives way to the replay's own top bar (back, Log, turn, move counter, a progress bar you can't drag);
   the controls sit in the bottom action bar (the phone's side rail when held sideways), like Watch mode. Taps of 44 px
   or more, inside the safe areas (the notch, the home indicator). */
body.replaying > header{display:none!important}
body.replaying #app{padding-top:calc(var(--rpbarh,52px) + 6px)!important;padding-bottom:calc(var(--dockh,0px) + 8px)}
body.replaying #oppbanner{top:calc(var(--rpbarh,52px) + 6px)}
body.replaying #logpanel{display:none!important}
#rpbar{position:fixed;z-index:58;top:0;left:0;right:0;display:flex;align-items:center;gap:6px 12px;flex-wrap:wrap;box-sizing:border-box;
 padding:calc(4px + env(safe-area-inset-top)) calc(10px + env(safe-area-inset-right)) 4px calc(10px + env(safe-area-inset-left));
 background:linear-gradient(180deg,#2e2620f5,#3a2c1ff0);color:#f6e7c1;border-bottom:2px solid var(--bronze);box-shadow:0 4px 14px #0005;
 touch-action:manipulation;-webkit-user-select:none;user-select:none}
#rpbar button{min-height:44px;min-width:44px;padding:0 12px;font-size:var(--fs-md)}
#rpbar .rp-title{font-size:var(--fs-lg);color:#f6e7c1}
#rpbar .rp-turn,#rpbar .rp-move{font-size:var(--fs-md);white-space:nowrap;font-variant-numeric:tabular-nums}
#rpbar .rp-move{font-weight:700}
#rpbar .rp-prog{flex:1 1 120px;min-width:80px;height:8px;border-radius:4px;background:#5a4a38;overflow:hidden;pointer-events:none}
#rpbar .rp-prog i{display:block;height:100%;background:linear-gradient(90deg,#c79a4a,#f3dfa8);transition:width .2s linear}
#rpbar .rp-log{margin-left:auto}
#rp-note{position:fixed;z-index:58;left:50%;transform:translateX(-50%);top:calc(var(--rpbarh,52px) + 8px);max-width:calc(100vw - 40px - var(--railw,0px));
 padding:6px 12px;border:1px dashed var(--bronze);border-radius:var(--r-md);background:#efe7da;color:#4a3b2c;font-style:italic;box-shadow:0 4px 12px #0004}
#rp-note.hidden{display:none}
/* the bar: fixed along the bottom on every layout but the sideways phone (there: the rail) */
body.replaying #actdock:not(.rail){position:fixed;left:0;right:0;bottom:0;z-index:55;max-height:none;box-sizing:border-box;
 padding:6px calc(10px + env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) calc(10px + env(safe-area-inset-left));
 background:#e9dfcffa;border-top:2px solid var(--bronze);box-shadow:0 -4px 14px #0004}
.rp-dock{display:flex;align-items:center;justify-content:center;gap:8px 16px;flex-wrap:wrap;touch-action:manipulation}
.rp-dock button{min-height:44px;min-width:44px;font-size:var(--fs-md);padding:0 14px;touch-action:manipulation}
.rp-ctl{display:flex;gap:8px}
.rp-ctl .rp-play{min-width:110px;font-weight:800}
.rp-speeds{display:flex;gap:4px}
.rp-speeds button{min-width:56px}
.rp-speeds button[aria-pressed=true]{background:#6d4c1f;color:#fff3d6;border-color:#e1b864;font-weight:800}
#actdock.rail .rp-dock{flex-direction:column;align-items:stretch;justify-content:flex-start;gap:4px;flex:1;min-height:0;flex-wrap:nowrap}
#actdock.rail .rp-ctl{flex-direction:column;gap:4px}
#actdock.rail .rp-ctl .rp-play{min-width:0}
#actdock.rail .rp-speeds{flex-direction:column;gap:3px;margin-top:auto}
#actdock.rail .rp-dock button{width:100%;min-width:0;padding:0 4px;font-size:var(--fs-md)}
@media (max-height:500px) and (min-width:560px) and (orientation:landscape){
 #rpbar{right:var(--railw);padding:calc(2px + env(safe-area-inset-top)) 8px 2px calc(8px + env(safe-area-inset-left));gap:4px 10px;flex-wrap:nowrap}
 #rpbar .rp-title{display:none}
 #rpbar button{padding:0 10px}
}
/* the calm states (loading, not available): a plain screen with a way back */
.rp-calm{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;box-sizing:border-box;
 padding:calc(16px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left))}
.rp-calm-box{max-width:420px;text-align:center;background:#2e2620e6;border:1px solid var(--bronze);border-radius:var(--r-lg);padding:18px 22px;color:#f6e7c1}
.rp-calm-box h1{margin:0 0 8px;font-size:var(--fs-xl)}
.rp-calm-box p{margin:0 0 14px;font-size:var(--fs-md);color:#e8d9b8}
.rp-calm-box button{min-height:44px;min-width:44px;padding:0 16px;font-size:var(--fs-md)}
/* the costs of the turn's moves aren't in a stored frame: not shown in a replay */
body.replaying .hs-atk,body.replaying .hs-claim{display:none}
/* Hunger beside the Main: ten stacked segments. 1-3 deep mustard, 4-7 burnt orange, 8-10 oxblood.
   Darker and browner than ATK red (#9e2b25). Empty segments stay dim. */
.hunger-bar{flex:none;align-self:center;width:16px;height:var(--ch);display:flex;flex-direction:column;align-items:center;background:transparent;border:0;box-shadow:none}
.hunger-bar .hb-segs{flex:1 1 auto;width:11px;min-height:0;display:flex;flex-direction:column;gap:1px;background:transparent}
.hunger-bar .seg-slot{flex:1 1 0;min-height:2px;display:flex}
.hunger-bar .seg-quiver{display:flex;width:100%;height:100%}
.hunger-bar .seg{width:100%;height:100%;border-radius:2px;background:transparent;box-shadow:inset 0 0 0 1px rgba(74,56,20,.5)}
/* Full Hunger: each filled segment breathes, jitters 1px, and carries its own faint black glow. The track stays transparent. */
.hunger-bar.max .seg.on{transform-origin:center center;animation:hb-pulse 2.6s ease-in-out infinite;animation-delay:var(--hb,0s);box-shadow:0 0 4px 1px rgba(0,0,0,.6)}
.hunger-bar.max .seg-quiver{animation:hb-quiver .28s linear infinite;animation-delay:var(--hb,0s)}
@keyframes hb-pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.18);opacity:.62}}
@keyframes hb-quiver{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(1px,-1px,0)}}
@media (prefers-reduced-motion:reduce){
 .hunger-bar.max .seg.on,.hunger-bar.max .seg-quiver{animation:none}
}
.hunger-bar .seg.on.s1{background:#79621a}
.hunger-bar .seg.on.s2{background:#856a1c}
.hunger-bar .seg.on.s3{background:#91771e}
.hunger-bar .seg.on.s4{background:#965b19}
.hunger-bar .seg.on.s5{background:#8a4e17}
.hunger-bar .seg.on.s6{background:#804517}
.hunger-bar .seg.on.s7{background:#773e1a}
.hunger-bar .seg.on.s8{background:#66301d}
.hunger-bar .seg.on.s9{background:#59271c}
.hunger-bar .seg.on.s10{background:#4d201b}
.hunger-bar .hb-num{flex:none;font-size:10px;line-height:1;font-weight:800;color:#4a3814}
/* Shade elemental frame. Art is not restyled. ATK stays red and DEF stays blue. */
.card.el-shade{border-width:3px;padding:0 2px 2px;border-style:solid;border-color:var(--el-edge);
 background:var(--el-scrim),var(--el-tex) center/180px auto;
 box-shadow:0 0 0 1px #000a,0 0 10px 2px var(--el-glow),inset 0 0 0 1px var(--el-keyline);
 --el-tex:url("cosmetics/shade/tex_shade.jpg");
 --el-scrim:linear-gradient(#0a0908bb,#141210cc);
 --el-edge:#B89B4C;--el-keyline:#E8E4D9aa;--el-glow:#B89B4C77;
 --el-hdtx:#E8E4D9;--el-tshadow:0 1px 2px #000;
 --el-banner:linear-gradient(90deg,#1a1816,#2B2B2B 35%,#3a3428 50%,#2B2B2B 65%,#1a1816);--el-bantx:#E8E4D9;
 --el-tb:linear-gradient(#E8E4D9e6,#d4cfc2f0),url("cosmetics/shade/tex_shade.jpg") center/160px auto;
 --el-tbsolid:#E8E4D9;--el-tbshade:#2B2B2B44;--el-cost:#B89B4C;--el-costtx:#1d1814;--el-orn:52px;
 --el-tl:url("cosmetics/shade/corner_shade_tl.png");--el-tr:url("cosmetics/shade/corner_shade_tr.png");
 --el-bl:url("cosmetics/shade/corner_shade_bl.png");--el-br:url("cosmetics/shade/corner_shade_br.png")}
.card.el-shade .hd{position:relative;background:var(--el-scrim),var(--el-tex) top left/180px auto;color:var(--el-hdtx);
 border-bottom:1px solid var(--el-keyline);text-shadow:var(--el-tshadow);margin:0 -2px}
.card.el-shade .ft{position:relative;background:var(--el-scrim),var(--el-tex) bottom left/180px auto;border-top:1px solid var(--el-keyline);margin:0 -2px -2px}
.card.el-shade .hd::after,.card.el-shade .ft::after{content:"";position:absolute;pointer-events:none;z-index:1;left:-6px;right:-6px;height:var(--el-orn)}
.card.el-shade .hd::after{top:-2px;background:var(--el-tl) top left/var(--el-orn) no-repeat,var(--el-tr) top right/var(--el-orn) no-repeat}
.card.el-shade .ft::after{bottom:-2px;background:var(--el-bl) bottom left/var(--el-orn) no-repeat,var(--el-br) bottom right/var(--el-orn) no-repeat}
.card.el-shade .hd>*,.card.el-shade .ft>*{position:relative;z-index:2}
.card.el-shade .art{position:relative;z-index:3;border-color:var(--el-edge);margin-left:0;margin-right:0}
.card.el-shade .banner{margin:0 -2px;background:var(--el-banner);color:var(--el-bantx);border-top:1px solid var(--el-keyline);border-bottom:1px solid var(--el-keyline)}
.card.el-shade .tb{background:var(--el-tb);color:#1d1814;box-shadow:inset 0 0 0 1px var(--el-keyline);margin:0 1px 4px;border-radius:3px}
.card.el-shade .cost{background:var(--el-cost);color:var(--el-costtx);border-color:var(--el-edge)}
.card.el-shade .badge{background:var(--el-tbsolid)}
.card.el-shade .badge.a{color:var(--red)}
.card.el-shade .badge.d{color:var(--blue)}
.card.el-shade.lg{--el-orn:72px;border-width:4px;padding:0 4px 4px}
.card.el-shade.lg .hd{margin:0 -4px}
.card.el-shade.lg .ft{margin:0 -4px -4px}

/* Collectibles hub. The menu button keeps #mn-codex so the Challenges chip still anchors after it.
   The label is longer than "Codex", so the count chip keeps its own padding and does not cover the word. */
#mn-codex{padding-right:86px!important}
#mn-codex b{letter-spacing:0}
@media (max-height:500px) and (min-width:560px) and (orientation:landscape){
 #mn-codex{padding-right:58px!important}
 #mn-codex b{font-size:13px;letter-spacing:0}
}
.cl-pg{max-width:980px}
/* The Shinies title row is already one 44px line, so one later control fits on the right and the list stays put at 844x390. */
.scr-cl-shinies .cl-shiny-head{flex-wrap:nowrap;align-items:center;box-sizing:border-box;height:44px;min-height:44px;margin-bottom:6px;padding-bottom:0;gap:8px}
.scr-cl-shinies .cl-shiny-head .pg-back{flex:none;box-sizing:border-box;height:44px;min-height:44px}
.scr-cl-shinies .cl-shiny-head h1{flex:1 1 auto;min-width:0;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:44px}
.cl-lead,.cl-note{margin:0 0 12px;font-size:var(--fs-md);line-height:var(--lh-body);color:#d8cab0}
.cl-note{margin-top:0;font-size:var(--fs-sm)}
.cl-nav{display:grid;grid-template-columns:1fr;gap:8px}
.cl-item{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;min-height:44px;padding:8px 12px;text-align:left;
 background:#1b1612;color:#eadfca;border:1px solid #6d5a44;border-left:4px solid var(--gold);border-radius:var(--r-md)}
.cl-item:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.cl-copy{display:flex;flex-direction:column;gap:2px;min-width:0}
.cl-copy b{font-family:var(--font-display);font-size:var(--fs-lg);color:#f6e7c1;letter-spacing:0}
.cl-copy small{font-size:var(--fs-sm);color:var(--ink2);line-height:var(--lh-snug)}
.cl-lock,.cl-count,.cl-ok{flex:none;font-size:var(--fs-sm);font-weight:800;letter-spacing:.02em;color:#f6e7c1;border:1px solid #6d5a44;border-radius:var(--r-lg);padding:2px 8px;background:#0e0b09}
.cl-ok{color:#c9f2d1;border-color:#6fbf80}
.cl-sec{margin:14px 0 6px;font-size:var(--fs-md);color:var(--gold);font-weight:700}
.cl-frames,.cl-backs{display:flex;flex-wrap:wrap;gap:8px}
.cl-frame{min-height:44px}
.cl-pg .st-row > div:first-child{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-width:0}
.cl-back{flex:1 1 150px;width:auto;max-width:190px;min-height:44px;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px;overflow:visible;background:#241c16;color:#eadfca;border:1px solid #6d5a44;border-radius:8px}
.cl-back .cos-lab,.cl-back .cos-tier,.cl-back .cos-lock,.cl-back .cos-hint{display:block;text-align:center;line-height:1.25}
.cl-back .mb-back,.cl-back img{width:72px;height:64px;object-fit:cover;border-radius:4px}
.cl-back.is-locked{opacity:.72}
.cl-packs{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.cl-pack{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:8px;align-items:center;min-height:44px;padding:4px 8px;border:1px solid #4d4033;border-radius:var(--r-md);background:#241c16}
.cl-pack-flag{display:flex;align-items:center;gap:6px;font-size:13.5px;font-weight:700;color:#f6e7c1;min-height:44px}
.cl-pack .btn{min-height:44px;font-size:13.5px}
.cl-pg button,.cl-pg select{font-size:13.5px}
.cl-status,.cos-hint,.cl-pg figcaption,.cl-name{font-size:13.5px;color:#f6e7c1}
.cl-name{background:none;border:0;color:#f6e7c1;font-family:var(--font-ui);font-weight:700;min-height:44px;text-align:left;padding:0}
.cl-ba{display:flex;gap:12px;align-items:flex-start;margin:0 0 10px}
.cl-shot{margin:0;display:flex;flex-direction:column;gap:4px;align-items:center}
.card.cl-face{width:132px;height:148px;--cw:132px;--ch:148px;pointer-events:none}
.card.cl-face .hd{display:none}
.card.cl-face .art{height:148px}
.cl-ba .mb-back{width:96px;height:120px;display:block}
.cl-shiny-all,.cl-spirits{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.cl-shiny-all li,.cl-spirit{min-height:44px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cl-spirit{align-items:flex-start}
.cl-spirit img{width:auto;height:auto;max-width:160px;max-height:min(220px,calc(100dvh - 168px));object-fit:contain;object-position:center;border-radius:6px;flex:none;background:#120e0b}
.cl-mystery{width:108px;aspect-ratio:286/581;height:auto;max-height:min(220px,calc(100dvh - 168px));border-radius:6px;background:#120e0b;border:1px solid #6d5a44;position:relative;flex:none}
.cl-mystery::before{content:"";position:absolute;left:50%;top:28%;width:36px;height:36px;margin-left:-18px;border-radius:50%;background:#3a3028}
.cl-mystery::after{content:"";position:absolute;left:50%;top:46%;width:64px;height:52px;margin-left:-32px;border-radius:32px 32px 12px 12px;background:#3a3028}
.cl-pg select{min-height:44px;font-family:var(--font-ui);background:#241c16;color:#f6e7c1;border:1px solid #6d5a44;border-radius:8px}
.cl-pack-name{min-width:0;font-weight:700;color:#f6e7c1}
.cl-tier,.cl-size,.cos-lab,.cos-tier,.cos-lock,.cos-hint,.cl-lock,.cl-count{color:#d8cab0;font-weight:400;font-size:13.5px}
.cl-size{white-space:nowrap}
@media (min-width:700px){
 .cl-nav{grid-template-columns:1fr 1fr}
}
@media (max-height:500px){
 .cl-pg{padding-bottom:8px}
 .cl-lead{margin-bottom:8px}
 .cl-item{padding:6px 10px}
 .cl-copy small{font-size:13.5px}
 .cl-sec{margin:8px 0 4px}
}
.cl-draft{flex:none;font-size:var(--fs-sm);font-weight:800;letter-spacing:.02em;color:#f6e7c1;border:1px solid #6d5a44;border-radius:var(--r-lg);padding:2px 8px;background:#0e0b09}
.lore-banner,.lore-note{margin:0 0 10px;font-size:var(--fs-md);line-height:1.45;color:#d8cab0}
.lore-jumps{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.lore-jump{min-height:44px;min-width:44px;padding:6px 12px}
.lore-jump:focus-visible,.lore-src:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.lore-fac{margin:0 0 16px}
.lore-fac h2,.lore-legend h3,.lore-sources h2{margin:0 0 6px;color:#f6e7c1;scroll-margin-top:8px}
.lore-legend{margin:12px 0 0}
.lore-legend h3{font-size:var(--fs-lg)}
.lore-status{margin:0 0 6px;font-size:var(--fs-sm);font-weight:700;color:var(--gold)}
.lore-prose{margin:0 0 8px;font-size:15px;line-height:1.45}
.lore-row{display:grid;grid-template-columns:minmax(0,1fr);gap:8px;align-items:start}
.lore-art{display:block;width:100%;max-width:100%;height:auto;max-height:70vh;object-fit:contain;object-position:left center;border:0;border-radius:0;box-shadow:none;background:transparent}
.lore-refs{margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px}
.lore-refs-lab{font-size:13.5px;font-weight:700;color:#d8cab0}
.lore-src{display:inline-flex;align-items:center;min-height:44px;padding:0 8px}
.lore-original{font-size:13.5px;line-height:1.4}
.lore-source,.lore-claim{margin:0 0 12px;padding-top:4px;scroll-margin-top:8px}
.lore-source h3,.lore-claim h3{margin:0 0 4px;font-size:var(--fs-md);color:#f6e7c1}
.lore-source p,.lore-claim li{margin:0 0 4px;font-size:13.5px;line-height:1.4}
.lore-loc{color:#d8cab0}
.lore-claim ul{margin:0;padding-left:1.1em}
@media (min-width:700px){
 .lore-row{grid-template-columns:minmax(140px,240px) minmax(0,1fr)}
 .lore-art{max-height:min(46vh,320px)}
}
@media (max-height:500px) and (min-width:700px){
 .lore-row{grid-template-columns:minmax(120px,34vw) minmax(0,1fr);align-items:start}
 .lore-prose{font-size:15px;line-height:1.4}
 .lore-art{max-height:calc(100dvh - 108px)}
 .lore-banner{margin-bottom:6px}
}
@media (prefers-reduced-motion:reduce){
 .lore-art,.lore-jump{animation:none;transition:none}
}

/* Save file card (ui/savefile.js): Export / Save as new file / Load wrap at 844x390 */
.st-savefile{margin-top:14px}
.st-savefile .st-sfbtns { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }
.st-savefile .st-sfbtns button { font-size: var(--fs-md); }   /* body size: new controls clear the 13px small-text check (tools/ui_screens.py) */
.st-savefile #sf-msg { margin: 6px 0 0; min-height: 1em; }
.sf-files-note { font-weight: 600; }
/* export suggestion (ui/savefile.js): a dismissible bar, never over a live match */
.sf-suggest{position:fixed;left:50%;bottom:max(10px,env(safe-area-inset-bottom));transform:translateX(-50%);z-index:60;width:min(640px,calc(100vw - 20px));display:flex;gap:10px 14px;align-items:center;flex-wrap:wrap;padding:10px 14px;border-radius:10px;background:var(--panel,#241c16);border:1px solid #6a5434;box-shadow:0 6px 24px #0008}
.sf-suggest p{margin:0;flex:1 1 300px;font-size:var(--fs-sm)}
.sf-suggest .sf-sug-btns{display:flex;gap:8px}
/* Settings analytics opt-out: label and description stay at least 13px (the shared .st-row small size is smaller). */
.scr-settings .st-analytics b{font-size:16px}
.scr-settings .st-analytics small{font-size:13px}
/* Short screens: a quest reward (a Spirit portrait plus two other grants, and Continue) has to stay
   inside 844x390. The portrait keeps its real shape, only shorter, so the labels and Continue are on screen. */
@media (max-height:500px){
 #modal .story-rewards,#modal-body .story-rewards{gap:4px}
 #modal .story-rewards .am-badge,#modal-body .story-rewards .am-badge{min-height:0;gap:2px 8px}
 #modal .story-rewards .am-badge:has(.sr-spirit),#modal-body .story-rewards .am-badge:has(.sr-spirit){grid-template-columns:72px minmax(0,1fr)}
 #modal .story-rewards .sr-art:has(.sr-spirit),#modal-body .story-rewards .sr-art:has(.sr-spirit){width:72px;max-width:72px}
 #modal .story-rewards .sr-spirit,#modal-body .story-rewards .sr-spirit{max-width:72px;max-height:120px}
 #modal-body:has(.story-rewards) h2,#modal:has(.story-rewards) h2{margin:0 0 4px;font-size:16px}
 #modal-body:has(.story-rewards) .welcome,#modal:has(.story-rewards) .welcome{margin-top:4px}
}
