/* =========================================================================
   নিশ্চিত — one stylesheet, no framework.
   Tokens come from ~/.claude/skills/design/references/bd-saas-landing.md,
   where every pair below was measured. Do not add a value that is not on a
   scale here; a size between two steps is a bug, not a refinement.
   ========================================================================= */

:root{
  /* surface */
  --bg:#ffffff;
  --bg-sunken:#f5f8f7;
  --surface:#ffffff;
  --line:#dfe6e4;          /* decorative hairline — separates, carries no meaning */
  --line-strong:#82918d;   /* 3.29:1 — the edge of anything a person operates */

  /* three text colours, and no fourth */
  --fg:#111a19;            /* 17.71:1 on --bg */
  --fg-muted:#41504e;      /*  8.46:1 */
  --fg-faint:#63716f;      /*  5.09:1 — never below 15px */

  /* one accent */
  --accent:#0f766e;        /* 5.47:1 on --bg */
  --accent-deep:#0b5a54;
  --accent-ink:#ffffff;
  --accent-wash:#e7f3f1;
  --accent-ghost:#a3d0ca;   /* decorative only: the big step numerals */

  /* semantic — each wash has an ink that passes on it */
  --good:#166534;   --good-wash:#dcfce7;
  --warn:#854d0e;   --warn-wash:#fef3c7;
  --danger:#9f1239; --danger-wash:#ffe4e6;

  /* type — five steps. marketing scale, not the app's dense one. */
  --t-small:15px;
  --t-body:18px;
  --t-lead:22px;
  --t-h2:34px;
  --t-h1:52px;

  /* space — one scale */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px;
  --s6:32px; --s7:48px; --s8:64px; --s9:96px;

  /* shape — two radii and a pill */
  --r:8px; --r-lg:16px; --r-pill:999px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  font-family:'Hind Siliguri','Noto Sans Bengali','Kohinoor Bangla','Nirmala UI',sans-serif;
  font-size:var(--t-body);
  line-height:1.75;          /* Bangla stacks three zones; 1.5 smudges it */
  letter-spacing:0;          /* never anything else on Bangla */
  hyphens:none;
  color:var(--fg);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{margin:0; line-height:1.38; letter-spacing:0; text-wrap:balance; font-weight:700}
p{margin:0; text-wrap:pretty}
ul,ol{margin:0; padding:0; list-style:none}
a{color:inherit; text-decoration:none}
img,svg{max-width:100%; height:auto; display:block}
:focus-visible{outline:3px solid var(--accent); outline-offset:2px; border-radius:2px}
.num{font-variant-numeric:tabular-nums}
.sr{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}

.container{max-width:1180px; margin-inline:auto; padding-inline:var(--s5)}
section{padding-block:var(--s9)}
@media (max-width:760px){
  :root{--t-h1:34px; --t-h2:26px; --t-lead:19px; --t-body:17px}
  section{padding-block:var(--s8)}
}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s2);
  min-height:48px; padding:0 var(--s5); border-radius:var(--r);
  font:inherit; font-size:var(--t-small); font-weight:600;
  border:1px solid transparent; cursor:pointer; text-align:center;
  transition:background-color .15s ease, border-color .15s ease;
}
.btn-primary{background:var(--accent); color:var(--accent-ink)}
.btn-primary:hover{background:var(--accent-deep)}
.btn-ghost{border-color:var(--line-strong); color:var(--fg); background:var(--surface)}
.btn-ghost:hover{background:var(--bg-sunken)}
.btn-invert{background:var(--surface); color:var(--fg)}
.btn-invert:hover{background:var(--bg-sunken)}
.btn-lg{min-height:56px; font-size:var(--t-body); padding:0 var(--s6)}
.btn-block{width:100%}

/* ---------- nav ---------- */
/* On a phone the bar holds two things: the brand and the toggle. Everything
   else drops into the drawer. The first build put the language pill and both
   buttons on the bar at every width; at 390px they added up to more than the
   viewport, and the whole document scrolled sideways because of it. */
.nav{border-bottom:1px solid var(--line); position:relative; background:var(--bg)}
.nav .container{display:flex; align-items:center; gap:var(--s5); min-height:72px}
.brand{font-weight:700; font-size:var(--t-lead); color:var(--accent); white-space:nowrap}
.brand span{color:var(--fg)}
.nav-menu{display:flex; align-items:center; gap:var(--s6); flex:1; min-width:0}
.nav-links{display:flex; gap:var(--s5); font-size:var(--t-small); color:var(--fg-muted); min-width:0}
.nav-links a:hover,.nav-links a[aria-current]{color:var(--fg)}
.nav-actions{margin-inline-start:auto; display:flex; align-items:center; gap:var(--s3)}
.lang{
  display:inline-flex; border:1px solid var(--line-strong);
  border-radius:var(--r-pill); overflow:hidden; flex:none;
  font-size:var(--t-small); font-weight:600;
}
.lang b,.lang a{padding:var(--s1) var(--s3); display:block}
.lang b{background:var(--fg); color:var(--bg)}
.lang a{color:var(--fg-muted)}
.nav-toggle{
  display:none; background:none; border:1px solid var(--line-strong);
  border-radius:var(--r); min-height:48px; min-width:48px; cursor:pointer; flex:none;
  margin-inline-start:auto;
}
.nav-toggle span{display:block; width:20px; height:2px; background:var(--fg); margin:4px auto}

@media (max-width:960px){
  .nav-toggle{display:block}
  .nav-menu{
    display:none; position:absolute; inset-inline:0; top:100%; z-index:20;
    flex-direction:column; align-items:stretch; gap:var(--s5);
    background:var(--bg); border-bottom:1px solid var(--line);
    padding:var(--s5); font-size:var(--t-body);
  }
  .nav[data-open="1"] .nav-menu{display:flex}
  .nav-links{flex-direction:column; gap:var(--s4); font-size:var(--t-body)}
  .nav-actions{margin-inline-start:0; flex-wrap:wrap; gap:var(--s3)}
  .nav-actions .btn{flex:1}
}

/* ---------- section header: eyebrow, H2, one line ---------- */
.section-head{text-align:center; max-width:44rem; margin:0 auto var(--s8)}
.eyebrow{
  display:inline-block; font-size:var(--t-small); font-weight:600;
  color:var(--accent); background:var(--accent-wash);
  padding:var(--s1) var(--s4); border-radius:var(--r-pill); margin-bottom:var(--s4);
}
.section-head h2{font-size:var(--t-h2); margin-bottom:var(--s3)}
.section-head .sub{color:var(--fg-muted); font-size:var(--t-lead)}

/* ---------- hero ---------- */
.hero{padding-block:var(--s8) var(--s9)}
.chip{
  display:inline-flex; align-items:center; gap:var(--s2);
  border:1px solid var(--line); background:var(--surface); border-radius:var(--r-pill);
  font-size:var(--t-small); font-weight:600; color:var(--fg-muted);
  padding:var(--s1) var(--s4); margin-bottom:var(--s5);
}
.chip .dot{width:8px; height:8px; border-radius:50%; background:var(--accent); flex:none}
.hero h1{font-size:var(--t-h1); max-width:24ch; margin-bottom:var(--s4)}
.hero h1 em{font-style:normal; color:var(--accent)}
.hero .sub{font-size:var(--t-lead); color:var(--fg-muted); max-width:52ch; margin-bottom:var(--s6)}
.cta{display:flex; gap:var(--s3); flex-wrap:wrap}
.proof-row{display:flex; align-items:center; gap:var(--s3); margin-top:var(--s5); font-size:var(--t-small); color:var(--fg-muted); flex-wrap:wrap}
.faces{display:flex; flex:none}
.faces span{
  width:30px; height:30px; border-radius:50%; border:2px solid var(--bg);
  margin-inline-start:-9px; display:grid; place-items:center;
  font-size:15px; font-weight:600; color:var(--accent-ink);
}
.faces span:first-child{margin-inline-start:0}
@media (max-width:760px){ .cta .btn{width:100%} }

/* ---------- the product, drawn as a browser window ---------- */
/* ---------- section 2: what you no longer buy ---------- */
.replaces{background:var(--bg-sunken); border-block:1px solid var(--line); padding-block:var(--s7)}
.replaces h2{font-size:var(--t-lead); margin-bottom:var(--s5); text-align:center}
.replaces h2 em{font-style:normal; color:var(--accent)}
.replaces ul{display:grid; grid-template-columns:repeat(5,1fr); gap:var(--s5)}
.replaces li{border-inline-start:1px solid var(--line); padding-inline-start:var(--s4)}
.replaces li:first-child{border-inline-start:0; padding-inline-start:0}
.replaces b{display:block; font-size:var(--t-small); text-decoration:line-through; text-decoration-color:var(--danger); text-decoration-thickness:2px}
.replaces span{display:block; font-size:15px; color:var(--fg-faint)}
@media (max-width:900px){
  .replaces ul{grid-template-columns:repeat(2,1fr)}
  .replaces li{border-inline-start:0; padding-inline-start:0}
}

/* ---------- stats ---------- */
.stats .container{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--s5)}
.stats b{display:block; font-size:44px; font-weight:700; line-height:1.2; color:var(--accent-deep)}
.stats span{font-size:var(--t-small); color:var(--fg-muted); display:block; max-width:22ch}
@media (max-width:760px){
  .stats .container{grid-template-columns:repeat(2,1fr); gap:var(--s6)}
  .stats b{font-size:32px}
}

/* ---------- flagship: one feature, its own section ---------- */
.flagship{background:var(--bg-sunken); border-block:1px solid var(--line)}
.flagship .grid{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.1fr); gap:var(--s8); align-items:center}
.flagship h2{font-size:var(--t-h2); margin-bottom:var(--s4)}
.flagship p{color:var(--fg-muted); max-width:46ch; margin-bottom:var(--s5)}
.flagship li{padding-inline-start:var(--s5); position:relative; margin-bottom:var(--s3); font-size:var(--t-small); color:var(--fg-muted)}
.flagship li::before{content:"✓"; position:absolute; inset-inline-start:0; color:var(--accent); font-weight:700}
.panel{border:1px solid var(--line); border-radius:var(--r-lg); background:var(--surface); overflow:hidden}
.panel-head{display:flex; align-items:center; gap:var(--s3); padding:var(--s3) var(--s4); border-bottom:1px solid var(--line); background:var(--bg-sunken); font-size:var(--t-small); font-weight:600; flex-wrap:wrap}
.panel-head .tag{font-weight:400; color:var(--fg-faint)}
/* It was named .scroller and never scrolled: no overflow rule existed, so a
   wide admin table pushed the whole page sideways instead of moving inside
   its own box. */
.scroller{overflow-x:auto; -webkit-overflow-scrolling:touch}
.panel .scroller{padding:var(--s3) var(--s4) var(--s4)}
@media (max-width:900px){ .flagship .grid{grid-template-columns:1fr; gap:var(--s6)} }

/* ---------- several shops, one app ---------- */
/* The app's left menu, drawn: one row per shop, the active one ticked in
   the accent, the count pill from the app's own status tiles. Light, like
   the fraud panel beside it in the page — the dark app frames belong to the
   real screenshots further down. */
.storelist{list-style:none; margin:0; padding:0}
.storelist li{display:flex; align-items:center; gap:var(--s3); padding:var(--s3) var(--s4); border-top:1px solid var(--line);
  margin:0; min-width:0; font-size:var(--t-body); color:var(--fg)}
/* .flagship li draws a tick before every list item in the section; these
   rows draw their own mark, so the inherited one is switched off. */
.storelist li::before{content:none}
#multistore .grid > *{min-width:0}
.pushmock{white-space:normal}
.storelist li:first-child{border-top:0}
.storelist li.on{background:var(--accent-wash)}
.storelist .mark{flex:none; width:28px; height:28px; border-radius:50%; border:1.5px solid var(--line-strong);
  display:grid; place-items:center; font-weight:700; font-size:15px; color:var(--fg-muted); background:var(--surface)}
.storelist li.on .mark{background:var(--accent); border-color:var(--accent); color:var(--accent-ink)}
.storelist li.add .mark{border-style:dashed}
.storelist .storename{flex:1; min-width:0; font-weight:600; line-height:1.35}
.storelist .storename small{display:block; font-weight:400; font-size:15px; color:var(--fg-faint);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.storelist li.add .storename{color:var(--fg-muted); font-weight:500}
.storelist li.add .storename small{font-family:inherit}
.storelist .pill{flex:none}
.storenote{padding:var(--s3) var(--s4) var(--s4); border-top:1px solid var(--line); background:var(--bg-sunken);
  display:flex; flex-direction:column; gap:var(--s1)}
/* Inline, not flex: at 320px a flex box split the shop name onto two lines
   while the rest of the sentence sat beside it. As text it wraps at spaces,
   and the name itself never breaks. */
.pushmock{display:inline-block; font-size:15px; line-height:1.5; color:var(--fg);
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r); padding:var(--s2) var(--s3); max-width:100%}
.pushmock b{color:var(--accent-deep); white-space:nowrap}
.storenote small{font-size:15px; color:var(--fg-faint)}
.flagship .finehint{margin-top:var(--s2)}

/* ---------- feature cards ---------- */
.cards{display:grid; grid-template-columns:repeat(2,1fr); gap:var(--s5)}
.card{
  border:1px solid var(--line); border-radius:var(--r-lg);
  background:var(--surface); padding:var(--s6); display:block;
  transition:border-color .15s ease;
}
a.card:hover{border-color:var(--accent)}
.card h3{font-size:var(--t-lead); margin-bottom:var(--s2)}
.card p{color:var(--fg-muted); font-size:var(--t-small); margin-bottom:var(--s4)}
.card .mini{display:flex; flex-wrap:wrap; gap:var(--s2)}
.card .mini span{
  font-size:15px; color:var(--fg-muted);
  background:var(--bg-sunken); border-radius:var(--r-pill); padding:2px var(--s3);
}
/* A card that leads with a piece of the real screen, laid on a tinted shelf
   rather than bled to the card's edges. Bleeding it made the crop the same
   surface as the card, so a cut-off row read as the page failing to load; on
   a shelf it reads as a piece of a phone, deliberately placed. The inset also
   drops the app's own type below the card's heading, where it belongs. */
.cardshot{padding:0; overflow:hidden}
/* One box, one height, and the crops all leave the build at 600×325, so the
   image fills it exactly and object-fit never has anything to take away. */
.cardshot .shot{
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-wash);
  border-bottom:1px solid var(--line);
  aspect-ratio:600/325; padding:var(--s4) var(--s5); overflow:hidden;
}
.cardshot .shot img{
  display:block; max-width:100%; max-height:100%; width:auto; height:auto;
  border-radius:10px;
  box-shadow:0 10px 26px -12px rgba(6,42,38,.42), 0 0 0 1px rgba(6,42,38,.07);
}
.cardshot .ico-lg{margin:var(--s5) var(--s6) 0}
.cardshot h3{margin:var(--s3) var(--s6) var(--s2)}
.cardshot p{margin:0 var(--s6) var(--s4)}
.cardshot .mini{margin:0 var(--s6) var(--s6)}

.more{text-align:center; margin-top:var(--s7)}
@media (max-width:760px){ .cards{grid-template-columns:1fr} }

/* ---------- steps ---------- */
.steps{display:grid; gap:var(--s5)}
.step{display:grid; grid-template-columns:76px minmax(0,1fr); gap:var(--s5); align-items:start; border-top:1px solid var(--line); padding-top:var(--s5)}
.step .n{font-size:40px; font-weight:700; color:var(--accent-ghost); line-height:1}
.step h3{font-size:var(--t-lead); margin-bottom:var(--s2)}
.step p{color:var(--fg-muted); font-size:var(--t-small); max-width:62ch}
@media (max-width:760px){ .step{grid-template-columns:52px minmax(0,1fr); gap:var(--s4)} .step .n{font-size:30px} }

/* ---------- pricing ---------- */
/* auto-fit + minmax so 2, 3 or 4 cards all fit without the page scrolling
   sideways — a 1fr track's floor is min-content, which overflowed once a
   fourth plan (unlimited) meant three cards showed during the offer instead
   of two. min(100%,240px) lets a card go full width before it would overflow. */
