:root {
    --card-width: 750px;
    --card-height: 1050px;
    --font-scale: 1.3;               /* global scale multiplier */
    --title-text-max-font-size: calc(2.5rem * var(--font-scale));
    --rules-text-max-font-size: calc(3.22rem * var(--font-scale));
    --bible-verse-font-max-font-size: calc(1.85rem * var(--font-scale));
    --fun-text-max-font-size: calc(1.95rem * var(--font-scale));
    --cost-text-max-font-size: calc(7rem * var(--font-scale));
    --copyright-text-max-font-size: calc(1.1rem * var(--font-scale));
    --weblink-text-max-font-size: calc(1.35rem * var(--font-scale));
    --cardnuminfo-text-max-font-size: calc(0.95rem * var(--font-scale));
    --rules-text-font-family: Tahoma;
    --rules-text-min-font-size: calc(0.8rem * var(--font-scale));
    --rules-text-icon-min-font-size: calc(2rem * var(--font-scale)); /*was 2.2rem 37.96px*/
    --costbox-inline-max-font-size: calc(0.9rem * var(--font-scale));
    --humility-text-max-font-size: calc(2.2rem * var(--font-scale));
    --humility-text-small-icon-font-size: calc(1.7rem * var(--font-scale));
    --art-y: 0;

    --text-shadow-outline-value:
            -1px -1px 0 #d6d6d6,
            1px -1px 0 #000,
            -1px  1px 0 #7e7e7e,
            1px  1px 0 #000;

    --text-shadow-outline-on-raw-border-value:
            -1px -1px 0 #202020,
            2px -2px 0 #000,
            -2px  2px 0 #7e7e7e,
            1px  1px 0 #000;

    --bg-Unction: #ffda67;
    --bg-Instant: var(--bg-Unction);
    --bg-Maturity: #c8f4b0;
    --bg-Resistance: #cacaca;
    /*--bg-Habitual_Good: rgb(223, 182, 122);*/
    --bg-Habitual_Good: rgb(175, 136, 79);
    --bg-Habitual_Evil: #fabc96;
    --bg-Temptation: #ffb2b2;

    --bible-verse-font-family: var(--fun-font-family);
    --art-background-color: rgba(255, 255, 255, 0.75);
    --rules-background: linear-gradient(180deg, rgba(255,255,255,0.4), rgba(255,255,255,0.6));
    --title-background: linear-gradient(180deg, rgba(255,255,255,0.9), rgba(255,255,255,0.8));
    /*rgba(255, 255, 255, 0.75); */
    --cost-wrap-top: 5px;     /* how far down the wrap “starts” */

    --cost-badge-size: 140px;         /* match .cost-badge width/height */
    --cost-badge-offset-x: 10px;      /* same as .cost-badge left */
    --cost-badge-offset-y: 10px;      /* same as .cost-badge bottom */


        /* ============================
           SERIF FONTS
        ============================ */
        --font-serif-1: "Cinzel", serif;
        --font-serif-2: "Merriweather", serif;
        --font-serif-3: "Playfair Display", serif;
        --font-serif-4: "Cormorant Garamond", serif;
        --font-serif-5: "Old Standard TT", serif;
        --font-serif-6: "Libre Baskerville", serif;
        --font-serif-7: "Lora", serif;
        --font-serif-8: "PT Serif", serif;
        --font-serif-9: "Crimson Pro", serif;
        --font-serif-10: "Garamond", serif;

        /* ============================
           SANS-SERIF FONTS
        ============================ */
        --font-sans-1: "Nunito Sans", sans-serif;
        --font-sans-2: "Montserrat", sans-serif;
        --font-sans-3: "Lato", sans-serif;
        --font-sans-4: "Roboto", sans-serif;
        --font-sans-5: "Open Sans", sans-serif;
        --font-sans-6: "Poppins", sans-serif;
        --font-sans-7: "Ubuntu", sans-serif;
        --font-sans-8: "Josefin Sans", sans-serif;
        --font-sans-9: "Oswald", sans-serif;
        --font-sans-10: "Raleway", sans-serif;

        /* ============================
           DISPLAY / TITLE FONTS
        ============================ */
        --font-display-1: "Bebas Neue", sans-serif;
        --font-display-2: "Anton", sans-serif;
        --font-display-3: "Cinzel Decorative", serif;
        --font-display-4: "Uncial Antiqua", serif;
        --font-display-5: "Staatliches", sans-serif;
        --font-display-6: "IM Fell English SC", serif;
        --font-display-7: "MedievalSharp", cursive;
        --font-display-8: "Black Ops One", sans-serif;
        --font-display-9: "Squada One", sans-serif;
        --font-display-10: "Fjalla One", sans-serif;

        /* ============================
           CONDENSED FONTS
        ============================ */
        --font-condensed-1: "Oswald", sans-serif;
        --font-condensed-2: "Bebas Neue", sans-serif;
        --font-condensed-3: "Roboto Condensed", sans-serif;
        --font-condensed-4: "Anton", sans-serif;
        --font-condensed-5: "PT Sans Narrow", sans-serif;

        /* ============================
           SCRIPT / CALLIGRAPHY
        ============================ */
        --font-script-1: "Dancing Script", cursive;
        --font-script-2: "Great Vibes", cursive;
        --font-script-3: "Allura", cursive;
        --font-script-4: "Satisfy", cursive;
        --font-script-5: "Parisienne", cursive;

        /* ============================
           HANDWRITTEN
        ============================ */
        --font-hand-1: "Shadows Into Light", cursive;
        --font-hand-2: "Indie Flower", cursive;
        --font-hand-3: "Patrick Hand", cursive;
        --font-hand-4: "Caveat", cursive;
        --font-hand-5: "Architects Daughter", cursive;

        /* ============================
           FANTASY / THEMATIC
        ============================ */
        --font-fantasy-1: "MedievalSharp", cursive;
        --font-fantasy-2: "Uncial Antiqua", serif;
        --font-fantasy-3: "Cinzel Decorative", serif;
        --font-fantasy-4: "Trade Winds", cursive;
        --font-fantasy-5: "Rye", cursive;

        /* ============================
           MONOSPACE (just in case)
        ============================ */
        --font-mono-1: "Source Code Pro", monospace;
        --font-mono-2: "Roboto Mono", monospace;
        --font-mono-3: "Fira Code", monospace;
        --font-mono-4: "Courier Prime", monospace;
        --font-mono-5: "JetBrains Mono", monospace;


    --font-perfect: "BEAGLB", serif;
    --primary-card-font-family: var(--font-perfect);
    --secondary-card-font-family: "Bebas Neue", serif;
    --fun-font-family: var(--font-perfect);
}

body {
    margin: 0;
    padding: 16px;
    font-family: "Nunito Sans", system-ui, -apple-system, sans-serif;
    background: #222;
    color: #eee;
    display: flex;
    gap: 16px;
    box-sizing: border-box;
}

h1 {
    margin-top: 0;
    font-family: var(--primary-card-font-family);
}

.layout {
    display: flex;
    gap: 24px;
    width: 100%;
}

.design button {
    font-size: smaller;
    max-width: 50px;
}


.field {
    margin-bottom: 10px;
}

.field label {
    display: block;
    font-size: 0.86rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 3px;
    color: #ccc;
}

.field input[type="text"],
.field input[type="number"],
.field textarea,
.field select {
    width: 100%;
    box-sizing: border-box;
    border-radius: 4px;
    border: 1px solid #555;
    padding: 6px 8px;
    font-size: 0.9rem;
    background: #222;
    color: #f5f5f5;
}

.field textarea {
    resize: vertical;
    min-height: 60px;
}

.field-hflex {
    display: flex;
    gap: 8px;
}

button {
    padding: 8px 14px;
    border-radius: 4px;
    border: none;
    background: #3ba96c;
    color: white;
    font-weight: 600;
    cursor: pointer;
    margin-top: 6px;
}

button:hover {
    background: #2f8855;
}

/* Right: card preview */
.preview-wrapper {
    flex: 1;
    display: flex;
    /*justify-content: center;*/
    align-items: flex-start;
    overflow: auto;
}
.preview-wrapper {
    justify-content: flex-start !important;
}

#card-preview {
    position: relative;
    width: var(--card-width);
    height: calc(var(--card-height) + 50px);
    box-sizing: border-box;
    background-size: cover;
    background-position: center;
    border-radius: 40px;
    box-shadow: 0 0 25px rgba(0,0,0,0.8);
    color: #000;
    font-family: "Nunito Sans", system-ui, -apple-system, sans-serif;
}


#card-preview-alt {
    position: relative;
    width: var(--card-width);
    height: calc(var(--card-height) + 50px);
    box-sizing: border-box;
    background-size: cover;
    background-position: center;
    border-radius: 40px;
    box-shadow: 0 0 25px rgba(0,0,0,0.8);
    color: #000;
    font-family: "Nunito Sans", system-ui, -apple-system, sans-serif;
}


/* Inner frame */
.card-inner {
    position: absolute;
    inset: 24px;
    border-radius: 28px;
    box-sizing: border-box;
    padding: 18px 22px 22px 22px;
}

/* Title bar */
.card-title-bar {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 10px;
    margin-top: -15px;
}

.card-title-pill {
    background: var(--title-background);
    border-radius: 16px;
    padding: 6px 18px;
    font-family: var(--primary-card-font-family);
    font-size: var(--title-text-max-font-size);
    font-weight: 600;
    box-shadow: 0 2px 0 rgba(0,0,0,0.25);
    max-width: 82%;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.long-title-gt50 {
    font-size: 1.4em;
}
.long-title-gt30 {
    font-size: 1.7em;
}
.long-title-gt20 {
    font-size: 2.1em;
}

.card-subtype-tag {
    position: absolute;
    right: 0;
    top: 20px;
    background: #c68a8a;
    color: white;
    padding: 4px 10px;
    border-radius: 8px;
    font-size: 0.85rem;
    font-weight: 600;
    box-shadow: 0 2px 0 rgba(0,0,0,0.25);
}
.card-type-tag {
    position: absolute;
    right: 0;
    top: 0;
    background: #ffffff;
    padding: 4px 10px;
    border-radius: 8px;
    font-size: 0.85rem;
    font-weight: 600;
   /* box-shadow: 0 2px 0 rgba(0,0,0,0.25); */
}

/* Art area */
.card-art {
    position: relative;
    height: 500px;
    margin-bottom: 10px;
    border-radius: 14px;
    overflow: hidden;
    background: linear-gradient(180deg, rgba(255,255,255,0.9), rgba(255,255,255,0.7));
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.12);
}

.card-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;

    /* TRUE transparency fade-out */
    mask-image: linear-gradient(to bottom,
    black 0%,
    black 60%,
    transparent 100%
    );
    -webkit-mask-image: linear-gradient(to bottom,
    black 0%,
    black 60%,
    transparent 100%
    );
}

.card-art {
    position: relative;
    height: 500px;
    margin-bottom: 10px;
    border-radius: 14px;
    overflow: hidden;

    /* no white fill, just the border */
    background: transparent;
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.12);
}

/* remove the white overlay entirely */
.card-art::after {
    content: none;
}

.card-art-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.1rem;
    color: #666;
}


/* Art stays where it is (you can adjust height if you want more art) */
.card-art {
    position: relative;
    height: 520px;        /* a bit taller so art covers more */
    margin-bottom: 0;     /* no hard gap below the art */
    border-radius: 14px;
    overflow: hidden;
    background: transparent;
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.12);
    z-index: 1;
}

/* Rules box overlaps the art and has top padding for breathing room */
.card-rules {
    position: relative;
    z-index: 2;               /* above the art */
    margin-top: -80px;        /* pull rules box up over the art */
    border-radius: 14px;
    padding: 60px 16px 12px;  /* ⬅ top padding so text doesn't start right away */
    height: calc(100% - 20px);
    max-height: calc(100% - 20px);

    /* subtle translucent background so art still peeks through at top */
    background: linear-gradient(
            to bottom,
            rgba(255,255,255,0.0) 0%,
            rgba(255,255,255,0.5) 30%,
            rgba(255,255,255,0.8) 100%
    );
}

.card-inner {
    position: absolute;
    inset: 24px;
    border-radius: 28px;
    box-sizing: border-box;
    padding: 18px 22px 22px 22px;
    display: flex;
    flex-direction: column;
}

.card-rules {
    background: var(--rules-background);
    border-radius: 14px;
    padding: 12px 16px;
    height: calc(100% - 10px);
    max-height: calc(100% - 160px);
    min-height: calc(100% - 350px);
}

.fulltext .card-art{
    height: 0;
}

.fulltext .card-rules{
    margin-top: 45px;
    height: 100%;
    max-height: 100%;
}

.tallart .card-art{
    height: 100% !important;
    max-height: 1000px !important;
}

/*  if the height of the image changes then the scale of the width changes too... */
.tallart #previewArt{
    height: 150% !important;
    max-height: 1000px !important;
}

/* Make tallart actually give most of the card to the art */

/* Make sure tallart is added to #card-preview (or another ancestor of .card-art/.card-rules) */
.tallart .card-inner {
    display: flex;
    flex-direction: column;
}

/* Let the art eat most of the vertical space */
.tallart .card-art {
    flex: 1 1 auto;
    height: auto !important;
    max-height: none !important;
    margin-bottom: 6px; /* small gap before rules */
}

/* Let the rules shrink to just their content */
.tallart .card-rules {
    flex: 0 0 auto;
    margin-top: 0;
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
    padding-top: 8px; /* adjust as you like */
}

.rules-text {
    margin-bottom: 6px;
    font-family: var(--rules-text-font-family);
    font-size: var(--rules-text-max-font-size); /* important */
}

.bible-verse {
    font-family: var(--bible-verse-font-family);
    font-style: italic;
    font-size: var(--bible-verse-font-max-font-size);
    margin-top: 10px;
    overflow: hidden;
    color: #420000;
    text-shadow: 0 0 2px #fff;
}


.fun-text {
    margin-top: 4px;
    font-family: var(--fun-font-family);
    font-size: var(--fun-text-max-font-size);
    font-style: italic;
    color: #190000;
    text-shadow: 0 0 2px #fff;
}


/* SQUARE badge: equal width/height for single digits ("1", "2", "X") with
 * near-square corners; longer content (e.g. "10") widens but keeps the
 * height, so all rules-text boxes sit on the same square rhythm. */
.rules-text-icon{
    display: inline-block;
    box-sizing: border-box;
    border-radius: 0.18em;
    font-size: var(--rules-text-icon-min-font-size);
    padding-left: 0.22em;
    padding-right: 0.22em;
    color: white;
    box-shadow: 0 0 0 3px #ffffff, 0 3px 0 rgba(0, 0, 0, 0.3);
    font-weight: bold;
    min-width: 1.35em;
    height: 1.35em;
    line-height: 1.35em;

    text-align: center;
}

.tilde-box.tilde-BB .desc::before {
    /*content: 'Boosts below...';*/
}
.tilde-box.tilde-BB{
    background: rgba(208, 250, 249, 0.75);
    padding: 3px;
    display: inline-block;
    margin-top: 7px;
    width: 99%;
}

/* U~bob~ */
.tilde-box.tilde-U {
    background: #abecc5;
    color: black;
}

.tilde-box {
    margin-bottom: 1px;
}

.card-type-tag {
    background: transparent !important;
    border: none !important;
}
.card-type-tag:has(.cimgref-Unction) {
    background: var(--bg-Unction);
}

.card-type-tag:has(.cimgref-Maturity) {
    background: var(--bg-Maturity);
}

.card-type-tag:has(.cimgref-Resistance) {
    background: var(--bg-Resistance);
}

.card-type-tag:has(.cimgref-Habitual_Good) {
    background-color: var(--bg-Habitual_Good);
}

.card-type-tag:has(.cimgref-Habitual_Evil) {
    background-color: var(--bg-Habitual_Evil);
}.card-type-tag:has(.cimgref-Temptation) {
    background-color: var(--bg-Temptation);
}



#previewType{
    transform: rotate(45deg) scale(1.1);
    margin-top: 20px;
    border: 1px solid darkgray;
}

/* Per-ICON tilt exceptions (kept in sync with game.css): the kittens cat
   tower is a building — keep it upright instead of the 45° tag tilt. */
#previewType:has(.cimgref-Habitual_Good_kittens){
    transform: rotate(0deg) scale(1.1);
}

#previewTypeAlt {
    margin-top: 0px;
    margin-right: 10px;
    border: 1px solid darkgray;
}

#previewTypeAlt:has(.cimgref-Temptation_romanwar){
    transform: rotate(90deg) scale(1.1);
    margin-top: 40px;
    margin-right: 35px;
}

