/* ATF Connect — shared UI kit (inner pages). Poppins · ATF blue · light default + day/night. */
:root {
    --ink:#0e2233; --muted:#5b6b76; --blue:#0e4d92; --blue2:#0a3a70;
    --bg:#f5f8fc; --card:#ffffff; --wash:#eef3fa; --line:#e3eaf3;
    --ok:#1a9e6c; --bad:#c94f4f; --radius:10px;
    /* C2 (review 2026-08-29) — the INK THAT SITS ON THE ACCENT, as a token. ~25 views paint a
       chip or a button with an inline `background:var(--blue)` and a literal `color:#fff`; the
       literal cannot follow the accent when the dark scope lifts --blue to a light tint, so every
       one of them read white-on-pale (~2:1). One token, flipped once per theme, moves them all. */
    --on-blue:#ffffff;
}
[data-theme="dark"] {
    --bg:#16202f; --wash:#1d2937; --card:#202c3d; --ink:#e9eef6; --muted:#a6b6ca; --line:#33445c;
    /* C1 (theme audit): the dark scope re-tokened surfaces but NOT the accents, so every
       link, kicker and chip kept brand blue #0e4d92 on #16202f — 1.9:1, unreadable. These
       are the same lifted accents the design system uses (ds/atf-theme.css:68-73). */
    --blue:#6aa5e2; --blue2:#85b8ea; --ok:#3fa76a; --bad:#d66560;
    /* the lifted accent is a LIGHT tint, so what sits on it must be dark ink, not white */
    --on-blue:#0e2233;
}
/* C7 (theme audit): native selects, scrollbars and form controls stayed light-painted
   because the UA never learned the page is dark. */
:root[data-theme="dark"] { color-scheme: dark; }
/* C2 (theme audit): the two places that put white text ON the accent. The lifted --blue
   above is a light tint, so white-on-it drops to ~2:1 — give each a dark twin instead of
   un-lifting the token that fixed every other use. */
