:root {
  --grid-gap: clamp(18px, 5vw, 34px);
  --icon-size: clamp(58px, 16vw, 76px);
  --icon-radius: 22%;
  --label: rgba(255, 255, 255, 0.95);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html {
  height: 100%;
  /* The wallpaper's edges are pure black, so a near-black fill blends seamlessly.
     This sits on the root canvas — the surface iOS Safari paints in the rubber-band
     overscroll area — so scrolling past the content never flashes white. */
  background-color: #000;
  overscroll-behavior: none;
}

body { height: 100%; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: #fff;
  min-height: 100vh;
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
  display: flex;
  justify-content: center;
  /* Transparent so the fixed wallpaper layer (body::before, z-index:-1) shows
     through. A solid color here would paint over it and hide the wallpaper. */
  background: transparent;
}

/* Wallpaper as a fixed full-screen layer.
   Using a fixed pseudo-element instead of `background-attachment: fixed`,
   which is unreliable on mobile (iOS Safari) and leaves the page uncovered. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-color: #000; /* dark fallback while the image loads */
  background-image: url("../eclipse.jpg");
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

.phone {
  width: 100%;
  max-width: 480px;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* ---------- Site header ---------- */
.site-header {
  text-align: center;
  padding: clamp(28px, 8vw, 52px) 24px clamp(8px, 3vw, 16px);
}
.site-name {
  font-size: clamp(30px, 8.5vw, 44px);
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.08;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.3);
}
.site-title {
  margin-top: 6px;
  font-size: clamp(15px, 4vw, 18px);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: rgba(255, 255, 255, 0.7);
}

/* ---------- App grid ---------- */
#home {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding: clamp(20px, 6vw, 40px) clamp(16px, 5vw, 30px);
}

.app-grid {
  /* larger icons on the home page only (dock keeps the root size) */
  --icon-size: clamp(60px, 18vw, 88px);
  display: grid;
  /* Size columns to the icons (not 1fr) and center the block. The icon and gap
     values are tuned so 4 columns + 3 gaps total 84vw — narrower than the ~90vw
     content area at every width, so the grid actually centers (matching the
     header and dock) instead of overflowing edge-to-edge on phones. 84vw also
     equals the dock's width, so the grid lines up with it. */
  grid-template-columns: repeat(4, var(--icon-size));
  gap: clamp(14px, 4vw, 20px);
  align-content: start;
  justify-content: center;
}

/* ---------- App icon ---------- */
.app {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: var(--label);
  -webkit-tap-highlight-color: transparent;
}

.app-tile {
  width: var(--icon-size);
  height: var(--icon-size);
  border-radius: var(--icon-radius);
  display: grid;
  place-items: center;
  font-size: calc(var(--icon-size) * 0.46);
  line-height: 1;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.35);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  position: relative;
  overflow: hidden;
}
.app-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* emoji glyph tiles: enlarge so the glyph fills the tile like image icons */
.app-tile.is-glyph { font-size: calc(var(--icon-size) * 0.68); }
.app-tile::after {
  /* subtle gloss */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), transparent 55%);
}

.app-label {
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 500;
  text-align: center;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  max-width: calc(var(--icon-size) + 22px);
  line-height: 1.2;
  white-space: normal;
  overflow-wrap: break-word;
}

.app:active .app-tile,
.app:focus-visible .app-tile {
  transform: scale(0.9);
}
@media (hover: hover) {
  .app:hover .app-tile {
    transform: translateY(-3px) scale(1.04);
    box-shadow: 0 14px 26px rgba(0, 0, 0, 0.38), inset 0 1px 1px rgba(255, 255, 255, 0.35);
  }
}
.app:focus-visible { outline: none; }
.app:focus-visible .app-tile {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85), 0 8px 18px rgba(0, 0, 0, 0.3);
}

/* ---------- Dock ---------- */
.dock {
  margin: auto auto clamp(16px, 5vw, 26px);
  padding: 14px clamp(16px, 4vw, 22px);
  display: flex;
  justify-content: center;
  gap: clamp(16px, 4vw, 26px);
  border-radius: 30px;
  background: rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.dock .app-label { display: none; }

/* ---------- Modal (in-page popup) ---------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(12px, 4vw, 32px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease;
}
.modal.is-open { opacity: 1; pointer-events: auto; }
body.modal-open { overflow: hidden; }

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(8px) saturate(120%);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
}

.modal-card {
  position: relative;
  width: min(820px, 100%);
  height: min(90vh, 1100px);
  height: min(90dvh, 1100px);
  display: flex;
  flex-direction: column;
  background: #1c1c1e;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
  transform: scale(0.96);
  transition: transform 0.22s ease;
}
.modal.is-open .modal-card { transform: scale(1); }

.modal-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px 10px 18px;
  background: rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.modal-title { font-weight: 600; font-size: 16px; }
.modal-actions { display: flex; align-items: center; gap: 8px; }
.modal-btn {
  appearance: none;
  border: 0;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font: inherit;
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 10px;
  cursor: pointer;
}
.modal-btn:hover { background: rgba(255, 255, 255, 0.2); }

.modal-frame {
  flex: 1;
  width: 100%;
  background: #fff;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
}
/* iOS Safari ignores the #view=FitH hint and renders PDFs at 1pt = 1px, so a
   612pt-wide page overflows a phone-width iframe and you have to pan to read it.
   Give the iframe the page's exact point size so the whole page fits its own
   viewport, then scale it down to the modal with a transform (the scale factor
   is set in js/apps.js — no PDF library needed). */
.modal-frame iframe.pdf-fit {
  width: 612px;
  height: 792px;
  flex: none;
  transform-origin: center center;
}

/* On phones, let the modal fill the screen so the PDF has maximum room. */
@media (max-width: 600px) {
  .modal { padding: 0; }
  .modal-card {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
  }
}

/* ---------- Utility ---------- */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