#previewTypeAlt:has(.cimgref-Resistance_romanwar){
    transform: scale(0.9); /* this is a bit big, lets scale it down*/
    margin-top: 15px;
    margin-right: -40px;
}

.fulltext.tallart .rules-text{
    margin-top: 25px;
}

#previewTypeAlt:has(.cimgref-Maturity){
    margin-top: 23px;
    margin-right: -45px;
}

#previewType:has(.cimgref-Habitual_Evil){
    margin-top: -15px;
    margin-right: 20px;
}

img.ctype.ctype-Maturity {
    transform: rotate(-20deg);
    margin-top: -58px;
    margin-left: -27px;
    height: auto;
    width: 128px;
}

img.ctype.ctype-Unction {
   transform: rotate(-20deg);
    margin-top: -40px;
    margin-left: 10px;
}


.alt-preview img.ctype.ctype-Unction {
    transform: rotate(0deg);
    margin-top: -20px;
    margin-left: 20px;
    margin-right: -20px;
}

img.ctype.ctype-Temptation {
    margin-top: -62px;
    margin-left: -29px;
    width: 128px;
    height: auto;
    transform: rotate(-90deg);
}

img.ctype.ctype-Resistance {
    margin-top: -40px;
    margin-left: -25px;
    width: 120px;
    height: auto;
}

#previewType:has(img.ctype) {
    width: 70px;
    text-align: center;
}

img.ctype {
    height: 100px;
    width: auto;
    background: transparent !important;
    mix-blend-mode: normal !important;
    isolation: isolate;
}

img.ctype.ctype-Habitual {
    margin-top: -45px;
    margin-left: -10px;
}

.discard-from-cost-zone-box {
    background: #958f8f;
}

.humility-box {
    background: #8ee6a8;
}

.humility-box {
    all: unset;
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;

    border-left: 28px solid transparent;
    border-right: 28px solid transparent;
    border-bottom: 40px solid #05d587;   /* triangle */
    top: -8px;
    vertical-align: middle;
}

.humility-box .humility-text {
    all: unset;
    position: absolute;
    left: 50%;
    top: 25px;
    transform: translate(-50%, -50%);
    font-size: var(--humility-text-max-font-size);
    font-weight: bold;
    color: white;
    -webkit-text-stroke: 1px #005a27;
    text-shadow: 0 0 3px #000000, 0 0 6px #292828;
}
.middle-icon .humility-box .humility-text {
    font-size: calc(var(--humility-text-small-icon-font-size) * 0.55);
    -webkit-text-stroke: 0.5px #005a27;
    text-shadow: 0 0 2px #000000, 0 0 4px #292828;
    top: 13px; /* optional: adjust vertical position for smaller size */
}

.small-icon .humility-box .humility-text {
    font-size: calc(var(--humility-text-small-icon-font-size) * 0.55);
    -webkit-text-stroke: 0.5px #005a27;
    text-shadow: 0 0 2px #000000, 0 0 4px #292828;
    top: 13px; /* optional: adjust vertical position for smaller size */
}


.humility-box {
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;

    /* inner triangle (your current green one) */
    border-left: 26px solid transparent;
    border-right: 26px solid transparent;
    border-bottom: 36px solid #05d587; /* inner fill */
}

/* OUTLINE BEHIND (slightly larger triangle) */
.humility-box::before {
    content: "";
    position: absolute;
    width: 0;
    height: 0;

    /* outline size = inner size + outline thickness */
    border-left: 30px solid transparent;   /* matching expansion */
    border-right: 30px solid transparent;
    border-bottom: 41px solid #004c2b;     /* outline color */

    top: 0px;      /* MUST equal difference between outline & inner */
    left: -33px;     /* MUST be centered offset */
    z-index: -1;    /* places outline behind inner triangle */
}

.humility-box::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;

    /* outline size = inner size + outline thickness */
    border-left: 30px solid transparent;   /* matching expansion */
    border-right: 30px solid transparent;
    border-bottom: 41px solid #004c2b;     /* outline color */

    top: -10px;      /* MUST equal difference between outline & inner */
    left: -30px;     /* MUST be centered offset */
    z-index: -1;    /* places outline behind inner triangle */
}

/* SMALLER INNER TRIANGLE — only inside .small-icon */
.small-icon .humility-box {
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;

    /* inner triangle */
    border-left: 12px solid transparent;
    border-right: 12px solid transparent;
    border-bottom: 18px solid #05d587; /* green fill */
}

/* OUTLINE LAYERS — only inside .small-icon */
.small-icon .humility-box::before,
.small-icon .humility-box::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;

    /* outline slightly larger than inner triangle */
    border-left: 20px solid transparent;
    border-right: 20px solid transparent;
    border-bottom: 24px solid #004c2b;

    z-index: -1;
}

/* bottom outline */
.small-icon .humility-box::before {
    top: -3px;
    left: -20px;
}

/* top/upper outline */
.small-icon .humility-box::after {
    top: -5px;
    left: -20px;
}


/* TINY INNER TRIANGLE — only inside .tiny-icon */
.tiny-icon .humility-box {
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;

    /* inner triangle (smaller) */
    border-left: 8px solid transparent;
    border-right: 8px solid transparent;
    border-bottom: 12px solid #05d587; /* green fill */
}

/* OUTLINE LAYERS — only inside .tiny-icon */
.tiny-icon .humility-box::before,
.tiny-icon .humility-box::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;

    /* outline slightly larger than inner */
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 14px solid #004c2b;

    z-index: -1;
}

/* bottom outline */
.tiny-icon .humility-box::before {
    top: -1px;
    left: -10px;
}

/* top/upper outline */
.tiny-icon .humility-box::after {
    top: -2px;
    left: -10px;
}

/* MIDDLE INNER TRIANGLE — between .small-icon and .tiny-icon */
.middle-icon .humility-box {
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;

    /* inner triangle (mid-size) */
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 15px solid #05d587; /* green fill */
}

/* OUTLINE LAYERS — only inside .middle-icon */
.middle-icon .humility-box::before,
.middle-icon .humility-box::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;

    /* outline slightly larger than inner */
    border-left: 14px solid transparent;
    border-right: 14px solid transparent;
    border-bottom: 18px solid #004c2b;

    z-index: -1;
}

/* bottom outline */
.middle-icon .humility-box::before {
    top: -2px;
    left: -14px;
}

/* top/upper outline */
.middle-icon .humility-box::after {
    top: -3px;
    left: -14px;
}

.draw-to-hand-box{
    background-color: #2892ff;
}

.tilde-box.tilde-D{
    background-color: #2892ff;
    color: white;
}

.cost-box {
    background: #22a12a;
    box-shadow: 0 0 0 3px #5a5a5a, 0 3px 0 rgba(0, 0, 0, 0.3);
}


.card-graphics-img.Any-Boost{
   width: 60px;
    height: auto;
    vertical-align: -14.46px;
}

.card-graphics-img.Self-Boost{
    width: 60px;
    height: auto;
    vertical-align: -14.46px;
}

.card-graphics-img.Brotherly-Boost{
    width: 60px;
    height: auto;
    vertical-align: -14.46px;
}


/* A# IS ORANGE, NOT RED — it was too close to R# to tell apart.
   The two chips carry different questions: A is an amount taken away, R is what
   an opponent pays to answer this card. Both were red — #a12222 and #7d1420 —
   and measured 23 apart under protanopia, which is not a difference, it is two
   dark red squares. Orange is 93 away from R under every kind of vision.
   Burnt rather than bright: a lighter orange lands on the green cost chip once
   red-green vision is simulated, and this one keeps white text at 4.7x. */
.negative-box{
    background: #b85a10;
}

/* R# — THE COUNTER/RESIST COST, WRITTEN INSIDE A RULE.
   The card already carries this value as a badge in its corner: on an evil
   card what Righteous pays to resist it, on a righteous one what Evil pays to
   counter it. So the inline chip wears the badge's own colours — #7d1420 with
   the pale ring, the same pair resistCostDefaults() in layouts.php dresses the
   box with — and a reader meets one thing twice rather than two things once.

   The negative box was #a12222 and near enough to this to be unreadable at a
   glance — 23 units apart under protanopia — so A# is burnt orange now and the
   counter cost keeps the badge's red. An attack and a counter cost are
   different numbers; telling them apart should not require remembering which
   red is which. */
.resist-box {
    background: #7d1420;
    box-shadow: 0 0 0 3px #f0d3d3, 0 3px 0 rgba(0, 0, 0, 0.3);
}

.cost-colon {
    font-size: 2.8rem;
    font-weight: bold;
    margin-left: 2px;
}

/* A note explaining an attribute begins on the attribute's own line. A
   tilde-box is inline-block and so cannot break, which pushed the whole note
   below "Reversal 1" and made it read as a separate rule rather than as the
   explanation of the chip above it. box-decoration-break:clone keeps the
   padding and rounded ends on each line fragment once it does wrap. Scoped to
   a note directly following an attribute chip, so every other N~ ~ keeps the
   block it was proofed with. Stated in layouts.php too, for the printed face. */
.ccg-attr + .tilde-box.tilde-N {
    display: inline;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}
.tilde-box {
    font-size: smaller;
    background: lightgoldenrodyellow;
    border-radius: 10px;
    display: inline-block;
    padding-top: 3px;
    padding-bottom: 3px;
    padding-left: 5px;
    padding-right: 5px;
}
.boost-keywords {
    font-weight: bold;
    font-size: 0.9em;
}

/* Cost badge bottom-left */
.cost-badge {
    position: absolute;
    left: -13px;
    bottom: -13px;
    width: 140px;
    height: 140px;
    border-radius: 16px;
    border: 1px solid black;
    background: #22a12a;
    box-shadow:
            0 6px 14px rgba(0, 0, 0, 0.55),   /* main soft shadow */
            0 2px 4px rgba(0, 0, 0, 0.45);    /* subtle closer shadow */
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--cost-text-max-font-size);
    font-weight: 700;
    color: #fff;
    font-family: var(--primary-card-font-family);
}

/* Copyright & link bottom center */
.copyright-line {
    position: absolute;
    left: 135px;
    bottom: 0px;
    font-family: var(--primary-card-font-family);
    font-size: var(--copyright-text-max-font-size);
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-shadow: var(--text-shadow-outline-value);
}

.fulltext.tallart #previewCopyrightText {
    font-size: var(--copyright-text-max-font-size);
}


.fulltext.tallart .card-footer{
    text-align: right;
}

.fulltext.tallart .copyright-line {
    position: static;
    display: inline-block;
    text-align: right;
    left: 136px;
    bottom: 50px;
    font-family: var(--primary-card-font-family);
    font-size: var(--copyright-text-max-font-size);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-shadow: var(--text-shadow-outline-value);
    text-shadow: var(--text-shadow-outline-on-raw-border-value);
    color: black;
}

.copyright-line span {
    white-space: nowrap;
}

/* Card info bottom-right */
.card-info-block {
    position: absolute;
    right: 55px;
    bottom: 5px;
    font-size: var(--cardnuminfo-text-max-font-size);
    text-align: right;
}

/* Icon slot (top right of text box) */
.card-icon-slot {
    position: absolute;
    right: 6px;
    bottom: 6px;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    border: 1px solid rgba(0,0,0,0.2);
    background: rgba(255,255,255,0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    text-align: center;
    padding: 4px;
    box-sizing: border-box;
    z-index: 10;
}

.card-icon-slot img {
    width: 100%;
    height: 100%;
   /* object-fit: contain;*/
}

/* Default neutral background (replace with your own) */
#card-preview.gold {
    background-image: url("../../../sets/back_FireGrassIceStone4.png");
    background-color: #d6aa4c;
}
#card-preview.fire {
    background-image: url("../../../sets/back_Fire2.png");
}
#card-preview.firehabitual {
    background-image: url("../../../CardBorders/back_fire_habitual7.png");
}
#card-preview.grass {
    background-image: url("../../../sets/back_Grass3.png");
}
#card-preview.ice {
    background-image: url("../../../sets/back_Ice4.png");
}
#card-preview.stone {
    background-image: url("../../../sets/back_Stone5.png");
}



.card-footer {
    position: absolute;
    bottom: 25px;
    width: 635px; /* calc(30px - var(--card-width)); */
    height: 100px;
    margin-top: 6px;
    padding: 10px 12px 12px 12px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.6);
    font-size: 0.96rem;
    line-height: 1.3;
    max-height: 35px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
    z-index: 999;
}



/* Inner frame becomes a flex column */
.card-inner {
    position: absolute;
    inset: 24px;
    border-radius: 28px;
    box-sizing: border-box;
    padding: 18px 22px 22px 22px;

    display: flex;
    flex-direction: column;
}



/* Make sure footer / cost float above if ever overlapping */
.cost-badge,
.copyright-line,
.card-info-block {
    z-index: 5;
}


.card-graphics-img {
    /* --glyph-x: the size factor from "#unction-1.5x#", 1 when not given.
       1.04em, and the number still comes from the coin it stands beside: that
       coin is 1.35em tall in its own em at font-size .70em — 0.945em here —
       and its white ring is drawn OUTSIDE that, so what the eye measures is
       0.945 + 2 × 0.07 × 0.70 = 1.04em. The earlier 1.22 was the same sum with
       the coin at .82em; both numbers moved down together because the question
       was never "how big is the coin" but "how big is the capital letter" —
       a cap is about 0.70em, and a mark three quarters taller than the letter
       beside it reads as a picture in the line rather than a symbol in it.
       Matching the box and ignoring its ring leaves the glyph visibly short,
       which is the shape of getting the arithmetic right and the question
       wrong — so keep counting the ring. */
    height: calc(0.96em * var(--glyph-x, 1));
    width: auto;          /* keep aspect ratio */
    margin-right: 0.15em; /* spacing that also scales with font size */
    display: inline-block;
    /* The mark's MIDDLE on the cap's middle: -0.17em = 0.35 - 1.04/2. Sat on
       the baseline (the old -0.1em, near enough to none) a tall mark can only
       grow upward, so the words looked lifted off the icons beside them. */
    vertical-align: -0.17em;
}

.card-graphics-img.rotate {
    transform: translateY(2px);
    display: inline-block;
}
/* THE TOKEN BODY IS PARCHMENT, so the tap glyph is not inverted here.
   It used to be, and the rule said why: the glyph is dark and vanished against
   the token's dark body. The body became a parchment mini-card -- the gradient
   is a few lines below this -- and the inversion stayed, so "created already
   spent" printed as a black disc with a white arrow: the one place on the card
   showing a negative of the symbol used everywhere else. The plain glyph
   already carries its own pale plate and dark ring, which is what makes it
   readable on any background, including this one. */

/* Inline COUNTER glyph (theme-neutral clock icon with an optional sign/number
   overlaid on the face). Mirrors the board's game.css so the standalone
   CardRenderer (view-card.php, _card_render.php) shows the overlay centered. */
/* A COUNTER VALUE TOO LONG FOR THE COIN sits beside it instead of over it.
   "+2" fits on the face; "+X+1" ran past both edges and printed over the words
   either side. Same mark, read left to right, and it keeps its size with the
   text around it rather than shrinking until it is not readable. */
