/* OTP HeroSMS Connect — buy-flow styles ([otp_buy] + OTP Buy template).
   Same design family as assets/otp-home.css: light marketplace theme,
   primary blue #2563EB, navy ink #0F1B3D, pale-blue tints, white cards
   with 12–18px radii and #E2E8F2 borders. Every selector is prefixed
   otp-buy- / otp-herosms- so nothing leaks into (or depends on) the
   active theme. Plain width:100% + max-width centring throughout —
   no viewport-width breakouts, no negative margins (see the v1.1.1
   note in otp-home.css for why).

   The ids styled here (#otp-service, #otp-price, #otp-active, …) are
   the hooks assets/otp-buy.js drives: it writes ONE text string into
   #otp-price, toggles [hidden] on #otp-active / #otp-code-wrap, and
   sets inline colours on #otp-msg. */

.otp-herosms {
    --otp-blue: #2563EB;
    --otp-blue-dark: #1D4ED8;
    --otp-ink: #0F1B3D;
    --otp-gray: #4B5563;
    --otp-tint: #F2F6FE;
    --otp-tint-2: #EAF1FD;
    --otp-border: #E2E8F2;
    --otp-input-border: #C7D5F2;
    --otp-green: #22C55E;
    --otp-green-dark: #15803D;
    --otp-green-btn: #16A34A;
    --otp-red: #B3261E;
    --otp-red-border: #E7AAAA;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    color: var(--otp-gray);
    font-size: 16px;
    line-height: 1.55;
    width: 100%;
}
.otp-herosms *, .otp-herosms *::before, .otp-herosms *::after { box-sizing: border-box; }
.otp-herosms h1, .otp-herosms p { margin: 0; }
.otp-herosms button, .otp-herosms select, .otp-herosms input { font: inherit; }
/* The JS toggles [hidden] on #otp-active / #otp-code-wrap; display
   rules below must never resurrect them. */
.otp-herosms [hidden] { display: none !important; }

.otp-buy-wrap {
    max-width: 1200px;
    margin: 0 auto;
    padding: 28px 24px 8px;
}

/* ---------- hero band ---------- */
.otp-buy-hero {
    background: linear-gradient(180deg, var(--otp-tint) 0%, var(--otp-tint-2) 100%);
    border: 1px solid var(--otp-border);
    border-radius: 18px;
    padding: 30px 34px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
}
.otp-buy-title {
    color: var(--otp-ink);
    font-size: 31px;
    font-weight: 800;
    letter-spacing: -0.5px;
    line-height: 1.12;
}
.otp-buy-sub { margin-top: 8px; font-size: 15.5px; max-width: 560px; }
.otp-buy-wallet-chip {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    background: #fff;
    border: 1px solid var(--otp-border);
    border-radius: 999px;
    padding: 9px 18px;
    box-shadow: 0 4px 14px rgba(15, 27, 61, 0.05);
    white-space: nowrap;
    /* v1.3.0: the chip is a link to /wallet/ on the buy page. */
    text-decoration: none;
    color: inherit;
    transition: box-shadow .15s ease, border-color .15s ease;
}
a.otp-buy-wallet-chip:hover { border-color: var(--otp-input-border); box-shadow: 0 6px 18px rgba(15, 27, 61, 0.09); }
.otp-buy-wallet-label { font-size: 13px; font-weight: 600; color: var(--otp-gray); }
.otp-buy-wallet-chip strong { color: var(--otp-ink); font-size: 17px; font-weight: 800; }
.otp-buy-wallet-add {
    font-size: 13px;
    font-weight: 700;
    color: var(--otp-blue);
    border-left: 1px solid var(--otp-border);
    padding-left: 10px;
}

/* Insufficient-balance hint under the Buy button (v1.3.0): shown by
   otp-buy.js only when logged in + price quoted + balance below it.
   [hidden] is force-guarded at the top of this file. */
.otp-buy-addfunds {
    margin: 12px 0 0;
    font-size: 14.5px;
    color: var(--otp-red);
}
.otp-buy-addfunds a { color: var(--otp-blue); font-weight: 700; text-decoration: none; }
.otp-buy-addfunds a:hover { text-decoration: underline; }

