/* ==========================================================
   Print Your Party Game — Bingo Card Maker
   Same cardstock/print system as the brand style board.
   Scoped under .pypg-bingo-app so it doesn't leak into the theme.
   ========================================================== */

.pypg-bingo-app {
  --pypg-paper: #FBF3E6;
  --pypg-paper-soft: #F5E9D8;
  --pypg-paper-soft2: #EFE0CB;
  --pypg-ink: #2B1E2F;
  --pypg-ink-soft: #6B5D6E;
  --pypg-pink: #FF4D7D;      --pypg-pink-deep: #E23566;
  --pypg-marigold: #FFB627;  --pypg-marigold-deep: #E89A00;
  --pypg-teal: #17A398;      --pypg-teal-deep: #0E8074;
  --pypg-grape: #6B3FA0;     --pypg-grape-deep: #532E80;
  --pypg-pumpkin: #E8631C;   --pypg-pumpkin-deep: #C24E10;
  --pypg-line: rgba(43, 30, 47, 0.18);
  --pypg-shadow: rgba(43, 30, 47, 0.18);
  --pypg-good: #17A398;
  --pypg-warn: #E8631C;
  --pypg-accent: var(--pypg-pink);
  --pypg-accent-deep: var(--pypg-pink-deep);
  /* The printed card itself (and its cells) is always plain white,
     border or not — deliberately not the brand's cream "Paper" tone,
     since a clean white background is what most printers/paper expect. */
  --pypg-card-bg: #ffffff;

  background: var(--pypg-paper);
  color: var(--pypg-ink);
  font-family: "Nunito", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15.5px;
  line-height: 1.55;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 10px 30px var(--pypg-shadow);
}

.pypg-bingo-app * { box-sizing: border-box; }

/* An element hidden via the plain HTML `hidden` attribute (like
   #pypgBorderOptions before "Add a Border" is clicked) should always stay
   hidden — but a later same-specificity rule like `.pypg-field { display:
   flex }` below silently wins over the browser's own [hidden] default and
   shows it anyway. This is what made the border/template gallery visible
   from page load, before anyone had actually chosen "Add a Border". */
.pypg-bingo-app [hidden] { display: none !important; }

.pypg-bingo-app h1, .pypg-bingo-app h2, .pypg-bingo-app h3 {
  font-family: "Lilita One", "Baloo 2", ui-rounded, system-ui, sans-serif;
  font-weight: 400;
  letter-spacing: 0.01em;
  margin: 0;
}

.pypg-bingo-app button,
.pypg-bingo-app input,
.pypg-bingo-app textarea { font-family: inherit; }

.pypg-bingo-app :focus-visible { outline: 3px solid var(--pypg-ink); outline-offset: 2px; }

/* ---------- layout ---------- */
.pypg-layout {
  display: grid;
  grid-template-columns: 340px 1fr;
  align-items: start;
}
@media (max-width: 860px) { .pypg-layout { grid-template-columns: 1fr; } }

.pypg-controls {
  padding: 26px clamp(16px, 3vw, 28px) 32px;
  border-right: 2px dashed var(--pypg-line);
  display: flex;
  flex-direction: column;
  gap: 20px;
}
@media (max-width: 860px) {
  .pypg-controls { border-right: none; border-bottom: 2px dashed var(--pypg-line); }
}

