/* =========================================================
   Restorative Hope, LLC — Digital Business Card
   Sonia D. Galloway, Ph.D.

   Tokens mirror the main site design system (styles.css) so the
   card reads as the same brand. Mobile-first; desktop is a
   centred column, never a stretched version of the phone layout.
   ========================================================= */

:root {
  /* --- Brand tokens, inherited from the main site --- */
  --ink-950: #12181f;
  --ink-900: #1a222c;
  --ink-700: #333f4d;
  --ink-500: #5d6b7c;
  --ink-300: #bcc5cd;
  --ink-200: #dde2e6;
  --ink-100: #eef1f3;

  --parchment: #faf7f1;
  --parchment-dim: #f2ede3;
  --white: #ffffff;

  --gold-700: #7d5817;
  --gold-600: #b6832b;
  --gold-100: #f8ecd6;

  /* Accent taken from the signature lockup's rule */
  --signature-pink: #fc0157;

  --font-display: "Fraunces", ui-serif, Georgia, "Times New Roman", serif;
  --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Single column width — the card never sprawls on desktop */
  --card-max: 30rem;      /* 480px */
  --gutter: 1.5rem;

  --radius: 10px;
  --shadow-soft: 0 1px 2px rgba(18, 24, 31, 0.04), 0 8px 24px rgba(18, 24, 31, 0.06);
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--parchment);
  color: var(--ink-900);
  font-family: var(--font-sans);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
h1, h2 { font-family: var(--font-display); font-weight: 500; line-height: 1.15; margin: 0; }
p { margin: 0; }

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink-950);
  color: var(--white);
  padding: 0.75rem 1rem;
  border-radius: 0 0 var(--radius) 0;
  font-size: 0.9375rem;
}
.skip-link:focus { left: 0; }

:focus-visible {
  outline: 3px solid var(--gold-600);
  outline-offset: 3px;
  border-radius: 4px;
}

/* =========================================================
   Card shell
   ========================================================= */

.card {
  width: 100%;
  max-width: var(--card-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  /* Respect notches and home indicators on iOS */
  padding-top: max(2.75rem, env(safe-area-inset-top));
  padding-bottom: max(3rem, calc(env(safe-area-inset-bottom) + 2rem));
}

/* =========================================================
   Hero
   ========================================================= */

.hero {
  text-align: center;
  /* The signature stands alone here — the set name/title was removed as a
     duplicate of what the lockup already says. This padding sets the gap
     between the lockup and the rule below it; larger values leave the
     signature looking like it floats. */
  padding-top: 1.5rem;
  /* A control needs more clearance beneath the lockup than a hairline
     rule did, or the button crowds the signature. */
  padding-bottom: 2.5rem;
}

/* The signature lockup is the primary identity. Used exactly as
   supplied — only scaled proportionally, never cropped or recoloured. */
.hero__signature {
  width: 100%;
  max-width: 22.5rem;   /* 360px */
  height: auto;
  margin: 0 auto;
}

/* =========================================================
   Introduction
   ========================================================= */

.intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  text-align: center;
  padding: 2.75rem 0;
  border-top: 1px solid var(--ink-200);
}

.intro__portrait {
  width: 7.5rem;
  height: 7.5rem;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 22%;
  box-shadow: var(--shadow-soft);
}

.intro__lede {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--ink-700);
  max-width: 26rem;
  /* pretty, not balance: balance stops applying past ~6 lines, which is
     where this bio lands on a phone, leaving "reconciliation." stranded
     on its own line. pretty prevents that orphan at any length. */
  text-wrap: pretty;
}

/* =========================================================
   Contact actions
   ========================================================= */

.actions {
  display: grid;
  gap: 0.625rem;
  padding-bottom: 2.25rem;
}

