/* =========================================================
   Thiên Long — Mini Game "Viết Nét Riêng"
   Shared stylesheet for the 8 step-by-step fullscreen screens.
   Native design canvas: 1440 × 850. The .br-stage element is
   scaled proportionally to fill the viewport (see /assets/js/stage.js).
   ========================================================= */

/* Brand display faces (woff2 for the browser; matching .otf/.ttf files
   alongside them back the GD compositor's server-side text — see
   inc/compositor.php). */
@font-face {
  font-family: "Maison Neue Extended";
  src: url("../fonts/MaisonNeueExtended-ExtraBold-800.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "BT Solisiert";
  src: url("../fonts/BTSolisiert-ExtraBold-800.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Dearpix";
  src: url("../fonts/dearpix-1-94-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
  min-height: 100%;
  background: #b7ddff;
  font-family: "Maison Neue Extended", "Be Vietnam Pro", "Helvetica Neue", Arial, sans-serif;
  color: #0070ff;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
html, body { overflow-y: auto; }
body.br-is-fixed { overflow: hidden; height: 100%; }

a { color: #0070ff; text-decoration: none; }
a:hover { opacity: 0.85; }

/* ---------- Stage: fixed-size design canvas ----------
   Default: fixed to viewport (letterboxed) for landscape / desktop.
   When JS adds .br-is-portrait, it becomes a normal block that fits width
   and lets the page scroll vertically on phones. */
.br-stage-wrap {
  position: fixed;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  /* The scene image lives here (not on .br-stage) so it always covers the
     full viewport with a single continuous layer — at any letterboxed
     aspect ratio the margins around .br-stage are the same image, not a
     separate fill, so there's no seam between "inside the card" and
     "outside" it. */
  background: url("../images/bg-grid.jpg") center / cover no-repeat, #b7ddff;
}
.br-stage-wrap.br-is-portrait {
  position: relative;
  inset: auto;
  width: 100%;
  overflow: visible;
  align-items: center;
  min-height: 100vh;
}

.br-stage {
  position: relative;
  width: 1440px;
  height: 850px;
  flex-shrink: 0;
  transform-origin: center center;
}
.br-stage-wrap.br-is-portrait .br-stage {
  transform-origin: center center;
}

/* ---------- SPA screen switching ----------
   All step screens live in the DOM at once; only the active one is shown.
   Their contents are already absolutely positioned relative to .br-stage, so
   the .br-screen wrapper itself needs no positioning of its own. */
.br-screen {
  display: none;
}
.br-screen.br-is-active {
  display: block;
}

/* Rules modal overlays the currently active screen instead of replacing it.
   .br-screen-modal itself stays inset:0 (matching .br-stage's own box) so
   its children's pixel-offset positions (.br-rules-panel, the close
   button) keep lining up the same way everything else on the stage does.
   No dim backdrop — by design, popups here sit directly over the screen
   underneath with nothing darkening it. */
.br-screen-modal {
  position: absolute;
  inset: 0;
  z-index: 50;
}

/* The slogan screen doubles as a popup (opened from the "Nhấn để điền
   slogan" preview on the photo screen) — same markup, shown as an overlay
   on top of whatever screen is underneath instead of replacing it. */
.br-screen.br-is-popup {
  position: absolute;
  inset: 0;
  z-index: 40;
}

/* Inline validation error boxes shown by interactions.js (display toggled
   in JS; layout/position is set per-screen via inline style). */
.br-step-error {
  z-index: 10;
}

/* ---------- Header bar (logo + campaign badge) ---------- */
.br-brand-logo {
  position: absolute;
  left: 52px;
  top: 51px;
  width: 332px;
  height: 48px;
  background: url("../images/logo-thienlong.png") center / contain no-repeat;
}

.br-campaign-badge {
  position: absolute;
  right: 38px;
  top: 34px;
  width: 232px;
  height: 82px;
  background: url("../images/badge-viet-net-rieng.png") center / contain no-repeat;
}

/* ---------- Buttons ---------- */
.br-btn {
  display: inline-block;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  outline: none;
}
.br-btn > span { display: none; } /* visually-hidden label kept for accessibility */

.br-btn-bat-dau,
.br-btn-the-le,
.br-btn-xac-nhan,
.br-btn-chot-don,
.br-btn-chia-se,
.br-btn-quay-lai-main {
  width: 225px;
  height: 79px;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  transition: transform .15s ease;
}
.br-btn-bat-dau       { background-image: url("../images/btn-bat-dau.png"); }
.br-btn-the-le        { background-image: url("../images/btn-the-le.png"); }
.br-btn-xac-nhan      { background-image: url("../images/btn-chot-don.png"); } /* legacy alias, kept in case anything still targets it */
.br-btn-chot-don      { background-image: url("../images/btn-chot-don.png"); }
.br-btn-chia-se       { background-image: url("../images/btn-chia-se.png"); }
.br-btn-quay-lai-main { background-image: url("../images/btn-quay-lai-main.png"); }
.br-btn:hover { transform: translateY(-2px); }
.br-btn:active { transform: translateY(1px); }
.br-btn-chia-se.br-is-loading { opacity: .5; pointer-events: none; }

/* small "Quay lại" text link (Frame 17/18/19/22/27) */
.br-btn-quay-lai-text {
  display: inline-block;
  padding: 4px 10px;
  color: #0070ff;
  font-weight: 600;
  font-size: 18px;
  cursor: pointer;
  background: transparent;
  border: 0;
}
.br-btn-quay-lai-text:hover { opacity: 0.75; }

/* Pixel-art "Quay lại" image button (Figma-exact), used for the in-flow
   step-back links; kept as a separate class from .br-btn-quay-lai-text
   above since that one's also reused on share.php with different labels
   ("Về trang chủ" / "Tự tạo thẻ của bạn") that this image doesn't say. */
.br-btn-quay-lai-img {
  display: inline-block;
  width: 104px;
  height: 29px;
  padding: 0;
  border: 0;
  cursor: pointer;
  background: url("../images/btn-quay-lai-text.png") center / contain no-repeat;
  transition: transform .15s ease;
}
.br-btn-quay-lai-img > span { display: none; }
.br-btn-quay-lai-img:hover { transform: translateY(-2px); }
.br-btn-quay-lai-img:active { transform: translateY(1px); }

/* stacked confirm + back on inner steps */
.br-action-stack {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

/* ---------- Titles (image glyphs) ---------- */
.br-title-img {
  position: absolute;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
}

/* Text-glyph title (chunky rounded uppercase, cyan→blue gradient, thick
   dark-blue outline) — used where a screen's title has no baked PNG, and
   as the mobile-only stand-in for titles that are still a PNG on desktop. */
.br-section-heading {
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  font-family: "Maison Neue Extended", "Fredoka", "Be Vietnam Pro", sans-serif;
  font-weight: 800;
  font-size: 56px;
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: transparent;
  background: linear-gradient(180deg, #eafcff 0%, #a3f0ff 32%, #4bb8ff 68%, #0064ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 4px #0031c5;
  paint-order: stroke fill;
  filter:
    drop-shadow(0 4px 0 rgba(0,49,197,0.45))
    drop-shadow(0 10px 14px rgba(0,49,197,0.25));
  pointer-events: none;
}

/* ---------- Responsive utility classes ---------- */
.br-mobile-only  { display: none; }
.br-desktop-only { display: block; }

/* ---------- Home screen (index) ---------- */
.br-home-title {
  position: absolute;
  left: 269px;
  top: 212px;
  width: 901px;
  height: 344px;
  background: url("../images/title-home-new.png") center / contain no-repeat;
}
.br-home-actions {
  position: absolute;
  left: 50%;
  top: 660px;
  transform: translateX(-50%);
  display: flex;
  gap: 60px;
}

/* ---------- Rules panel (Frame 25) ---------- */
.br-rules-panel {
  position: absolute;
  left: 50%;
  top: 96px;
  transform: translateX(-50%);
  width: 900px;
  height: 720px;
  background: url("../images/panel-rules.png") center / 100% 100% no-repeat;
  padding: 64px 90px 48px 90px;
  overflow: hidden;
}
.br-rules-title {
  font-family: "Maison Neue Extended", "Chakra Petch", "Be Vietnam Pro", sans-serif;
  font-weight: 800;
  font-size: 20px;
  line-height: 1.3;
  letter-spacing: 0.02em;
  color: #0070ff;
  text-transform: uppercase;
  margin: 0 0 18px;
}
.br-rules-h3 {
  font-weight: 800;
  font-size: 15px;
  color: #0070ff;
  margin: 14px 0 6px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.br-rules-p {
  font-size: 13px;
  line-height: 1.45;
  color: #0b55b4;
  margin: 0 0 4px;
}

/* Close / back control shared by the rules modal (index.php) and the
   standalone rules page (the-le.php) — a <button> in one, an <a> in the
   other, so the shared bits live on a class rather than an element type. */
.br-rules-close {
  position: absolute;
  right: 340px;
  top: 158px;
  width: 24px;
  height: 24px;
  background: url("../images/close.svg") center / contain no-repeat;
  border: none;
  cursor: pointer;
}

/* ---------- Card select (Frame 17) ---------- */
.br-section-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
.br-title-chon-the {
  top: 148px;
  width: 730px;
  height: 89px;
  background: url("../images/title-chon-the.png") center / contain no-repeat;
}

.br-card-row {
  position: absolute;
  left: 50%;
  top: 268px;
  transform: translateX(-50%);
  display: flex;
  gap: 24px;
}
.br-card-choice {
  width: 216px;
  height: 306px;
  /* Plain "cover" still left the art's baked-in soft outer glow (a ~27px
     fade-to-transparent ring in the source PNGs) uncropped on the
     height-bound axis, showing as a pale fringe between the frame and the
     CSS border - most visible on the green swatch against this page's
     green-tinted backdrop. Zooming in past cover crops that fade ring away
     on every edge instead of just the width-bound one. */
  background-size: 125% 115%;
  background-repeat: no-repeat;
  background-position: center;
  cursor: pointer;
  transition: transform .2s ease, filter .2s ease;
  border-width: 3px;
  border-style: solid;
  border-radius: 16px;
  padding: 0;
  /* White fill behind the art: card-green.png's photo cutout is real
     transparency now (the others are still flat opaque PNGs, pending the
     same treatment), so without this the hole shows whatever's behind
     the button instead of a clean white card interior. */
  background-color: #ffffff;
}
.br-card-choice:hover  { transform: translateY(-6px); }
.br-card-choice.br-is-selected {
  transform: translateY(-6px) scale(1.03);
  filter: drop-shadow(0 8px 18px rgba(0,49,197,0.35));
}
/* Colour → asset map (verified against extracted PNGs):
   card-a = ORANGE, card-b = PINK, card-c = PURPLE, card-d = BLUE, card-green = GREEN.
   Border colors sampled from each PNG's own border/background art. */
.br-card-choice[data-color="pink"]   { background-image: url("../images/card-b.png"); border-color: #FF86D9; }
.br-card-choice[data-color="orange"] { background-image: url("../images/card-a.png"); border-color: #FFBA79; }
.br-card-choice[data-color="green"]  { background-image: url("../images/card-green.png"); border-color: #67C684; }
.br-card-choice[data-color="purple"] { background-image: url("../images/card-c.png"); border-color: #4D56E2; }
.br-card-choice[data-color="blue"]   { background-image: url("../images/card-d.png"); border-color: #30AEFF; }

/* ---------- Sticker select (Frame 18) ---------- */
.br-title-them-sticker {
  top: 148px;
  width: 824px;
  height: 89px;
  background: url("../images/title-them-sticker.png") center / contain no-repeat;
}

.br-preview-card {
  position: absolute;
  left: 200px;
  top: 268px;
  width: 380px;
  height: 496px;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}
.br-preview-card.br-is-editable {
  cursor: pointer;
}

/* Desktop: an inert wrapper (the grid keeps its own absolute position and
   the arrows are hidden). Mobile: becomes the positioning context for the
   prev/next arrows overlaid on the horizontally-scrolling rail. */
.br-sticker-rail-wrap {
  position: static;
}
.br-sticker-arrow {
  display: none;
}

.br-sticker-grid {
  position: absolute;
  left: 660px;
  top: 268px;
  width: 550px;
  height: 380px;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: repeat(4, 1fr);
  gap: 12px;
}
.br-sticker-cell {
  background: #f0f3f9;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
  border: 2px solid transparent;
}
.br-sticker-cell:hover {
  transform: scale(1.06);
  box-shadow: 0 4px 12px rgba(0,49,197,0.15);
}
.br-sticker-cell.br-is-selected {
  border-color: #0070ff;
  background: #dbeafe;
}
.br-sticker-cell img {
  max-width: 70%;
  max-height: 70%;
  object-fit: contain;
  pointer-events: none;
}

/* ---------- Stickers placed on a card frame (real content) ----------
   Reusable across preview-card / card-editor / result-card.
   Positions come from inline style (see br_card_sticker_style() in inc/bootstrap.php)
   so they line up identically at every scale. */
.br-card-sticker {
  position: absolute;
  pointer-events: none;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.25));
}
.br-card-sticker img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ---------- Uploaded photo, clipped into the card's white cutout ----------
   Position comes from inline style (see br_card_photo_style()). */
.br-card-photo {
  position: absolute;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
}
.br-card-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.br-card-photo .br-icon {
  width: 15%;
  height: 15%;
  min-width: 28px;
  min-height: 28px;
  background: url("../images/icon-image-placeholder.png") center / contain no-repeat;
  opacity: 0.45;
}

/* ---------- Photo upload (Frame 19) ---------- */
.br-card-editor {
  position: absolute;
  left: 50%;
  top: 130px;
  transform: translateX(-50%);
  width: 390px;
  height: 520px;
}
/* The frame art (border + baked-in decorations, transparent where the
   photo shows through) rendered as the topmost layer of a card preview,
   over the photo/stickers below it. pointer-events:none so clicks reach
   whatever's underneath — the photo upload label, in the editor's case. */
.br-card-frame-overlay {
  position: absolute;
  inset: 0;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  pointer-events: none;
}
.br-card-editor .br-field-name,
.br-card-editor .br-field-slogan {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-weight: 800;
  letter-spacing: 0.05em;
  cursor: text;
  background: transparent;
  border: 0;
  text-align: center;
  outline: none;
  font-family: inherit;
  width: 60%;
}
/* Size/position/color matched to the mockup's rendered name (26px Dearpix,
   26px from the top of the same 390x520 frame art) so it doesn't visibly
   jump the moment the card advances to the result screen. */
.br-card-editor .br-field-name {
  top: 44px;
  font-size: 26px;
  color: #00d13a;
  font-family: "Dearpix", "Chakra Petch", "Press Start 2P", monospace;
  text-transform: uppercase;
  text-shadow: -1px 1px 0 #006f20;
}
/* Placeholder is name-placeholder.png (a pre-rendered pixel-art label),
   not native placeholder text — hide the browser's own text render and
   swap in the art while the field is empty. */
.br-card-editor .br-field-name::placeholder { color: transparent; text-shadow: none; }
.br-card-editor .br-field-name:placeholder-shown {
  background: url("../images/name-placeholder.png") center / auto 18px no-repeat;
}
/* A <button> (not an <input>, which can only ever show one line and would
   silently clip or scroll a longer slogan out of view) — wraps up to 2
   lines so a full preset/custom slogan always stays fully readable.
   Sized/positioned to match the mockup for the same reason as the name
   field above. */
.br-card-editor .br-field-slogan {
  bottom: 75px;
  left: 90px;
  right: 90px;
  transform: none;
  width: auto;
  font-size: 18px;
  color: #ffffff;
  cursor: pointer;
  padding: 0;
  white-space: normal;
  overflow-wrap: break-word;
  line-height: 1.35;
  max-height: 2.7em;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* Placeholder is slogan-placeholder.png, not text — interactions.js
   leaves the button empty (no textContent) until a slogan is actually
   chosen, so :empty is exactly "still showing the placeholder". */
.br-card-editor .br-field-slogan:empty {
  /* No text content means no line box to size against — without an
     explicit height the button (and its background image) collapses to
     0px tall. */
  min-height: 1.35em;
  background: url("../images/slogan-placeholder.png") center / auto 14px no-repeat;
}

.br-card-editor .br-photo-slot {
  /* Kept in sync with CARD_PHOTO_BOX in inc/bootstrap.php (left:84 top:117
     w:221 h:251 on the 390×520 canonical box) — this element is styled
     directly in CSS rather than via br_card_photo_style(), unlike the
     confirm/result screens' .br-card-photo boxes. */
  position: absolute;
  left: 84px;
  right: 85px;
  top: 117px;
  bottom: 152px;
  background: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: 0;
}
.br-card-editor .br-photo-slot .br-icon {
  width: 44px;
  height: 44px;
  background: url("../images/icon-image-placeholder.png") center / contain no-repeat;
  opacity: 0.5;
}
.br-card-editor .br-photo-slot img.br-photo-preview {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.br-photo-hint {
  position: absolute;
  left: 50%;
  top: 660px;
  transform: translateX(-50%);
  width: 380px;
  font-size: 12px;
  color: #0b55b4;
  text-align: center;
  transition: color .15s ease;
}
.br-photo-hint.br-is-warning {
  color: #c0392b;
  font-weight: 700;
}

/* ---------- Slogan select (Frame 27) ---------- */
.br-slogan-panel {
  position: absolute;
  left: 50%;
  top: 128px;
  transform: translateX(-50%);
  width: 879px;
  height: 613px;
  background: url("../images/panel-slogans.png") center / 100% 100% no-repeat;
  padding: 76px 100px 60px 100px;
}
/* Horizontal scroll-snap carousel: each .br-slogan-page is one full page
   (custom row + up to 4/5 presets), swipeable on touch and paged via the
   dots below (wired in interactions.js). No JS library — native scroll
   snapping does the paging/animation. */
.br-slogan-carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.br-slogan-carousel::-webkit-scrollbar { display: none; }
.br-slogan-page {
  flex: 0 0 100%;
  scroll-snap-align: start;
}
.br-slogan-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.br-slogan-item {
  position: relative;
  height: 60px;
  background: url("../images/slogan-row.png") center / 100% 100% no-repeat;
  display: flex;
  align-items: center;
  padding-left: 62px;
  padding-right: 24px;
  cursor: pointer;
  color: #0070ff;
  font-weight: 700;
  font-size: 18px;
  transition: filter .15s ease;
}
.br-slogan-item:hover { filter: brightness(1.05); }
/* Radio-style selection marker. icon-uncheck.png/icon-check.png (despite
   their names) are actually pre-rendered "NHẤN ĐỂ ĐIỀN..." label text
   images, not tick icons — mislabeled assets left over from an earlier
   export. dot.png/check.png are the real unselected/selected graphics. */
.br-slogan-item .br-tick {
  position: absolute;
  left: 22px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  background: url("../images/dot.png") center / contain no-repeat;
}
.br-slogan-item.br-is-selected .br-tick {
  background-image: url("../images/check.png");
}
.br-slogan-item.br-is-selected {
  background: url("../images/slogan-row-active.png") center / 100% 100% no-repeat;
  color: #0031c5;
}
/* "Nội dung khác" free-input variant */
.br-slogan-item.br-slogan-item--custom {
  background: linear-gradient(180deg, #74edff 0%, #a3f2ff 100%);
}
/* Selected (the default state on popup open, since sloganId starts as
   'custom') must still pick up the same pixel-bordered art as every other
   selected row, not the plain gradient above — same specificity as that
   rule, so this has to come after it to win. */
.br-slogan-item.br-slogan-item--custom.br-is-selected {
  background: url("../images/slogan-row-active.png") center / 100% 100% no-repeat;
}
.br-slogan-item.br-slogan-item--custom input {
  flex: 1;
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  color: inherit;
  border-bottom: 1px solid rgba(0,112,255,0.4);
  padding: 4px 0;
}

.br-slogan-pager {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 22px;
}
.br-slogan-pager .br-dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border-radius: 50%;
  background: #ffffff;
  border: 1px solid #0070ff;
  cursor: pointer;
}
.br-slogan-pager .br-dot.br-is-active { background: #74edff; }

.br-slogan-confirm {
  position: absolute;
  left: 50%;
  bottom: 42px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
/* Sits below the slogan panel itself (which doesn't span the full stage
   height, unlike every other screen's back link) rather than inside it. */
.br-slogan-back {
  position: absolute;
  left: 50%;
  top: 790px;
  transform: translateX(-50%);
}
/* As a popup (opened from the photo screen's slogan preview) the screen
   underneath is still visible and already has its own Quay lại — showing
   this one too doubles it up. Chốt đơn already closes the popup on its
   own, so it's the only exit needed here. */
.br-screen.br-is-popup .br-slogan-back {
  display: none;
}

/* ---------- Result / share (Frame 21) ----------
   photo-sample.png is a FULLY-composited card bitmap (frame + stickers + person),
   so we render it as a single background and only overlay the personal fields. */
.br-result-title {
  position: absolute;
  left: 50%;
  top: 100px;
  transform: translateX(-50%);
  width: 620px;
  height: 130px;
  background: url("../images/title-chao-phien-ban-moi.png") center / contain no-repeat;
}
.br-result-card {
  position: absolute;
  left: 50%;
  top: 240px;
  transform: translateX(-50%);
  width: 290px;
  height: 386px;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}
.br-result-card .br-name {
  position: absolute;
  top: 33px;
  left: 0;
  right: 0;
  text-align: center;
  color: #00d13a;
  font-family: "Dearpix", "Chakra Petch", "Press Start 2P", monospace;
  font-weight: 400;
  font-size: 19px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-shadow: -1px 1px 0 #006f20;
}
.br-result-card .br-slogan {
  position: absolute;
  bottom: 56px;
  left: 67px;
  right: 67px;
  text-align: center;
  color: #ffffff;
  font-weight: 800;
  font-size: 13px;
  line-height: 1.35;
  letter-spacing: 0.02em;
  /* Natural case, not uppercase — matches the mockup, which sentence-cases
     the slogan while the name above it stays uppercase. */
  /* A long preset/custom slogan wraps up to 2 lines and stays fully
     readable rather than growing past its footer band on the card art. */
  overflow-wrap: break-word;
  max-height: 2.7em;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.br-result-actions {
  position: absolute;
  left: 50%;
  top: 660px;
  transform: translateX(-50%);
  display: flex;
  gap: 60px;
}

/* ---------- Utility ---------- */
.br-visually-hidden {
  position: absolute !important;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px; width: 1px;
  margin: -1px; overflow: hidden;
  padding: 0; white-space: nowrap;
}

/* =========================================================
   MOBILE LAYOUT — matches the Figma "UI_Mobile" 393×852 designs.
   Under 720px viewport width, discard the fixed 1440×850 scaled canvas
   (stage.js skips the transform entirely below this width — see
   br_fit()) and flow the stage as a natural portrait column instead.
   ========================================================= */
@media (max-width: 720px) {
  .br-mobile-only  { display: block; }
  .br-desktop-only { display: none !important; }

  html, body {
    background: url("../images/bg-grid-mobile.jpg") center / cover no-repeat fixed, #b7ddff;
  }

  /* Kill the scaled canvas layout. */
  .br-stage-wrap,
  .br-stage-wrap.br-is-portrait {
    position: static !important;
    inset: auto;
    width: 100%;
    height: auto !important;
    min-height: 100vh;
    overflow: visible;
    background: transparent;
    display: block;
  }
  .br-stage {
    position: relative;
    width: 100%;
    max-width: 440px;
    height: auto;
    margin: 0 auto;
    padding: 76px 20px 44px;
    transform: none !important;
    background: transparent;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  /* Header — pinned to top of the stage column. */
  .br-brand-logo {
    left: 20px;
    top: 30px;
    width: 152px;
    height: 26px;
  }
  .br-campaign-badge {
    right: 18px;
    top: 18px;
    width: 128px;
    height: 48px;
  }

  .br-section-heading {
    position: static;
    margin: 32px auto 24px;
    font-size: 30px;
    -webkit-text-stroke-width: 3.5px;
    filter:
      drop-shadow(0 3px 0 rgba(0,49,197,0.45))
      drop-shadow(0 6px 10px rgba(0,49,197,0.25));
  }

  /* ---------- HOME ---------- */
  .br-home-title {
    position: static;
    left: auto; top: auto;
    transform: none;
    width: 100%;
    max-width: 340px;
    aspect-ratio: 901 / 344;
    height: auto;
    margin: 84px auto 0;
  }
  .br-home-actions {
    position: static;
    top: auto;
    transform: none;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    margin: auto auto 40px;
    padding-top: 80px;
  }
  .br-btn-bat-dau, .br-btn-the-le,
  .br-btn-xac-nhan, .br-btn-chot-don,
  .br-btn-chia-se, .br-btn-quay-lai-main {
    width: 200px;
    height: 70px;
  }

  /* ---------- RULES ---------- */
  .br-rules-panel {
    position: static;
    top: auto;
    transform: none;
    width: 100%;
    max-width: 360px;
    height: auto;
    min-height: 0;
    margin: 24px auto 32px;
    padding: 34px 26px 30px;
    background-size: 100% 100%;
  }
  .br-rules-title { font-size: 15px; margin: 0 0 14px; }
  .br-rules-h3    { font-size: 14px; margin: 14px 0 4px; }
  .br-rules-p     { font-size: 12px; line-height: 1.42; }
  /* The absolute-positioned close X would land off in space once the
     panel is no longer at a fixed pixel offset; the mobile column is
     short enough that a simple top-of-panel close reads fine instead. */
  .br-rules-close {
    position: static;
    display: block;
    margin: 0 auto 16px;
  }

  /* ---------- CARD SELECT (3-column grid) ---------- */
  .br-chon-the-title-text {
    margin-top: 20px;
    margin-bottom: 30px;
  }
  .br-card-row {
    position: static;
    top: auto;
    transform: none;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    row-gap: 16px;
    justify-items: center;
    width: 100%;
    max-width: 340px;
    margin: 0 auto;
  }
  .br-card-choice {
    width: 100%;
    max-width: 104px;
    height: 148px;
    border-width: 2px;
    border-radius: 14px;
  }
  .br-card-choice.br-is-selected { transform: scale(1.03); }

  /* Bottom action buttons — flow after the content instead of pinning
     to a fixed px offset that no longer matches the column's height. */
  .br-action-stack {
    position: static;
    top: auto !important;
    transform: none;
    margin: auto auto 32px;
    padding-top: 48px;
    gap: 8px;
  }

  /* ---------- STICKER SELECT — preview stacks above the sticker rail ---------- */
  .br-preview-card {
    /* relative, not static: its frame-overlay child is inset:0 and needs
       this box to stay its containing block, or it escapes to size itself
       against .br-stage instead. */
    position: relative;
    left: auto; top: auto;
    margin: 0 auto 22px;
    width: 250px;
    height: 336px;
  }
  .br-sticker-rail-wrap {
    position: relative;
    width: 100%;
    max-width: 360px;
    margin: 0 auto;
  }
  .br-sticker-grid {
    position: static;
    left: auto; top: auto;
    width: 100%;
    height: auto;
    margin: 0 auto;
    /* Horizontal slider — ~4 stickers visible, snap-scrolled via the
       prev/next arrows or a direct swipe. */
    display: flex;
    gap: 14px;
    padding: 4px 34px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .br-sticker-grid::-webkit-scrollbar { display: none; }
  .br-sticker-cell {
    flex: 0 0 calc((100% - 42px - 68px) / 4);
    aspect-ratio: 1;
    scroll-snap-align: start;
  }
  .br-sticker-cell img { max-width: 72%; max-height: 72%; }
  .br-sticker-arrow {
    display: block;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 24px;
    height: 24px;
    color: #0070ff;
    font-size: 22px;
    font-weight: 800;
    line-height: 22px;
    text-align: center;
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
    z-index: 2;
    text-shadow: 0 1px 2px rgba(0,49,197,0.25);
  }
  .br-sticker-arrow.br-prev { left: 2px; }
  .br-sticker-arrow.br-next { right: 2px; }

  /* ---------- PHOTO EDITOR ---------- */
  .br-card-editor {
    /* relative: keeps it the containing block for its absolutely
       positioned frame-overlay/photo-slot/field children. */
    position: relative;
    left: auto;
    top: auto;
    transform: none;
    width: 280px;
    height: 372px;
    margin: 24px auto 0;
  }
  .br-card-editor .br-field-name   { top: 32px; font-size: 19px; }
  .br-card-editor .br-field-slogan { bottom: 54px; left: 65px; right: 65px; font-size: 13px; }
  .br-card-editor .br-photo-slot   { left: 60px; right: 61px; top: 84px; bottom: 109px; }
  .br-photo-hint {
    position: static;
    top: auto;
    transform: none;
    width: 100%;
    max-width: 280px;
    margin: 10px auto 0;
  }

  /* ---------- SLOGAN ---------- */
  .br-slogan-panel {
    /* relative: keeps it the containing block for the absolutely
       positioned .br-slogan-confirm button pinned to its bottom edge. */
    position: relative;
    left: auto;
    top: auto;
    transform: none;
    width: 100%;
    max-width: 360px;
    height: auto;
    margin: 20px auto 0;
    padding: 40px 24px 100px;
    background-size: 100% 100%;
  }
  /* Desktop's slogan-row(-active).png is an 11:1 strip — stretched to a
     mobile row's much narrower box it'd swell the pixel-art border/corners
     out of proportion, so mobile gets its own art sized for this ratio. */
  .br-slogan-item { font-size: 13px; height: 46px; padding-left: 48px; padding-right: 14px; background-image: url("../images/slogan-row-mobile.png"); }
  .br-slogan-item.br-is-selected,
  .br-slogan-item.br-slogan-item--custom.br-is-selected { background-image: url("../images/slogan-row-active-mobile.png"); }
  .br-slogan-item .br-tick { left: 16px; width: 18px; height: 18px; }
  .br-slogan-confirm {
    position: absolute;
    left: 50%;
    bottom: 22px;
    transform: translateX(-50%);
  }
  .br-slogan-back {
    position: static;
    left: auto;
    top: auto;
    transform: none;
    display: block;
    text-align: center;
    margin: 16px auto 32px;
  }

  /* ---------- RESULT ---------- */
  .br-result-title {
    position: static;
    top: auto;
    transform: none;
    margin: 22px auto 16px;
    width: 100%;
    max-width: 320px;
    height: 74px;
  }
  .br-result-card {
    /* relative: keeps it the containing block for its absolutely
       positioned photo/frame-overlay/name/slogan children. */
    position: relative;
    left: auto;
    top: auto;
    transform: none;
    margin: 0 auto 30px;
    width: 220px;
    height: 292px;
  }
  .br-result-card .br-name   { font-size: 15px; top: 25px; }
  .br-result-card .br-slogan { font-size: 10px; bottom: 42px; left: 51px; right: 51px; }
  .br-result-actions {
    position: static;
    top: auto;
    transform: none;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    margin: 20px auto 0;
  }
}

/* ---------- TABLET (721–1024px) ----------
   stage.js's portrait branch already width-fits the scaled canvas here;
   this just keeps the letterboxing tidy at the top instead of vertically
   centering a canvas taller than the viewport. */
@media (min-width: 721px) and (max-width: 1024px) {
  .br-stage-wrap.br-is-portrait { align-items: flex-start; }
}
