/* ==========================================================================
   Digital Rouge X — NFC card stylesheet
   Shared by every card under /tap/<slug>. One card = one HTML file whose only
   unique part is the CARD object. Change the look here, every card follows.

   Palette: black ground, rouge accents, warm-neutral type. The rouge is kept
   off small text on purpose — see the contrast note on .btn-solid.
   ========================================================================== */

:root{
  --ground:#0B0B0C;
  --card:#131315;
  --raise:#1A1A1D;
  --line:rgba(255,255,255,.085);
  --line-2:rgba(255,255,255,.15);
  --text:#F2F1EF;
  --dim:#8B8B90;
  --faint:#5A5A60;
  --pane:#0E0E10;

  /* Digital Rouge X rouge — the default accent. A card may override --accent
     and --accent-ink in its CARD object to carry the client's own brand colour;
     --accent-fill is what sits behind text and must be measured. */
  --rouge:#DB4216;
  --rouge-fill:#C93D14;
  --rouge-hi:#B8380F;
  --rouge-deep:#8E2A0E;
  --rouge-soft:rgba(219,66,22,.14);

  --accent:#DB4216;
  --accent-fill:#C93D14;
  --accent-ink:#FFFFFF;      /* text ON the accent fill */
  --accent-soft:rgba(219,66,22,.14);

  --radius:22px;
}

*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  background:var(--pane);
  color:var(--text);
  font-family:'Archivo',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  font-size:16px;line-height:1.55;
  -webkit-font-smoothing:antialiased;
  min-height:100vh;
  /* The tail was 44px of nothing under the QR caption, which on a phone reads
     as the card having run out rather than ended. The card is the whole page,
     so the bottom only needs enough room to clear the home indicator. */
  padding-block:26px 24px;
  padding-inline:16px;
  display:flex;flex-direction:column;align-items:center;
}
.sheet{width:100%;max-width:432px;display:flex;flex-direction:column;gap:14px}

/* ---------- identity ---------- */
.id{
  /* the card's accent bleeds faintly into the ground — enough to read as the
     client's colour, not so much that it fights the text. --accent-soft is a
     low-alpha tint, so this stays subtle whatever colour the card carries. */
  background:
    radial-gradient(120% 62% at 50% 0%, var(--accent-soft), transparent 64%),
    var(--card);
  border:1px solid var(--line);
  border-radius:var(--radius);
  text-align:center;
  position:relative;
  overflow:hidden;
  /* no padding: the portrait runs full-bleed to the card's edge */
}

/* The portrait is a large square block, not an avatar. Full-bleed across the
   top so the face is the first thing seen, with the card's own radius clipping
   the top corners. */
.photo{
  position:relative;
  aspect-ratio:1 / 1;
  background:var(--pane);
  overflow:hidden;
}
.photo img{
  width:100%;height:100%;object-fit:cover;display:block;
}
/* rouge seam under the portrait — the one brand note on an otherwise black card */
.photo::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:linear-gradient(90deg,transparent,var(--accent) 22%,var(--accent) 50%,var(--accent) 78%,transparent);
}
/* Some cards have no photo yet. Same square block, initials at display size —
   never a generated face. See README. */
.photo.is-mono{
  display:flex;align-items:center;justify-content:center;
  background:
    radial-gradient(circle at 50% 36%,rgba(219,66,22,.20),transparent 60%),
    var(--pane);
}
.photo.is-mono span{
  font-family:'Fraunces',Georgia,serif;
  font-size:clamp(72px,22vw,104px);font-weight:600;letter-spacing:.01em;
  color:var(--text);
  text-shadow:0 0 44px var(--accent-soft);
}

/* A logo rather than a portrait. Wide wordmarks lose their edges under `cover`,
   so this fit shows the mark whole on a tinted ground. Set photoFit:"contain"
   and a logo on the CARD object.
   The block is shorter than 1:1 on purpose — a landscape wordmark inside a
   square box leaves most of the box empty and the logo reads small. */
