/* ==========================================================================
   base.css — shared reset, design tokens, landing layout, modal, HUD
   Used by every page. Prototype-specific rules live in their own file.
   ========================================================================== */

/* ---- tokens ------------------------------------------------------------- */
:root {
  --bg: #f4f4f2;
  --bg-elevated: #ffffff;
  --fg: #1a1a1a;
  --fg-muted: #5c5c5c;
  --border: #d9d9d4;
  --accent: #2f6df6;
  --accent-contrast: #ffffff;
  --shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
  --radius: 12px;
  --maxw: 60rem;
  /* the about icon's visible edge sits inside its 0.3rem button padding, so it
     lands 1.3rem from the top and 1.45rem from the right; the zoom controls
     and the modal reuse that inset so every edge gap matches */
  --hud-icon-inset-y: 1.3rem;
  --hud-icon-inset-x: 1.45rem;
  --font: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #121316;
    --bg-elevated: #1c1e22;
    --fg: #f0f0f0;
    --fg-muted: #a2a2a2;
    --border: #33363c;
    --accent: #6ea0ff;
    --accent-contrast: #0b1020;
    --shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
  }
}

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

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

/* everything is sized in rem, so this scales the whole site down on
   phones: 87.5% of the browser's default (16px -> 14px) */
@media (max-width: 640px) {
  html {
    font-size: 87.5%;
  }
}

body {
  margin: 0;
  font-family: var(--font);
  color: var(--fg);
  background: var(--bg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: var(--accent);
}

/* ---- landing page --------------------------------------------------------- */
.page {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(1.5rem, 5vw, 4rem) 1.25rem;
}

.page__title {
  font-size: clamp(1.75rem, 5vw, 2.75rem);
  line-height: 1.15;
  margin: 0 0 0.5rem;
}

.page__intro {
  color: var(--fg-muted);
  max-width: 40rem;
  margin: 0 0 2.5rem;
}

.card-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
}

.card {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 1.25rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.card:hover,
.card:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

.card__eyebrow {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-muted);
}

.card__name {
  font-size: 1.2rem;
  font-weight: 650;
}

.card__desc {
  color: var(--fg-muted);
  font-size: 0.95rem;
}

.card--soon {
  opacity: 0.55;
  pointer-events: none;
}

/* ---- standalone QR content page (Prototype 3) --------------------------- */
.page__back {
  display: inline-flex;
  text-decoration: none;
  margin-bottom: 1.5rem;
}

/* ---- buttons ----------------------------------------------------------- */
.btn {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--fg);
  font: inherit;
  font-size: 0.9rem;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  cursor: pointer;
  line-height: 1;
}

.btn:hover,
.btn:focus-visible {
  border-color: var(--accent);
}

.btn--icon {
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 1.25rem;
}

/* ---- modal (native <dialog>) ---------------------------------------------- */
dialog.modal {
  border: none;
  padding: 0;
  border-radius: var(--radius);
  background: var(--bg-elevated);
  color: var(--fg);
  box-shadow: var(--shadow);
  /* full viewport height, inset by the same gap as the HUD icons */
  margin: var(--hud-icon-inset-y) auto;
  width: 100%;
  max-width: min(32rem, calc(100vw - 2 * var(--hud-icon-inset-x)));
  height: calc(100vh - 2 * var(--hud-icon-inset-y));
  height: calc(100dvh - 2 * var(--hud-icon-inset-y));
  max-height: none;
  overflow: hidden; /* .modal__inner scrolls so the close button stays put */
  --modal-pad: 1.5rem; /* .modal__inner's padding */
  --modal-close: 0.875rem; /* the close button's × */
  /* between the header and the stage, the stage and the rule, and the
     rule and the title */
  --modal-gap: 1.5rem;
  --modal-text-gap: 0.5rem; /* a heading (title or part) to its paragraph */
}

/* the QOLORFUL modal's slider greys the whole site:
   assets/js/obelisk/greyscale.js sets --greyscale (0..1) on <html>, with
   .is-greyscale while it's above 0 (any filter, even grayscale(0),
   changes how fixed children are placed). The dialogs are in the top
   layer, outside <html>'s painting, so they take the filter themselves. */
html.is-greyscale :is(.stage, .hud, dialog.modal) {
  filter: grayscale(var(--greyscale));
}

dialog.modal::backdrop {
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px);
}

/* opening slides the modal up from below the screen and fades its
   backdrop in; closing runs it back down. Closed, the modal waits just
   past the bottom edge; @starting-style starts an opening from there, and
   transitioning display and overlay keeps a closing modal on screen, in
   the top layer, until it's gone. Browsers without these skip the
   animation. Opening eases out, closing eases in. */
dialog.modal,
dialog.modal::backdrop {
  transition-duration: 0.28s;
  transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}

dialog.modal {
  transform: translateY(calc(100% + var(--hud-icon-inset-y)));
  transition-property: transform, display, overlay;
  transition-behavior: allow-discrete;
}

dialog.modal::backdrop {
  opacity: 0;
  transition-property: opacity, display, overlay;
  transition-behavior: allow-discrete;
}

dialog.modal[open] {
  transform: none;
}