.counter-glyph.counter-glyph-wide { margin-right: 0.1em; }
.counter-glyph .counter-glyph-beside {
    margin-left: 0.12em;
    font-weight: 800;
    font-size: 0.86em;
    white-space: nowrap;
    vertical-align: baseline;
}
.counter-glyph {
    position: relative;
    /* Its own stacking context, so the value's z-index is measured against the
       dial beside it and not against whatever the card happens to be doing. */
    isolation: isolate;
    display: inline-block;
    vertical-align: -0.13em;
    line-height: 1;
    margin-right: 0.15em;
}
.counter-glyph img.card-graphics-img.counter {
    /* 0.96em: the one height every inline mark shares — chip, coin, wedge and
       glyph — so a line holding several of them sits straight. At 1.15 the dial
       stood above the boxes beside it. Stated in layouts.php too; move both. */
    height: 0.96em;
    width: auto;
    margin-right: 0;
    vertical-align: middle;
    display: inline-block;
}
.counter-glyph-overlay {
    position: absolute;
    /* 57%, not 50%: the dial is a clock face whose clear centre sits below the
       middle of its box — above it are the rim and the twelve o'clock tick — so
       arithmetic centring left the value riding high against that tick. Stated
       in layouts.php as well, which is the copy the printed face obeys. */
    top: 57%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: 'Cinzel', serif;
    /* DARK TYPE ON A LIGHT DIAL, WHICH NEEDS NO OUTLINE AT ALL.
       icon_counter.svg is a pale clock face — #edf5ff inside a #6aa9ff rim — and
       the value was set WHITE on it. White on near-white cannot be read, so it
       was given a 0.16em black stroke to survive, and at weight 900 that
       outline was thicker than the strokes it outlined: "+X" set as a black
       lozenge with a white crack through it.
       The outline was solving a problem the colour made. Navy on the pale face
       reads on its own — it is the colour of the dial's own tick marks — so
       there is nothing to outline, and what is left is a value rather than a
       blot. The faint light halo is only for the case where a tall glyph
       touches the rim. */
    font-weight: 800;
    font-size: 0.92em;          /* the per-length rules below set the real size */
    letter-spacing: -0.01em;
    line-height: 1;
    color: #ffffff;
    /* ABOVE THE DIAL, NOT IN IT. The icon is an <img> in the same stacking
       context; without this the value can be painted under it depending on
       source order, which reads as a counter with nothing on it. */
    z-index: 2;
    /* WHITE INSIDE A HARD BLUE EDGE. The dial has hands and tick marks under
       it, so the value needs something of its own — but a plate covers the
       clock and an outline does not, which is the difference asked for.
       The blue is the rim's own colour, darkened, so the edge belongs to the
       icon rather than being a black line drawn on it.
       0.17em at weight 800 — 18% of the glyph's height, where the lozenge
       began at 20%, so it is as hard as it goes with a margin rather than a
       hope. The tracking opens by the same amount it thickens: a wider outline
       needs somewhere to put itself, and two characters set tight will meet
       through their strokes long before the letters touch. the first attempt was 0.16em at weight 900 and the two characters'
       outlines met in the middle. The dial's ticks and hands were greyed at the
       same time — half this problem was behind the letters, not around them,
       and a heavier outline alone would have gone back to the lozenge trying to
       out-shout them. */
    -webkit-text-stroke: 0.17em #14245e;
    paint-order: stroke fill;
    /* A GROUND OF ITS OWN, WHICH IS WHAT THE OTHER MARKS HAVE.
       Dark ink on the pale dial was still hard to read, and the reason is that
       the dial is not a flat colour: it has hands and twelve tick marks, and a
       "-1" sitting across a hand is a "-1" with a line through it. A halo
       cannot fix that — it softens the edge of the letter, it does not hide
       what is behind it.
       Every other mark on a card already solves this the same way: the cost
       coin, the X chip and the -1 triangle are all dark-or-white ink on a
       SOLID shape. So the counter's value gets one too — a small pale plate in
       the dial's own face colour, which reads as part of the clock rather than
       as something stuck on it, with a hairline ring so it does not dissolve
       into the lighter parts of the face. */
    /* A whisper of a shadow, for engines that ignore -webkit-text-stroke —
       not a halo: the stroke is the contrast. */
    text-shadow: 0 1px 1px rgba(10,16,44,.45);
    white-space: nowrap;
    pointer-events: none;
}
.counter-glyph-overlay.cg-len1 { font-size: 0.94em; -webkit-text-stroke-width: 0.17em; }
.counter-glyph-overlay.cg-len2 { font-size: 0.72em; letter-spacing: 0.035em;
    -webkit-text-stroke-width: 0.13em; }
.counter-glyph-overlay.cg-len3 { font-size: 0.58em; letter-spacing: 0.025em;
    -webkit-text-stroke-width: 0.105em; }


#card-preview {
    background-size: contain;   /* <— ALWAYS SHOW FULL BACKGROUND */
    background-repeat: no-repeat;
    background-position: center;
}

.alt-preview-wrap { margin-top: 18px; }

.footer-link {
    font-family: var(--primary-card-font-family);
    font-size: var(--weblink-text-max-font-size);
}

#previewCopyrightText {
    display: block;
}
.card-scale-wrapper {
    width: 100%;
    max-width: 750px;
    margin: 0 auto;
    transform-origin: top left;
}

#card-preview {
    border-radius: 20px;
}

#card-preview {
    background-size: cover !important;
    background-repeat: no-repeat;
    background-position: center;
}

/* Optional: style the toggle button */
#toggleCardScaleBtn {
    margin-top: 10px;
    background: #498df0;
    border-radius: 6px;
    color: #fff;
    font-weight: 600;
}
#toggleCardScaleBtn:hover {
    background: #3a6fbe;
}

#card-preview {
    transition: transform 0.25s ease;
}

/* Base (1 digit) */
.cost-badge {
    font-size: var(--cost-text-max-font-size);
}

/* 2 digits */
.cost-badge.len-2 {
    font-size: calc(var(--cost-text-max-font-size) * 0.75);
}

/* 3 digits (or 2 chars like "5X") */
.cost-badge.len-3 {
    font-size: calc(var(--cost-text-max-font-size) * 0.55);
}

/* 4+ chars ("10X", "0–50", etc.) */
.cost-badge.len-4 {
    font-size: calc(var(--cost-text-max-font-size) * 0.60);
}

.cost-badge {
    z-index: 1000;
}

.card-title-bar {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 9999;
    width: max(100%, calc( var(--card-width) - 60px) );
    text-align: left;
    justify-content: left;
}

#cardArtDropZone {
    cursor: pointer;
    outline: none;
}

#cardArtDropZone:focus {
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.35);
}

#rulesText {
    height: 250px;
}
.btnFieldSave, .btnOptSave{
    font-size: 0.75rem;
    padding: 2px;
    display: inline-block;
    float: right;
}

[data-unsaved="true"] {
    background-color: rgba(243, 227, 144, 0.2) !important;
    color: black;
}


.math-symbol-let-x {
    font-weight: bold;
    text-transform: uppercase;
}

.math-symbol{
    font-weight: bold;
    font-size:1.3em;
}

.placeholder-wrap-container{
    position: relative;
    line-height: 1.2;
    white-space: normal;      /* ensures wrapping */
    overflow-wrap: break-word;
    word-break: break-word;
}

/* This is the invisible anchor the text wraps around */
.placeholder-div {
    width: 80px;              /* should match your cost box width */
    shape-outside: inset(0);  /* required for wrapping */
    pointer-events: none;
}

.gdimage-preview {
    /*position: absolute;
    bottom: 0;*/
}

.gdimage-preview img {
    display: block;
}

.top-bottom-flex {
    flex: 1;                 /* this column grows */
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* override old rule */
.preview-wrapper {
    flex: 0 0 auto;          /* don't stretch vertically */
    display: flex;
    align-items: flex-start;
    overflow: visible;       /* or auto, your choice */
}

.gdimage-preview {
    flex: 0 0 auto;          /* also just its natural height */
}

.rounded.down{
    font-size: smaller;
}

/** this doesn't work right now **/
.boost-summary {
    display: none;
    font-size: 0.6em;
    font-style: italic;
    background: #d0faf9;
    padding: 3px;
}

.rules-text h1, h2, h3, h4, h5, h6 {
    margin: 0;
    margin-bottom: 3px;
}

.rules-text ul {
    list-style-type: none;
    padding-left: 0;
}
button.down {
    background: #456a3c;
}

/* container holding form + preview */
.field-hflex.card-layout {      /* or whatever wrapper you use */
    display: flex;
    align-items: flex-start;
}

/* LEFT COLUMN: Card Designer form */
.card-form {
    flex: 0 0 420px;    /* or whatever width you like */
    max-width: 420px;

    /* IMPORTANT: remove fixed height/own scroll */
    height: auto;
    max-height: none;
    overflow: visible;  /* no inner scrollbar */
}


/* ============================
   FULLTEXT MODE: text over art
   ============================ */

/* Make sure fulltext is on #card-preview or an ancestor of .card-art/.card-rules */
/* e.g. $('#card-preview').toggleClass('fulltext'); */

.fulltext.tallart .card-inner {
    position: relative; /* anchor for overlaying things */

}

/* Restore art height (don’t hide it) */
.fulltext.tallart .card-art {
    height: 520px !important;      /* or whatever your normal art height is */
    max-height: none !important;
    margin-bottom: 0;
    position: relative;
    z-index: 1;
}

/* Rules box overlays the bottom of the art with a dark gradient */
.fulltext.tallart .card-rules {
    position: relative;
    z-index: 2;

    /* pull it up so it sits on top of the lower portion of the art */
    margin-top: -220px;            /* tweak this to taste */

    /* let it size by content */
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;

    padding: 24px 16px 16px;

    /* dark gradient for readability */
    background: linear-gradient(
            to bottom,
            rgba(0,0,0,0.0),
            rgba(0,0,0,0.75)
    );

    color: #fff;
    text-shadow: 0 0 4px rgba(0,0,0,0.9);
}

/* Optional: paragraphs/verse/fun text slightly tighter for overlay mode */
.fulltext.tallart .rules-text,
.fulltext.tallart .bible-verse,
.fulltext.tallart .fun-text {
    margin-bottom: 4px;
}

.noart .card-art {
    display: none;
}

/* ============================
   FULLTEXT + TALLART overlay
   ============================ */

/* In this mode, treat card-inner as a positioned box, not a flex column */
.fulltext.tallart .card-inner {
    position: relative;
    display: block;
    left: -30px;
    height: 1020px;
}

/* Art fills the inner card and sits behind the overlay */
.fulltext.tallart .card-art {
    position: relative;
    z-index: 1;
    height: 620px !important;    /* tweak to taste */
    height: calc(100% - 120px) !important;    /* tweak to taste */
    margin-bottom: 0;
}

/* Rules/verse/fun text as a band over the lower part of the art. The dark
   backing now reaches ALL the way down to the footer (bottom:92px, matching
   the art-split band) and goes fully opaque near its base so rules text stays
   legible over busy/light art right down to the last line — no mid-card
   fade-out that leaves the lower art un-darkened. The top keeps a little
   art bleed-through for the classic text-over-art look; the separate top
   scrim (.card-art::after, below) protects the title. */
.fulltext.tallart .card-rules {
    position: absolute;
    top: 35px;
    left: 0;               /* span full inner width */
    right: 0;
    bottom: 92px;          /* reach the footer/copyright bar (was 130px) */
    margin: 0;
    vertical-align: middle;

    box-sizing: border-box;
    /* Horizontal padding baked with --rules-inset-x (Card Designer; default 0)
       so the rules block can be narrowed without clobbering the base padding. */
    padding: 24px calc(22px + var(--rules-inset-x, 0px)) 18px calc(22px + var(--rules-inset-x, 0px));

    height: auto !important;
    max-height: none !important;    /* fill down to the footer */
    min-height: 0 !important;
    overflow: hidden;

    border-radius: 14px;
    background: linear-gradient(
            to bottom,
            rgba(0,0,0,0.30) 0%,
            rgba(0,0,0,0.66) 26%,
            rgba(0,0,0,0.82) 55%,
            rgba(0,0,0,0.88) 100%
    );
    color: #fff;
    text-shadow: 0 0 4px rgba(0,0,0,0.9);
    z-index: 2;
}


.card-rules.vert-align {
    /* NEW: vertical centering of inner content */
    display: flex;
    flex-direction: column;
    justify-content: center;   /* vertical align */
    align-items: flex-start;   /* keep text left-aligned */
}


/* Slightly tighter text inside overlay band */
.fulltext.tallart .rules-text,
.fulltext.tallart .bible-verse,
.fulltext.tallart .fun-text {
    margin-bottom: 4px;
    color: white;
}

.fulltext.tallart #previewArt {
    opacity: 0.5;
}
.fulltext.tallart .card-footer{
    /* Pin to the bottom of .card-inner so the copyright never floats up
       into the title area. The flex-column layout of .tallart .card-inner
       means a `position: static` footer would just take its turn in the
       flow — for cards with short rules (e.g. Tokens) that landed the
       footer next to the title pill. Absolute + bottom-anchored gives the
       same result as the legacy non-tallart layout. */
    position: absolute;
    left: 0;
    right: 0;
    bottom: 25px;
    width: auto;
    height: auto;
    text-align: right;
    text-shadow:
            -1px -1px 0 #000,
            1px -1px 0 #000,
            -1px  1px 0 #000,
            1px  1px 0 #000;
    background: none;
}
.fulltext.tallart .card-footer .copyright-line {
    color: black;
    text-shadow: 0 0 6px #a1a1a1;
    /* Flow the copyright + card number inline, right-aligned, ending just to
       the LEFT of the type-icon slot (right:6px, 40px wide) so nothing covers
       or clips "© Kinsman Software LLC". */
    position: static;
    display: inline;
    white-space: nowrap;
}
/* Card number rides inline right after the copyright (was absolutely
   positioned at right:55px, which floated on top of "…LLC"). The 50px right
   margin clears the corner type-icon. */
.fulltext.tallart .card-footer .card-info-block {
    position: static;
    display: inline;
    right: auto;
    bottom: auto;
    margin-left: 6px;
    margin-right: 50px;
}
.fulltext.tallart .card-footer .card-info-block br { display: none; }

/* ================================================================
   ADJUSTABLE ART/TEXT SPLIT  (per-card, per-theme — opt-in)
   ----------------------------------------------------------------
   CardRenderer adds `.has-art-split` + a `--art-split` custom prop
   (the ART region's share of the card height, from the top) when a
   card carries a saved split for the current theme. The picture is
   pinned to the TOP `--art-split` slice (crisp, cover-fit) and the
   rules/text band fills everything BELOW it down to the footer — so
   a smaller split → smaller art + a taller text band (autoFit grows
   the font to fill it). No class = the default text-over-full-bleed
   layout above stays exactly as-is (back-compat).
   ================================================================ */
.fulltext.tallart.has-art-split .card-art {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    height: calc(100% * var(--art-split, 0.55)) !important;
    max-height: none !important;
    margin: 0 !important;
    overflow: hidden !important;
    border-radius: 14px 14px 0 0;
    z-index: 1;
}
.fulltext.tallart.has-art-split .card-art img {
    width: 100% !important;
    height: 100% !important;
    max-height: none !important;
    min-height: 0 !important;
    object-fit: cover !important;
    object-position: center;            /* per-card kittens framing overrides this inline */
    opacity: 1 !important;              /* dedicated art region → show it crisply */
}
.fulltext.tallart.has-art-split .card-rules {
    top: calc(100% * var(--art-split, 0.55)) !important;
    bottom: 92px !important;            /* clear the footer / copyright bar */
    left: 0 !important;
    right: 0 !important;
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
    overflow: hidden;
    border-radius: 0 0 14px 14px;
    /* Solid, readable band that reaches ALL the way down to the footer
       (no mid-card fade-out). */
    background: linear-gradient(to bottom,
        rgba(0,0,0,0.66) 0%,
        rgba(0,0,0,0.82) 14%,
        rgba(0,0,0,0.86) 100%) !important;
    display: flex !important;
    flex-direction: column;
    justify-content: center;   /* vertically centre the fitted text in the band */
    align-items: stretch;
    z-index: 2;
}
/* The green cost badge must always paint ON TOP of the footer/copyright bar
   (which follows it in DOM order) — and above the art in split mode. */
.fulltext.tallart .cost-badge { z-index: 6; }

/* ── TOP SCRIM ────────────────────────────────────────────────────────────
   A soft dark gradient over the very top of the art so the card TITLE (and
   the top-right type tag) stay legible over busy/light art. Tasteful, not
   heavy — fades out well before the rules band. Painted inside .card-art so
   it sits above the picture but below the title bar (lifted below) and the
   rules band. Works in both the default full-bleed layout and the art-split
   layout (where .card-art is just the top slice — the scrim still crowns it).
   ───────────────────────────────────────────────────────────────────────── */
.fulltext.tallart .card-art { position: relative; }
.fulltext.tallart .card-art::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 165px;
    background: linear-gradient(
            to bottom,
            rgba(0,0,0,0.52) 0%,
            rgba(0,0,0,0.26) 45%,
            rgba(0,0,0,0.0) 100%
    );
    border-radius: 14px 14px 0 0;
    pointer-events: none;
    z-index: 3;
}
/* Keep the title above the scrim + art so the top darkening backs it, not
   covers it. (Type/subtype tags ride along in the same bar.) */
.fulltext.tallart .card-title-bar { position: relative; z-index: 5; }

.fulltext.tallart .tilde-box.tilde-BB{
    color: black;
    text-shadow: 0 0 2px #aeaeae;
}

#card-qrcode{

    bottom: 5px;

    z-index: 999999;
}

:root{
    --qr-width: 125px;
}
.fulltext.tallart #card-qrcode img{
    margin-left: 365px;
    margin-top: 10px;
    z-index: 999999;
    width: var(--qr-width);
    height: var(--qr-width);
    overflow: auto;
}

