/* ============================================================================
   glass.css — THE MATERIAL. Owned by: glass builder. Depends on: tokens.css.

   API (BRIEF §10 — fixed contract, do not rename):
     .glass + .glass--panel | --card | --bar | --pill | --inset
     modifiers: .glass--tint-court|gold|coral|turf  .glass--edge
                .glass--frost  .glass--flat
     controls:  .glass-btn (+ --primary --ghost --sm --lg --block)
                .glass-field .glass-label .glass-input .glass-select
                .glass-hint .glass-error .glass-divider

   Four rules:
     1. Never write your own backdrop-filter. If .glass cannot do it, ask.
     2. A pane over ~60% of the viewport must be .glass--flat, or be split into
        cards (BRIEF §4 rule 1).
     3. Never set background / filter / opacity / mask / mix-blend-mode on a
        .glass ELEMENT: any of those makes it a Backdrop Root and ::after then
        has nothing behind it to sample.
     4. One radius per surface. A pane is ONE layer with ONE corner; anything
        cut into it uses --r-well, controls use --r-pill. Never a third arc.

   The rim is a LIT EDGE, NOT A LIGHT SOURCE: three 1px lines, no wide band.
   Re-measure the rim peak off rendered pixels before raising any rim token.
   ========================================================================= */


/* ==========================================================================
   1. BASE PANE
   ========================================================================== */

.glass {
  --g-r: var(--r-xl);
  --g-core-blur: var(--g-blur);
  --g-core-fill: var(--g-fill);
  --g-spec: 1;                   /* rim multiplier; sections may nudge it */

  position: relative;
  z-index: 0;                    /* stacking context for the ::after layer */
  display: block;
  border-radius: var(--g-r);
  padding: clamp(18px, 2.2vw, 26px);
  color: var(--paper);
  text-shadow: var(--g-ink);     /* local scrim, inherited by descendants */
  box-shadow: var(--sh-card);
}

/* Explicitly none, so no stale rule can half-inherit the old specular rim. */
.glass::before { content: none; }

/* THE PANE: inset 0, radius inherited — one surface, one corner, one layer
   carrying the filter, the fill, the tint, the sheen and the rim. */
.glass::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;

  -webkit-backdrop-filter: blur(var(--g-core-blur)) saturate(var(--g-sat))
                           brightness(var(--g-bright)) contrast(var(--g-contrast));
          backdrop-filter: blur(var(--g-core-blur)) saturate(var(--g-sat))
                           brightness(var(--g-bright)) contrast(var(--g-contrast));

  background-color: var(--g-core-fill);
  background-image:
    linear-gradient(0deg, var(--g-tint), var(--g-tint)),
    linear-gradient(180deg, var(--g-sheen-top) 0%, transparent 40%,
                            var(--g-sheen-bot) 100%);

  box-shadow:
    inset 0  0 0 1px var(--g-rim-soft),
    inset 0  1px 0   var(--g-rim),
    inset 0 -1px 0   var(--g-rim-dark);
}

/* A nested pane must not double the material: a second filter pass inside an
   already-frosted pane buys nothing and costs a full layer. */
.glass .glass { box-shadow: var(--sh-pill); }
.glass .glass::after {
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  background-color: rgb(var(--haze-rgb) / .10);
  background-image: none;
  box-shadow: inset 0 0 0 1px rgb(var(--paper-rgb) / .08);
}


/* ==========================================================================
   2. REFRACTION — REMOVED

   Nothing here references url(#gl-refract) any more: a displacement map bends
   the BACKDROP, and the ground is now a smooth drawn gradient (BRIEF §0), so
   the lens cost ~11 filter primitives and a second backdrop-filter pass per
   pane to bend nothing visible.

   ⚠️ If a photographic ground ever returns and the lens with it, two Chromium
   facts still hold and cost a round each: a filter referenced from ANOTHER
   document (data: URI, base64, separate .svg) is a SILENT no-op, and a filter
   whose map comes from <feImage> is tainted so feDisplacementMap is silently
   dropped. The map must be built from primitives in a same-document
   <svg class="glass-defs"> block — glass-lab.html holds the master copy and
   tools/injectdefs.py propagates it. Those blocks are currently inert.
   ========================================================================== */