.action {
  display: grid;
  grid-template-columns: 1.5rem 1fr;
  grid-template-rows: auto auto;
  column-gap: 0.875rem;
  row-gap: 0.125rem;
  align-items: center;

  /* Comfortably above the 44px minimum touch target */
  min-height: 4rem;
  padding: 0.9375rem 1.25rem;

  background: var(--white);
  border: 1px solid var(--ink-200);
  border-radius: var(--radius);
  color: var(--ink-900);

  transition: border-color 180ms ease, transform 180ms ease, box-shadow 180ms ease;
}

.action__icon {
  grid-row: 1 / 3;
  width: 1.25rem;
  height: 1.25rem;
  fill: var(--gold-700);
  justify-self: center;
}

.action__label {
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.005em;
}

.action__meta {
  font-size: 0.8125rem;
  color: var(--ink-500);
  /* Long email addresses must not blow out the layout on small phones */
  overflow-wrap: anywhere;
}

.action--save {
  background: var(--ink-950);
  border-color: var(--ink-950);
  color: var(--white);
}
.action--save .action__icon { fill: var(--gold-100); }
.action--save .action__meta { color: rgba(255, 255, 255, 0.72); }

/* Hover is deliberately restrained — a 1px border shift and a
   sub-pixel lift, nothing that reads as a marketing page. */
@media (hover: hover) and (pointer: fine) {
  .action:hover {
    border-color: var(--gold-600);
    transform: translateY(-1px);
    box-shadow: var(--shadow-soft);
  }
  .action--save:hover {
    border-color: var(--gold-600);
    background: var(--ink-900);
  }
}

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

/* Guidance shown only inside in-app browsers, where saving a file is
   impossible. Quiet, not alarming — it is an instruction, not an error. */
.actions__note {
  max-width: 24rem;
  margin: -1rem auto 1.75rem;
  padding: 0.75rem 1rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  text-align: center;
  color: var(--ink-700);
  background: var(--gold-100);
  border-radius: var(--radius);
  text-wrap: pretty;
}

/* =========================================================
   Website call to action
   ========================================================= */

.site-cta {
  padding-bottom: 3rem;
}

/* Shared outline button. The share control uses the same treatment as
   "Visit Restorative Hope" so no new button style is introduced; the one
   filled button on the page stays Save Contact. */
.btn-line {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 3.25rem;
  padding: 0.875rem 1.5rem;

  font-family: var(--font-display);
  font-size: 1.0625rem;
  color: var(--ink-950);

  background: transparent;
  border: 1px solid var(--ink-300);
  border-radius: var(--radius);

  transition: border-color 180ms ease, background-color 180ms ease;
}

.btn-line__icon {
  width: 1.0625rem;
  height: 1.0625rem;
  fill: var(--gold-700);
  flex: none;
}

.btn-site__arrow {
  transition: transform 220ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .btn-line:hover {
    border-color: var(--gold-600);
    background: var(--gold-100);
  }
  .btn-line:hover .btn-site__arrow { transform: translateX(3px); }
}

/* =========================================================
   Share
   ========================================================= */

.share {
  padding-bottom: 2rem;
  text-align: center;
}

/* Copy-fallback confirmation. Height is reserved so the layout does not
   shift when the message appears. */
.share__status {
  min-height: 1.25rem;
  margin-top: 0.625rem;
  font-size: 0.8125rem;
  color: var(--ink-500);
  opacity: 0;
  transition: opacity 200ms ease;
}
.share__status.is-shown { opacity: 1; }

.share__hint {
  max-width: 22rem;
  margin: 0.25rem auto 0;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--ink-500);
  text-wrap: pretty;
}

/* Android install button — quieter than the share control above it */
.share__install {
  min-height: 2.75rem;
  margin-top: 0.5rem;
  padding: 0 0.5rem;
  font-size: 0.8125rem;
  color: var(--ink-500);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--ink-300);
  border-radius: 0;
  transition: color 180ms ease, border-color 180ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .share__install:hover { color: var(--gold-700); border-color: var(--gold-600); }
}

