/* =============================================================================
   Matthew House - Check-in Kiosk. Surface rebuilt to Matthew_House_Kiosk.html
   (REBUILD-06). Brand tokens re-stated locally so the kiosk is independent of
   .mh-app. App fonts per the standing ruling (Hanken), NOT the mock's Urbanist.
   Responsive full-screen (flex), not the mock's fixed 1920x1080 scale canvas.
   ============================================================================= */
/* Full-viewport backdrop behind the scaled stage. Fills the letterbox bands (when the
   screen aspect differs from 16:9) with the kiosk paper colour so the fit looks seamless. */
.kioskbg {
    position:fixed; inset:0; z-index:999;
    background:
        radial-gradient(80% 70% at 88% -8%, rgba(120,150,140,.06) 0%, transparent 55%),
        radial-gradient(70% 60% at -6% 108%, rgba(94,122,131,.07) 0%, transparent 55%),
        #E8EBF0;
}

/* SCALE-TO-FIT STAGE ("back engine for resolution"): the kiosk is authored on a fixed
   1920x1080 canvas (matches the mock) and scaled uniformly by --kfit (set in kiosk.js =
   min(vw/1920, vh/1080)) to fill ANY screen without cropping or overflow. This restores
   the mock's scale-canvas behaviour the responsive port had dropped, so the kiosk looks
   identical and correctly proportioned on every laptop/monitor. The transform also makes
   this element the containing block for the fixed overlays inside it (.koverlay/.kunavail),
   so confirmation cards and the unavailable screen scale WITH the stage. */
.kioskroot {
    --teal:#5E7A83; --teal-deep:#4E7C72; --teal-700:#3D655D;
    --slate-900:#2E4A43; --slate-850:#284039; --slate-800:#32514A;
    /* DE-CREAMED (CEO, Jul 29 2026). The three ink tokens were olive-warm - #2A2F31 / #5B5C54 /
       #8A8B83 - which is what put a cream cast over every line of text on this screen even
       though the paper behind it was already cool. They are now the WIZARD's own ink ramp
       (--ink-1/2/3 in enroll-wizard.css), so the kiosk and the wizards read as one product.
       Side benefit on a public screen: both muted tones got darker, so they carry further. */
    --ink:#1C2733; --ink-soft:#3B474B; --ink-faint:#677579;
    --paper:#E8EBF0; --paper-2:#F1F4F7; --card:#FFFFFF; --line:#D9DFE7; --line-soft:#E3E8EE;
    --clay:#C97B5A; --green:#4E7C72; --amber:#D89B3D; --red:#B0463C;
    --font:'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif;
    --r-sm:10px; --r-md:14px; --r-lg:22px; --r-xl:30px;
    --sh-1:0 1px 2px rgba(33,50,58,.06), 0 1px 1px rgba(33,50,58,.04);
    --sh-2:0 10px 30px rgba(33,50,58,.10), 0 2px 6px rgba(33,50,58,.06);
    --sh-3:0 40px 90px rgba(33,50,58,.32);
    position:fixed; left:50%; top:50%;
    width:1920px; height:1080px;
    transform:translate(-50%,-50%) scale(var(--kfit,1));
    transform-origin:center center;
    z-index:1000;
    font-family:var(--font); color:var(--ink);
    display:flex; flex-direction:column; overflow:hidden;
    background:
        radial-gradient(80% 70% at 88% -8%, rgba(120,150,140,.06) 0%, transparent 55%),
        radial-gradient(70% 60% at -6% 108%, rgba(94,122,131,.07) 0%, transparent 55%),
        var(--paper);
}
.kioskroot svg { display:block; }