/* ==========================================================================
   3. SIZES  (BRIEF §10)
   ========================================================================== */

.glass--panel {
  --g-r: var(--r-2xl);
  --g-core-blur: var(--g-blur-panel);
  --g-core-fill: var(--g-fill-panel);
  padding: clamp(22px, 3vw, 40px);
  box-shadow: var(--sh-contact);
}

.glass--card {
  --g-r: var(--r-xl);
  --g-core-blur: var(--g-blur);
  --g-core-fill: var(--g-fill);
  padding: clamp(16px, 1.8vw, 22px);
}

.glass--bar {
  --g-r: var(--r-pill);
  --g-core-blur: var(--g-blur-bar);
  --g-core-fill: var(--g-fill-bar);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 8px 10px;
  box-shadow: var(--sh-bar);
}

.glass--pill {
  --g-r: var(--r-pill);
  --g-core-blur: var(--g-blur-pill);
  --g-core-fill: var(--g-fill-pill);
  display: inline-flex;
  align-items: center;
  gap: .45em;
  padding: 6px 14px;
  min-height: 30px;
  border-radius: var(--r-pill);
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.2;
  white-space: nowrap;
  box-shadow: var(--sh-pill);
}

/* A well is cut INTO a pane, so it has no rim and no filter of its own — the
   pane behind it is already frosted. --r-well keeps its corner from echoing
   the surface arc (that echo was the client's "multiple corners"). */
.glass--inset {
  --g-r: var(--r-well);
  padding: clamp(12px, 1.4vw, 18px);
  background-color: var(--g-fill-inset);
  box-shadow:
    inset 0 2px 4px rgb(2 5 16 / .46),
    inset 0 0 0 1px rgb(2 5 16 / .34);
  text-shadow: var(--g-ink-soft);   /* already dark; go light on the scrim */
}
.glass--inset::before,
.glass--inset::after { display: none; }


/* ==========================================================================
   4. TINTS  (BRIEF §10 — names are a fixed contract)
   Four positions on one cobalt scale plus the single accent, ~.10 alpha, so
   they colour what you see through the pane instead of hiding it.
   ========================================================================== */

.glass--tint-court { --g-tint: rgb(var(--blue-300-rgb) / .10); }
.glass--tint-turf  { --g-tint: rgb(var(--navy-700-rgb) / .16); }
.glass--tint-gold  { --g-tint: rgb(var(--ball-rgb) / .05);
                     --g-rim-soft: rgb(var(--ball-rgb) / .20); }
.glass--tint-coral { --g-tint: rgb(var(--ball-deep-rgb) / .08);
                     --g-rim-soft: rgb(var(--ball-rgb) / .28); }


/* ==========================================================================
   5. MODIFIERS  (BRIEF §10)
   ========================================================================== */

/* Focal surface. It is lifted off the ground, NOT lit brighter — a brighter
   rim here is what produced the white corner bloom the client rejected. */
.glass--edge { --g-spec: 1.1; box-shadow: var(--sh-lift); }

/* The one dense surface: for a paragraph over a genuinely light region. Every
   .frost is a hole in the see-through-ness, so use it sparingly. */
.glass--frost {
  --g-core-blur: var(--g-blur-frost);
  --g-core-fill: var(--g-fill-frost);
  --g-spec: .85;
}

/* No blur at all — mandatory on anything that moves (BRIEF §4 rule 2). */
.glass--flat,
.glass--flat::after {
  -webkit-backdrop-filter: none !important;
          backdrop-filter: none !important;
}
.glass--flat {
  --g-core-fill: var(--g-fill-flat);
  background-color: transparent;
}


/* ==========================================================================
   6. BUTTONS  (BRIEF §10)
   One filter pass, no pseudo-element ring, no transform on hover/press — a
   blurred surface must never move (BRIEF §4 rule 2), so the press reads
   through fill and inner shadow.
   ========================================================================== */