.photo.is-logo{
  aspect-ratio:5 / 4;
  display:flex;align-items:center;justify-content:center;
  padding:6%;
  background:
    radial-gradient(circle at 50% 44%, var(--accent-soft), transparent 70%),
    var(--pane);
}
.photo.is-logo img{object-fit:contain}

.id-body{padding:26px 26px 28px;position:relative}
h1{
  font-family:'Fraunces',Georgia,serif;
  font-size:35px;font-weight:600;letter-spacing:-.017em;line-height:1.08;
}
.role{font-size:14px;color:var(--dim);margin-top:8px}
.org{font-size:15px;font-weight:600;margin-top:3px;letter-spacing:.03em}
.blurb{
  font-size:14.5px;color:var(--dim);margin:16px auto 0;
  max-width:31ch;line-height:1.6;
}
.powered{
  display:inline-flex;align-items:center;gap:7px;
  font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--faint);margin-top:20px;
}
.powered i{width:5px;height:5px;border-radius:50%;background:var(--accent);display:block}

/* ---------- controls ---------- */
.btn,.link{
  display:flex;align-items:center;gap:12px;
  background:var(--card);border:1px solid var(--line);color:var(--text);
  text-decoration:none;border-radius:15px;padding:16px 18px;
  font-size:15px;font-weight:500;font-family:inherit;text-align:left;
  cursor:pointer;min-height:56px;
  transition:background .18s ease,border-color .18s ease,transform .12s ease;
  -webkit-tap-highlight-color:transparent;
}
.btn:hover,.link:hover{background:var(--raise);border-color:var(--line-2)}
.btn:active,.link:active{transform:scale(.985)}
.btn svg,.link svg{flex:none;width:19px;height:19px}
.btn .sub,.link .sub{display:block;font-size:12.5px;color:var(--faint);
  margin-top:1px;font-weight:400;letter-spacing:0}

/* One type size and one footprint across every action button. Weight and fill
   carry the hierarchy; size does not, because mixed sizes are what made the
   stack look assembled rather than designed.
   min-height is set here rather than inherited: <button> and <a> resolve a
   couple of pixels apart, which is visible in a stack of five. */
.btn{font-size:15.5px;padding:16px 18px;min-height:58px;border-radius:15px;text-align:center}

/* 14px, matching .sheet's own gap. At 10px the first two buttons sat closer
   together than the review and save buttons below them — those are children of
   .sheet, not of .primary, so they were spaced by the other rule and the stack
   ran 10,10,14,14. One rhythm now. The Call button's number stays at 8px: it
   belongs to the button above it, so it should sit closer than a sibling does. */
.primary{display:flex;flex-direction:column;gap:14px}

/* Every action button is the same width, height, radius and type size, with its
   label centred. Only the *fill* varies — that is hierarchy, not inconsistency.
   Widths used to differ per button, which read as unfinished. */
.pcenter{display:flex;flex-direction:column;gap:8px}
.btn-center{width:100%;justify-content:center}
/* the detail line sits centred under its button, matching the label above it */
.pcenter-sub{
  display:block;text-align:center;
  font-size:14.5px;color:var(--dim);text-decoration:none;
  letter-spacing:.01em;padding:3px 0;
}
.pcenter-sub:hover{color:var(--text)}

.btn-solid,.btn-quiet,.btn-review,.btn-save{width:100%;justify-content:center}

/* Review button: five filled stars then the label. Same footprint as the rest;
   only the outline and the smaller type mark it as the quieter ask. */
.btn-review{
  gap:11px;
  font-size:15.5px;font-weight:600;
  border-color:var(--line-2);
}
.btn-review .stars{width:74px;height:14px;color:var(--accent);flex:none}
.btn-review:hover{border-color:var(--accent)}