.plans{display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap:var(--s4); align-items:start}
.plan{border:1px solid var(--line); border-radius:var(--r-lg); background:var(--surface); padding:var(--s5); position:relative}

/* A plan that is on the page to be understood, not bought.

   Readable, not blurred — Sazzad's call, 3 Sep: "ekdom blur na kore just
   bujhben eta ekhon ar nei, ager plan gulo details dekhte parbe". Somebody
   deciding whether ৪৯০ is a good price needs to see what the other plans
   actually offer; a blur left them a shape to guess at.

   So it sinks the card, dashes its edge and says so out loud instead of
   fading anything. Every word stays readable: on --bg-sunken the name measures
   16.6:1 and the features 7.9:1 — measured on that ground, not the on-white
   figures the token block quotes. The one thing that does step back is the
   price, to --fg-muted at 7.9:1, so the card reads as secondary without
   becoming hard to read. */
.plan.is-dim{
  background:var(--bg-sunken);
  border-style:dashed;
  box-shadow:none;
}
.plan.is-dim .price b{color:var(--fg-muted)}
.plan.is-dim .btn{
  border-style:dashed;
  color:var(--fg-faint);
  background:transparent;
  cursor:not-allowed;
}
.plan .badge.gone{background:var(--bg-sunken); color:var(--fg-muted); border:1px dashed var(--line-strong)}

/* How much off, beside the plan's own badge — and "beside" has to be spelled
   out, because .plan .badge below pins every badge to the same corner. The two
   only miss each other today by luck: the default experiment plan is unlimited,
   which has no badge of its own. Choose গ্রোথ on /admin/plans and "৫০% ছাড়"
   would land on top of "সবচেয়ে জনপ্রিয়".

   Written as `.plan .badge.off` for weight: `.plan .badge` carries the same
   specificity and comes later, so the shorter selector lost silently and the
   badge painted the wrong colour. */
.plan .badge.off{
  background:var(--danger-wash); color:var(--danger);
  inset-inline-start:auto; inset-inline-end:var(--s6);
}

