/* Liquid glass.

   The technique is the real one, not a gradient pretending to be glass: a baked
   rounded rect displacement map is fed to feDisplacementMap so the backdrop is
   genuinely refracted and bends at the edges, three times at slightly different
   scales so the fringe splits into colour the way real glass does, over a
   blurred and saturated backdrop, under two masked rim layers that catch a
   specular highlight. Ported from rdev/liquid-glass-react to plain CSS because
   this app carries no framework, and baked at build time because generating the
   map per element would mean 250 phones each running the same canvas.

   Glass needs something behind it or it is just a grey box, so anything wearing
   it has to sit over the brand ground, never over flat paper.

   The filter itself is injected once by js/glass.js. Nothing here assumes it
   worked: the @supports ladder below degrades to blur alone, then to a solid
   surface, and the component still reads correctly at every step. On the
   register form that matters more than the effect does. */

:root {
  --glass-tint: rgba(255, 255, 255, .07);
  --glass-tint-strong: rgba(255, 255, 255, .16);
  --glass-rim: rgba(255, 255, 255, .55);
  --glass-shadow: 0 12px 40px rgba(0, 0, 0, .25);
  --glass-blur: 34px;
}

/* The ground. A large, very low contrast wash of the brand colour, so the glass
   has something with structure to refract. Two soft pools rather than a linear
   gradient, because a linear gradient bends into nothing. */