/* ---------- the card + steps ---------- */
.otp-buy-card {
    max-width: 860px;
    margin: 26px auto 0;
    background: #fff;
    border: 1px solid var(--otp-border);
    border-radius: 16px;
    box-shadow: 0 12px 32px rgba(15, 27, 61, 0.07);
    padding: 30px 32px 32px;
}
.otp-herosms-step { margin-bottom: 22px; }
.otp-herosms-step label,
.otp-buy-step-label {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--otp-ink);
    font-size: 16px;
    font-weight: 700;
    margin-bottom: 9px;
}
.otp-buy-badge {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--otp-blue);
    color: #fff;
    font-size: 13.5px;
    font-weight: 700;
}
.otp-herosms-step select {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--otp-input-border);
    border-radius: 10px;
    background: #fff;
    color: var(--otp-ink);
    font-size: 15.5px;
    cursor: pointer;
}
.otp-herosms-step select:focus {
    outline: none;
    border-color: var(--otp-blue);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}
.otp-herosms-step select:disabled {
    background: var(--otp-tint);
    color: #94A3B8;
    cursor: not-allowed;
}

/* Popular-service chips + service search (v1.2.2). Both are
   progressive enhancement driven by otp-buy.js: a chip selects its
   service in #otp-service by catalogue code (data-service), and the
   search rebuilds the dropdown from the captured full list. Markup
   lives in Step 1 of render_buy_flow(). */