.plan.best{background:var(--fg); color:var(--bg); border-color:var(--fg)}
.plan .badge{
  position:absolute; top:calc(var(--s3) * -1); inset-inline-start:var(--s6);
  background:var(--accent); color:var(--accent-ink);
  font-size:15px; font-weight:600; padding:2px var(--s4); border-radius:var(--r-pill);
}
.plan h3{font-size:var(--t-lead)}
.plan .note{font-size:var(--t-small); color:var(--fg-faint); margin-bottom:var(--s4)}
.plan.best .note{color:#b9c6c3}
/* price and unit each keep their own line box, so a long Bangla unit cannot
   ride over the figure — the exact collision oxiosoft ships */
.plan .price{display:flex; align-items:baseline; gap:var(--s2); flex-wrap:wrap; margin-bottom:var(--s2)}
.plan .price b{font-size:32px; line-height:1.2}
.plan .price span{font-size:var(--t-small); color:var(--fg-faint)}
.plan.best .price span{color:#b9c6c3}
.plan .cap{font-size:var(--t-small); color:var(--fg-muted); margin-bottom:var(--s5)}
.plan.best .cap{color:#d5dedc}
.plan ul{margin-bottom:var(--s6)}
.plan li{padding-inline-start:var(--s5); position:relative; margin-bottom:var(--s3); font-size:var(--t-small); color:var(--fg-muted)}
.plan.best li{color:#d5dedc}
.plan li::before{content:"✓"; position:absolute; inset-inline-start:0; color:var(--accent); font-weight:700}
.plan.best li::before{color:#5eead4}
.plan .perunit{font-size:15px; color:var(--fg-faint); margin-bottom:var(--s4)}
.plan.best .perunit{color:#b9c6c3}

/* ---------- the offer bar ---------- */
/* Directly under the nav, only while the early-bird window is open. It says
   the price and the days left, because "offer running" on its own is noise. */
.offerbar{background:var(--accent); color:var(--accent-ink)}
.offerbar .container{
  display:flex; align-items:center; justify-content:center;
  flex-wrap:wrap; gap:var(--s2) var(--s4);
  padding-block:var(--s3); text-align:center;
  font-size:var(--t-small);
}
/* The lead pill. An opaque ground, not a white wash: .16 white over --accent
   composites to #358c85, and white on that is 4.01:1 — under the 4.5 floor for
   15px text, on the first coloured thing under the nav. --accent-deep carries
   the same white at 8.06:1. The rose bar needs its own, below, or the pill
   would come out teal on a rose ground. */
.offerbar b{
  background:var(--accent-deep); border:1px solid rgba(255,255,255,.28);
  padding:2px var(--s3); border-radius:var(--r-pill);
  font-size:15px; font-weight:600; white-space:nowrap;
}
.offerbar .what s{opacity:.88; margin-inline-end:2px}
.offerbar .what strong{font-size:19px; font-weight:700}
.offerbar .what small{font-size:14px; opacity:.88; margin-inline-start:2px}
.offerbar .left{
  font-weight:600; white-space:nowrap;
  padding-inline-start:var(--s4); border-inline-start:1px solid rgba(255,255,255,.3);
}
.offerbar a{
  color:var(--accent-ink); font-weight:600; white-space:nowrap;
  text-decoration:underline; text-underline-offset:3px;
}
.offerbar a:hover{text-decoration-thickness:2px}
@media (max-width:640px){
  .offerbar .left{padding-inline-start:0; border-inline-start:0}
}

/* The experiment's own bar and clock.

   Rose rather than teal, because this one is not an offer running alongside
   the prices — it is the prices, for as long as it lasts, and it has to read
   as the exception. White on --danger measures 8.0:1, --danger on
   --danger-wash 6.7:1, so the shift costs no legibility. */
.offerbar.solo{background:var(--danger)}
/* #7a0f2b under white is 10.9:1, and it keeps the pill on the bar's own hue. */
.offerbar.solo b{background:#7a0f2b}
.countdown.solo{border-color:var(--danger); background:var(--danger-wash)}
.countdown.solo .countdown-lead{color:var(--danger)}
.countdown.solo .countdown-lead b{background:var(--danger); color:#fff}
.countdown.solo .countdown-clock span{border-color:var(--danger); background:var(--surface)}
.countdown.solo .countdown-note b{color:var(--danger)}

/* ---------- the rolling early-bird offer ---------- */
/* One plan borrows a smaller plan's price for a week at a time, so the card
   has to say both numbers — the one being paid and the one being skipped —
   and the strip above says when the week runs out. */
/* The clock. Rendered with real figures by the server and then ticked, so it
   is never four zeroes waiting for a script. Tabular numerals because digits
   that change width make the whole row twitch once a second. */
/* Capped at 660px so the clock reads as one strip rather than stretching the
   width of a three- or four-card grid. It used to be tied to .plans.two, from
   when an offer always withdrew exactly one of three plans; the grid below it
   can now be any width, and this no longer follows it. */
.countdown{
  max-width:660px; margin:0 auto var(--s6); text-align:center;
  padding:var(--s5) var(--s5) var(--s4);
  border:1px solid var(--accent-ghost); border-radius:var(--r-lg);
  background:var(--accent-wash);
}
.countdown-lead{
  display:flex; align-items:center; justify-content:center;
  flex-wrap:wrap; gap:var(--s2) var(--s3); margin-bottom:var(--s4);
  font-size:var(--t-small); color:var(--accent-deep);
}
.countdown-lead b{
  background:var(--accent); color:var(--accent-ink);
  padding:2px var(--s3); border-radius:var(--r-pill);
  font-size:15px; font-weight:600; white-space:nowrap;
}
.countdown-clock{display:flex; justify-content:center; flex-wrap:wrap; gap:var(--s3)}
.countdown-clock span{
  display:flex; flex-direction:column; align-items:center; gap:1px;
  min-width:76px; padding:var(--s3) var(--s2);
  background:var(--surface); border:1px solid var(--accent-ghost);
  border-radius:var(--r);
}
.countdown-clock b{font-size:30px; line-height:1.15; font-variant-numeric:tabular-nums}
.countdown-clock small{font-size:14px; color:var(--fg-muted)}
.countdown-note{margin-top:var(--s4); font-size:15px; color:var(--fg-muted)}
@media (max-width:520px){
  .countdown{padding-inline:var(--s4)}
  .countdown-clock{gap:var(--s2)}
  .countdown-clock span{min-width:64px}
  .countdown-clock b{font-size:26px}
}
/* Two cards left in a three-column grid would each stretch to a third of the
   page and look like something is missing. */
.plans.two{grid-template-columns:repeat(2,1fr); max-width:660px; margin-inline:auto}
.plan .price s.was{font-size:20px; color:var(--fg-faint); text-decoration-thickness:2px}
.plan.best .price s.was{color:#b9c6c3}
.plan .earlynote{
  margin:calc(var(--s4) * -1) 0 var(--s5);
  font-size:15px; font-weight:600; color:var(--accent-deep);
}
.plan.best .earlynote{color:#5eead4}

/* ---------- monthly / yearly / lifetime ---------- */
/* Links, not a script: the server renders whichever period the URL asks for,
   so this works with JS off and the URL is worth pasting into WhatsApp. */
.billsw{
  display:flex; flex-wrap:wrap; justify-content:center; gap:2px;
  width:fit-content; max-width:100%; margin:0 auto var(--s6);
  padding:3px; border:1px solid var(--line-strong);
  border-radius:var(--r-pill); background:var(--surface);
}
.billsw-opt{
  display:flex; flex-direction:column; align-items:center; gap:1px;
  padding:var(--s2) var(--s5); border-radius:var(--r-pill);
  font-size:16px; font-weight:600; color:var(--fg-muted); text-decoration:none;
  white-space:nowrap;
}
.billsw-opt:hover{color:var(--fg); background:var(--bg-sunken)}
.billsw-opt.on{background:var(--accent); color:var(--accent-ink)}
.billsw-opt.on:hover{background:var(--accent); color:var(--accent-ink)}
.billsw-opt small{font-size:14px; font-weight:400; opacity:.85}
.billsw-note{
  max-width:44rem; margin:calc(var(--s6) * -1 + var(--s2)) auto var(--s6);
  text-align:center; font-size:var(--t-small); color:var(--fg-muted);
}
.billsw-note b{font-weight:600; color:var(--fg)}
@media (max-width:420px){
  .billsw{width:100%; flex-direction:column; border-radius:var(--r-lg)}
  .billsw-opt{flex-direction:row; justify-content:space-between; border-radius:calc(var(--r-lg) - 3px)}
}

/* The old max-width:1100px → repeat(2,1fr) rule is gone: it forced two rigid
   columns that overflowed with three cards. auto-fit above handles narrowing. */
@media (max-width:640px){
  .plans, .plans.two{grid-template-columns:1fr}

  /* One column would put three unavailable plans above the one on offer. The
     offer goes first instead; the others keep their full detail below it,
     because being able to read them is the point. Guarded by :has(.is-dim), so
     with the experiment off the order is the ladder's own, ascending. */
  .plans:has(.plan.is-dim) .plan:not(.is-dim){order:-1}
}

/* the signed-in name in the nav: a green dot, then who you are */
.whoami{display:inline-flex; align-items:center; gap:var(--s2); max-width:12rem}
.whoami-dot{width:7px; height:7px; border-radius:999px; background:var(--good); flex:none}
.dlsoon{font-size:15px; color:var(--fg-faint); margin:var(--s2) 0 0; text-align:center}
.btn[disabled]{opacity:.55; cursor:not-allowed}

/* ---------- the rest of the app, small ---------- */
.appmore-head{
  font-size:var(--t-lead); text-align:center;
  margin:var(--s8) 0 var(--s5); font-weight:700;
}
.appmore{display:grid; grid-template-columns:repeat(5,1fr); gap:var(--s4)}
.appmore-item img{
  display:block; width:100%; height:auto;
  border:6px solid #12191a; border-radius:24px; background:#12191a;
  box-shadow:0 10px 24px -14px rgba(17,26,25,.4);
}
.appmore-item h4{font-size:var(--t-small); font-weight:600; margin:var(--s4) 0 var(--s1)}
.appmore-item p{font-size:15px; color:var(--fg-muted)}
@media (max-width:1000px){ .appmore{grid-template-columns:repeat(3,1fr)} }
@media (max-width:640px){ .appmore{grid-template-columns:repeat(2,1fr); gap:var(--s5)} }
@media (max-width:400px){ .appmore{grid-template-columns:1fr; max-width:16rem; margin-inline:auto} }

/* ---------- the mid-page buy bands ---------- */
/* Lighter than the closing CTA on purpose. These punctuate a long page; the
   dark one at the end is the last word, and two things cannot both be that. */
.ctaband{
  display:flex; flex-direction:column; align-items:center; gap:var(--s4);
  margin:var(--s7) auto 0; max-width:56rem; text-align:center;
  padding:var(--s6) var(--s5);
  background:var(--accent-wash); border:1px solid #bfdedb; border-radius:var(--r-lg);
}
.ctaline{font-size:var(--t-lead); font-weight:600; color:var(--fg); margin:0; max-width:44ch}
.ctaline b{font-weight:700; color:var(--accent)}
.ctabtns{display:flex; flex-wrap:wrap; justify-content:center; gap:var(--s3)}
.ctanote{font-size:15px; color:var(--fg-muted); margin:0; max-width:48ch}
@media (max-width:520px){
  .ctaband{padding:var(--s5) var(--s4)}
  .ctabtns{width:100%; flex-direction:column}
  .ctabtns .btn{width:100%}
}

/* ---------- the hero phones ---------- */
/* Three real screens where a drawn browser window used to be. The middle one
   is bigger because it is the one the headline is about; the other two are
   context, and on a phone they are not even fetched. */
.heroshots{
  display:flex; justify-content:center; align-items:flex-end;
  gap:var(--s5); margin-top:var(--s8);
}
.heroshot img{
  display:block; width:100%; height:auto;
  border:8px solid #12191a; border-radius:34px; background:#12191a;
  box-shadow:0 22px 46px -20px rgba(17,26,25,.42);
}
.heroshot.lead{width:270px}
.heroshot.side{width:214px; opacity:.94}
.heroshots-note{
  text-align:center; font-size:15px; color:var(--fg-faint); margin-top:var(--s4);
}
@media (max-width:820px){
  .heroshots{gap:var(--s4)}
  .heroshot.lead{width:230px}
  .heroshot.side{width:180px}
}
@media (max-width:620px){
  .heroshot.side{display:none}
  .heroshot.lead{width:252px}
}

/* ---------- the app section ---------- */
/* A screen per feature, alternating sides. The phone gets a real bezel: a
   floating rounded rectangle reads as a design mockup, and the point of this
   section is that this is the thing in your hand. */
.appwrap{background:var(--bg-sunken)}
.appfeat{
  display:grid; grid-template-columns:minmax(0,320px) minmax(0,1fr);
  gap:var(--s7) var(--s8); align-items:center;
  padding-block:var(--s8); border-top:1px solid var(--line);
}
.appfeat:first-of-type{border-top:0; padding-top:var(--s6)}
/* Flipping with `order` alone left the text in the 320px column and the phone
   in the wide one — the columns have to swap, not just their contents. */
.appfeat.flip{grid-template-columns:minmax(0,1fr) minmax(0,320px)}
.appfeat.flip .appshot{order:2}
/* Width on the wrapper, not only on the image: justify-self:center makes this
   shrink to fit its content, and an image at width:100% of a shrink-to-fit
   parent resolves to nothing — the frames collapsed to their 18px of bezel and
   the browser never even fetched the screenshots. */
.appshot{justify-self:center; width:100%; max-width:300px}
.appshot img{
  display:block; width:100%; height:auto;
  border:9px solid #12191a; border-radius:38px; background:#12191a;
  box-shadow:0 18px 40px -18px rgba(17,26,25,.45);
}
.appsay h3{font-size:var(--t-lead); margin:var(--s2) 0 var(--s3)}
.appsay p{color:var(--fg-muted); max-width:52ch}
.appsay ul{margin-top:var(--s5)}
.appsay li{
  padding-inline-start:var(--s5); position:relative;
  margin-bottom:var(--s3); color:var(--fg-muted); max-width:56ch;
}
.appsay li::before{content:"✓"; position:absolute; inset-inline-start:0; color:var(--accent); font-weight:700}
@media (max-width:900px){
  .appfeat{grid-template-columns:1fr; gap:var(--s5); padding-block:var(--s7)}
  .appfeat.flip .appshot{order:0}
  .appshot{max-width:250px}
}

/* ---------- downloads and the setup guide ---------- */
.dlgrid{display:grid; grid-template-columns:repeat(2,1fr); gap:var(--s4)}
.dlcard{
  display:flex; flex-direction:column; gap:var(--s3);
  border:1px solid var(--line); border-radius:var(--r-lg);
  background:var(--surface); padding:var(--s5);
}
.dlcard.off{background:var(--bg-sunken)}
.dltop h3{font-size:var(--t-lead)}
.dlmeta{font-size:15px; color:var(--fg-faint); margin:0}
.dlmeta b{font-weight:600; color:var(--fg-muted)}
.dlblurb{font-size:var(--t-small); color:var(--fg-muted); margin:0; flex:1}
.dlcard .btn{margin-top:var(--s2)}

.guide{margin-top:var(--s8)}
.guidehead{display:flex; align-items:flex-start; gap:var(--s4); margin-bottom:var(--s4)}
.gnum{
  flex:none; width:2.5rem; height:2.5rem; display:grid; place-items:center;
  border-radius:var(--r); background:var(--accent-wash); color:var(--accent);
  font-weight:700; font-size:var(--t-small);
}
.guidehead h2{font-size:var(--t-lead)}
.gtime{font-size:15px; color:var(--fg-faint); margin:0}
.gnote{
  font-size:var(--t-small); color:var(--fg-muted); margin-bottom:var(--s4);
  padding:var(--s3) var(--s4); border-inline-start:3px solid var(--line-strong);
  background:var(--bg-sunken); border-radius:0 var(--r) var(--r) 0;
}
/* The number is printed by PHP, like every other figure on this site: a CSS
   counter would be a second way of writing digits, and a browser without the
   bengali counter style would quietly fall back to Latin ones. */
.gsteps{display:grid; gap:var(--s3)}
.gsteps li{
  list-style:none; position:relative;
  padding:var(--s4) var(--s5) var(--s4) calc(var(--s5) + var(--s6));
  border:1px solid var(--line); border-radius:var(--r); background:var(--surface);
}
.gsteps .gn{
  position:absolute; inset-inline-start:var(--s5); top:var(--s4);
  color:var(--fg-faint); font-weight:600; font-size:var(--t-small);
}
.gsteps b{display:block; font-weight:600; font-size:var(--t-small)}
.gsteps p{margin:var(--s1) 0 0; color:var(--fg-muted); font-size:15px}
@media (max-width:640px){
  .dlgrid{grid-template-columns:1fr}
  .gsteps li{padding-inline-start:var(--s5); padding-top:calc(var(--s4) + var(--s5))}
  .gsteps .gn{top:var(--s3)}
}

/* ---------- next renewal ---------- */
/* Same wording on the dashboard and in the admin table, same colours: a date
   the customer can plan around and the admin can chase. */
.renewbox{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--s2) var(--s4);
  margin-top:var(--s5); padding:var(--s4) var(--s5);
  border:1px solid var(--line); border-inline-start:3px solid var(--accent);
  border-radius:var(--r); background:var(--bg-sunken);
}
.renewbox div{display:flex; align-items:baseline; gap:var(--s3)}
.renewbox b{font-size:15px; font-weight:600; color:var(--fg-muted)}
.renewbox span{font-size:var(--t-lead); font-weight:700}
.renewbox p{font-size:15px; color:var(--fg-muted); margin:0}
.renewbox.renew-soon{border-inline-start-color:var(--warn)}
.renewbox.renew-soon p{color:var(--warn)}
.renewbox.renew-expired{border-inline-start-color:var(--danger)}
.renewbox.renew-expired p{color:var(--danger)}
.renewbox.renew-cancelled{border-inline-start-color:var(--fg-faint)}
.renewbox.renew-lifetime{border-inline-start-color:var(--accent)}
.renew b{display:block; font-weight:600}
.renew small{display:block; font-size:14px; color:var(--fg-muted)}
.renew-soon b{color:var(--warn)}
.renew-expired b{color:var(--danger)}

.limitnote{max-width:620px; margin:var(--s7) auto 0}
.limitnote div{display:grid; grid-template-columns:minmax(0,15rem) minmax(0,1fr); gap:var(--s4); padding-block:var(--s4); border-top:1px solid var(--line); font-size:var(--t-small)}
.limitnote b{font-weight:600}
.limitnote p{color:var(--fg-muted)}
.overline{text-align:center; font-size:var(--t-small); color:var(--fg-muted); margin-top:var(--s6)}
/* Inside a flagship section every p is capped at 46ch and sits at the left
   edge, so a centred overline under the /trial form was centred inside a box
   that was not — text off to the left of the form above it (Sazzad, 9 Sep:
   "alignment thik nai"). Give it the form's width and centre the box. */
.flagship p.overline{max-width:38rem; margin-inline:auto}
/* The same trap for the two other centred paragraphs on /trial: the
   section-head's sub line and the fine print under the form's button were
   46ch boxes sitting at the left with centred text inside. Neither is body
   copy; they follow their own box. */
.flagship .section-head p{max-width:none}
.flagship .askform p{max-width:none; margin-inline:auto}
@media (max-width:760px){ .limitnote div{grid-template-columns:1fr; gap:var(--s1)} }

/* ---------- compare ---------- */
.compare{max-width:620px; margin-inline:auto; border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden}
.compare .row{display:flex; justify-content:space-between; gap:var(--s4); padding:var(--s4) var(--s5); border-bottom:1px solid var(--line); font-size:var(--t-small)}
.compare .row span:last-child{color:var(--fg-faint); white-space:nowrap}
.compare .total{background:var(--bg-sunken); font-weight:600; color:var(--fg)}
.compare .ours{background:var(--accent-wash); color:var(--accent-deep); font-weight:600; border-bottom:0}
.compare .ours span:last-child{color:var(--accent-deep)}

/* ---------- faq ---------- */
.faq{max-width:760px; margin-inline:auto}
.faq details{border-top:1px solid var(--line)}
.faq details:last-child{border-bottom:1px solid var(--line)}
.faq summary{
  cursor:pointer; list-style:none; padding:var(--s5) var(--s6) var(--s5) 0;
  font-size:var(--t-lead); font-weight:600; position:relative;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"+"; position:absolute; inset-inline-end:0; top:var(--s5);
  font-size:var(--t-lead); color:var(--accent); font-weight:400;
}
.faq details[open] summary::after{content:"−"}
.faq p{padding-bottom:var(--s5); color:var(--fg-muted); font-size:var(--t-small); max-width:65ch}

/* ---------- closing cta ---------- */
.closing{background:var(--fg); color:var(--bg); text-align:center}
.closing h2{font-size:var(--t-h2); margin-bottom:var(--s3); max-width:20ch; margin-inline:auto}
.closing p{color:#b9c6c3; margin-bottom:var(--s6)}
.closing .cta{justify-content:center}

/* ---------- footer ---------- */
.foot{border-top:1px solid var(--line); background:var(--bg-sunken); padding-block:var(--s8) var(--s6)}
.foot .cols{display:grid; grid-template-columns:1.4fr repeat(4,1fr); gap:var(--s6)}
.foot .about p{font-size:var(--t-small); color:var(--fg-muted); max-width:30ch; margin-top:var(--s3)}
.foot h4{font-size:var(--t-small); color:var(--fg); margin-bottom:var(--s3)}
.foot li{margin-bottom:var(--s2)}
.foot a{font-size:var(--t-small); color:var(--fg-muted)}
.foot a:hover{color:var(--fg)}
.foot .base{border-top:1px solid var(--line); margin-top:var(--s7); padding-top:var(--s5); font-size:15px; color:var(--fg-faint); display:flex; justify-content:space-between; gap:var(--s4); flex-wrap:wrap}
@media (max-width:900px){ .foot .cols{grid-template-columns:repeat(2,1fr)} }

/* ---------- features page ---------- */
.fgroup{border-top:1px solid var(--line); padding-block:var(--s7)}
.fgroup .head{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.4fr); gap:var(--s7); align-items:start}
.fgroup h2{font-size:var(--t-h2)}
.fgroup .lede{color:var(--fg-muted); font-size:var(--t-small); margin-top:var(--s3); max-width:38ch}
.flist li{display:grid; grid-template-columns:minmax(0,15rem) minmax(0,1fr); gap:var(--s4); padding-block:var(--s3); border-bottom:1px solid var(--line)}
.flist li:last-child{border-bottom:0}
.flist b{font-size:var(--t-small); display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap}
.flist p{font-size:var(--t-small); color:var(--fg-muted)}
.soon{
  font-size:15px; font-weight:600; color:var(--warn); background:var(--warn-wash);
  border-radius:var(--r-pill); padding:0 var(--s3); white-space:nowrap;
}
@media (max-width:900px){
  .fgroup .head{grid-template-columns:1fr; gap:var(--s5)}
  .flist li{grid-template-columns:1fr; gap:var(--s1)}
}

/* ---------- tutorial videos ---------- */
/* Read mode. Each card is a poster and a play button; the player is only
   created for the one somebody presses, so the page costs one image per video
   and no script from the host until then. */
.vidjump{display:flex; flex-wrap:wrap; gap:var(--s2); margin-bottom:var(--s7)}
.vidjump a{
  font-size:15px; font-weight:600; color:var(--fg-muted); text-decoration:none;
  border:1px solid var(--line); border-radius:var(--r-pill); padding:var(--s1) var(--s4);
  /* 44px, not 36: these are the page's navigation on a phone, and a thumb
     needs the full target. Measured at 36 first. */
  min-height:44px; display:inline-flex; align-items:center; gap:6px;
}
/* 14px is the site's floor for --fg-faint; the browser's default small sat at 12.5. */
.vidjump a small{color:var(--fg-faint); font-weight:400; font-size:14px}
.vidjump a:hover{border-color:var(--line-strong); color:var(--fg)}
.vidjump a:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

.vidpart{margin-bottom:var(--s8)}
.vidpart h2{font-size:var(--t-h3); margin-bottom:var(--s5); display:flex; align-items:baseline; gap:var(--s3)}
.vidpart h2 .num{color:var(--accent); font-size:var(--t-small); font-weight:700}

.vidgrid{display:grid; grid-template-columns:repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap:var(--s5)}
.vidgrid-3{grid-template-columns:repeat(auto-fit, minmax(min(100%, 280px), 1fr))}

.vid{
  border:1px solid var(--line); border-radius:var(--r-lg); background:var(--surface);
  overflow:hidden; display:flex; flex-direction:column;
}
.vidlink{text-decoration:none; color:inherit}
.vidlink:hover{border-color:var(--line-strong)}
.vidlink:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* 16:9, always. YouTube's hqdefault is 4:3 with black bars and Drive's
   thumbnail is whatever the file is, so the poster is cropped to the shape the
   player will take and nothing jumps on press. */
.vidposter{
  position:relative; display:block; width:100%; aspect-ratio:16/9;
  padding:0; border:0; background:#000; cursor:pointer; overflow:hidden;
}
.vidposter img{width:100%; height:100%; object-fit:cover; display:block}
/* A phone recording is 9:16. Cropping it to 16:9 shows a band through the
   middle of the screen, so the poster learns its shape from the image (onload)
   and stands tall on a dark ground, whole. The player it becomes is the same
   shape, capped so one card never fills a laptop screen. */
.vidposter.is-tall{aspect-ratio:4/5; background:var(--accent-deep)}
/* cover, not contain: YouTube's thumbnail for a portrait video is 4:3 with
   black bars either side, and covering a 4:5 box scales to the height and
   crops the bars off. A Drive poster, already portrait, loses a sliver. */
.vidposter.is-tall img{object-fit:cover}
.vidframe.is-tall{aspect-ratio:9/16; max-height:72vh; margin-inline:auto; width:auto; max-width:100%}
.vidplay{
  position:absolute; inset:0; margin:auto; width:64px; height:64px;
  display:flex; align-items:center; justify-content:center;
  border-radius:50%; background:var(--accent); color:var(--accent-ink);
  box-shadow:0 6px 24px rgba(0,0,0,.35);
  transition:transform .15s ease;
}
.vidplay svg{margin-inline-start:3px}
.vidposter:hover .vidplay,.vidlink:hover .vidplay{transform:scale(1.06)}
.vidposter:focus-visible{outline:2px solid var(--accent); outline-offset:-3px}
.vidframe{display:block; width:100%; aspect-ratio:16/9; border:0; background:#000}
/* No poster came back — a private Drive file, or a video since deleted. The
   title stands in on the accent ground, so the card still says what it is
   rather than showing a black rectangle with a broken-image glyph. */
.vidbare{display:none}
.vidposter.is-bare{background:var(--accent-deep)}
.vidposter.is-bare .vidbare{
  display:block; position:absolute; inset:0; padding:var(--s5) var(--s5) var(--s9);
  color:var(--accent-ink); font-size:var(--t-lead); font-weight:700; line-height:1.5; text-align:start;
}
.vidposter.is-bare .vidplay{top:auto; bottom:var(--s4); inset-inline-start:var(--s5); margin:0; width:48px; height:48px}
@media (prefers-reduced-motion:reduce){ .vidplay{transition:none} }

.vidbody{padding:var(--s4) var(--s5) var(--s5); display:flex; flex-direction:column; gap:var(--s2)}
.vidbody h3{font-size:var(--t-body); font-weight:700; line-height:1.5; display:flex; gap:var(--s2); align-items:baseline}
.vidbody h3 .num{color:var(--fg-faint); font-size:15px; font-weight:600; flex:none}
.vidbody p{font-size:15px; color:var(--fg-muted); line-height:1.7; margin:0}
.vidout{
  margin-top:auto; padding-top:var(--s2); font-size:15px; font-weight:600;
  color:var(--accent); text-decoration:underline; text-underline-offset:3px; width:fit-content;
}
.vidout:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

.vidempty,.vidnote{max-width:56rem; color:var(--fg-muted); line-height:1.8}
.vidnote{margin-top:var(--s7)}
.vidempty a,.vidnote a{color:var(--accent); text-decoration:underline}

.vidband{background:var(--bg-sunken)}
.vidmore{text-align:center; margin-top:var(--s6)}

/* ---------- checkout ---------- */
.checkout{display:grid; grid-template-columns:minmax(0,1.35fr) minmax(0,1fr); gap:var(--s8); align-items:start}
.orderform{border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--s6); background:var(--surface)}
.field{margin-bottom:var(--s5); border:0; padding:0}
.field label,.field legend{display:block; font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2)}
.field .opt{font-weight:400; color:var(--fg-faint)}
/* A choice inside a field: the label is the target, not the dot. Two of these
   sit under "have you got a site?", and a 13px dot is not something to ask
   somebody to hit on a phone. */
.field .radio{
  display:flex; align-items:center; gap:var(--s3);
  min-height:48px; margin-bottom:0;
  font-weight:400; cursor:pointer;
}
.field .radio input{width:20px; height:20px; accent-color:var(--accent); flex:none; margin:0}
.field .radio span{font-size:var(--t-body)}
.field input[type=text],.field input[type=tel],.field input[type=email]{
  width:100%; min-height:52px; padding:0 var(--s4);
  font:inherit; font-size:var(--t-body); color:var(--fg); background:var(--surface);
  border:1px solid var(--line-strong); border-radius:var(--r);
}
.field input:focus-visible{outline:3px solid var(--accent); outline-offset:1px}
.field input[aria-invalid]{border-color:var(--danger)}
.field .hint{display:block; font-size:15px; color:var(--fg-faint); margin-top:var(--s2)}
.field .err{display:block; font-size:15px; font-weight:600; color:var(--danger); margin-top:var(--s2)}
.formerror{
  background:var(--danger-wash); color:var(--danger); font-size:var(--t-small); font-weight:600;
  padding:var(--s4); border-radius:var(--r); margin-bottom:var(--s5);
}
/* the period picker inside the order form: three tiles, one row */
.billpick{display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s3)}
.billpick-opt{
  display:flex; flex-direction:column; align-items:center; gap:2px; cursor:pointer;
  border:1px solid var(--line-strong); border-radius:var(--r);
  padding:var(--s3) var(--s2); text-align:center;
}
.billpick-opt.on,.billpick-opt:has(input:checked){border-color:var(--accent); background:var(--accent-wash)}
.billpick-opt:has(input:focus-visible){outline:3px solid var(--accent); outline-offset:2px}
.billpick-opt input{position:absolute; opacity:0; width:0; height:0}
.billpick-opt span{font-size:var(--t-small); font-weight:600}
.billpick-opt small{font-size:14px; color:var(--fg-muted)}
@media (max-width:420px){ .billpick{grid-template-columns:1fr} .billpick-opt{flex-direction:row; justify-content:space-between} }

.planpick{
  display:flex; align-items:center; gap:var(--s4); cursor:pointer;
  border:1px solid var(--line-strong); border-radius:var(--r);
  padding:var(--s4); margin-bottom:var(--s3);
}
.planpick.on,.planpick:has(input:checked){border-color:var(--accent); background:var(--accent-wash)}
.planpick:has(input:focus-visible){outline:3px solid var(--accent); outline-offset:2px}
.planpick input{margin:0; width:20px; height:20px; accent-color:var(--accent); flex:none}
.planpick .pp-text{flex:1; min-width:0}
.pp-name{display:block; font-size:var(--t-small); font-weight:600}
.pp-cap{display:block; font-size:15px; color:var(--fg-muted)}
.pp-price{flex:none; font-size:var(--t-lead); font-weight:700; text-align:end; white-space:nowrap}
.pp-price small{font-size:15px; font-weight:400; color:var(--fg-faint)}
.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}
.finehint{font-size:15px; color:var(--fg-faint); margin-top:var(--s4)}
.checkout-side h2{font-size:var(--t-small); margin:var(--s6) 0 var(--s3)}
.checkout-side h2:first-child{margin-top:0}
.checkout-side p,.checkout-side li{font-size:var(--t-small); color:var(--fg-muted)}
.checkout-side li{padding-inline-start:var(--s5); position:relative; margin-bottom:var(--s2)}
.checkout-side li::before{content:"✓"; position:absolute; inset-inline-start:0; color:var(--accent); font-weight:700}
.checkout-side a{color:var(--accent); text-decoration:underline}
@media (max-width:900px){ .checkout{grid-template-columns:1fr; gap:var(--s6)} }

/* ---------- licence key ---------- */
.keybox{border:1px solid var(--accent); border-radius:var(--r-lg); background:var(--accent-wash); padding:var(--s6); text-align:center}
.keybox .k{font-size:var(--t-small); font-weight:600; color:var(--accent-deep)}
.keybox .key{
  font-size:30px; font-weight:700; letter-spacing:0; margin:var(--s3) 0 var(--s4);
  word-break:break-all; color:var(--fg);
}
.keymeta{display:flex; justify-content:center; gap:var(--s6); flex-wrap:wrap; margin-top:var(--s5); font-size:var(--t-small); color:var(--fg-muted)}
.keymeta b{display:block; font-size:15px; color:var(--fg-faint); font-weight:600}
@media (max-width:760px){ .keybox .key{font-size:22px} }

/* ---------- admin (Operate, not Persuade) ---------- */
/* Denser than the marketing pages on purpose: this is a screen to scan, not to
   read. 15px is the floor even here — below that Bangla conjuncts break. */
.admintabs{border-bottom:1px solid var(--line); background:var(--bg-sunken)}
.admintabs .container{display:flex; align-items:center; gap:var(--s6); min-height:60px; flex-wrap:wrap}
.admintabs .brand small{font-weight:400; font-size:15px; color:var(--fg-faint)}
.admintabs nav{display:flex; align-items:center; gap:var(--s5); font-size:var(--t-small); flex-wrap:wrap}
.admintabs nav>a{color:var(--fg-muted); padding-block:var(--s2)}
.admintabs nav>a[aria-current]{color:var(--accent); font-weight:600; box-shadow:inset 0 -2px 0 var(--accent)}

/* A heading in the admin bar, and the links that live under it. Built on
   <details>, so it opens and closes with no script at all. */
.navgrp{position:relative}
.navgrp>summary{
  display:inline-flex; align-items:center; gap:var(--s1); cursor:pointer; list-style:none;
  color:var(--fg-muted); padding-block:var(--s2); user-select:none;
}
.navgrp>summary::-webkit-details-marker{display:none}
.navgrp>summary:hover{color:var(--accent)}
.navgrp>summary:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:4px}
.navgrp>summary svg{width:11px; height:11px; flex:none; opacity:.65; transition:transform .15s}
.navgrp[open]>summary svg{transform:rotate(180deg)}
/* Marked while shut too, or the bar stops answering "where am I". */
.navgrp[data-here]>summary{color:var(--accent); font-weight:600; box-shadow:inset 0 -2px 0 var(--accent)}
.navmenu{
  position:absolute; z-index:30; inset-inline-start:0; top:calc(100% + var(--s2));
  display:flex; flex-direction:column; min-width:11rem; padding:var(--s1);
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  box-shadow:0 10px 28px rgba(15, 32, 30, .13);
}
/* The last heading sits nearest the edge; its menu opens inward. */
.navgrp:last-of-type .navmenu{inset-inline-start:auto; inset-inline-end:0}
.navmenu a{padding:var(--s2) var(--s3); border-radius:calc(var(--r) - var(--s1));
  color:var(--fg-muted); white-space:nowrap}
.navmenu a:hover{background:var(--bg-sunken); color:var(--fg)}
.navmenu a[aria-current]{color:var(--accent); font-weight:600; background:var(--bg-sunken)}

/* On a narrow screen the bar wraps onto two lines, and a menu hung under its
   own heading then falls off one edge or the other — off the right for the
   middle headings, off the left for the last one once it has wrapped. So
   below this width the menu is measured from the bar instead and opens the
   full width beneath it, where there is no edge to fall off. */
@media (max-width:720px){
  /* Three rows on a phone — brand, then the links, then sign-out on a line of
     its own — took 233px of a 375px screen before you reached the page. Two
     rows: the brand and the way out share the first, because both are small
     and neither is what you came for. */
  .admintabs .container{
    position:relative;
    display:grid; grid-template-columns:1fr auto; align-items:center;
    gap:var(--s2) var(--s4); padding-block:var(--s3); min-height:0;
  }
  /* Placed by row, not left to auto-placement: nav spans both columns, so
     anything after it in source order is pushed onto a row of its own. */
  .admintabs .brand{grid-column:1; grid-row:1}
  .admintabs .out{grid-column:2; grid-row:1; margin-inline-start:0}
  .admintabs nav{grid-column:1 / -1; grid-row:2; gap:var(--s3) var(--s4)}
  .navgrp{position:static}
  /* Named twice so it also beats the last-heading rule above. */
  .navgrp .navmenu, .navgrp:last-of-type .navmenu{
    inset-inline:0; top:100%; flex-direction:row; flex-wrap:wrap; gap:var(--s1);
    padding:var(--s3); border-radius:0 0 var(--r) var(--r);
  }
  /* A finger, not a pointer: 42px was under the 44 minimum. */
  .navmenu a{padding:var(--s3) var(--s4)}
}
.admintabs .out{margin-inline-start:auto; font-size:var(--t-small); color:var(--fg-faint)}
/* The admin is an Operate surface and gets more width than a reading one.
   1180px is a measure for prose; a seven-column licence table in it scrolled
   sideways on every screen, however big, because the container — not the
   window — was the constraint. */
.adminwrap{padding-block:var(--s6) var(--s9)}
.adminwrap .container{max-width:1440px}
.adminwrap h2{font-size:var(--t-lead); margin:var(--s7) 0 var(--s4)}
.adminwrap .empty{font-size:var(--t-small); color:var(--fg-faint); padding:var(--s5) 0}
.adminwrap table{font-size:var(--t-small)}
.adminwrap td small{font-size:15px}
.adminlogin{padding-block:var(--s9)}
.adminlogin .orderform{max-width:24rem; margin-inline:auto}
.adminlogin h1{font-size:var(--t-h2); margin-bottom:var(--s5)}
.adminlogin input[type=password]{
  width:100%; min-height:52px; padding:0 var(--s4); font:inherit; font-size:var(--t-body);
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.figures{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--s4)}
.fig{border:1px solid var(--line); border-radius:var(--r); padding:var(--s5)}
.fig span{display:block; font-size:15px; color:var(--fg-faint)}
.fig b{display:block; font-size:30px; font-weight:700; line-height:1.3; color:var(--accent-deep)}
.fig em{display:block; font-style:normal; font-size:15px; color:var(--fg-muted)}

/* ---------- the admin home ----------
   A map of the admin, not a report. Three layers, in the order somebody
   opening it needs them: what the shop took, what is waiting on a person,
   and every screen there is with the one number that says whether it needs
   opening. */
.home-top{display:flex; align-items:flex-end; justify-content:space-between; gap:var(--s4); flex-wrap:wrap; margin-bottom:var(--s5)}
.home-top h1{font-size:var(--t-lead); line-height:1.4; margin:0}
.home-top .when{display:block; font-size:var(--t-small); color:var(--fg-faint)}
.home-top .filterbar{margin:0}
.home-top .filterbar input[type=search]{min-width:min(22rem, 100%)}

/* What needs a person. Only lines with a count are rendered — a row of
   zeroes teaches the eye to skip the whole block. */
.todo{border:1px solid var(--line); border-radius:var(--r-lg); background:var(--surface); margin-top:var(--s5); overflow:hidden}
.todo-head{display:flex; align-items:center; justify-content:space-between; gap:var(--s3);
  padding:var(--s3) var(--s4); border-bottom:1px solid var(--line); background:var(--bg-sunken);
  font-size:var(--t-small); font-weight:600}
.todo-head span{font-weight:400; color:var(--fg-faint)}
.todo a{display:flex; align-items:center; gap:var(--s3); padding:var(--s3) var(--s4);
  border-top:1px solid var(--line); font-size:var(--t-small); color:var(--fg); transition:background-color .12s}
.todo a:first-of-type{border-top:0}
.todo a:hover{background:var(--bg-sunken)}
.todo a > span{display:flex; flex-wrap:wrap; column-gap:var(--s2)}
.todo .pill{min-width:2.6em; text-align:center; font-weight:700}
.todo em{font-style:normal; color:var(--fg-muted)}
.todo .go{margin-inline-start:auto; width:16px; height:16px; color:var(--fg-faint); flex:none}
.todo .none{padding:var(--s4); font-size:var(--t-small); color:var(--fg-faint)}

/* Every screen in the admin, grouped the way the bar is, so the map and the
   menu never disagree about where a thing lives. */
.launch{margin-top:var(--s6); display:grid; grid-template-columns:1fr 1fr; gap:var(--s6)}
.launch h2{font-size:var(--t-body); font-weight:700; margin:0 0 var(--s3)}
.tiles{display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap:var(--s3)}
/* Four sit two by two; three across and one alone reads as a leftover. */
.tiles.four{grid-template-columns:repeat(2, 1fr)}
.tile{display:grid; grid-template-columns:auto 1fr; grid-template-rows:auto auto auto; column-gap:var(--s3);
  padding:var(--s4); border:1px solid var(--line); border-radius:var(--r); background:var(--surface);
  color:var(--fg); transition:border-color .12s}
.tile:hover{border-color:var(--accent)}
.tile:hover .tile-name{color:var(--accent)}
.tile-ico{grid-row:1/4; width:40px; height:40px; border-radius:var(--r); background:var(--accent-wash);
  display:grid; place-items:center; align-self:start}
.tile-ico .ico{width:22px; height:22px}
.tile-name{font-size:var(--t-small); font-weight:600; line-height:1.5}
.tile-fig{font-size:var(--t-lead); font-weight:700; line-height:1.4; color:var(--accent-deep)}
.tile-fig small{font-size:var(--t-small); font-weight:500; color:var(--fg-muted); margin-inline-start:var(--s1)}
.tile-sub{font-size:var(--t-small); color:var(--fg-faint); line-height:1.6}

.recent{margin-top:var(--s6)}
.recent .rhead{display:flex; align-items:baseline; justify-content:space-between; gap:var(--s3); margin-bottom:var(--s3)}
.recent .rhead h2{margin:0; font-size:var(--t-body)}
.recent .rhead a{font-size:var(--t-small); color:var(--accent); font-weight:600}

@media (max-width:900px){.launch{grid-template-columns:1fr; gap:var(--s5)}}
/* On a phone the list of what needs doing comes before the takings: it is
   what somebody opening this on the move came for. The figures shrink so the
   list is still above the fold. */
@media (max-width:760px){
  .home{display:flex; flex-direction:column}
  .home .home-top{order:-2}
  .home .todo{order:-1; margin:0 0 var(--s5)}
  .figures{grid-template-columns:1fr 1fr}
  .fig{padding:var(--s4)}
  .fig b{font-size:var(--t-lead)}
}
@media (max-width:480px){
  .tiles, .tiles.four{grid-template-columns:1fr 1fr; gap:var(--s2)}
  /* A third card in two columns would sit alone; it takes the whole row. */
  .tile:last-child:nth-child(odd){grid-column:1 / -1}
  .tile{padding:var(--s3); column-gap:var(--s2)}
  .tile-ico{width:32px; height:32px}
  .tile-ico .ico{width:18px; height:18px}
}
.filterbar{display:flex; gap:var(--s3); align-items:center; flex-wrap:wrap; margin-bottom:var(--s5)}
.filterbar input[type=search]{
  min-height:44px; padding:0 var(--s4); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r); min-width:16rem; background:var(--surface); color:var(--fg);
}
.chipfilter{
  font-size:var(--t-small); border:1px solid var(--line-strong); border-radius:var(--r-pill);
  padding:var(--s2) var(--s4); color:var(--fg-muted);
}
.chipfilter.on{background:var(--accent); border-color:var(--accent); color:var(--accent-ink); font-weight:600}

/* How many are behind each tab. Tabular figures so the three chips do not
   change width as the counts do, and a lighter weight than the label: the
   number is the reason to press it, not the thing being pressed. */
.tabrow .n{margin-inline-start:var(--s2); font-variant-numeric:tabular-nums; opacity:.75}
.tabrow{margin-top:calc(-1 * var(--s3))}

/* What the renewal will cost. Under the date, quiet — until it has been set by
   hand, which is a fact about this one licence and worth showing plainly. */
.licences .renewprice{display:block; color:var(--fg-muted); font-variant-numeric:tabular-nums}
.licences .renewprice.set{color:var(--fg); font-weight:600}
.licences .acts form,.adminwrap .acts form{display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center}
.acts input[type=text]{
  min-height:34px; padding:0 var(--s3); font:inherit; font-size:15px; width:11rem;
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
/* Changing a plan, in the column that shows it.

   It started in the actions cell beside the other verbs, and measuring
   said no: a fifth control pushed the buttons onto a third line and put
   42px on every row that had four of them. Here it costs nothing on a row
   that is already three lines tall — the licence key wraps — and lifts the
   short rows to the same height, which reads as more regular, not less.

   The only select in the admin, so it is given the body of the text input
   in the actions cell rather than a look of its own. min-width, because
   auto sizes to about 83px and clips "বিজনেস". */
.planform{display:flex; flex-direction:column; gap:var(--s2); align-items:flex-start}
.planform select{
  min-height:34px; min-width:7rem; padding:0 var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.planform select:hover{background:var(--bg-sunken)}
/* ---------- staff sign-in and the team screen ---------- */
/* A second way in, under the first and quieter than it: the owner uses the
   password every day and an agent uses this once. */
.adminlogin .staffin{max-width:24rem; margin:var(--s6) auto 0; background:var(--bg-sunken)}
.adminlogin .staffin h2{font-size:var(--t-lead); margin-bottom:var(--s2)}
.adminlogin .staffin .settings-lede{margin-bottom:var(--s4)}
.staffadd{max-width:38rem; margin-bottom:var(--s6)}
.staffadd .row2{display:grid; grid-template-columns:1fr 1fr; gap:var(--s4)}
@media (max-width:520px){ .staffadd .row2{grid-template-columns:1fr} }

/* Setting somebody's password from the list: a field and a button on one line,
   narrow enough that it does not push the row's other actions off screen. */
.pwreset{display:flex; gap:var(--s2); align-items:center; margin-bottom:var(--s2)}
.pwreset input{width:11rem; min-width:0; padding:6px var(--s3); font-size:14px}

.pwform{max-width:26rem}

/* ---------- what was said to a lead, and when ---------- */
/* A call log, not a note field. Newest first, because the last thing said is
   what the next caller needs; the time and the name are dimmer than the words
   because you scan for the words and only then ask who and when. */
.notelog{list-style:none; margin:var(--s2) 0 0; padding:0; display:grid; gap:var(--s2)}
.notelog li{
  font-size:14px; line-height:1.7; padding-left:var(--s3);
  border-left:2px solid var(--line);
}
.notelog li:first-child{border-left-color:var(--accent)}
.notewhen{display:block; font-size:13px; color:var(--fg-muted)}

/* ---------- who is asking, on the ticket form ---------- */
/* Shown, not asked. The server takes these from the account either way, so a
   box here would be a lie about what is editable. */
.asme{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--s3) var(--s6);
  background:var(--bg-sunken); border-radius:var(--r);
  padding:var(--s3) var(--s4); margin-bottom:var(--s4);
}
.asme span{display:block; font-size:13px; color:var(--fg-muted)}
.asme b{font-size:var(--t-body); font-weight:600}
.asme a{margin-left:auto; font-size:14px}

/* ---------- a support conversation ---------- */
/* Not chat bubbles. It is read once, often days apart, by somebody who needs
   to find what was said — so it reads as a transcript, and who said it is a
   label rather than a side of the screen. */
.thread{max-width:44rem; margin:0 auto var(--s6)}
.line{
  border:1px solid var(--line); border-inline-start:3px solid var(--line-strong);
  border-radius:var(--r); padding:var(--s4) var(--s5); margin-bottom:var(--s4);
  background:var(--surface);
}
.line-us{border-inline-start-color:var(--accent); background:var(--accent-wash)}
.line header{display:flex; align-items:baseline; gap:var(--s3); margin-bottom:var(--s2); font-size:var(--t-small)}
.line header b{font-weight:600}
.line-us header b{color:var(--accent-deep)}
.line header time{margin-inline-start:auto; color:var(--fg-faint); font-size:14px}
.line p{color:var(--fg-muted); font-size:var(--t-small); white-space:pre-line}
.threadreply{margin-top:var(--s6)}
.threadreply textarea{
  width:100%; padding:var(--s3) var(--s4); font:inherit; font-size:var(--t-body);
  line-height:1.75; resize:vertical; min-height:7rem;
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.ticketreply{max-width:44rem}
.ticketreply textarea{
  width:100%; padding:var(--s3) var(--s4); font:inherit; font-size:var(--t-small);
  line-height:1.7; resize:vertical; margin-bottom:var(--s4);
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.ticketreply p{display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center}
.adminwrap .thread{margin-inline:0}

/* ---------- the SMS wording editor ---------- */
.msgform{max-width:52rem}
.msg{border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--s5); margin-bottom:var(--s5)}
.msg-head{display:flex; align-items:center; gap:var(--s3); flex-wrap:wrap; margin-bottom:var(--s2)}
.msg-head b{font-size:var(--t-lead)}
/* The part count is the price of the message, so it is loud when it is >1. */
.msg-parts{margin-inline-start:auto; font-size:14px; font-weight:600; color:var(--fg-faint)}
.msg-parts.over{color:var(--danger)}
.msg-when{color:var(--fg-muted); font-size:var(--t-small); margin-bottom:var(--s3)}
/* A switched-off message is faded but still readable and still editable — the
   wording is worth keeping while it is off, so it is there when it goes back on. */
.msg.is-off{background:var(--bg-sunken)}
.msg.is-off textarea,.msg.is-off .msg-preview{opacity:.6}
.msg-on{display:flex; align-items:center; gap:var(--s3); margin-bottom:var(--s3); cursor:pointer}
.msg-on input{width:20px; height:20px; accent-color:var(--accent); margin:0; flex:none}
.msg-on span{font-size:var(--t-small); font-weight:600}
.msg-locked{
  font-size:14px; color:var(--warn); background:var(--warn-wash);
  border-radius:var(--r); padding:var(--s2) var(--s3); margin-bottom:var(--s3); max-width:60ch;
}
.msg textarea{
  width:100%; padding:var(--s3) var(--s4); font:inherit; font-size:var(--t-small);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace; line-height:1.7; resize:vertical;
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.msg-tokens{margin-top:var(--s2); font-size:14px; color:var(--fg-faint)}
.msg-tokens code{
  background:var(--bg-sunken); border-radius:4px; padding:1px 6px; margin-inline-end:var(--s2);
  font-size:13px; color:var(--accent);
}
.msg-preview{margin-top:var(--s3); font-size:14px; color:var(--fg-muted)}
.msg-preview span{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; overflow-wrap:anywhere}

/* ---------- status pills ---------- */
/* Used on the flagship table and in all four admin tables, and never defined
   anywhere: every status has been rendering as plain text the same weight as
   the words around it. Status is the one thing a table like this is scanned
   for. All four tones measured on their wash: 6.4:1 or better. */
.pill{
  display:inline-block; font-size:14px; font-weight:600; white-space:nowrap;
  border-radius:var(--r-pill); padding:1px var(--s3);
  background:var(--bg-sunken); color:var(--fg-muted);
}
.pill.g{background:var(--good-wash); color:var(--good)}
.pill.w{background:var(--warn-wash); color:var(--warn)}
.pill.d{background:var(--danger-wash); color:var(--danger)}

/* ---------- every table in the admin ---------- */
/* An Operate surface: dense is right, and the fault was never the density. It
   was that every row said everything at one weight — a name run into a phone
   number with nothing between them, a 28-character key wrapped onto three
   lines, and on the licence screen seven identical bordered buttons wrapping
   onto three more.
   Written for all four admin tables at once, not for one of them: they had the
   same faults because they had no treatment at all. */
/* The customer's account page has tables too — receipts and support tickets —
   and every rule below was scoped to .adminwrap, so they had no treatment at
   all: no padding, no rules between rows, and `৳২০<small>মাসিক</small>` ran
   together into "৳২০মাসিক" because the small was never made a block. Adding
   .acct to the selector rather than writing a second set: two copies of a
   table treatment is how the two drift. */
.adminwrap table,.acct table{width:100%; border-collapse:collapse}
.adminwrap th,.acct th{
  text-align:start; font-size:15px; font-weight:600; color:var(--fg-faint);
  padding:0 var(--s4) var(--s3); border-bottom:1px solid var(--line); white-space:nowrap;
}
.adminwrap td,.acct td{
  vertical-align:top; padding:var(--s4); border-bottom:1px solid var(--line);
  line-height:1.7;   /* Bangla stacks three zones; 1.5 smudges it */
}
.adminwrap tbody tr:hover,.acct tbody tr:hover{background:var(--bg-sunken)}
.adminwrap td small,.acct td small{display:block; font-size:14px; color:var(--fg-faint); margin-top:2px}
/* An id or a key: Latin, fixed width, and not something to read as prose. */
.adminwrap td.num > code,.lkey{white-space:nowrap}

/* The key is a fixed 28 characters. Left to wrap it took three lines and set
   the height of every row in the table. */
.lkey{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:13px; letter-spacing:0; white-space:nowrap;
  background:var(--bg-sunken); border-radius:var(--r); padding:2px var(--s2);
}
.adminwrap .who{display:block; font-weight:600}
/* The select and its verb side by side, not stacked. Three things down the
   cell made it the tallest in the table and set the height of every row. */
.licences .planform{flex-direction:row; align-items:center; margin-bottom:var(--s2)}
.licences .planform select{min-width:6.5rem}
/* Shrink-to-content on everything with a known shape, so the two columns that
   hold names and addresses get the slack instead. Without this the browser
   shared the width evenly, the actions cell came out narrower than its two
   buttons and they stacked — which is the thing this row was rebuilt to stop. */
.licences th:nth-child(1),.licences td:nth-child(1),
.licences th:nth-child(4),.licences td:nth-child(4),
.licences th:nth-child(5),.licences td:nth-child(5),
.licences th:nth-child(6),
.licences th:nth-child(7),.licences td:nth-child(7){width:1%; white-space:nowrap}
.licences td:nth-child(5){white-space:normal}
.licences td:nth-child(6) .pill{white-space:nowrap}
.licences td:nth-child(5) .renew{white-space:nowrap}
.licences th:nth-child(2),.licences th:nth-child(3){width:auto}

/* The installs a key is running on. One line each, the address doing the
   talking and the way to free it kept quiet beside it — pressing it puts a
   real shop behind a wall, so it should never be the thing the eye lands on.
   The cell wraps, unlike its neighbours: a path can be long and truncating an
   address is how somebody frees the wrong one. */
.licences td.sites{white-space:normal; min-width:14rem}
.licences .site{display:flex; gap:var(--s2); align-items:baseline; justify-content:space-between}
.licences .site + .site{margin-top:2px}
.licences .site span{overflow-wrap:anywhere}
.licences .freeone{display:inline}
.licences .freebtn{
  background:none; border:0; padding:0; cursor:pointer;
  font:inherit; font-size:15px; color:var(--fg-muted);
  text-decoration:underline; text-underline-offset:2px;
}
.licences .freebtn:hover,.licences .freebtn:focus-visible{color:var(--danger)}
.licences td.sites .pill{margin-top:var(--s2)}

.licences .doth{text-align:end}
.licences .acts{text-align:end}
.licences .acts form{display:flex; flex-direction:column; gap:var(--s2); align-items:flex-end}

/* One verb, then a menu. Native <details>: no script, and the keyboard works.
   Named .rowmenu, not .more — `.more` is already the "সব ফিচার দেখুন" link on
   the homepage, and its margin-top:48px pushed this menu a line below the
   button it belongs beside. Second time a name has been reused in this file;
   see the note above .act for the first.

   It opens **inline**, not as a floating panel. A panel would have to be
   absolutely positioned, and this table sits in a box that scrolls sideways
   when the window is narrow — which clips anything positioned out of flow.
   Growing the row instead cannot be clipped at any width, and in a table
   nobody reads top to bottom that costs nothing. */
.rowmenu{display:block; margin:0; text-align:start}
.rowmenu summary{
  list-style:none; cursor:pointer; user-select:none;
  font-size:15px; font-weight:600; white-space:nowrap;
  border:1px solid var(--line-strong); border-radius:var(--r);
  padding:var(--s1) var(--s3); min-height:34px;
  display:inline-flex; align-items:center; gap:var(--s1);
}
.rowmenu summary::-webkit-details-marker{display:none}
.rowmenu summary::after{content:'▾'; font-size:11px; color:var(--fg-faint)}
.rowmenu summary:hover{background:var(--bg-sunken)}
.rowmenu summary:focus-visible{outline:3px solid var(--accent); outline-offset:2px}
.rowmenu[open] summary{background:var(--bg-sunken)}
.rowmenu[open] summary::after{content:'▴'}
.rowmenu .menu{
  display:flex; flex-direction:column; align-items:stretch;
  margin-top:var(--s2); padding:var(--s2);
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg-sunken);
}
.rowmenu .menu button{
  font:inherit; font-size:15px; text-align:start; cursor:pointer;
  background:none; border:0; border-radius:var(--r);
  padding:var(--s2) var(--s3); min-height:40px; color:var(--fg); white-space:nowrap;
}
.rowmenu .menu button:hover{background:var(--surface)}
.rowmenu .menu button:focus-visible{outline:3px solid var(--accent); outline-offset:-2px}
.rowmenu .menu button.danger{color:var(--danger)}
.rowmenu .menu button.danger:hover{background:var(--danger-wash)}
.rowmenu .menu button.good{color:var(--good)}
.rowmenu .menu button.good:hover{background:var(--good-wash)}
.rowmenu .menu hr{border:0; border-top:1px solid var(--line); margin:var(--s2) var(--s1)}
/* Setting the renewal date by hand: a labelled date field above its button. */
.rowmenu .menu .setdate{display:flex; flex-direction:column; gap:2px; padding:var(--s2) var(--s3) 0}
.rowmenu .menu .setdate span{font-size:12px; color:var(--fg-faint)}
.rowmenu .menu .setdate input{
  font:inherit; font-size:14px; padding:6px var(--s2); color:var(--fg);
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface);
}
.rowmenu .menu .setdate input:focus-visible{outline:2px solid var(--accent); outline-offset:1px}

a.act{display:inline-flex; align-items:center; text-decoration:none}
/* Named .act, not .mini — .mini is the pill group inside a feature card, and
   this rule's border was drawing a box around those pills on the homepage. */
.act{
  font:inherit; font-size:15px; font-weight:600; cursor:pointer;
  border:1px solid var(--line-strong); background:var(--surface); color:var(--fg);
  border-radius:var(--r); padding:var(--s1) var(--s3); min-height:34px; white-space:nowrap;
}
.act:hover{background:var(--bg-sunken)}
.act.danger{color:var(--danger); border-color:var(--danger)}
.act.good{color:var(--good); border-color:var(--good)}
@media (max-width:900px){ .figures{grid-template-columns:repeat(2,1fr)} }

/* ---------- customer dashboard ---------- */
/* Two ways to sign in. Links, not tabs: this page is opened on a cheap
   phone on mobile data by somebody who has already lost one credential,
   and a tab strip that needs JavaScript to work is one more thing that can
   fail to. */
.loginbox{max-width:32rem}
.loginways{display:flex; gap:var(--s2); margin-bottom:var(--s5)}
.loginway{
  flex:1; text-align:center; text-decoration:none;
  font-size:var(--t-small); font-weight:600; color:var(--fg-muted);
  border:1px solid var(--line-strong); border-radius:var(--r);
  padding:var(--s3) var(--s4); min-height:44px;
  display:flex; align-items:center; justify-content:center;
}
.loginway:hover{background:var(--bg-sunken)}
/* The one you are on carries the accent, so it is not a matter of noticing
   which of two identical pills is a shade different. */
.loginway.on{background:var(--accent); border-color:var(--accent); color:var(--accent-ink)}
.notice{background:var(--good-wash); color:var(--good); font-size:var(--t-small); font-weight:600; padding:var(--s4); border-radius:var(--r); margin-bottom:var(--s5)}
.lcard{border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--s6); margin-bottom:var(--s5)}
.planchange label{display:block; font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2)}
.planchange .row{display:flex; gap:var(--s3); flex-wrap:wrap}
.planchange select{
  flex:1; min-width:14rem; min-height:48px; padding:0 var(--s4); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.planchange .hint,.renewform .hint{display:block; font-size:15px; color:var(--fg-faint); margin-top:var(--s2)}
.renewform{display:flex; flex-direction:column; align-items:flex-start}
/* Red on the outline only. A filled red button beside a plan dropdown reads
   as "delete my licence", and this deletes nothing — it stops a renewal. */
.btn-ghost.danger{color:var(--danger); border-color:var(--danger)}
.btn-ghost.danger:hover{background:var(--danger-wash)}
/* Said once, at the top of the card, in the colour of the thing it warns
   about — not on the button, which the person has already pressed. */
.ending{
  background:var(--danger-wash); color:var(--danger); font-size:var(--t-small); font-weight:600;
  padding:var(--s4); border-radius:var(--r); margin:var(--s5) 0 0;
}
.domform{margin-top:var(--s5); border-top:1px solid var(--line); padding-top:var(--s5)}
.domform label{display:block; font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2)}
.domform .row{display:flex; gap:var(--s3); flex-wrap:wrap}
.domform input{
  flex:1; min-width:14rem; min-height:48px; padding:0 var(--s4); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r); background:var(--surface); color:var(--fg);
}
.domform .hint{display:block; font-size:15px; color:var(--fg-faint); margin-top:var(--s2)}
.empty{font-size:var(--t-small); color:var(--fg-faint)}

/* ---------- account page: one card per site, quiet unless it must not be ----------
   Every value is a token. The rules this replaced were removed with it. */

/* The line at the top when there is more than one site. */
.lsummary{font-size:var(--t-small); color:var(--fg-muted); margin:0 0 var(--s5)}
.lsummary b{color:var(--fg)}
.lsummary-warn{color:var(--warn); font-weight:600}

/* Tighter than v1 (s5, not s6): three of these on one screen is the case that
   matters, and the padding was a fifth of every card. The top edge carries the
   only colour the card ever gets. */
.lcard.lsite{padding:var(--s5); border-top:3px solid var(--line)}
.lcard.lsite.is-warn{border-top-color:var(--warn)}
.lcard.lsite.is-danger{border-top-color:var(--danger)}
.lcard.lsite.is-muted{border-top-color:var(--line-strong)}

.lhead2{display:flex; align-items:flex-start; justify-content:space-between; gap:var(--s4); flex-wrap:wrap}
.lwho{min-width:0; flex:1}
/* The domain is the title. --t-lead, the same step the v1 key used, so the
   hierarchy is unchanged — only what sits at the top of it. */
.ldomain{font-size:var(--t-lead); font-weight:700; margin:0; line-height:1.3; word-break:break-all}
.ldomain-none{color:var(--fg-faint); font-weight:600}
.lmeta{font-size:var(--t-small); color:var(--fg-muted); margin:var(--s1) 0 0; display:flex; flex-wrap:wrap; gap:var(--s2) var(--s3); align-items:baseline}
/* The key, demoted but still there and still selectable. 15px is the floor
   for --fg-faint (5.09:1); it does not go smaller. */
.lkey{font-size:15px; color:var(--fg-faint); word-break:break-all; overflow-wrap:anywhere; white-space:normal}
/* Flex items refuse to shrink below their content by default, and a 28-char
   key has no spaces to break at — at 320px it pushed 140px past the card.
   min-width:0 lets it wrap; on a phone it takes its own line. */
.lmeta > *{min-width:0}
@media (max-width:480px){ .lkey{flex:1 1 100%} }

/* The one row on every card: renews when, used how much, running where. */
.lstate{
  display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:var(--s4);
  margin-top:var(--s5); padding-top:var(--s4); border-top:1px solid var(--line);
}
.lstate > div{min-width:0}
.lstate b{display:block; font-size:15px; font-weight:600; color:var(--fg-faint); margin-bottom:var(--s1)}
.lstate span{font-size:var(--t-body); font-weight:700; color:var(--fg); overflow-wrap:anywhere}
.lstate small{display:block; font-size:15px; color:var(--fg-muted); margin-top:2px}
/* A price agreed by hand. Accent, because it is the one number on the card
   that is this shop's alone and not a fact about the plan. */
.lstate .lmine{color:var(--accent-deep); margin-top:var(--s1)}
.lstate .lmine s{color:var(--fg-faint); font-weight:400; margin-inline-end:4px}
/* .lstate b is display:block — it makes the three column labels stack. Inside
   this line the <b> is the price itself and has to sit beside the struck one,
   so it goes back to inline. Measured, not guessed: the <b> was rendering
   350px wide, the full column, which is what pushed it onto its own line and
   made nowrap look broken. */
.lstate .lmine b{display:inline; font-weight:700}
/* The old price and the new one stay on one line whatever the column width;
   the label wraps before them instead. */
.lstate .lmine-n{white-space:nowrap}
.lstate-renew.renew-soon span,.lstate-renew.renew-soon small{color:var(--warn)}
.lstate-renew.renew-expired span,.lstate-renew.renew-expired small{color:var(--danger)}
.lstate-renew.renew-cancelled span{color:var(--fg-muted)}
.lstate-quota.warn span{color:var(--warn)}
.lstate-quota.over span{color:var(--danger)}
/* The bar reuses .bar's geometry but sits inside the cell, so it is its own
   class rather than .bar with a margin override. */
.lbar{display:block; height:6px; border-radius:var(--r-pill); background:var(--bg-sunken); overflow:hidden; margin-top:var(--s2)}
.lbar i{display:block; height:100%; background:var(--accent); border-radius:var(--r-pill)}
.lstate-quota.warn .lbar i{background:var(--warn)}
.lstate-quota.over .lbar i{background:var(--danger)}

/* The sentence and the button, only when there is one. Wash matches the edge. */
.lact{
  display:flex; align-items:center; justify-content:space-between; gap:var(--s3) var(--s4); flex-wrap:wrap;
  margin-top:var(--s4); padding:var(--s3) var(--s4); border-radius:var(--r);
  background:var(--bg-sunken);
}
.lact p{margin:0; font-size:var(--t-small); font-weight:600; color:var(--fg)}
.lact-form{margin:0}
.lcard.lsite.is-warn .lact{background:var(--warn-wash)} .lcard.lsite.is-warn .lact p{color:var(--warn)}
.lcard.lsite.is-danger .lact{background:var(--danger-wash)} .lcard.lsite.is-danger .lact p{color:var(--danger)}

/* Settings, folded. A native disclosure: no script, keyboard-operable, and the
   forms inside are unchanged. */
.lmore{margin-top:var(--s4); border-top:1px solid var(--line)}
.lmore summary{
  cursor:pointer; list-style:none; padding:var(--s3) 0; min-height:44px;
  display:flex; align-items:center; gap:var(--s2);
  font-size:var(--t-small); font-weight:600; color:var(--fg-muted);
}
.lmore summary::-webkit-details-marker{display:none}
.lmore summary::before{
  content:""; width:8px; height:8px; flex:none;
  border-right:2px solid currentColor; border-bottom:2px solid currentColor;
  transform:rotate(-45deg); transition:transform .15s;
}
.lmore[open] summary::before{transform:rotate(45deg)}
.lmore summary span{font-weight:400; color:var(--fg-faint)}
.lmore summary:hover{color:var(--fg)}
.lmore summary:focus-visible{outline:2px solid var(--accent); outline-offset:2px; border-radius:var(--r)}
.lmore-body{display:flex; flex-direction:column; gap:var(--s5); padding:var(--s2) 0 var(--s3)}
.lmore-row{margin:0; padding:0; border:0}
.lmore-row > b,.lmore-row > label{display:block; font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2)}
.lmore-row .row{display:flex; gap:var(--s3); flex-wrap:wrap}
.lmore-row .hint{display:block; font-size:15px; color:var(--fg-faint); margin-top:var(--s2)}
/* .planchange/.domform/.renewform rules above still apply to the controls;
   only their v1 top borders and margins are switched off inside the fold. */
.lmore .planchange,.lmore .domform,.lmore .renewform{margin-top:0; border-top:0; padding-top:0}
/* v1 gave the select and the domain box min-width:14rem, which is wider than
   a 320px card's inside. In the fold they fill the row instead. */
/* A select is as wide as its longest option unless told otherwise, and the
   longest option here is ~250px of Bangla — wider than a 320px card's inside.
   width:100% makes it the row's width and the browser truncates the text. */
.lmore .planchange select,.lmore .domform input{min-width:0; width:100%; max-width:100%; flex:1 1 12rem}

@media (max-width:640px){
  .lstate{grid-template-columns:1fr 1fr}
  .lstate-live{grid-column:1 / -1}
  .lact{flex-direction:column; align-items:stretch}
  .lact .btn{text-align:center}
}
@media (max-width:400px){
  .lstate{grid-template-columns:1fr}
  .lstate-live{grid-column:auto}
}

/* ---------- icons ---------- */
/* One colour for all of them, on purpose. Six features with six gradient hues
   is six accents, which is no accent — see references/tells.md. */
.ico{width:22px; height:22px; color:var(--accent); flex:none; vertical-align:-3px}
.ico-lg{width:28px; height:28px}
.brand{display:inline-flex; align-items:center; gap:var(--s2)}
.brand img{width:28px; height:28px}
.stats .ico-lg{display:block; width:30px; height:30px; margin-bottom:var(--s3); color:var(--accent)}
.card .ico-lg{display:block; margin-bottom:var(--s4)}
.replaces li{display:grid; grid-template-columns:22px minmax(0,1fr); gap:var(--s1) var(--s3); align-items:start}
.replaces li b,.replaces li span{grid-column:2}
.replaces .ico{grid-row:span 2; color:var(--fg-faint)}
.fgroup h2 .ico-lg{color:var(--accent)}
@media (max-width:900px){ .replaces li{grid-template-columns:22px minmax(0,1fr)} }

/* ---------- admin settings ---------- */
.settings-lede{font-size:var(--t-small); color:var(--fg-muted); max-width:60ch; margin-bottom:var(--s5)}
.orderform.settings{max-width:38rem}

/* The settings groups on /admin/plans.

   They had no styling at all, so every label was display:inline and each group
   ran together as one paragraph with inputs embedded in the prose — "পরীক্ষাটা
   এখন চলবে কোন প্ল্যান [select] মাসিক দাম [490] বছর হবে এর দশ গুণ…". Readable
   as a sentence, unusable as a form, and this is the screen the pricing
   experiment is switched on from.

   The class is used on one page only, so this reaches nothing else. */
.settings-group{
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  padding:var(--s5);
  margin-bottom:var(--s6);
}
.settings-group > legend{
  font-size:var(--t-body); font-weight:700; padding:0 var(--s3);
}
.settings-group > label{display:block; margin-bottom:var(--s5)}
.settings-group > label:last-child{margin-bottom:0}
.settings-group > label > span{
  display:block; font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2);
}
.settings-group > label > small{
  display:block; font-size:15px; color:var(--fg-faint); margin-top:var(--s2); line-height:1.6;
}
.settings-group input[type=number],
.settings-group input[type=date],
.settings-group input[type=text],
.settings-group select{
  min-height:44px; padding:0 var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r);
  background:var(--surface); color:var(--fg);
}
.settings-group input[type=number]{width:8rem}
.settings-group input[type=date]{width:12rem}

