/* ==================================================================
   4YouAll — website
   Every colour is a CSS custom property bound at runtime from
   data/yaskins_web.json (the app's own resolved skin dump).
   No palette is hardcoded here. Switching skin rebinds the variables.
   ================================================================== */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
button, input, select, textarea { font: inherit; color: inherit; }

:root {
  /* Bound at runtime from the skin file — these are only fallbacks, so they
     are DARK, not a skin colour. JS overwrites --bg-1/--bg-2 via applySkin on
     every load; the fallback is visible only in the pre-JS window on a cold
     load or reload. An amber fallback painted a coloured flash there (the
     header and below-hdr use this gradient directly), regardless of the active
     skin. Dark matches the presplash cover, so that window is invisible. */
  --bg-1:#14181C; --bg-2:#14181C; --bg-dir:180deg;
  --text:#4F3300;
  --border:#4F3300; --border-w:1px; --radius:4px;
  --selection:rgba(79,51,0,0.15);
  --icon-bg:transparent; --icon-border:#4F3300; --icon-border-w:1px;
  --icon-radius:4px; --icon-label:#4F3300;
  --sym-1:#FFFFFF; --sym-2:#919191; --sym-3:#5E5E5E;
  --sym-4:#1A1A1A; --sym-5:#ED2939; --sym-6:#919191;
  --field-bg:#4F3300; --field-text:#FFFFFF;
  --field-placeholder:rgba(255,255,255,.5);
  --field-radius:2px; --field-cursor:#FFBF00;
  --btn-radius:2px; --btn-disabled:.5;

  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --font-th:'Noto Sans Thai','Inter',sans-serif;
}
html[lang="th"] { --font: var(--font-th); }

/* The crawler-readable copy generated by build_seo.py. Present in the markup
   for anything that reads HTML without running JavaScript — search engines, AI
   summarisers, link-preview bots — but not shown to a human visitor, who gets
   the app instead. The text is identical to what the app renders, so this is
   not cloaking. */
#seo {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

html, body { height: 100%; }
body {
  font-family: var(--font);
  color: var(--text);
  background: #14181C;
  display: grid; place-items: center;
  min-height: 100dvh;
  /* On a real phone the app fills the screen and nothing scrolls. On a desktop
     the phone is a fixed 820px tall, which can be taller than a short laptop
     window — so allow the page to scroll rather than clipping the bottom off. */
  overflow: hidden auto;
  padding: 20px 0;
}
@media (max-width: 419px) {
  body { overflow: hidden; padding: 0; }
}
::selection { background: var(--selection); }

/* ---------- The phone: the whole site lives inside this ----------
   On a desktop the dimensions are FIXED — 380x820 — and do not respond to the
   window at all. The site is a phone app; resizing the browser should not
   reflow it into something else. Below that we go full-bleed, which is the
   real phone case.

   No bezel: against the dark page it was invisible anyway, and its rounded
   corners were the cause of a Safari artefact — the header's own square-cornered
   gradient would sometimes fail to clip against the rounded parent and bleed
   through at the top corners. Removing the rounding removes the artefact. */
.phone {
  position: relative;
  width: 100%; height: 100dvh;
  display: flex; flex-direction: column;
  overflow: hidden;
  /* Dark by default. The skin gradient is applied only once JS has resolved the
     skin variables and added `.skinned` — otherwise, on a reload, the phone's
     own gradient can paint for a frame (with stale or default colours) before
     the presplash cover and applySkin catch up, giving a coloured flash. */
  background: #14181C;
}
.phone.skinned {
  background: linear-gradient(var(--bg-dir), var(--bg-1), var(--bg-2));
}
@media (min-width: 420px) {
  .phone {
    width: 380px;
    height: 760px;
    flex: 0 0 auto;
    border-radius: 18px;
    /* Own stacking context: makes the corner clip reliable rather than leaving
       it to the compositor, which is where the Safari bleed came from. */
    isolation: isolate;
    box-shadow: 0 30px 80px rgba(0,0,0,.5);
  }
  /* The header paints its own gradient to the very top edge. Give it matching
     top corners so there is no square-cornered background for Safari to clip
     against the rounded parent — that mismatch was the artefact, not the
     rounding itself. Same for the banner at the bottom, and for anything else
     that paints its own background across the whole phone. */
  .phone .hdr      { border-radius: 18px 18px 0 0; }
  .phone .banner   { border-radius: 0 0 18px 18px; }
  .phone .splash   { border-radius: 18px; }
  .phone .presplash{ border-radius: 18px; }
  .phone .backdrop { border-radius: 18px; }
}