.glass-ground {
  position: relative;
  background:
    radial-gradient(70% 46% at 78% 8%,  color-mix(in srgb, var(--brand-mid) 92%, #fff) 0%, transparent 62%),
    radial-gradient(58% 38% at 8%  32%, color-mix(in srgb, var(--brand-mid) 70%, transparent) 0%, transparent 64%),
    radial-gradient(85% 45% at 50% 100%, color-mix(in srgb, var(--brand) 40%, #000) 0%, transparent 70%),
    var(--brand);
}

/* Where the brand has photography, the glass sits on that instead. This is the
   whole point of the material: refracting a gradient produces a gradient and
   looks like nothing, refracting a photograph bends a horizon and a treeline at
   the pane's edge, which is what makes it read as glass. The gradient above
   stays underneath as the paint-in and as the answer for brands with no imagery
   yet. */
.glass-ground[data-ground] {
  background-image:
    linear-gradient(180deg,
      color-mix(in srgb, var(--brand) 55%, transparent) 0%,
      color-mix(in srgb, var(--brand) 72%, transparent) 55%,
      color-mix(in srgb, var(--brand) 94%, #000) 100%),
    var(--ground-image);
  background-size: auto, cover;
  background-position: center, center top;
  background-repeat: no-repeat, no-repeat;
  background-attachment: scroll, fixed;
  background-color: var(--brand);
}

/* ------------------------------------------------------------------ surface */

.glass {
  position: relative;
  isolation: isolate;
  border-radius: 18px;
  background:
    linear-gradient(180deg, var(--glass-tint), rgba(255, 255, 255, .03)),
    color-mix(in srgb, var(--brand) 34%, transparent);
  box-shadow: var(--glass-shadow);
  color: #fff;
}

/* The refracting pane. Kept as a child rather than on .glass itself so the
   content on top is never displaced along with the backdrop. */
.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
}

/* The rim. One masked ring carrying an angled highlight, so the edge catches
   light on one side and falls away on the other. Two blend modes stacked, screen
   for the bright side and overlay for the body, which is what gives the edge its
   thickness instead of a flat 1px stroke. */
.glass::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  pointer-events: none;
  background: linear-gradient(
    var(--glass-angle, 135deg),
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, .32) 33%,
    rgba(255, 255, 255, .60) 66%,
    rgba(255, 255, 255, 0) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  mix-blend-mode: overlay;
  box-shadow:
    0 0 0 .5px rgba(255, 255, 255, .5) inset,
    0 1px 3px rgba(255, 255, 255, .25) inset,
    0 1px 4px rgba(0, 0, 0, .35);
}

/* Refraction, only where the browser actually has it. Everything above already
   stands on its own, so this is the layer that is allowed to be missing. */
html.glass-refract .glass::before { filter: url(#liquid-glass); }

/* ------------------------------------------------------------------ buttons */

.btn.glass {
  border: 0;
  background: var(--glass-tint-strong);
  color: #fff;
  border-radius: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
  transition: transform .16s cubic-bezier(.2, .8, .2, 1), background .16s ease;
}
.btn.glass:hover { background: rgba(255, 255, 255, .22); }
/* Apple's glass controls squash into the press rather than dropping down. */
.btn.glass:active { transform: scale(.975); }
.btn.glass:disabled { opacity: .45; transform: none; }

/* ------------------------------------------------------------------- fields */

.glass-form .field label { color: rgba(255, 255, 255, .78); }
.glass-form input,
.glass-form select,
.glass-form textarea {
  background-color: rgba(0, 0, 0, .14);
  border: 1px solid rgba(255, 255, 255, .26);
  color: #fff;
  border-radius: 13px;
  -webkit-backdrop-filter: blur(10px) saturate(150%);
          backdrop-filter: blur(10px) saturate(150%);
  box-shadow: 0 0 0 .5px rgba(255, 255, 255, .35) inset, 0 1px 2px rgba(0, 0, 0, .18);
}
.glass-form input::placeholder,
.glass-form textarea::placeholder { color: rgba(255, 255, 255, .45); }
.glass-form input:focus,
.glass-form select:focus,
.glass-form textarea:focus {
  border-color: rgba(255, 255, 255, .70);
  background-color: rgba(255, 255, 255, .16);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .14);
}
/* The default caret is drawn from --ink-soft and disappears on a dark pane. */
.glass-form select {
  background-image: linear-gradient(45deg, transparent 50%, rgba(255,255,255,.75) 50%),
                    linear-gradient(135deg, rgba(255,255,255,.75) 50%, transparent 50%);
}
.glass-form .field.invalid input,
.glass-form .field.invalid select { border-color: #FF8A80; }
.glass-form .field .error { color: #FF8A80; }

/* -------------------------------------------------------------- choice rows */

.glass .choice, .glass-form .choice {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .18);
  color: #fff;
}
.glass-form .choice:hover { border-color: rgba(255, 255, 255, .45); }
.glass-form .choice .dot { border-color: rgba(255, 255, 255, .45); }
.glass-form .choice[aria-checked="true"] {
  background: rgba(255, 255, 255, .18);
  border-color: rgba(255, 255, 255, .75);
}
.glass-form .choice[aria-checked="true"] .dot {
  border-color: #fff; background: #fff;
  box-shadow: inset 0 0 0 4px color-mix(in srgb, var(--brand) 80%, #000);
}

/* ---------------------------------------------------------------- fallbacks */

/* No backdrop-filter at all. Rather than leave a transparent pane with unreadable
   text over it, the surface goes solid in the brand's own dark. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: color-mix(in srgb, var(--brand) 82%, #000); }
  .glass-form input, .glass-form select, .glass-form textarea { background: rgba(0, 0, 0, .28); }
  .btn.glass { background: rgba(255, 255, 255, .24); }
}

/* Someone who has asked the system to calm animation down does not want a
   button that squashes, and blur is the most expensive thing on the page. */
@media (prefers-reduced-motion: reduce) {
  .btn.glass:active { transform: none; }
}
@media (prefers-reduced-transparency: reduce) {
  .glass::before { -webkit-backdrop-filter: none; backdrop-filter: none; }
  .glass { background: color-mix(in srgb, var(--brand) 86%, #000); }
}

/* ------------------------------------------------------------- dark ground */

/* base.css sets its ink for a white page. Anything standing on the brand ground
   has to be re-inked or it is black text on a dark blue field. */
.glass-ground {
  color: #fff;
  min-height: 100%;
  background-attachment: fixed;
}
.glass-ground h1, .glass-ground h2, .glass-ground h3 { color: #fff; }
.glass-ground .soft, .glass-ground .help, .glass-ground .small { color: rgba(255, 255, 255, .70); }
.glass-ground .status { color: rgba(255, 255, 255, .70); }
.glass-ground .topbar { background: transparent; }
.glass-ground .card { border: 0; }
/* The photo well is a light grey box in base.css, which reads as a hole. */
.glass-ground .shot {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .20);
}
.glass-ground .shot .ph { color: rgba(255, 255, 255, .50); }

/* --------------------------------------------------------------- the pass */

/* The QR is the one thing on the site a machine has to read, at a desk, under
   whatever lighting the venue has. It stays solid white on solid black with a
   quiet zone around it. No tint, no blur, no glass behind it. */
.glass-ground .ticket .qr .box,
.glass-ground .ticket .qr .box img,
.glass-ground .ticket .qr .box canvas {
  background: #fff;
}
.glass-ground .ticket .qr .box {
  padding: 10px;
  border-radius: 12px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .30);
}
.glass-ground .ticket .qr .code { color: rgba(255, 255, 255, .82); }
.glass-ground .ticket .head .k { color: rgba(255, 255, 255, .62); }
.glass-ground .ticket .head .v { color: #fff; }
.glass-ground .ticket .rows { color: rgba(255, 255, 255, .88); }

/* ------------------------------------------------------------- step cards */

/* base.css paints these white for a white page. On the ground they become the
   same material as everything else, one step down in weight so they read as
   content rather than as chrome. */
.glass-ground .stepcard,
.glass-ground .row,
.glass-ground .panel {
  background: rgba(255, 255, 255, .07);
  border-color: rgba(255, 255, 255, .16);
  color: #fff;
}
.glass-ground .stepcard .meta,
.glass-ground .row .meta { color: rgba(255, 255, 255, .66); }

/* .btn.ghost is a transparent outline on white in base.css, which vanishes on
   the ground. Given glass it becomes the quieter of two glass buttons. */
.btn.glass.ghost {
  background: rgba(255, 255, 255, .06);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .28);
}
.btn.glass.ghost:hover { background: rgba(255, 255, 255, .13); }

/* --------------------------------------------------------- ground coverage */

/* base.css paints html as well as body, so a short page showed a band of the
   light page colour under the ground. The ground has to own the whole viewport
   or the seam is visible on every page that does not fill the screen. */
html:has(> body.glass-ground) { background: var(--brand); }
.glass-ground { min-height: 100vh; }

/* Any card on the ground is the same material, not a white slab. Pages build
   their own cards in JS with their own class names, so this keys off .card
   rather than trying to name each one. */
.glass-ground .card {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, .03)),
    color-mix(in srgb, var(--brand) 34%, transparent);
  border: 1px solid rgba(255, 255, 255, .16);
  color: #fff;
  -webkit-backdrop-filter: blur(22px) saturate(170%);
          backdrop-filter: blur(22px) saturate(170%);
  box-shadow: 0 10px 34px rgba(0, 0, 0, .22);
}
/* .glass carries its own pane and rim, so it must not be given a second one. */
.glass-ground .card.glass { background: none; border: 0; backdrop-filter: none; -webkit-backdrop-filter: none; }
.glass-ground .card.glass {
  background:
    linear-gradient(180deg, var(--glass-tint), rgba(255, 255, 255, .03)),
    color-mix(in srgb, var(--brand) 34%, transparent);
  box-shadow: var(--glass-shadow);
}

/* Hairlines and secondary type inside those cards were drawn for a white page. */
.glass-ground .card .t,
.glass-ground .slot .t { color: rgba(255, 255, 255, .66); }
.glass-ground .slot { border-top-color: rgba(255, 255, 255, .16); }
.glass-ground .day h2 { color: #fff; }