/* A checkbox belongs beside its sentence, not above it. */
.settings-group > label.check{
  display:flex; align-items:flex-start; gap:var(--s3);
}
.settings-group > label.check input{
  width:20px; height:20px; accent-color:var(--accent); flex:none; margin:2px 0 0;
}
.settings-group > label.check > span{
  margin-bottom:0; font-weight:600; line-height:1.6;
}
.settings-group > .hint{
  font-size:15px; color:var(--fg-muted); line-height:1.7; margin-bottom:var(--s5);
}

/* A choice between two ways of ending, on the settings form. The order page's
   radios are scoped to .field, so without this the admin ones fall back to
   browser defaults next to styled controls — the one place a settings screen
   looks unfinished. */
.settings .radios{border:0; padding:0; margin:0 0 var(--s5)}
.settings .radios legend{font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2); padding:0}
.settings .radio{
  display:flex; gap:var(--s3); align-items:flex-start;
  padding:var(--s3) var(--s4); margin-bottom:var(--s2);
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg);
  cursor:pointer;
}
.settings .radio:has(input:checked){border-color:var(--accent); background:var(--accent-wash)}
.settings .radio input{width:20px; height:20px; accent-color:var(--accent); flex:none; margin:3px 0 0}
.settings .radio span{font-size:var(--t-small); line-height:1.6}
.settings .field label{display:flex; gap:var(--s3); align-items:baseline; flex-wrap:wrap}
.src{font-size:15px; font-weight:600; border-radius:var(--r-pill); padding:0 var(--s3)}
.src.db{background:var(--good-wash); color:var(--good)}
.src.config{background:var(--warn-wash); color:var(--warn)}
.src.none{background:var(--bg-sunken); color:var(--fg-faint)}
.settings input[type=text],.settings input[type=tel]{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:var(--t-small)}

