/* ==========================================================================
   Altoria Labs, altoria.dev
   Concept: "altitude". The mark is a peak; the page is a climb. Topographic
   contour lines carry that motif from the hero to the summit (coming soon).

   No external requests anywhere in this file. No @import, no CDN, no
   third-party host. The only url() reference points at our own /fonts.

   Theming: every themed value is a light-dark() pair resolved against
   color-scheme, so the OS preference and the manual toggle share ONE set of
   token definitions. Switching themes only flips color-scheme on :root:
   there is no duplicated dark block to drift out of sync.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Nunito, self-hosted, SIL Open Font License 1.1. See fonts/OFL.txt.
   Variable weight axis 200–1000 in a single 34 KB file.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Nunito";
  src: url("../fonts/nunito-latin-var.woff2") format("woff2-variations"),
       url("../fonts/nunito-latin-var.woff2") format("woff2");
  font-weight: 200 1000;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   Brand constants, verbatim from corporate_identity/altoria-brand.md.
   These never change between themes; they are the identity.
   -------------------------------------------------------------------------- */
:root {
  --altoria-teal: #14B8A6;
  --altoria-coral: #FF7059;
  --altoria-lagoon: #134E4A;
  --altoria-sunbeam: #FFC24B;
  --altoria-mist: #D7EEE9;
  --altoria-cloud: #F7FAF8;
  --altoria-teal-soft: #7CDCCE;

  --radius: 14px;
  --radius-lg: 22px;
  --radius-xl: 32px;

  --font-ui: "Nunito", ui-rounded, "SF Pro Rounded", "Segoe UI", system-ui,
             -apple-system, sans-serif;

  /* Fluid type scale */
  --step--1: clamp(0.83rem, 0.80rem + 0.14vw, 0.92rem);
  --step-0:  clamp(1.00rem, 0.95rem + 0.24vw, 1.15rem);
  --step-1:  clamp(1.20rem, 1.10rem + 0.45vw, 1.45rem);
  --step-2:  clamp(1.50rem, 1.30rem + 0.90vw, 2.05rem);
  --step-3:  clamp(1.95rem, 1.55rem + 1.80vw, 3.00rem);
  --step-4:  clamp(2.45rem, 1.70rem + 3.40vw, 4.60rem);

  --measure: 60ch;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --shell: 1180px;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/* --------------------------------------------------------------------------
   Theme switching.
   color-scheme is the ONLY thing that changes. light-dark() below resolves
   against it, so both the OS preference and the toggle drive one token set.
   -------------------------------------------------------------------------- */
:root                    { color-scheme: light dark; }  /* follow the OS */
:root[data-theme="light"]{ color-scheme: light; }       /* user forced light */
:root[data-theme="dark"] { color-scheme: dark; }        /* user forced dark  */

/* --------------------------------------------------------------------------
   Semantic tokens. Every pair is light-dark(<light value>, <dark value>).
   Everything below this line paints with these, never with the raw brand
   constants above.

   The dark side is built from Deep lagoon (the brand doc's designated dark
   surface colour) stepped down for the page ground. Teal soft carries links
   and secondary text there, exactly as it carries the word "Labs" in the dark
   lockup.
   -------------------------------------------------------------------------- */
:root {
  --bg:           light-dark(#F7FAF8, #072220);
  --bg-alt:       light-dark(#EEF7F5, #0B2C29);
  --surface:      light-dark(#FFFFFF, #0F3733);
  --surface-2:    light-dark(#D7EEE9, #16443F);
  --border:       light-dark(#D7EEE9, #1C504A);
  --border-strong:light-dark(#C2E5DE, #266B63);

  --text:         light-dark(#134E4A, #E9F6F3);
  --text-muted:   light-dark(#3F6F6B, #B6D8D2);
  /* Light value is #4A6F6A, not something softer: this is used at --step--1
     (~14px) for nav, footer and back links, and anything lighter drops under
     WCAG AA. #5C8681 measured 3.86:1 on Cloud and 4.05:1 on white, both short
     of the 4.5:1 small-text floor. #4A6F6A is 5.30:1 / 5.57:1. */
  --text-soft:    light-dark(#4A6F6A, #8FBDB6);

  /* The brand's contrast rule inverts by theme: bright teal is too light for
     small text on Cloud, and too dark for small text on the lagoon ground.
     So links step darker in light mode and lighter in dark mode. */
  --accent-ink:       light-dark(#0F766E, #7CDCCE);
  --accent-on-surface:light-dark(#14B8A6, #7CDCCE);

  /* Display-size type and large graphics: the sizes where full teal is
     allowed to carry, per the brand doc. */
  --display-accent: light-dark(#14B8A6, #7CDCCE);

  /* Contour lines. Alpha is baked in rather than set via opacity, because
     light-dark() resolves colours only, and thin light-on-dark lines must sit
     stronger than dark-on-light ones to read at the same weight. */
  --topo-line:    light-dark(rgba(194, 229, 222, 0.55), rgba(35, 87, 79, 0.80));
  --peak-contour: light-dark(#C2E5DE, #23574F);

  --peak-glow-1: light-dark(rgba(255, 255, 255, 0.95), rgba(20, 184, 166, 0.18));
  --peak-glow-2: light-dark(rgba(215, 238, 233, 0.75), rgba(20, 184, 166, 0.07));
  --peak-glow-3: light-dark(rgba(215, 238, 233, 0.00), rgba(20, 184, 166, 0.00));

  /* The summit panel is dark in BOTH themes. In dark mode it lifts above the
     page ground instead of sinking into it, and gains a border so it still
     reads as an elevated panel rather than a hole. */
  --summit-c1:          light-dark(#134E4A, #12433E);
  --summit-c2:          light-dark(#0C3B38, #082926);
  --summit-bg:          linear-gradient(160deg, var(--summit-c1), var(--summit-c2));
  --summit-border:      light-dark(transparent, #1C504A);
  --summit-contour:     light-dark(rgba(124, 220, 206, 0.16), rgba(124, 220, 206, 0.13));
  --summit-chip-bg:     light-dark(rgba(124, 220, 206, 0.12), rgba(124, 220, 206, 0.10));
  --summit-chip-border: light-dark(rgba(124, 220, 206, 0.28), rgba(124, 220, 206, 0.24));

  /* Lagoon-tinted shadows in light mode; near-black in dark, where a tinted
     shadow would be invisible. */
  --shadow-1: light-dark(rgba(19, 78, 74, 0.05), rgba(0, 0, 0, 0.30));
  --shadow-2: light-dark(rgba(19, 78, 74, 0.04), rgba(0, 0, 0, 0.24));
  --shadow-3: light-dark(rgba(19, 78, 74, 0.07), rgba(0, 0, 0, 0.34));
  --shadow-4: light-dark(rgba(19, 78, 74, 0.10), rgba(0, 0, 0, 0.45));

  --shadow-sm: 0 1px 2px var(--shadow-1), 0 2px 6px var(--shadow-2);
  --shadow-md: 0 2px 4px var(--shadow-2), 0 8px 24px var(--shadow-3);
  --shadow-lg: 0 4px 8px var(--shadow-1), 0 18px 50px var(--shadow-4);
}

/* --------------------------------------------------------------------------
   Fallback for browsers without light-dark() (Safari < 17.5, Chrome < 123,
   Firefox < 120).

   Without this, every light-dark() token is invalid at computed-value time, so
   each var() falls back to `unset`. That is not a graceful degradation: on the
   summit panel the gradient dies while its hard-coded `color: #FFFFFF` lives,
   and the word "Apps" turns white-on-white. .btn--ghost loses its background
   AND its border at the same time.

   So: redefine every token with its light value and serve those browsers the
   light theme, complete and readable. The duplication is deliberate and is the
   one place tokens are repeated. IF YOU CHANGE A LIGHT VALUE ABOVE, CHANGE IT
   HERE TOO. Supporting browsers skip this block entirely.
   -------------------------------------------------------------------------- */
@supports not (color: light-dark(#000, #fff)) {
  :root {
    --bg: #F7FAF8;
    --bg-alt: #EEF7F5;
    --surface: #FFFFFF;
    --surface-2: #D7EEE9;
    --border: #D7EEE9;
    --border-strong: #C2E5DE;

    --text: #134E4A;
    --text-muted: #3F6F6B;
    --text-soft: #4A6F6A;

    --accent-ink: #0F766E;
    --accent-on-surface: #14B8A6;
    --display-accent: #14B8A6;

    --topo-line: rgba(194, 229, 222, 0.55);
    --peak-contour: #C2E5DE;

    --peak-glow-1: rgba(255, 255, 255, 0.95);
    --peak-glow-2: rgba(215, 238, 233, 0.75);
    --peak-glow-3: rgba(215, 238, 233, 0.00);

    --summit-c1: #134E4A;
    --summit-c2: #0C3B38;
    --summit-border: transparent;
    --summit-contour: rgba(124, 220, 206, 0.16);
    --summit-chip-bg: rgba(124, 220, 206, 0.12);
    --summit-chip-border: rgba(124, 220, 206, 0.28);

    --shadow-1: rgba(19, 78, 74, 0.05);
    --shadow-2: rgba(19, 78, 74, 0.04);
    --shadow-3: rgba(19, 78, 74, 0.07);
    --shadow-4: rgba(19, 78, 74, 0.10);
  }

  /* The toggle only flips color-scheme, which does nothing here. Hide the
     control rather than leave a button that visibly does nothing.

     Scoped to :root deliberately. This block sits above the .theme-toggle
     rules, so a bare `.theme-toggle` selector would tie on specificity and
     lose to the later `display: inline-grid`. :root makes it (0,2,0) and
     removes the dependence on source order. */
  :root .theme-toggle { display: none; }
}

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font-ui);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.65;
  color: var(--text);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }

h1, h2, h3 {
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-weight: 800;
  text-wrap: balance;
}

p { text-wrap: pretty; }

a { color: inherit; }

:focus-visible {
  outline: 3px solid var(--altoria-coral);
  outline-offset: 3px;
  border-radius: 6px;
}

::selection {
  background: var(--altoria-teal-soft);
  color: var(--altoria-lagoon);
}

/* --------------------------------------------------------------------------
   Theme-aware logo swap.
   The brand ships two lockups (the dark one sets "Altoria" in white and "Labs"
   in Teal soft, per the brand doc) and the mark must never be recoloured with
   a filter. So we ship both files and show one.

   This is the one place that cannot use light-dark(): that function resolves
   colours, not `display`. <picture> can't do it either: its media queries see
   the OS preference but are blind to the manual toggle. Hence explicit
   selectors for the three states: OS-driven, forced light, forced dark.
   -------------------------------------------------------------------------- */
.logo__dark { display: none; }
.logo__light { display: block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo__light { display: none; }
  :root:not([data-theme="light"]) .logo__dark  { display: block; }
}

:root[data-theme="dark"] .logo__light { display: none; }
:root[data-theme="dark"] .logo__dark  { display: block; }
:root[data-theme="light"] .logo__light { display: block; }
:root[data-theme="light"] .logo__dark  { display: none; }

/* --------------------------------------------------------------------------
   Theme toggle
   -------------------------------------------------------------------------- */
.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--accent-ink);
  cursor: pointer;
  transition: border-color 0.2s var(--ease-out),
              color 0.2s var(--ease-out),
              transform 0.35s var(--ease-out);
}

.theme-toggle:hover {
  border-color: var(--altoria-teal);
  transform: rotate(-18deg);
}

.theme-toggle svg { width: 19px; height: 19px; }

/* Show the icon for the theme you'd switch TO, not the one you're in. */
.theme-toggle__sun { display: none; }
.theme-toggle__moon { display: block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle__moon { display: none; }
  :root:not([data-theme="light"]) .theme-toggle__sun  { display: block; }
}

:root[data-theme="dark"] .theme-toggle__moon { display: none; }
:root[data-theme="dark"] .theme-toggle__sun  { display: block; }
:root[data-theme="light"] .theme-toggle__moon { display: block; }
:root[data-theme="light"] .theme-toggle__sun  { display: none; }

/* No JS, no working toggle, so don't show a dead control. */
.no-js .theme-toggle { display: none; }

/* Same reasoning for the mail links: js/site.js is what turns href="#" into a
   real mailto:, so without JS the link is dead. Hide it and let the adjacent
   <noscript> show the address in readable form instead. */
.no-js .js-mail { display: none; }

/* --------------------------------------------------------------------------
   Layout primitives
   -------------------------------------------------------------------------- */
.shell {
  width: min(100% - (var(--gutter) * 2), var(--shell));
  margin-inline: auto;
}

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--gutter);
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--altoria-teal);
  color: #06302C;
  border-radius: 0 0 var(--radius) var(--radius);
  font-weight: 800;
  text-decoration: none;
}

.skip-link:focus { top: 0; }

/* --------------------------------------------------------------------------
   Topographic motif: the page's signature.
   Concentric contour rings evoke a peak seen from above. Pure CSS gradients,
   so there is no image request and it scales to any viewport.
   -------------------------------------------------------------------------- */
.topo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    repeating-radial-gradient(
      circle at 50% 100%,
      transparent 0 46px,
      var(--topo-line) 46px 47.5px,
      transparent 47.5px 94px
    );
  -webkit-mask-image: radial-gradient(circle at 50% 100%, #000 0%, transparent 72%);
          mask-image: radial-gradient(circle at 50% 100%, #000 0%, transparent 72%);
}

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */
.site-header {
  position: relative;
  z-index: 2;
  padding-block: clamp(1.25rem, 3vw, 2rem);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.logo {
  display: inline-flex;
  border-radius: var(--radius);
  transition: transform 0.35s var(--ease-out);
}

.logo img { height: clamp(34px, 5vw, 42px); width: auto; }

.logo:hover { transform: translateY(-2px); }

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2rem);
  font-size: var(--step--1);
  font-weight: 700;
}

.site-nav a {
  color: var(--text-soft);
  text-decoration: none;
  transition: color 0.2s var(--ease-out);
}

.site-nav a:hover { color: var(--text); }

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.5rem, 9vw, 7.5rem) clamp(4rem, 10vw, 8rem);
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}

@media (max-width: 900px) {
  .hero__inner { grid-template-columns: 1fr; }
}

.hero h1 {
  font-size: var(--step-4);
  font-weight: 900;
  letter-spacing: -0.035em;
  margin-bottom: 1.5rem;
}

/* Display size, so full teal is allowed here: it is a large element, not
   small text. In dark mode it steps up to teal soft for the same reason. */
.hero h1 em {
  font-style: normal;
  position: relative;
  color: var(--display-accent);
  white-space: nowrap;
}

/* Underline with the brand's round line caps. */
.hero h1 em::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.08em;
  height: 0.09em;
  border-radius: 999px;
  background: var(--altoria-coral);
  transform-origin: left center;
}

@media (prefers-reduced-motion: no-preference) {
  .hero h1 em::after {
    animation: draw 0.9s 0.5s var(--ease-out) both;
  }
  @keyframes draw {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }
}

.hero__lede {
  font-size: var(--step-1);
  color: var(--text-muted);
  max-width: 46ch;
  margin-bottom: 2rem;
}

.hero__actions {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.6rem;
  border-radius: var(--radius);
  font: inherit;
  font-weight: 800;
  text-decoration: none;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.25s var(--ease-out),
              box-shadow 0.25s var(--ease-out),
              background-color 0.2s var(--ease-out);
}

/* Teal fill with white text passes AA at this weight/size. Kept identical in
   both themes: the primary button is a brand moment, not a surface. */
.btn--primary {
  background: var(--altoria-teal);
  color: #06302C;
  box-shadow: var(--shadow-md);
}

.btn--primary:hover {
  background: #2ACBB9;
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.btn--ghost {
  color: var(--text);
  border-color: var(--border-strong);
  background: var(--surface);
}

.btn--ghost:hover {
  border-color: var(--altoria-teal);
  transform: translateY(-2px);
}

.btn:active { transform: translateY(0); }

/* --------------------------------------------------------------------------
   Hero peak: the mark rebuilt at scale as a real graphic element.
   -------------------------------------------------------------------------- */
.peak {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}

/* The glow is absolutely positioned and the mark is not, so without explicit
   z-indexes the glow would paint ON TOP of the mark (positioned elements beat
   non-positioned siblings) and wash it out. */
.peak__ring {
  position: absolute;
  inset: 8%;
  z-index: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 62%,
      var(--peak-glow-1) 0%,
      var(--peak-glow-2) 45%,
      var(--peak-glow-3) 70%);
}

.peak svg {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  overflow: visible;
}

.peak__stroke {
  fill: none;
  stroke: var(--display-accent);
  stroke-width: 9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (prefers-reduced-motion: no-preference) {
  .peak__stroke {
    stroke-dasharray: 220;
    stroke-dashoffset: 220;
    animation: trace 1.6s 0.3s var(--ease-out) forwards;
  }
  @keyframes trace { to { stroke-dashoffset: 0; } }
}

.peak__dot {
  fill: var(--altoria-sunbeam);
  transform-origin: 60px 69px;
}

@media (prefers-reduced-motion: no-preference) {
  .peak__dot { animation: pop 0.5s 1.5s var(--ease-out) both; }
  @keyframes pop {
    from { transform: scale(0); }
    60%  { transform: scale(1.25); }
    to   { transform: scale(1); }
  }
}

.peak__contour {
  fill: none;
  stroke: var(--peak-contour);
  stroke-width: 1.5;
  stroke-linecap: round;
}

/* --------------------------------------------------------------------------
   Section furniture
   -------------------------------------------------------------------------- */
.section { padding-block: clamp(3.5rem, 8vw, 6.5rem); }

.section--mist {
  position: relative;
  background: linear-gradient(180deg, var(--bg), var(--bg-alt) 40%, var(--bg));
}

.section__head { max-width: var(--measure); margin-bottom: clamp(2rem, 4vw, 3rem); }

.section__kicker {
  display: block;
  font-size: var(--step--1);
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 0.75rem;
}

.section__head h2 { font-size: var(--step-3); margin-bottom: 1rem; }

.section__head p { font-size: var(--step-1); color: var(--text-muted); }

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1rem, 2.5vw, 1.5rem);
}

.card {
  position: relative;
  padding: clamp(1.5rem, 3vw, 2rem);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: transform 0.35s var(--ease-out),
              box-shadow 0.35s var(--ease-out),
              border-color 0.35s var(--ease-out);
}

.card:hover {
  transform: translateY(-4px);
  border-color: var(--altoria-teal-soft);
  box-shadow: var(--shadow-md);
}

.card__icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 1.25rem;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--accent-on-surface);
}

.card__icon svg { width: 26px; height: 26px; }

.card h3 { font-size: var(--step-1); margin-bottom: 0.6rem; }

.card p { color: var(--text-muted); font-size: var(--step-0); }

/* --------------------------------------------------------------------------
   Summit: the "coming soon" moment. The one screen where sunbeam leads.
   Already dark in light mode; in dark mode it lifts slightly above the page
   ground so it still reads as an elevated panel rather than a hole.
   -------------------------------------------------------------------------- */
.summit {
  position: relative;
  overflow: hidden;
  padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.5rem, 5vw, 4rem);
  border-radius: var(--radius-xl);
  background: var(--summit-bg);
  color: #FFFFFF;
  text-align: center;
  border: 1.5px solid var(--summit-border);
  box-shadow: var(--shadow-lg);
}

/* Contour rings again, inverted, converging on the summit. */
.summit::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    repeating-radial-gradient(
      circle at 50% 118%,
      transparent 0 38px,
      var(--summit-contour) 38px 39.5px,
      transparent 39.5px 78px
    );
  -webkit-mask-image: radial-gradient(circle at 50% 118%, #000 10%, transparent 70%);
          mask-image: radial-gradient(circle at 50% 118%, #000 10%, transparent 70%);
  pointer-events: none;
}

.summit > * { position: relative; z-index: 1; }

.summit__spark {
  width: 72px;
  height: 72px;
  margin: 0 auto 1.5rem;
}

@media (prefers-reduced-motion: no-preference) {
  .summit__spark { animation: twinkle 5s ease-in-out infinite; }
  @keyframes twinkle {
    0%, 100% { transform: rotate(0deg) scale(1); }
    50%      { transform: rotate(8deg) scale(1.07); }
  }
}

.summit h2 {
  font-size: var(--step-3);
  margin-bottom: 1rem;
}

.summit h2 span { color: var(--altoria-sunbeam); }

.summit p {
  max-width: 52ch;
  margin: 0 auto 2rem;
  color: var(--altoria-teal-soft);
  font-size: var(--step-1);
}

.summit__note {
  margin-top: 1.5rem;
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--altoria-teal-soft);
}

/* JS-off fallback: the only place the address is ever rendered. */
.summit__fallback {
  display: inline-block;
  margin-top: 1.5rem;
  padding: 0.65rem 1.35rem;
  border-radius: 999px;
  background: var(--summit-chip-bg);
  border: 1.5px solid var(--summit-chip-border);
  font-size: var(--step--1);
  font-weight: 700;
  color: #FFFFFF;
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.site-footer {
  padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
  border-top: 1.5px solid var(--border);
  background: var(--surface);
}

.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 5vw, 3rem);
  margin-bottom: 3rem;
}

@media (max-width: 760px) {
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}

.footer__brand img { height: 38px; width: auto; margin-bottom: 1.25rem; }

.footer__brand p {
  color: var(--text-soft);
  font-size: var(--step--1);
  max-width: 34ch;
}

.footer__col h3 {
  font-size: var(--step--1);
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 1rem;
}

.footer__col ul { list-style: none; padding: 0; }

.footer__col li + li { margin-top: 0.6rem; }

.footer__col a,
.footer__col address {
  font-style: normal;
  font-size: var(--step--1);
  color: var(--text-muted);
  text-decoration: none;
  line-height: 1.7;
}

.footer__col a {
  border-bottom: 1.5px solid transparent;
  transition: color 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}

.footer__col a:hover {
  color: var(--accent-ink);
  border-bottom-color: var(--altoria-teal);
}

.footer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding-top: 2rem;
  border-top: 1.5px solid var(--border);
  font-size: var(--step--1);
  color: var(--text-soft);
}

/* Prose pages have no footer columns above the bar, so it needs no divider. */
.footer__bar--bare { border-top: 0; padding-top: 0; }

/* "Made with <3 in Oxford and Bremen".
   The heart is inline SVG, not a character: Nunito ships no U+2665 glyph, so
   text would silently fall back to a system emoji font and render
   inconsistently across platforms. */
.made-with {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700;
  color: var(--text-muted);
}

.made-with__heart {
  width: 15px;
  height: 15px;
  fill: var(--altoria-coral);
  flex-shrink: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .made-with__heart { animation: beat 2.4s ease-in-out infinite; }
  @keyframes beat {
    0%, 100%   { transform: scale(1); }
    12%, 30%   { transform: scale(1.22); }
    20%        { transform: scale(1.05); }
  }
}

/* --------------------------------------------------------------------------
   404
   -------------------------------------------------------------------------- */
.error-page {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  min-height: 62vh;
  padding-block: clamp(3rem, 8vw, 6rem);
  text-align: center;
}

.error-page__inner { position: relative; z-index: 1; }

.error-page__mark {
  width: clamp(90px, 14vw, 130px);
  margin: 0 auto 1.5rem;
  overflow: visible;
}

.error-page__code {
  font-size: var(--step-1);
  font-weight: 900;
  letter-spacing: 0.14em;
  color: var(--accent-ink);
  margin-bottom: 0.5rem;
}

.error-page h1 { font-size: var(--step-3); margin-bottom: 1rem; }

.error-page__lede {
  max-width: 42ch;
  margin: 0 auto 2rem;
  color: var(--text-muted);
  font-size: var(--step-1);
}

/* --------------------------------------------------------------------------
   Legal / prose pages
   -------------------------------------------------------------------------- */
.prose-page { padding-block: clamp(2.5rem, 6vw, 4.5rem); }

.prose { max-width: 68ch; }

.prose h1 { font-size: var(--step-3); margin-bottom: 0.75rem; }

.prose > p.prose__intro {
  font-size: var(--step-1);
  color: var(--text-muted);
  margin-bottom: 2.5rem;
}

.prose h2 {
  font-size: var(--step-2);
  margin-top: 2.75rem;
  margin-bottom: 0.85rem;
}

.prose p, .prose li { color: var(--text-muted); }

.prose p + p { margin-top: 1rem; }

.prose ul { margin-top: 0.75rem; padding-left: 1.25rem; }

.prose li + li { margin-top: 0.4rem; }

.prose a { color: var(--accent-ink); font-weight: 700; }

.prose strong { color: var(--text); }

/* Divider between the two language versions on bilingual pages
   (checkcode-privacy.html). */
.prose hr {
  border: 0;
  border-top: 1.5px solid var(--border);
  margin-block: 3rem;
}

.prose code {
  padding: 0.1em 0.4em;
  border-radius: 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 0.88em;
}

.prose__facts { margin-top: 1.5rem; }

.prose address {
  font-style: normal;
  padding: 1.25rem 1.5rem;
  margin-top: 1rem;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  line-height: 1.8;
  color: var(--text);
}

/* Scoped to .prose to beat `.prose a` (0,1,1) on specificity. Unscoped, these
   two rules lose to it: the link would silently render accent-ink instead of
   muted, and :hover would resolve to the colour it already had, i.e. no hover
   feedback at all. */
.prose .prose__back {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 2rem;
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--text-soft);
  text-decoration: none;
}

.prose .prose__back:hover { color: var(--accent-ink); }

.prose__back svg { width: 16px; height: 16px; }

/* --------------------------------------------------------------------------
   Entrance choreography: one orchestrated page load, staggered.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(18px);
    animation: reveal 0.75s var(--ease-out) forwards;
  }
  .reveal:nth-child(1) { animation-delay: 0.05s; }
  .reveal:nth-child(2) { animation-delay: 0.14s; }
  .reveal:nth-child(3) { animation-delay: 0.23s; }
  .reveal:nth-child(4) { animation-delay: 0.32s; }

  @keyframes reveal {
    to { opacity: 1; transform: translateY(0); }
  }
}