/* =========================================================
   QR
   ========================================================= */

.qr {
  text-align: center;
  padding: 2.75rem 0 3rem;
  border-top: 1px solid var(--ink-200);
}

.qr__heading {
  font-size: 0.75rem;
  font-family: var(--font-sans);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-500);
}

/* White frame guarantees the quiet zone regardless of page background */
.qr__frame {
  width: 11.5rem;
  margin: 1.5rem auto 0;
  padding: 0.875rem;
  background: var(--white);
  border: 1px solid var(--ink-200);
  border-radius: var(--radius);
}

.qr__img {
  width: 100%;
  height: auto;
  /* Keep module edges crisp when the QR is scaled down */
  image-rendering: -webkit-optimize-contrast;
}

.qr__caption {
  margin-top: 1rem;
  font-size: 0.8125rem;
  color: var(--ink-500);
}

/* =========================================================
   Footer
   ========================================================= */

.foot {
  text-align: center;
  padding-top: 2rem;
  border-top: 1px solid var(--ink-200);
}

.foot__org {
  font-family: var(--font-display);
  font-size: 0.9375rem;
  color: var(--ink-700);
}

.foot__link {
  display: inline-flex;
  align-items: center;
  /* 44px minimum tap target, per WCAG 2.5.5 */
  min-height: 2.75rem;
  margin-top: 0.25rem;
  padding-inline: 0.5rem;
  font-size: 0.8125rem;
  color: var(--ink-500);
  border-bottom: 1px solid var(--ink-300);
  transition: color 180ms ease, border-color 180ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .foot__link:hover { color: var(--gold-700); border-color: var(--gold-600); }
}

/* =========================================================
   Entrance animation
   Elements are revealed once, in sequence, by card.js adding
   .is-in. If JS never runs, .reveal stays fully visible.
   ========================================================= */

.js .reveal {
  opacity: 0;
  transform: translateY(10px);
}

.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 620ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 620ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* The signature gets a slightly longer, softer entrance so it
   settles rather than pops. */
.js .reveal--sig { transform: translateY(14px); }
.js .reveal--sig.is-in {
  transition-duration: 900ms;
  transition-delay: 60ms;
}

/* =========================================================
   Tablet / desktop
   The column stays narrow; the extra room becomes whitespace,
   and the two primary actions sit side by side.
   ========================================================= */

@media (min-width: 40em) {
  /* 36rem, not 34rem: at 34rem the bio's text column narrows to 320px,
     which pushes it to nine lines and strands "reconciliation." alone on
     the last one. The extra 2rem widens the column enough to resolve it
     without touching the portrait size or the layout. */
  :root { --card-max: 36rem; --gutter: 2rem; }

  .card { padding-top: 4.5rem; padding-bottom: 4rem; }

  .hero { padding-top: 0.5rem; padding-bottom: 3rem; }
  .hero__signature { max-width: 26rem; }

  .intro {
    flex-direction: row;
    text-align: left;
    align-items: center;
    gap: 1.75rem;
    padding: 3.25rem 0;
  }
  .intro__portrait { width: 8.25rem; height: 8.25rem; flex: none; }
  .intro__lede { font-size: 1.0625rem; }

  /* Deliberately kept single-column. A two-up grid forces the email
     address to break mid-word and leaves LinkedIn orphaned in the
     left column; full-width rows stay legible and evenly weighted. */
  .actions { gap: 0.75rem; }
  .action { min-height: 4.25rem; padding-inline: 1.5rem; }
}

@media (min-width: 64em) {
  .card { padding-top: 5.5rem; }
  .hero__signature { max-width: 28rem; }
}

/* =========================================================
   Reduced motion — honour the OS preference completely
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .reveal.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* =========================================================
   Print — a clean sheet, no interactive chrome
   ========================================================= */

@media print {
  body { background: #fff; }
  .skip-link, .actions, .site-cta { display: none; }
  .card { max-width: none; }
}