.glass-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55em;
  min-height: 44px;
  min-width: 44px;
  padding: 0 24px;
  border-radius: var(--r-pill);
  font-family: var(--font-ui);
  font-size: .95rem;
  font-weight: var(--fw-semi);
  letter-spacing: .012em;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  color: var(--paper);
  text-shadow: var(--g-ink);     /* a control can appear outside a pane */
  background-color: rgb(var(--blue-300-rgb) / .30);
  -webkit-backdrop-filter: blur(11px) saturate(1.6) brightness(.94);
          backdrop-filter: blur(11px) saturate(1.6) brightness(.94);
  box-shadow:
    inset 0 1px 0  rgb(var(--paper-rgb) / .16),
    inset 0 0 0 1px rgb(var(--haze-rgb) / .22),
    inset 0 -1px 0 rgb(2 5 16 / .34),
    var(--sh-pill);
  transition:
    background-color var(--dur-1) var(--ease-glass),
    color            var(--dur-1) var(--ease-glass),
    opacity          var(--dur-1) var(--ease-glass);
}

.glass-btn:hover,
.glass-btn[data-state="hover"] { background-color: rgb(var(--blue-100-rgb) / .46); }

/* [data-state] mirrors :hover / :active so screenshots can pin a state
   without a pointer. Never set it in production markup. */
.glass-btn:active,
.glass-btn[data-state="active"] {
  background-color: rgb(var(--navy-800-rgb) / .62);
  box-shadow:
    inset 0 2px 6px rgb(2 5 16 / .60),
    inset 0 0 0 1px rgb(var(--haze-rgb) / .22),
    0 2px 6px -4px rgb(2 5 16 / .6);
}

.glass-btn:focus-visible {
  outline: none;
  box-shadow:
    inset 0 0 0 1px rgb(var(--haze-rgb) / .22),
    var(--focus-ring);
}

.glass-btn[disabled],
.glass-btn[aria-disabled="true"],
.glass-btn--disabled {
  cursor: not-allowed;
  opacity: .42;
  color: var(--paper-mute);
  background-color: rgb(var(--navy-800-rgb) / .40);
  box-shadow: inset 0 0 0 1px rgb(var(--haze-rgb) / .16);
}

/* PRIMARY — the one accent. Opaque, so it needs no filter at all. */
.glass-btn--primary {
  color: var(--navy-900);
  text-shadow: none;             /* dark ink on an opaque accent */
  background-color: var(--ball);
  background-image: linear-gradient(184deg,
    rgb(255 255 255 / .14) 0%, rgb(255 255 255 / 0) 46%,
    rgb(var(--ball-deep-rgb) / .42) 100%);
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  box-shadow:
    inset 0 1px 0  rgb(255 255 255 / .24),
    inset 0 -1px 0 rgb(var(--navy-900-rgb) / .24),
    var(--sh-pill);
}
.glass-btn--primary:hover,
.glass-btn--primary[data-state="hover"] { background-color: #D3E779; }
.glass-btn--primary:active,
.glass-btn--primary[data-state="active"] {
  background-color: var(--ball-deep);
  box-shadow: inset 0 2px 6px rgb(var(--navy-900-rgb) / .38),
              0 2px 6px -4px rgb(2 5 16 / .6);
}
.glass-btn--primary[disabled] { color: var(--paper-mute); background-image: none; }

/* GHOST — a rim and nothing else. Cheapest control on the site. */
.glass-btn--ghost {
  color: var(--paper);
  background-color: transparent;
  background-image: none;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  box-shadow: inset 0 0 0 1px rgb(var(--haze-rgb) / .40);
}
.glass-btn--ghost:hover,
.glass-btn--ghost[data-state="hover"] { background-color: rgb(var(--haze-rgb) / .14); }
.glass-btn--ghost:active,
.glass-btn--ghost[data-state="active"] {
  background-color: rgb(2 5 16 / .34);
  box-shadow: inset 0 0 0 1px rgb(var(--haze-rgb) / .5);
}

.glass-btn--sm  { min-height: 36px; padding: 0 16px; font-size: .82rem; }
.glass-btn--lg  { min-height: 54px; padding: 0 34px; font-size: 1.02rem; }
.glass-btn--block { display: flex; width: 100%; }
@media (pointer: coarse) { .glass-btn--sm { min-height: 44px; } }


/* ==========================================================================
   7. FORM CONTROLS  (BRIEF §10)
   Inputs are wells cut into a pane that is already frosted, so they carry no
   backdrop-filter of their own — the fill alone makes them read as holes.
   ========================================================================== */

.glass-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}