.otp-buy-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}
.otp-buy-chip {
    flex: 1 1 calc(25% - 6px);
    min-width: 0;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 8px 10px;
    background: #fff;
    border: 1.5px solid var(--otp-border);
    border-radius: 12px;
    color: var(--otp-ink);
    font-size: 14.5px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.otp-buy-chip:hover { border-color: var(--otp-input-border); background: var(--otp-tint); }
.otp-buy-chip:focus-visible {
    outline: none;
    border-color: var(--otp-blue);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}
.otp-buy-chip-active {
    border-color: var(--otp-blue);
    background: var(--otp-tint-2);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.14);
}
.otp-buy-chip-icon { display: inline-flex; flex: 0 0 auto; width: 20px; height: 20px; }
.otp-buy-chip-icon svg { display: block; width: 100%; height: 100%; }
.otp-buy-chip-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.otp-buy-search { position: relative; margin-bottom: 12px; }
.otp-buy-search-icon {
    position: absolute;
    left: 13px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    width: 18px;
    height: 18px;
    color: #7C8DB0;
    pointer-events: none;
}
.otp-buy-search-icon svg { display: block; width: 100%; height: 100%; }
.otp-buy-search input {
    width: 100%;
    padding: 12px 14px 12px 42px;
    border: 1px solid var(--otp-input-border);
    border-radius: 10px;
    background: #fff;
    color: var(--otp-ink);
    font-size: 15.5px;
}
.otp-buy-search input::placeholder { color: #94A3B8; }
.otp-buy-search input:focus {
    outline: none;
    border-color: var(--otp-blue);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}

/* Price panel: the JS writes "$1.08 · 12,345 in stock" (or a status
   message) as one string into #otp-price. */
.otp-herosms-price {
    background: var(--otp-tint);
    border: 1px solid var(--otp-border);
    border-radius: 12px;
    padding: 15px 18px;
    color: var(--otp-ink);
    font-size: 21px;
    font-weight: 800;
    line-height: 1.3;
}

/* ---------- buttons ---------- */
.otp-herosms-btn {
    display: inline-block;
    padding: 12px 24px;
    border: 1.5px solid var(--otp-blue);
    border-radius: 10px;
    background: var(--otp-blue);
    color: #fff;
    font-size: 15.5px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.otp-herosms-btn:hover:not(:disabled) { background: var(--otp-blue-dark); border-color: var(--otp-blue-dark); }
.otp-herosms-btn:disabled {
    background: #C3CFE3;
    border-color: #C3CFE3;
    color: #5B6B84;
    cursor: not-allowed;
}
/* The main buy action: full-width and taller than the default button. */
.otp-buy-btn-main {
    width: 100%;
    padding: 15px 24px;
    font-size: 16.5px;
}
/* Finish = solid green. */
.otp-herosms-btn-alt { background: var(--otp-green-btn); border-color: var(--otp-green-btn); }
.otp-herosms-btn-alt:hover:not(:disabled) { background: var(--otp-green-dark); border-color: var(--otp-green-dark); }
/* Cancel = outlined red. */
.otp-herosms-btn-danger {
    background: #fff;
    border-color: var(--otp-red-border);
    color: var(--otp-red);
}
.otp-herosms-btn-danger:hover:not(:disabled) { background: #FEF2F2; border-color: var(--otp-red); color: var(--otp-red); }
.otp-herosms-btn-danger:disabled { background: #fff; }

/* ---------- login notice (logged-out state) ---------- */
.otp-buy-login-notice {
    background: var(--otp-tint-2);
    border: 1px solid var(--otp-border);
    border-radius: 12px;
    padding: 20px 22px;
    margin-bottom: 16px;
}
.otp-buy-login-notice p { color: var(--otp-ink); font-size: 15px; }
.otp-buy-login-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.otp-buy-login-btn {
    display: inline-block;
    background: var(--otp-blue);
    border: 1.5px solid var(--otp-blue);
    color: #fff;
    font-weight: 600;
    font-size: 14.5px;
    padding: 10px 26px;
    border-radius: 10px;
    text-decoration: none;
}
.otp-buy-login-btn:hover { background: var(--otp-blue-dark); border-color: var(--otp-blue-dark); color: #fff; }
.otp-buy-login-btn-outline { background: transparent; color: var(--otp-blue); }
.otp-buy-login-btn-outline:hover { background: #fff; color: var(--otp-blue); }

/* Status line under the buy button. The JS sets its text colour
   inline (red for errors, green for confirmations); the layout
   properties live here. */
.otp-herosms .otp-herosms-msg {
    min-height: 1.4em;
    margin: 14px 0 0;
    font-size: 14.5px;
    font-weight: 600;
}

/* ---------- active activation ---------- */
.otp-herosms-active {
    margin-top: 24px;
    padding: 24px;
    border: 1px solid var(--otp-border);
    border-radius: 14px;
    background: var(--otp-tint);
}
.otp-buy-active-label {
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--otp-gray);
}
.otp-herosms-phone {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 30px;
    font-weight: 700;
    letter-spacing: 1px;
    color: var(--otp-ink);
    margin: 4px 0 10px;
    user-select: all;
    overflow-wrap: anywhere;
}
/* Waiting status with a pulsing dot. The dot is a ::before, so the
   JS rewriting the status text never disturbs it; :has() stops the
   pulse once a terminal state disables the cancel button (and turns
   the dot green once the code is on screen). Browsers without :has
   simply keep the gentle pulse — graceful, not broken. */
.otp-herosms-status {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--otp-ink);
    font-weight: 600;
    font-size: 15.5px;
    margin: 4px 0 8px;
}
.otp-herosms-status::before {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--otp-blue);
    animation: otp-buy-pulse 1.6s ease-in-out infinite;
}
@keyframes otp-buy-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.35); }
    50% { box-shadow: 0 0 0 6px rgba(37, 99, 235, 0); }
}
.otp-herosms-active:has(#otp-cancel-btn:disabled) .otp-herosms-status::before { animation: none; }
.otp-herosms-active:has(#otp-code-wrap:not([hidden])) .otp-herosms-status::before {
    animation: none;
    background: var(--otp-green);
}
.otp-buy-wait-hint { font-size: 13.5px; margin-bottom: 6px; }
#otp-code-wrap { margin-top: 16px; }
.otp-herosms-code {
    display: inline-block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 32px;
    font-weight: 800;
    letter-spacing: 4px;
    color: var(--otp-green-dark);
    background: rgba(34, 197, 94, 0.09);
    border: 1.5px solid var(--otp-green);
    border-radius: 12px;
    padding: 10px 22px;
    margin-top: 6px;
    user-select: all;
}
.otp-buy-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
.otp-herosms-note { font-size: 13px; margin-top: 14px; }

/* ---------- responsive ---------- */
@media (max-width: 640px) {
    .otp-buy-wrap { padding: 18px 16px 4px; }
    .otp-buy-hero { padding: 24px 22px; flex-direction: column; align-items: flex-start; }
    .otp-buy-title { font-size: 26px; }
    .otp-buy-card { padding: 22px 18px 24px; margin-top: 20px; }
    .otp-herosms-price { font-size: 19px; padding: 13px 15px; }
    .otp-herosms-active { padding: 18px 16px; }
    .otp-herosms-phone { font-size: 24px; }
    .otp-herosms-code { font-size: 27px; letter-spacing: 3px; padding: 8px 16px; }
    .otp-buy-actions .otp-herosms-btn { flex: 1 1 100%; text-align: center; }
    .otp-buy-login-actions .otp-buy-login-btn { flex: 1 1 auto; text-align: center; }
    /* Chips: 3 per row on small tablets/phones. */
    .otp-buy-chip { flex-basis: calc(33.333% - 6px); }
}

@media (max-width: 420px) {
    /* Chips: 2 per row on narrow phones. */
    .otp-buy-chip { flex-basis: calc(50% - 4px); }
}

/* ---------- privacy policy page (v1.6.2) ----------
   templates/page-otp-privacy.php prints the designated policy
   page's own authored content inside one card; these rules only
   style that card and give the authored markup (h2 / p / ul / a)
   the site's prose rhythm — the .otp-herosms resets above zero
   the margins, so the content rules restore them. */
.otp-privacy-card {
    max-width: 860px;
    margin: 26px auto 0;
    background: #fff;
    border: 1px solid var(--otp-border);
    border-radius: 16px;
    box-shadow: 0 12px 32px rgba(15, 27, 61, 0.07);
    padding: 34px 38px 38px;
}
.otp-privacy-title {
    color: var(--otp-ink);
    font-size: 29px;
    font-weight: 800;
    letter-spacing: -0.5px;
    line-height: 1.15;
    margin: 0 0 6px;
}
.otp-privacy-content { font-size: 15.5px; }
.otp-privacy-content h2 {
    color: var(--otp-ink);
    font-size: 20px;
    font-weight: 700;
    line-height: 1.3;
    margin: 26px 0 8px;
}
.otp-privacy-content h2:first-child { margin-top: 10px; }
.otp-privacy-content h3 {
    color: var(--otp-ink);
    font-size: 16.5px;
    font-weight: 700;
    margin: 20px 0 6px;
}
.otp-privacy-content p { margin: 0 0 12px; }
.otp-privacy-content ul,
.otp-privacy-content ol { margin: 0 0 12px; padding-left: 22px; }
.otp-privacy-content li { margin-bottom: 5px; }
.otp-privacy-content a { color: var(--otp-blue); font-weight: 600; text-decoration: none; }
.otp-privacy-content a:hover { text-decoration: underline; }

@media (max-width: 640px) {
    .otp-privacy-card { padding: 24px 20px 26px; margin-top: 20px; }
    .otp-privacy-title { font-size: 24px; }
}

/* ---------- api access page (v1.7.0) ----------
   render_api_page() prints the key card + docs card inside the
   buy-page wrap; the cards reuse .otp-buy-card, these rules only
   add the key row, the examples block and the docs rhythm. The
   action/error tables reuse .otp-prices-table from otp-home.css. */
.otp-api-card { max-width: 860px; margin-left: auto; margin-right: auto; }
.otp-api-notice { max-width: 860px; margin: 20px auto 0; }
.otp-api-endpoint { margin: 0 0 12px; }
.otp-api-endpoint code,
.otp-api-examples code { word-break: break-all; }
.otp-api-keyrow { display: flex; gap: 10px; align-items: stretch; margin: 4px 0 10px; }
.otp-api-key {
    flex: 1 1 auto;
    min-width: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 14px;
    padding: 10px 12px;
    border: 1px solid var(--otp-border);
    border-radius: 10px;
    background: #f6f9ff;
    color: var(--otp-ink);
}
.otp-api-keystate { margin: 0 0 14px; }
.otp-api-keyactions { display: flex; flex-wrap: wrap; gap: 10px; }
.otp-api-keyactions form { margin: 0; }
.otp-api-h3 { color: var(--otp-ink); font-size: 16.5px; font-weight: 700; margin: 22px 0 8px; }
.otp-api-examples { display: grid; gap: 8px; }
.otp-api-examples code {
    display: block;
    font-size: 12.5px;
    background: #0f1b33;
    color: #cfe3ff;
    border-radius: 10px;
    padding: 10px 12px;
    overflow-x: auto;
    white-space: nowrap;
}

@media (max-width: 640px) {
    .otp-api-keyrow { flex-direction: column; }
    .otp-api-keyrow .otp-herosms-btn { text-align: center; }
}