/* ---------- plan editor ---------- */
.planedit td b{display:block}
.planedit td small{display:block; color:var(--fg-faint); font-size:15px}
.planedit input[type=number]{
  width:8rem; min-height:44px; padding:0 var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r);
  background:var(--surface); color:var(--fg);
}
.adminwrap .orderform.settings{max-width:none}
.planedit{max-width:56rem}

/* ---------- telegram setup ---------- */
.howto{max-width:62ch; margin:0 0 var(--s5); padding-inline-start:var(--s5); list-style:decimal}
.howto li{font-size:var(--t-small); color:var(--fg-muted); margin-bottom:var(--s3)}
.howto b{color:var(--fg)}
.howto code,.settings-lede code{background:var(--bg-sunken); border-radius:4px; padding:1px 6px; font-size:15px}
.chatlist{max-width:34rem; margin-bottom:var(--s5)}

/* ---------- legal ---------- */
.legal{max-width:68ch}
.legal h2{font-size:var(--t-lead); margin:var(--s7) 0 var(--s3)}
.legal h2:first-child{margin-top:0}
.legal p{color:var(--fg-muted); font-size:var(--t-small); margin-bottom:var(--s3)}

/* ---------- renewing from a key ---------- */
.renewwrap{max-width:38rem; margin-inline:auto}
.renewfacts{
  /* The domain is the longest of the three and the one worth reading whole. */
  display:grid; grid-template-columns:1.5fr 1fr 1fr; gap:var(--s4);
  border:1px solid var(--line); border-radius:var(--r-lg);
  background:var(--bg-sunken); padding:var(--s5); margin-bottom:var(--s5);
}
.renewfacts b{display:block; font-size:15px; color:var(--fg-faint); font-weight:600}
.renewfacts span{display:block; font-weight:600; overflow-wrap:break-word; font-size:var(--t-small)}
.renewto{color:var(--fg-muted); font-size:var(--t-small); margin-bottom:var(--s5)}
.askform input[autocomplete="one-time-code"]{
  font-size:var(--t-h2); letter-spacing:0.4em; text-align:center; font-variant-numeric:tabular-nums;
}
/* A submit button that has to read as a link: "send it again" is one of two
   things this form does, and a second big button would argue with the first. */