/* --haze is a BACKGROUND token; as label ink it measures 3.93:1. Labels get
   --paper-dim plus their own scrim, because 11px uppercase at .14em tracking
   is the thinnest ink on the site. */
.glass-label {
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--paper-dim);
  text-shadow: var(--g-ink);
}

.glass-input,
.glass-select,
textarea.glass-input {
  width: 100%;
  min-height: 48px;
  padding: 12px 16px;
  border: 0;
  border-radius: var(--r-well);   /* the single inner radius — see tokens §4 */
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.4;
  color: var(--paper);
  text-shadow: none;              /* a well is already dark */
  background-color: var(--g-fill-inset);
  box-shadow:
    inset 0 2px 5px rgb(2 5 16 / .52),
    inset 0 0 0 1px rgb(2 5 16 / .40);
  transition: box-shadow var(--dur-1) var(--ease-glass),
              background-color var(--dur-1) var(--ease-glass);
}
textarea.glass-input { min-height: 120px; resize: vertical; }

/* 16px normal weight, so WCAG 1.4.3 applies in full: --paper-mute over the
   well measures 8:1+ and still reads as a hint. --haze/.62 measured 3.07:1. */
.glass-input::placeholder { color: var(--paper-mute); opacity: 1; }

.glass-input:hover,
.glass-select:hover { background-color: rgb(8 14 34 / .78); }

.glass-input:focus-visible,
.glass-select:focus-visible {
  outline: none;
  background-color: rgb(8 14 34 / .82);
  box-shadow:
    inset 0 2px 5px rgb(2 5 16 / .55),
    inset 0 0 0 1px rgb(var(--ball-rgb) / .55),
    var(--focus-ring);
}

.glass-select {
  appearance: none;
  padding-right: 42px;
  cursor: pointer;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%237C99B6' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 12px 8px;
}
.glass-select option { background: var(--navy-800); color: var(--paper); }

.glass-input[aria-invalid="true"],
.glass-select[aria-invalid="true"] {
  box-shadow:
    inset 0 2px 5px rgb(2 5 16 / .55),
    inset 0 0 0 1.5px rgb(var(--ball-deep-rgb) / .85);
}

.glass-hint {
  font-size: var(--fs-xs);
  color: var(--paper-dim);   /* dim, not mute: hints are read */
}

.glass-error {
  display: flex;
  align-items: center;
  gap: .4em;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: .04em;
  color: var(--ball);
}
.glass-error:empty { display: none; }
.glass-error::before { content: "▲"; font-size: .7em; line-height: 1; }

.glass-divider {
  height: 1px;
  border: 0;
  margin: var(--sp-4) 0;
  background: linear-gradient(90deg, transparent,
    rgb(2 5 16 / .5) 20%, rgb(2 5 16 / .5) 80%, transparent);
}


/* ==========================================================================
   8. FALLBACK — no backdrop-filter (BRIEF §4)
   Never ship an unreadable transparent panel: go solid, keep the rim.
   ========================================================================== */

@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .glass::after       { background-color: rgb(16 29 68 / .96); }
  .glass--frost::after{ background-color: rgb(11 21 52 / .98); }
  .glass--inset,
  .glass-input,
  .glass-select { background-color: rgb(6 11 30 / .96); }
  .glass-btn    { background-color: rgb(36 60 116 / .96); }
  .glass-btn--ghost { background-color: transparent; }
}


/* ==========================================================================
   9. MOTION POLICY
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .glass, .glass::after,
  .glass-btn, .glass-input, .glass-select {
    transition: none !important;
    animation: none !important;
  }
}