/* ---------------------- Header view ----------------------
   The header uses the SAME gradient as the content, but with its start and
   end points SWAPPED (YAHeaderView: startPoint = skin.gradientEndPoint,
   endPoint = skin.gradientStartPoint). Same colours, opposite direction —
   so the header's bottom edge meets the content's top edge on the same
   colour, and the two join seamlessly.                                     */
.hdr {
  position: relative;
  flex: 0 0 auto;
  height: 86px;
  display: flex; align-items: center; justify-content: space-between;
  /* 16pt from the top edge: flush to the corner reads as cramped rather than
     composed. The ornaments still sit ~1pt from the left and right edges. */
  padding: 16px 1px 0;
  background: linear-gradient(var(--hdr-dir), var(--bg-1), var(--bg-2));
}
.orn { width: 70px; height: 70px; object-fit: contain; flex: 0 0 auto; }

/* Coin: continuous 3D Y-axis rotation, 20s per turn, with backface hiding —
   matching YAHeaderView's display-link animation. */
.coin {
  position: relative;
  width: 58px; height: 58px;
  flex: 0 0 auto;
  perspective: 600px;
}
.coin-inner {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  animation: coin-spin 20s linear infinite;
}
.coin img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: contain;
  backface-visibility: hidden;
}
.coin-back { transform: rotateY(180deg); }
@keyframes coin-spin {
  from { transform: rotateY(0deg); }
  to   { transform: rotateY(360deg); }
}
/* Reduced motion: no spin. Show the backside, as requested. */
@media (prefers-reduced-motion: reduce) {
  .coin-inner { animation: none; transform: rotateY(180deg); }
}

/* The strip + content share the content gradient as one continuous surface,
   so the seamless join with the reversed header gradient is preserved. */
.below-hdr {
  flex: 1 1 auto;
  display: flex; flex-direction: column;
  min-height: 0;
  background: linear-gradient(var(--bg-dir), var(--bg-1), var(--bg-2));
}

/* ---- Spacing strip: a 20pt band between the header and the app grid. ---- */
.strip {
  flex: 0 0 auto;
  height: 20px;
}

/* ---------------- Splash: the first visit only ----------------
   A full-bleed black screen, vertically centred, that gives way to the gold
   app. Shown once; thereafter Welcome is an ordinary skinned view opened from
   the grid, so it obeys the skin picker like everything else. */
.splash {
  position: absolute; inset: 0; z-index: 40;
  background: #1E2228;
  color: #F0EBE2;
  display: flex; flex-direction: column; justify-content: center;
  padding: 0 34px;
  transition: opacity .55s ease;
}
.splash.out { opacity: 0; pointer-events: none; }

/* Static pre-splash cover — same dark as the real splash, painted from the
   first frame so no gold home shows during the Splash.html fetch. Sits just
   under the real splash's z-index; removed by boot() once the splash mounts. */
.presplash {
  position: absolute; inset: 0; z-index: 39;
  background: #1E2228;
}