.linkish{
  background:none; border:0; padding:0; font:inherit; font-size:inherit;
  color:var(--accent); font-weight:600; text-decoration:underline; cursor:pointer;
}
@media (max-width:520px){ .renewfacts{grid-template-columns:1fr; gap:var(--s3)} }

/* ---------- a renewal's already-known details ---------- */
.known{border:1px solid var(--line); border-radius:var(--r); margin-bottom:var(--s5); background:var(--bg-sunken)}
.known summary{
  display:flex; align-items:baseline; gap:var(--s3); flex-wrap:wrap;
  padding:var(--s4); cursor:pointer; list-style:none;
}
.known summary::-webkit-details-marker{display:none}
.known summary b{font-size:var(--t-small)}
.known summary span{flex:1; min-width:0; color:var(--fg-muted); font-size:var(--t-small)}
.known summary em{font-style:normal; color:var(--accent); font-weight:600; font-size:var(--t-small); text-decoration:underline}
.known[open] summary em::after{content:' ▴'}
.known:not([open]) summary em::after{content:' ▾'}
.known-body{padding:0 var(--s4) var(--s2); background:var(--surface); border-top:1px solid var(--line)}
.known-body .field:first-child{padding-top:var(--s4)}

/* ---------- the trial ---------- */
.tryline{margin-top:var(--s4); font-size:var(--t-small); color:var(--fg-muted)}
.tryline a{color:var(--accent); font-weight:600; text-decoration:underline}
.tryline b{font-size:var(--t-lead); color:var(--fg); font-weight:700}
.trialband{
  display:flex; align-items:center; justify-content:space-between; gap:var(--s5); flex-wrap:wrap;
  max-width:56rem; margin:var(--s6) auto 0;
  border:1px solid var(--line); border-radius:var(--r-lg);
  background:var(--surface); padding:var(--s5) var(--s6);
}
.trialband b{display:block; font-size:var(--t-lead)}
.trialband span{display:block; color:var(--fg-muted); font-size:var(--t-small); max-width:52ch}
.trialband .btn{flex:none}