[data-theme="dark"] .btn-primary { background:linear-gradient(135deg,#2f74c8,#0e4d92); }
/* C2 follow-up (review 2026-08-29): the `.badge` half of that pair is GONE. It could never win —
   every blue chip carries its colour INLINE, which beats a stylesheet rule — and it repainted the
   badges that carry NO background at all in the card's own colour, i.e. invisible. The inline
   sites now use var(--on-blue); a bare badge keeps the base .badge colour in both themes. */
* { margin:0; padding:0; box-sizing:border-box; }
html { scrollbar-width:thin; scrollbar-color:rgba(120,145,180,.35) transparent; }
::-webkit-scrollbar { width:6px; height:6px; }
::-webkit-scrollbar-thumb { background:rgba(120,145,180,.35); border-radius:8px; }
::-webkit-scrollbar-track { background:transparent; }
body {
    font-family:'Poppins',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif;
    background:var(--bg); color:var(--ink); min-height:100vh; -webkit-font-smoothing:antialiased;
    display:flex; flex-direction:column; transition:background .3s ease, color .3s ease;
}
a { color:var(--blue); text-decoration:none; }
img { max-width:100%; }

/* ── Header ── */
/* Z LAW (Owner screenshot, 31 Aug — the map painted OVER the mega menu): Leaflet's own panes
   run 100-700 and its controls 800. Everything that must beat a map lives ABOVE 800:
   header 900 · header dropdowns 910 · assistant 850 · full modals 1000+. */
.site-head { background:var(--card); border-bottom:1px solid var(--line); position:sticky; top:0; z-index:900; }
.site-head .inner { max-width:1200px; margin:0 auto; display:flex; align-items:center; gap:14px; padding:6px 16px; }
.site-head .logo { height:52px; width:auto; mix-blend-mode:multiply; }
[data-theme="dark"] .site-head .logo { mix-blend-mode:normal; background:#fff; padding:3px 7px; border-radius:8px; }
.site-nav { display:flex; gap:2px; margin-left:6px; flex:1; }
.site-nav a { padding:9px 12px; border-radius:8px; font-size:.88rem; font-weight:500; color:var(--ink); white-space:nowrap; }
.site-nav a:hover, .site-nav a.on { background:var(--wash); color:var(--blue); }
.head-actions { display:flex; align-items:center; gap:8px; margin-left:auto; }
.iconbtn { width:36px; height:36px; border-radius:8px; border:1px solid var(--line); background:var(--card); cursor:pointer; font-size:.95rem; }
.burger { display:none; }
@media (max-width:960px) {
    .site-nav { display:none; position:absolute; top:100%; left:0; right:0; background:var(--card);
        border-bottom:1px solid var(--line); flex-direction:column; padding:8px 12px 14px; gap:2px; box-shadow:0 14px 30px rgba(14,34,51,.12); }
    .site-nav.open { display:flex; }
    .site-nav a { padding:12px 12px; font-size:.95rem; }
    .burger { display:inline-flex; align-items:center; justify-content:center; }
    .site-head .logo { height:44px; }
}

/* ── Buttons (edges only slightly covered — 8px, never pills) ── */
.btn { display:inline-flex; align-items:center; justify-content:center; gap:8px; border-radius:4px;
    padding:10px 18px; font-weight:600; font-size:.88rem; cursor:pointer; border:none; font-family:inherit; text-decoration:none; }
/* T17 (Owner 2026-08-22, booking.com north star): "everything is a notch too big and strong" — type, weight,
   padding and shadow all come down HERE, in the theme layer, so every screen moves at once. */
.btn-primary { background:linear-gradient(135deg,var(--blue),var(--blue2)); color:#fff; box-shadow:0 4px 12px rgba(14,77,146,.18); }
.btn-primary:hover { filter:brightness(1.08); }
.btn-ghost { border:1.5px solid var(--blue); color:var(--blue); background:transparent; }
.btn-sm { padding:7px 12px; font-size:.82rem; }
/* Secondary actions are TEXT LINKS, not buttons (DESIGN-DIRECTION-GALLERY §3: "Show on map" is a link).
   .link-action for <a>; .btn-link for a <button> that must submit a form but should READ as a link. */
.link-action, .btn-link { display:inline-flex; align-items:center; gap:5px; color:var(--blue); font-weight:600;
    font-size:.86rem; text-decoration:none; background:none; border:0; padding:0; cursor:pointer; font-family:inherit;
    border-bottom:1px solid transparent; line-height:1.4; }
.link-action:hover, .btn-link:hover { border-bottom-color:currentColor; }
.link-action.muted, .btn-link.muted { color:var(--muted); font-weight:500; }
.link-action:focus-visible, .btn-link:focus-visible { outline:2px solid var(--brand-gold,#d99a1c); outline-offset:2px; border-radius:3px; }
.btn-block { width:100%; }

/* ── Cards / layout ── */
.page { flex:1; width:100%; max-width:1200px; margin:0 auto; padding:26px 16px 60px; }
.page-narrow { max-width:520px; }
/* T27 fix (26 Aug review): a 2-column form inside the 520px narrow page gave ~200px fields on
   desktop — NARROWER than the old single column. A narrow page that carries the forms grid
   widens so each column is a real field (~320px); phones still collapse to one column. */
.page-narrow:has(.form-grid) { max-width:760px; }
.card { background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
    box-shadow:0 1px 3px rgba(14,34,51,.05); }
.card-pad { padding:clamp(20px,4vw,32px); }
.page-title { font-size:clamp(1.2rem,3.4vw,1.6rem); font-weight:700; letter-spacing:-.015em; margin-bottom:4px; }   /* T17: a notch down */
.page-sub { color:var(--muted); font-size:.88rem; margin-bottom:18px; }
.kicker { text-transform:uppercase; letter-spacing:.2em; font-size:.66rem; color:var(--blue); font-weight:700; }

/* ── Forms ── */
.field { margin-bottom:16px; }
.field label { display:block; font-size:.82rem; font-weight:600; margin-bottom:6px; color:var(--ink); }
/* T27 (Owner #1, 25 Aug): THE forms standard — two fields per row, defined ONCE. Textareas and
   anything marked .fg-full span the row; under 640px it collapses to one column. */
.form-grid { display:grid; grid-template-columns:1fr 1fr; column-gap:14px; row-gap:10px; align-items:start; }
.form-grid .field { min-width:0; }
.form-grid .field:has(textarea), .form-grid .fg-full { grid-column:1 / -1; }
@media (max-width:640px) { .form-grid { grid-template-columns:1fr; } }
/* review (31 Aug): a PAIR of fields that is not a whole form. Same geometry and the same 640px
   collapse as .form-grid, deliberately without the name — because .page-narrow:has(.form-grid)
   above widens the page to 760px, which is right for a form PAGE and very wrong for one composer
   row inside a 520px feed. Use this whenever the pair sits on a page that is not a form. */
.composer-grid { display:grid; grid-template-columns:1fr 1fr; column-gap:14px; row-gap:10px; align-items:start; }
.composer-grid .field { min-width:0; }
@media (max-width:640px) { .composer-grid { grid-template-columns:1fr; } }
.field .hint { font-size:.72rem; color:var(--muted); margin-top:4px; }

/* ── T36 (PR-8): the Connect Guide "?" — context help in the header, never a modal ── */
.guide-dd { position:relative; }
.guide-dd > summary { list-style:none; font-weight:700; color:var(--blue); }
.guide-dd > summary::-webkit-details-marker { display:none; }
.guide-dd-menu { position:absolute; right:0; top:calc(100% + 8px); width:min(340px, 88vw); z-index:910;
    background:var(--card); border:1px solid var(--line); border-radius:10px; padding:14px 16px;
    box-shadow:0 14px 34px rgba(14,34,51,.16); }
.guide-dd-item { border-bottom:1px solid var(--line); padding:4px 0; }
.guide-dd-item summary { cursor:pointer; font-size:.86rem; font-weight:600; padding:6px 0; list-style:none; }
.guide-dd-item summary::-webkit-details-marker { display:none; }
.guide-dd-item p { font-size:.82rem; color:var(--muted); line-height:1.6; padding:0 0 8px; margin:0; }
.guide-dd .link-action { margin-top:10px; }

/* ── T29 (A89/A90): the /me hub layout ──
   The completion/identity card DOCKS beside the hub from 1100px (it floated centered with dead
   space both sides — the Owner's screenshot); stacked on a phone. The orientation strip offers a
   brand-new member direction: continue the profile, or go Home and explore. */
.me-layout { display:grid; grid-template-columns:1fr; gap:0 22px; align-items:start; }
@media (min-width:1100px) {   /* 900px left the hub ONE cramped column beside a 340px aside (review) */
    .me-layout { grid-template-columns:340px minmax(0,1fr); }
    .me-side { position:sticky; top:76px; z-index:10; }   /* B5: auto z let later cards paint over it */
}
.me-orient { display:flex; flex-wrap:wrap; gap:12px; align-items:center; border:1px solid var(--line);
    border-left:4px solid var(--blue); background:var(--wash); border-radius:var(--radius);
    padding:14px 18px; margin-bottom:18px; }
.me-orient p { margin:0; flex:1 1 240px; font-size:.92rem; line-height:1.55; }
.me-orient-x { border:0; background:none; color:var(--muted); font-size:1.25rem; line-height:1;
    cursor:pointer; padding:4px 8px; border-radius:6px; }
.me-orient-x:hover { color:var(--ink); background:var(--line); }
.input, select.input {
    width:100%; padding:12px 14px; border:1.5px solid var(--line); border-radius:8px; font-size:.95rem;
    font-family:inherit; background:var(--card); color:var(--ink); outline:none; transition:border-color .15s ease;
}
.input:focus { border-color:var(--blue); box-shadow:0 0 0 3px rgba(14,77,146,.12); }
.input-group { display:flex; gap:8px; }
.input-group .input.dial { max-width:96px; text-align:center; }
.pw-wrap { position:relative; }
.pw-wrap .input { padding-right:46px; }
.pw-eye { position:absolute; right:6px; top:50%; transform:translateY(-50%); border:none; background:transparent;
    cursor:pointer; font-size:1.05rem; padding:6px; color:var(--muted); }
.captcha-row { display:flex; align-items:center; gap:10px; }
.captcha-q { background:var(--wash); border:1.5px dashed var(--line); border-radius:8px; padding:11px 16px;
    font-weight:700; color:var(--blue); white-space:nowrap; font-size:.95rem; }

/* role chips (radio) */
.role-grid { display:grid; grid-template-columns:repeat(2,1fr); gap:8px; }
@media (min-width:560px) { .role-grid { grid-template-columns:repeat(3,1fr); } }
.role-chip input { position:absolute; opacity:0; }
.role-chip span { display:flex; align-items:center; justify-content:center; text-align:center; padding:11px 8px;
    border:1.5px solid var(--line); border-radius:8px; font-size:.82rem; font-weight:600; cursor:pointer;
    background:var(--card); color:var(--ink); min-height:46px; transition:all .12s ease; }
.role-chip input:checked + span { border-color:var(--blue); background:var(--wash); color:var(--blue); box-shadow:0 0 0 2px rgba(14,77,146,.15); }

/* alerts */
.alert { border-radius:8px; padding:12px 16px; font-size:.88rem; margin-bottom:16px; }
.alert-error { background:rgba(201,79,79,.1); border:1px solid rgba(201,79,79,.35); color:var(--bad); }
.alert-ok { background:rgba(14,77,146,.08); border:1px solid rgba(14,77,146,.28); color:var(--blue); }   /* Golden Rule 10: confirmations in ATF blue, never green (T20 own-eyes catch) */

/* A3 (theme audit): .table-responsive exists only in the vendored DS bundle, so any page
   that loads app.css alone had a table that overflowed the viewport instead of scrolling. */
.table-responsive { overflow-x:auto; -webkit-overflow-scrolling:touch; position:relative; }

/* badges */
.badge { display:inline-block; font-size:.72rem; font-weight:600; padding:4px 10px; border-radius:6px; color:#fff; background:var(--muted,#78899a);}

/* ── Footer ── */
.site-foot { border-top:1px solid var(--line); background:var(--card); text-align:center;
    padding:22px 16px 28px; color:var(--muted); font-size:.78rem; line-height:1.8; }
.site-foot a { font-weight:600; }

/* ── Image cropper (house standard: fixed crops only) ── */
.cropfield { display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
.crop-preview { width:84px; height:84px; border-radius:12px; object-fit:cover; border:1.5px solid var(--line); background:var(--wash); }
.crop-preview.wide { width:148px; height:84px; }
.crop-modal { position:fixed; inset:0; z-index:1000;   /* B1: was 200 — under Leaflet panes and the assistant bubble */ background:rgba(10,20,35,.66); display:none; align-items:center; justify-content:center; padding:16px; }
.crop-modal.open { display:flex; }
.crop-box { background:var(--card); border-radius:12px; padding:16px; max-width:640px; width:100%; }
.crop-box .stage { max-height:60vh; overflow:hidden; background:#0b1522; border-radius:8px; }
.crop-box img { max-width:100%; display:block; }
.crop-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:12px; }
.venue-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:10px; }
.venue-grid .vph { position:relative; border-radius:10px; overflow:hidden; border:1px solid var(--line); }
.venue-grid .vph img { width:100%; height:92px; object-fit:cover; display:block; }
/* The remove control is a <button> now, not an <a>: deleting a photo is a POST (review 2026-08-28). */
.venue-grid .vph a, .venue-grid .vph button { position:absolute; top:6px; right:6px; background:rgba(10,20,35,.72); color:#fff; border-radius:6px;
    padding:2px 8px; font-size:.7rem; text-decoration:none; border:0; cursor:pointer; font-family:inherit; line-height:1.5; }

/* language dropdown (shell header) */
.langdd { position:relative; }
.langdd-btn { display:flex; align-items:center; gap:7px; border:1px solid var(--line); background:var(--card); color:var(--ink);
    border-radius:8px; padding:7px 11px; font-weight:600; font-size:.82rem; cursor:pointer; font-family:inherit; }
.langdd-btn img { width:19px; height:13px; border-radius:2px; object-fit:cover; }
.langdd .chev { font-style:normal; font-size:.66rem; color:var(--muted); }
.langdd-menu { position:absolute; right:0; top:calc(100% + 6px); min-width:172px; background:var(--card); border:1px solid var(--line);
    border-radius:10px; box-shadow:0 12px 30px rgba(14,34,51,.16); padding:6px; display:none; z-index:910; }
.langdd.open .langdd-menu { display:block; }
.langdd-item { display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:7px; color:var(--ink);
    font-size:.85rem; text-decoration:none; }
.langdd-item:hover, .langdd-item.on { background:var(--wash); }
.langdd-item.on { font-weight:700; }
.langdd-item img { width:19px; height:13px; border-radius:2px; object-fit:cover; }
@media (max-width:560px) { .langdd-btn .lgname { display:none; } }

/* ── Welcome line ───────────────────────────────────────────────────────────
   Copy only. The header already carries Get Connected + Login, so this strip
   never repeats them (owner, 2026-08-19: "lets not have two same buttons
   together everywhere"). The words themselves link to /register.             */
.welcomebar { background:var(--wash); border-bottom:1px solid var(--line); }
.wb-inner { max-width:1180px; margin:0 auto; padding:8px 20px; }
.wb-copy { display:flex; align-items:center; gap:9px; flex-wrap:wrap;
    font-size:.82rem; line-height:1.5; color:var(--ink); }
.wb-mark { display:inline-flex; color:var(--blue); flex:0 0 auto; opacity:.85; }
.wb-msg { font-weight:600; letter-spacing:.005em; }
.wb-hint { color:var(--muted); text-decoration:none; border-bottom:1px solid transparent;
    transition:color .15s, border-color .15s; }
.wb-hint::before { content:""; display:inline-block; width:1px; height:11px;
    background:var(--line); margin-right:9px; vertical-align:-1px; }
.wb-hint:hover { color:var(--blue); border-bottom-color:var(--blue); }

@media (max-width:760px) {
    .wb-inner { padding:7px 14px; }
    .wb-copy { font-size:.75rem; gap:7px; }
    .wb-hint { display:none; }   /* one clean line on a phone; the header buttons carry the action */
}

/* ── Demonstration band (profile pages) ─────────────────────────────────────
   Showcase profiles are labelled honestly but quietly — the page still has to
   read high-end. Owner: never the word "DEMO"; "For Demonstration" only.      */
.demoband { display:flex; align-items:center; gap:9px; margin:0 0 16px;
    padding:9px 15px; border-radius:8px; background:var(--wash);
    border:1px solid var(--line); border-left:3px solid var(--blue); }
.db-mark { display:inline-flex; color:var(--blue); flex:0 0 auto; opacity:.9; }
.db-text { font-size:.79rem; color:var(--muted); line-height:1.5; letter-spacing:.005em; }
.svc-mark { position:absolute; left:0; display:inline-flex; color:var(--blue); top:2px; }
.cert-mark { display:inline-flex; color:var(--blue); opacity:.85; }

/* ── Fit-text: cards must NEVER change size ─────────────────────────────────
   Owner rule (2026-08-19): "for no apparent reason, the profile boxes will not
   be allowed to change size" — a long Thai name or a long academy name must not
   stretch its card. The hierarchy the owner specified, in order:
     1. shrink the type a little   (JS steps 100% → 94% → 88% → 82%)
     2. clamp to a fixed line count
     3. reveal the full text on hover/focus via tooltip  (title attribute)
   Applied site-wide, not per page.                                            */
.u-fit { display:-webkit-box; -webkit-box-orient:vertical; overflow:hidden;
    -webkit-line-clamp:var(--fit-lines,2); line-clamp:var(--fit-lines,2);
    overflow-wrap:anywhere; transition:font-size .1s ease; }
.u-fit[data-truncated="1"] { cursor:help; }
.u-fit-1 { --fit-lines:1; }
.u-fit-3 { --fit-lines:3; }

/* every result card is the same height, whatever it contains */
.rcard { min-height:268px; }
.rtop { min-height:62px; align-items:flex-start; }
.rspec { min-height:38px; }
.rfoot { margin-top:auto; }

/* the whole card head is a link now — name AND photo open the profile */
.rlink { color:inherit; text-decoration:none; display:block; }
.rlink:hover .rname { color:var(--blue); }
.ravlink { display:inline-block; border-radius:10px; overflow:hidden; line-height:0;
    transition:transform .15s ease, box-shadow .15s ease; }
.ravlink:hover { transform:scale(1.04); box-shadow:0 6px 18px rgba(14,77,146,.28); }

/* the demonstration note under View Profile — owner wants it red and centred */
.demo-note { display:block; width:100%; text-align:center; margin-top:9px;
    font-size:.7rem; font-weight:600; letter-spacing:.03em; color:var(--demo); }
:root { --demo:#c0392b; }
[data-theme="dark"] { --demo:#ff8a7a; }
.demoband { border-left-color:var(--demo); }
.demoband .db-text { color:var(--demo); font-weight:600; }
.demoband .db-mark { color:var(--demo); }

/* ── National flag on result cards ──────────────────────────────────────────
   Owner (2026-08-19): "a small country flag in the upper right corner … very
   helpful for people to identify with their national flags." Real SVGs from the
   vendored set — emoji flags render as bare letters (GB, JP) on Windows.       */
.rflag { position:absolute; top:14px; right:14px; width:26px; height:18px;
    object-fit:cover; border-radius:3px; box-shadow:0 1px 4px rgba(14,34,51,.22);
    border:1px solid rgba(255,255,255,.65); z-index:2; }
[data-theme="dark"] .rflag { border-color:rgba(255,255,255,.22); }
/* keep the flag clear of the favourite heart */
/* Owner 2026-08-24: the heart sat on the TITLE (top-right fought the flag for the corner and
   lost into the text). Bottom-right is the card's one quiet corner — visible, never colliding. */
.rcard .fav-heart { top:auto; bottom:10px; right:10px; }

/* ── Image lightbox ─────────────────────────────────────────────────────────*/
.lbox { position:fixed; inset:0; z-index:9999; display:none; align-items:center;
    justify-content:center; padding:28px; background:rgba(8,18,32,.86);
    backdrop-filter:blur(3px); opacity:0; transition:opacity .18s ease; }
.lbox.on { display:flex; opacity:1; }
.lbox-fig { margin:0; max-width:min(92vw,720px); text-align:center; }
.lbox-img { display:block; width:100%; height:auto; max-height:82vh; object-fit:contain;
    border-radius:12px; box-shadow:0 24px 70px rgba(0,0,0,.55); }
.lbox-cap { margin-top:12px; color:#e8eef7; font-size:.86rem; font-weight:500; letter-spacing:.01em; }
.lbox-x { position:absolute; top:18px; right:22px; width:40px; height:40px; border:0;
    border-radius:8px; background:rgba(255,255,255,.12); color:#fff; font-size:1.7rem;
    line-height:1; cursor:pointer; transition:background .15s; }
.lbox-x:hover { background:rgba(255,255,255,.24); }
[data-zoom] { cursor:zoom-in; }

/* ── Favourite heart ────────────────────────────────────────────────────────
   Sits BESIDE the national flag, not under it. The flag owns the top-right
   corner; the heart moves left of it. Previously this was inline-styled with no
   class, so it collided with the flag for logged-in members only — invisible
   while logged out, which is how the site was being reviewed.                 */
/* default = tight corner; only zone cards (.rcard) reserve flag clearance */
.fav-heart { position:absolute; top:11px; right:8px; z-index:3; }
.fav-heart.fav-inline { position:static; display:inline; }
.fav-btn, a.fav-btn { border:0; background:rgba(255,255,255,.88); border-radius:50%; text-decoration:none;
    width:30px; height:30px; cursor:pointer; line-height:0; display:inline-flex;
    align-items:center; justify-content:center; color:var(--muted);
    box-shadow:0 1px 4px rgba(14,34,51,.18); transition:color .15s, transform .15s; }
.fav-btn:hover { transform:scale(1.08); color:var(--demo); }
.fav-mark.on { color:var(--demo); }
[data-theme="dark"] .fav-btn { background:rgba(21,34,56,.9); }
.empty-mark { display:flex; justify-content:center; color:var(--muted); opacity:.55; margin-bottom:10px; }

/* ── Membership tiers: crest + glowing outline ──────────────────────────────
   Owner (2026-08-19): "whichever badge is placed on whichever profile, that box's
   outline should also glow in that colour. That would make the box stand out."

   The glow is a coloured border plus a soft outer shadow — restrained by default
   and lifting on hover, so a grid of tiered cards still reads as a calm page and
   not a fairground. Tier is conveyed by the CREST as well as the colour, so it
   stays legible to colour-blind members.                                       */
.rcard.tier { border-width:1.5px; }

.tier-bronze   { --tier:#b87333; --tier-soft:rgba(184,115,51,.30); }
.tier-silver   { --tier:#8fa0ae; --tier-soft:rgba(143,160,174,.32); }
.tier-gold     { --tier:#d4a017; --tier-soft:rgba(212,160,23,.32); }
.tier-platinum { --tier:#4a90d9; --tier-soft:rgba(74,144,217,.34); }

.rcard.tier { border-color:var(--tier);
    box-shadow:0 0 0 1px var(--tier-soft), 0 6px 20px -6px var(--tier-soft); }
.rcard.tier:hover { box-shadow:0 0 0 2px var(--tier-soft), 0 14px 34px -8px var(--tier-soft); }

/* the crest sits bottom-right, clear of the flag (top-right) and the heart */
.rrole { display:inline-flex; align-items:center; gap:6px; min-width:0; }
.rtier { width:22px; height:20px; object-fit:contain; flex:0 0 auto; cursor:zoom-in;
    filter:drop-shadow(0 1px 3px rgba(14,34,51,.26)); transition:transform .15s ease; }
.rtier:hover { transform:scale(1.18); }

/* The footer must ALWAYS be one row: the button never wraps, and the role label
   yields space instead. Owner rule: card size is fixed — a badge or a long role
   name must never grow the box. This regressed once; these three lines prevent it. */
.rfoot { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:nowrap; }
.rfoot .btn { white-space:nowrap; flex:0 0 auto; }
.rrole { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* dark theme: the same colours need a touch more presence against a dark card */
[data-theme="dark"] .rcard.tier {
    box-shadow:0 0 0 1px var(--tier-soft), 0 6px 22px -4px var(--tier-soft); }

/* profile page: crest beside the name */
.ptier { width:56px; height:auto; vertical-align:middle; margin-left:10px;
    filter:drop-shadow(0 2px 6px rgba(14,34,51,.32)); }
/* crest sits left of the card title; the name shrinks (u-fit) rather than the card growing */
.rnamerow { display:flex; align-items:flex-start; gap:7px; min-width:0; }
.rnamerow .rlink { min-width:0; flex:1 1 auto; }
.rnamerow .rtier { margin-top:1px; }

/* ── Sidebar map ────────────────────────────────────────────────────────────
   Owner (2026-08-19): the profile map was "too overpowering right in the centre".
   It now sits in the sidebar under the Get Connected card, deliberately short —
   enough to place someone on a map, not enough to dominate the page.
   The shared _map partial hard-codes 340px, so the override is scoped here.     */
.map-side [id^="map"] { height:190px !important; margin-bottom:0 !important; border-radius:8px; }
.map-side .sec-title { font-size:.78rem; letter-spacing:.06em; }
@media (max-width:860px) {
    /* on a phone the sidebar stacks under the content — keep the map shorter still */
    .map-side [id^="map"] { height:170px !important; }
}

/* ── Header: the logo must never be squeezed ────────────────────────────────
   Adding Courts + Community to the nav (2026-08-20) pushed the flex row past its
   width and the logo — an <img> with `width:auto` — was the item that gave way,
   collapsing to a sliver. flex-shrink:0 makes the brand non-negotiable; the nav
   yields instead, and drops to the burger sooner on narrower screens.            */
.site-head .logo { flex:0 0 auto; min-width:96px; object-fit:contain; }
.site-head .inner > a:first-child { flex:0 0 auto; display:inline-flex; }
.site-nav { min-width:0; }
.site-nav a { padding:9px 10px; font-size:.855rem; }

/* nine items is too many for a laptop width — hand over to the burger earlier */
@media (max-width:1180px) {
    .site-nav { display:none; }
    .burger { display:inline-flex !important; }
}
/* ── The burger panel IS the mega menu ──────────────────────────────────────
   Owner (2026-08-20): the mobile menu looked bland next to the desktop panel.
   Rather than maintain two designs, the burger simply reveals the SAME mega panel
   inline — icon tiles, titles and descriptions intact — so a phone gets the same
   quality of navigation, not a stripped-down list. */
@media (max-width:1180px) {
    .site-nav.open { display:flex; position:absolute; top:100%; left:0; right:0;
        background:var(--card); border-bottom:1px solid var(--line); flex-direction:column;
        padding:10px; gap:4px; z-index:40; max-height:calc(100vh - 60px); overflow-y:auto;
        box-shadow:0 18px 40px -12px rgba(14,34,51,.28); }

    /* the panel stops floating and becomes part of the sheet */
    .site-nav.open .mega-wrap { position:static; }
    .site-nav.open .mega-btn  { display:none; }
    .site-nav.open .mega-panel {
        position:static; opacity:1; visibility:visible; transform:none;
        width:auto; border:0; box-shadow:none; padding:0 0 6px; background:transparent; }
    .site-nav.open .mega-grid { grid-template-columns:1fr; gap:2px; }
    .site-nav.open .mega-item.is-last { grid-column:auto; }
    .site-nav.open .mega-head { padding:2px 8px 8px; }

    /* the remaining flat links get the same tile treatment so nothing looks orphaned */
    .site-nav.open > a { display:flex; align-items:center; gap:12px; padding:12px 10px;
        border-radius:10px; font-size:.9rem; font-weight:700; color:var(--ink); }
    .site-nav.open > a .navico { display:inline-flex; align-items:center; justify-content:center;
        width:38px; height:38px; border-radius:9px; flex:0 0 auto; color:var(--blue);
        background:color-mix(in srgb, var(--blue) 9%, transparent); }
    .site-nav.open > a:hover { background:var(--wash); }
}

/* With nine nav items the header actions must give ground before the nav does.
   The flag alone identifies the language perfectly well; the word is a luxury we
   can afford only on a wide screen. */
@media (max-width:1460px) {
    .langdd-btn .lgname { display:none; }
    .langdd-btn { padding-left:10px; padding-right:8px; }
}
@media (max-width:1320px) {
    .site-nav a { padding:9px 8px; font-size:.82rem; }
}

/* ── Mega menu ──────────────────────────────────────────────────────────────
   One panel replaces eight flat links. Design follows the owner's reference:
   a soft-cornered white sheet, a quiet section label, and a two-column grid of
   items where each carries a tinted icon tile, a bold title and one explanatory
   line. Restraint is the point — this sits over the page, so it must feel like
   part of the page, not a dialog.                                              */
.mega-wrap { position:relative; }
.mega-btn { display:inline-flex; align-items:center; gap:6px; padding:9px 12px; border:0;
    border-radius:8px; background:transparent; color:var(--ink); font:inherit;
    font-size:.88rem; font-weight:600; cursor:pointer; white-space:nowrap; }
.mega-btn:hover, .mega-btn[aria-expanded="true"] { background:var(--wash); color:var(--blue); }
.mega-btn .chev { font-style:normal; font-size:.7rem; opacity:.75; transition:transform .18s ease; }
.mega-btn[aria-expanded="true"] .chev { transform:rotate(180deg); }

.mega-panel { position:absolute; top:calc(100% + 10px); left:0; z-index:910;
    width:min(720px, calc(100vw - 32px));
    background:var(--card); border:1px solid var(--line); border-radius:16px;
    box-shadow:0 24px 60px -12px rgba(14,34,51,.28), 0 2px 8px rgba(14,34,51,.06);
    padding:18px 18px 14px; opacity:0; visibility:hidden; transform:translateY(-6px);
    transition:opacity .16s ease, transform .16s ease, visibility .16s; }
.mega-panel.open { opacity:1; visibility:visible; transform:translateY(0); }

.mega-head { font-size:.7rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
    color:var(--muted); padding:0 8px 12px; }
.mega-grid { display:grid; grid-template-columns:1fr 1fr; gap:2px; }

.mega-item { display:flex; align-items:flex-start; gap:12px; padding:11px 10px;
    border-radius:10px; text-decoration:none; transition:background .13s ease; }
.mega-item:hover { background:var(--wash); }
.mega-ico { flex:0 0 auto; width:38px; height:38px; border-radius:9px; display:inline-flex;
    align-items:center; justify-content:center; color:var(--blue);
    background:color-mix(in srgb, var(--blue) 9%, transparent); transition:background .13s ease; }
.mega-item:hover .mega-ico { background:color-mix(in srgb, var(--blue) 16%, transparent); }
.mega-txt { min-width:0; display:flex; flex-direction:column; gap:2px; }
.mega-title { font-size:.9rem; font-weight:700; color:var(--ink); line-height:1.25; }
.mega-desc { font-size:.775rem; color:var(--muted); line-height:1.45; }

/* the eighth item — the community grid — is the destination, so it reads as the
   conclusion of the list rather than one more sibling */
.mega-item.is-last { grid-column:1 / -1; margin-top:6px; padding-top:14px;
    border-top:1px solid var(--line); border-radius:0 0 10px 10px; }
.mega-item.is-last .mega-ico { background:color-mix(in srgb, var(--blue) 14%, transparent); }

[data-theme="dark"] .mega-panel { box-shadow:0 26px 64px -12px rgba(0,0,0,.6); }

@media (max-width:900px) {
    .mega-panel { width:calc(100vw - 24px); left:auto; right:0; }
    .mega-grid { grid-template-columns:1fr; }
    .mega-item.is-last { grid-column:auto; }
}

/* ── Community grid: showcase cards lead ────────────────────────────────────*/
.grid .card.is-demo { border-color:color-mix(in srgb, var(--demo) 35%, var(--line)); }
/* A119: one avatar mode everywhere — square tiles (the Owner's card law) */
.grid .avlink { display:inline-block; border-radius:10px; overflow:hidden; line-height:0; flex:0 0 auto;
    transition:transform .15s ease, box-shadow .15s ease; }
.grid .avlink:hover { transform:scale(1.05); box-shadow:0 6px 16px rgba(14,77,146,.28); }
.grid .namelink { color:inherit; text-decoration:none; }
.grid .namelink:hover { color:var(--blue); }
.grid .card .demo-note { margin-top:10px; }

/* the landing stat band shares the mega menu's tinted icon-tile language */
.ex-ico { display:inline-flex; align-items:center; justify-content:center; width:52px; height:52px;
    margin:0 auto 10px; border-radius:12px; color:var(--blue);
    background:color-mix(in srgb, var(--blue) 10%, transparent); }
.ex-card:hover .ex-ico { background:color-mix(in srgb, var(--blue) 18%, transparent); }

/* theme toggle shows the action, not the current state: a moon in light mode
   (tap for dark), a sun in dark mode (tap for light) */
.ico-sun { display:none; }
[data-theme="dark"] .ico-moon { display:none; }
[data-theme="dark"] .ico-sun  { display:inline-flex; }
/* centre the glyph inside icon buttons — but NOT .burger, whose display is a
   responsive state (.burger { display:none } until the breakpoint). A blanket
   `.iconbtn { display:inline-flex }` re-showed the burger on desktop. */
.iconbtn:not(.burger) { display:inline-flex; align-items:center; justify-content:center; }
.burger { align-items:center; justify-content:center; }

/* ── Header: bigger brand, same height ──────────────────────────────────────
   Owner asked for the logo 25% larger with NO increase in header height.
   Measured before: header 57px, logo 96x44 (width-constrained by min-width).
   120px wide is +25%, which makes it 55px tall — so the row's vertical padding
   is reclaimed to pay for it. Net header height stays 57px.                    */
/* The header height is FIXED at 57px — the owner's explicit instruction, twice. It must not
   drift as a side effect of changing the logo, the buttons or anything else inside it. Locking
   min-height here means the bar is the constant and the contents fit inside it, rather than the
   contents deciding the bar. (Trimming the logo removed the tallest element and silently shrank
   the header — exactly the drift this prevents.) */
.site-head .inner { padding-top:0; padding-bottom:0; min-height:56px; }   /* +1px border = 57px total, matching live exactly */
/* The brand asset is now PRE-TRIMMED (atf-logo.png). The original JPG was 71% whitespace, so
   most of the "logo size" was empty canvas — raising its width grew the padding, not the mark.
   With the padding gone, a 39px-tall box renders the mark ~25% larger than the old 120px-wide
   box did, and the header stays 57px. There is headroom here for more if the owner wants it. */
.site-head .logo  { height:44px; width:auto; min-width:0; max-height:none; mix-blend-mode:normal; }
[data-theme="dark"] .site-head .logo { background:transparent; padding:0; }

/* Home sits between the brand and the mega menu */
.homebtn { display:inline-flex; align-items:center; justify-content:center;
    width:38px; height:38px; border-radius:9px; color:var(--ink); flex:0 0 auto;
    transition:background .13s ease, color .13s ease; }
.homebtn:hover { background:var(--wash); color:var(--blue); }
.homebtn.on { background:color-mix(in srgb, var(--blue) 12%, transparent); color:var(--blue); }
@media (max-width:1180px) { .homebtn { width:34px; height:34px; } }

/* ── Mobile header: nothing may wrap ────────────────────────────────────────
   "Get Connected" was breaking onto two lines and dragging the header taller.
   The controls now scale down with the viewport instead of wrapping, and the
   Home button — which the logo already duplicates — steps aside on small screens. */
@media (max-width:620px) {
    .homebtn { display:none; }
    .site-head .logo { height:34px; }
    .head-actions { gap:6px; }
    .head-actions .btn { padding:7px 10px; font-size:.78rem; white-space:nowrap; }
    .langdd-btn { padding:6px 8px; }
    .langdd-btn .lgname { display:none; }
    .iconbtn:not(.burger) { width:32px; height:32px; }
}
@media (max-width:400px) {
    .site-head .logo { height:30px; }
    .head-actions .btn { padding:6px 8px; font-size:.72rem; }
    .head-actions .btn-ghost { display:none; }   /* Login is inside the panel; keep one CTA */
}
.head-actions .btn { white-space:nowrap; }

/* the nav icons exist for the burger sheet only — desktop keeps clean text links */
.navico { display:none; }

/* community card flag — absolutely positioned so the card size is untouched */
.grid .card { position:relative; }
.cflag { position:absolute; top:14px; right:14px; width:24px; height:17px; object-fit:cover;
    border-radius:3px; box-shadow:0 1px 4px rgba(14,34,51,.22);
    border:1px solid rgba(255,255,255,.6); z-index:2; }
[data-theme="dark"] .cflag { border-color:rgba(255,255,255,.2); }
.grid .card .who { padding-right:30px; }   /* keep long names clear of the flag */

/* ── Find a court: search left, map right ───────────────────────────────────*/
.courts-split { display:grid; grid-template-columns:320px 1fr; gap:16px; margin-bottom:20px; align-items:start; }
.courts-search { align-self:start; }
.courts-search .field { margin-bottom:12px; }
.courts-count { margin:14px 0 0; padding-top:12px; border-top:1px solid var(--line);
    font-size:.8rem; color:var(--muted); }
.courts-map { position:relative; padding:0; overflow:hidden; min-height:420px; }
.courts-map-canvas { height:420px; width:100%; }
/* B3 (theme audit): bottom-right put this under Leaflet's own attribution control (z 1000),
   which is also anchored bottom-right — the button was both covered and un-tappable.
   B3 follow-up (review 2026-08-29): 1100 then painted OVER the booking modal (.bw-modal, z 1000,
   _book_widget_css.php:5) on find_court.php. Moving to TOP-right already clears every Leaflet
   control (its panes stop at 800, its bottom-anchored controls at 1000), so 400 is above the map
   and safely below any dialog — the modal is the layer that must always win. */
.locate-btn { position:absolute; right:12px; top:12px; z-index:400; background:var(--card);
    box-shadow:0 4px 14px rgba(14,34,51,.22); }
@media (max-width:900px) {
    .courts-split { grid-template-columns:1fr; }   /* search first — a thumb reaches filters before it reads a map */
    .courts-map-canvas, .courts-map { min-height:300px; height:300px; }
}

/* ════════════════════════════════════════════════════════════════════════════
   SUBTLE POLISH — owner brief (2026-08-20): "add some subtle designing to our
   pages, they are too bland right now. Please do not over power it."

   The rule followed throughout: motion under 200ms, shadows tinted with the brand
   blue rather than black, nothing that moves more than 2px, and every effect tied
   to an interaction the visitor initiated. Nothing animates on its own except one
   page-entry fade — decoration that loops becomes noise.
   ════════════════════════════════════════════════════════════════════════════ */

/* honour a visitor who has asked for less motion — this is not optional */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration:.01ms !important; animation-iteration-count:1 !important;
        transition-duration:.01ms !important; scroll-behavior:auto !important; }
}

/* ── page entry: one gentle rise, never repeated ────────────────────────────
   Wrapped in prefers-reduced-motion: no-preference ON PURPOSE. With `both` fill
   mode the elements hold the animation's START state (opacity 0) if the animation
   never runs — so an old browser, a print stylesheet or a blocked stylesheet would
   render a BLANK page. Outside this query nothing is hidden, so the default is
   always visible content and the motion is the enhancement.                       */
@media (prefers-reduced-motion: no-preference) {
    @keyframes riseIn { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
    .page > .kicker, .page > .page-title, .page > .page-sub, .dirhead { animation:riseIn .34s ease both; }
    .page > .page-title { animation-delay:.04s; }
    .page > .page-sub   { animation-delay:.08s; }

    /* cards arrive in a soft stagger — only the first few, so a long list is not a slideshow */
    .grid > .card, .results > .card { animation:riseIn .32s ease both; }
    .grid > .card:nth-child(1), .results > .card:nth-child(1) { animation-delay:.02s; }
    .grid > .card:nth-child(2), .results > .card:nth-child(2) { animation-delay:.05s; }
    .grid > .card:nth-child(3), .results > .card:nth-child(3) { animation-delay:.08s; }
    .grid > .card:nth-child(4), .results > .card:nth-child(4) { animation-delay:.11s; }
    .grid > .card:nth-child(5), .results > .card:nth-child(5) { animation-delay:.13s; }
    .grid > .card:nth-child(6), .results > .card:nth-child(6) { animation-delay:.15s; }
    .grid > .card:nth-child(n+7), .results > .card:nth-child(n+7) { animation-delay:.17s; }
    .rflag, .cflag, .rtier { animation:riseIn .3s ease both; animation-delay:.12s; }
}

/* ── cards: lift on hover, tinted with the brand rather than black ──────────*/
.card { transition:transform .16s ease, box-shadow .16s ease, border-color .16s ease; }
.grid > .card:hover, .results > .card:hover {
    transform:translateY(-2px);
    box-shadow:0 12px 28px -10px rgba(14,77,146,.32);
    border-color:color-mix(in srgb, var(--blue) 26%, var(--line));
}

/* ── the section kicker gets a small brand rule, so headings feel anchored ──*/
.kicker { position:relative; }
.dirhead .kicker::after, .page > .kicker::after {
    content:''; display:block; width:34px; height:2px; border-radius:2px;
    background:var(--blue); opacity:.55; margin:8px auto 0; }
.page > .kicker::after { margin-left:0; margin-right:auto; }
.dirhead .kicker::after { margin-left:auto; margin-right:auto; }

/* ── buttons: a touch of depth, and a real pressed state ───────────────────*/
.btn { transition:transform .12s ease, box-shadow .16s ease, filter .16s ease, background .16s ease; }
.btn-primary:hover { transform:translateY(-1px); box-shadow:0 10px 22px -8px rgba(14,77,146,.55); }
.btn:active { transform:translateY(0) scale(.985); }
.btn-ghost:hover { background:color-mix(in srgb, var(--blue) 7%, transparent); }

/* ── inputs: a calm focus ring in the brand colour, never the browser default */
.input { transition:border-color .15s ease, box-shadow .15s ease, background .15s ease; }
.input:focus, .input:focus-visible {
    outline:none; border-color:var(--blue);
    box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); }

/* ── keyboard users get a visible ring everywhere, matching the brand ───────*/
a:focus-visible, button:focus-visible, .mega-item:focus-visible, .homebtn:focus-visible {
    outline:2px solid var(--blue); outline-offset:2px; border-radius:8px; }

/* ── avatars: a whisper of a ring, stronger on hover ────────────────────────*/
.av, .rav { transition:box-shadow .16s ease, transform .16s ease; }
.grid > .card:hover .av, .results > .card:hover .rav {
    box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }

/* ── role badges + tier crests lift very slightly with their card ───────────*/
.badge { transition:transform .16s ease; }
.grid > .card:hover .badge { transform:translateY(-1px); }

/* ── section titles get a leading brand tick ────────────────────────────────*/
.sec-title { display:flex; align-items:center; gap:8px; }

/* ── links underline from the middle out, rather than snapping on ───────────*/
.page a:not(.btn):not(.mega-item):not(.rlink):not(.avlink):not(.namelink):not(.ravlink) {
    background-image:linear-gradient(var(--blue), var(--blue));
    background-size:0% 1.5px; background-position:50% 100%; background-repeat:no-repeat;
    transition:background-size .22s ease; padding-bottom:1px; }
.page a:not(.btn):not(.mega-item):not(.rlink):not(.avlink):not(.namelink):not(.ravlink):hover {
    background-size:100% 1.5px; }

/* ── the sticky header gains a hairline shadow once the page moves ──────────*/
.site-head { transition:box-shadow .2s ease, background .2s ease; }
.site-head.scrolled { box-shadow:0 6px 20px -12px rgba(14,34,51,.35); }

/* Defensive: if this stylesheet were ever missing or stale, an inline SVG next to text
   sits on the baseline and looks misaligned. Aligning it centrally costs nothing and means
   a degraded page still looks deliberate. (This is what the owner saw on 2026-08-20 when a
   cached stylesheet met fresh markup.) */
.site-nav a svg, .btn svg, .sec-title svg, .kicker svg { vertical-align:middle; }
.site-nav > a { display:inline-flex; align-items:center; gap:8px; }

/* T39 (30 Aug, hostile-user sweep): a single unbroken 1000-character string posted on the wall made the
   390px page 9,647px wide, and a 100-character court name overflowed the venue's court card. Member-typed
   text may never widen the page: break anywhere, only when it would otherwise overflow. Site-wide. */
.card, .card-pad, p, li, td, th, dd, strong, blockquote, .badge, [style*="pre-wrap"] { overflow-wrap: anywhere; }

/* ── A110: ATF Recognition chip (the federation's own award — distinct from earned crests) ── */
.arec{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;letter-spacing:.4px;
  text-transform:uppercase;padding:2px 9px;border-radius:20px;border:1px solid var(--arec,#b8860b);
  color:var(--arec,#b8860b);background:var(--arec-soft,rgba(184,134,11,.09));white-space:nowrap;max-width:100%}
.arec-dot{width:7px;height:7px;border-radius:50%;background:var(--arec,#b8860b);flex:none}
.arec-gold{--arec:#b8860b;--arec-soft:rgba(184,134,11,.10)}
.arec-silver{--arec:#6e7b8a;--arec-soft:rgba(110,123,138,.12)}
.arec-bronze{--arec:#9c5a2d;--arec-soft:rgba(156,90,45,.10)}
[data-theme="dark"] .arec-gold{--arec:#e6b84c;--arec-soft:rgba(230,184,76,.14)}
[data-theme="dark"] .arec-silver{--arec:#aab8c8;--arec-soft:rgba(170,184,200,.14)}
[data-theme="dark"] .arec-bronze{--arec:#d08a52;--arec-soft:rgba(208,138,82,.14)}

/* ════════════════════════════════════════════════════════════════════════════
   MOBILE SWEEP — the Owner's 390×844 / 360×740 pass (31 Aug). Every rule here is
   written against a CLASS, not a page: the same six defects appeared on 43 screens,
   so the fixes live in the kit and every screen moves at once. Desktop is untouched —
   each block is gated on a coarse pointer or a phone-width viewport.
   ════════════════════════════════════════════════════════════════════════════ */

/* Item 1 — mobile (31 Aug): the "?" guide panel anchors to the VIEWPORT, not to a 32px
   button sitting 228px into the header, which threw a third of it off-screen (left −112
   at 390, −113 at 360) with no way to scroll it back. Markup is in the SEALED _header.php,
   so this is CSS-only: fixed positioning makes the viewport the containing block. Both
   shells park their bar at ~57px, so 62px clears either one. */
@media (max-width:640px) {
    .guide-dd-menu { position:fixed; top:62px; left:8px; right:8px; width:auto; max-width:none;
        max-height:calc(100vh - 76px); overflow-y:auto; -webkit-overflow-scrolling:touch; }
    /* mobile (31 Aug, conference-path drive): the LANGUAGE menu had the same off-screen fault as the guide panel —
       measured x=-33 at 390px, 33px of every locale label cut off. The first control a Thai official touches. */
    .langdd-menu { position:fixed; top:62px; left:8px; right:8px; min-width:0; width:auto; max-height:calc(100vh - 76px); overflow-y:auto; }
}

/* Item 3 — mobile (31 Aug): a flex row of inputs cannot shrink below its content, so a pair
   of them ran off a 360 screen. The row wraps instead, and the dial drops its 96px cap once
   it owns the line. (The venue-settings field PAIRS now use .form-grid, the house standard,
   which already collapses to one column at 640 — see venue_settings.php.) */
@media (max-width:400px) {
    .input-group { flex-wrap:wrap; }
    .input-group .input.dial { max-width:none; }
}

/* Item 5 — mobile (31 Aug): ONE rule for touch targets. Measured: .btn 41px, .btn-sm 34–36,
   .iconbtn 32–36 — all under the 44px floor every touch guideline agrees on. Gated on
   (pointer:coarse) so a mouse-driven desktop keeps the tighter design exactly as it is.

   NB .iconbtn takes size but NOT display: `.burger` is an .iconbtn whose display is a
   responsive STATE, and a blanket inline-flex here would re-show it on a touch laptop.

   THE HEADER IS AN EXCEPTION — header icons stay 32px. The bar is locked at 56px and its
   flex row does not wrap (see "Mobile header: nothing may wrap", app.css:549-559): at 360px
   logged-in it already carries logo + language + theme + guide + notifications + logout +
   burger, so forcing each to 44px WIDE would overflow the row it cannot wrap out of. The
   44px floor applies everywhere else. This is a real trade-off, not an oversight: the
   header's own ≤620px rule keeps those targets small, and only the Owner can decide to
   spend header width on bigger ones. */
@media (pointer:coarse) {
    .btn, .btn-sm, .langdd-btn, .btn-link, .link-action { min-height:44px; }
    .btn, .btn-sm, .langdd-btn { align-items:center; justify-content:center; }
    .btn-link, .link-action { align-items:center; }
    .iconbtn { min-height:44px; min-width:44px; }          /* icon-only: square, so width too */
    .iconbtn:not(.burger) { align-items:center; justify-content:center; }
    .fav-btn, a.fav-btn { min-height:44px; min-width:44px; }

    /* a table row must not grow by 44px per cell — the link keeps its own line box there */
    td .link-action, td .btn-link { min-height:auto; }

    /* the header exception, stated last so it wins on order as well as specificity */
    .site-head .iconbtn, .site-head .btn, .site-head .langdd-btn {
        min-height:auto; min-width:auto; }
}

/* Item 6 — mobile (31 Aug): type floors. .badge rendered 11.5px (×247 on /find-court),
   .kicker 10.6px (×92), .btn-sm 13.1px (×180) — all below the 14px readable floor on a
   phone. Applies on a touch device OR any phone-width viewport, since small type is a
   reading problem, not a pointing one. */
@media (pointer:coarse), (max-width:640px) {
    .badge { font-size:.78rem; }
    .kicker { font-size:.72rem; }
    .btn-sm { font-size:.88rem; }
}

/* Item 8 — mobile (31 Aug): a native 13×13 tick is not a touch target. .check-inline makes
   the whole label the target. A class, so every composer and filter that needs an inline
   checkbox gets it — not a one-off on the wall.
   The BASE is desktop-neutral: layout only, no sizing, so a mouse-driven page looks exactly
   as it did. The 20px box and the 44px tap box are enlargements, so they live under the same
   coarse/phone gate as the rest of the sweep (review 31 Aug — this was ungated). */
.check-inline { display:inline-flex; align-items:center; gap:10px; font-size:.85rem;
    cursor:pointer; line-height:1.4; }
.check-inline input[type="checkbox"] { flex:0 0 auto; margin:0;
    accent-color:var(--blue); cursor:pointer; }
@media (pointer:coarse), (max-width:640px) {
    /* min-height, not padding alone: the tap box must clear 44px whatever the label wraps to */
    .check-inline { min-height:44px; padding:6px 2px; }
    .check-inline input[type="checkbox"] { width:20px; height:20px; }
}

/* ── A116 (Owner, 31 Aug): ONE anatomy per card row — no dynamic displacement, anywhere.
   The name block is a fixed two-line slot and the ATF-chip slot reserves its height even
   when empty, so name / chip / location / rating land at identical heights across a row. ── */
.rnamerow { min-height: 44px; align-items: flex-start; }
.arec-slot { height: 24px; display: flex; align-items: center; margin: 2px 0 2px; }
.arec-slot:empty { visibility: hidden; }