.pypg-field { display: flex; flex-direction: column; gap: 8px; }
.pypg-field label {
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pypg-ink-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.pypg-field .pypg-hint { margin: 0; font-size: 12px; color: var(--pypg-ink-soft); }

.pypg-bingo-app input[type="text"],
.pypg-bingo-app input[type="number"],
.pypg-bingo-app textarea {
  background: var(--pypg-paper-soft);
  border: 2px solid var(--pypg-line);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 14.5px;
  color: var(--pypg-ink);
  width: 100%;
}
.pypg-bingo-app input:focus, .pypg-bingo-app textarea:focus { border-color: var(--pypg-accent); }
.pypg-bingo-app textarea { resize: vertical; line-height: 1.5; }
.pypg-bingo-app input[type="number"] { width: 90px; }

.pypg-bingo-app input[type="file"] {
  background: var(--pypg-paper-soft);
  border: 2px dashed var(--pypg-line);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  color: var(--pypg-ink);
  width: 100%;
}

.pypg-word-count {
  font-weight: 800; letter-spacing: 0; text-transform: none;
  background: var(--pypg-paper-soft2); color: var(--pypg-ink-soft);
  border-radius: 999px; padding: 3px 10px; font-size: 12px;
}
.pypg-word-count.pypg-ok { background: var(--pypg-good); color: var(--pypg-paper); }
.pypg-word-count.pypg-warn-state { background: var(--pypg-warn); color: var(--pypg-paper); }

.pypg-pill-group, .pypg-template-group { display: flex; gap: 8px; flex-wrap: wrap; }
.pypg-pill {
  border: 2px solid var(--pypg-line); background: var(--pypg-paper-soft); color: var(--pypg-ink);
  padding: 9px 16px; border-radius: 999px; font-weight: 800; font-size: 13.5px; cursor: pointer;
}
.pypg-pill.pypg-active { background: var(--pypg-ink); color: var(--pypg-paper); border-color: var(--pypg-ink); }

.pypg-template-card {
  width: 74px;
  border: 3px solid transparent;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  background: var(--pypg-paper-soft);
  padding: 0;
}
.pypg-template-card img { width: 100%; height: 60px; object-fit: cover; display: block; }
.pypg-template-card span { display: block; font-size: 10px; font-weight: 700; text-align: center; padding: 3px 2px; color: var(--pypg-ink-soft); }
.pypg-template-card.pypg-active { border-color: var(--pypg-accent-deep); }

.pypg-checkbox { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--pypg-ink); cursor: pointer; }
.pypg-checkbox input { width: 17px; height: 17px; accent-color: var(--pypg-accent); }

.pypg-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 22px; border-radius: 999px; font-weight: 800; font-size: 14px;
  border: 2px solid transparent; cursor: pointer;
}
.pypg-btn-primary { background: var(--pypg-accent); color: var(--pypg-paper); box-shadow: 0 10px 20px var(--pypg-shadow); }
.pypg-btn-primary:hover { background: var(--pypg-accent-deep); }
.pypg-btn-primary:disabled { opacity: 0.6; cursor: wait; }
.pypg-btn-ghost { background: transparent; color: var(--pypg-ink); border-color: var(--pypg-ink); }
.pypg-btn-ghost:hover { background: var(--pypg-ink); color: var(--pypg-paper); }
.pypg-btn-block { width: 100%; }

.pypg-warning {
  background: rgba(232, 99, 28, 0.12); border: 2px solid var(--pypg-warn); color: var(--pypg-pumpkin-deep);
  font-size: 13px; font-weight: 700; padding: 10px 12px; border-radius: 8px; margin: 0;
}

/* ---------- preview ---------- */
.pypg-preview { padding: 26px clamp(16px, 3vw, 32px) 22px; min-height: 50vh; }

.pypg-empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  gap: 14px; padding: 50px 20px; color: var(--pypg-ink-soft);
}
.pypg-empty-state svg { opacity: 0.7; }
.pypg-empty-state h2 { font-size: 22px; color: var(--pypg-ink); }
.pypg-empty-state p { max-width: 40ch; margin: 0; font-size: 14px; }

/* 380px min (not 280px): below that, long multi-word prompts don't
   reliably fit their cells even at the smallest font tier — see the
   .pypg-cell rules below. Matches the print card's own width, so the
   on-screen preview is a true preview of what actually prints. */
.pypg-cards-out { display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 24px; }
/* On a narrow phone, a 380px *minimum* column would force the grid
   wider than the screen (horizontal scrolling of the whole page) —
   worse than a few pixels of tight text. Below 860px there's only ever
   one card per row anyway (.pypg-layout above goes single-column too),
   so drop the floor and just let each card fill the available width. */