#card-qrcode img{
    margin-left: 392px;
    margin-top: -38px; /*-15 was too low*/
    z-index: 999999;
    width: var(--qr-width);
    height: var(--qr-width);
    overflow: auto;
}

.previewLinkTextLine2 {
    text-align: center;
}

.fulltext.tallart .card-graphics-img.rotate {
    filter: invert(1);
}

.fulltext.tallart .tilde-box {
    color: black;
}

.rules-text {

}

#statusMessage {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
}

.rules-text h1, .rules-text h2, .rules-text h3, .rules-text h4, .rules-text h5, .rules-text h6 {
    margin: 0;
    padding: 0;
}

.rules-text h1, .rules-text h2, .rules-text h3, .rules-text h4, .rules-text h5, .rules-text h6{
    margin-top: -15px !important;
}

.rules-text p {
    margin: 0;
    padding: 0;
}

.rules-text #card-qrcode{

    bottom: 5px;

    z-index: 999999;
}

#cardSortButtons button {
    padding: 1px;
    font-size: 0.8em;
}

.card-legend {
    font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 0.65rem;              /* small-card friendly */
    line-height: 1.2;
    background: rgba(255, 255, 255, 0.85);
    border-radius: 8px;
    padding: 6px 7px;
    border: 1px solid rgba(0, 0, 0, 0.25);
    box-sizing: border-box;
    max-width: 100%;                 /* fit inside card */
    /* Optional: constrain width if you want a column look */
    /* max-width: 260px; */
}

.card-legend-title {
    text-align: center;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.6rem;
    margin-bottom: 4px;
}

.card-legend-list {
    list-style: none;
    padding-left: 0;
    margin: 0;
}

.card-legend-list li {
    margin: 0 0 2px;
}

/* Slight visual separation between sections */
.card-legend-divider {
    border-top: 1px solid rgba(0, 0, 0, 0.25);
    margin: 4px 0;
}

/* Optional: slightly dim less-important sentences */
.card-legend-types li,
.card-legend-actions li {
    /* tweak if needed */
}

/* If you need it even tighter for tiny cards, use this helper class */
.card-legend.card-legend-tight {
    font-size: 0.6rem;
    line-height: 1.1;
    padding: 4px 5px;
}

/* HTML tags */
.hwt-tag {
    color: #268bd2;        /* blue */
    font-weight: 600;
}

/* HTML attributes */
.hwt-attr {
    color: #b58900;        /* amber */
}

/* Attribute values */
.hwt-string {
    color: #2aa198;        /* teal */
}

/* Comments */
.hwt-comment {
    color: #93a1a1;        /* gray */
    font-style: italic;
}

/* Custom keywords */
.hwt-keyword {
    color: #dc322f;        /* red */
    font-weight: 600;
}

/* code mirror */
.cm-wrapper {
    height: 340px;
    border: 2px solid #2c6bed;
    border-radius: 10px;
    background: #1e1e1e;
}

/* 1) Give BOTH previews the same base sizing/positioning */
#card-preview,
#card-preview-alt {
    position: relative;
    width: var(--card-width);
    height: calc(var(--card-height) + 50px);
    box-sizing: border-box;
    border-radius: 40px;
    box-shadow: 0 0 25px rgba(0,0,0,0.8);
    color: #000;
    font-family: "Nunito Sans", system-ui, -apple-system, sans-serif;

    /* keep your background behavior consistent */
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
}

/* 2) Your existing background image rules only target #card-preview.<class>.
      Duplicate them for #card-preview-alt.<class> */
#card-preview.gold,
#card-preview-alt.gold {
    background-image: url("../../../sets/back_FireGrassIceStone4.png");
    background-color: #d6aa4c;
}
#card-preview.fire,
#card-preview-alt.fire {
    background-image: url("../../../sets/back_Fire2.png");
}
#card-preview.firehabitual,
#card-preview-alt.firehabitual {
    background-image: url("../../../CardBorders/back_fire_habitual7.png");
}
#card-preview.grass,
#card-preview-alt.grass {
    background-image: url("../../../sets/back_Grass3.png");
}
#card-preview.ice,
#card-preview-alt.ice {
    background-image: url("../../../sets/back_Ice4.png");
}
#card-preview.stone,
#card-preview-alt.stone {
    background-image: url("../../../sets/back_Stone5.png");
}

/* 3) If you want the alt preview NOT to stretch its wrapper: */
.alt-preview-wrap {
    width: var(--card-width);
    max-width: var(--card-width);
    margin: 18px 0 0 0;  /* left aligned under first */
}

.preview-wrapper {
    display: flex;
    flex-direction: column; /* stack previews */
    align-items: flex-start;
    gap: 18px;
}

/* preview-wrapper already contains: card, alt card, gd preview */
.preview-wrapper{
    display: flex;
    flex-direction: column;   /* default = stacked */
    align-items: flex-start;
    gap: 18px;
}

/* When side-by-side mode is on */
.preview-wrapper.side-by-side{
    flex-direction: row;
    align-items: flex-start;
    gap: 18px;
    flex-wrap: wrap; /* allows gd preview to drop below if not enough width */
}

/* Make sure both cards keep card size (don’t expand to 100%) */
.preview-wrapper .card-scale-wrapper{
    width: var(--card-width);
    max-width: var(--card-width);
    margin: 0;
}

/* Optional: in side-by-side mode, put gd preview on its own row */
.preview-wrapper.side-by-side .gdimage-preview{
    flex-basis: 100%;
}
#card-preview,
#card-preview-alt{
    width: var(--card-width);
    height: calc(var(--card-height) + 50px);
    position: relative;
}

/* ===== FINAL AUTHORITY: preview layout ===== */

/* default (stacked) */
.top-bottom-flex .preview-wrapper{
    display: flex !important;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
}

/* side-by-side mode */
.top-bottom-flex .preview-wrapper.side-by-side{
    flex-direction: row !important;
    align-items: flex-start;
    gap: 18px;
    flex-wrap: wrap; /* allow wrap if window too narrow */
}

/* CRITICAL: don't let the card wrappers be width:100% in flex-row */
.top-bottom-flex .preview-wrapper .card-scale-wrapper{
    width: var(--card-width) !important;
    max-width: var(--card-width) !important;
    flex: 0 0 var(--card-width);
    margin: 0 !important;          /* kill auto-centering */
}

/* your alt wrapper has margin-top for stacked view; remove it in side-by-side */
.top-bottom-flex .preview-wrapper.side-by-side .alt-preview-wrap{
    margin-top: 0 !important;
}

/* optional: push GD preview to full row under both cards */
.top-bottom-flex .preview-wrapper.side-by-side .gdimage-preview{
    flex: 0 0 100%;
}

/* ====== DEFAULT (stacked) ====== */
.preview-wrapper{
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
}

/* Only in stacked mode do we allow "center + max-width" wrappers */
.preview-wrapper:not(.side-by-side) .card-scale-wrapper{
    width: 100%;
    max-width: var(--card-width);
    margin: 0 auto;
}

/* ====== SIDE-BY-SIDE MODE ====== */
.preview-wrapper.side-by-side{
    flex-direction: row;
    flex-wrap: nowrap;        /* IMPORTANT: never wrap to next line */
    align-items: flex-start;
    gap: 18px;
    overflow-x: auto;         /* scroll horizontally if screen is too narrow */
    overflow-y: hidden;
}

/* In side-by-side, each card wrapper must be a fixed card-width column */
.preview-wrapper.side-by-side .card-scale-wrapper{
    flex: 0 0 var(--card-width);
    width: var(--card-width);
    max-width: var(--card-width);
    margin: 0;
}

/* don’t push the alt down in side-by-side */
.preview-wrapper.side-by-side .alt-preview-wrap{
    margin-top: 0;
}

/* optional: keep the GD preview below (or remove if you want it inline) */
.preview-wrapper.side-by-side .gdimage-preview{
    flex: 0 0 100%;
}


/* Default = middle, but controllable per-card via --art-y */
.card-art img{
    object-position: 50% var(--art-y, 50%);
}


img.ctype-Habitual {
    margin-top: 5px;
    margin-right: -50px;
}

img.ctype.cimgref-Habitual_Evil_romanwar {
    margin-top: -25px;
    margin-right: -40px;
}

img.ctype.cimgref-Habitual_Good_romanwar {
    margin-top: 5px;
    margin-right: -50px;
}

/* Kittens EVIL Habitual — the "mouse-hole" corner glyph sat too LOW with the
   generic Habitual offset (margin-top:-45px), dropping into the title row
   while the Good-Habitual tower + other kittens type icons crown the corner.
   Lift it so it sits higher/cleaner in the top-right. Scoped to the evil
   kittens ref so Good Habitual (tower), other types and other themes are
   unaffected. The .ch-card-root variant out-specifies game.css's generic
   `.ch-card-root img.ctype.ctype-Habitual` (which loads after this file). */
img.ctype.cimgref-Habitual_Evil_kittens,
.ch-card-root img.ctype.ctype-Habitual.cimgref-Habitual_Evil_kittens {
    margin-top: -78px;
}

.keyword {
    font-weight: bold;
}

.keyword.cost-zone{
    display: inline-flex;
    align-items: center;
    gap: 0.15em;
}

/* the CZ coin itself — SQUARE token (matches the rules-text number boxes) */
.keyword.cost-zone .coin{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;

    width: auto;
    height: 1.35em;
    min-width: 1.35em;
    padding: 0 0.22em;
    white-space: nowrap;   /* keep "CZ" on one line (token, not stacked) */
    line-height: 1;

    border-radius: 0.18em;

    /* refined gold coin */
    background:
            radial-gradient(circle at 30% 28%,
            rgba(255,255,255,.95) 0%,
            rgba(255,255,255,.45) 20%,
            rgba(255,255,255,0) 42%
            ),
            linear-gradient(145deg,
            #ffe39a 0%,
            #f2c35a 22%,
            #c98a2f 52%,
            #f0c96a 78%,
            #fff0b8 100%
            );

    box-shadow:
            inset 0 0 0 2px rgba(92,61,10,.45),   /* rim */
            inset 0 -2px 3px rgba(0,0,0,.28),    /* depth */
            0 1px 1px rgba(0,0,0,.3);             /* lift */

    font-size: 0.82em;    /* fit "CZ" on one line inside the pill */
    font-weight: 900;
    letter-spacing: 0.02em;
    font-family: var(--font-display-2, system-ui);

    color: #5c3d0a;

    text-shadow:
            0 1px 0 rgba(255,255,255,.55),
            0 -1px 0 rgba(0,0,0,.35);

    vertical-align: -0.08em;
}

/*:not(.tilde-BB) */.card-graphics-img{
    border-radius: 15px;
    padding-left: 2px;
    padding-right: 2px;
    padding-top: 1px;
    padding-bottom: 1px;
    border: 1px solid black;
}
/* ── THE TYPE GLYPHS, ON PLATES OF THEIR OWN TYPE'S COLOUR ────────────────
 *
 * Six glyphs stand in the rules text where a word would, and every one of them
 * is a bright drawing: a yellow bolt, a green face, a pale fist. Four had a
 * BRIGHT plate and two had none at all -- so the bolt on a light card
 * disappeared, and the ones that were dressed were dressed in a colour close to
 * the glyph sitting on it.
 *
 * ONE RULE FOR ALL SIX: a DARK plate in that type's own hue. Dark, because
 * these drawings are light and a light drawing needs somewhere dark to stand;
 * in the type's hue, because the plate should still say which type this is
 * without being read -- an orange one is a Habitual before anybody looks at the
 * picture. And the same treatment across all six, so a sentence with three of
 * them in it reads as three marks rather than as three accidents.
 *
 * A PALE RIM RATHER THAN A BLACK ONE. The base rule outlines every glyph in
 * black, which was right against a bright plate and vanishes against a dark one
 * -- and against dark art it took the plate's edge with it, so the mark lost
 * its shape exactly where it most needed one.
 */
/* ONE PLATE WIDTH FOR ALL SIX, because the artwork is not one shape. Measured
   off the files: the bolt is 15x25 — a tall, narrow drawing — the middle four
   are square, and the evil Habitual is 533x369, half again as wide as it is
   tall. Sized by height alone the bolt's plate came out a sliver two fifths the
   width of its neighbours' and the evil Habitual's a long slab, so a sentence
   with three of them read as three different kinds of mark.
   Brought to one width with side padding rather than by sizing the image:
   padding widens the box without touching the drawing, and the alternative — a
   fixed width with object-fit — is not drawn by the rasteriser that photographs
   these cards, so it would look right on screen and print stretched. */
.card-graphics-img.plated.unction,
.card-graphics-img.plated.maturity,
.card-graphics-img.plated.resistance,
.card-graphics-img.plated.temptation,
.card-graphics-img.plated.habitual_good,
.card-graphics-img.plated.habitual_evil,
.card-graphics-img.plated.resistance_romanwar,
.card-graphics-img.plated.temptation_romanwar,
.card-graphics-img.plated.habitual_good_romanwar,
.card-graphics-img.plated.habitual_evil_romanwar {
    padding: 0.06em 0.20em;
    box-sizing: content-box;
    border-radius: 0.28em;
}
/* NO PER-GLYPH SIZE HERE ANY MORE. These were paddings measured by hand off
   each file, and they broke the first time a picture was replaced: the rule
   shrinking the evil Habitual was measured against the wide Christian drawing,
   and the Roman one is square, so the two came out different sizes side by
   side. A stylesheet cannot see the file. CardRenderer's fitTypePlates()
   measures each drawing and fits it inside one fixed box, so nothing is
   stretched and every plate is the same rectangle. The padding above is the
   starting point it refines. */

/* ONLY ON A GLYPH BEING DRAWN AS AN INLINE MARK — the .plated class, which
   fitTypePlates adds to exactly the ones it sizes as marks. Without it these
   painted every glyph of that type anywhere on the card, and the corner type
   badge came out as a pale sliver of plate with the drawing lost inside it.
   One decision, made in one place: what gets a mark's size gets a mark's paint.

   THE PLATE COLOURS, MEASURED OFF THE STROKES — which is the second time this
   has been measured and the first time against the right thing.

   The round before this sampled each glyph's MEAN luminance and gave the three
   that averaged light a dark plate. But these are line drawings: the mean is
   dominated by the pale fill inside them, while what anybody reads is the dark
   outline. Sampled properly — the 25th percentile of the opaque pixels, which
   is the ink — every one of the six is dark art, 0.00 to 0.08. On dark plates
   the handcuffs measured 1.98 and the temptation 1.25: not a colour that is
   hard to see, ink on ink.

   So all six get a PALE plate in the type's own hue with a dark rim. One rule
   for all six, which is what this wanted to be from the start; it only needed
   the right measurement to be true. 4.7x at worst, 15x at best.

   The evil pair are warm on purpose as well as by measurement: a reddish plate
   under a temptation and a light brown under the handcuffs say whose card this
   is before the drawing is read. The _romanwar variants carry the same colours
   — the other game's art is a different drawing of the same idea. */
