/* Sydney Standard glass system.
   Surfaces: .glass (panel), .glass--quiet (lists, FAQ), .glass--dark (on black).
   Controls: .btn, .btn--primary, .btn--glass, .input.
   Light comes from above: a bright top edge, a shadow that falls down,
   and a soft sheen that follows the pointer (set by site.js via --mx / --my). */

/* Registered so the blur can animate on the hero card as it "forms". */
@property --blur {
  syntax: "<length>";
  inherits: true;
  initial-value: 24px;
}

.glass {
  --glass-blur: 24px;
  --blur: var(--glass-blur);
  --r: var(--r-card);
  position: relative;
  isolation: isolate;
  border-radius: var(--r);
  color: var(--ink);
  background: linear-gradient(180deg, rgb(255 255 255 / .76), rgb(255 255 255 / .58));
  -webkit-backdrop-filter: blur(var(--blur)) saturate(1.6);
  backdrop-filter: blur(var(--blur)) saturate(1.6);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .95),
    0 0 0 1px rgb(20 23 28 / .07),
    0 1px 2px rgb(20 23 28 / .06),
    0 14px 36px rgb(20 23 28 / .10);
}

/* Sheen: a pool of light under the pointer, resting top-left until touched. */
.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(440px circle at var(--mx, 22%) var(--my, 0%), rgb(255 255 255 / .9), transparent 60%);
  opacity: 0;
  transition: opacity .35s ease;
}
.glass[data-glow]::before { opacity: .38; }
.glass[data-glow]:hover::before,
.glass[data-glow]:focus-within::before { opacity: 1; }

/* Rim light: a 1px edge that brightens near the pointer. */
.glass::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  pointer-events: none;
  background:
    radial-gradient(280px circle at var(--mx, 22%) var(--my, 0%), #fff, rgb(255 255 255 / 0) 70%),
    linear-gradient(180deg, rgb(255 255 255 / .95), rgb(255 255 255 / .18));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}

.glass--pill { --r: 999px; }

.glass--quiet {
  --glass-blur: 16px;
  background: rgb(255 255 255 / .62);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .95), 0 0 0 1px rgb(20 23 28 / .08), 0 6px 18px rgb(20 23 28 / .05);
}
.glass--quiet::before, .glass--quiet::after { display: none; }

.glass--dark {
  color: #fff;
  background: linear-gradient(180deg, rgb(20 23 28 / .54), rgb(20 23 28 / .68));
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .38),
    0 0 0 1px rgb(255 255 255 / .14),
    0 28px 64px rgb(20 23 28 / .4);
}
.glass--dark::before {
  background: radial-gradient(440px circle at var(--mx, 22%) var(--my, 0%), rgb(255 255 255 / .2), transparent 60%);
}
.glass--dark::after {
  background:
    radial-gradient(280px circle at var(--mx, 22%) var(--my, 0%), rgb(255 255 255 / .9), rgb(255 255 255 / 0) 70%),
    linear-gradient(180deg, rgb(255 255 255 / .5), rgb(255 255 255 / .08));
}