/* --accent-fill, not --accent. The accent behind text must be measured: brand
   rouge with white text is 4.37:1, under AA, and a client's palette may be
   lighter still. card.js picks --accent-ink (black or white) so the fill passes
   whichever colour the client brings. Re-measure before changing either. */
.btn-solid{
  background:var(--accent-fill);border-color:var(--accent-fill);color:var(--accent-ink);
  font-weight:700;
}
.btn-solid:hover{filter:brightness(.92)}
.btn-solid .sub{color:var(--accent-ink);opacity:.85}
.btn-solid svg{stroke:var(--accent-ink)}
.btn-quiet{justify-content:center}

.btn-save{justify-content:center;font-weight:600;border-color:var(--line-2)}
.btn-save.did{background:var(--accent-soft);border-color:var(--accent)}

/* Centred to sit over the centred rows it labels. Left-aligned, it read as a
   leftover from the old list layout the links no longer use. */
.group-label{
  font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--faint);font-weight:600;padding:8px 4px 2px;text-align:center;
}
.links{display:flex;flex-direction:column;gap:9px}
/* Links are centred like the action buttons, not left-aligned like a list:
   icon and label share a centred line, the detail sits centred beneath it.
   No chevron — it marked a direction this layout no longer has. */
.link{flex-direction:column;justify-content:center;gap:2px;text-align:center}
.link-line{display:flex;align-items:center;justify-content:center;gap:10px}
.link .ico{display:flex;align-items:center;justify-content:center;
  color:var(--accent);flex:none}

/* ---------- nfc note ---------- */
.nfc{
  margin-top:10px;text-align:center;color:var(--faint);
  border-top:1px solid var(--line);padding-top:26px;
}
.tap-mark{
  width:52px;height:52px;margin:0 auto 14px;border:1px solid var(--accent);
  border-radius:50%;display:flex;align-items:center;justify-content:center;
  color:var(--accent);position:relative;
}
.tap-mark::after{
  content:"";position:absolute;inset:-1px;border-radius:50%;
  border:1px solid var(--accent);opacity:0;
  animation:pulse 3.4s ease-out infinite;
}
@keyframes pulse{0%{transform:scale(1);opacity:.5}70%{transform:scale(1.55);opacity:0}100%{opacity:0}}
.tap-mark svg{width:22px;height:22px}
.nfc p{font-size:12.5px;max-width:30ch;margin:0 auto;line-height:1.6}
.nfc .line{
  font-family:'Fraunces',Georgia,serif;font-size:15px;color:var(--dim);
  margin-top:10px;
}
/* QR fallback for phones that won't tap. On a white tile on purpose: a QR
   needs light/dark contrast to scan, and the card's accent on black would not. */
.qr{margin-top:22px;display:flex;flex-direction:column;align-items:center;gap:9px}
.qr[hidden]{display:none}   /* stays hidden until card.js has drawn the code */
/* 200px, not 132px. Decoded from the render: at 132 the QR only read from a
   pixel-exact capture and failed on any resampling and on a 3x3 blur — which
   is exactly what a phone camera does. At 200 it survives resampling to 140px
   and survives the blur. A logo-centred QR with rounded modules needs the
   headroom; this is the fallback for someone whose tap didn't register. */
.qr img{width:200px;height:200px;display:block;background:#fff;
  padding:10px;border-radius:10px}
.qr span{font-size:11.5px;letter-spacing:.06em;color:var(--faint)}

/* ---------- reveal ---------- */
.rv{opacity:0;transform:translateY(10px);
  animation:rv .5s cubic-bezier(.2,.7,.3,1) forwards}
@keyframes rv{to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .rv{animation:none;opacity:1;transform:none}
  .btn,.link{transition:none}
  .tap-mark::after{animation:none}
}

@media (max-width:360px){
  h1{font-size:30px}
  .btn,.link{padding:15px;font-size:14.5px}
}
@media (min-width:900px){
  body{padding-block:44px 40px}
  .sheet{gap:16px}
  h1{font-size:38px}
}