.trialfacts{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--s5); max-width:64rem; margin-inline:auto}
.trialfacts li{border-top:2px solid var(--accent); padding-top:var(--s4)}
.trialfacts b{display:block; font-size:var(--t-lead); margin-bottom:var(--s2)}
.trialfacts span{display:block; color:var(--fg-muted); font-size:var(--t-small)}
@media (max-width:900px){ .trialfacts{grid-template-columns:repeat(2,1fr)} }
@media (max-width:520px){ .trialfacts{grid-template-columns:1fr} .trialband{flex-direction:column; align-items:stretch} .trialband .btn{width:100%} }

/* ---------- order protection ---------- */
.protect{background:var(--bg-sunken); border-block:1px solid var(--line)}

/* Two panels and an arrow. The left one is deliberately the plainer of the
   two — it is what the shop does today, and it should not look like an
   offer. */
.beforeafter{
  display:grid; grid-template-columns:1fr auto 1fr; gap:var(--s5); align-items:stretch;
  max-width:60rem; margin-inline:auto;
}
.ba-then,.ba-now{border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--s5); background:var(--surface)}
.ba-now{border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-wash)}
.ba-then b,.ba-now b{display:block; font-size:var(--t-small); margin-bottom:var(--s2)}
.ba-then b{color:var(--fg-faint)}
.ba-now b{color:var(--accent)}
.ba-then p,.ba-now p{color:var(--fg-muted); font-size:var(--t-small)}
.ba-arrow{align-self:center; font-size:26px; color:var(--accent-ghost)}

.protect-head{font-size:var(--t-lead); text-align:center; margin:var(--s8) 0 var(--s5)}
.outcomes{display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s5); max-width:64rem; margin-inline:auto}
.outcomes li{background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--s5)}
.outcomes .n{
  display:inline-grid; place-items:center; width:28px; height:28px; margin-bottom:var(--s3);
  border-radius:50%; background:var(--accent-wash); color:var(--accent); font-weight:700; font-size:15px;
}
.outcomes b{display:block; margin-bottom:var(--s1)}
.outcomes li > span:last-child{display:block; color:var(--fg-muted); font-size:var(--t-small)}

.protect-more{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--s5); max-width:64rem; margin:var(--s7) auto 0}
.protect-more b{display:block; font-size:var(--t-small); margin-bottom:var(--s1)}
.protect-more span{display:block; color:var(--fg-muted); font-size:15px}

@media (max-width:900px){
  .beforeafter{grid-template-columns:1fr}
  .ba-arrow{transform:rotate(90deg); justify-self:center}
  .outcomes{grid-template-columns:1fr}
  .protect-more{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:560px){ .protect-more{grid-template-columns:1fr} }

/* ---------- the desk, in a browser window ---------- */
/* A window frame rather than a bare screenshot. The desk is a web page, and
   the chrome says so in one glance — without it a wide table of orders reads
   as a spreadsheet, which is the thing this replaces. */
.deskwrap{background:var(--bg-sunken); border-block:1px solid var(--line)}
.window{
  margin:0; border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden;
  background:var(--surface); box-shadow:0 34px 64px -34px rgba(6,42,38,.4);
}
.window-bar{
  display:flex; align-items:center; gap:var(--s4);
  padding:var(--s3) var(--s4); background:var(--bg);
  border-bottom:1px solid var(--line);
}
.window-bar .dots{display:flex; gap:6px; flex:none}
.window-bar .dots i{width:10px; height:10px; border-radius:50%; background:var(--line-strong); opacity:.45}
.window-bar .url{
  font-size:15px; color:var(--fg-faint);
  background:var(--bg-sunken); border:1px solid var(--line);
  border-radius:var(--r-pill); padding:1px var(--s4);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.window-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch}
.window img{display:block; width:100%; height:auto}
/* Below this the table stops being readable at all, so it keeps its width and
   the reader swipes instead. The page itself never scrolls sideways. */
@media (max-width:820px){
  .window img{width:880px; max-width:none}
}

/* The one measured claim on the page. Given a box rather than a paragraph,
   because a number nobody notices might as well not have been measured. */
.deskspeed{
  max-width:44rem; margin:var(--s6) auto 0;
  padding:var(--s4) var(--s5);
  border:1px solid var(--accent-ghost); border-radius:var(--r-lg);
  background:var(--accent-wash); color:var(--accent-deep);
  font-size:var(--t-small); line-height:1.8; text-align:center;
}
.deskspeed .num{font-weight:700; white-space:nowrap}

/* The way into the demo, directly under the picture of the thing it opens.

   Centred and given room, because it is the one control on this page that
   costs the reader nothing — no login, no install, no call — and a page that
   buries that is arguing when it could be showing. */
.deskopen{
  display:flex; flex-direction:column; align-items:center; gap:var(--s3);
  margin:var(--s6) 0 var(--s7); text-align:center;
}
.deskopen p{font-size:var(--t-small); color:var(--fg-muted); margin:0}

/* The same promise, said in a line rather than a block. */
.demoline{
  margin:var(--s3) 0 0; font-size:var(--t-small); color:var(--fg-muted);
}
.demoline b{color:var(--fg)}
.demoline-mid{
  display:flex; align-items:center; justify-content:center;
  flex-wrap:wrap; gap:var(--s2) var(--s3);
  margin:var(--s6) auto 0; text-align:center;
}
.demoline-mid span{font-size:15px; color:var(--fg-faint)}

.deskpoints{display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s5) var(--s6); margin-top:var(--s7)}
.deskpoints li b{display:block; margin-bottom:var(--s1)}
.deskpoints li span{display:block; color:var(--fg-muted); font-size:var(--t-small)}
@media (max-width:900px){ .deskpoints{grid-template-columns:repeat(2,1fr)} }
@media (max-width:560px){ .deskpoints{grid-template-columns:1fr} }

/* ---------- roadmap ---------- */
/* A rail with a dot per item. The dot carries the stage, so how far along
   something is can be read down the column without stopping to read words. */
.roadmap{position:relative; max-width:56rem; padding-inline-start:var(--s6)}
.roadmap::before{
  content:""; position:absolute; inset-block:14px auto; height:calc(100% - 28px);
  inset-inline-start:6px; width:2px; background:var(--line);
}
.road{position:relative; padding-block:0 var(--s6)}
.road:last-child{padding-bottom:0}
.road-mark{
  position:absolute; inset-inline-start:calc(var(--s6) * -1 + 1px); top:8px;
  width:14px; height:14px; border-radius:50%;
  background:var(--surface); border:2px solid var(--line-strong);
}
.road[data-stage="building"] .road-mark{background:var(--accent); border-color:var(--accent)}
.road[data-stage="testing"] .road-mark{background:var(--warn); border-color:var(--warn)}
.road[data-stage="shipped"] .road-mark{background:var(--good); border-color:var(--good)}
.road-meta{display:flex; align-items:center; gap:var(--s3); flex-wrap:wrap; margin-bottom:var(--s1)}
.road-meta .stage{
  font-size:15px; font-weight:600; color:var(--accent);
  background:var(--accent-wash); border-radius:var(--r-pill); padding:0 var(--s3);
}
.road[data-stage="testing"] .stage{color:var(--warn); background:var(--warn-wash)}
.road[data-stage="shipped"] .stage{color:var(--good); background:var(--good-wash)}
.road[data-stage="idea"] .stage{color:var(--fg-muted); background:var(--bg-sunken)}
.road-meta .eta{font-size:15px; color:var(--fg-faint)}
.road h3{font-size:var(--t-lead)}
.road-lede{color:var(--fg-muted); font-size:var(--t-small); margin-top:var(--s1); max-width:62ch}
.roadempty{color:var(--fg-muted); max-width:56rem}
.roadnote{margin-top:var(--s7); max-width:56rem}
.roadnote a{color:var(--accent); text-decoration:underline}

/* ---------- the feature-request form ---------- */
.askform{
  max-width:38rem; margin-inline:auto;
  border:1px solid var(--line); border-radius:var(--r-lg);
  background:var(--surface); padding:var(--s6);
}
.askform label{display:block; margin-bottom:var(--s5)}
.askform label > span{display:block; font-size:var(--t-small); font-weight:600; margin-bottom:var(--s2)}
.askform label > span small{font-weight:400; color:var(--fg-faint)}
.askform input[type=text],.askform input[type=tel],.askform textarea{
  width:100%; padding:var(--s3) var(--s4);
  font:inherit; font-size:var(--t-body); color:var(--fg); background:var(--surface);
  border:1px solid var(--line-strong); border-radius:var(--r);
}
.askform input[type=text],.askform input[type=tel]{min-height:52px; padding-block:0}
.askform textarea{line-height:1.75; resize:vertical; min-height:9rem}
.askform .row2{display:grid; grid-template-columns:1fr 1fr; gap:var(--s4)}
.askform .btn{width:100%}
.askform .finehint{margin-top:var(--s3); text-align:center}
/* The three questions on /trial reuse the checkout's .field/.radio; the
   options sit in a row and wrap on a phone, each row still a 48px target. */
.askform .field{margin-bottom:var(--s5)}
.askform .radios{display:flex; flex-wrap:wrap; gap:0 var(--s5)}
.askform .radios .radio{flex:0 1 auto}
/* The answers under a trial request in the admin: one line of pills. */
.req .answers{display:flex; flex-wrap:wrap; gap:var(--s2); margin:var(--s2) 0 var(--s3)}
.askerror{
  background:var(--danger-wash); color:var(--danger); font-size:var(--t-small); font-weight:600;
  padding:var(--s4); border-radius:var(--r); margin-bottom:var(--s5);
}
.asked{
  max-width:38rem; margin:0 auto var(--s5); display:block;
  background:var(--good-wash); color:var(--good); border-radius:var(--r); padding:var(--s4);
}
.asked b{display:block; font-size:var(--t-lead)}
.asked span{font-size:var(--t-small)}
.asked a{text-decoration:underline}
/* Off-screen rather than display:none — a bot that skips hidden fields still
   fills this one, which is the whole point of it being here. */
.hp{position:absolute; inset-inline-start:-9999px; width:1px; height:1px; overflow:hidden}
@media (max-width:520px){ .askform .row2{grid-template-columns:1fr} }

/* ---------- admin: requests and the roadmap editor ---------- */
.adminhead{font-size:var(--t-lead); margin:var(--s8) 0 var(--s3)}
.adminhead:first-of-type{margin-top:0}
.adminhead small{font-size:var(--t-small); color:var(--fg-faint); font-weight:400}
.filters{display:flex; gap:var(--s2); flex-wrap:wrap; margin-bottom:var(--s5); font-size:var(--t-small)}
.filters a{
  border:1px solid var(--line-strong); border-radius:var(--r-pill);
  padding:var(--s1) var(--s4); color:var(--fg-muted);
}
.filters a[aria-current]{background:var(--fg); border-color:var(--fg); color:var(--bg); font-weight:600}
.reqlist{display:grid; gap:var(--s4); margin-bottom:var(--s5)}
.req{border:1px solid var(--line); border-inline-start:3px solid var(--line-strong); border-radius:var(--r); padding:var(--s5)}
.req[data-status="new"]{border-inline-start-color:var(--accent)}
.req[data-status="planned"]{border-inline-start-color:var(--good)}
.req[data-status="declined"]{border-inline-start-color:var(--line)}
.req[data-status="declined"] .body{color:var(--fg-faint)}
.req header{display:flex; align-items:baseline; gap:var(--s3); flex-wrap:wrap; margin-bottom:var(--s3); font-size:var(--t-small)}
.req header .site,.req header time{color:var(--fg-faint)}
.req header time{margin-inline-start:auto}
.req .body{font-size:var(--t-small); color:var(--fg-muted); margin-bottom:var(--s4); white-space:pre-line}
.reqform{display:inline-flex; align-items:center; gap:var(--s2); flex-wrap:wrap; margin-inline-end:var(--s3)}
.reqform select,.reqform input[type=text]{
  min-height:44px; padding:0 var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r);
  background:var(--surface); color:var(--fg);
}
.reqform input[type=text]{min-width:14rem}
.reqform .btn{min-height:44px}
.reqform .bin{color:var(--danger); border-color:var(--line)}
.reqform .bin:hover{border-color:var(--danger)}
.roadedit input[type=text],.roadedit input[type=number],.roadedit select{
  min-height:44px; padding:0 var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line-strong); border-radius:var(--r);
  background:var(--surface); color:var(--fg);
}
.roadedit input[type=number]{width:5rem}
.roadedit td:nth-child(2) input{min-width:16rem}
.roadedit td:nth-child(3) input{min-width:24rem}
.roadedit td.tick{text-align:center}
.roadedit input[type=checkbox]{width:20px; height:20px; accent-color:var(--accent)}

@media (prefers-reduced-motion:reduce){
  *{animation:none !important; transition:none !important}
}

/* ---------- the team setup course (/admin/course) ---------- */
/* Reuses the admin surface tokens. Progress is the viewer's own (the ring and
   bar), video links are shared (the play button and the edit form). */
.course .coursehead{display:flex; align-items:flex-start; justify-content:space-between; gap:var(--s5); flex-wrap:wrap; margin-bottom:var(--s4)}
.courseprog{display:flex; align-items:center; gap:var(--s3); flex:none}
.courseprog .ring{
  width:60px; height:60px; border-radius:50%; display:grid; place-items:center; flex:none;
  background:var(--accent-wash); color:var(--accent); font-weight:700; line-height:1;
  border:2px solid var(--accent);
}
.courseprog .ring b{font-size:var(--t-lead)}
.courseprog .ring span{font-size:12px}
.courseprog .progmeta .num{font-size:var(--t-lead); font-weight:700; font-variant-numeric:tabular-nums; display:block}
.courseprog .progmeta .num b{color:var(--accent)}
.courseprog .progmeta .sub{font-size:var(--t-small); color:var(--fg-muted)}

.coursebar{height:8px; border-radius:var(--r-pill); background:var(--bg-sunken);
  border:1px solid var(--line); overflow:hidden; margin-bottom:var(--s6)}
.coursebar span{display:block; height:100%; background:var(--accent); border-radius:inherit;
  transition:width .45s cubic-bezier(.2,.7,.2,1)}

.cstep{border:1px solid var(--line); border-radius:var(--r-lg); background:var(--bg);
  margin-bottom:var(--s4); overflow:hidden}
.cstep.all{border-color:var(--good)}
.cshead{display:flex; align-items:center; gap:var(--s4); width:100%; text-align:start;
  background:none; border:0; padding:var(--s4) var(--s5); cursor:pointer; color:inherit; font:inherit}
