/* ============================================================
   register.sherigarba.ca v3, the live components.
   Loaded AFTER register.css on the four light pages. register.css is the client's
   own white design; this file carries everything the live scripts inject or the
   register page needs that the client's stylesheet does not know about: the sign in
   card, the identity strip, the read only email, the honest demo, failure and
   success panels, the toasts and the offline bar from core.js, the install pill,
   the Garba Buddy widget, the reveal animation, the pass actions, the pass chips and
   the print rule. Every colour pair here was measured against the ground it lands on
   (contrast.py in the QA folder): nothing below is under 4.5:1 for body text.
   ============================================================ */
:root{
  /* names the live scripts' components were written against, mapped onto the white
     tokens register.css defines */
  --text:var(--ink); --muted:var(--ink-3); --paper:var(--bg);
  --surface:var(--panel); --surface-2:var(--panel-2); --field-line:var(--line-strong);
  --mono:var(--code);
  --brand:#5B2A8C;          /* 9.75 on white, 8.80 on panel-2 */
  --brand-ink:#411E64;
  --ok:#1A6B50;             /* 6.44 on white, 5.06 on its own 16% tint */
  --danger:#A8362F;         /* 6.49 on white, 5.74 on its own 8% tint */
  --on-accent:#22110A;      /* 6.94 on marigold, 9.25 on saffron */
  --shadow-sm:0 10px 24px -18px rgba(42,23,63,.28);
}

/* Until a mode is stamped nothing mode specific paints, so a live site never flashes the
   sample data ribbon before the adapter has had its say, and a demo build never flashes
   the Google button it cannot honour. firebase-adapter.js stamps html[data-sg-mode] the
   moment it runs; app.js keeps it in step. */
:root:not([data-sg-mode]) [data-demo-only],
:root:not([data-sg-mode]) [data-live-only]{display:none}
:root[data-sg-mode="live"] [data-demo-only]{display:none}
:root[data-sg-mode="demo"] [data-live-only]{display:none}
/* The sign in state machine swaps #authWait, the sign in card, the identity strip and the
   form with the hidden attribute. register.css carries the same guard; it is repeated here
   so that if either sheet fails to load, a signed out visitor is never shown the "Signed in"
   strip (.whoami's display:flex would otherwise beat the UA [hidden] rule). register.css in
   turn repeats the mode gating above. Each light sheet holds both guards on its own. */
[hidden]{display:none !important}

/* Every scroll into view (focus moves, Shift+Tab, the form's own refusal focusing a blank
   field, anchor jumps, app.js scrollIntoView) stops below the 64px sticky header instead
   of under it. Padding on the scroll root covers controls as well as sections, so the
   per element margins are zeroed: margin and padding would otherwise add up. */
html{scroll-padding-top:92px}
section[id],.legal h2{scroll-margin-top:0}
.note{font-size:.88rem;color:var(--ink-3);line-height:1.55}
.note a,.passnote a,.failure a,.demo-note a,.success a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}
.code{font-family:var(--code);font-variant-numeric:tabular-nums;letter-spacing:.04em}
.mono{font-family:var(--code);font-variant-numeric:tabular-nums;letter-spacing:.03em}
button{font-family:inherit}

/* ---------- button aliases ----------
   app.js, core.js and wallet.js render buttons with the short modifier classes the
   night stylesheet used (.btn.ghost, .btn.sm, .btn.lg, .btn.block). They paint here
   exactly like the client's own .btn-ghost, .btn-gold and .btn-block. */
.btn.ghost{background:transparent;border-color:var(--line-strong);color:var(--ink);box-shadow:none}
.btn.ghost:hover{border-color:var(--accent-pink);color:var(--ink)}
.btn.block{width:100%}
.btn.lg{padding:15px 26px;font-size:1.04rem}
.btn.sm{padding:8px 14px;font-size:.86rem;min-height:44px}
.btn.saved,.btn.saved:hover,.btn.saved:active{background:color-mix(in srgb,var(--ok) 16%,var(--panel));color:var(--ok);border-color:var(--ok);box-shadow:none;transform:none;cursor:default;filter:none}
.btn.saved .ic{width:17px;height:17px;flex:none}
.btn svg{flex:none}