.card-graphics-img.plated.unction    { background: #f6dfa0; }   /* 15.1x */
.card-graphics-img.plated.maturity   { background: #c7e9bb; }   /* 10.5x */
.card-graphics-img.plated.resistance,
.card-graphics-img.plated.resistance_romanwar { background: #ccd6ea; }   /*  9.4x */
.card-graphics-img.plated.temptation,
.card-graphics-img.plated.temptation_romanwar { background: #f0b3a6; }   /* 11.7x */
.card-graphics-img.plated.habitual_evil,
.card-graphics-img.plated.habitual_evil_romanwar { background: #e8bb8e; }   /*  4.7x */
.card-graphics-img.plated.habitual_good,
.card-graphics-img.plated.habitual_good_romanwar { background: #bcd8f0; }   /* 14.2x */
/* THE STONE GETS NO PLATE, having briefly had one. Giving it its own blue
   rectangle made it a separate chip sitting OUTSIDE the boost band — two blues
   in a row, one of them the wrong shape. It is not a type being named here; it
   is a qualifier on the boost beside it, so it belongs inside that band on the
   band's own ground, at the size of the other marks on the line. */
.card-graphics-img.plated.unction,
.card-graphics-img.plated.maturity,
.card-graphics-img.plated.resistance,
.card-graphics-img.plated.resistance_romanwar,
.card-graphics-img.plated.temptation,
.card-graphics-img.plated.temptation_romanwar,
.card-graphics-img.plated.habitual_evil,
.card-graphics-img.plated.habitual_evil_romanwar,
.card-graphics-img.plated.habitual_good,
.card-graphics-img.plated.habitual_good_romanwar { border: 1px solid rgba(0, 0, 0, 0.55); }

.tilde-BB .card-graphics-img {
    height: 49px;
}

/* The righteous Habitual's plate is set with the other five above. This rule
   used to give it its own, brighter one from further down the file -- two
   places deciding one colour, and the later one winning by accident of order. */

.fulltext.tallart .bible-verse {
    margin-top: 10px;
    opacity: 85%;
}
.fulltext.tallart .fun-text {
    margin-top: 14px;
    opacity: 85%;
}


.citations {
    font-size: 0.6em;
    font-style: italic;
    opacity: 70%;
}

#card-qrcode {
   display: none !important; /* forget about qr code, not important, just more work */
}

/* ── Kittens theme: photo-forward art ──────────────────────────────────
   The chr frame backgrounds (sets/back_*.png) carry an embossed emblem
   (open hand / tree / rock motif on gold, heavy textures on the colors).
   Base tallart CSS renders the art <img> at opacity .5 so that motif
   shows through the art — intended for chr, but it muddies the kitten
   photos badly. Under the renderer's .theme-kittens scope the photo is
   fully opaque (emblem hidden behind it) and the rules band keeps a
   lighter, even scrim so white rules text stays readable without
   darkening the open art above it. Other themes are untouched. */
.ch-card-root.theme-kittens .card-art img {
    /* Photo fully opaque AND un-masked so it covers the whole art box top to
       bottom. The base .card-art img fades its lower ~40% to transparent
       (mask-image) — intended so the chr frame emblem/texture bleeds into the
       art — but for kittens that let the color-frame's leaf/emboss texture
       (e.g. sets/back_Grass3.png on grass cards) show THROUGH the lower half of
       the kitten photo. Kill the fade + force opacity so the photo reads clean
       on EVERY surface (board tile, view-card, inspector/pin, dialogs). */
    opacity: 1 !important;
    -webkit-mask-image: none !important;
    mask-image: none !important;
}
/* Drop the color-frame's leaf/emboss BACKGROUND-IMAGE (sets/back_*.png) for
   kittens so nothing textured can bleed into or around the photo; the solid
   per-color background-color stays, so the card border still reads as its
   color (grass = green, fire = red, …). Scoped to kittens — chr / romanwar /
   plantlover / blockbuilding frame textures are untouched. Beats view-card.php
   inline `.ch-card-root.<color>` and game.css `.ch-card-root.<color>` rules. */
.ch-card-root.theme-kittens {
    background-image: none !important;
}
.ch-card-root.fulltext.tallart.theme-kittens .card-rules {
    /* Just enough dark scrim behind the rules text for readability over the
       now-opaque photo — the open art above stays crisp. */
    background: linear-gradient(
            to bottom,
            rgba(0, 0, 0, 0.30),
            rgba(0, 0, 0, 0.72)
    );
}


/* ── Inline Humility/Power triangle: scale WITH the rules text ─────────────
   The base .humility-box (and game.css's .ch-card-root copy) draws the green
   triangle with FIXED px borders, so after autoFitRulesText picks a large
   font the badge reads as a minuscule glyph next to the words ("Gain ▲3").
   Inside a rendered card's rules text, rebuild it in em units so it tracks
   the fitted font-size exactly, like every other inline glyph
   (.card-graphics-img height:1em). Scoped to .ch-card-root .rules-text —
   the designer preview (#card-preview) and print pipeline are untouched.
   Higher specificity (0,3,0) than game.css's .ch-card-root .humility-box
   (0,2,0), so it wins regardless of stylesheet order. */
.ch-card-root .rules-text .humility-box {
    all: unset;
    /* explicit: .rules-text-icon pins font-size to a fixed 2rem var and the
       browser keeps it despite the all:unset above — restate the inherit so
       the em borders below track the autofitted rules font. */
    font-size: inherit;
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;
    /* Visibility pass 2: the badge still read weak next to the C/D/S chips —
       grow the whole triangle (~25%) and darken the fill a step so the white
       digit carries real contrast. */
    border-left: 0.62em solid transparent;
    border-right: 0.62em solid transparent;
    border-bottom: 0.90em solid #04b371;
    /* The 0.62em borders already give the triangle its visual width; only a
       hair of margin is needed so it hugs the surrounding words like the cost
       pill / D-box / counter do (was 0.72/0.68em → big floating gaps). */
    margin: 0 0.1em;
    vertical-align: -0.16em;
}
.ch-card-root .rules-text .humility-box::before,
.ch-card-root .rules-text .humility-box::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    /* A TRIANGLE HAS ROOM ONLY AT THE BOTTOM, so it has to be wider than it
       looks to hold two characters. "-2" and "+1" are two glyphs in a shape
       that narrows to nothing, and at the old size they were squeezed into the
       middle where the shape is half as wide as the base. */
    border-left: 0.86em solid transparent;
    border-right: 0.86em solid transparent;
    border-bottom: 1.22em solid #013d22;
    left: -0.86em;
    z-index: -1;
}
.ch-card-root .rules-text .humility-box::before { top: 0; }
.ch-card-root .rules-text .humility-box::after  { top: -0.24em; }
.ch-card-root .rules-text .humility-box .humility-text {
    all: unset;
    position: absolute;
    left: 50%;
    /* LOW IN THE TRIANGLE, where it is widest. Every hundredth of an em further
       down is width the number can use. */
    top: 0.78em;
    transform: translate(-50%, -50%);
    /* THE NUMBER IS THE POINT OF THE MARK. The triangle says "humility" and the
       number says how much, and it was set smaller than the digits in the cost
       chip next to it -- a value printed at two thirds the size of the values
       around it reads as a footnote to them. */
    font-size: 0.92em;
    font-weight: 900;
    color: #fff;
    /* A THIN, DARK OUTLINE AND A TIGHT SHADOW. The old stroke was heavy enough
       at this size to close up the counter of a 2 and thicken a minus sign into
       the digit beside it; the shadow does the separating instead. */
    -webkit-text-stroke: 0.025em #00190d;
    text-shadow: 0 0 0.05em #00190d, 0 0.03em 0.05em #000, 0 0 0.16em #000;
    white-space: nowrap;
    letter-spacing: -0.04em;
}

/* Inline number boxes (C#, D#, S#, A#) inside a rendered card's rules text.
   autoFitRulesText pins .rules-text-icon font-size to a FIXED fraction
   (~0.62em) of the fitted rules font, so the pill rendered noticeably SMALLER
   than the #rot#/#ctr# graphics glyphs (height:1em / 1.15em) and the words on
   the same line ("C3 #rot#: #ctr+1#"). Track the fitted rules font instead so
   every inline element sits at the same visual height. !important beats the
   inline px pin the autofit writes; scoped to .ch-card-root .rules-text so the
   designer preview (#card-preview) and the print/fcimage pipeline are untouched. */
/* THE SAME BOXES ON THE PRINTED FACE, WHICH HAS A DIFFERENT DOM.
   This rule is what makes CX, SX and AX sit at the same height as #rot# and
   #ctr#, and it was scoped to .ch-card-root .rules-text — the board's markup.
   layouts.php builds its own card out of .slot elements and never matches that
   selector, so on the printed face the boxes kept their full 1.35em while the
   glyphs beside them stayed at 1em: a coin a third taller than the symbol it
   shares a line with.
   The editor's own preview panel marks itself .letx-scope rather than using
   slots, so it is listed too — the same reason letx.css lists both. */
.ch-card-root .rules-text .cost-box,
.ch-card-root .rules-text .draw-to-hand-box,
.ch-card-root .rules-text .discard-from-cost-zone-box,
.ch-card-root .rules-text .resist-box,
.ch-card-root .rules-text .negative-box,
.slot .cost-box,
.slot .draw-to-hand-box,
.slot .discard-from-cost-zone-box,
.slot .resist-box,
.slot .negative-box,
.letx-scope .cost-box,
.letx-scope .draw-to-hand-box,
.letx-scope .discard-from-cost-zone-box,
.letx-scope .resist-box,
.letx-scope .negative-box {
    /* 0.70em: box height = 1.35em x 0.70em = 0.945em, plus the 0.07em ring on
       each side = 1.04em outer — the same outer edge the glyph beside it now
       has in layouts.php. Changing one of these two without the other is what
       makes a coin look a third taller than the symbol it shares a line with,
       so the numbers are stated in both places and have to be moved together. */
    /* The multiplier is inside the value because this is !important: a later
       rule could not beat it, and "D2{3x}" would do nothing. */
    font-size: calc(0.70em * var(--mark-x, 1)) !important;
    /* CENTRED ON THE CAP, not sat on the baseline. The layout box is 0.945em
       and the cap's middle is 0.35em up, so -0.12em = 0.35 - 0.945/2. The ring
       is box-shadow and sits outside layout, evenly on both sides, so centring
       the box centres what the eye sees too. */
    vertical-align: -0.12em;
}

/* AND THE RING SCALES WITH THE BOX. The white rim was a flat 3px, which is a
   fixed thickness around a box measured in em — so the smaller the rules text
   got, the heavier the rim looked, and at the size a full card sets it read as
   a thick white border rather than an edge. */
.slot .rules-text-icon,
.letx-scope .rules-text-icon {
    box-shadow: 0 0 0 0.07em #ffffff, 0 0.07em 0 rgba(0, 0, 0, 0.3);
}

/* ── Kittens: per-card art credit in the footer ────────────────────────────
   Populated by CardRenderer from theme-kittens-images/art_credits.json for
   theme=kittens only; empty (display:none) everywhere else, so chr and the
   other themes render byte-identically. Tiny + low-opacity so it never
   competes with the copyright/number line. */
.card-footer .art-credit:empty { display: none; }
.card-footer .art-credit {
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1.5em;
    text-align: center;
    font-size: 0.85rem;
    opacity: 0.55;
    line-height: 1;
    pointer-events: none;
}


/* ══════════════════════════════════════════════════════════════════════════
   CARD FRAME DECORATIONS  (Task #26 — design + render; editor picker deferred)
   ───────────────────────────────────────────────────────────────────────────
   Three restrained, self-contained (pure-CSS + inline-SVG data-URI) treatments
   applied as sensible DEFAULTS to every rendered card face, on BOTH render
   roots: .ch-card-root (board / view-card / catalog / html2canvas export) and
   #card-preview (designer live preview).  No third-party assets; no JS.

     A. Inset metallic frame line + bevel + soft inner glow, ELEMENT-TINTED
        (gold / fire-ember / grass / ice / stone).  Lives entirely in the 24px
        frame margin, so it never touches art, rules text, cost badge or footer.
     B. A refined title-plate hairline/sheen under the title bar.
     C. Two top-corner metallic flourishes, THEME-KEYED (chr cross-stud,
        kittens paw, romanwar laurel, plantlover leaf, blockbuilding hex-bolt).
        Only the TOP corners are decorated: the bottom-left corner is owned by
        the cost badge and the bottom band by the footer.  The flourishes sit at
        z-index 2 — BELOW the title bar (z3), cost badge (z3) and footer (z999) —
        so those always paint on top and legibility can never regress.

   Everything coexists with the per-theme art/text split (.has-art-split /
   --art-split, 5847a667) and the bottom-band + top scrim + cost-badge z-index
   work (632eefa8): the frame line sits under .card-inner content and the
   flourishes sit under the title/cost/footer, so none of that is disturbed.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Element/colour accent palette (drives frame line + glow tint) ────────── */
.ch-card-root, #card-preview {
    --frame-accent: #cda63a;                 /* default: warm gold  */
    --frame-hi:   rgba(255,246,214,0.75);    /* top bevel highlight */
    --frame-lo:   rgba(45,30,0,0.42);        /* bottom bevel shadow */
    --frame-glow: rgba(205,166,58,0.22);     /* soft inner glow     */
    --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 3 L37 20 L20 37 L3 20 Z' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M20 9 V31 M9 20 H31' stroke='%23f7edc4' stroke-width='3.2' stroke-linecap='round' opacity='0.9'/%3E%3Cpath d='M20 9 V31 M9 20 H31' stroke='%235a3f0a' stroke-width='1.1' stroke-linecap='round'/%3E%3C/svg%3E");             /* default motif = cross-stud */
}
.ch-card-root.gold,  #card-preview.gold  {
    --frame-accent:#dcb845; --frame-hi:rgba(255,248,216,.82); --frame-lo:rgba(70,48,0,.48); --frame-glow:rgba(220,184,69,.26); }
.ch-card-root.fire,  #card-preview.fire,
.ch-card-root.firehabitual, #card-preview.firehabitual {
    --frame-accent:#c9633a; --frame-hi:rgba(255,212,178,.72); --frame-lo:rgba(52,8,0,.55); --frame-glow:rgba(198,72,40,.26); }
.ch-card-root.grass, #card-preview.grass {
    --frame-accent:#3f9e4a; --frame-hi:rgba(214,246,206,.72); --frame-lo:rgba(6,44,10,.5);  --frame-glow:rgba(70,168,80,.24); }
.ch-card-root.ice,   #card-preview.ice   {
    --frame-accent:#4a86d6; --frame-hi:rgba(206,228,255,.75); --frame-lo:rgba(0,26,60,.5);   --frame-glow:rgba(74,134,214,.24); }
.ch-card-root.stone, #card-preview.stone {
    --frame-accent:#b3bcc6; --frame-hi:rgba(244,248,252,.8);  --frame-lo:rgba(24,30,38,.5);  --frame-glow:rgba(179,188,198,.22); }

/* ── A + B.  Inset metallic frame line, bevel, inner glow ────────────────────
   No z-index → paints UNDER .card-inner, so it shows only in the frame margin
   and can never wash over art or text.  Coordinates are the 750×1100 card
   space; scales down cleanly with --ch-scale on the board (invisibly small on
   thumbnails, which is fine). */
.ch-card-root::before,
#card-preview::before {
    content: "";
    position: absolute;
    inset: 13px;
    border-radius: 33px;
    pointer-events: none;
    /* --frame-deco-opacity: per-theme Card Designer frame-line strength (default 1). */
    opacity: var(--frame-deco-opacity, 1);
    /* --frame-thickness: per-theme Card Designer rule-width multiplier (default 1). */
    box-shadow:
        inset 0 0 0 calc(2px * var(--frame-thickness, 1)) var(--frame-accent),   /* crisp metallic rule */
        inset 0 0 0 calc(3.5px * var(--frame-thickness, 1)) rgba(0,0,0,0.28),    /* thin shadow just out */
        inset 0 2.5px 5px var(--frame-hi),          /* top bevel highlight    */
        inset 0 -3px 7px var(--frame-lo),           /* bottom bevel shadow    */
        inset 0 0 24px var(--frame-glow);           /* soft element inner glow*/
}

/* B. Title-plate refinement — a hairline + faint sheen directly under the
   title bar so the name sits on a subtle plate.  Kept inside the title bar's
   own box (which already has z-index 3), purely decorative. */
.ch-card-root .card-title-bar::after,
#card-preview .card-title-bar::after {
    content: "";
    position: absolute;
    left: 6%;
    right: 6%;
    bottom: -6px;
    height: 3px;
    border-radius: 3px;
    pointer-events: none;
    background: linear-gradient(90deg,
        rgba(0,0,0,0) 0%,
        var(--frame-accent) 22%,
        var(--frame-hi) 50%,
        var(--frame-accent) 78%,
        rgba(0,0,0,0) 100%);
    opacity: 0.7;
}

/* ── C.  Two top-corner metallic flourishes (theme-keyed) ────────────────────
   Same symmetric SVG placed in both top corners.  z-index 2 keeps it below the
   title bar / cost badge / footer, so it only ever shows in the corner gaps. */
.ch-card-root::after,
#card-preview::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    /* --corner-deco-opacity: per-theme Card Designer corner-flourish strength (default 1). */
    opacity: var(--corner-deco-opacity, 1);
    background-image: var(--corner-flourish), var(--corner-flourish);
    background-repeat: no-repeat, no-repeat;
    background-size: 52px 52px, 52px 52px;
    background-position: top 11px left 11px, top 11px right 11px;
}