.cshead:hover{background:var(--bg-sunken)}
.cnum{font-weight:700; font-variant-numeric:tabular-nums; width:40px; height:40px; flex:none;
  border-radius:var(--r); display:grid; place-items:center; font-size:15px;
  background:var(--accent-wash); color:var(--accent); border:1px solid #bfdedb}
.cstep.all .cnum{background:var(--good-wash); color:var(--good); border-color:var(--good)}
.cstitle{flex:1; min-width:0}
.cstitle b{font-size:var(--t-lead); display:block}
.cstitle small{color:var(--fg-muted); font-size:var(--t-small)}
.ccount{font-variant-numeric:tabular-nums; font-weight:700; font-size:var(--t-small); color:var(--fg-muted);
  background:var(--bg-sunken); border:1px solid var(--line); border-radius:var(--r-pill); padding:3px 12px; white-space:nowrap}
.cstep.all .ccount{color:var(--good); background:var(--good-wash); border-color:var(--good)}
.cchev{color:var(--fg-muted); flex:none; transition:transform .2s ease}
.cchev svg{width:20px; height:20px; display:block}
.cstep.collapsed .cchev{transform:rotate(-90deg)}
.cstep.collapsed .csbody{display:none}

.ctopic{display:flex; gap:var(--s4); padding:var(--s4) var(--s5); border-top:1px solid var(--line)}
.ctopic.done{background:var(--good-wash)}
.cstate{flex:none; margin-top:2px; width:26px; height:26px; display:grid; place-items:center}
.cstate .dot{width:22px; height:22px; border-radius:50%; border:2px solid var(--line);
  background:var(--bg); display:grid; place-items:center; color:#fff}
.cstate .dot.on{background:var(--good); border-color:var(--good)}
.cstate .dot svg{width:12px; height:12px}
.ctmain{flex:1; min-width:0}
.ctrow{display:flex; align-items:baseline; gap:var(--s2); flex-wrap:wrap}
.ctnum{font-weight:700; font-variant-numeric:tabular-nums; font-size:var(--t-small); color:var(--accent); flex:none}
.ctopic.done .ctnum, .cstep.all .ctnum{color:var(--good)}
.cttitle{font-weight:700; font-size:16px; color:var(--fg)}
.ctopic.done .cttitle{text-decoration:line-through; text-decoration-color:var(--good); color:var(--fg-muted)}
.ctvid{margin-inline-start:auto; display:inline-flex; align-items:center; gap:var(--s3); flex:none}
.vbtn{display:inline-flex; align-items:center; gap:6px; text-decoration:none; white-space:nowrap;
  font-weight:600; font-size:var(--t-small); color:var(--accent-ink); background:var(--accent);
  border:1px solid var(--accent); border-radius:var(--r-pill); padding:5px 14px}
.vbtn:hover{filter:brightness(1.07)}
.vbtn.hide{display:none}
.vbtn svg{width:13px; height:13px}
.linkbtn{appearance:none; background:none; border:0; cursor:pointer; padding:0;
  font:inherit; font-size:var(--t-small); font-weight:600; color:var(--fg-muted); text-decoration:underline; text-underline-offset:3px}
.linkbtn:hover{color:var(--accent)}
.ctwhat{color:var(--fg-muted); font-size:var(--t-small); margin:2px 0 0}
/* Where the recording happens — computer, phone, or both. A chip beside the
   title, because it decides which device the recorder picks up first. */
.cwhere{font-size:12px; font-weight:600; color:var(--fg-muted); border:1px solid var(--line);
  border-radius:var(--r-pill); padding:1px 9px; white-space:nowrap; flex:none; align-self:center}
/* The second state of a made video: is it on the public videos page yet?
   Amber until it is, green once Videos::LIST carries its id. */
.csite{font-size:12px; font-weight:700; white-space:nowrap; border-radius:var(--r-pill); padding:3px 10px;
  color:var(--warn); background:var(--warn-wash); border:1px solid #f1d78b}
.csite.on{color:var(--good); background:var(--good-wash); border-color:#a7dcb5}
.csite.hide{display:none}
/* The queue for whoever puts videos on the site. */
.cpending{background:var(--warn-wash); border:1px solid #f1d78b; border-radius:var(--r-lg);
  padding:var(--s4) var(--s5); margin-bottom:var(--s5)}
.cpending > b{color:var(--warn)}
.cpending ul{list-style:none; margin:var(--s2) 0 0; padding:0; display:grid; gap:8px}
.cpending li{display:flex; flex-wrap:wrap; gap:4px var(--s3); align-items:baseline; font-size:var(--t-small); line-height:1.6}
.cpending li span{font-weight:600; color:var(--fg)}
.cpending li a{color:var(--accent); text-decoration:underline; text-underline-offset:3px; word-break:break-all}
.cpending li small{color:var(--fg-muted)}
.cpending p{margin:var(--s3) 0 0; font-size:var(--t-small); color:var(--fg-muted)}

.linkedit{display:flex; gap:var(--s2); align-items:center; margin-top:var(--s3); flex-wrap:wrap}
.linkedit[hidden]{display:none}
.linkinput{flex:1; min-width:220px; padding:8px var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg); color:var(--fg)}
.linkinput:focus-visible{outline:2px solid var(--accent); outline-offset:1px; border-color:var(--accent)}
.linkedit .linksave{padding:8px 16px}
.linkcancel{appearance:none; background:none; border:0; cursor:pointer; font:inherit;
  font-size:var(--t-small); color:var(--fg-muted)}
.linkcancel:hover{color:var(--fg)}

.cguide{margin-top:var(--s3); background:var(--bg-sunken); border:1px solid var(--line); border-radius:var(--r); padding:var(--s3) var(--s4)}
.cglabel{font-size:12px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--warn)}
.cguide ul{list-style:none; margin:var(--s2) 0 0; padding:0; display:grid; gap:6px}
.cguide li{position:relative; padding-inline-start:16px; font-size:var(--t-small); color:var(--fg); line-height:1.7}
.cguide li::before{content:""; position:absolute; inset-inline-start:3px; top:11px; width:5px; height:5px; border-radius:50%; background:var(--warn)}

@media (max-width:640px){
  .cshead{padding:var(--s3) var(--s4); gap:var(--s3)}
  .ctopic{padding:var(--s3) var(--s4); gap:var(--s3)}
  .ctvid{margin-inline-start:0; width:100%}
}

/* ---------- one-tap WhatsApp on a trial request ---------- */
/* Opens WhatsApp with the message ready; the human presses send. Green is the
   one place WhatsApp's own colour earns its keep — it says which app opens. */
/* WhatsApp's green, with dark text rather than white.
   White on #25d366 measures 1.98:1 — nowhere near the 4.5:1 a 15px semibold
   label needs, and it had been that way on the leads and trials pages from the
   start. Darkening the green instead would have cost the recognition the
   colour is there to buy; darkening the text keeps it and measures 8.93:1,
   6.51:1 on hover. */
.wabtn{display:inline-flex; align-items:center; gap:var(--s2); text-decoration:none; white-space:nowrap;
  font-weight:600; font-size:var(--t-small); color:var(--fg); background:#25d366;
  border:1px solid #1eb457; border-radius:var(--r-pill); padding:var(--s1) var(--s3)}
.wabtn:hover{background:#1eb457}
/* In the leads table the button sits under the number, not beside it — the
   name, the number and the message are three separate things to reach for. */
.adminwrap td.leadwho{display:flex; flex-direction:column; align-items:flex-start; gap:var(--s1)}
.wabtn:focus-visible{outline:2px solid var(--fg); outline-offset:2px}
.wabtn svg{width:15px; height:15px}
.watmpl{border:1px solid var(--line); border-radius:var(--r-lg); background:var(--bg-sunken);
  margin:0 0 var(--s5); overflow:hidden}
.watmpl summary{cursor:pointer; padding:var(--s3) var(--s4); font-weight:600; font-size:var(--t-small);
  display:flex; align-items:center; gap:var(--s2); color:var(--fg); list-style:none}
.watmpl summary::-webkit-details-marker{display:none}
.watmpl summary svg{width:16px; height:16px; color:#25d366; flex:none}
.watmpl summary:hover{color:var(--accent)}
.watmpl form{padding:0 var(--s4) var(--s4); border-top:1px solid var(--line)}
.watmpl .watext{width:100%; padding:var(--s3); font:inherit; font-size:var(--t-small); line-height:1.7;
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg); color:var(--fg);
  margin:var(--s3) 0; resize:vertical}
.watmpl .watext:focus-visible{outline:2px solid var(--accent); outline-offset:1px; border-color:var(--accent)}

/* ---------- correcting a trial request's details ---------- */
.trialedit{margin-top:var(--s3)}
.trialedit summary{cursor:pointer; font-size:var(--t-small); font-weight:600; color:var(--fg-muted);
  list-style:none; display:inline-flex; align-items:center; gap:6px; width:fit-content}
.trialedit summary::-webkit-details-marker{display:none}
.trialedit summary::before{content:"\270E"; font-size:13px}
.trialedit summary:hover{color:var(--accent)}
.trialedit form{margin-top:var(--s3); padding:var(--s4); background:var(--bg-sunken);
  border:1px solid var(--line); border-radius:var(--r)}
.trialedit .editrow{display:flex; gap:var(--s3); flex-wrap:wrap; margin-bottom:var(--s3)}
.trialedit .editrow label{flex:1; min-width:160px; display:flex; flex-direction:column; gap:4px;
  font-size:13px; font-weight:600; color:var(--fg-muted)}
.trialedit .editrow input{padding:8px var(--s3); font:inherit; font-size:var(--t-small);
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg); color:var(--fg); font-weight:400}
.trialedit .editrow input:focus-visible{outline:2px solid var(--accent); outline-offset:1px; border-color:var(--accent)}
.trialedit .edithint{display:inline-block; margin-inline-start:var(--s3); font-size:13px; color:var(--fg-muted)}

/* ---------- the production-standards note on the tutorial board ---------- */
.course .cnote{background:var(--accent-wash); border:1px solid #bfdedb; border-radius:var(--r-lg);
  padding:var(--s4) var(--s5); margin-bottom:var(--s6); font-size:var(--t-small)}
.course .cnote b{color:var(--fg)}
.course .cnote ul{list-style:none; margin:var(--s2) 0 0; padding:0; display:grid; gap:6px}
.course .cnote li{position:relative; padding-inline-start:18px; color:var(--fg); line-height:1.7}
.course .cnote li::before{content:""; position:absolute; inset-inline-start:3px; top:11px; width:6px; height:6px;
  border-radius:50%; background:var(--accent)}

/* ---------- discount code on the order form ---------- */
/* Closed unless in use: a code is something a few people are given, and an open
   box asking for one makes everybody else feel they are missing a deal. */
.couponbox{margin-bottom:var(--s4)}
.couponbox summary{cursor:pointer; font-size:var(--t-small); font-weight:600; color:var(--fg-muted);
  list-style:none; width:fit-content}
.couponbox summary::-webkit-details-marker{display:none}
.couponbox summary::before{content:'+ '; color:var(--accent)}
.couponbox[open] summary::before{content:'– '}
.couponbox summary:hover{color:var(--accent)}
.couponbox .field{margin-top:var(--s3)}
.couponbox input{text-transform:uppercase}

/* the plan / billing allowlists on the coupon form */
.checkrow{display:flex; flex-wrap:wrap; gap:var(--s2) var(--s4); padding-top:6px}
.checkrow label{display:inline-flex; align-items:center; gap:6px; font-weight:500; font-size:var(--t-small)}
.checkrow input{width:18px; height:18px; accent-color:var(--accent); margin:0}
.couponform .row2{display:grid; grid-template-columns:1fr 1fr; gap:var(--s4)}
@media (max-width:640px){ .couponform .row2{grid-template-columns:1fr} }

/* the coupon box's answer: a good one is not an error, so it is not red */
.okhint{display:block; font-size:14px; color:var(--good); font-weight:600; margin-top:6px}
/* a plan whose price a code has cut */
.pp-price.cut{color:var(--good)}

/* the price a discount code replaced, struck through on the plan picker —
   same treatment the early-bird cards already use */
.pp-price s.was{font-size:0.85em; color:var(--fg-faint); text-decoration-thickness:2px; font-weight:400}

/* ---------- what you are about to pay ---------- */
/* Above the button, because the number a person checks last is the one they are
   about to hand over. */
.paysum{border:1px solid var(--line); border-radius:var(--r); background:var(--bg-sunken);
  padding:var(--s4); margin-bottom:var(--s4)}
.paysum-row{display:flex; align-items:baseline; justify-content:space-between; gap:var(--s4);
  font-size:var(--t-small); padding:2px 0}
.paysum-row b{font-size:var(--t-lead); font-weight:700}
.paysum-row s.was{color:var(--fg-faint); font-weight:400; margin-inline-end:6px; text-decoration-thickness:2px}
.paysum-row.cut{color:var(--good)}
.paysum-row.cut b{font-size:var(--t-small); font-weight:700}
.paysum-row[hidden]{display:none}
.paysum-note{margin:var(--s2) 0 0; padding-top:var(--s2); border-top:1px solid var(--line);
  font-size:14px; color:var(--fg-muted); line-height:1.7}
.paysum-note[hidden]{display:none}


/* ---------------------------------------------------------------- guides
   A written setup guide: numbered steps, the plugin's own field names, and
   the tables that go with them. Named .gd- so nothing here can reach the
   marketing pages, which use .step and .steps for something else. */

.gd{max-width:780px}
.gd-lede{font-size:var(--t-lead); color:var(--fg-muted); margin:0 0 var(--s5)}
.gd-need{margin:0 0 var(--s7); color:var(--fg-muted)}
.gd > p{margin:0 0 var(--s5)}

.gd-part{display:flex; align-items:baseline; gap:var(--s4); flex-wrap:wrap;
  margin:var(--s9) 0 var(--s6); padding-bottom:var(--s3); border-bottom:2px solid var(--fg)}
.gd-part h2{margin:0; font-size:var(--t-h2)}
.gd-part span{font-size:var(--t-small); font-weight:600; color:var(--fg-faint); letter-spacing:.04em}

.gd-steps{list-style:none; margin:0 0 var(--s7); padding:0; display:grid; gap:var(--s6)}
.gd-steps > li{display:grid; grid-template-columns:56px minmax(0,1fr); gap:var(--s5); align-items:start}
/* A grid item defaults to min-width:auto, so the wide table inside would
   push the whole page sideways instead of scrolling in its own box. */
.gd-steps > li > div{min-width:0}
.gd-steps .n{font-size:38px; font-weight:700; line-height:1; color:var(--accent-ghost); text-align:end}
.gd-steps h3{margin:0 0 var(--s3); font-size:20px}
.gd-steps p{margin:0 0 var(--s3); color:var(--fg-muted)}
.gd-steps p:last-child{margin-bottom:0}
.gd-aside{font-weight:400; color:var(--fg-faint)}

.gd-note{border-inline-start:3px solid var(--accent); background:var(--accent-wash);
  padding:var(--s3) var(--s4); border-radius:0 var(--r) var(--r) 0; font-size:16px}
.gd-warn{border-inline-start-color:var(--warn); background:var(--warn-wash)}

.gd-fields{border:1px solid var(--line); border-radius:var(--r); background:var(--surface);
  margin:0 0 var(--s4); overflow:hidden}
.gd-fields > div{display:grid; grid-template-columns:minmax(0,180px) minmax(0,1fr); gap:var(--s5);
  padding:var(--s3) var(--s4); border-top:1px solid var(--line)}
.gd-fields > div:first-child{border-top:0}
.gd-fields span{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:15px; font-weight:600}
.gd-fields p{margin:0; font-size:16px; color:var(--fg-muted)}

.gd-scroll{overflow-x:auto; border:1px solid var(--line); border-radius:var(--r);
  background:var(--surface); margin:0 0 var(--s5)}
.gd-table{border-collapse:collapse; width:100%; min-width:520px; font-size:16px}
.gd-table th,.gd-table td{text-align:start; padding:var(--s3) var(--s4);
  border-top:1px solid var(--line); vertical-align:top}
.gd-table thead th{border-top:0; background:var(--bg-sunken); font-size:var(--t-small);
  color:var(--fg-muted); font-weight:600; white-space:nowrap}
.gd-table small{display:block; color:var(--fg-faint); font-size:var(--t-small)}

.gd-pill{display:inline-block; font-size:14px; font-weight:600; padding:1px 9px;
  border-radius:var(--r-pill); white-space:nowrap;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.gd-ok{background:var(--good-wash); color:var(--good)}
.gd-hold{background:var(--accent-wash); color:var(--accent-deep)}
.gd-drop{background:var(--warn-wash); color:var(--warn)}
.gd-bad{background:var(--danger-wash); color:var(--danger)}

.gd-miss{list-style:none; margin:0; padding:0; display:grid; gap:var(--s4)}
.gd-miss li{padding-bottom:var(--s4); border-bottom:1px solid var(--line); color:var(--fg-muted)}
.gd-miss li:last-child{border-bottom:0; padding-bottom:0}

@media (max-width:640px){
  .gd-steps > li{grid-template-columns:minmax(0,1fr); gap:var(--s2)}
  .gd-steps .n{text-align:start; font-size:30px}
  .gd-fields > div{grid-template-columns:1fr; gap:var(--s1)}
}