/* The one moment: on load the glass forms over the stage. */
@media (prefers-reduced-motion: no-preference) {
  .stage__slab { animation: slab-wipe .9s cubic-bezier(.7, 0, .2, 1) both; }
  .stage__disc { animation: disc-rise 1s cubic-bezier(.2, .7, .2, 1) .12s both; }
  .hero-card { animation: glass-form 1.1s cubic-bezier(.2, .7, .2, 1) .3s both; }
}
@keyframes slab-wipe { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0); } }
@keyframes disc-rise { from { transform: scale(.62); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes glass-form {
  from { --blur: 0px; opacity: 0; transform: translateY(18px); }
  to   { --blur: 24px; opacity: 1; transform: none; }
}

/* Buttons: 48px tall, 24px side padding, sentence-case verb plus object. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 24px;
  border: 0;
  border-radius: 999px;
  font: 600 1.0625rem/1 var(--font);
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  transition: box-shadow .2s ease, background-color .2s ease, transform .12s ease;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn--sm { min-height: 44px; padding: 0 20px; font-size: 1rem; }

/* Primary: Harbour, reserved for the one action per section. */
.btn--primary {
  color: #fff;
  background: linear-gradient(180deg, rgb(255 255 255 / .14), rgb(255 255 255 / 0) 55%), var(--harbour);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .28), 0 8px 24px rgb(14 90 82 / .28);
}
.btn--primary:hover {
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .4), inset 0 0 0 1px rgb(255 255 255 / .35), 0 10px 28px rgb(14 90 82 / .38);
}
/* On Ink, Harbour light carries the action, as the brand rules allow. */
.on-dark .btn--primary {
  color: var(--ink);
  background: var(--harbour-light);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .5), 0 0 0 1px rgb(124 196 184 / .6);
}
.on-dark .btn--primary:hover { box-shadow: inset 0 1px 0 rgb(255 255 255 / .6), 0 0 0 3px rgb(124 196 184 / .45); }

/* Secondary: glass with a 1px edge that holds 3:1 against the page. */
.btn--glass {
  color: var(--ink);
  background: rgb(255 255 255 / .5);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .95), 0 0 0 1px rgb(20 23 28 / .5);
}
.btn--glass:hover {
  background: rgb(255 255 255 / .88);
  box-shadow: inset 0 1px 0 #fff, 0 0 0 1px rgb(20 23 28 / .8), 0 8px 20px rgb(20 23 28 / .10);
}
.on-dark .btn--glass {
  color: #fff;
  background: rgb(255 255 255 / .12);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .4), 0 0 0 1px rgb(255 255 255 / .55);
}
.on-dark .btn--glass:hover {
  background: rgb(255 255 255 / .22);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .55), 0 0 0 1px #fff;
}
.btn[disabled] { cursor: progress; opacity: .85; }