/* Theme-keyed corner motif (root carries theme-<x>; #card-preview → chr default) */
.ch-card-root.theme-kittens::after       { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cellipse cx='20' cy='25' rx='9.5' ry='8' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.3'/%3E%3Ccircle cx='10.5' cy='15' r='3.5' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3Ccircle cx='16.5' cy='9.5' r='3.6' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3Ccircle cx='23.5' cy='9.5' r='3.6' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3Ccircle cx='29.5' cy='15' r='3.5' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3C/svg%3E"); }
.ch-card-root.theme-romanwar::after      { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cg fill='none' stroke='url(%23g)' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M20 36 C10 33 6.5 21 12 8'/%3E%3Cpath d='M20 36 C30 33 33.5 21 28 8'/%3E%3C/g%3E%3Cg fill='url(%23g)' stroke='%236b4e12' stroke-width='0.6'%3E%3Cellipse cx='9.5' cy='16' rx='3.1' ry='1.7' transform='rotate(-40 9.5 16)'/%3E%3Cellipse cx='11' cy='24' rx='3.1' ry='1.7' transform='rotate(-15 11 24)'/%3E%3Cellipse cx='15' cy='31' rx='3.1' ry='1.7' transform='rotate(20 15 31)'/%3E%3Cellipse cx='30.5' cy='16' rx='3.1' ry='1.7' transform='rotate(40 30.5 16)'/%3E%3Cellipse cx='29' cy='24' rx='3.1' ry='1.7' transform='rotate(15 29 24)'/%3E%3Cellipse cx='25' cy='31' rx='3.1' ry='1.7' transform='rotate(-20 25 31)'/%3E%3C/g%3E%3C/svg%3E"); }
.ch-card-root.theme-plantlover::after    { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 4 C31 13 31 28 20 37 C9 28 9 13 20 4 Z' fill='url(%23g)' stroke='%233f5a1e' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M20 7 V34' stroke='%233f5a1e' stroke-width='1.3'/%3E%3Cpath d='M20 15 L14 12 M20 15 L26 12 M20 22 L13 18 M20 22 L27 18 M20 29 L15 26 M20 29 L25 26' stroke='%233f5a1e' stroke-width='1'/%3E%3C/svg%3E"); }
.ch-card-root.theme-blockbuilding::after { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 5 L32.9 12.5 L32.9 27.5 L20 35 L7.1 27.5 L7.1 12.5 Z' fill='url(%23g)' stroke='%234a4a4a' stroke-width='1.6' stroke-linejoin='round'/%3E%3Ccircle cx='20' cy='20' r='5.4' fill='none' stroke='%234a4a4a' stroke-width='1.6'/%3E%3Ccircle cx='20' cy='20' r='2.2' fill='%234a4a4a'/%3E%3C/svg%3E"); }

/* ══════════════════════════════════════════════════════════════════════════
   ADMIN-SELECTABLE FRAME OVERRIDES  (Task #32 — editor Frame picker)
   ───────────────────────────────────────────────────────────────────────────
   The default frame treatment above is AUTOMATIC (element-tinted metallic rule
   + theme-keyed corner flourishes).  An admin can OVERRIDE it per theme via the
   card editor's Frame picker; the choice is stored in opts.frame_style /
   opts.frame_corner ({ "<theme>": "<name>" } maps) and CardRenderer.build adds
   `frame-style-<name>` / `frame-corner-<motif>` to `.ch-card-root`.  Absent /
   "auto" → the automatic default (back-compat).  These rules sit AFTER the
   theme-keyed motif block so an explicit corner choice always wins.  They only
   touch the ::before frame rule and ::after corner layer (both pointer-events
   none, in the frame margin / corners) — never art, rules text, cost badge or
   footer, so legibility can't regress. ────────────────────────────────────── */

/* Minimal / none — a clean face: drop the metallic rule, corner flourishes and
   title-plate sheen entirely. */
.ch-card-root.frame-style-none::before { box-shadow: none; }
.ch-card-root.frame-style-none::after  { background-image: none; }
.ch-card-root.frame-style-none .card-title-bar::after { display: none; }

/* Metallic (element) — keep the element-tinted rule + bevel + glow, but drop
   the corner flourishes for a cleaner metallic-only look. */
.ch-card-root.frame-style-metallic::after { background-image: none; }

/* Gold ornate — force the warm-gold accent regardless of element colour, a
   richer double rule, and the gold cross-diamond corners. The vars sit at the
   same specificity as the .fire/.grass/… element tints but come later, so they
   win; the corner override below re-supplies the motif. */
.ch-card-root.frame-style-gold {
    --frame-accent:#dcb845; --frame-hi:rgba(255,248,216,.85);
    --frame-lo:rgba(70,48,0,.5); --frame-glow:rgba(220,184,69,.30);
}
.ch-card-root.frame-style-gold::before {
    box-shadow:
        inset 0 0 0 2px var(--frame-accent),         /* inner crisp gold rule  */
        inset 0 0 0 3.5px rgba(0,0,0,0.30),          /* shadow gap             */
        inset 0 0 0 5px var(--frame-accent),         /* outer gold rule (double)*/
        inset 0 2.5px 6px var(--frame-hi),           /* top bevel highlight    */
        inset 0 -3px 8px var(--frame-lo),            /* bottom bevel shadow    */
        inset 0 0 26px var(--frame-glow);            /* soft gold inner glow   */
}
.ch-card-root.frame-style-gold::after {
    background-image: var(--corner-flourish), var(--corner-flourish);
    --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 3 L37 20 L20 37 L3 20 Z' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M20 9 V31 M9 20 H31' stroke='%23f7edc4' stroke-width='3.2' stroke-linecap='round' opacity='0.9'/%3E%3Cpath d='M20 9 V31 M9 20 H31' stroke='%235a3f0a' stroke-width='1.1' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ── Corner motif override (independent of the frame-style choice) ────────────
   Re-asserts the ::after background so a motif shows even when a frame style
   (metallic / none) suppressed it; frame-corner-none forces the corners off. */
.ch-card-root.frame-corner-cross::after,
.ch-card-root.frame-corner-paw::after,
.ch-card-root.frame-corner-laurel::after,
.ch-card-root.frame-corner-leaf::after,
.ch-card-root.frame-corner-hex::after {
    background-image: var(--corner-flourish), var(--corner-flourish);
}
.ch-card-root.frame-corner-none::after   { background-image: none; }
.ch-card-root.frame-corner-cross::after  { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 3 L37 20 L20 37 L3 20 Z' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M20 9 V31 M9 20 H31' stroke='%23f7edc4' stroke-width='3.2' stroke-linecap='round' opacity='0.9'/%3E%3Cpath d='M20 9 V31 M9 20 H31' stroke='%235a3f0a' stroke-width='1.1' stroke-linecap='round'/%3E%3C/svg%3E"); }
.ch-card-root.frame-corner-paw::after    { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cellipse cx='20' cy='25' rx='9.5' ry='8' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.3'/%3E%3Ccircle cx='10.5' cy='15' r='3.5' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3Ccircle cx='16.5' cy='9.5' r='3.6' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3Ccircle cx='23.5' cy='9.5' r='3.6' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3Ccircle cx='29.5' cy='15' r='3.5' fill='url(%23g)' stroke='%236b4e12' stroke-width='1.1'/%3E%3C/svg%3E"); }
.ch-card-root.frame-corner-laurel::after { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cg fill='none' stroke='url(%23g)' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M20 36 C10 33 6.5 21 12 8'/%3E%3Cpath d='M20 36 C30 33 33.5 21 28 8'/%3E%3C/g%3E%3Cg fill='url(%23g)' stroke='%236b4e12' stroke-width='0.6'%3E%3Cellipse cx='9.5' cy='16' rx='3.1' ry='1.7' transform='rotate(-40 9.5 16)'/%3E%3Cellipse cx='11' cy='24' rx='3.1' ry='1.7' transform='rotate(-15 11 24)'/%3E%3Cellipse cx='15' cy='31' rx='3.1' ry='1.7' transform='rotate(20 15 31)'/%3E%3Cellipse cx='30.5' cy='16' rx='3.1' ry='1.7' transform='rotate(40 30.5 16)'/%3E%3Cellipse cx='29' cy='24' rx='3.1' ry='1.7' transform='rotate(15 29 24)'/%3E%3Cellipse cx='25' cy='31' rx='3.1' ry='1.7' transform='rotate(-20 25 31)'/%3E%3C/g%3E%3C/svg%3E"); }
.ch-card-root.frame-corner-leaf::after   { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 4 C31 13 31 28 20 37 C9 28 9 13 20 4 Z' fill='url(%23g)' stroke='%233f5a1e' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M20 7 V34' stroke='%233f5a1e' stroke-width='1.3'/%3E%3Cpath d='M20 15 L14 12 M20 15 L26 12 M20 22 L13 18 M20 22 L27 18 M20 29 L15 26 M20 29 L25 26' stroke='%233f5a1e' stroke-width='1'/%3E%3C/svg%3E"); }
.ch-card-root.frame-corner-hex::after    { --corner-flourish: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Cdefs%3E%3CradialGradient id='g' cx='38%25' cy='32%25' r='75%25'%3E%3Cstop offset='0' stop-color='%23fbf1c9'/%3E%3Cstop offset='0.5' stop-color='%23d9b64a'/%3E%3Cstop offset='1' stop-color='%238f6e1c'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M20 5 L32.9 12.5 L32.9 27.5 L20 35 L7.1 27.5 L7.1 12.5 Z' fill='url(%23g)' stroke='%234a4a4a' stroke-width='1.6' stroke-linejoin='round'/%3E%3Ccircle cx='20' cy='20' r='5.4' fill='none' stroke='%234a4a4a' stroke-width='1.6'/%3E%3Ccircle cx='20' cy='20' r='2.2' fill='%234a4a4a'/%3E%3C/svg%3E"); }

/* ══════════════════════════════════════════════════════════════════════════
   CARD DESIGNER — THEME-WIDE FRAME STYLES + THICKNESS  (Task #49 P4)
   ───────────────────────────────────────────────────────────────────────────
   Applied as `frame-dsg-<style>` on the card root by CardRenderer.applyThemeDesign
   (theme-wide; supersedes the automatic + per-card frame). All are decorative
   ::before rules (pointer-events none, in the frame margin) — they never touch
   art / rules text / cost badge / footer, so legibility can't regress. Rule
   widths scale with --frame-thickness (default 1). The accent tint reuses the
   element-keyed --frame-accent / --frame-hi / --frame-lo / --frame-glow vars
   (or the Designer's accent-color override). Original CSS only.
   ══════════════════════════════════════════════════════════════════════════ */
.ch-card-root[class*="frame-dsg-"]::before { --fw: calc(2px * var(--frame-thickness, 1)); }

.ch-card-root.frame-dsg-none::before     { box-shadow: none; }
.ch-card-root.frame-dsg-hairline::before { box-shadow: inset 0 0 0 var(--fw) var(--frame-accent); }
.ch-card-root.frame-dsg-thin::before {
    box-shadow: inset 0 0 0 calc(var(--fw) * 1.5) var(--frame-accent),
                inset 0 0 8px var(--frame-glow);
}
.ch-card-root.frame-dsg-double::before {
    box-shadow: inset 0 0 0 var(--fw) var(--frame-accent),
                inset 0 0 0 calc(var(--fw) * 2) rgba(0,0,0,0.35),
                inset 0 0 0 calc(var(--fw) * 3) var(--frame-accent);
}
.ch-card-root.frame-dsg-beveled::before {
    box-shadow: inset 0 0 0 calc(var(--fw) * 1.5) var(--frame-accent),
                inset 0 3px 8px var(--frame-hi),
                inset 0 -4px 10px var(--frame-lo);
}
.ch-card-root.frame-dsg-inlaid::before {
    box-shadow: inset 0 0 0 var(--fw) rgba(0,0,0,0.45),
                inset 0 0 0 calc(var(--fw) * 2.4) var(--frame-accent),
                inset 0 0 0 calc(var(--fw) * 3) rgba(0,0,0,0.4);
}
.ch-card-root.frame-dsg-embossed::before {
    box-shadow: inset 0 0 0 var(--fw) var(--frame-accent),
                inset 2px 2px 6px var(--frame-hi),
                inset -2px -2px 6px var(--frame-lo),
                inset 0 0 20px var(--frame-glow);
}
.ch-card-root.frame-dsg-heavy::before {
    box-shadow: inset 0 0 0 calc(var(--fw) * 3.5) var(--frame-accent),
                inset 0 0 0 calc(var(--fw) * 4) rgba(0,0,0,0.4);
}
.ch-card-root.frame-dsg-ornate::before {
    box-shadow: inset 0 0 0 var(--fw) var(--frame-accent),
                inset 0 0 0 calc(var(--fw) * 1.8) rgba(0,0,0,0.3),
                inset 0 0 0 calc(var(--fw) * 2.6) var(--frame-accent),
                inset 0 2px 6px var(--frame-hi),
                inset 0 -3px 8px var(--frame-lo),
                inset 0 0 26px var(--frame-glow);
}
.ch-card-root.frame-dsg-artdeco::before {
    border-radius: 6px;
    box-shadow: inset 0 0 0 calc(var(--fw) * 1.5) var(--frame-accent),
                inset 0 0 0 calc(var(--fw) * 4) rgba(0,0,0,0.28),
                inset 0 0 0 calc(var(--fw) * 5) var(--frame-accent);
}
.ch-card-root.frame-dsg-rope::before {
    box-shadow: none;
    border: calc(var(--fw) * 2) dashed var(--frame-accent);
}

/* ================================================================
   LANDSCAPE LAYOUT  (Card Designer · orientation = "landscape")
   ----------------------------------------------------------------
   CardRenderer adds `.layout-landscape` to the card root when a
   theme's design sets layout=landscape. Everything here is scoped to
   that class, so PORTRAIT cards (no class) are byte-for-byte unchanged.
   Arrangement matches the reference sketch:
     • type icon  → top-left circle
     • card title → runs VERTICALLY down the left edge
     • art        → the large centre/right area
     • rules band → overlays the bottom of the art
     • cost badge → bottom-right
   The wide box (swap the 750×1050 portrait footprint for a landscape
   one) is applied ONLY inside the editor preview (`.ace-card-render`)
   so the in-game board/hand geometry — which assumes portrait — is not
   disturbed. In-game landscape is a follow-up once the face is signed
   off. `--lsw`/`--lsh` name the landscape inner box dimensions.
   ================================================================ */
.ace-card-render .layout-landscape {
    --lsw: 1050px;
    --lsh: 760px;
    width: var(--lsw) !important;
    height: calc(var(--lsh) + 50px) !important;
}

/* Inner becomes a positioned landscape canvas; children are pinned. */
.layout-landscape.fulltext.tallart .card-inner,
.layout-landscape .card-inner {
    position: absolute !important;
    inset: 24px !important;
    left: 24px !important;
    height: auto !important;
    display: block !important;
    padding: 18px !important;
}

/* Type icon → top-left circle (over the vertical title's start). */
.layout-landscape .card-title-bar {
    position: static !important;
    margin: 0 !important;
    display: block !important;
}
.layout-landscape .card-type-tag {
    position: absolute !important;
    left: 6px !important;
    top: 6px !important;
    right: auto !important;
    width: 120px !important;
    height: 120px !important;
    border-radius: 50% !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    z-index: 6 !important;
}

/* Card title → vertical, reading bottom-to-top, hugging the left edge
   under the type circle. writing-mode + rotate gives the sketch's look;
   nowrap is dropped so a long name can wrap into a second column. */
.layout-landscape .card-title-pill {
    position: absolute !important;
    left: 10px !important;
    top: 140px !important;
    bottom: 70px !important;
    max-width: none !important;
    width: auto !important;
    writing-mode: vertical-rl !important;
    transform: rotate(180deg) !important;
    transform-origin: center !important;
    white-space: normal !important;
    overflow: hidden !important;
    text-overflow: clip !important;
    text-align: start !important;
    display: flex !important;
    align-items: flex-start !important;
    z-index: 5 !important;
}

/* Art → the big centre/right area, leaving a ~130px title gutter left. */
.layout-landscape.fulltext.tallart .card-art,
.layout-landscape .card-art {
    position: absolute !important;
    left: 140px !important;
    right: 12px !important;
    top: 12px !important;
    bottom: 12px !important;
    width: auto !important;
    height: auto !important;
    max-height: none !important;
    margin: 0 !important;
    border-radius: 16px !important;
    z-index: 1 !important;
}
.layout-landscape .card-art img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
}

/* Rules band → overlays the bottom slice of the art (legible scrim). */
.layout-landscape.fulltext.tallart .card-rules,
.layout-landscape .card-rules {
    position: absolute !important;
    left: 140px !important;
    right: 12px !important;
    bottom: 12px !important;
    top: auto !important;
    height: auto !important;
    max-height: 42% !important;
    padding: 14px 16px !important;
    border-radius: 0 0 16px 16px !important;
    background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,.72) 45%, rgba(0,0,0,.88) 100%) !important;
    color: #fff !important;
    z-index: 3 !important;
}

/* Cost badge → bottom-right corner, above the art. */
.layout-landscape .cost-badge {
    position: absolute !important;
    right: 14px !important;
    bottom: 14px !important;
    left: auto !important;
    top: auto !important;
    z-index: 7 !important;
}

/* Footer / copyright rides along the very bottom-left, clear of the art. */
.layout-landscape.fulltext.tallart .card-footer,
.layout-landscape .card-footer {
    position: absolute !important;
    left: 140px !important;
    right: auto !important;
    bottom: 2px !important;
    text-align: left !important;
    z-index: 4 !important;
}

/* ================================================================
   TYPE-ICON CIRCLE  +  TITLE DESIGN TREATMENTS  (Card Designer)
   ----------------------------------------------------------------
   Opt-in via root classes set by CardRenderer.applyThemeDesign:
     .type-emblem-circle      → a backing disc beneath the type icon (inside)
     .type-emblem-protrude    → a disc/emblem that STICKS OUT over the corner
     .title-style-<name>      → alternate title looks (banner/plate/…)
   Default (no class) leaves the classic pill + bare type tag intact.
   --type-emblem-color = ring/accent color (default gold).
   ================================================================ */

/* Circular disc beneath the type icon (Unction, etc.), inside the card. */
.type-emblem-circle .card-type-tag {
    background: radial-gradient(circle at 50% 38%, #ffffff 0%, #ececec 70%, #d7d7d7 100%);
    border-radius: 50%;
    width: 92px;
    height: 92px;
    min-width: 92px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0,0,0,.35), inset 0 0 0 3px rgba(0,0,0,.10);
    border: 3px solid var(--type-emblem-color, #cda63a);
    overflow: hidden;
}
.type-emblem-circle .card-type-icon-img {
    width: 72%;
    height: 72%;
    object-fit: contain;
}

/* Emblem that STICKS OUT over the top-right corner of the card. The root/inner
   don't clip (overflow visible), so negative offsets + a high z-index let a
   ringed disc overhang the corner and sit on top of the frame — like a wax
   seal / medallion. */
.type-emblem-protrude .card-type-tag {
    position: absolute;
    top: -44px;            /* rise up through the top edge */
    right: -26px;          /* poke out past the right edge */
    width: 132px;
    height: 132px;
    min-width: 132px;
    padding: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: radial-gradient(circle at 50% 36%, #ffffff 0%, #f0f0f0 62%, #d9d9d9 100%);
    border: 5px solid var(--type-emblem-color, #cda63a);
    box-shadow: 0 6px 16px rgba(0,0,0,.55), 0 0 0 2px rgba(0,0,0,.25);
    overflow: hidden;
    z-index: 20;
}
.type-emblem-protrude .card-type-icon-img {
    width: 70%;
    height: 70%;
    object-fit: contain;
}

/* ── Title design treatments — all target the title pill ── */
/* Banner: a full-width bar across the title row. */
.title-style-banner .card-title-pill {
    max-width: 100%;
    width: 100%;
    border-radius: 4px;
    padding: 8px 18px;
    background: linear-gradient(180deg, rgba(0,0,0,.72), rgba(0,0,0,.5));
    color: #fff;
    box-shadow: 0 3px 0 rgba(0,0,0,.35);
    letter-spacing: .01em;
}
/* Engraved plate: metallic slab with an inset/embossed feel. */
.title-style-plate .card-title-pill {
    background: linear-gradient(180deg, #f4f0e4, #cfc7b0);
    color: #2a2418;
    border-radius: 8px;
    padding: 7px 20px;
    letter-spacing: .04em;
    text-shadow: 0 1px 0 rgba(255,255,255,.6);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.8), inset 0 -2px 3px rgba(0,0,0,.25), 0 2px 4px rgba(0,0,0,.3);
    border: 1px solid rgba(0,0,0,.25);
}
/* Ribbon: notched-end banner via clip-path. */
.title-style-ribbon .card-title-pill {
    max-width: 92%;
    border-radius: 0;
    padding: 8px 30px;
    background: linear-gradient(180deg, #b23a2e, #7c2018);
    color: #fff;
    box-shadow: 0 3px 6px rgba(0,0,0,.35);
    clip-path: polygon(12px 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 12px 100%, 0 50%);
}
/* Underline only: no plate, just a rule beneath the text. */
.title-style-underline .card-title-pill {
    background: transparent;
    border-radius: 0;
    padding: 4px 6px 8px;
    box-shadow: none;
    border-bottom: 3px solid currentColor;
}
/* Outline text: transparent fill, stroked glyphs. */
.title-style-outline .card-title-pill {
    background: transparent;
    box-shadow: none;
    color: #fff;
    -webkit-text-stroke: 1px rgba(0,0,0,.85);
    text-shadow: 0 2px 4px rgba(0,0,0,.6);
    padding: 4px 10px;
}
/* Vertical: run the title down the left side (works in portrait too). It is
   MOVEABLE like every other element — the Designer's Title X / Y / Size sliders
   feed --title-dx/dy/scale, applied here so the vertical title translates from
   its left-edge home position just like the horizontal title does. */
.title-style-vertical .card-title-bar {
    position: absolute;
    left: 2px;
    top: 90px;
    bottom: 90px;
    margin: 0;
    display: block;
    z-index: 5;
    transform: translate(var(--title-dx, 0px), var(--title-dy, 0px)) scale(var(--title-scale, 1));
    transform-origin: top left;
}
.title-style-vertical .card-title-pill {
    writing-mode: vertical-rl;
    /* rotate is composed with the bar's translate/scale above (separate element)
       so moving/scaling the title still works. */
    transform: rotate(180deg);
    max-width: none;
    white-space: normal;
    padding: 14px 6px;
}

/* ============================================================================
   PER-THEME BACKGROUND PANEL (chr + romanwar)
   ==========================================================================*/
.theme-bg-panel {
    border: 1px solid #444;
    border-radius: 8px;
    padding: 10px 12px;
    background: #1c1c1c;
}
.theme-bg-panel > label { display: block; margin-bottom: 8px; }
.theme-bg-panel small { color: #9a9a9a; font-weight: 400; }

.tbg-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}
.tbg-theme-tabs { display: inline-flex; gap: 4px; }
.tbg-theme-tab {
    background: #2a2a2a;
    color: #ddd;
    border: 1px solid #555;
    border-radius: 6px;
    padding: 5px 12px;
    cursor: pointer;
    font-size: 0.9rem;
}
.tbg-theme-tab.active {
    background: #3ba96c;
    border-color: #3ba96c;
    color: #fff;
}
.tbg-cat { color: #ccc; font-size: 0.9rem; }
.tbg-cat b { color: #ffd479; }

.tbg-body { display: flex; gap: 12px; align-items: flex-start; }

.tbg-preview {
    flex: 0 0 96px;
    width: 96px;
    height: 132px;
    border: 1px solid #555;
    border-radius: 6px;
    overflow: hidden;
    background: #111;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}
.tbg-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tbg-thumb-empty { color: #777; font-size: 0.72rem; padding: 6px; line-height: 1.3; }

.tbg-controls { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.tbg-controls .tbg-line { display: flex; flex-direction: column; gap: 3px; }
.tbg-controls label { font-size: 0.85rem; color: #ccc; }
.tbg-toggle { display: flex; align-items: center; gap: 6px; font-size: 0.9rem; cursor: pointer; }
.tbg-controls select,
.tbg-controls textarea {
    background: #262626;
    color: #eee;
    border: 1px solid #555;
    border-radius: 5px;
    padding: 5px 7px;
    font-size: 0.85rem;
    width: 100%;
}
.tbg-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.tbg-actions button {
    background: #2a2a2a;
    color: #eee;
    border: 1px solid #666;
    border-radius: 6px;
    padding: 6px 12px;
    cursor: pointer;
    font-size: 0.88rem;
}
.tbg-actions button:hover { background: #333; border-color: #888; }
#tbgGenBtn { border-color: #3ba96c; }
#tbgGenBtn:hover { background: #2f8855; }

.tbg-status { font-size: 0.82rem; min-height: 1em; color: #aaa; }
.tbg-status.tbg-ok  { color: #7fdc8f; }
.tbg-status.tbg-err { color: #e88; }

/* When a theme bg image is applied, it is painted via inline background-image;
   ensure it covers and overrides the class PNG cleanly. */
#card-preview.has-theme-bg,
#card-preview-alt.has-theme-bg {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* Generation progress bar */
.tbg-progress { display: flex; align-items: center; gap: 8px; margin-top: 2px; }
.tbg-track {
    position: relative;
    flex: 1;
    height: 8px;
    background: #333;
    border-radius: 4px;
    overflow: hidden;
}
.tbg-progress-bar {
    height: 100%;
    width: 0;
    background: linear-gradient(90deg, #3ba96c, #7fdc8f);
    border-radius: 4px;
    transition: width 0.3s ease;
}
.tbg-progress-bar.indeterminate {
    width: 35% !important;
    position: absolute;
    left: 0;
    animation: tbg-indet 1.1s ease-in-out infinite;
}
@keyframes tbg-indet {
    0%   { left: -35%; }
    100% { left: 100%; }
}
.tbg-progress-label { font-size: 0.78rem; color: #bbb; white-space: nowrap; min-width: 78px; }
.tbg-actions button:disabled { opacity: 0.5; cursor: default; }

/* Card Styling panel (rules box + title FX) */
#cardFxPanel .cfx-row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.cfx-field { flex: 1; min-width: 160px; display: flex; flex-direction: column; gap: 3px; }
.cfx-field label { font-size: 0.85rem; color: #ccc; }
.cfx-field select {
    background: #262626; color: #eee; border: 1px solid #555;
    border-radius: 5px; padding: 6px 7px; font-size: 0.85rem; width: 100%;
}
.cfx-reset {
    background: #2a2a2a; color: #eee; border: 1px solid #666;
    border-radius: 6px; padding: 7px 12px; cursor: pointer; font-size: 0.85rem;
}
.cfx-reset:hover { background: #333; border-color: #888; }
#titleFxCount { color: #888; font-weight: 400; }

/* Generated-background history gallery */
.tbg-gallery-wrap { margin-top: 10px; border-top: 1px solid #3a3a3a; padding-top: 8px; }
.tbg-gallery-head {
    display: flex; align-items: center; justify-content: space-between;
    font-size: 0.85rem; color: #ccc; margin-bottom: 6px;
}
.tbg-gallery-head small { color: #8f8f8f; }
.tbg-gallery-count { color: #ffd479; font-size: 0.8rem; }
.tbg-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
    gap: 6px;
    max-height: 210px;
    overflow-y: auto;
}
.tbg-gallery-empty { color: #777; font-size: 0.8rem; padding: 4px 0; grid-column: 1 / -1; }
.tbg-gcell {
    position: relative;
    aspect-ratio: 3 / 4;
    border: 1px solid #555;
    border-radius: 5px;
    overflow: hidden;
    background: #111;
}
.tbg-gcell img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: pointer; }
.tbg-gcell:hover { border-color: #3ba96c; }
.tbg-gdel {
    position: absolute; top: 2px; right: 2px;
    width: 18px; height: 18px; line-height: 15px; text-align: center;
    padding: 0; border: none; border-radius: 50%;
    background: rgba(0,0,0,.6); color: #fff; font-size: 14px; cursor: pointer;
    opacity: 0; transition: opacity .15s;
}
.tbg-gcell:hover .tbg-gdel { opacity: 1; }
.tbg-gdel:hover { background: #c0392b; }


/* A shorthand token whose icon is missing falls back to its own words (see
   CardRenderer ICON_FALLBACK_WORD). Styled to read the way the icon would have
   — a small emphasised chip inside the sentence, not a gap. */
.card-graphics-word {
    display: inline-block;
    padding: 0 .28em;
    margin: 0 .08em;
    border-radius: .25em;
    background: rgba(0, 0, 0, .07);
    font-weight: 700;
    font-size: .92em;
    white-space: nowrap;
}

/* A COST PAID ALONE. The same green box -- it is a cost and has to read as one
   first -- with a pale double rim around it: one player, fenced off, rather
   than a pool several may add to. A border and not a colour, because the
   colours on a cost already mean something else. */
.rules-text-icon.cost-box.cost-alone {
    box-shadow: 0 0 0 0.06em rgba(255,255,255,0.92), 0 0 0 0.13em rgba(0,0,0,0.55);
    outline: none;
}

/* "1-SOURCE" ACROSS THE BOTTOM OF AN ALONE COST. The rim says it to somebody
   who already knows what the rim means; the word says it to everybody else.
   Inside the box's own footprint, like the boost captions, so it cannot push
   the line apart -- and weighted rather than enlarged, which is what survives
   the rasteriser at this size. */
.cost-alone-stack { position: relative; display: inline-block; line-height: 0; }
/* UNDER THE BOX, NOT OVER IT. The badge was centred on the box and covering
   the number -- and the number is the cost, which is the thing being read. It
   hangs off the bottom edge now and is shorter: "1-src" says the same as
   "1-SOURCE" in half the width, and what the badge has to do is remind, not
   explain. The stack has no height of its own, so hanging below costs the
   line nothing. */
.cost-alone-stack .cost-alone-tag {
    position: absolute;
    left: 50%;
    /* Clear of the box by a hair more, and slightly see-through: it is a
       reminder sitting on the card's own art, and a solid white plate reads as
       part of the card rather than as a note on it. */
    bottom: -1.2em;
    opacity: 0.7;
    transform: translateX(-50%);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.26em;
    font-weight: 800;
    letter-spacing: 0.01em;
    text-transform: uppercase;
    color: #10181f;
    background: #fff;
    border: 0.08em solid rgba(0,0,0,0.6);
    border-radius: 0.3em;
    padding: 0 0.18em;
    line-height: 1.25;
    white-space: nowrap;
    text-shadow: none;
}

/* A COST COUNTED IN PLAYERS -- RP, AP, EP -- set as one mark rather than two
   letters. Inside a box the size of a digit, normally-spaced "2RP" reads as a 2
   beside something else; tightened and slightly narrowed it reads as one value,
   which is what it is. */
/* R AND P ARE ONE MARK, so they overlap rather than sit side by side -- the
   pair is a single quantity and two evenly-spaced initials read as two things.
   The room saved goes AFTER the pair instead, so "RPX" does not run into its X
   and the number in "2RP" stays visibly separate from the count. */
/* ONE RULE, EVERYWHERE THE PAIR APPEARS -- see the same rule in game.css.
   Scoped to the inline chip, it set "CRP" in rules text as one tight mark and
   left the RP in the card's own cost gem as two loose letters: the same value,
   printed two ways on one card. The chip's size and weight went with the
   scope, so both places take those from the box they sit in. */
/* PADDING cancels the trailing letter-spacing, not margin: the negative
   tracking shortens the span's own box while the P is still drawn where it was,
   so the glyph overhangs its box and a margin carries the overhang along with
   it. Explained in full in game.css. The margins that remain are gaps to real
   neighbours -- the count in "2RP", an X in "RPX". */
.cost-players {
    letter-spacing: -0.28em;
    padding-right: 0.40em;
    margin-left: 0.06em;
    margin-right: 0.08em;
    display: inline-block;
}
/* A WIDER BOX, not padding on one side of a centred mark -- padding there is a
   shove, moving the letters left by half of it and leaving the box the width it
   was. min-width is cut for the one or two digits every other cost is; "RP" is
   two capitals and fills it wall to wall, so the box grows and centring puts
   the room on both sides. Marked by the renderer (cost-players-box) so the
   width is in the markup before html2canvas sees it. See game.css. */
.rules-text-icon.cost-box.cost-players-box { min-width: 1.8em; }
/* The same width inside a ~note~, asserted at the specificity the card's badge
   rules use rather than left to win on (0,3,0) against whatever a note brings
   with it. A chip in a note is the same chip. See game.css. */
.ch-card-root .rules-text .cost-box.cost-players-box,
.ch-card-root .rules-text .tilde-box .cost-box.cost-players-box,
.tilde-box .cost-box.cost-players-box {
    min-width: 1.8em !important;
}

/* A TOKEN THAT HAS NO RULES SAYS ITS NAME INSTEAD.
   Most tokens are markers — what matters is how many you hold, not what they
   do — so their rules text is empty by authoring. Rendered as empty that is a
   blank card, which reads as a card that failed to load. Set large and centred
   in the space the rules would have used, so the token is legible as itself
   from across the table. */
/* The plate stands down when the body carries the name: printed in both, it
   is said twice, and the plate is the one that has to clip it to fit. */
.ch-card-root.marker-token .card-title-pill,
.marker-token .card-title-pill { visibility: hidden; }
/* And the name sits in the middle of the card, not at the top of a tall box —
   the rules box is only as tall as its content unless told otherwise. */
.ch-card-root.marker-token .card-rules,
.marker-token .card-rules { display: flex; }
/* A MARKER TOKEN HAS NO PRICE. It is minted by a card, never paid for, so the
   cost plate showed a 0 that means nothing and collided with the footer bar it
   now sits on. The plate is for cards you buy. */
.ch-card-root.marker-token .cost-badge,
.marker-token .cost-badge { display: none; }
.ch-card-root.marker-token .card-footer,
.marker-token .card-footer { padding-left: 12px; }
.rules-text.token-marker {
    flex: 1 1 auto;
    min-height: 60%;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-size: calc(2.6rem * var(--font-scale, 1));
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: .01em;
    opacity: .95;
    text-wrap: balance;
}

/* ── THE HUMILITY WEDGE, DRAWN ──────────────────────────────────────────────
   HERE, and not in game.css, because this is the stylesheet every page that
   renders a card actually loads — card.php, the game, play2, view-card and the
   layout editor. game.css is loaded by some of them and not by card.php, which
   is exactly where the mark was still coming out the old way.

   WHY DRAWN AT ALL: a CSS triangle is a BORDER — a box of zero width and height
   whose edges happen to make a wedge. Nothing can be centred inside a box of
   zero size, so every context that showed this mark guessed a `top:` of its own
   (25px on the card, 20px in the rules text, 13px for a middle icon, .6em on
   card.php) and each guess was right at one size and wrong at every other. The
   number was never centred; it was only positioned.

   Drawn as a picture with real width and height, the number is laid out by the
   box like any other text and lands in the same place at every size. It also
   gets what borders cannot give: a rim, a gradient, a highlight inside the rim,
   and a base to stand on — against dark art a bare wedge's bottom edge simply
   stops, and the mark reads as fading out rather than sitting on something.

   SIZED BY MEASUREMENT. Rendered at several sizes and read back: the wedge is
   only as wide as the height you write at, so a number at 67% of the height has
   about two thirds of the base to live in. 3.2 x 2.15em at 1.1em holds three
   characters with room to spare, and the number is now the size of the words
   around it — which is the point of it, since the triangle says "humility" and
   the number says how much.

   WHITE, AND SAID SO. The colour was left to inherit, so on the card page the
   number came out in the card's own gold on a green plate — the least legible
   pairing available. !important because four stylesheets have an opinion about
   this element and the one that wins by file order set everything except the
   colour.

   TOGGLED WITH data-tri="css" ON THE ROOT, which puts the border version back
   untouched: it is what every card proofed so far was approved against, and a
   mark that changes shape under an approval unapproves the set. */
:root:not([data-tri="css"]) .humility-box,
:root:not([data-tri="css"]) .ch-card-root .humility-box,
:root:not([data-tri="css"]) .rules .humility-box,
:root:not([data-tri="css"]) .ch-card-root .rules-text .humility-box {
    width: 2.4em !important;
    /* The height of a cost chip, near enough: 39.0px against the chip's 37.8px,
       measured. A triangle reads slightly smaller than a square of the same
       height, so a hair taller is what makes the two look equal on a line. */
    /* Short enough to sit INSIDE the line: at 1.5em the wedge hung 3.3px below
       the text band it belongs to, which reads as a mark that has slipped. */
    height: 1.35em !important;
    border: 0 !important;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='76' viewBox='0 0 100 76'><defs><linearGradient id='g' x1='0' y1='0' x2='0' y2='1'><stop offset='0' stop-color='%2358f5b9'/><stop offset='1' stop-color='%2304ad6e'/></linearGradient></defs><path d='M50 4L96 70H4Z' fill='none' stroke='%23013d22' stroke-width='7' stroke-linejoin='round'/><path d='M50 4L96 70H4Z' fill='url(%23g)'/><path d='M50 15L84 65H16Z' fill='none' stroke='%2358f5b9' stroke-width='2' opacity='.4'/><rect x='3' y='67' width='94' height='7' rx='3.5' fill='%23013d22'/></svg>") center / 100% 100% no-repeat !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    position: relative;
    top: 0 !important;
    /* LEVEL WITH THE CHIPS. The number sits at 66% of the box's height, not at
       its centre, so aligning the box by eye left the number a couple of pixels
       below the chip beside it — on a line of three values that reads as one of
       them having slipped. Measured against a real chip: at -0.44em the two
       numbers' centres are 0.07px apart. */
    vertical-align: -0.26em !important;
    padding: 0 !important;
}
/* The two offset shadow triangles were the old rim. The drawn one carries its
   own, so these would now sit behind it as a second wedge slightly out of true. */
:root:not([data-tri="css"]) .humility-box::before,
:root:not([data-tri="css"]) .humility-box::after { display: none !important; }

:root:not([data-tri="css"]) .humility-box .humility-text,
:root:not([data-tri="css"]) .rules .humility-box .humility-text,
:root:not([data-tri="css"]) .ch-card-root .rules-text .humility-box .humility-text {
    position: absolute !important;
    left: 50% !important;
    top: 62% !important;
    transform: translate(-50%, -50%) !important;
    /* BIG ENOUGH TO BE THE POINT OF THE MARK. The triangle says "humility" and
       the number says how much — but a card reading "gain +2 and draw 1" prints
       three numbers in one sentence, all values of the same kind, and they are
       set at one size. The chip is 1em of the rules text; this is 1.05em, which
       measures the same, because a number inside a shape that narrows reads
       slightly smaller than one on a flat plate.

       The wedge came DOWN to the number rather than the number up to the wedge:
       3.2 x 2.15em around a 1.1em value is a lot of triangle and a little
       number. The editor sizes this per value because it knows how many glyphs
       there are; CSS cannot count, so this is the two-character answer, which
       is what almost every one of these values is. */
    font-size: 1.05em !important;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif !important;
    font-variant-numeric: lining-nums tabular-nums;
    font-weight: 900 !important;
    color: #fff !important;
    /* The rim behind it does the separating, so the outline stays light enough
       not to close up the counter of an 8 or thicken a minus into its digit. */
    -webkit-text-stroke: 0.03em #00190d !important;
    text-shadow: 0 0 0.07em #00190d, 0 0.02em 0.05em #000, 0 0 0.2em rgba(0, 0, 0, .9) !important;
    white-space: nowrap;
    letter-spacing: -0.04em;
}

/* ================================================================
   PLATE MODE  (per-card, per-theme — opt-in)
   ----------------------------------------------------------------
   For a card whose PICTURE CARRIES THE CONTENT: a reference card, a
   timeline, a map. CardRenderer adds `.layout-plate` when a card
   carries layout_mode "plate" for the current theme.

   The picture gets most of the face. The title bar, the rules line
   and the footer STAY — a card with no name and no type is not a
   card, it is a loose illustration in a deck. The first cut of this
   hid all of them and produced exactly that.

   CONTAIN, NOT COVER. The ordinary face crops art into its slot with
   cover, which is right for a picture of a person and takes the first
   and last letters off every line of a picture made of words.
   ================================================================ */
.fulltext.tallart.layout-plate .card-art,
.layout-plate .card-art {
    position: absolute !important;
    top: 0 !important; left: 0 !important; right: 0 !important;
    height: calc(100% * var(--plate-art, 0.68)) !important;
    max-height: none !important;
    margin: 0 !important;
    overflow: hidden !important;
    border-radius: 14px 14px 0 0;
    z-index: 1;
}
.layout-plate .card-art img {
    width: 100% !important;
    height: 100% !important;
    max-height: none !important;
    min-height: 0 !important;
    object-fit: contain !important;          /* never crop a picture made of words */
    object-position: center center !important;
    opacity: 1 !important;
    filter: none !important;
}
.layout-plate .card-rules {
    top: calc(100% * var(--plate-art, 0.68)) !important;
    bottom: 92px !important;
    left: 0 !important; right: 0 !important;
    height: auto !important; max-height: none !important; min-height: 0 !important;
    overflow: hidden;
    border-radius: 0 0 14px 14px;
    background: linear-gradient(to bottom,
        rgba(0,0,0,0.66) 0%, rgba(0,0,0,0.82) 14%, rgba(0,0,0,0.86) 100%) !important;
    display: flex !important;
    flex-direction: column;
    justify-content: center;
}

/* ================================================================
   A COLOUR, NAMED AND SHOWN  (.greencards, .grncard, .red, …)
   ----------------------------------------------------------------
   This used to set the whole phrase as one solid chip — "Green
   cards" in white on green — which makes a noun phrase look like a
   keyword and drops a block of colour into the middle of every
   sentence that mentions one.

   What needs pointing at is the COLOUR. So the name sits in a quiet
   box with a swatch of the colour beside it, and the word after it
   ("card", "cards") is ordinary text, because it is an ordinary word.

   THE SWATCH CARRIES THE COLOUR SO THE BOX DOES NOT HAVE TO. A solid
   Silver chip needs dark ink and a solid Red one needs light, so the
   six of them read as different kinds of thing; with the colour in a
   square, every one of them is the same mark with a different square
   in it.
   ================================================================ */
.ccg-color-name {
    display: inline-flex;
    align-items: center;
    gap: 0.28em;
    /* Roomier on the LEFT, where the swatch now sits, and tight on the right.
       I swapped these the wrong way round when the swatch moved to the front —
       which put the wider padding after "cards", on top of the ordinary word
       space that already follows the chip, and the two together read as a gap
       in the sentence. The right edge needs less than the left, not more: a
       letter ends where it ends, while a square of colour wants air around it
       or it touches the border. */
    padding: 0.04em 0.24em 0.04em 0.34em;
    border-radius: 0.24em;
    background: rgba(0,0,0,.28);
    border: 1px solid rgba(255,255,255,.34);
    line-height: 1.15;
    white-space: nowrap;
    /* It is a noun, not a keyword: same weight as the sentence around it. */
    font-weight: inherit;
}
.ccg-color-swatch {
    display: inline-block;
    width: 0.62em;
    height: 0.62em;
    border-radius: 0.1em;
    /* A hairline in both directions, so a pale swatch (Silver) keeps an edge on
       a light card and a dark one (Blue) keeps an edge on a dark card. */
    box-shadow: 0 0 0 1px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.28);
    flex: 0 0 auto;
}

/* ================================================================
   A DEFINED ATTRIBUTE  (.reversal2 → "Reversal 2", then its wording)
   ----------------------------------------------------------------
   Some rules are a NAMED thing with a number attached, and the name
   is what a player learns once and then recognises. It should look
   like a label the game has defined, not like the first two words of
   a sentence — so it gets a plate, and the number gets a disc of its
   own inside it: the name says WHICH rule, the number says how much,
   and they are different questions.

   Quiet, deliberately. This sits at the head of its own sentence and
   is followed immediately by the wording it names, so it has only to
   be distinct — a loud label in front of a long clause is read twice
   and the clause once.
   ================================================================ */
.ccg-attr {
    display: inline-flex;
    align-items: center;
    gap: 0.3em;
    padding: 0.05em 0.28em 0.05em 0.42em;
    border-radius: 0.9em;
    background: rgba(0,0,0,.3);
    border: 1px solid rgba(255,255,255,.34);
    line-height: 1.15;
    white-space: nowrap;
    vertical-align: baseline;
}
.ccg-attr-name {
    font-variant: small-caps;
    letter-spacing: 0.06em;
    font-weight: 700;
}
.ccg-attr-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.35em;
    height: 1.35em;
    padding: 0 0.16em;
    background: #f0e6cf;
    color: #1d1408;
    font-weight: 800;
    /* The disc is round, so a two-digit number has to be allowed to widen it
       rather than spill out of it — min-width above, and a pill once it does. */
    border-radius: 0.7em;
    font-size: 0.86em;
    line-height: 1;
    /* NO SHADOW OF ANY KIND. The disc is a cream fill on the dark Reversal
       pill, so it needs nothing to separate it — and it was inheriting the
       rules text's shadow, which is there to hold white words up against card
       art and does the opposite to a dark digit on a light ground: it thickens
       the strokes from underneath and closes the counter of the figure. The
       1px ring went with it; an edge drawn to help a shape that is already
       clearly edged is just more ink in the same place. */
    text-shadow: none;
}

/* ── #maxN# : "may be used at most N times per turn", as a badge ───────────
   Same parts as .ccg-attr (dark pill, small caps, value in a cream disc) on
   purpose: the card already has a way of saying "named property, number
   attached", and this is one of those. Built only from things the printed
   card's rasteriser can draw — a border, a linear gradient and text. No
   box-shadow, no inset rim, no filter: html2canvas silently drops all three,
   and a mark that is only correct on screen is not a mark on a printed card. */
.ccg-maxturn {
    display: inline-flex;
    align-items: center;
    gap: 0.22em;
    /* The same 0.96em outer height every other inline mark on a rules line is
       set to, reached the same way: a 1.2em box at .80em type. */
    font-size: 0.80em;
    height: 1.2em;
    padding: 0 0.3em 0 0.4em;
    border-radius: 0.6em;
    border: 0.085em solid rgba(255, 255, 255, 0.82);
    background: linear-gradient(180deg, #3b4668, #222a42);
    color: #f2ead6;
    vertical-align: 0.04em;   /* measured against the chips, see layouts.php */
    line-height: 1;
    white-space: nowrap;
    text-shadow: none;
}
.ccg-maxturn-name {
    font-family: 'Cinzel', Georgia, serif;
    font-size: 0.66em;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ccg-maxturn-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.15em;
    height: 1.15em;
    padding: 0 0.14em;
    border-radius: 0.6em;
    background: #f0e6cf;
    color: #1d1408;
    font-weight: 800;
    font-size: 0.86em;
    line-height: 1;
    text-shadow: none;
}
/* "/turn" is the unit, not the value: it says what the number is counted
   against and should never compete with it for attention. */
.ccg-maxturn-per {
    font-size: 0.58em;
    letter-spacing: 0.02em;
    opacity: 0.8;
}

/* "blue cards" — both words, set as one phrase at the RULES TEXT'S OWN SIZE.
   They were sized apart at first, which made the noun read as a footnote to
   the adjective; they are one thing being named. Shrinking the pair was the
   next thing tried and was also wrong: this is an ordinary noun phrase in an
   ordinary sentence, and the swatch is already doing the pointing, so there is
   nothing for a smaller size to earn. Inside the box so a line break can never
   separate the halves of one mark, and no opacity: on a printed card that is
   ink removed, not emphasis reduced. */
.ccg-color-word {
    font-size: inherit;
}

/* A blank line in the card text: one break plus 0.7 of a line, rather than the
   whole empty line pre-wrap would otherwise spend. 0.7lh is seven tenths of
   this element's own line height, so it follows the rules text wherever the
   autofit takes it; the em above is the fallback for anything that does not
   know that unit, and lands within a hair of it at the line heights a card
   uses. */
.ccg-blankline {
    display: block;
    height: 0.95em;
    height: 0.7lh;
}

/* "H+3{3x}" and "{h-center}" on the board.
   The scale is a font-size because every part of this mark is measured in em:
   scale the font and the wedge, the number and the rim follow together, with
   no second set of numbers to keep in step. Centring makes it a block with
   automatic side margins — a mark that IS the card's rule, rather than one
   inside a sentence. */
.humility-box[style*="--mark-x"], .rules-text-icon[style*="--mark-x"] {
    font-size: calc(1em * var(--mark-x, 1));
}
.mark-center {
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: max-content;
    vertical-align: baseline;
}

/* {line:h-center}: centres a whole line of rules text — a block so it spans the
   box, and text-align rather than auto margins because what is being centred is
   a run of words and marks together, not one object with a width. */
.line-center { display: block; text-align: center; }

/* A word given a size — nothing but the size: it keeps the rules text's face,
   colour and weight, because it is still a word in the sentence. inline-block
   so its line box owns its own height; as a bare inline, a word two or three
   times the size would leave the line spaced for the small text around it. */
.mark-word { display: inline-block; line-height: 1; font-size: calc(1em * var(--mark-x, 1)); }

/* The fast mark — a bolt, drawn rather than fetched: there is no bolt file and
   this project's art is not in the repository. A data-URI SVG cannot arrive
   late and cannot 404, which for a mark that changes WHEN a boost is paid
   matters more than a nicer picture. */
.boost-fast {
    display: inline-block;
    width: 0.59em;
    height: 0.96em;
    vertical-align: -0.17em;
    margin: 0 0.06em 0 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='44' height='72' viewBox='0 0 44 72'><path d='M26 2 L6 40 h13 L18 70 L38 30 H25 Z' fill='%23ffd23f' stroke='%23231400' stroke-width='5' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 100% 100%;
}