@media (max-width: 860px) {
  .pypg-cards-out { grid-template-columns: 1fr; }
}

.pypg-more-note {
  grid-column: 1 / -1;
  text-align: center;
  padding: 16px;
  border-radius: 10px;
  border: 2px dashed var(--pypg-line);
  color: var(--pypg-ink-soft);
  font-weight: 700;
  font-size: 13.5px;
}

.pypg-bingo-card {
  position: relative;
  background: var(--pypg-card-bg);
  border-radius: 14px;
  padding: 18px;
  box-shadow: 0 10px 24px var(--pypg-shadow);
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
}
/* The Standard (no-border) card: plain white with just a light dashed
   cut-line — a print guide, not a placeholder/error look. */
.pypg-bingo-card.pypg-no-frame { border: 1.5px dashed var(--pypg-line); }

/* padding-bottom (not the grid's own margin — that collapses away since
   this element has no border/padding of its own to contain it) reserves
   real room for the absolutely-positioned "Card X of Y" and site-domain
   labels, so they sit below the grid instead of over its last row. */
.pypg-card-inner { position: relative; padding-bottom: 34px; }
/* Base size = "Medium" (also the fallback for any card rendered without
   an explicit size — e.g. a purchase made before this option existed). */
.pypg-card-title { text-align: center; font-size: 24px; color: var(--pypg-ink); line-height: 1.1; }
.pypg-card-title.pypg-title-small { font-size: 18px; }
.pypg-card-title.pypg-title-medium { font-size: 24px; }
.pypg-card-title.pypg-title-large { font-size: 30px; }
.pypg-card-sub { text-align: center; font-family: "Caveat", cursive; font-weight: 600; font-size: 14px; color: var(--pypg-ink); margin-top: 2px; }

.pypg-bingo-grid { margin-top: 12px; display: grid; gap: 5px; }
.pypg-cell {
  background: var(--pypg-card-bg); border: 1.5px solid var(--pypg-line); border-radius: 5px;
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 4px; font-weight: 700; line-height: 1.08; color: var(--pypg-ink); overflow: hidden;
  /* A flex child's default min-width is "auto", which resolves to its
     content's un-wrapped width — without this, a long phrase refuses to
     wrap and instead spills past the cell's right edge. break-word is
     the second half: once the box CAN shrink, long words still need to
     be allowed to break mid-word as a last resort so they wrap instead
     of forcing the cell wider. */
  min-width: 0; overflow-wrap: break-word; word-break: break-word;
}
/* Longer phrases get a smaller font so they still fit a square cell
   instead of being clipped by overflow:hidden — tuned (see the plugin
   repo's fit-test harness) against real full-sentence prompts down to a
   ~380px card, which is also comfortably above the print card's own
   width, so what's previewed on screen matches what actually prints. */
.pypg-cell.pypg-len-s { font-size: 10px; }
.pypg-cell.pypg-len-m { font-size: 8.25px; }
.pypg-cell.pypg-len-l { font-size: 7px; }
.pypg-cell.pypg-len-xl { font-size: 6px; }
.pypg-cell.pypg-len-xxl { font-size: 5.25px; }
.pypg-cell.pypg-free { background: var(--pypg-card-bg); padding: 3px; }
.pypg-cell.pypg-free svg, .pypg-cell.pypg-free img { width: 88%; height: 88%; object-fit: contain; }

.pypg-card-num { position: absolute; bottom: 6px; right: 12px; font-size: 10px; font-weight: 800; color: var(--pypg-ink-soft); }
.pypg-card-site { position: absolute; bottom: 6px; left: 12px; font-size: 10px; font-weight: 800; letter-spacing: 0.02em; color: var(--pypg-ink-soft); }