/* ===== header ===== */
.kioskroot .khead { position:relative; z-index:3; display:flex; align-items:center; justify-content:space-between; padding:32px 56px 0; gap:24px; }
.kioskroot .lockup { display:flex; align-items:center; gap:20px; }
.kioskroot .lockup .mk { width:76px; height:76px; border-radius:22px; background:linear-gradient(180deg,#6E948A,#4E7C72); display:grid; place-items:center; box-shadow:0 14px 30px rgba(61,101,93,.35); }
.kioskroot .lockup .mk img { width:46px; height:46px; }
.kioskroot .lockup .wm .ey { font-size:14px; letter-spacing:.26em; text-transform:uppercase; color:var(--teal-700); font-weight:700; }
.kioskroot .clock { display:flex; align-items:center; gap:24px; background:#fff; border:1.5px solid var(--line); border-radius:20px; padding:16px 30px; box-shadow:var(--sh-1); }
.kioskroot .clock .dt { text-align:right; }
.kioskroot .clock .dt .d { font-size:18px; font-weight:700; color:var(--ink); }
.kioskroot .clock .dt .wk { font-size:13px; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-faint); font-weight:700; margin-top:3px; }
.kioskroot .clock .sep { width:1.5px; height:44px; background:var(--line); }
.kioskroot .clock .tm { font-size:38px; font-weight:700; color:var(--slate-900); font-variant-numeric:tabular-nums; letter-spacing:.01em; min-width:210px; text-align:right; }

/* ===== body ===== */
.kioskroot .kbody { position:relative; z-index:2; flex:1; min-height:0; display:grid; grid-template-columns:1.32fr 1fr; gap:30px; padding:30px 56px 0; }
.kioskroot .col { display:flex; flex-direction:column; gap:24px; min-height:0; }

/* class card */
.kioskroot .classcard { background:#fff; border:1.5px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--sh-2); overflow:hidden; flex:0 0 auto; }
.kioskroot .cc-band { display:flex; align-items:center; gap:14px; padding:18px 26px; border-bottom:1.5px solid var(--line-soft); }
.kioskroot .cc-band .tag { font-size:14px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:var(--teal-700); }
.kioskroot .cc-band .dot { width:9px; height:9px; border-radius:50%; background:var(--green); box-shadow:0 0 0 5px rgba(78,124,114,.18); }
.kioskroot .cc-body { padding:26px 28px 28px; }
/* Uppercase headline + class names (CEO, Jul 29 2026). letter-spacing goes POSITIVE for
   uppercase - the -.02em tracking was tuned for sentence case and pinches capitals together. */
.kioskroot .noclass .nc-h { font-size:42px; font-weight:800; color:var(--slate-900); letter-spacing:.01em; text-transform:uppercase; }
.kioskroot .noclass .nc-s { font-size:19px; color:var(--ink-soft); margin-top:12px; line-height:1.5; max-width:34ch; }
.kioskroot .sched .s-time { display:flex; align-items:baseline; gap:14px; }
.kioskroot .sched .s-time .t { font-size:42px; font-weight:800; color:var(--slate-900); letter-spacing:-.02em; }
.kioskroot .sched .s-time .ampm { font-size:22px; font-weight:700; color:var(--ink-soft); }
/* Covers BOTH the single-class name and the "N CLASSES RUNNING" headline. */
.kioskroot .sched .s-name { font-size:25px; font-weight:700; color:var(--ink); margin-top:8px; text-transform:uppercase; letter-spacing:.02em; }
/* The multi-class variant leads with its headline, so it gets the headline's weight and size
   instead of the 25px class-name treatment. */
.kioskroot .sched.multi .s-name { font-size:38px; font-weight:800; color:var(--slate-900); margin-top:0; letter-spacing:.01em; }
/* ONE class at a time, on a 4s loop. The slot is a FIXED height so the card cannot resize as
   longer and shorter class names come round. */
.kioskroot .cc-rotator { margin-top:18px; height:52px; position:relative; }
.kioskroot .cc-rotator .cc-cl { position:absolute; inset:0; animation:ccFade 4s ease-in-out both; }
/* Sequential, NOT a cross-fade: up by 12%, hold, out by 88%. Only one string is ever painted,
   because @key replaces the node - so two class names can never overlap mid-transition. */
@keyframes ccFade {
    0%   { opacity:0; transform:translateY(8px); }
    12%  { opacity:1; transform:none; }
    88%  { opacity:1; transform:none; }
    100% { opacity:0; transform:translateY(-8px); }
}
@media (prefers-reduced-motion:reduce) {
    .kioskroot .cc-rotator .cc-cl { animation:none; opacity:1; transform:none; }
}
/* which of the N classes is showing */
.kioskroot .cc-dots { display:flex; gap:7px; margin-top:14px; }
.kioskroot .cc-pip { width:7px; height:7px; border-radius:50%; background:rgba(78,124,114,.22); transition:background .25s; }
.kioskroot .cc-pip.on { background:var(--green); }
.kioskroot .cc-cl { display:flex; align-items:center; gap:12px; padding:12px 16px; border-radius:14px;
    background:rgba(78,124,114,.07); border:1px solid rgba(78,124,114,.16); }
.kioskroot .cc-cl-dot { width:9px; height:9px; border-radius:50%; background:var(--green); flex:0 0 auto;
    box-shadow:0 0 0 4px rgba(78,124,114,.16); }
.kioskroot .cc-cl-n { flex:1; min-width:0; font-size:19px; font-weight:800; color:var(--slate-900);
    text-transform:uppercase; letter-spacing:.02em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.kioskroot .cc-cl-t { font-size:15px; font-weight:700; color:var(--teal-700); flex:0 0 auto; }
.kioskroot .sched .s-meta { display:flex; gap:26px; margin-top:16px; flex-wrap:wrap; }
.kioskroot .sched .s-meta .m { display:flex; align-items:center; gap:10px; font-size:16px; color:var(--ink-soft); font-weight:600; }
.kioskroot .sched .s-meta .m svg { width:20px; height:20px; color:var(--teal-700); }

/* scan zone (dark pine) */
.kioskroot .scan { flex:1; min-height:0; border-radius:var(--r-lg); position:relative; overflow:hidden;
    background:linear-gradient(165deg,#2E4A43 0%,#213A33 60%,#19302B 100%);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    cursor:pointer; border:1.5px solid rgba(255,255,255,.06); box-shadow:var(--sh-2); }
.kioskroot .scan.closed { cursor:default; }
.kioskroot .scan::before { content:""; position:absolute; inset:0; opacity:.5;
    background-image:radial-gradient(rgba(255,255,255,.05) 1px,transparent 1px); background-size:30px 30px; }
/* The two static .arc circles were REMOVED from the markup (CEO, Jul 29 2026) - they never
   animated, unlike the ring's own ::before/::after pulse, so they were just decoration
   crowding the panel. Their rules go with them. */
.kioskroot .scan .ring { position:relative; width:150px; height:150px; border-radius:50%; display:grid; place-items:center;
    background:radial-gradient(circle at 50% 38%, rgba(120,150,140,.35),rgba(120,150,140,.06)); box-shadow:0 0 0 2px rgba(120,150,140,.25) inset; }
.kioskroot .scan .ring::after { content:""; position:absolute; inset:-22px; border-radius:50%; border:2px solid rgba(120,150,140,.45); animation:kpulse 2.4s ease-out infinite; }
.kioskroot .scan .ring::before { content:""; position:absolute; inset:-22px; border-radius:50%; border:2px solid rgba(120,150,140,.30); animation:kpulse 2.4s ease-out infinite .9s; }
@keyframes kpulse { 0%{transform:scale(.78);opacity:.9;} 100%{transform:scale(1.55);opacity:0;} }
.kioskroot .scan .ring svg { width:74px; height:74px; color:#CFE0D9; }
/* THE MATTHEW HOUSE QR, sitting inside the ring like the code on a member card. White tile
   because a QR needs its quiet zone to read as a QR; rounded to echo the pass. The SvgPine
   output carries its own white ground, so the tile just clips it to the radius. */
/* Slightly smaller, and PADDED (CEO, Jul 30 2026): the code used to run edge to edge of its
   white tile, which both looked wrong and eats the quiet zone a decoder needs. 104 -> 96 with
   9px of white around it. `position:relative` is what the centred logo mark anchors to. */
.kioskroot .scan .ring .qr-tile { width:96px; height:96px; border-radius:16px; overflow:hidden;
    background:#fff; display:block; padding:5px;/* QRFILL29: was 9px */ position:relative; line-height:0;
    box-shadow:0 6px 18px rgba(0,0,0,.28); }
.kioskroot .scan .ring .qr-tile svg { width:100%; height:100%; display:block; }
/* The pine logo mark, centred - the canonical MH tile, same construction as .sum-qr in
   detail-view.css. Level-H error correction is what lets it sit on top and still decode.
   pointer-events:none so it can never eat a tap meant for the panel. */
.kioskroot .scan .ring .qr-tile .qr-logo { position:absolute; inset:0; margin:auto; width:26px; height:26px;
    border-radius:8px; background:#2E4A43; display:grid; place-items:center; pointer-events:none;
    box-shadow:0 0 0 3px #fff; }
.kioskroot .scan .ring .qr-tile .qr-logo img { width:17px; height:17px; display:block; object-fit:contain; }
/* reader-missing state: the panel is live (a class IS running) but nothing can be read */
.kioskroot .scan.noreader .ring svg { color:#E8B4A0; }
.kioskroot .scan.noreader .st { color:#F0C9B8; }
/* The padlock was #E6C98A - cream gold, and the single most visible warm thing on the
   kiosk. Cool slate now: still clearly "inactive" against the live icon, no cream. */
.kioskroot .scan.closed .ring svg { color:#9FB6BE; }
.kioskroot .scan .st { position:relative; z-index:2; font-size:38px; font-weight:800; color:#fff; letter-spacing:-.02em; margin-top:40px; text-align:center; padding:0 20px; }
.kioskroot .scan .ss { position:relative; z-index:2; font-size:19px; color:rgba(205,216,219,.78); margin-top:14px; font-weight:500; text-align:center; padding:0 20px; }
.kioskroot .scan .badge { position:absolute; bottom:30px; display:flex; align-items:center; gap:10px; font-size:14px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:#8FB3A8; }
.kioskroot .scan .badge .bd { width:8px; height:8px; border-radius:50%; background:#8FB3A8; animation:kblink 1.6s ease-in-out infinite; }
@keyframes kblink { 0%,100%{opacity:.3;} 50%{opacity:1;} }
.kioskroot .scan.bad { animation:kbadflash .5s ease; }
@keyframes kbadflash { 0%,100%{box-shadow:var(--sh-2);} 50%{box-shadow:0 0 0 5px rgba(176,70,60,.55);} }

/* recent check-ins */
.kioskroot .listcard { flex:1; min-height:0; background:#fff; border:1.5px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--sh-2); display:flex; flex-direction:column; overflow:hidden; }
.kioskroot .lc-head { display:flex; align-items:center; justify-content:space-between; padding:20px 24px 16px; border-bottom:1.5px solid var(--line-soft); }
/* Uppercase, per the standing kiosk heading/button ruling (CEO, Jul 29 2026). */
.kioskroot .lc-head h3 { font-size:24px; font-weight:800; color:var(--slate-900); text-transform:uppercase; letter-spacing:.03em; }
/* TODAY lines up with the IN / OUT badges beneath it (CEO, Jul 30 2026). The header is
   space-between so the pill sat hard against the card edge, 66px right of the badge column -
   which is exactly the width the entry rows give their points column (50px) plus the 16px
   flex gap. Reserving that same 66px here puts the two right edges on one line. */
.kioskroot .lc-head .cnt { font-size:14px; font-weight:700; color:var(--teal-700); background:rgba(120,150,140,.14);
    padding:6px 14px; border-radius:30px; margin-right:66px; text-transform:uppercase; letter-spacing:.06em; }
.kioskroot .listbox { flex:1; min-height:0; overflow:auto; }
.kioskroot .lb-empty { padding:40px 26px; color:var(--ink-faint); font-size:17px; font-weight:600; text-align:center; }
.kioskroot .entry { display:flex; align-items:center; gap:16px; padding:16px 24px; border-bottom:1px solid var(--line-soft); }
/* The zebra stripe was rgba(246,244,239,.5) - CREAM, the same warm family as the scroll thumb
   the CEO called out. Swapped for the kiosk's own cool --paper-2 tint so the strip belongs to
   the de-creamed palette. Not asked for; it was the last warm surface left on this panel. */
.kioskroot .entry:nth-child(odd) { background:rgba(241,244,247,.75); }
.kioskroot .entry .av { width:52px; height:52px; border-radius:15px; display:grid; place-items:center; font-weight:800; font-size:18px; color:#fff; flex:0 0 auto; }
.kioskroot .entry .who { flex:1; min-width:0; }
.kioskroot .entry .who .n { font-size:19px; font-weight:700; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.kioskroot .entry .who .t { font-size:14px; color:var(--ink-faint); font-weight:600; margin-top:3px; }
/* WHICH class this check-in belongs to. Rendered only while more than one class is running,
   and styled as the same quiet teal pill the manual list uses, so "which class" looks the
   same wherever the kiosk has to say it. */
.kioskroot .entry .who .t .ent-cls { display:inline-block; margin-left:9px; padding:1px 9px; border-radius:999px;
    background:rgba(78,124,114,.12); color:var(--teal-700); font-weight:800; font-size:12px; }
.kioskroot .entry .stat { font-size:13px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; padding:6px 0; border-radius:9px; width:52px; text-align:center; flex:0 0 auto; }
.kioskroot .entry .stat.in { background:rgba(78,124,114,.15); color:#3D655D; }
.kioskroot .entry .stat.out { background:rgba(201,123,90,.16); color:#B5663F; }
.kioskroot .entry .pts { font-size:16px; font-weight:800; color:var(--green); min-width:50px; text-align:right; }

/* ===== actions ===== */
.kioskroot .actions { position:relative; z-index:2; display:grid; grid-template-columns:repeat(3,1fr); gap:24px; padding:26px 56px 40px; }
/* ALL THREE ACTIONS ARE UPPERCASE (CEO, Jul 29 2026). Done here rather than by rewriting
   the labels, so the markup keeps its readable sentence case. The small letter-spacing is
   what stops uppercase at 23px from looking cramped. */
.kioskroot .act { height:96px; border-radius:var(--r-lg); display:flex; align-items:center; justify-content:center; gap:16px; font-family:var(--font); font-size:23px; font-weight:700; text-transform:uppercase; letter-spacing:.03em; cursor:pointer; transition:transform .12s ease, box-shadow .15s; }
.kioskroot .act:active { transform:translateY(2px); }
.kioskroot .act svg { width:28px; height:28px; }
.kioskroot .act.ghost { background:#fff; border:1.5px solid var(--line); color:var(--slate-900); box-shadow:var(--sh-1); }
.kioskroot .act.ghost:hover { border-color:var(--teal); box-shadow:var(--sh-2); }
.kioskroot .act.ghost .ic { color:var(--teal-700); display:inline-flex; }
.kioskroot .act.primary { background:linear-gradient(180deg,#32514A,#2E4A43); color:#fff; box-shadow:0 14px 30px rgba(33,50,58,.30); border:1.5px solid rgba(255,255,255,.05); }
/* margin-RIGHT now: the padlock moved in front of the label, so the nudge has to move with
   it or the gap lands on the wrong side of the glyph. */
.kioskroot .act.primary .lockico { margin-right:4px; color:rgba(205,216,219,.65); display:inline-flex; }

/* ===== parked-station refusal ===== */
.kioskroot .kunavail { position:fixed; inset:0; z-index:1200; display:grid; place-items:center; padding:32px;
    background:
        radial-gradient(80% 70% at 88% -8%, rgba(120,150,140,.06) 0%, transparent 55%),
        radial-gradient(70% 60% at -6% 108%, rgba(94,122,131,.07) 0%, transparent 55%),
        var(--paper); }
.kioskroot .kunavail-card { max-width:560px; width:92%; text-align:center; background:var(--card); border:1.5px solid var(--line);
    border-radius:26px; box-shadow:0 40px 90px rgba(33,50,58,.24); padding:48px 56px; animation:kpop .2s ease; }
.kioskroot .kunavail-mk { width:76px; height:76px; margin:0 auto 22px; border-radius:22px; display:grid; place-items:center;
    background:var(--paper-2); border:1px solid var(--line); }
.kioskroot .kunavail-mk img { width:44px; height:44px; object-fit:contain; }
.kioskroot .kunavail-card h1 { margin:0 0 12px; font-size:30px; font-weight:800; letter-spacing:-.02em; color:var(--slate-900); }
.kioskroot .kunavail-card p { margin:0; font-size:17px; line-height:1.55; color:var(--ink-soft); }
.kioskroot .kunavail-note { margin-top:22px; font-size:13px; font-weight:700; color:var(--ink-faint);
    background:var(--paper-2); border:1px solid var(--line); border-radius:12px; padding:10px 14px; }

/* hidden reader capture */
.kioskroot .kscanfield { position:absolute; left:-9999px; top:0; width:1px; height:1px; opacity:0; }

/* ===== overlays ===== */
.kioskroot .koverlay { position:fixed; inset:0; z-index:1100; display:grid; place-items:center; padding:24px;
    background:rgba(20,30,35,.55); backdrop-filter:blur(7px); -webkit-backdrop-filter:blur(7px); }
@keyframes kpop { from{opacity:0; transform:translateY(14px) scale(.98)} to{opacity:1; transform:none} }
@keyframes krise { from{opacity:0; transform:translateY(18px) scale(.985)} to{opacity:1; transform:none} }

/* confirmation card */
.kioskroot .confirm { background:#fff; border-radius:var(--r-xl); box-shadow:var(--sh-3); overflow:hidden; display:flex; position:relative; animation:krise .4s cubic-bezier(.2,.8,.2,1); width:1180px; max-width:1760px; }
.kioskroot .confirm .statusrail { width:14px; flex:0 0 auto; background:var(--green); }
.kioskroot .confirm.out .statusrail { background:var(--clay); }
/* THE PANEL RULER. This was var(--amber) #D89B3D - gold, and it is the creamy vertical rail
   the CEO kept seeing down the left edge of Check My Points. Cool slate now, so every panel
   rail on the kiosk is either brand green (an action) or slate (a lookup). --amber itself is
   left defined: the gift-card face still uses that gold deliberately. */
.kioskroot .confirm .statusrail.amber { background:var(--teal); }
/* BIGGER PORTRAIT (CEO, Jul 29 2026): 290x340 -> 380x460, so someone standing at the kiosk
   can actually recognise themselves. The column widened with it (340 -> 430) or the frame
   would have overflowed its own grid cell; the card is 1180px wide and the detail side keeps
   the 1fr remainder. Still a rectangle - that was already right, it was just too small. */
.kioskroot .confirm .inner { flex:1; display:grid; grid-template-columns:430px 1fr; gap:0; min-width:0; }
.kioskroot .photoside { padding:44px 0 44px 44px; display:flex; flex-direction:column; align-items:center; gap:20px; }
.kioskroot .photobox { width:380px; height:460px; border-radius:var(--r-lg); overflow:hidden; position:relative;
    background:linear-gradient(160deg,#DFE4EA,#CFD7E0); border:1.5px solid var(--line); display:grid; place-items:center; box-shadow:var(--sh-1); }
.kioskroot .photobox svg { width:112px; height:112px; color:#9AA7B3; }
/* A REAL photo fills the frame. object-fit:cover is what keeps a portrait or a landscape
   snapshot from being stretched into the 380x460 box; `display:block` kills the inline
   baseline gap that would otherwise show a hairline of the placeholder gradient underneath.
   .has drops the placeholder gradient so a transparent PNG does not sit on beige. */
.kioskroot .photobox.has { background:#0E1512; }
.kioskroot .photobox img { width:100%; height:100%; object-fit:cover; display:block; }
.kioskroot .photobox .ph-tag { position:absolute; bottom:14px; left:0; right:0; text-align:center; font-family:'IBM Plex Mono',monospace; font-size:12px; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-faint); }
.kioskroot .photoside .pid { font-size:15px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-faint); }
.kioskroot .detail { padding:46px 52px 44px 40px; display:flex; flex-direction:column; min-width:0; }
.kioskroot .detail .status { display:flex; align-items:center; gap:18px; }
.kioskroot .detail .status .badge { display:flex; align-items:center; gap:13px; padding:12px 22px; border-radius:16px; font-size:36px; font-weight:800; letter-spacing:-.02em; white-space:nowrap; }
.kioskroot .detail .status .badge.in { background:rgba(78,124,114,.13); color:#3D655D; }
.kioskroot .detail .status .badge.out { background:rgba(201,123,90,.15); color:#B5663F; }
.kioskroot .detail .status .badge svg { width:38px; height:38px; }
.kioskroot .detail .cname { font-size:50px; font-weight:800; color:var(--slate-900); letter-spacing:-.025em; margin-top:24px; line-height:1.05; }
.kioskroot .detail .ctime { font-size:22px; color:var(--ink-soft); font-weight:600; margin-top:14px; display:flex; align-items:center; gap:11px; }
.kioskroot .detail .ctime svg { width:24px; height:24px; color:var(--teal-700); flex:0 0 auto; }
.kioskroot .detail .points { display:inline-flex; align-items:center; gap:12px; align-self:flex-start; margin-top:22px; padding:14px 24px; border-radius:18px; background:linear-gradient(180deg,rgba(78,124,114,.16),rgba(78,124,114,.10)); border:1.5px solid rgba(78,124,114,.28); }
.kioskroot .detail .points .lab { font-size:18px; font-weight:700; color:#3D655D; }
.kioskroot .detail .points .val { font-size:32px; font-weight:800; color:#3D655D; }
.kioskroot .detail .points.muted { background:var(--paper-2); border-color:var(--line); }
.kioskroot .detail .points.muted .lab { color:var(--ink-soft); }
.kioskroot .giftrow { display:flex; align-items:center; gap:24px; margin-top:auto; padding-top:30px; }
/* THE TWO LABELS WERE PAINTED ON TOP OF EACH OTHER (CEO, Jul 30 2026 - "no texts are mixed
   with each other"). Both were absolutely positioned onto the SAME baseline of a fixed 220px
   card: "Reward Card" from left:20 ran to about x=150 at 22px/800, while "Gift ready" from
   right:20 started at about x=125 - so roughly 25px of the two strings were drawn over one
   another and it read as garbled text. Nothing about that depended on the data; it was wrong
   at every width, which is why it was visible on the very first eligible check-in.
   They are now IN FLOW, stacked, in a column the card lays out: gc-top on top, the label and
   its caption pushed to the bottom by margin-top:auto. Two strings on one line inside a card
   this narrow can only be made safe by not putting them on one line. */
.kioskroot .giftcard { width:220px; height:142px; border-radius:18px; flex:0 0 auto; position:relative; overflow:hidden;
    display:flex; flex-direction:column;
    background:linear-gradient(145deg,#D6AD3C 0%,#C49A33 48%,#A98322 100%); box-shadow:0 16px 32px rgba(169,131,34,.32); padding:20px; color:#3a2e08; }
.kioskroot .giftcard .gc-top { display:flex; align-items:center; justify-content:space-between; flex:none; }
.kioskroot .giftcard .gc-chip { width:42px; height:30px; border-radius:6px; background:rgba(255,255,255,.45); }
.kioskroot .giftcard .gc-mark { width:30px; height:30px; border-radius:50%; background:rgba(255,255,255,.35); display:grid; place-items:center; }
.kioskroot .giftcard .gc-mark svg { width:18px; height:18px; color:#3a2e08; }
.kioskroot .giftcard .gc-label { margin-top:auto; font-weight:800; font-size:22px; letter-spacing:.02em; line-height:1.15;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.kioskroot .giftcard .gc-sub { margin-top:3px; font-size:13px; font-weight:700; letter-spacing:.1em; opacity:.7; line-height:1.15;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.kioskroot .gifttext { flex:1; min-width:0; }
.kioskroot .gifttext .gt-h { font-size:21px; font-weight:800; color:var(--ink); }
.kioskroot .gifttext .gt-p { font-size:16px; color:var(--ink-soft); line-height:1.5; margin-top:7px; max-width:34ch; }
.kioskroot .confirm-foot { position:absolute; bottom:0; left:14px; right:0; height:8px; background:var(--line-soft); }
.kioskroot .confirm-foot .bar { height:100%; background:var(--green); width:100%; }
.kioskroot .confirm.out .confirm-foot .bar { background:var(--clay); }
/* 5s, matching DismissSecs in Kiosk.razor (CEO, Jul 29 2026). This was 6s and is the FOURTH
   place the old duration was written down - the bar would have emptied a second after the card
   had already gone, which reads as the animation being broken. If DismissSecs ever changes,
   this is the one value that has to change with it (CSS cannot read the C# const). */
.kioskroot .confirm-foot .bar.kbar { animation:kbarShrink 5s linear forwards; }
@keyframes kbarShrink { from{width:100%} to{width:0} }
/* The countdown sat at bottom:24px with the 8px bar at bottom:0, and the card's own content
   ran right up under it - so "Returning in 5 ..." collided with the last row and its ellipsis
   clipped on the rounded corner (CEO, Jul 30 2026). It now sits clear of the bar with real
   margin, and the cards that host it carry bottom padding to reserve the strip. */
.kioskroot .returning { position:absolute; right:40px; bottom:30px; font-size:16px; font-weight:700; color:var(--ink-faint); display:flex; align-items:center; gap:9px; white-space:nowrap; }
.kioskroot .returning .num { font-size:20px; color:var(--slate-900); font-variant-numeric:tabular-nums; }

/* block / message card (not found, closed) */
.kioskroot .confirm.blockcard { width:680px; flex-direction:column; text-align:center; padding:50px 52px 54px; align-items:center; }
.kioskroot .block-ic { width:86px; height:86px; border-radius:50%; background:rgba(201,123,90,.16); color:var(--clay); display:grid; place-items:center; font-size:48px; font-weight:800; margin-bottom:18px; }
.kioskroot .confirm.blockcard h2 { font-size:38px; font-weight:800; color:var(--slate-900); }
.kioskroot .confirm.blockcard p { font-size:19px; color:var(--ink-soft); max-width:460px; margin:12px auto 0; line-height:1.5; }
/* FIX 1: access block - the person's name sits between the neutral headline and the see-staff line. */
.kioskroot .confirm.blockcard .block-ic svg { width:44px; height:44px; }
/* A refused check-in: the lock is RED so the person sees at a glance something needs a staff member (owner, 28 Sep). The late card keeps its clay clock below. */
.kioskroot .confirm.blockcard.access .block-ic { background:rgba(192,57,43,.12); color:#C0392B; box-shadow:0 0 0 6px rgba(192,57,43,.06); }
.kioskroot .confirm.blockcard .blk-name { font-size:30px; font-weight:800; color:var(--slate-900); margin-top:8px; letter-spacing:-.01em; }

/* LATE-CHECKIN-01 (Aug 9 2026): the too-late refusal.
   The icon turns CLAY (a clock, not a padlock) because this is a timing problem, not an
   access problem - the padlock's teal "nothing is wrong with your record" reading would be
   the wrong reassurance when the answer is "you are late". */
.kioskroot .confirm.blockcard.late .block-ic { background:rgba(201,123,90,.16); color:var(--clay); }
/* Their real balance, stated the same way the My Points card states it: a number and the
   word "points", and nothing at all about rewards or eligibility. */
.kioskroot .confirm.blockcard .blk-points { margin-top:22px; display:flex; align-items:baseline; justify-content:center; gap:10px; }
.kioskroot .confirm.blockcard .blk-points .bp-n { font-size:64px; font-weight:800; line-height:1; color:var(--slate-900); font-variant-numeric:tabular-nums; }
.kioskroot .confirm.blockcard .blk-points .bp-l { font-size:20px; font-weight:700; color:var(--ink-soft); }

/* FIX 4: family (multi-member) check-in overlay */
.kioskroot .confirm.famcard { width:760px; flex-direction:column; }
/* padding-bottom reserves the strip the absolute countdown + progress bar live in, so the
   card's content can no longer run under "Returning in N ..." (CEO, Jul 30 2026). */
.kioskroot .fam-inner { flex:1; padding:40px 46px 78px; display:flex; flex-direction:column; min-width:0; }

/* ===== family DONE card: the adult big, their kids in a row underneath ===== */
.kioskroot .fam-shot { margin-top:22px; display:flex; flex-direction:column; align-items:center; gap:24px; }
.kioskroot .fs-adult { display:flex; flex-direction:column; align-items:center; gap:12px; }
/* Reuses .photobox (frame, placeholder gradient, object-fit:cover on a real photo) at the size
   this card can afford - the single-person confirm is 380x460, this shares a row with kids. */
.kioskroot .fs-photo { width:220px; height:266px; }
.kioskroot .fs-name { font-size:30px; font-weight:800; color:var(--slate-900); letter-spacing:.01em; text-align:center; }
.kioskroot .fs-role { font-size:16px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--teal-700); }
.kioskroot .fs-kids { width:100%; border-top:1.5px solid var(--line-soft); padding-top:20px; }
.kioskroot .fs-kids-h { font-size:14px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-faint); text-align:center; margin-bottom:16px; }
/* ONE ROW. Scrolls sideways rather than wrapping, so four kids never push the card taller than
   the screen; the scrollbar is hidden because nobody drags on a kiosk - they just see them. */
.kioskroot .fs-kidrow { display:flex; gap:18px; justify-content:center; overflow-x:auto; padding-bottom:4px;
    scrollbar-width:none; -ms-overflow-style:none; }
.kioskroot .fs-kidrow::-webkit-scrollbar { width:0; height:0; display:none; }
.kioskroot .fs-kid { flex:0 0 auto; width:112px; display:flex; flex-direction:column; align-items:center; gap:9px; }
.kioskroot .fs-kidphoto { width:112px; height:134px; }
.kioskroot .fs-kidname { font-size:16px; font-weight:700; color:var(--ink); text-align:center; width:100%;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* ===== staff panel: reader status ===== */
.kioskroot .ss-reader { display:flex; align-items:center; gap:14px; border:1.5px solid var(--line);
    border-radius:18px; padding:18px 20px; margin:20px 0 0; background:var(--paper-2); }
.kioskroot .ss-reader .ss-rdot { width:11px; height:11px; border-radius:50%; flex:0 0 auto; }
.kioskroot .ss-reader.ok .ss-rdot { background:var(--green); box-shadow:0 0 0 5px rgba(78,124,114,.18); }
.kioskroot .ss-reader.bad { border-color:rgba(201,123,90,.45); background:rgba(201,123,90,.07); }
.kioskroot .ss-reader.bad .ss-rdot { background:var(--clay); box-shadow:0 0 0 5px rgba(201,123,90,.20); }
.kioskroot .fam-head { display:flex; align-items:center; justify-content:space-between; gap:16px; }
.kioskroot .fam-head h2 { font-size:38px; font-weight:800; color:var(--slate-900); letter-spacing:-.02em; }
.kioskroot .fam-head.done { flex-wrap:wrap; gap:14px; }
.kioskroot .fam-head .badge.in { display:flex; align-items:center; gap:12px; padding:12px 22px; border-radius:16px; font-size:32px; font-weight:800; background:rgba(78,124,114,.13); color:#3D655D; }
.kioskroot .fam-head .badge.in svg { width:34px; height:34px; }
.kioskroot .fam-sum { font-size:18px; font-weight:700; color:var(--ink-soft); }
.kioskroot .fam-list { margin-top:20px; display:flex; flex-direction:column; gap:12px; overflow:auto; max-height:46vh; }
.kioskroot .fam-row { display:flex; align-items:center; gap:18px; padding:14px 20px; border:1.5px solid var(--line); border-radius:16px; background:var(--paper-2); cursor:pointer; transition:.13s; }
.kioskroot .fam-row.off { opacity:.55; }
.kioskroot .fam-row.on { border-color:rgba(78,124,114,.45); background:#fff; box-shadow:var(--sh-1); }
.kioskroot .fam-row.inalready { cursor:default; opacity:.8; }
.kioskroot .fam-row.done { cursor:default; }
.kioskroot .fam-row .av { width:52px; height:52px; border-radius:15px; display:grid; place-items:center; font-weight:800; font-size:18px; color:#fff; flex:0 0 auto; }
.kioskroot .fam-row .who { flex:1; min-width:0; }
.kioskroot .fam-row .who .n { font-size:21px; font-weight:700; color:var(--ink); }
.kioskroot .fam-row .who .r { font-size:14px; color:var(--ink-faint); font-weight:600; margin-top:2px; }
.kioskroot .fam-check { width:34px; height:34px; border-radius:50%; border:2px solid #C3CCD6; flex:0 0 auto; display:grid; place-items:center; color:#fff; }
.kioskroot .fam-check.on { background:var(--green); border-color:var(--green); }
.kioskroot .fam-check svg { width:20px; height:20px; }
.kioskroot .fam-tag { font-size:13px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; padding:7px 14px; border-radius:11px; background:rgba(78,124,114,.14); color:#3D655D; flex:0 0 auto; }
.kioskroot .fam-row .chk { display:flex; align-items:center; gap:7px; font-weight:800; color:var(--green); font-size:14px; text-transform:uppercase; letter-spacing:.05em; flex:0 0 auto; }
.kioskroot .fam-row .chk svg { width:20px; height:20px; }
.kioskroot .fam-row .ptag { font-size:18px; font-weight:800; color:var(--green); min-width:56px; text-align:right; flex:0 0 auto; }
.kioskroot .fam-row.kid .ptag { color:var(--ink-faint); font-weight:600; }
.kioskroot .fam-actions { display:flex; gap:14px; margin-top:24px; }
.kioskroot .fam-btn { flex:1; height:66px; border-radius:16px; font-family:var(--font); font-weight:800; font-size:20px; cursor:pointer; border:1.5px solid var(--line); }
.kioskroot .fam-btn.ghost { background:#fff; color:var(--slate-900); }
.kioskroot .fam-btn.ghost:hover { background:var(--paper-2); }
.kioskroot .fam-btn.primary { background:linear-gradient(180deg,#32514A,#2E4A43); color:#fff; border-color:transparent; }
.kioskroot .fam-btn.primary:disabled { opacity:.5; cursor:default; }

/* FIX-03B: in-kiosk staff Sessions panel */
.kioskroot .confirm.staffpanel { width:660px; flex-direction:column; }
.kioskroot .sp-inner { flex:1; padding:40px 46px 44px; display:flex; flex-direction:column; min-width:0; }
.kioskroot .ss-live { border:1.5px solid var(--line); border-radius:18px; padding:20px 22px; margin:22px 0 20px; background:var(--paper-2); }
.kioskroot .ss-row { display:flex; align-items:center; gap:14px; }
.kioskroot .ss-dot { width:12px; height:12px; border-radius:50%; background:var(--green); box-shadow:0 0 0 5px rgba(78,124,114,.18); flex:0 0 auto; }
.kioskroot .ss-name { font-size:24px; font-weight:800; color:var(--slate-900); }
.kioskroot .ss-meta { font-size:15px; color:var(--ink-soft); margin-top:2px; }
.kioskroot .ss-badge { background:rgba(78,124,114,.14); color:#3D655D; font-weight:800; font-size:13px; text-transform:uppercase; letter-spacing:.4px; padding:6px 14px; border-radius:999px; flex:0 0 auto; }
.kioskroot .ss-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:14px; margin-top:18px; border-top:1px solid var(--line); padding-top:16px; }
.kioskroot .ss-stats b { display:block; font-size:22px; font-weight:800; color:var(--slate-900); }
.kioskroot .ss-stats span { font-size:12px; color:var(--ink-soft); font-weight:700; text-transform:uppercase; letter-spacing:.3px; }
.kioskroot .ss-actions { display:flex; gap:12px; }
.kioskroot .ss-btn { flex:1; height:60px; border:1.5px solid var(--line); background:#fff; border-radius:14px; font-family:var(--font); font-weight:800; font-size:17px; color:var(--slate-900); cursor:pointer; }
.kioskroot .ss-btn:hover { background:var(--paper-2); }
.kioskroot .ss-btn.primary { background:var(--green); color:#fff; border-color:var(--green); }
.kioskroot .ss-btn.danger { color:var(--red); border-color:rgba(176,70,60,.4); }
.kioskroot .ss-note-msg { margin-top:16px; padding:11px 16px; border-radius:12px; background:rgba(78,124,114,.10); color:#2f6b54; font-weight:700; font-size:15px; }
.kioskroot .kp-note { font-size:13.5px; color:var(--ink-soft); margin-top:18px; text-align:center; }

/* scan-prompt (two options) */
.kioskroot .confirm.sprompt { width:760px; flex-direction:column; text-align:center; padding:54px 56px 56px; }
.kioskroot .confirm.sprompt h2 { font-size:40px; font-weight:800; color:var(--slate-900); letter-spacing:-.02em; }
.kioskroot .sp-opts { display:grid; grid-template-columns:1fr 1fr; gap:22px; margin-top:32px; }
.kioskroot .sp-opt { border:1.5px solid var(--line); background:var(--paper-2); border-radius:20px; padding:34px 24px; display:flex; flex-direction:column; align-items:center; gap:12px; cursor:pointer; transition:.15s; font-family:var(--font); }
.kioskroot .sp-opt:hover { border-color:var(--green); background:#fff; box-shadow:var(--sh-2); transform:translateY(-2px); }
.kioskroot .sp-ic { width:74px; height:74px; border-radius:50%; background:rgba(78,124,114,.12); display:grid; place-items:center; color:var(--teal-700); }
.kioskroot .sp-ic svg { width:38px; height:38px; }
.kioskroot .sp-t { font-size:24px; font-weight:800; color:var(--slate-900); }
.kioskroot .sp-d { font-size:15px; color:var(--ink-soft); font-weight:600; }

/* manual / points panels */
.kioskroot .confirm.kpanel { width:860px; }
/* CLASS PICKER (several classes running). Same panel chrome as the manual list, with big
   tap targets - this is a public touch surface, not a staff one. */
.kioskroot .confirm.classpick { width:820px; }
.kioskroot .cp-list { margin-top:24px; display:flex; flex-direction:column; gap:14px; }
.kioskroot .cp-opt { display:flex; align-items:center; gap:18px; width:100%; padding:22px 24px; cursor:pointer;
    border:1.5px solid var(--line); border-radius:18px; background:var(--paper-2); font-family:var(--font);
    text-align:left; transition:border-color .15s, box-shadow .15s, background .15s; }
.kioskroot .cp-opt:hover { background:#fff; border-color:var(--green); box-shadow:var(--sh-2); }
.kioskroot .cp-dot { width:11px; height:11px; border-radius:50%; background:var(--green); flex:0 0 auto;
    box-shadow:0 0 0 5px rgba(78,124,114,.18); }
.kioskroot .cp-txt { flex:1; min-width:0; display:flex; flex-direction:column; gap:4px; }
.kioskroot .cp-n { font-size:24px; font-weight:800; color:var(--slate-900); text-transform:uppercase; letter-spacing:.02em; }
.kioskroot .cp-t { font-size:16px; font-weight:700; color:var(--ink-soft); }
.kioskroot .cp-go { width:46px; height:46px; border-radius:50%; flex:0 0 auto; display:grid; place-items:center;
    background:var(--green); color:#fff; }
.kioskroot .cp-go svg { width:22px; height:22px; }
.kioskroot .kp-inner { flex:1; padding:40px 46px 46px; display:flex; flex-direction:column; min-width:0; }
.kioskroot .kp-head { display:flex; align-items:center; justify-content:space-between; }
.kioskroot .kp-head h2 { font-size:38px; font-weight:800; color:var(--slate-900); letter-spacing:-.02em; }
.kioskroot .kp-x { border:none; background:var(--paper-2); width:48px; height:48px; border-radius:14px; font-size:26px; color:var(--ink-soft); cursor:pointer; line-height:1; }
.kioskroot .kp-x:hover { background:var(--line); }
.kioskroot .kp-sub { font-size:18px; color:var(--ink-soft); margin:10px 0 22px; }
.kioskroot .kp-search { width:100%; border:2px solid var(--line); border-radius:18px; padding:16px 20px; font-family:var(--font); font-size:21px; color:var(--ink); background:#fff; box-sizing:border-box; }
.kioskroot .kp-search:focus { outline:none; border-color:var(--green); }
/* THE SCROLL THUMB IS COOL, NOT CREAMY (CEO, Jul 29 2026). This list had NO scrollbar rule at
   all, so it inherited the browser's default thumb - a warm grey that read as tan against the
   panel and was the one creamy thing left on the kiosk. Styled explicitly in both dialects:
   `scrollbar-color` (Firefox + modern Chromium) and the ::-webkit-scrollbar pieces, so the
   colour holds whichever engine the station's browser uses. Cool slate, from the same family
   as --line / --paper-2, so it belongs to the de-creamed palette. */
.kioskroot .kp-list { margin-top:20px; display:flex; flex-direction:column; gap:12px; overflow-y:auto; max-height:46vh;
    scrollbar-width:thin; scrollbar-color:#AFBAC6 var(--paper-2); }
.kioskroot .kp-list::-webkit-scrollbar { width:12px; }
.kioskroot .kp-list::-webkit-scrollbar-track { background:var(--paper-2); border-radius:999px; }
.kioskroot .kp-list::-webkit-scrollbar-thumb { background:#AFBAC6; border-radius:999px;
    /* the transparent border + background-clip is what insets the thumb inside its track */
    border:3px solid var(--paper-2); background-clip:padding-box; }
.kioskroot .kp-list::-webkit-scrollbar-thumb:hover { background:#93A0AE; background-clip:padding-box; }
.kioskroot .kp-row { display:flex; align-items:center; gap:18px; padding:14px 20px; border:1.5px solid var(--line); border-radius:16px; background:var(--paper-2); flex:0 0 auto; }
.kioskroot .kp-row .av { width:52px; height:52px; border-radius:15px; display:grid; place-items:center; font-weight:800; font-size:18px; color:#fff; flex:0 0 auto; }
.kioskroot .kp-row .who { flex:1; min-width:0; }
.kioskroot .kp-row .who .n { font-size:21px; font-weight:700; color:var(--ink); }
.kioskroot .kp-row .who .t { font-size:14px; color:var(--ink-faint); font-weight:600; margin-top:2px; }
/* WHICH CLASS this row would write to. A quiet pill rather than more grey text on the same
   line, because it is the one thing that differs between two rows for the same person. */
.kioskroot .kp-row .who .t .kp-cls { display:inline-block; margin-left:10px; padding:2px 10px; border-radius:999px;
    background:rgba(78,124,114,.12); color:var(--teal-700); font-weight:800; font-size:13px; }
/* Uppercase, per the standing kiosk button ruling (CEO, Jul 29 2026). The padlock rides INSIDE
   the button because the lock is a property of the action, not of the person - pressing it is
   what raises the staff PIN. */
.kioskroot .kp-row .go { border:none; border-radius:14px; padding:12px 20px; font-family:var(--font); font-weight:800; font-size:16px; text-transform:uppercase; letter-spacing:.03em; cursor:pointer; color:#fff; background:var(--green); flex:0 0 auto; display:inline-flex; align-items:center; gap:9px; }
.kioskroot .kp-row .go .go-lock { display:inline-flex; opacity:.75; }
.kioskroot .kp-row .go .go-lock svg { width:17px; height:17px; }
/* Already in -> the action is a check-OUT, so it carries the clay the rest of the kiosk uses
   for "leaving" (the OUT badge, the out status rail). */
.kioskroot .kp-row .go.out { background:var(--clay); }
/* The state pill: present only for people who ARE checked in. */
.kioskroot .kp-row .kp-instate { flex:0 0 auto; margin-right:12px; font-size:13px; font-weight:800; letter-spacing:.06em;
    text-transform:uppercase; padding:6px 12px; border-radius:999px; background:rgba(78,124,114,.15); color:#3D655D; }
.kioskroot .kp-row.isin { border-color:rgba(78,124,114,.35); background:rgba(78,124,114,.06); }
.kioskroot .kp-empty { padding:40px; text-align:center; color:var(--ink-faint); font-size:18px; font-weight:600; }
/* The Points card is a narrow centred panel, not the two-column confirm card, so its
   portrait is the same rectangle scaled down to fit and centred above the name. */
.kioskroot .kp-photo { width:260px; height:315px; margin:0 auto 22px; }
.kioskroot .kp-result { margin-top:28px; text-align:center; }
.kioskroot .kp-result .who2 { font-size:24px; font-weight:700; color:var(--slate-900); margin-bottom:12px; }
.kioskroot .kp-result .pn { font-size:88px; font-weight:800; color:var(--green); line-height:1; }
.kioskroot .kp-result .pl { font-size:19px; color:var(--ink-soft); font-weight:600; margin-top:6px; }
.kioskroot .kp-prog { position:relative; height:18px; border-radius:999px; background:var(--paper-2); overflow:hidden; margin:24px auto 0; max-width:560px; }
.kioskroot .kp-prog span { display:block; height:100%; background:linear-gradient(90deg,var(--green),var(--teal-700)); border-radius:999px; transition:width .5s; }
/* POINTS-MATH-05: the half-tier mark, sitting ON the bar at the percentage it represents.
   A hairline rather than a labelled pip - this screen is read from a few feet away by
   someone who has just scanned in, and the sentence underneath is what carries the meaning.
   Rendered only while they are still short, so a full bar is never broken up by a notch. */
.kioskroot .kp-tick { position:absolute; top:0; bottom:0; width:3px; margin-left:-1.5px; background:rgba(255,255,255,.85); box-shadow:0 0 0 1px rgba(33,50,58,.10); }
.kioskroot .kp-gift { margin-top:20px; font-size:19px; font-weight:700; }
.kioskroot .kp-gift.yes { color:var(--amber); }
/* Past the mark but nothing to collect: the kiosk's forward colour, deliberately NOT the
   amber of "gift card ready" - the two must never be mistaken for each other at a glance. */
.kioskroot .kp-gift.half { color:var(--teal-700); }
.kioskroot .kp-gift.no { color:var(--ink-soft); }

/* graceful shrink for narrower kiosk displays */
@media (max-width:1240px) {
    .kioskroot .confirm .inner { grid-template-columns:280px 1fr; }
    .kioskroot .detail .cname { font-size:42px; }
    /* (the .arc circles no longer exist - nothing to hide here) */
}

/* Recent check-ins: the whole visit on one line - "In 12:27 PM - Out 12:28 PM". */
.kioskroot .entry .who .t .sep{display:inline-block;margin:0 7px;opacity:.55}

/* KIOSKAV18 (24 Sep 2026) - no photo = the photo studio default (pine + the shared person glyph in
   cream at 46%), never initials - the owner's standing rule, the same default every record shows. */
.kioskroot :is(.entry,.fam-row,.kp-row) .av{color:#F4F0E6}
.kioskroot :is(.entry,.fam-row,.kp-row) .av > svg{width:46%;height:46%}

/* =============================================================================
   KSTD28 - THE KIOSK ON THE NEW STANDARD (owner, 28 Sep 2026: "turn the interface of the Kiosk
   with our new standard interface and buttons behavior - it's getting the old ones").
   ONE LAYER, appended last so it wins without editing the rules above; delete this block to go
   back. Values are the app standard's own, not re-picked by eye:
     canvas #E1E6EB (records / Mail), glass card = .pd-card.mint (40% white, .72 rim, blur 24,
     card shadow), capsule head = .mint-ph, tile = .mint-w, pine panel = the record rail,
     buttons = the footer pair (HANDOFF 3o-b): PRIMARY mint gradient + glow + 2px lift,
     SECONDARY water glass + lift. Sizes stay at kiosk scale (a public 1920x1080 touch screen).
   Nothing here changes behaviour - markup and logic are untouched.
   ============================================================================= */
.kioskroot {
    --k-canvas:#E1E6EB;
    --k-glass:rgba(255,255,255,.4); --k-glass-rim:rgba(255,255,255,.72);
    --k-tile:rgba(255,255,255,.72); --k-tile-rim:rgba(255,255,255,.85);
    --k-lift:0 3px 8px -5px rgba(30,55,48,.14), 0 16px 34px -18px rgba(30,55,48,.26);
    --k-lift-hi:0 3px 7px -4px rgba(30,55,48,.18), 0 10px 20px -10px rgba(30,55,48,.26), inset 0 0 0 1px rgba(255,255,255,.85);
    --k-card-sh:0 22px 54px -26px rgba(30,55,48,.42);
    --k-tile-sh:0 6px 16px -12px rgba(30,55,48,.35);
    --k-grad:radial-gradient(120% 55% at 90% 3%, rgba(255,255,255,.18), rgba(255,255,255,0) 42%),
             linear-gradient(162deg, #42856E 0%, #2F6B57 60%, #2A5749 100%);
    --k-rail:radial-gradient(120% 55% at 90% 3%, rgba(255,255,255,.14), rgba(0,0,0,0) 42%),
             linear-gradient(162deg, #2E4A43 0%, #213A33 100%);
    --k-pine:#2F6B57; --k-pine-ink:#375A50; --k-tab-ink:#2A4C41; --k-label:#7A8A84;
    background:var(--k-canvas);
}
.kioskbg { background:#E1E6EB; }

/* ---- header: the pine mark + the clock on glass ---- */
.kioskroot .lockup .mk { background:var(--k-rail); box-shadow:0 14px 30px -10px rgba(33,58,51,.55), inset 0 0 0 1px rgba(255,255,255,.12); }
.kioskroot .lockup .wm .ey { color:var(--k-tab-ink); }
.kioskroot .clock { background:var(--k-glass); border:1px solid var(--k-glass-rim); box-shadow:var(--k-lift);
    -webkit-backdrop-filter:blur(24px) saturate(1.5); backdrop-filter:blur(24px) saturate(1.5); }
.kioskroot .clock .sep { background:rgba(30,55,48,.14); }

/* ---- the two cards = .pd-card.mint, their heads = the .mint-ph capsule ---- */
.kioskroot :is(.classcard, .listcard) { background:var(--k-glass); border:1px solid var(--k-glass-rim); border-radius:26px;
    box-shadow:var(--k-card-sh); -webkit-backdrop-filter:blur(24px) saturate(1.5); backdrop-filter:blur(24px) saturate(1.5); }
.kioskroot .cc-band, .kioskroot .lc-head { margin:18px 18px 0; padding:12px 14px 12px 26px; min-height:60px; border:1px solid rgba(255,255,255,.8);
    border-radius:999px; background:rgba(255,255,255,.6); box-shadow:0 6px 16px -12px rgba(30,55,48,.3); }
.kioskroot .cc-band .tag, .kioskroot .lc-head h3 { font-size:17px; font-weight:800; letter-spacing:.11em; text-transform:uppercase; color:var(--k-tab-ink); }
.kioskroot .lc-head .cnt { background:rgba(47,107,87,.12); color:var(--k-pine); margin-right:0; }
.kioskroot .cc-cl { background:var(--k-tile); border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); }
.kioskroot .noclass .nc-h, .kioskroot .sched .s-time .t, .kioskroot .sched.multi .s-name { color:#1C2A25; }

/* recent check-ins: each visit is a tile (the .mint-w material), no zebra, no hairlines */
.kioskroot .listbox { padding:16px 18px 18px; display:flex; flex-direction:column; gap:10px; }
.kioskroot .entry { border:1px solid var(--k-tile-rim); border-bottom:1px solid var(--k-tile-rim); border-radius:18px;
    background:var(--k-tile); box-shadow:var(--k-tile-sh); flex:0 0 auto; }
.kioskroot .entry:nth-child(odd) { background:var(--k-tile); }
.kioskroot .entry .pts { color:var(--k-pine); }

/* ---- the scan panel = the record rail's pine ---- */
.kioskroot .scan { background:var(--k-rail); border:1px solid rgba(255,255,255,.08); border-radius:26px;
    box-shadow:0 26px 60px -28px rgba(20,40,34,.65); }
.kioskroot .scan .badge, .kioskroot .scan .badge .bd { color:#BFD2BA; }
.kioskroot .scan .badge .bd { background:#BFD2BA; }

/* ---- the three actions = the FOOTER PAIR at kiosk scale ----
   MANUAL CHECK IN / OUT and CHECK MY POINTS = SECONDARY (water glass); STAFF = PRIMARY (mint). */
.kioskroot .act { border-radius:22px; transition:transform .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease; }
.kioskroot .act.ghost { background:var(--k-glass); border:1px solid var(--k-glass-rim); color:var(--k-pine-ink); box-shadow:var(--k-lift);
    -webkit-backdrop-filter:blur(24px) saturate(1.5); backdrop-filter:blur(24px) saturate(1.5); }
.kioskroot .act.ghost .ic { color:var(--k-pine-ink); }
.kioskroot .act.ghost:hover { background:rgba(255,255,255,.72); color:#1C2733; border-color:var(--k-glass-rim); transform:translateY(-2px); box-shadow:var(--k-lift-hi); }
.kioskroot .act.primary { background:var(--k-grad); border:1px solid transparent; color:#fff; box-shadow:0 10px 24px -6px rgba(47,107,87,.5); }
.kioskroot .act.primary:hover { transform:translateY(-2px); box-shadow:0 16px 32px -8px rgba(47,107,87,.6); }
.kioskroot .act.primary .lockico { color:rgba(255,255,255,.75); }
.kioskroot .act:active { transform:translateY(1px); }

/* ---- popups: the standard window's canvas, not white ---- */
.kioskroot .koverlay { background:rgba(12,24,20,.55); }
.kioskroot .confirm { background:linear-gradient(180deg,#EEF1F4 0%,#E1E6EB 100%); border:1px solid rgba(255,255,255,.85);
    box-shadow:0 50px 110px -22px rgba(8,18,14,.62); }
.kioskroot .confirm .statusrail { background:var(--k-pine); }
.kioskroot .confirm .statusrail.amber { background:#5E7A83; }
.kioskroot .photobox { border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); }
.kioskroot .detail .points { background:var(--k-tile); border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); }
.kioskroot .detail .points :is(.lab,.val) { color:var(--k-pine); }
.kioskroot .detail .points.muted { background:rgba(255,255,255,.45); }
.kioskroot .confirm-foot { background:rgba(30,55,48,.08); }
.kioskroot .confirm-foot .bar { background:var(--k-pine); }
.kioskroot .returning .num { color:var(--k-pine); }

/* rows inside popups (family, manual list, class/scan options) = tiles */
.kioskroot :is(.fam-row, .kp-row, .cp-opt, .sp-opt) { background:var(--k-tile); border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); }
.kioskroot .fam-row.on { background:#fff; border-color:rgba(47,107,87,.4); box-shadow:0 0 0 2px rgba(47,107,87,.14), var(--k-tile-sh); }
.kioskroot .kp-row.isin { background:rgba(255,255,255,.9); border-color:rgba(47,107,87,.3); }
.kioskroot :is(.cp-opt, .sp-opt):hover { background:#fff; border-color:rgba(47,107,87,.4); transform:translateY(-2px); box-shadow:var(--k-lift-hi); }
.kioskroot :is(.fam-check.on, .cp-dot, .ss-dot) { background:var(--k-pine); border-color:var(--k-pine); }
.kioskroot .cp-go { background:var(--k-grad); box-shadow:0 4px 12px -2px rgba(47,107,87,.42); }
.kioskroot :is(.ss-live, .ss-reader) { background:var(--k-tile); border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); }
.kioskroot .ss-reader.bad { background:rgba(201,123,90,.08); border-color:rgba(201,123,90,.4); }

/* buttons inside popups = the footer pair too */
.kioskroot :is(.fam-btn, .ss-btn) { border-radius:16px; transition:transform .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease; }
.kioskroot :is(.fam-btn.ghost, .ss-btn:not(.primary)) { background:var(--k-glass); border:1px solid var(--k-glass-rim); color:var(--k-pine-ink); box-shadow:var(--k-lift);
    -webkit-backdrop-filter:blur(24px) saturate(1.5); backdrop-filter:blur(24px) saturate(1.5); }
.kioskroot :is(.fam-btn.ghost, .ss-btn:not(.primary)):hover { background:rgba(255,255,255,.72); color:#1C2733; transform:translateY(-2px); box-shadow:var(--k-lift-hi); }
.kioskroot .ss-btn.danger { color:#A0452F; }
.kioskroot .ss-btn.danger:hover { background:#C0533A; color:#fff; }
.kioskroot :is(.fam-btn.primary, .ss-btn.primary) { background:var(--k-grad); border:1px solid transparent; color:#fff; box-shadow:0 4px 12px -2px rgba(47,107,87,.42); }
.kioskroot :is(.fam-btn.primary, .ss-btn.primary):hover:not(:disabled) { transform:translateY(-2px); box-shadow:0 8px 20px -4px rgba(47,107,87,.5); }
.kioskroot .kp-row .go { background:var(--k-grad); box-shadow:0 4px 12px -2px rgba(47,107,87,.42); transition:transform .15s ease, box-shadow .15s ease; }
.kioskroot .kp-row .go:hover { transform:translateY(-2px); box-shadow:0 8px 20px -4px rgba(47,107,87,.5); }
.kioskroot .kp-row .go.out { background:linear-gradient(162deg,#D98E6C 0%,#C97B5A 60%,#B5663F 100%); box-shadow:0 4px 12px -2px rgba(181,102,63,.42); }
/* the close X = the standard glass square */
.kioskroot .kp-x { background:var(--k-glass); border:1px solid var(--k-glass-rim); box-shadow:var(--k-lift); color:var(--k-pine-ink);
    transition:transform .15s ease, background .15s ease; }
.kioskroot .kp-x:hover { background:rgba(255,255,255,.72); color:#1C2733; transform:translateY(-2px); }
/* the search box in Manual / My Points = a tile field with the pine focus */
.kioskroot .kp-search { background:var(--k-tile); border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); }
.kioskroot .kp-search:focus { background:#fff; border-color:rgba(47,107,87,.45); box-shadow:0 0 0 3px rgba(47,107,87,.14); }
.kioskroot .kp-list { scrollbar-color:rgba(30,55,48,.28) transparent; }
.kioskroot .kp-list::-webkit-scrollbar-track { background:transparent; }
.kioskroot .kp-list::-webkit-scrollbar-thumb { background:rgba(30,55,48,.28); border-color:transparent; }
.kioskroot .kp-result .pn { color:var(--k-pine); }
.kioskroot .kp-prog { background:rgba(255,255,255,.6); box-shadow:inset 0 0 0 1px rgba(30,55,48,.08); }
.kioskroot .kp-prog span { background:var(--k-grad); }

/* the parked-station screen */
.kioskroot .kunavail { background:var(--k-canvas); }
.kioskroot .kunavail-card { background:linear-gradient(180deg,#EEF1F4 0%,#E1E6EB 100%); border:1px solid rgba(255,255,255,.85); }
.kioskroot :is(.kunavail-mk, .kunavail-note) { background:var(--k-tile); border:1px solid var(--k-tile-rim); }

/* KSTD28 - the STAFF PIN PAD on the kiosk. It is the shared PinPad (scoped CSS, also used by Case
   Notes, Feedback and My Profile) rendered as a SIBLING after .kioskroot - so `.kioskroot ~ .pk-ov`
   reaches it on the kiosk ONLY; everywhere else keeps its own look. Specificity 0,3,0 beats the
   component's scoped 0,2,0. */
.kioskroot ~ .pk-ov { background:rgba(12,24,20,.55); -webkit-backdrop-filter:blur(7px); backdrop-filter:blur(7px); }
.kioskroot ~ .pk-ov .pk-card { background:linear-gradient(180deg,#EEF1F4 0%,#E1E6EB 100%); border:1px solid rgba(255,255,255,.85);
    border-radius:24px; box-shadow:0 50px 110px -22px rgba(8,18,14,.62); font-family:'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; }
.kioskroot ~ .pk-ov .pk-head h2 { color:#1C2A25; }
.kioskroot ~ .pk-ov .pk-x { width:40px; height:40px; padding:0; display:grid; place-items:center; border-radius:12px;
    background:rgba(255,255,255,.4); border:1px solid rgba(255,255,255,.72); color:#375A50;
    box-shadow:0 3px 8px -5px rgba(30,55,48,.14), 0 16px 34px -18px rgba(30,55,48,.26); }
.kioskroot ~ .pk-ov .pk-x:hover { background:rgba(255,255,255,.72); color:#1C2733; }
.kioskroot ~ .pk-ov .pk-dots span { border-color:rgba(30,55,48,.28); }
.kioskroot ~ .pk-ov .pk-dots span.on { background:#2F6B57; border-color:#2F6B57; }
.kioskroot ~ .pk-ov .pk-key { background:rgba(255,255,255,.72); border:1px solid rgba(255,255,255,.85); color:#1C2A25;
    box-shadow:0 6px 16px -12px rgba(30,55,48,.35); transition:transform .15s ease, background .15s ease, box-shadow .15s ease; }
.kioskroot ~ .pk-ov .pk-key:hover { background:#fff; border-color:rgba(47,107,87,.3); transform:translateY(-2px);
    box-shadow:0 3px 7px -4px rgba(30,55,48,.18), 0 10px 20px -10px rgba(30,55,48,.26); }
.kioskroot ~ .pk-ov .pk-key:active { transform:scale(.96); }
.kioskroot ~ .pk-ov .pk-key:focus-visible { border-color:rgba(47,107,87,.45); box-shadow:0 0 0 3px rgba(47,107,87,.16); }
.kioskroot ~ .pk-ov .pk-aux { background:rgba(255,255,255,.4); color:#375A50; }

/* KSTD28 - NO PHOTO = THE STUDIO DEFAULT on every kiosk photo frame (standing rule, 24 Sep): pine +
   the person glyph in cream, never a grey silhouette. .has (a real photo) is untouched. Same pine
   the avatars already wear (KIOSKAV18) and the same #5E8C81 -> #2F4640 as every record's default. */
.kioskroot .photobox:not(.has) { background:linear-gradient(150deg,#5E8C81,#2F4640); border-color:rgba(255,255,255,.14); }
.kioskroot .photobox:not(.has) svg { color:#F4F0E6; opacity:.46; }
.kioskroot .photobox:not(.has) .ph-tag { color:rgba(244,240,230,.62); }

/* KSEARCH28 - the Manual Check In / Out search, on the global search's pattern (owner, 28 Sep): a
   search glyph in the box, a clear X once something is typed, a live "N matches" line, and the
   Up / Down highlight on the row Enter will act on. */
.kioskroot .kp-sbox { position:relative; display:block; }
.kioskroot .kp-sbox .kp-search { padding-left:62px; padding-right:62px; }
.kioskroot .kp-sic { position:absolute; left:22px; top:50%; transform:translateY(-50%); color:var(--k-pine-ink,#375A50); display:grid; pointer-events:none; }
.kioskroot .kp-sic svg { width:24px; height:24px; }
.kioskroot .kp-sx { position:absolute; right:12px; top:50%; transform:translateY(-50%); width:42px; height:42px; border:0; border-radius:12px;
    background:transparent; color:#677579; font-size:28px; line-height:1; cursor:pointer; display:grid; place-items:center; }
.kioskroot .kp-sx:hover { background:rgba(30,55,48,.08); color:#1C2733; }
.kioskroot .kp-count { margin:12px 4px -8px; font-size:15px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:#7A8A84; }
.kioskroot .kp-row.hi { background:#fff; border-color:rgba(47,107,87,.45); box-shadow:0 0 0 3px rgba(47,107,87,.14), 0 6px 16px -12px rgba(30,55,48,.35); }
.kioskroot .kp-row .go .go-lock { opacity:1; }
.kioskroot .kp-row .go .go-lock svg { width:19px; height:19px; }

/* KSCROLL28 - every kiosk scrollbar is the standard's white glass (owner, 28 Sep: "change that roller ... same as our
   new standard, white or glassy"). The Recent check-ins list had NO rule and showed the browser's beige thumb.
   A white thumb on a light card needs its pine hairline to stay visible; the track stays clear. */
/* scrollbar-color / scrollbar-width are RESET: in Chrome/Edge 121+ either one switches the ::-webkit-scrollbar
   rules below off, and the old .kp-list rule set both - the glass thumb would never have painted. */
.kioskroot :is(.listbox, .kp-list, .fam-list) { scrollbar-width:auto; scrollbar-color:auto; }
.kioskroot :is(.listbox, .kp-list, .fam-list)::-webkit-scrollbar { width:12px; }
.kioskroot :is(.listbox, .kp-list, .fam-list)::-webkit-scrollbar-track { background:rgba(30,55,48,.05); border-radius:999px; margin:10px 0; }
.kioskroot :is(.listbox, .kp-list, .fam-list)::-webkit-scrollbar-thumb {
    background:linear-gradient(180deg, rgba(255,255,255,.98), rgba(255,255,255,.82)); border-radius:999px;
    border:2px solid transparent; background-clip:padding-box;
    box-shadow:inset 0 0 0 1px rgba(30,55,48,.16), 0 2px 6px -2px rgba(30,55,48,.25); }
.kioskroot :is(.listbox, .kp-list, .fam-list)::-webkit-scrollbar-thumb:hover { background:#fff; background-clip:padding-box; box-shadow:inset 0 0 0 1px rgba(47,107,87,.35); }

/* KSCROLL28b - the list stops short of the card's rounded bottom corner (owner, 28 Sep: "the down button is gone").
   The scroller ran to the card's edge, and the card's 26px radius + overflow:hidden clipped the bottom arrow. */
.kioskroot .listbox { margin:0 10px 18px 0; }
.kioskroot :is(.kp-list, .fam-list) { margin-right:-4px; padding-right:4px; }

/* FAMCIRCLE28 (owner, 28 Sep) - check-in / check-out cards polished.
   1. EVERY face on the kiosk is a CIRCLE, like every photo the studio makes: the single confirm card,
      the family done card, My Points, and the small avatars in Recent / Manual / the family list.
      object-fit:cover fills the circle - a studio photo is already cropped for it.
   2. The family done card's status was a bare icon with no size rule (.badge.out had none), so it
      painted a huge white "exit" glyph. It is now a small pill - pine for in, clay for out - and the
      single card's status is scaled down to match.
   3. The student heads the family card (photo + name), the kids sit under "<Name>'s kids", and kids'
      names wrap to two lines instead of being cut off. */
.kioskroot .photobox { border-radius:50%; }
.kioskroot .photobox img { object-position:center; }
.kioskroot .confirm:not(.famcard) .photobox { width:360px; height:360px; }
.kioskroot .photoside { justify-content:center; }
.kioskroot .photobox .ph-tag { bottom:20%; }
.kioskroot .fs-photo { width:200px; height:200px; }
.kioskroot .fs-kidphoto { width:112px; height:112px; }
.kioskroot .kp-photo { width:240px; height:240px; }
.kioskroot :is(.entry, .fam-row, .kp-row) .av { border-radius:50%; overflow:hidden; }
.kioskroot :is(.fam-row .av, .fam-parent .fp-photo) img { width:100%; height:100%; object-fit:cover; object-position:center; display:block; }
.kioskroot .fam-row .av.has { background:#0E1512 !important; }

/* the status: a pill, not a poster */
.kioskroot .detail .status .badge { font-size:26px; padding:10px 18px; gap:10px; border-radius:14px; }
.kioskroot .detail .status .badge svg { width:26px; height:26px; }
.kioskroot .fam-head.done { justify-content:flex-start; align-items:center; gap:14px; }
.kioskroot .fam-head.done .badge { display:inline-flex; align-items:center; gap:9px; padding:8px 16px; border-radius:999px;
    font-size:17px; font-weight:800; letter-spacing:.01em; white-space:nowrap; }
.kioskroot .fam-head.done .badge svg { width:19px; height:19px; flex:0 0 auto; }
.kioskroot .fam-head.done .badge.in { background:rgba(47,107,87,.12); color:#2F6B57; }
.kioskroot .fam-head.done .badge.out { background:rgba(201,123,90,.15); color:#B5663F; }
.kioskroot .fam-sum { font-size:17px; }

/* the student at the top of the select card */
.kioskroot .fam-parent { display:flex; align-items:center; gap:20px; margin-top:20px; padding:16px 20px; border-radius:18px;
    background:var(--k-tile); border:1px solid var(--k-tile-rim); box-shadow:var(--k-tile-sh); cursor:pointer; transition:.13s; }
.kioskroot .fam-parent.on { background:#fff; border-color:rgba(47,107,87,.4); box-shadow:0 0 0 2px rgba(47,107,87,.14), var(--k-tile-sh); }
.kioskroot .fam-parent.off { opacity:.6; }
.kioskroot .fam-parent :is(.ref, .inalready), .kioskroot .fam-parent.ref, .kioskroot .fam-parent.inalready { cursor:default; }
.kioskroot .fam-parent .fp-photo { width:76px; height:76px; border-radius:50%; overflow:hidden; flex:0 0 auto; display:grid; place-items:center;
    background:linear-gradient(150deg,#5E8C81,#2F4640); color:#F4F0E6; border:1px solid rgba(255,255,255,.7); }
.kioskroot .fam-parent .fp-photo.has { background:#0E1512; }
.kioskroot .fam-parent .fp-photo > svg { width:44%; height:44%; }
.kioskroot .fam-parent .who { flex:1; min-width:0; }
.kioskroot .fam-parent .who .n { font-size:25px; font-weight:800; color:#1C2A25; letter-spacing:-.01em; }
.kioskroot .fam-parent .who .r { font-size:13px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:#5E7A70; margin-top:3px; }
.kioskroot .fam-kids-h { margin:20px 4px 0; font-size:14px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#5E7A70; }
.kioskroot .fam-kids-h + .fam-list { margin-top:10px; }

/* kids' names: two lines, never cut */
.kioskroot .fs-kid { width:130px; }
.kioskroot .fs-kidname { white-space:normal; line-height:1.2; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }

/* KIOSKFIX28 (28 Sep) - the family done card names anyone the database refused (A5), in clay,
   instead of claiming "Family checked in" for people who were not. */
.kioskroot .fam-miss { flex-basis:100%; margin-top:2px; padding:10px 14px; border-radius:12px;
    background:rgba(201,123,90,.12); border:1px solid rgba(201,123,90,.3); color:#9A4F2C;
    font-size:15px; font-weight:700; line-height:1.35; }

/* KIOSKFIX28 - the public kiosk never shows the developer's phone and email on the reconnect
   screen (list item F). Staff screens keep the Contact Developer button. */
body:has(.kioskroot) :is(#mntContactBtn, #mntDevModal) { display:none !important; }

/* =============================================================================
   FSBTN29 (29 Sep 2026) - the FULL SCREEN button in the header, beside the clock (owner: "the
   KIOSK page had a rectangle when you pressed on it the browser went to full screen ... staff
   are very lazy so we must guide them"). The kiosk glass, the clock's height; it disappears
   while the page IS full screen (Esc brings it back). The first-tap auto full screen stays.
   ============================================================================= */
.kioskroot .khead .clock { margin-left:auto; }   /* clock + button sit together on the right */
.kioskroot .khead .fsbtn { display:inline-flex; align-items:center; justify-content:center; align-self:stretch; aspect-ratio:1; padding:0;
    border-radius:20px; background:var(--k-glass); border:1px solid var(--k-glass-rim); box-shadow:var(--k-lift);
    -webkit-backdrop-filter:blur(24px) saturate(1.5); backdrop-filter:blur(24px) saturate(1.5);
    color:var(--k-pine-ink); cursor:pointer; transition:transform .15s, box-shadow .15s, background .15s; }
.kioskroot .khead .fsbtn svg { width:32px; height:32px; fill:none; stroke:currentColor; stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round; }
.kioskroot .khead .fsbtn:hover { background:rgba(255,255,255,.72); transform:translateY(-2px); box-shadow:var(--k-lift-hi); }
.kioskroot .khead .fsbtn:focus-visible { outline:3px solid rgba(47,107,87,.45); outline-offset:3px; }
:root:fullscreen .kioskroot .khead .fsbtn { display:none; }

/* =============================================================================
   KAVATAR29 (29 Sep 2026) - no photo = THE CLIENTS' STUDIO DEFAULT, everywhere on the kiosk
   (owner: "assign our default clients default photo on everywhere on kiosk"; the kids' glyph
   was "really big"). The big circles (check-in card, family card student + kids, My Points)
   drew their own person glyph at a FIXED 112px - the whole circle on a 112px kid - in grey at
   46% opacity, with a "no photo on file" caption. Now they are the Client record's .mh-photo:
   Avatars.PersonIcon at 46% of the circle, cream #F4F0E6, pine 150deg #5E8C81 -> #2F4640, the
   soft rim. No caption (the Client record has none).
   ============================================================================= */
.kioskroot .photobox:not(.has) { background:linear-gradient(150deg,#5E8C81,#2F4640); border:2.5px solid rgba(234,241,237,.5);
    box-shadow:inset 0 0 0 3px rgba(255,255,255,.16), 0 6px 18px rgba(0,0,0,.26); display:grid; place-items:center; }
.kioskroot .photobox:not(.has) > svg { width:46%; height:46%; color:#F4F0E6; opacity:1; }
.kioskroot .fam-parent .fp-photo > svg { width:46%; height:46%; }

/* =============================================================================
   RECENTIO29 (29 Sep 2026) - "Recent check-ins/out": every row shows the IN and the OUT SIDE BY
   SIDE, each with its time (owner: "add the check in and check out row side by side and it must
   show when the student checked in and when the student checked out ... that is the standard").
   The OUT box waits as a muted dash until they leave. Newest action first (unchanged - the proc
   sorts on the check-out time once there is one). Names may take two lines now the time line
   under them is gone.
   ============================================================================= */
.kioskroot .entry .who .n { white-space:normal; line-height:1.2; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.kioskroot .entry .io { display:flex; gap:10px; flex:0 0 auto; }
.kioskroot .entry .io .iocol { display:flex; flex-direction:column; align-items:center; gap:5px; width:76px; }
.kioskroot .entry .io .stat { width:64px; }                 /* the same pill as before, one width for IN and OUT */
.kioskroot .entry .io .stat.none { background:transparent; box-shadow:inset 0 0 0 1px rgba(30,55,48,.16); color:#9AA7A2; }
.kioskroot .entry .io .iot { font-size:13px; font-weight:700; color:var(--ink-soft, #4A5A55); font-variant-numeric:tabular-nums; white-space:nowrap; }
.kioskroot .entry .io .stat.none + .iot { color:#9AA7A2; }

/* ROWCLASS29 (29 Sep 2026) - the class name sits under every student name on the recent strip
   (the same quiet teal pill), always, not only when two classes run. */
.kioskroot .entry .who .t { margin-top:5px; line-height:1; }
.kioskroot .entry .who .t .ent-cls { margin-left:0; padding:3px 10px; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; vertical-align:top; }

/* =============================================================================
   LCCOLS29 (29 Sep 2026) - the frozen column header of "Recent check-ins/out" (owner: "open a
   header below the Recent Check-ins/out ... Student Name - In - Out - Pts ... Freeze the header")
   and the title centred in its band (the h3 carried an 8px bottom margin that lifted it).
   The header is OUTSIDE .listbox, so it cannot scroll. Its sides copy the row geometry exactly:
   listbox side padding 18 + row border 1 + row padding 24 = 43; and BOTH it and the list reserve
   the scrollbar's gutter always, so the columns line up with or without a scrollbar.
   ============================================================================= */
.kioskroot .lc-head h3 { margin:0; line-height:1.2; }
.kioskroot .listbox { scrollbar-gutter:stable; }
.kioskroot .lc-cols { flex:0 0 auto; display:flex; align-items:center; gap:16px; margin:14px 10px 0 0;
    padding:0 43px 2px 43px; overflow-y:hidden; scrollbar-gutter:stable;
    font-size:12px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:var(--k-label, #7A8A84); }
.kioskroot .lc-cols::-webkit-scrollbar { width:12px; }
.kioskroot .lc-cols .c-av { width:52px; flex:0 0 auto; }
.kioskroot .lc-cols .c-name { flex:1; min-width:0; }
.kioskroot .lc-cols .c-io { display:flex; gap:10px; flex:0 0 auto; }
.kioskroot .lc-cols .c-io > span { width:76px; text-align:center; }
.kioskroot .lc-cols .c-pts { min-width:50px; text-align:right; flex:0 0 auto; }
.kioskroot .lc-cols + .listbox { padding-top:8px; }

/* LCGRAD29 (29 Sep 2026) - the column header words in the Matthew House gradient (owner: "turn it to
   Matthew House branding gradient color"): the STAFF button's own stops, #42856E -> #2F6B57 -> #2A5749,
   laid into each word's text; .g is the word itself, so every label gets the WHOLE gradient. */
.kioskroot .lc-cols .g { display:inline-block;
    background:linear-gradient(135deg, #42856E 0%, #2F6B57 60%, #2A5749 100%);
    -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; color:#2F6B57; }