.splash .rule {
  width: 78px; height: 4px;
  background: var(--bg-1);
  margin-bottom: 26px;
}
.splash h1 {
  font-size: 40px; font-weight: 700;
  line-height: 1.08; letter-spacing: -.025em;
  margin-bottom: 22px;
}
.splash p {
  font-size: 17px; line-height: 1.5;
  color: #C9C3B8;
  margin-bottom: 14px;
}
.splash p.lede { color: #E4DFD5; }
/* The entry button is bilingual — Thai above, English below — ALWAYS both,
   whatever the current language. It is the one place where showing both IS
   the message: the product's premise, demonstrated before a word of copy. */
.splash .enter {
  margin-top: 40px;
  align-self: center;
  display: block;
  text-align: center;
  color: var(--text); background: var(--bg-1);
  border: 0; border-radius: 3px;
  padding: 13px 30px;
  cursor: pointer;
  line-height: 1.25;
}
.splash .enter .th {
  display: block;
  font-size: 15px; font-weight: 700;
}
.splash .enter .en {
  display: block;
  font-size: 13px; font-weight: 500;
  opacity: .72;
}
.splash .enter:hover { filter: brightness(1.08); }
.splash .enter:focus-visible { outline: 2px solid #F0EBE2; outline-offset: 3px; }

/* The closing sign-off, below the button with room to breathe. */
.splash .domain {
  margin-top: 46px;
  text-align: center;
  font-size: 12.5px; letter-spacing: .09em;
  color: #8C8578;
}
.splash .domain strong { color: #C9C3B8; font-weight: 600; letter-spacing: .12em; }

@media (prefers-reduced-motion: reduce) { .splash { transition: none; } }

/* ---------------- Skin picker popup ----------------
   Presented from the palette in the header's lower right, in the manner of
   the app's YAPositionedPicker: a backdrop plus a bordered list. */
.backdrop {
  position: absolute; inset: 0; z-index: 20;
  background: rgba(0,0,0,.35);
  opacity: 0; transition: opacity .2s ease;
}
.backdrop.in { opacity: 1; }

.picker {
  position: absolute; z-index: 21;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(.92);
  min-width: 190px;
  max-width: calc(100% - 32px);
  width: max-content;
  background: linear-gradient(var(--bg-dir), var(--bg-1), var(--bg-2));
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 14px 40px rgba(0,0,0,.4);
  overflow: hidden;
  opacity: 0;
  transition: transform .18s cubic-bezier(.32,.72,0,1), opacity .18s ease;
}
.picker.in { transform: translate(-50%, -50%) scale(1); opacity: 1; }
.picker button {
  display: block; width: 100%;
  text-align: left;
  font-size: 14px; font-weight: 500; line-height: 1.35;
  color: var(--text);
  background: none; border: 0;
  padding: 11px 14px;
  cursor: pointer;
  white-space: normal;      /* long role options wrap rather than truncate */
}
.picker button + button { border-top: 1px solid var(--border); }
.picker button:hover { background: var(--selection); }
.picker button[aria-current="true"] { font-weight: 700; background: var(--selection); }
.picker button:focus-visible { outline: 2px solid var(--text); outline-offset: -2px; }
@media (prefers-reduced-motion: reduce) {
  .backdrop, .picker { transition: none; }
}

/* ---------------------- YAContentView ---------------------- */
.content { position: relative; flex: 1 1 auto; overflow: visible; min-height: 0; }

/* The home surface: the grid, then the proof block below it. Scrolls as one. */
.home {
  position: absolute; inset: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column;
}

/* Grid: the app's exact metrics — 4 columns of 84x96pt tiles, each with a
   40x40pt icon box and an 84x26pt label area (up to two lines). */
.grid {
  flex: 0 0 auto;
  padding: 0 10px 24px;
  display: grid;
  grid-template-columns: repeat(4, 84px);
  justify-content: center;
  gap: 4px 8px;
  align-content: start;
}
.tile {
  width: 84px; height: 96px;
  background: none; border: 0; padding: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center;
}
.tile[disabled] { cursor: default; opacity: var(--btn-disabled); }

/* The bordered box is the 40x40 icon plus its surrounding padding — in the
   app the border sits around the icon, not around the whole cell. */
.tile .box {
  width: 66px; height: 66px;
  display: grid; place-items: center;
  background: var(--icon-bg);
  border: var(--icon-border-w) solid var(--icon-border);
  border-radius: var(--icon-radius);
  flex: 0 0 auto;
}
.tile .box svg { width: 40px; height: 40px; }
/* A tile whose icon is an emoji (Language, Country colours) rather than an
   SVG. Sized to sit in the same 40x40 icon area. */
.tile .box .emoji {
  font-size: 30px; line-height: 40px;
  height: 40px;
  display: block;
}

.tile .lbl {
  width: 84px; height: 26px;
  margin-top: 4px;
  display: flex; align-items: flex-start; justify-content: center;
  font-size: 12px; font-weight: 500; line-height: 13px;
  text-align: center; color: var(--icon-label);
  overflow: hidden;
}
.tile:not([disabled]):hover .box { background: var(--selection); }
.tile:focus-visible .box { outline: 2px solid var(--icon-border); outline-offset: 2px; }

/* Per-row symbol colours — the app's appIconSymbolColors, 4 per row */
.grid .tile:nth-child(-n+4)                 .box svg { color: var(--sym-1); }
.grid .tile:nth-child(n+5):nth-child(-n+8)  .box svg { color: var(--sym-2); }
.grid .tile:nth-child(n+9):nth-child(-n+12) .box svg { color: var(--sym-3); }

/* ---------------- Proof: the app itself ----------------
   Fills the space below the grid with the strongest thing available — the
   real product. The button is the app's actionButton idiom; tapping reveals
   two live screenshots (Thai UI on the Thailand skin, English UI on the
   Philippine skin) which slide in from either side. They stay until tapped:
   they are evidence, and evidence should not be snatched away from someone
   still reading it. Tapping them returns the button. */
.proof {
  position: relative;
  /* Intrinsic height, not flexed. On a tall viewport this still fills the
     space below the grid; on a short one it keeps its full height and pushes
     the home surface past the viewport, so `.home`'s overflow-y engages and
     the page scrolls — rather than the screenshots being squeezed to fit. */
  flex: 1 0 auto;
  min-height: 420px;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 26px 16px 24px;
}
.proof-btn {
  font-size: 15px; font-weight: 600;
  color: var(--text);
  background: var(--icon-bg);
  border: var(--border-w) solid var(--border);
  border-radius: var(--btn-radius);
  padding: 13px 26px;
  cursor: pointer;
}
.proof-btn:hover { background: var(--selection); }
.proof-btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.proof.open .proof-btn { visibility: hidden; }

.shots {
  position: absolute; inset: 10px 12px 12px;
  display: flex; align-items: flex-start; justify-content: center;
  gap: 12px;
  cursor: pointer;
}
/* display:flex above overrides the `hidden` attribute's implicit display:none,
   which would leave the element invisible but still swallowing clicks meant
   for the button beneath it. */
.shots[hidden] { display: none; }
.shots img {
  width: 47%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 9px;
  box-shadow: 0 8px 26px rgba(0,0,0,.3);
  transition: transform .28s cubic-bezier(.32,.72,0,1), opacity .28s ease;
  opacity: 0;
}
.shots .shot-l { transform: translateX(-60px); }
.shots .shot-r { transform: translateX(60px); transition-delay: .06s; }
.proof.open .shots img { transform: translateX(0); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .shots img { transition: none; }
}

/* ---------------- Views: slide in from the right ----------------
   The view is pulled up by 20px so it spans the spacer, letting the back
   button sit over it — as the app's 30x30pt back button sits directly below
   the header. Content is padded back down so nothing else moves. */
.view {
  position: absolute;
  top: -20px; left: 0; right: 0; bottom: 0;
  background: linear-gradient(var(--bg-dir), var(--bg-1), var(--bg-2));
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 26px 22px 30px;
  transform: translateX(100%);
  transition: transform .32s cubic-bezier(.32,.72,0,1);
  will-change: transform;
}
.view.in { transform: translateX(0); }

/* Once the slide has finished, drop the transform altogether. A lingering
   transform (even translateX(0)) makes the view a containing block, and iOS
   Safari will then refuse to raise the keyboard for inputs inside it — the
   field focuses but no keyboard appears. Removing it after the animation
   costs nothing and fixes that. */
.view.settled { transform: none; will-change: auto; }
/* The view is focused programmatically for a11y (see openView) — it is a
   container, not a control, so it must not paint a focus ring. */
.view:focus { outline: none; }
@media (prefers-reduced-motion: reduce) { .view { transition: none; } }

/* The back button sits in a 30x30pt box directly below the header — it
   overlaps the 20pt spacer rather than occupying a row of its own, exactly as
   in the app. Regular weight, not bold. */
.view-top { height: 0; }
.back {
  position: absolute;
  top: 0; left: 0;
  z-index: 3;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: none; border: 0; padding: 0;
  cursor: pointer;
  font-size: 20px; font-weight: 400; line-height: 1;
  color: var(--text);
  /* The arrow is an icon, not prose. Pin it to the Latin font so it does not
     get redrawn by Noto Sans Thai when the language switches. */
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.back:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

/* ---- Shared view typography (used by the view/*.html files) ---- */
.v-title { font-size: 30px; font-weight: 700; letter-spacing: -.02em; text-align: center; }
.v-sub   { text-align: center; font-size: 15px; line-height: 1.45; opacity: .82; margin: 6px 0 20px; }
.v-date  { text-align: center; font-size: 11px; letter-spacing: .1em;
           text-transform: uppercase; opacity: .6; margin-bottom: 18px; }
.v-body  { font-size: 14.5px; line-height: 1.6; opacity: .9; }
.v-body + .v-body { margin-top: 12px; }

/* Expandable cards. Collapsed: heading + one-line teaser. Tap to reveal the
   full argument. The reader chooses what to read rather than facing a wall. */
.cards { display: flex; flex-direction: column; gap: 13px; }
.card {
  display: block; width: 100%;
  text-align: left;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius);
  background: none;
  padding: 13px 15px;
  cursor: pointer;
  color: inherit;
}
.card:hover { background: var(--selection); }
.card:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
}
.card-title { font-size: 15px; font-weight: 700; }

/* Chevron: rotates a quarter-turn when the card opens. */
.chev {
  flex: 0 0 auto;
  width: 9px; height: 9px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg);
  transition: transform .22s ease;
  opacity: .65;
  margin-bottom: 3px;
}
.card[aria-expanded="true"] .chev { transform: rotate(225deg); margin-bottom: -3px; }

.card-teaser {
  display: block;
  margin-top: 5px;
  font-size: 13.5px; line-height: 1.5;
  opacity: .85;
}

.card-detail {
  display: block;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height .3s cubic-bezier(.32,.72,0,1), opacity .25s ease,
              margin-top .3s ease;
}
.card-detail > span {
  display: block;
  font-size: 13.5px; line-height: 1.6;
  padding-top: 11px;
  border-top: 1px solid var(--border);
  opacity: .9;
}
/* Multi-paragraph detail copy. */
.card-detail p + p { margin-top: 10px; }
.card[aria-expanded="true"] .card-detail {
  max-height: 900px;
  opacity: 1;
  margin-top: 11px;
}

/* "What you get": what 4YouAll gives its users. Every item a commitment. */
.benefits { list-style: none; margin: 0; padding: 0; }
.benefits li {
  position: relative;
  padding-left: 17px;
  margin-bottom: 10px;
  font-size: 13.5px; line-height: 1.5;
}
.benefits li:last-child { margin-bottom: 0; }
.benefits li::before {
  content: '';
  position: absolute;
  left: 0; top: 7px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: .55;
}

@media (prefers-reduced-motion: reduce) {
  .chev, .card-detail { transition: none; }
}

.cta {
  display: block; width: 100%; margin-top: 22px;
  font-size: 16px; font-weight: 600;
  color: var(--text); background: var(--icon-bg);
  border: var(--border-w) solid var(--border);
  border-radius: var(--btn-radius);
  padding: 15px; cursor: pointer;
}
.cta:hover { background: var(--selection); }
.cta:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.shot {
  width: 100%; aspect-ratio: 9/16;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 14px;
  display: grid; place-items: center;
  font-size: 12px; opacity: .45;
  object-fit: cover;
}

/* ---------------- Flow carousel ----------------
   A centred screenshot with its neighbours peeking either side, so it is
   visibly scrollable rather than looking like a single image. Swipe, tap a
   peeking neighbour, or use the dots.

   Slides are sized by HEIGHT and keep their own aspect ratio: the Android
   device is narrower and taller than the iPhone, and forcing both into one
   frame would distort them. The difference is real, and showing it is honest. */
.carousel {
  margin: 22px -22px 0;          /* bleed to the view's edges */
  padding: 0;
  position: relative;
}
.track {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Padding either side is what lets the first and last slide sit centred
     while their neighbours peek. */
  padding: 4px calc(50% - 86px) 4px;
}
.track::-webkit-scrollbar { display: none; }

.slide {
  flex: 0 0 auto;
  height: 374px;                 /* same size as the home screen's proof shots */
  scroll-snap-align: center;
  border-radius: 9px;
  box-shadow: 0 8px 26px rgba(0,0,0,.3);
  cursor: pointer;
  display: block;
  width: auto;                   /* width follows the image's own ratio */
  /* Full opacity throughout — every screenshot is legible. The neighbours sit
     slightly back in scale, so the centred one has visual precedence and the
     peek reads as deliberate rather than as an image that happens to be cut. */
  transform: scale(.93);
  transition: transform .28s ease;
}
.slide.current {
  transform: scale(1);
  cursor: default;
}
@media (prefers-reduced-motion: reduce) {
  .slide { transition: none; }
  .track { scroll-behavior: auto; }
}

.dots {
  display: flex; justify-content: center; gap: 7px;
  margin-top: 14px;
}
.dots button {
  width: 7px; height: 7px;
  padding: 0; border: 0; border-radius: 50%;
  background: var(--text);
  opacity: .3;
  cursor: pointer;
  transition: opacity .2s ease, transform .2s ease;
}
.dots button[aria-current="true"] { opacity: .85; transform: scale(1.25); }
.dots button:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }

/* ---- Form fields: the app's inputField skin ---- */
.field { margin-bottom: 12px; }
.field label { display: block; font-size: 12px; font-weight: 600; margin-bottom: 5px; }
/* The role select. The longest option does not fit on one line, so the field
   grows to two rather than truncating — the option text is the qualification
   signal and must be readable in full. `select` cannot wrap, so this is a
   button that opens the same picker used for skins. */
.field .select-btn {
  width: 100%;
  text-align: left;
  font-size: 14px; line-height: 1.35;
  color: var(--field-text);
  background: var(--field-bg);
  border: 0; border-radius: var(--field-radius);
  padding: 11px 34px 11px 12px;
  min-height: 42px;
  cursor: pointer;
  position: relative;
  display: block;
}
.field .select-btn.placeholder { color: var(--field-placeholder); }
.field .select-btn::after {
  content: '';
  position: absolute;
  right: 14px; top: 50%;
  width: 7px; height: 7px;
  border-right: 2px solid var(--field-text);
  border-bottom: 2px solid var(--field-text);
  transform: translateY(-70%) rotate(45deg);
  opacity: .8;
}
.field .select-btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.field input, .field textarea {
  width: 100%;
  font-size: 14px;
  color: var(--field-text);
  background: var(--field-bg);
  border: 0; border-radius: var(--field-radius);
  padding: 12px;
  caret-color: var(--field-cursor);
  -webkit-appearance: none;
  appearance: none;
}

/* The Send button is disabled until every field has a value. */
.cta[disabled] {
  opacity: var(--btn-disabled);
  cursor: default;
}
.cta[disabled]:hover { background: var(--icon-bg); }
.field textarea { min-height: 80px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--field-placeholder); }
.field input:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--text); outline-offset: 2px;
}
.botcheck {
  position: absolute !important;
  left: -9999px !important;
  opacity: 0 !important;
  pointer-events: none;
}

.note { font-size: 12px; line-height: 1.5; opacity: .7; margin: 14px 0 2px; }
.done { text-align: center; padding-top: 50px; }
.done h3 { font-size: 20px; margin-bottom: 8px; }
.done p  { opacity: .8; }

/* ---------------------- Ad banner view ---------------------- */
.banner {
  flex: 0 0 auto; height: 78px;
  display: grid; place-items: center; gap: 3px;
  color: #fff; text-align: center;
  background: var(--banner-bg, #00C155);
}
.b-emoji { font-size: 20px; line-height: 1; }
.b-text  { font-size: 15px; font-weight: 700; }