/* ---------- word list (caller's checklist) ---------- */
/* On screen: sits between the toolbar and the card grid. In print: its
   own page, built by JS (see buildWordListElement in bingo-maker.js) and
   inserted before the per-card pages. Same card-shaped look as the boards
   themselves so it reads as part of the same set. */
.pypg-wordlist {
  background: var(--pypg-card-bg);
  border: 2px solid var(--pypg-line);
  border-radius: 16px;
  box-shadow: 0 3px 0 var(--pypg-line);
  padding: 20px 24px 22px;
  margin: 0 auto 22px;
  max-width: 640px;
}
.pypg-wordlist-title {
  font-family: "Lilita One", cursive;
  font-size: 20px;
  color: var(--pypg-ink);
  text-align: center;
  letter-spacing: 0.01em;
}
.pypg-wordlist-hint {
  text-align: center;
  font-size: 12.5px;
  color: var(--pypg-ink-soft);
  margin-top: 4px;
}
.pypg-wordlist-grid {
  margin-top: 16px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px 16px;
}
.pypg-wordlist-item {
  position: relative;
  font-size: 13px;
  font-weight: 600;
  color: var(--pypg-ink);
  line-height: 1.3;
  padding-left: 22px;
}
.pypg-wordlist-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--pypg-ink-soft);
  border-radius: 4px;
  background: var(--pypg-card-bg);
}

/* ---------- checkout bar ---------- */
.pypg-checkout-bar {
  margin-top: 26px; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: var(--pypg-paper-soft); border: 2px dashed var(--pypg-line); border-radius: 12px; padding: 16px 20px; flex-wrap: wrap;
}
.pypg-checkout-info { display: flex; flex-direction: column; gap: 2px; }
.pypg-checkout-info strong { font-size: 15px; }
.pypg-checkout-info span { font-size: 12.5px; color: var(--pypg-ink-soft); }

@media (prefers-reduced-motion: no-preference) {
  .pypg-bingo-card { animation: pypgPop 0.22s ease; }
}
@keyframes pypgPop { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

/* ---------- unlocked / print view ---------- */
.pypg-unlocked-toolbar { display: flex; justify-content: center; padding: 6px 0 18px; }

.pypg-print-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  justify-content: center;
  padding: 4px 0 6px;
}
.pypg-control-group { display: flex; align-items: center; gap: 10px; }
.pypg-control-label {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pypg-ink-soft);
}

/* Built by JS only for the print stylesheet — never shown on screen.
   width/height:0 + overflow:hidden (not display:none) so it still has a
   real, measurable layout at its full natural size — applyPrintFit() in
   bingo-maker.js needs to read each card frame's true rendered width/
   height (via getBoundingClientRect) to work out how much to zoom it to
   fill its page, and a display:none subtree can't be measured at all
   (everything reports 0). A 0×0 overflow:hidden box has zero footprint
   in the page (nothing to scroll to, nothing visible) while everything
   inside it still lays out normally and stays fully measurable. */
.pypg-print-only { width: 0; height: 0; overflow: hidden; }
/* This width is NOT inside @media print — it has to hold outside of
   print too, because applyPrintFit() (bingo-maker.js) measures each
   frame's natural size with getBoundingClientRect() while the page is
   just sitting there normally (not printing). A rule scoped to
   @media print wouldn't apply yet at that point, so the frame would have
   no explicit width, collapse to fit its 0-width .pypg-print-only
   parent, and every measurement — and therefore the real print width
   and every card-element font-size applyPrintFit() computes from it —
   would come out wrong. Giving it a real width here doesn't affect
   anything visible on screen, since .pypg-print-only itself has zero
   footprint outside of print regardless of what's inside it. */
.pypg-print-card-frame { width: 480px !important; }
.pypg-print-page.pypg-per-2 .pypg-print-card-frame { width: 400px !important; }