dialog.modal[open]::backdrop {
  opacity: 1;
}

dialog.modal[open],
dialog.modal[open]::backdrop {
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}

@starting-style {
  dialog.modal[open] {
    transform: translateY(calc(100% + var(--hud-icon-inset-y)));
  }

  dialog.modal[open]::backdrop {
    opacity: 0;
  }
}

.modal__inner {
  height: 100%;
  overflow-y: auto;
  padding: var(--modal-pad);
}

.modal__close {
  position: absolute;
  /* same inset as .modal__inner's padding */
  top: var(--modal-pad);
  right: var(--modal-pad);
  padding: 0;
  border: none;
  background: transparent;
  color: var(--fg-muted);
  line-height: 0;
  cursor: pointer;
  /* showModal() focuses this button on open; no ring around the × */
  outline: none;
}

/* round caps reach exactly to the viewBox edge, so the × fills the button
   and its corners sit on the 1.5rem inset */
.modal__close svg {
  display: block;
  width: var(--modal-close);
  height: var(--modal-close);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.modal__close:hover,
.modal__close:focus-visible {
  color: var(--fg);
}

/* the content fills .modal__inner's content box, so its children can
   size as a share of it (longer copy still scrolls in .modal__inner) */
.modal__inner > div {
  height: 100%;
}

/* a fixed top and a scrolling text section: .modal__layout fills
   .modal__inner, and only .modal__text scrolls, when its copy overflows */
.modal__layout {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* the top 40% of .modal__inner's content box: the header, then the
   interaction area filling the rest; the rule sits right below it */
.modal__top {
  flex: none;
  display: flex;
  flex-direction: column;
  height: 40%;
}

/* the eyebrow and the close button as one row: the row is the ×'s
   height, at the same top inset, and the eyebrow is centred in it, so
   both share a centre line (the button itself stays in the page's HTML,
   positioned over the row's right end) */
.modal__header {
  flex: none;
  display: flex;
  align-items: center;
  min-height: var(--modal-close);
  padding-right: calc(var(--modal-close) + var(--modal-gap));
}

/* a line exactly the x's height, so one line of eyebrow fills the row and
   a longer one wraps onto more rows below it */
.modal__header .modal__eyebrow {
  margin: 0;
  line-height: var(--modal-close);
}

.modal__stage {
  flex: 1;
  min-height: 0;
  position: relative;
}

/* the stage's canvas: the stage less --modal-gap above and below, sized
   by the stage alone (absolutely placed, so the canvas's own pixel size
   never feeds back into the layout). Each modal draws its own. */
.modal__canvas {
  position: absolute;
  top: var(--modal-gap);
  left: 0;
  display: block;
  width: 100%;
  height: calc(100% - 2 * var(--modal-gap));
  touch-action: manipulation;
}

.modal__part {
  margin: 1.5rem 0 var(--modal-text-gap);
  font-size: 1rem;
  color: var(--fg);
}

.modal__rule {
  flex: none;
  margin: 0 0 var(--modal-gap);
  border: none;
  border-top: 1px solid var(--border);
}

.modal__text {
  position: relative; /* offsetParent for scrolling to a part */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* the scrollbar sits in .modal__inner's right padding, so the copy
     keeps its width whether or not it scrolls */
  margin-right: -1rem;
  padding-right: 1rem;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

/* dark theme: all the copy pure white, muted text included (the close
   button sits outside .modal__layout, so it keeps its own colours) */
@media (prefers-color-scheme: dark) {
  .modal__layout {
    --fg: #fff;
    --fg-muted: #fff;
  }
}

/* text right below the header (no interactive top): --modal-gap apart */
.modal__header + .modal__text {
  margin-top: var(--modal-gap);
}

/* Safari: no scrollbar-width / scrollbar-color */
.modal__text::-webkit-scrollbar {
  width: 6px;
}

.modal__text::-webkit-scrollbar-thumb {
  border-radius: 3px;
  background: var(--border);
}

.modal__eyebrow {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-muted);
  margin: 0 0 0.35rem;
}

.modal__title {
  margin: 0 0 var(--modal-text-gap);
  font-size: 1.35rem;
}

.modal__body {
  margin: 0;
  color: var(--fg-muted);
}

/* a heading sits --modal-text-gap above its first paragraph: the
   paragraph's own top margin would otherwise widen the gap */
.modal__title + .modal__body > :first-child,
.modal__part + p {
  margin-top: 0;
}

.modal__body img {
  margin-top: 1rem;
  border-radius: 8px;
}

/* a picture in the copy with its caption, both centred */
.modal__figure {
  margin: 1.25rem 0;
  text-align: center;
}

.modal__figure img {
  display: block;
  width: min(60%, 16rem);
  height: auto;
  margin: 0 auto;
  background: #fff;
}

.modal__figure figcaption {
  margin-top: 0.5rem;
  font-size: 0.85rem;
}

/* full-width sheet on small screens, still inset like the HUD icons */
@media (max-width: 640px) {
  dialog.modal {
    margin: var(--hud-icon-inset-y) var(--hud-icon-inset-x);
    width: calc(100vw - 2 * var(--hud-icon-inset-x));
    max-width: none;
    border-radius: 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
