:root {
    /* Light only (#82): the portal's palette is fixed, so let the browser render
       form controls, scrollbars and other UA widgets light even when the device
       is in dark mode. Without this, a dark-mode browser recolours those parts
       and they clash with the page. */
    color-scheme: light;
    --bg: #0f172a;
    --bg-soft: #1e293b;
    --card: #ffffff;
    --ink: #0f172a;
    --muted: #64748b;
    --brand: #0ea5e9;
    --brand-dark: #0284c7;
    --accent: #14b8a6;
    --danger: #ef4444;
    --success: #16a34a;
    --warning: #d97706;
    --border: #e2e8f0;
    --radius: 14px;
    --shadow: 0 10px 30px rgba(2, 8, 23, 0.12);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: var(--ink);
    background: #f1f5f9;
    line-height: 1.5;
}

a { color: var(--brand-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

.container { max-width: 1100px; margin: 0 auto; padding: 0 20px; }
.narrow { max-width: 460px; }

/* Top navigation */
.nav {
    background: var(--bg);
    color: #e2e8f0;
    padding: 14px 0;
}
.nav .container { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.brand { font-weight: 700; font-size: 1.25rem; color: #fff; display: flex; align-items: center; gap: 8px; }
.nav a { color: #cbd5e1; margin-left: 18px; }
.nav a:hover { color: #fff; text-decoration: none; }
.nav-links { display: flex; align-items: center; flex-wrap: wrap; }

/* Hero */
.hero {
    background: linear-gradient(135deg, #0ea5e9 0%, #14b8a6 100%);
    color: #fff;
    padding: 56px 0;
    text-align: center;
}
.hero h1 { font-size: 2.4rem; margin: 0 0 10px; }
.hero p { font-size: 1.1rem; opacity: 0.95; margin: 0 auto; max-width: 620px; }

/* Layout helpers */
.section { padding: 40px 0; }
.section h2 { font-size: 1.6rem; margin-top: 0; }
.grid { display: grid; gap: 20px; }
.grid.cols-3 { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* Voucher / home login: constrained on desktop, full width on mobile */
.voucher-row, .login-row { display: flex; }
.voucher-row .card, .login-row .card { width: 100%; max-width: 460px; }
.row { display: flex; gap: 16px; flex-wrap: wrap; }
.between { justify-content: space-between; align-items: center; }

/* Cards */
.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 22px;
    box-shadow: var(--shadow);
}
.card.flat { box-shadow: none; }

/* Plan cards */
.plan { display: flex; flex-direction: column; }
.plan h3 { margin: 0 0 4px; font-size: 1.3rem; }
.plan .price { font-size: 2rem; font-weight: 800; color: var(--brand-dark); margin: 8px 0; }
.plan .price small { font-size: 0.9rem; color: var(--muted); font-weight: 500; }
.plan ul { list-style: none; padding: 0; margin: 10px 0 18px; }
.plan ul li { padding: 6px 0; border-bottom: 1px dashed var(--border); font-size: 0.95rem; }
.plan .spacer { flex: 1; }

/* Buttons */
.btn {
    display: inline-block;
    border: none;
    border-radius: 10px;
    padding: 11px 18px;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    background: var(--brand);
    color: #fff;
    text-align: center;
    transition: background 0.15s ease;
}
.btn:hover { background: var(--brand-dark); text-decoration: none; }
.btn.block { display: block; width: 100%; }
.btn.accent { background: var(--accent); }
.btn.accent:hover { background: #0d9488; }
.btn.ghost { background: transparent; color: var(--brand-dark); border: 1px solid var(--brand); }
.btn.ghost:hover { background: #e0f2fe; }
.btn.danger { background: var(--danger); }
.btn.danger:hover { background: #dc2626; }
.btn.sm { padding: 7px 12px; font-size: 0.85rem; }
.btn:disabled, .btn.is-disabled { background: var(--muted, #9ca3af); cursor: not-allowed; opacity: 0.6; pointer-events: none; }
.btn:disabled:hover, .btn.is-disabled:hover { background: var(--muted, #9ca3af); }

/* Visually hidden (kept for screen readers) */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Forms */
.field { margin-bottom: 16px; }
.field label { display: block; font-weight: 600; margin-bottom: 6px; font-size: 0.92rem; }
.field .hint { color: var(--muted); font-size: 0.82rem; margin-top: 4px; }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=url], textarea, select {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    font-size: 0.95rem;
    font-family: inherit;
    background: #fff;
    color: var(--ink);
}
textarea { min-height: 110px; resize: vertical; }
.checkbox { display: flex; align-items: center; gap: 8px; }
.checkbox input { width: auto; }

/* Alerts */
.alert { padding: 12px 16px; border-radius: 10px; margin-bottom: 18px; font-size: 0.92rem; }
.alert.success { background: #dcfce7; color: #166534; border: 1px solid #bbf7d0; }
.alert.error { background: #fee2e2; color: #991b1b; border: 1px solid #fecaca; }
.alert.warn { background: #fef3c7; color: #92400e; border: 1px solid #fde68a; }
.alert.info { background: #e0f2fe; color: #075985; border: 1px solid #bae6fd; }
.error-text { color: var(--danger); font-size: 0.82rem; margin-top: 4px; }

/* Badges */
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; }
.badge.paid { background: #dcfce7; color: #166534; }
.badge.pending { background: #fef3c7; color: #92400e; }
.badge.expired, .badge.failed { background: #fee2e2; color: #991b1b; }
.badge.open { background: #e0f2fe; color: #075985; }
.badge.answered { background: #dcfce7; color: #166534; }
.badge.closed { background: #e2e8f0; color: #475569; }
.badge.admin { background: #ede9fe; color: #6d28d9; }

/* Tables */
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 11px 12px; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
th { color: var(--muted); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; }
.table-card { overflow-x: auto; }

/* Credentials box */
.creds { background: #0f172a; color: #e2e8f0; border-radius: 10px; padding: 14px; font-family: ui-monospace, monospace; font-size: 0.9rem; }
.creds .pair { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; }
.creds .pair span:first-child { color: #94a3b8; }

/* Modal */
/* The payment popup covers the whole visible page, so the backdrop has no
   padding to inset it and stretches it to full height rather than centring a
   card in the middle. It stays scrollable for the case the popup outgrows the
   screen — a short landscape phone — which stretch keeps reachable and
   centring would push off the top. */
.modal-backdrop {
    position: fixed; inset: 0; background: rgba(2, 8, 23, 0.6);
    display: none; align-items: stretch; justify-content: center; padding: 0; z-index: 50;
    overflow-y: auto;
}
.modal-backdrop.show { display: flex; }
/* The instructions popup (#102) sits over the QR popup, so it needs to beat the
   z-index above — both are full-page, and the one being read has to be on top. */
.modal-backdrop-top { z-index: 60; }
/* Full-page popup: no width cap and no rounded corners, since there is no edge
   left for them to sit on. min-height rather than height so the popup still
   grows past the screen if its content ever needs more room instead of
   clipping. The column centres the stage inside it while there is space spare.
   !important on the background (#82): the popup carries dark text and a QR that
   has to stay readable, so the panel must be white in every browser — including
   ones that force their own dark-mode colours onto page backgrounds. */
.modal {
    position: relative; background: #fff !important;
    width: 100%; max-width: none; min-height: 100%;
    border-radius: 0; padding: 26px; text-align: center;
    display: flex; flex-direction: column; justify-content: center;
}
.modal h3 { margin-top: 0; }
/* Bold red instruction above "Scan/Upload with GCash to Connect" (#68), now on
   the instructions popup (#102). Sized here rather than left at the browser's h2
   default so it stays wider than the heading below it without wrapping mid-word
   on a narrow phone. */
.screenshot-note { margin: 0 0 12px; font-size: 1.25rem; line-height: 1.25; font-weight: 800; color: var(--danger); letter-spacing: 0.03em; }
/* Red note under "Scan/Upload with GCash to Connect" (#100): what to do when
   GCash's upload-from-gallery reader answers "Code is not valid". The same red
   as the call-out above the heading, but at body size and a lighter weight —
   it is an aside to the instruction, not a second headline competing with it. */
.qr-note { margin: 0 0 12px; font-size: 0.95rem; line-height: 1.35; font-weight: 600; color: var(--danger); }
.modal-close {
    position: absolute; top: 10px; right: 12px;
    width: 32px; height: 32px; padding: 0;
    border: none; background: transparent; cursor: pointer;
    font-size: 1.6rem; line-height: 1; color: var(--muted);
    border-radius: 8px;
}
.modal-close:hover { background: #f1f5f9; color: var(--text, #0f172a); }
/* Pull the QR box out past the modal's 26px padding so the code sits ~5px
   from the popup edge — larger QRs scan more reliably on some devices (#67).
   The -21px side margins are fixed, so the 5px gap holds at any modal width. */
.qr-box { display: flex; justify-content: center; margin: 18px -21px; min-height: 200px; align-items: center; }
/* No border: the code is shown bare. The 5px of padding stays, and is not
   decoration now that nothing is drawn around it — it is the code's quiet zone.
   qrcode.js runs the modules right to the edge of its canvas, so without this
   the outermost row would butt straight up against whatever sits next to it.
   Padding rather than anything painted into the bitmap because padding is a
   fixed number of screen pixels: it holds at 5px whether the popup is full
   width or squeezed on a small phone, where anything inside the image would
   scale with the image. The white background is what shows through the padding,
   and it also backs QR images that carry transparency — a code needs light
   behind it to decode.

   Size: the code takes the full width of the box, so it is as large as the
   screen allows rather than capped at one fixed size. box-sizing is border-box
   globally, so the padding comes out of the width and the code itself lands at
   the screen width less 20px — 260px on a folded Galaxy's cover screen, 300px
   on an iPhone SE, 340px on a 360px Android, 410px on the widest phones. A
   fixed cap cannot do that: the largest one that fits every phone is the
   narrowest phone's 260px, which is smaller than the 300px this used to use.

   The two caps that remain:
   - 590px, the resolution the code arrives at (both a proxy bitmap and the one
     we draw ourselves). Past that we would be enlarging a bitmap rather than
     showing it, and no phone is that wide anyway — it only bites on a tablet.
   - the height left after the popup's text (300px of it: 260px is what the text
     measures on a phone-width screen, and the rest covers the heading and the
     "Code is not valid" note wrapping to more lines on a narrow one), so that on
     a screen too short for a full-width code — a phone in landscape, or a 568px
     iPhone SE — the code shrinks instead of running off the bottom. On every
     other phone in portrait the width still binds and this does nothing. Keep
     it in step with the copy above the code: more lines of text, larger number.
     The floor
     stops that shrinking at a code that can still be scanned: below ~250px a
     QR Ph payload is under 5px per module, which is where scanning starts to
     fail, and the popup is scrollable for that case (see .modal-backdrop).
   Written three times over: browsers without min()/max() take the plain 590px,
   ones without dvh take the vh line, and dvh is what tracks a mobile browser's
   viewport as its URL bar comes and goes. */
.qr-box img, .qr-box canvas { width: 100%; max-width: 590px; padding: 5px; background: #fff; }
.qr-box img, .qr-box canvas { max-width: max(260px, min(590px, calc(100vh - 300px))); }
.qr-box img, .qr-box canvas { max-width: max(260px, min(590px, calc(100dvh - 300px))); }
.countdown { font-weight: 700; color: var(--brand-dark); }
.muted { color: var(--muted); }
.small { font-size: 0.85rem; }
.center { text-align: center; }
.hidden { display: none !important; }

/* Admin layout */
.admin-shell { display: flex; min-height: 100vh; }
.sidebar { width: 230px; background: var(--bg); color: #cbd5e1; padding: 20px 0; flex-shrink: 0; }
.sidebar .brand { padding: 0 20px 18px; }
.sidebar a { display: block; color: #cbd5e1; padding: 11px 22px; font-size: 0.92rem; }
.sidebar a:hover, .sidebar a.active { background: rgba(255,255,255,0.08); color: #fff; text-decoration: none; }
.admin-main { flex: 1; background: #f1f5f9; }
.admin-topbar { background: #fff; border-bottom: 1px solid var(--border); padding: 14px 26px; display: flex; justify-content: space-between; align-items: center; }
.admin-content { padding: 26px; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; margin-bottom: 26px; }
.stat { background: #fff; border: 1px solid var(--border); border-radius: var(--radius); padding: 18px; }
.stat .label { color: var(--muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; }
.stat .value { font-size: 1.8rem; font-weight: 800; margin-top: 6px; }

footer.site { background: var(--bg); color: #94a3b8; padding: 26px 0; margin-top: 40px; font-size: 0.88rem; }
footer.site a { color: #cbd5e1; }

@media (max-width: 720px) {
    .sidebar { width: 100%; }
    .admin-shell { flex-direction: column; }
    .hero h1 { font-size: 1.8rem; }

    /* Stack the top navigation so links stay tappable on phones */
    .nav .container { flex-direction: column; align-items: flex-start; gap: 10px; }
    .nav-links { width: 100%; }
    .nav a { margin-left: 0; margin-right: 18px; }
    .nav-links form { margin-left: 0 !important; }

    /* Voucher / login card and plans stretch to full width on mobile */
    .voucher-row .card, .login-row .card { max-width: 100%; }
    .section { padding: 28px 0; }
    .grid { gap: 16px; }
}