@media print {
  /* CartFlows ships its own collapsed order-review panel on this same
     Thank You page ("Je bestelling" / "Your order" — a real WooCommerce
     order summary block, class .wcf-collapsed-order-review-section,
     display:none on screen). Something in CartFlows' or the theme's own
     print CSS re-enables it specifically for printing — plausibly with
     !important, since a plain (non-important) `body * {visibility:
     hidden}` wasn't enough to keep it off the printed page. Matching
     that with our own !important, PLUS display:none (not just
     visibility:hidden — display:none also removes any leftover layout
     space) on everything outside #pypgBingoUnlocked, is a much harder
     override to lose to.
     A version of this rule shipped in 1.0.15 without the :has() clause
     below and broke printing completely (blank pages again): excluding
     #pypgBingoUnlocked and #pypgBingoUnlocked's own DESCENDANTS isn't
     enough — every wrapper div ABOVE #pypgBingoUnlocked (CartFlows' and
     WooCommerce's own containers, between <body> and our own element)
     also matches a bare `body *` and was getting display:none too. A
     display:none ancestor can't be "undone" by a descendant no matter
     what that descendant's own display/visibility says — unlike
     visibility:hidden, which a descendant CAN override — so
     #pypgBingoUnlocked's own visibility:visible was powerless once one
     of its ancestors had display:none. :has(#pypgBingoUnlocked) excludes
     exactly that ancestor chain too. Needs :not(complex selector) and
     :has() — both standard, well-supported in any recent Chromium
     browser (this whole workflow already depends on one). */
  body *:not(#pypgBingoUnlocked):not(#pypgBingoUnlocked *):not(:has(#pypgBingoUnlocked)) {
    display: none !important;
    visibility: hidden !important;
  }
  #pypgBingoUnlocked, #pypgBingoUnlocked * { visibility: visible !important; }
  /* #pypgBingoUnlocked IS .pypg-bingo-app (the shortcode's root div
     carries both the id and that class), so it also inherits that
     class's on-screen "card/panel" chrome: a warm paper-cream background,
     a drop shadow, and rounded+clipped corners. All of that used to
     bleed straight into the printed output — the cream behind the word
     list AND every card, and a visible shadow edge along whatever the
     print engine treated as this element's own box. Print should just be
     plain flat white with none of the on-screen "card" styling. */
  #pypgBingoUnlocked {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    background: none;
    box-shadow: none;
    border-radius: 0;
    overflow: visible;
  }
  /* Border templates are applied as a CSS background-image (see
     buildCardElement in bingo-maker.js), and most browsers' print dialog
     defaults its "background graphics"/"achtergrondbeelden" option to
     OFF — which silently drops background-images along with background
     colors, leaving a bordered card's frame missing even though the text
     inside prints fine. This forces backgrounds to print regardless of
     that checkbox, standard property first, -webkit- prefix for Chrome. */
  #pypgBingoUnlocked, #pypgBingoUnlocked * {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
  /* The on-screen word-list checklist (a direct child of #pypgBingoUnlocked,
     shown above the card previews) has its own separate copy built fresh
     for print inside .pypg-print-only/.pypg-print-page — without hiding
     this on-screen one too, both copies print: the unpaginated on-screen
     version first, then the real paginated one, so the list (and the
     layout after it) doubles up. The child-combinator (>) is deliberate:
     it only matches the on-screen copy sitting directly under
     #pypgBingoUnlocked, not the print-only one nested inside .pypg-print-page. */
  .pypg-unlocked-toolbar, .pypg-print-controls, .pypg-cards-out,
  #pypgBingoUnlocked > .pypg-wordlist { display: none !important; }

  /* Every .pypg-bingo-card (see buildCardElement in bingo-maker.js) has a
     "pop in" entrance animation — fades from opacity:0 to opacity:1 over
     0.22s — meant for when a card first appears on screen. The printed
     copies inherit that same class, but they've been sitting inside
     .pypg-print-only with display:none the whole time (never shown, so
     the animation never ran). The instant printing starts, .pypg-print-only
     flips to display:block and this animation starts fresh from
     opacity:0 — and Chrome renders/snapshots the print output almost
     immediately, well before that 0.22s finishes, so it prints the cards
     frozen at (or near) their invisible starting frame. The word-list
     page never carries this class, which is exactly why it kept printing
     fine while every card page came out blank. Fix: kill the animation
     entirely for anything inside the print output and pin it to its
     finished (fully visible, untransformed) state. */
  .pypg-print-only, .pypg-print-only * {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  .pypg-print-only { width: auto; height: auto; overflow: visible; }
  /* NOT flex + min-height:90vh + align/justify-content:center on every
     page — that was tried and shipped in 1.0.9, then reverted in 1.0.10
     because it causes real, physical print output to come out with
     blank pages. Reasoning: min-height:90vh forced EVERY .pypg-print-page
     to be an artificially tall box — roughly as tall as, or taller than,
     the printable area of a Letter/A4 page — regardless of how little
     content actually sat inside it. Chromium's print engine has to
     fragment that oversized flex box across the physical page boundary,
     and when the box uses align-items/justify-content:center, the
     fragmentation + centering math it applies routinely computes the
     real (small) content as belonging entirely on the SECOND physical
     page, leaving the FIRST page print as nothing but blank paper — a
     well-known Chromium bug with centered flex content that's taller
     than one page.
     The word-list page below still avoids that: it just flows from the
     top with ordinary padding, no flex, no forced height. The card
     pages further down DO use flex + centering again (for the page-
     filling "1 per page" / "2 per page" layout) — but safely this time,
     because JS (applyPrintFit in bingo-maker.js) gives each one a height
     that's EXACTLY one physical page, never taller, computed from the
     chosen paper size — a box that's precisely one page tall never
     needs to fragment, so there's nothing for that Chromium bug to
     trigger on. */
  .pypg-print-page {
    page-break-after: always;
  }
  .pypg-print-page:last-child { page-break-after: auto; }

  /* The word-list page: unaffected by any of the card-page changes below
     — still just flows from the top of its own page. Wider than a card
     (it's a checklist, not a board) and with the box-shadow dropped,
     same as the cards, so it doesn't print a stray grey bar under the
     border. */
  .pypg-print-page:not(.pypg-print-card-page) { padding-top: 24mm; }
  .pypg-print-page .pypg-wordlist {
    box-shadow: none;
    width: 100%;
    max-width: 680px;
    margin: 0 auto 22px;
    page-break-inside: avoid;
  }

  /* Card pages: no background of their own (plain white/paper, like the
     word-list page) — the "beige page" Lauren described was shorthand
     for how BIG the card should be (page-filling), not an actual mat to
     print. Sized to exactly one physical page (height set inline by JS —
     see applyPrintFit) with the card(s) centered on it. For "1 per page"
     there's one frame, so centering just centers the single card. For
     "2 per page" there are two frames plus a .pypg-print-cut-line
     between them (inserted by refreshPrintPages), laid out side by side
     since flex-direction's default is row — same centering, just with
     two items instead of one. */
  .pypg-print-card-page {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    page-break-inside: avoid;
  }

  /* .pypg-print-card-frame's width (the "natural", unscaled design size
     applyPrintFit() measures from) is set further up, outside this
     @media block — see the comment there for why it has to be. */

  /* The dashed cut-line between the two cards on a "2 per page" sheet.
     align-self:stretch makes it span the full height of the flex row
     (i.e. the whole page), matching the reference layout Lauren shared
     for another product (two cards side by side, a dotted line down the
     middle to cut along) — same mechanic, this product's own beige mat
     instead of that one's black background. */
  .pypg-print-cut-line {
    align-self: stretch;
    width: 0;
    border-left: 2px dashed var(--pypg-ink);
    margin: 0 14px;
  }

  .pypg-print-card {
    box-shadow: none;
    width: 100%;
    /* A thin, solid cut/fold guide around the printed card — deliberately
       plain black regardless of border template, since its job here is
       marking the physical edge of a page-filling card, not decoration. */
    border: 1px solid #000 !important;
  }
}