/* ---------- hero facts as the client's pills ---------- */
.hero .herofacts{display:flex;flex-wrap:wrap;gap:8px 10px;margin:26px 0 0;padding:0;list-style:none}
.hero .herofacts li{display:inline-flex;align-items:center;gap:5px;background:#2B1550;border:1px solid rgba(246,234,214,.25);border-radius:999px;padding:8px 15px;font-size:.86rem;font-weight:600;color:#FFF6E5;box-shadow:0 4px 14px -6px rgba(0,0,0,.5);line-height:1.35}
.hero .herofacts b{color:var(--saffron)}   /* 8.04 on #2B1550 */
@media (max-width:420px){.hero .herofacts li{font-size:.82rem;padding:7px 12px}}
/* The client's prototype loads one Playfair italic, 600, so its italic subtitle renders
   SemiBoldItalic whatever weight it asks for. register.css now self hosts that face; the
   subtitle asks for it by name so it does not settle on the 400 italic instead. */
.hero .sub{font-weight:600}

/* ---------- demo ribbon and footer chip ---------- */
.demo-ribbon{background:#160B26;color:#EADFF6;font-family:var(--code);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;text-align:center;padding:.58rem 1rem;line-height:1.6}
.demo-ribbon b{color:var(--gold);font-weight:600}   /* 10.31 on #160B26 */
@media (max-width:430px){.demo-ribbon{font-size:.63rem;letter-spacing:.1em}}
.demochip{margin-top:14px;padding:10px 12px;border:1px dashed var(--line-strong);border-radius:var(--radius-xs);font-size:.82rem;color:var(--ink-3);line-height:1.5;max-width:46ch}

/* ---------- header extras ---------- */
.brand .bn .guj{font-size:.82rem;font-weight:500;color:var(--ink-2)}
.menu-btn svg{width:20px;height:20px}
.site-header .nav-links{z-index:5}

/* ---------- the register card: the three states ----------
   #authWait, the sign in card, the form and the "pass on file" note all live inside
   one .form-card and swap with the hidden attribute. */
.form-card .state-head h3{font-family:var(--serif);font-size:1.5rem;margin:0 0 4px;color:var(--ink)}
.form-card .state-head .hint{color:var(--ink-3);font-size:.92rem;margin:0 0 22px}
#authWait{margin:0;font-size:.98rem;color:var(--ink-2)}
#authWait .authwait-fallback{display:block;margin-top:.6rem;font-size:.9rem;color:var(--ink-3)}
noscript .note{margin:0}
.field .lbl{display:block;font-weight:600;font-size:.875rem;margin-bottom:6px;color:var(--ink)}
.field input:disabled,.field select:disabled{opacity:.6;cursor:not-allowed}
.field select{appearance:auto}
.form-note{color:var(--ink-3)}
.form-err:empty{display:none}
.form-err{display:block}
.form-err a{color:var(--accent-red)}
.consent input:disabled{cursor:not-allowed}
.consent{color:var(--ink-2)}

/* --- the sign in card --- */
.signin{max-width:none}
.signin-note{margin:0 0 18px;font-size:.95rem;color:var(--ink-2);line-height:1.6}
.signin-note b{color:var(--ink);font-weight:600}
/* Google's own light button. Ink #1F1F1F on white measures 16.48; the #747775 edge 4.53. */
.btn.google{background:#FFFFFF;color:#1F1F1F;border:1px solid #747775;box-shadow:none;font-weight:600;letter-spacing:0;gap:.7em;min-height:50px}
.btn.google:hover{background:#F2F2F2;border-color:#5F6368;filter:none}
.btn.google:active{background:#E8E8E8}
.btn.google .gmark{width:18px;height:18px;flex:none;display:block}
.signin-or{display:flex;align-items:center;gap:.8rem;margin:16px 0;font-family:var(--code);font-size:.68rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.signin-or::before,.signin-or::after{content:"";flex:1;height:1px;background:var(--line-strong)}
.emailform{display:grid;gap:11px}
@media (min-width:460px){.emailform{grid-template-columns:minmax(0,1fr) auto;align-items:end}}
.emailform .field{margin:0}
.emailform .btn{min-height:50px}
.emailform .sent{grid-column:1/-1}
.sent{margin:0}
.sent:empty{display:none}

/* --- the signed in identity strip --- */
.whoami{display:flex;align-items:center;gap:12px;min-width:0;margin:0 0 18px;padding:9px 11px 9px 13px;border:1px solid var(--line);border-radius:999px;background:var(--panel-2)}
.whoami .av{flex:none;width:38px;height:38px;border-radius:50%;overflow:hidden;display:grid;place-items:center;background:linear-gradient(135deg,var(--marigold),var(--saffron));color:var(--on-accent);font-family:var(--sans);font-weight:700;font-size:.95rem;line-height:1}
.whoami .av img{width:100%;height:100%;object-fit:cover}
.whoami .id{flex:1;min-width:0}
.whoami .em{display:block;margin:0;font-size:.92rem;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.whoami small{display:block;font-family:var(--code);font-size:.62rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
.whoami .btn{flex:none}
@media (max-width:430px){
  .whoami{border-radius:var(--radius-sm);flex-wrap:wrap;padding:11px 13px}
  .whoami .btn{margin-left:auto}
}

/* --- the account's email, shown and not editable --- */
.rofield{display:flex;align-items:center;gap:.6rem;min-width:0;margin:0;padding:12px 14px;border-radius:var(--radius-xs);border:1px dashed var(--line-strong);background:transparent;color:var(--ink);font-size:1rem;line-height:1.35}
.rofield .v{display:block;min-width:0;flex:1;margin:0;font-weight:600;color:var(--ink);overflow-wrap:anywhere}
.rofield .lk{flex:none;margin:0;color:var(--ink-3);display:grid;place-items:center}
.rofield .lk svg{width:16px;height:16px}

/* --- honest panels --- */
.demo-note{margin-top:16px;padding:13px 15px;border-radius:var(--radius-sm);background:var(--panel-2);border:1px dashed var(--line-strong);font-size:.88rem;color:var(--ink-2);line-height:1.55}
.demo-note b{color:var(--ink)}
.demo-note p,.success p,.failure p{margin:0}
.success{border:1px solid color-mix(in srgb,var(--ok) 60%,transparent);background:color-mix(in srgb,var(--ok) 10%,var(--panel));border-radius:var(--radius-sm);padding:16px 18px;margin-top:16px;color:var(--ink);font-size:.95rem;line-height:1.55}
.failure{border:1px solid color-mix(in srgb,var(--danger) 60%,transparent);background:color-mix(in srgb,var(--danger) 8%,var(--panel));border-radius:var(--radius-sm);padding:16px 18px;margin-top:16px;color:var(--ink);font-size:.95rem;line-height:1.55}
.failure strong{color:var(--danger)}
.success strong{color:var(--ok)}
#rgOut{margin-top:16px}
#rgOut:empty{display:none}

/* --- what the pass does, icons --- */
.why li .ic svg{width:16px;height:16px}
.why .demo p{margin:0}
.why .demo b{color:var(--ink-2)}

/* ---------- the pass card, actions and state ---------- */
#pass{margin-top:28px}
#passOut{padding:0;margin-top:0}
#pass .kicker{margin:0 0 .7rem;display:block}
.passgrid{grid-template-columns:286px minmax(0,1fr)}
@media (max-width:640px){.passgrid{grid-template-columns:1fr;justify-items:stretch}.passcard{margin:0 auto}}
.passnote h4{font-family:var(--serif);font-size:1.25rem;margin:0 0 8px;color:var(--ink)}
.passnote strong{font-size:1.06rem;color:var(--ink)}
.passnote p{color:var(--ink-2);margin:0 0 12px;font-size:.96rem}
.passnote p.note{font-size:.88rem;color:var(--ink-3)}
.btnrow{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0 10px}
.btnrow .btn{padding:11px 18px;font-size:.95rem;min-height:44px}
.savednote{display:flex;gap:.45rem;align-items:flex-start;margin:10px 0 0;font-size:.88rem;color:var(--ok);font-weight:600;line-height:1.5}
.savednote svg{width:16px;height:16px;flex:none;margin-top:.2em}
.pline.revoked{color:#A8362F;font-weight:600}
.pline.city{color:#6B5E80;font-size:.84rem}
/* The card is a fixed 286px with overflow hidden, so one long unbroken word in the holder
   name or the city (a Hawaiian surname, a Welsh town, Gujarati typed without spaces) would
   lose its end at the card edge, on screen and in print. Break inside the word instead,
   the way wallet.js wrap() hard splits it on the PNG and the PDF. */
.passcard .pline,.passcard .pline strong{overflow-wrap:anywhere}

/* ---------- passes on this device ---------- */
#mineList{min-height:1px}
.pass-chip:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.pass-chip .who{min-width:0;display:block}
.pass-chip .who span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pass-chip b{color:var(--ink)}
.pass-chip .tag{display:inline-block;margin-left:6px;font-family:var(--code);font-size:.64rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
.find-card{padding:clamp(20px,3vw,30px);margin-top:26px}
.find-card h3{font-family:var(--serif);font-size:1.3rem;margin:0 0 6px;color:var(--ink)}
.find-card .lede{color:var(--ink-2);margin:0;font-size:.96rem}
.find-form .field{margin:0}
.find-form .btn{min-height:50px}
#findErr{margin-top:12px}
#mypass{padding-top:0}

/* ---------- footer extras ---------- */
.site-footer .fbrand{font-family:var(--serif);font-size:1.15rem;color:var(--ink)}
.site-footer .fbrand .guj{font-size:.9rem;font-weight:500;color:var(--ink-2);margin-left:6px}
.site-footer .footer-grid p{color:var(--ink-3);margin:6px 0 0;font-size:.9rem;max-width:40ch}
.site-footer .meta a{text-decoration:underline;text-underline-offset:2px}
.site-footer .meta .credit{display:block;margin-top:6px}
/* v3.0.1 review: with the photo credit gone, the eVamb credit is the footer's last line, and
   at full scroll it sat under the fixed Buddy button (16px up, 56px tall). The footer now ends
   88px clear of the viewport bottom, so the credit finishes above the button at every width. */
.site-footer{padding-bottom:calc(88px + env(safe-area-inset-bottom,0px))}
/* v3.0.3 (V302-SPEC 9 A2): iPad Safari at 768x1024 broke the credit's last line under the
   Buddy button anyway (WebKit wraps the meta block differently from Chromium), so below 900px
   the meta block also keeps the button's column clear on the right: 16px inset, 56px button,
   8px of air. The credit can then never share a pixel with the button, however it wraps. */
@media (max-width:899px){.site-footer .meta{padding-right:calc(80px + env(safe-area-inset-right,0px))}}

/* ---------- toasts (core.js) ----------
   Stacked above the Buddy button (16 + 56 + 12), not on it. #F4ECDF on #160B26 is 16.14. */
.toasts{position:fixed;right:calc(16px + env(safe-area-inset-right,0px));bottom:calc(84px + env(safe-area-inset-bottom,0px));z-index:300;display:flex;flex-direction:column;gap:9px;pointer-events:none;max-width:calc(100vw - 32px)}
.toast{background:#160B26;color:#F4ECDF;border:1px solid color-mix(in srgb,var(--saffron) 38%,transparent);border-left:3px solid var(--saffron);border-radius:var(--radius-sm);padding:12px 16px;font-size:.88rem;box-shadow:var(--shadow);max-width:330px;animation:tin .28s ease}
.toast.ok{border-left-color:var(--jade)} .toast.bad{border-left-color:var(--maple)}
@keyframes tin{from{opacity:0;transform:translateY(10px)}}

/* ---------- offline and queue bar (core.js) ---------- */
.netbar{display:none;padding:9px 16px;background:color-mix(in srgb,var(--danger) 8%,var(--bg));border-bottom:1px solid color-mix(in srgb,var(--danger) 40%,transparent);font-family:var(--code);font-weight:600;font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--danger);text-align:center}
.netbar.on{display:block}

/* ---------- install pill (core.js) ----------
   left + right + margin-inline:auto centres it against the full viewport; width:max-content
   keeps it the one line pill it was drawn as. .tucked is core.js hiding it while a form
   control has focus or a submit button sits under it. */
.install{position:fixed;left:12px;right:12px;margin-inline:auto;width:max-content;bottom:calc(18px + env(safe-area-inset-bottom));z-index:120;display:none;gap:11px;align-items:center;padding:10px 12px 10px 17px;border-radius:999px;background:var(--panel);border:1px solid var(--line-strong);box-shadow:var(--shadow);font-size:.86rem;font-weight:600;color:var(--ink);max-width:calc(100% - 24px);transition:opacity .15s}
.install.on{display:flex}
.install.tucked{opacity:0;pointer-events:none}
.install .icon-btn{width:36px;height:36px;font-size:1.1rem}
#main:focus-within~.install{opacity:0;pointer-events:none}
@media (max-width:860px){.install{bottom:calc(84px + env(safe-area-inset-bottom))}}

/* ---------- Garba Buddy (buddy.js) ---------- */
.buddy-fab{position:fixed;right:calc(16px + env(safe-area-inset-right,0px));bottom:calc(16px + env(safe-area-inset-bottom,0px));z-index:130;width:56px;height:56px;border-radius:50%;border:0;cursor:pointer;display:grid;place-items:center;background:linear-gradient(135deg,var(--marigold),var(--saffron));color:var(--on-accent);box-shadow:0 14px 34px -12px rgba(246,169,59,.8);transition:transform .18s,opacity .15s}
.buddy-fab:hover{transform:scale(1.06)}
/* At every width, not only phones: buddy.js adds .tucked only while a field has focus or a
   submit button sits under the button, and an iPad in portrait (810 wide) has both cases,
   with a tap on the right end of Find my pass opening Buddy instead. */
.buddy-fab.tucked{opacity:0;pointer-events:none}
.buddy-fab svg{width:26px;height:26px}
.buddy-fab .badge{position:absolute;top:-3px;right:-3px;min-width:20px;height:20px;border-radius:999px;background:#2B1550;color:#fff;font-family:var(--code);font-weight:600;font-size:.7rem;line-height:20px;text-align:center;padding:0 5px;border:1px solid rgba(255,255,255,.35)}
.buddy{position:fixed;right:calc(14px + env(safe-area-inset-right,0px));z-index:140;width:min(calc(100vw - 28px),392px);bottom:calc(14px + env(safe-area-inset-bottom,0px));height:min(calc(100dvh - 96px),604px);display:none;flex-direction:column;background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden;color:var(--ink)}
.buddy.open{display:flex}
.buddy-head{display:flex;align-items:center;gap:11px;padding:14px 15px;border-bottom:1px solid var(--line);background:#160B26;color:#FFF6E5;--focus:var(--saffron)}
.buddy-head .av{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--marigold),var(--saffron));display:grid;place-items:center;color:var(--on-accent);flex:none;font-weight:700}
.buddy-head .av img{width:30px;height:30px;object-fit:contain}
.buddy-head b{display:block;font-family:var(--serif);font-size:1rem;letter-spacing:-.01em;color:#fff}
.buddy-head small{display:block;font-family:var(--code);font-size:.6rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--gold);margin-top:4px}
.buddy-head small:lang(gu),.buddy-head small:lang(hi){letter-spacing:0;text-transform:none}
.buddy-head .icon-btn{background:transparent;color:#FFF6E5;border-color:rgba(255,255,255,.3);width:44px;height:44px}
.buddy-head .icon-btn:hover{border-color:var(--saffron);color:#fff}
.buddy-log{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:11px;overscroll-behavior:contain;background:var(--bg-2)}
.msg{max-width:88%;padding:11px 14px;border-radius:15px;font-size:.92rem;line-height:1.55;white-space:pre-line;overflow-wrap:anywhere}
.msg.bot{background:var(--panel);border:1px solid var(--line);border-bottom-left-radius:5px;align-self:flex-start;color:var(--ink)}
.msg.me{background:linear-gradient(135deg,var(--marigold),var(--saffron));color:var(--on-accent);border-bottom-right-radius:5px;align-self:flex-end;font-weight:500}
.msg.sys{align-self:center;background:transparent;color:var(--ink-3);font-size:.78rem;font-family:var(--code);letter-spacing:.06em;text-transform:uppercase}
.msg a{color:var(--accent);text-decoration:underline;font-weight:600}
.msg.me a{color:var(--on-accent)}
.chips{display:flex;flex-wrap:wrap;gap:7px;padding:0 16px 12px;background:var(--bg-2)}
.chip{padding:.45rem .9rem;border-radius:999px;border:1px solid var(--line-strong);background:var(--panel);cursor:pointer;font-size:.82rem;font-weight:600;color:var(--brand);text-decoration:none;transition:border-color .14s,color .14s,background .14s;min-height:44px;display:inline-flex;align-items:center}
.chip:hover{border-color:var(--brand);background:var(--panel-2)}
@media (pointer:coarse){.chip{font-size:16px}}
.buddy-form{display:flex;gap:8px;padding:12px;border-top:1px solid var(--line);background:var(--panel-2)}
.buddy-form input{flex:1;min-width:0;padding:.7rem .95rem;border-radius:999px;border:1px solid var(--line-strong);background:var(--panel);color:var(--ink);font:inherit;font-size:max(16px,1em)}
.buddy-form input:focus{border-color:var(--accent-pink);outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--accent-pink) 35%,transparent)}
.buddy-form button{width:44px;height:44px;border-radius:50%;border:0;background:linear-gradient(135deg,var(--marigold),var(--saffron));color:var(--on-accent);cursor:pointer;display:grid;place-items:center;flex:none;padding:0}
.buddy-form button svg{width:18px;height:18px}
.buddy-lang{margin-left:auto;width:auto;min-height:44px;padding:.3rem .6rem;border-radius:999px;border:1px solid rgba(255,255,255,.3);background:transparent;color:#FFF6E5;font-size:max(16px,.9em);cursor:pointer;font-family:var(--guj)}
.buddy-lang option{color:#26163F;background:#fff}
.typing{display:flex;gap:4px;padding:13px 15px}
.typing i{width:6px;height:6px;border-radius:50%;background:var(--ink-3);animation:blink 1.3s infinite}
.typing i:nth-child(2){animation-delay:.18s} .typing i:nth-child(3){animation-delay:.36s}
@keyframes blink{0%,60%,100%{opacity:.28}30%{opacity:1}}
@media (max-width:720px){
  .buddy{width:calc(100vw - 20px - env(safe-area-inset-right,0px) - env(safe-area-inset-left,0px));right:calc(10px + env(safe-area-inset-right,0px));height:min(calc(100dvh - 76px),100%)}
}

/* ---------- reveal: visible by default, html.reveal-ready opts in (core.js) ---------- */
.reveal{opacity:1;transform:none}
html.reveal-ready .reveal{opacity:0;transform:translateY(20px);transition:opacity .65s ease,transform .65s ease}
html.reveal-ready .reveal.in{opacity:1;transform:none}
html.reveal-ready .reveal.d1{transition-delay:.08s}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  html.reveal-ready .reveal{opacity:1;transform:none;transition:none}
  .toast{animation:none}
  .typing i{animation:none;opacity:.7}
  .buddy-fab,.btn,.install{transition:none}
  .buddy-fab:hover{transform:none}
}

/* info pages: the three touches the client's prototype set inline (no aarti, the
   Platinum sponsor named as text, the desk phone on the venue facts) */
.nights-table .muted{color:var(--ink-3)}
.partners .sponsor-name{display:block;font-family:var(--serif);font-size:1.3rem;color:var(--ink);margin:0 auto 8px}
.info-card a{color:var(--accent);text-decoration:none}
.info-card a:hover,.info-card a:focus-visible{text-decoration:underline}

/* ---------- print: the card and nothing else ----------
   The card sits at #main > #register > .wrap > #pass > #passOut > .passgrid > .passcard.
   Each level keeps only the branch that leads to the card, so one sheet comes out and
   the visibility rule register.css carries is no longer load bearing. */
@media print{
  @page{size:auto;margin:12mm}
  html,body{height:auto;min-height:0;background:#fff;color:#26163F;overflow:visible}
  body>*:not(#main){display:none !important}
  #main>*:not(#register){display:none !important}
  #register .wrap>*:not(#pass){display:none !important}
  #passOut>*:not(.passgrid){display:none !important}
  .passgrid>*:not(.passcard){display:none !important}
  #register,#pass,#passOut,#main{padding:0 !important;margin:0 !important;background:none !important;border:0 !important;box-shadow:none !important;min-height:0 !important}
  .passgrid{display:block}
  .passcard{position:static;left:auto;top:auto;transform:none;box-shadow:none;margin:0 auto;break-inside:avoid;page-break-inside:avoid;visibility:visible}
  body *{visibility:visible}
  .toasts,.install,.buddy,.buddy-fab,.netbar,.demo-ribbon{display:none !important}
  /* v3.0.2: once app.js has put the rendered card PNG beside the card, print THAT and not
     the DOM card. 90 mm wide keeps the whole card on one A4 or Letter page. */
  #passOut.print-img .passcard{display:none !important}
  #passOut.print-img .passgrid>#passPrintImg{display:block !important;width:90mm;max-width:100%;height:auto;margin:0 auto;break-inside:avoid;page-break-inside:avoid;visibility:visible;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .passcard,.passcard *{-webkit-print-color-adjust:exact;print-color-adjust:exact}
}
/* the print copy of the card never shows on screen */
.passprint{display:none}

/* ---------- footer: brand left, links right, as the client drew it ----------
   The two links the register adds (Verify a pass, Operator sign in) make the nav one
   712px line, wider than what is left beside the brand at 1366, so flex-wrap used to push
   the whole nav under the brand. The nav now wraps inside its own column instead, right
   aligned once it sits beside the brand; under about 860px it drops below the brand and
   reads left aligned as before. */
.footer-grid nav{flex:1 1 380px;max-width:560px;gap:0 20px;align-self:flex-start;align-content:flex-start}
@media (min-width:861px){.footer-grid nav{justify-content:flex-end}}

/* ---------- tap targets of at least 44 x 44 ----------
   The header menu and sign out, the pass actions (.btn.sm and .btnrow above), the consent
   label, the footer and band links and the desktop nav. The colophon links that run inside
   a sentence keep their inline box. The crumb and the venue desk phone grow their hit area
   with padding that negative margins give back, so no line box moves. The consent label
   does the same: 11px of padding inside and 11px less margin outside. Its 4px top margin
   collapses into the 20px below .form-note, so the top margin that gives 11 back is -11,
   not 4 minus 11; below, 18 becomes 7. Measured: the text sits exactly where the client
   put it at 390, 768 and 1366. */
.site-header .icon-btn{width:44px;height:44px}
.consent{padding-block:11px;margin:-11px 0 7px}
.footer-grid nav a{display:inline-flex;align-items:center;min-height:44px}
@media (min-width:861px){.nav-links a{display:inline-flex;align-items:center;min-height:44px}}
/* v3.0.1 review: in the open phone menu each link was an inline box inside its LI, so its
   padding painted 43px but the row it owned was 25.6px and only the word was tappable. As a
   flex row it fills the panel width and stands about 50px; 44px is the floor, not the size. */
@media (max-width:860px){.nav-links a{display:flex;align-items:center;min-height:44px}}
.crumbs a,.info-card .v a{display:inline-block;padding-block:13px;margin-block:-13px}
/* V310-SPEC 8 F3: privacy.html's standalone "Privacy contact" link in the header card is a
   value in a label and value row, not a link inside a sentence, so it gets the same 44px
   hit area. The card's 18px padding holds the 13px it grows; no line moves. */
.legal .meta-card a{display:inline-block;padding-block:13px;margin-block:-13px}

/* ---------- safe areas ----------
   The pages set viewport-fit=cover, so in iPhone landscape the notch and the rounded
   corners sit over the first 47px of each side. The gutter grows to the inset there and
   stays the client's clamp everywhere else. The fixed Buddy, toasts and install pill
   already add the insets themselves. */
.wrap{padding-left:max(var(--gutter),env(safe-area-inset-left,0px));padding-right:max(var(--gutter),env(safe-area-inset-right,0px))}
@media (max-width:860px){.nav-links{padding-left:max(var(--gutter),env(safe-area-inset-left,0px));padding-right:max(var(--gutter),env(safe-area-inset-right,0px))}}

/* ---------- Gujarati labels on the photo heroes ----------
   The client's pink (#E0218A) measured 2.6 to 2.9:1 against the real photo and scrim
   pixels under the label on venue, nights and privacy at 1366 and on the home hero at iPad
   width, under the 3:1 floor for 19 to 21px bold. A lighter pink of the same hue clears
   it on the measured ground (5.44:1 on rgb(68,45,30), 8.04 on #160B26). The pink on the
   white sections is untouched. */
.hero .place .guj,.page-hero .guj{color:#FF7DBE}

/* v3.0.1 header (client request 2026-10-08). The Foundation band is gone; the mark is the
   client logo cut to its Om disc by tools/make_mark.py, and the brand reads the Gujarati name
   as the title with the festival name under it, as written, not upper cased. */
.brand .mark{width:44px;height:44px;border:0;border-radius:50%;background:#ebedee center/cover no-repeat url("../img/osf/osf-mark.webp")}
.brand .bn.guj{font-family:var(--guj);font-weight:600;font-size:1.32rem;line-height:1.15;color:var(--ink);letter-spacing:0}
.brand .bs{font-size:.8rem;font-weight:500;letter-spacing:.01em;text-transform:none;color:var(--ink-2)}

/* ---------- v3.1.0 party size buttons (V310-SPEC section 1) ----------
   Real radios in a fieldset, each stretched invisibly over its own label so a tap, a
   click and Playwright all land on the input itself, while the .face underneath paints
   the button. Checked: filled marigold with the ink the gold buttons use (#1A0F2E on
   #F5A623, 9.9:1). Unchecked: outlined on the field ground. Every button is at least 48px
   tall and 44px wide (min-height on the face, grid tracks of at least 72px that share a
   row's height), and the row wraps: at 320 the five sit 3 and 2, at 390 4 and 1, from the
   tablet widths in one line. The focus ring
   is the site's pink, drawn on the face when the hidden radio has focus-visible, so the
   arrow keys show where they are. The disabled look matches the other locked controls. */
.party-pick{border:0;padding:0;margin:0 0 6px;min-width:0}
.party-pick legend{display:block;float:none;width:100%;padding:0;font-weight:600;font-size:.875rem;margin:0 0 8px;color:var(--ink)}
.party-pick legend .opt{color:var(--ink-3);font-weight:400}
.party-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(72px,1fr));gap:8px;margin:0}
.party-btn{position:relative;display:flex;min-width:44px;margin:0;cursor:pointer}
.party-btn .face{flex:1 1 auto;width:100%}
.party-btn input[type=radio]{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;opacity:0;cursor:pointer;z-index:1;appearance:none;-webkit-appearance:none}
.party-btn .face{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:48px;padding:7px 8px;border:1px solid var(--line-strong);border-radius:var(--radius-xs);background:var(--panel-2);color:var(--ink);text-align:center;line-height:1.15;transition:background .12s ease,border-color .12s ease}
.party-btn .face .n{font-weight:700;font-size:1.08rem;font-variant-numeric:tabular-nums}
.party-btn .face .cap{font-size:.74rem;color:var(--ink-3);margin-top:3px;overflow-wrap:anywhere}
.party-btn input:checked~.face{background:var(--primary);border-color:var(--primary);color:var(--on-primary);box-shadow:0 8px 20px -12px rgba(245,166,35,.8)}
.party-btn input:checked~.face .cap{color:var(--on-primary)}
.party-btn input:focus-visible~.face{outline:3px solid var(--focus);outline-offset:2px}
.party-btn input:disabled{cursor:not-allowed}
.party-btn input:disabled~.face{opacity:.6}
@media (hover:hover){.party-btn input:not(:disabled):not(:checked):hover~.face{border-color:var(--accent-pink)}}
@media (prefers-reduced-motion:reduce){.party-btn .face{transition:none}}
/* Forced colours (Windows High Contrast): the pressed look above is only a fill and a
   border colour, both replaced by the forced palette, and the real radio is opacity 0, so
   the five buttons came out identical. A border WIDTH survives the palette: the checked
   face gets a 3px border with 2px less padding, so the box keeps its exact size, and the
   focus ring stays the separate outline at offset 2px (fix round, B #7). */
@media (forced-colors:active){
  .party-btn input:checked~.face{border-width:3px;padding:5px 6px}
}

/* ---------- v3.2.0 the group's emails and the shared pass (V320-SPEC sections 1 and 2) ----------
   Register form: one block per attendee (first name, last name, email). Phones stack the
   three fields; from 520px first and last sit side by side and the email takes the row
   under them. Tracks are minmax(0,1fr) so a long address never widens the form past a
   320px screen. The refusal sits under the attendee's own row in the form error red
   (#C8102E, 5.9:1 on white) and the field it names gets the same red edge. */
.att-block{margin:0 0 6px;min-width:0}
.att-block .lbl{display:block;font-weight:600;font-size:.875rem;margin:0 0 4px;color:var(--ink)}
.att-note{margin:0 0 12px}
.att-block .attendee-list,.att-form .attendee-list{display:grid;gap:12px;margin:0}
.att-group{min-width:0;padding:12px 12px 2px;border:1px solid var(--line);border-radius:var(--radius-xs);background:var(--panel)}
.att-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:0 12px}
@media (min-width:520px){.att-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.att-grid .att-mail{grid-column:1/-1}}
.att-grid .field{margin-bottom:12px;min-width:0}
.att-grid .field input{font-size:max(16px,1rem)}
.att-err{margin:-4px 0 10px;color:var(--accent-red);font-weight:600;font-size:.86rem;line-height:1.45}
.att-err:empty{display:none}
.field input[aria-invalid="true"]{border-color:var(--accent-red);box-shadow:0 0 0 2px color-mix(in srgb,var(--accent-red) 30%,transparent)}

/* the holder's own card: the line about the group, the saved line and the Edit group link.
   The link is a real button with a 44px hit area; its text is the site's link colour
   (#9A4E12, 6.0:1 on white). */
.att-line{margin:4px 0 0}
.att-line .note{margin:0 0 6px}
.att-open{margin:0}
.linkbtn{display:inline-flex;align-items:center;min-height:44px;min-width:44px;padding:0 2px;margin:0;border:0;background:none;color:var(--accent);font:inherit;font-size:.95rem;font-weight:600;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.linkbtn:hover{color:var(--ink)}
/* the panel itself, full width under the card */
.att-edit{margin-top:22px;padding:clamp(16px,3vw,26px);min-width:0}
.att-edit h4{font-family:var(--serif);font-size:1.2rem;margin:0 0 6px;color:var(--ink)}
.att-edit .form-note{margin:0 0 14px}
.att-edit .form-err{margin:10px 0 0}
.att-edit .btnrow{margin:14px 0 0}
#attEditOut{margin-top:14px}

/* the passes shared with this account, after the account's own */
#shared{margin-top:34px}
#pass[hidden]+#shared{margin-top:28px}
.shared-title{font-family:var(--serif);font-size:1.4rem;margin:0 0 12px;color:var(--ink)}
.shared-pass{min-width:0;padding-top:18px;border-top:1px solid var(--line)}
.shared-pass+.shared-pass{margin-top:30px}
.shared-pass:focus{outline:none}
.shared-pass:focus-visible{outline:3px solid var(--focus);outline-offset:4px;border-radius:6px}
.shared-by{margin:0 0 14px;font-weight:600;font-size:1rem;color:var(--ink);overflow-wrap:anywhere}
.shared-note{margin:0 0 18px}

/* Print: the account's own card when there is one, else the first shared card, and only
   its rendered PNG once that exists (the same never blank rule as #passOut). */
@media print{
  #register .wrap>#shared:not([hidden]){display:block !important;margin:0 !important;padding:0 !important}
  #register .wrap>#pass:not([hidden])~#shared{display:none !important}
  #shared>*:not(#sharedOut){display:none !important}
  #sharedOut>.shared-pass~.shared-pass{display:none !important}
  .shared-pass{border:0 !important;padding:0 !important}
  .shared-pass>*:not(.passgrid){display:none !important}
  .shared-pass .passgrid>*:not(.passcard):not(.passprint){display:none !important}
  .shared-pass.print-img .passcard{display:none !important}
  .shared-pass.print-img .passgrid>.passprint{display:block !important;width:90mm;max-width:100%;height:auto;margin:0 auto;break-inside:avoid;page-break-inside:avoid;visibility:visible;-webkit-print-color-adjust:exact;print-color-adjust:exact}
}