/* Fields */
.field { display: grid; gap: 8px; }
.field label { font-weight: 600; }
.input {
  width: 100%;
  min-height: 52px;
  padding: 14px 16px;
  border: 0;
  border-radius: var(--r-field);
  font: inherit;
  color: var(--ink);
  background: rgb(255 255 255 / .6);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .95), 0 0 0 1px rgb(20 23 28 / .5);
  transition: box-shadow .2s ease, background-color .2s ease;
}
textarea.input { min-height: 168px; resize: vertical; line-height: 1.5; }
.input::placeholder { color: var(--ink-3); opacity: 1; }
.input:hover { background: rgb(255 255 255 / .8); }
.input:focus { outline: none; background: #fff; box-shadow: inset 0 1px 0 #fff, 0 0 0 2px var(--ink), 0 8px 20px rgb(20 23 28 / .10); }
.input:focus-visible { outline: none; }

/* Failure is a field change plus words. Signal red is for errors only. */
.input[aria-invalid="true"] {
  background: var(--signal);
  color: #fff;
  box-shadow: 0 0 0 1px var(--signal);
}
.input[aria-invalid="true"]::placeholder { color: rgb(255 255 255 / .8); }
.field-error { display: none; align-items: flex-start; gap: 8px; font-weight: 600; }
.field-error svg { flex: none; margin-top: 3px; }
.field[data-invalid="true"] .field-error { display: flex; }
.form-grid { display: grid; gap: 18px; }
.form-status { min-height: 1.5em; font-weight: 600; }
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

/* Fallbacks: no backdrop-filter, or the person asks for less transparency. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: rgb(255 255 255 / .94); }
  .glass--dark { background: rgb(20 20 20 / .94); }
  .btn--glass, .input { background: rgb(255 255 255 / .92); }
  .on-dark .btn--glass { background: rgb(40 40 40 / .94); }
}
@media (prefers-reduced-transparency: reduce) {
  .glass, .btn--glass, .input { -webkit-backdrop-filter: none; backdrop-filter: none; }
  .glass { background: #fff; }
  .glass--dark { background: #1a1a1a; }
  .btn--glass, .input { background: #fff; }
  .on-dark .btn--glass { background: #2a2a2a; }
}
@media (forced-colors: active) {
  .glass, .btn--glass, .input { border: 1px solid CanvasText; }
  .glass::before, .glass::after { display: none; }
}

/* Technique: refractive glass. An SVG displacement filter bends the backdrop.
   Chromium only (Safari drops the whole backdrop-filter on url()), so site.js adds
   html.refract for Chromium and everything else keeps the plain blur above. */
.refract .glass--bend {
  /* Light blur after the displacement (about 4px at rest): a heavy blur would smooth the bend away. */
  backdrop-filter: url(#ss-bend) blur(calc(var(--blur) / 6)) saturate(1.6);
}

/* Technique: image glow. A blurred, saturated, oversized copy of the picture sits behind it,
   so the glow always takes its colour from the picture itself.
   Parent needs isolation: isolate so the z-index: -1 stays inside it. */
.glow::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: inherit;
  filter: blur(40px) saturate(1.8);
  scale: 1.1;
}

/* Technique: Tide download button. The ring is the button's own rim. */
@property --fill  { syntax: "<color>"; inherits: true; initial-value: #14171C; }
@property --on    { syntax: "<color>"; inherits: true; initial-value: #fff; }
@property --track { syntax: "<color>"; inherits: true; initial-value: rgb(255 255 255 / .28); }

.tide {
  --fill: #14171C;
  --on: #fff;
  --track: rgb(255 255 255 / .28);
  display: inline-grid;
  justify-items: center;
  gap: 14px;
  transition: --fill .32s ease, --on .32s ease, --track .32s ease;
}
.tide__btn {
  display: block;
  width: 124px;
  aspect-ratio: 1;
  border-radius: 50%;
  color: var(--on);
  background: var(--fill);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .3), 0 12px 30px rgb(20 23 28 / .22);
  transition: box-shadow .2s ease, transform .12s ease;
  -webkit-tap-highlight-color: transparent;
}
.tide__btn:hover { box-shadow: inset 0 1px 0 rgb(255 255 255 / .45), 0 0 0 2px var(--harbour), 0 12px 30px rgb(20 23 28 / .22); }
.tide__btn:active { transform: translateY(1px); }
.tide__btn svg { display: block; width: 100%; height: 100%; overflow: visible; }
.tide__track { fill: none; stroke: var(--track); stroke-width: 3.7; }
.tide__arc { fill: none; stroke: var(--on); stroke-width: 3.7; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100; }
.tide__pip { fill: var(--on); opacity: 0; }
.tide__glyph path { fill: none; stroke: var(--on); stroke-width: 2.9; stroke-linecap: round; stroke-linejoin: round; }
.tide__pct { fill: var(--on); font: 600 9px var(--font); text-anchor: middle; opacity: 0; transition: opacity .2s ease; }
.tide[data-state="run"] .tide__pct { opacity: 1; }
.tide[data-state="run"] .tide__pip, .tide[data-state="stall"] .tide__pip { opacity: 1; }
/* Stall holds the ring on charcoal. Failure inverts the field, so the ink stays dark on sand. */
.tide[data-state="stall"] { --fill: #333333; }
.tide[data-state="fail"] { --fill: #B3261E; --on: #fff; --track: rgb(255 255 255 / .28); }
.tide__label { font-weight: 600; text-align: center; min-height: 1.5em; }

/* Type: Archivo (expanded) for headings and controls, Newsreader for reading text. */
h1, h2, h3, .nav-links a, summary, .facts, .note, .footer-meta, .footer-grid h2, label, .input,
.steps li::before, .todo, .tide__label, .field-error { font-family: var(--font); }
h1, h2 { font-stretch: 125%; letter-spacing: -0.02em; }
h3 { font-stretch: 112%; }
.field-error { color: var(--signal); }
.wordmark img { display: block; height: 22px; width: auto; }
.footer-logo { display: block; height: 72px; width: auto; }

.about-grid--solo { grid-template-columns: minmax(0, 46rem); }
.about-grid--solo .about-copy { display: grid; gap: 16px; }
@media (max-width: 760px) { .wordmark img { height: 17px; } .footer-logo { height: 60px; } }

/* Touch and small screens: the same light, driven by scroll instead of a pointer.
   Desktop has a sheen that follows the cursor, a bead in the nav and refractive glass.
   A phone has no cursor, so the light travels with the thumb: each card is lit as it crosses
   the screen, things rise into place as they arrive, and the hero shapes drift at different
   speeds. This is progressive enhancement. Without scroll-driven animation the page is still,
   and with reduced motion on nothing below runs. */
@property --mx { syntax: "<length-percentage>"; inherits: true; initial-value: 22%; }
@property --my { syntax: "<length-percentage>"; inherits: true; initial-value: 0%; }

@media (hover: none) {
  .glass[data-glow]::before { opacity: .7; }
  .glass[data-glow]:active::before { opacity: 1; }
}

@media (max-width: 760px) {
  .js .nav-links a[aria-current="page"] { gap: 10px; }
  .js .nav-links a[aria-current="page"]::before {
    content: "";
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--harbour);
    box-shadow: 0 0 0 4px rgb(14 90 82 / .14), 0 0 12px rgb(14 90 82 / .5);
  }
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes menu-in { from { opacity: 0; translate: 0 -10px; } }
  @media (max-width: 760px) {
    .js .nav[data-open="true"] .nav-links > li { animation: menu-in .34s cubic-bezier(.2, .7, .2, 1) backwards; }
    .js .nav[data-open="true"] .nav-links > li:nth-child(2) { animation-delay: .04s; }
    .js .nav[data-open="true"] .nav-links > li:nth-child(3) { animation-delay: .08s; }
    .js .nav[data-open="true"] .nav-links > li:nth-child(4) { animation-delay: .12s; }
  }

  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    @media (hover: none), (max-width: 760px) {
      @keyframes rise-in { from { opacity: 0; translate: 0 28px; } }
      @keyframes sheen-travel { from { --mx: 8%; --my: 105%; } to { --mx: 92%; --my: -5%; } }
      @keyframes drift-slow { to { translate: 0 -20%; } }
      @keyframes drift-fast { to { translate: 0 -36%; } }
      @keyframes surface-up { from { translate: 0 40%; } }

      /* Arrive: fade and rise over the first part of the entry. */
      .statement, .steps > li, .faq, .section-head, .pov blockquote, .about-copy, .experience, .tide-card {
        animation: rise-in linear backwards;
        animation-timeline: view();
        animation-range: entry 0% entry 45%;
      }

      /* Lit cards also carry the sheen across as they pass through the screen. */
      .glass[data-glow]:not(.hero-card) {
        animation: rise-in linear backwards, sheen-travel linear both;
        animation-timeline: view(), view();
        animation-range: entry 0% entry 45%, cover;
      }
      .glass.hero-card[data-glow] {
        animation: glass-form 1.1s cubic-bezier(.2, .7, .2, 1) .3s both, sheen-travel linear both;
        animation-timeline: auto, view();
        animation-range: normal, cover;
      }

      /* Depth: the hero shapes lift away at different rates as the hero leaves; the closing band rises into place. */
      .hero .stage { view-timeline: --hero block; }
      .hero .stage__disc {
        animation: disc-rise 1s cubic-bezier(.2, .7, .2, 1) .12s both, drift-slow linear both;
        animation-timeline: auto, --hero;
        animation-range: normal, exit;
      }
      .hero .stage__ring { animation: drift-fast linear both; animation-timeline: --hero; animation-range: exit; }

      .cta-band { view-timeline: --cta block; }
      .cta-band .stage__disc {
        animation: disc-rise 1s cubic-bezier(.2, .7, .2, 1) .12s both, surface-up linear both;
        animation-timeline: auto, --cta;
        animation-range: normal, entry 0% cover 55%;
      }
      .cta-band .stage__ring { animation: surface-up linear both; animation-timeline: --cta; animation-range: entry 0% cover 70%; }
    }
  }
}
