/* ============================================================================
   Place ID Finder — paper, ink and gold.
   The palette is earned rather than picked: warm paper because the output of
   this tool ends up printed on a counter, gold because that is the colour of
   the stars we are asking people for.
   ========================================================================== */

/* ─────────────────────────── tokens ─────────────────────────── */
:root {
  /* surfaces */
  --paper:      #eef1f9;
  --paper-2:    #fcfdfe;
  --paper-3:    #e1e7f3;
  --ink:        #10141b;
  --ink-2:      #363d4e;
  --ink-3:      #6a758d;
  --rule:       #ced5e8;
  --rule-soft:  #dbe2f0;

  /* signal */
  --gold:       #2f4ef0;
  --gold-deep:  #1c37c4;
  --gold-wash:  #e4e9ff;

  /* states */
  --bad:        #a32f22;
  --bad-wash:   #f9e9e5;
  --good:       #2f6b43;

  /* button ink (flips in dark) */
  --btn-bg:     #10141b;
  --btn-fg:     #f7f8fc;

  --shadow-1:  0 1px 2px rgba(14,22,48,.05), 0 2px 8px -2px rgba(14,22,48,.06);
  --shadow-2:  0 2px 6px rgba(14,22,48,.06), 0 18px 44px -18px rgba(14,22,48,.22);
  --shadow-3:  0 30px 70px -30px rgba(14,22,48,.4), 0 6px 18px -8px rgba(14,22,48,.18);

  --r-sm: 8px;
  --r:    12px;
  --r-lg: 18px;

  --shell: 1180px;
  --gut: 28px;

  --f-display: "Instrument Serif", "Iowan Old Style", Georgia, serif;
  --f-ui: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --f-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --ease: cubic-bezier(.22, 1, .36, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);

  --grain-opacity: .5;
  --specimen-shadow: rgba(14, 22, 48, .26);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:     #0c0d10;
    --paper-2:   #13151c;
    --paper-3:   #191d28;
    --ink:       #eceff8;
    --ink-2:     #acb5ca;
    --ink-3:     #7a8297;
    --rule:      #242a37;
    --rule-soft: #1d212d;
    --gold:      #7d97ff;
    --gold-deep: #a8bcff;
    --gold-wash: #16204a;
    --bad:       #f0917f;
    --bad-wash:  #2c1713;
    --good:      #7dc194;
    --btn-bg:    #eceff8;
    --btn-fg:    #0e1118;
    --shadow-1:  0 1px 2px rgba(0,0,0,.5);
    --shadow-2:  0 2px 8px rgba(0,0,0,.4), 0 20px 48px -20px rgba(0,0,0,.8);
    --shadow-3:  0 30px 80px -30px rgba(0,0,0,.9), 0 8px 20px -8px rgba(0,0,0,.6);
    --grain-opacity: .22;
    --specimen-shadow: rgba(0, 0, 0, .75);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --paper:     #0c0d10;
  --paper-2:   #13151c;
  --paper-3:   #191d28;
  --ink:       #eceff8;
  --ink-2:     #acb5ca;
  --ink-3:     #7a8297;
  --rule:      #242a37;
  --rule-soft: #1d212d;
  --gold:      #7d97ff;
  --gold-deep: #a8bcff;
  --gold-wash: #16204a;
  --bad:       #f0917f;
  --bad-wash:  #2c1713;
  --good:      #7dc194;
  --btn-bg:    #eceff8;
  --btn-fg:    #0e1118;
  --shadow-1:  0 1px 2px rgba(0,0,0,.5);
  --shadow-2:  0 2px 8px rgba(0,0,0,.4), 0 20px 48px -20px rgba(0,0,0,.8);
  --shadow-3:  0 30px 80px -30px rgba(0,0,0,.9), 0 8px 20px -8px rgba(0,0,0,.6);
  --grain-opacity: .22;
  --specimen-shadow: rgba(0, 0, 0, .75);
  color-scheme: dark;
}

/* ─────────────────────────── base ─────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-ui);
  font-size: 16px;
  line-height: 1.62;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;
}

/* Paper tooth. Cheap, fixed, and the thing that stops this reading as a template. */
.grain {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: var(--grain-opacity);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='.38'/%3E%3C/svg%3E");
  mix-blend-mode: multiply;
}
:root[data-theme="dark"] .grain { mix-blend-mode: screen; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .grain { mix-blend-mode: screen; } }

main, .masthead, .colophon { position: relative; z-index: 1; }

h1, h2, h3, h4 { margin: 0 0 .45em; line-height: 1.1; font-weight: 600; }
p { margin: 0 0 1.05em; }
a { color: inherit; }
/* Place IDs are long and unbreakable; let them wrap rather than widen a column. */
.mono { font-family: var(--f-mono); font-size: .92em; letter-spacing: -.01em; overflow-wrap: anywhere; }
.display { font-family: var(--f-display); font-weight: 400; letter-spacing: -.012em; line-height: 1.04; }
.display em { font-style: italic; color: var(--gold-deep); }
code { font-family: var(--f-mono); font-size: .9em; }

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gut); }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: var(--paper-2); padding: 12px 18px;
}
.skip-link:focus { left: 0; }

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

::selection { background: var(--gold-wash); color: var(--ink); }

/* ─────────────────────────── masthead ─────────────────────────── */
.masthead {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--paper) 86%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid var(--rule-soft);
}
.scroll-line {
  position: absolute; left: 0; top: 0; height: 2px; width: 100%;
  background: var(--gold); transform: scaleX(0); transform-origin: 0 50%;
}
.masthead__inner { display: flex; align-items: center; gap: 20px; height: 66px; }

.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; margin-right: auto; }
.brand__mark { width: 22px; color: var(--gold); display: block; }
.brand__mark svg { display: block; width: 100%; height: auto; }
/* Thin dark outline on the pin. Width is in the 32-unit viewBox, so at the 22px
   render it lands under a pixel — enough to define the silhouette against pale
   paper without reading as a drawn border. */
.brand__mark svg path:first-child { stroke: #0c0d10; stroke-width: 1.3; stroke-linejoin: round; }
.brand__star { fill: #fbbf24; transition: fill .4s var(--ease); }
.brand:hover .brand__star { fill: #ffd76a; }
.brand__word { font-size: 17px; font-weight: 600; letter-spacing: -.015em; }
.brand__word-b { color: var(--gold); font-weight: 600; }

.masthead__nav { display: flex; gap: 2px; }
.masthead__nav a {
  position: relative; text-decoration: none; color: var(--ink-2);
  font-size: 14px; font-weight: 500; padding: 6px 12px; border-radius: 99px;
  transition: color .2s;
}
.masthead__nav a::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 2px; height: 1.5px;
  background: var(--gold); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .32s var(--ease);
}
.masthead__nav a:hover { color: var(--ink); }
.masthead__nav a:hover::after { transform: scaleX(1); }

.masthead__tools { display: flex; gap: 4px; }
.icon-btn {
  width: 36px; height: 36px; display: grid; place-items: center;
  border: 1px solid transparent; border-radius: 10px; background: transparent;
  color: var(--ink-2); cursor: pointer; transition: background .2s, color .2s, border-color .2s;
}
.icon-btn:hover { background: var(--paper-3); color: var(--ink); border-color: var(--rule-soft); }
.icon-btn svg { width: 18px; height: 18px; }
.ico { display: none; }
:root[data-theme="system"] .ico--auto,
:root[data-theme="light"]  .ico--sun,
:root[data-theme="dark"]   .ico--moon { display: block; }

@media (max-width: 900px) { .masthead__nav { display: none; } }

/* ─────────────────────────── hero ─────────────────────────── */
.hero { padding: clamp(48px, 8vw, 96px) 0 clamp(28px, 4vw, 44px); }
.hero__grid {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(32px, 6vw, 72px); align-items: center;
}
.hero__copy { max-width: 34ch; }
.hero h1 { font-size: clamp(2.7rem, 7.2vw, 4.6rem); margin-bottom: .3em; }

.tag {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 22px;
}
.tag__dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold) 70%, transparent);
  animation: pulse 2.8s var(--ease-soft) infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold) 65%, transparent); }
  70%  { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.lede { font-size: clamp(1.02rem, 1.6vw, 1.14rem); color: var(--ink-2); max-width: 46ch; }

.hero__points { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 11px; }
.hero__points li {
  display: flex; gap: 12px; align-items: baseline;
  font-size: 14.5px; color: var(--ink-2); line-height: 1.45;
}
.rule-dot {
  flex: none; width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold); transform: translateY(-2px);
}

/* the tilted specimen deck */
.hero__specimen { display: grid; place-items: center; perspective: 1400px; }
.specimen { position: relative; width: min(300px, 100%); }

/* Four cards fanned. The fan transform sits on the slot and the animation on
   the card inside it, so the two never fight over `transform` — the usual way
   a hover transition and a keyframe loop end up cancelling each other out.
   Slot 1 stays in flow and sets the height; the rest are laid over it. */
.specimen__deck { position: relative; z-index: 2; animation: float 9s ease-in-out infinite; }
.specimen__slot {
  position: absolute; inset: 0;
  transition: transform .75s var(--ease);
}
/* Offsets do two jobs. Vertically, each card behind the front one has to clear
   it far enough to show its own top band — the accent rule and the star row;
   fanning sideways alone exposed nothing but blank paper margin, which showed
   none of the colour the deck exists to demonstrate. Horizontally, the fan is
   held to about 40px either side of the 300px card, inside the 447px the hero
   grid allows, so nothing clips and no page-wide horizontal scroll appears. */
.specimen__slot--1 { position: relative; z-index: 4; transform: rotate(-2.4deg) rotateY(7deg) rotateX(3deg); }
.specimen__slot--2 { z-index: 3; transform: translate(12%, -9%)   rotate(6deg) scale(.975); }
.specimen__slot--3 { z-index: 2; transform: translate(-12%, -17%) rotate(-10deg) scale(.95); }
.specimen__slot--4 { z-index: 1; transform: translate(2%, -25%)   rotate(12deg) scale(.925); }

/* Hovering opens the fan, so all four colours are legible at once. */
.hero__specimen:hover .specimen__slot--1 { transform: rotate(-1deg) scale(1.01); }
.hero__specimen:hover .specimen__slot--2 { transform: translate(20%, -5%)  rotate(11deg) scale(.975); }
.hero__specimen:hover .specimen__slot--3 { transform: translate(-20%, -9%) rotate(-16deg) scale(.95); }
.hero__specimen:hover .specimen__slot--4 { transform: translate(5%, -16%)  rotate(18deg) scale(.925); }

.specimen__card {
  background: var(--paper-2); border: 1px solid var(--rule);
  /* The accent rule carries the card's colour on the one strip that stays
     visible when it is buried in the fan. */
  border-top: 3px solid var(--accent, var(--gold));
  border-radius: 4px; padding: 27px 26px 26px; text-align: center;
  box-shadow: var(--shadow-3);
  opacity: 0;
  /* Two animations, two properties: cardIn fades, cardLift moves. Overlapping
     them on `transform` would mean the later one silently wins. */
  animation: cardIn .8s var(--ease) forwards,
             cardLift 12s var(--ease) infinite;
  animation-delay: calc(var(--i) * .13s), calc(var(--i) * -3s);
}
@keyframes cardIn { to { opacity: 1; } }

/* Each card lifts in turn — 12s cycle, four cards, so one every three seconds. */
@keyframes cardLift {
  0%, 16%, 100% { transform: translateY(0) scale(1); }
  8%            { transform: translateY(-11px) scale(1.018); }
}
@keyframes float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -9px; }
}
.specimen__shadow {
  position: absolute; inset: auto 12% -26px 12%; height: 40px; z-index: 1;
  /* Tied to a token: a hardcoded near-black cast shadow disappears entirely on
     the dark theme's near-black ground. */
  background: radial-gradient(ellipse at center, var(--specimen-shadow), transparent 70%);
  filter: blur(10px);
}
.specimen__stars { display: flex; justify-content: center; gap: 3px; margin-bottom: 14px; }
/* --accent is set per card in app.js; the gold is the fallback for the first. */
.specimen__stars svg { width: 15px; height: 15px; fill: var(--accent, var(--gold)); }
.specimen__stars svg:nth-child(n) { animation: starIn .5s var(--ease) backwards; }
.specimen__stars svg:nth-child(1) { animation-delay: .25s; }
.specimen__stars svg:nth-child(2) { animation-delay: .33s; }
.specimen__stars svg:nth-child(3) { animation-delay: .41s; }
.specimen__stars svg:nth-child(4) { animation-delay: .49s; }
.specimen__stars svg:nth-child(5) { animation-delay: .57s; }
@keyframes starIn { from { opacity: 0; transform: scale(.3) rotate(-40deg); } }
.specimen__lead { font-family: var(--f-display); font-size: 1.42rem; margin: 0 0 16px; }
/* Rounded and clipped so the tinted background behind the code reads as a
   deliberate panel rather than a square of off-white that missed the corner. */
.specimen__qr {
  width: 150px; margin: 0 auto 14px; aspect-ratio: 1;
  border-radius: 6px; overflow: hidden;
}
.specimen__qr svg { display: block; width: 100%; height: 100%; }
.specimen__foot {
  margin: 0; font-size: 10.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}
/* The card says "scan to leave a Google review" because that is what a real
   printed one says. The code above it is decorative, so say so plainly rather
   than let a reader think the site is broken when nothing happens. Sits below
   the shadow, outside the tilted card, so it never reads as part of the art. */
.specimen__note {
  position: absolute; left: 0; right: 0; top: calc(100% + 26px);
  margin: 0; text-align: center;
  font-size: 11px; line-height: 1.45; color: var(--ink-3); opacity: .75;
}

@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; }
  .hero__copy { max-width: none; }
  .hero__specimen { display: none; }
}

/* ─────────────────────────── panels & finder ─────────────────────────── */
.finder-band { padding-bottom: clamp(36px, 6vw, 64px); }

.panel {
  background: var(--paper-2); border: 1px solid var(--rule);
  border-radius: var(--r-lg); padding: clamp(18px, 3vw, 26px);
  box-shadow: var(--shadow-2);
}
.panel__title {
  font-size: 1.02rem; font-weight: 600; display: flex; align-items: baseline; gap: 12px;
  margin-bottom: 16px;
}
.num {
  font-family: var(--f-mono); font-size: .76em; color: var(--gold-deep);
  letter-spacing: .06em;
}

/* tabs with a sliding indicator */
.tabs {
  position: relative; display: flex; gap: 2px; padding: 4px;
  background: var(--paper-3); border-radius: 12px; margin-bottom: 20px;
}
.tabs__slider {
  position: absolute; top: 4px; bottom: 4px; left: 0; width: 0;
  background: var(--paper-2); border-radius: 9px; box-shadow: var(--shadow-1);
  transition: transform .42s var(--ease), width .42s var(--ease);
  will-change: transform, width;
}
.tab {
  position: relative; z-index: 1; flex: 1; min-height: 38px; cursor: pointer;
  border: 0; background: transparent; font: inherit; font-size: 14px; font-weight: 500;
  color: var(--ink-3); border-radius: 9px; padding: 8px 12px;
  transition: color .25s;
}
.tab.is-active { color: var(--ink); font-weight: 600; }
.tab:hover { color: var(--ink); }

.tabpanel { animation: panelIn .4s var(--ease); }
@keyframes panelIn { from { opacity: 0; transform: translateY(6px); } }

.label {
  display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 9px;
}

.input-row { display: flex; gap: 10px; }
.input-shell { position: relative; flex: 1; min-width: 0; }
.input-shell__ico {
  position: absolute; left: 15px; top: 50%; translate: 0 -50%;
  width: 18px; height: 18px; color: var(--ink-3); pointer-events: none;
  transition: color .25s;
}
.input-shell:focus-within .input-shell__ico { color: var(--gold-deep); }
.input-shell input, .text-input {
  width: 100%; font: inherit; font-size: 16px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--r); padding: 14px 46px 14px 44px; min-height: 54px;
  transition: border-color .22s, box-shadow .22s, background .22s;
}
.text-input { padding: 12px 14px; min-height: 46px; font-size: 15px; }
/* `.input-shell input` (0,1,1) outranks `.text-input` (0,1,0), so the sizing the
   class promises has to be restated here or the dialog's key field renders at
   the full 54px/16px search-input size. */
.input-shell--plain input { padding: 12px 14px; min-height: 46px; font-size: 15px; }
.input-shell input::placeholder, .text-input::placeholder { color: var(--ink-3); opacity: .75; }
.input-shell input:focus, .text-input:focus {
  outline: none; border-color: var(--gold);
  box-shadow: 0 0 0 4px var(--gold-wash); background: var(--paper-2);
}
.input-shell input::-webkit-search-cancel-button { display: none; }
input[type="search"] { appearance: none; }

.input-shell__kbd {
  position: absolute; right: 14px; top: 50%; translate: 0 -50%;
  font-family: var(--f-mono); font-size: 11px; color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 5px; padding: 1px 7px;
  background: var(--paper-2); pointer-events: none; transition: opacity .2s;
}
.input-shell:focus-within .input-shell__kbd { opacity: 0; }
@media (hover: none) { .input-shell__kbd { display: none; } }

.input-shell__clear {
  position: absolute; right: 10px; top: 50%; translate: 0 -50%;
  width: 28px; height: 28px; display: grid; place-items: center;
  border: 0; background: transparent; color: var(--ink-3); cursor: pointer;
  border-radius: 50%; transition: background .2s, color .2s;
}
.input-shell__clear:hover { background: var(--paper-3); color: var(--ink); }
.input-shell__clear svg { width: 15px; height: 15px; }

.help { font-size: 13.5px; color: var(--ink-3); margin: 10px 0 0; }
.help code { background: var(--paper-3); padding: 1px 5px; border-radius: 4px; }

.seeds { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-top: 16px; }
.seeds__label {
  font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); margin-right: 3px;
}
.seed {
  font: inherit; font-size: 13px; cursor: pointer; color: var(--ink-2);
  background: transparent; border: 1px solid var(--rule); border-radius: 99px;
  padding: 5px 13px; transition: border-color .2s, color .2s, background .2s, transform .2s var(--ease);
}
.seed:hover { border-color: var(--gold); color: var(--ink); background: var(--gold-wash); transform: translateY(-1px); }

/* ─────────────────────────── buttons ─────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font: inherit; font-size: 14.5px; font-weight: 600; cursor: pointer; text-decoration: none;
  padding: 12px 20px; min-height: 48px; border-radius: var(--r);
  border: 1px solid transparent; white-space: nowrap;
  transition: background .22s, color .22s, border-color .22s, transform .2s var(--ease), box-shadow .22s;
}
.btn svg { width: 17px; height: 17px; flex: none; }
.btn:active { transform: translateY(1px); }
.btn--lg { min-height: 54px; padding: 14px 26px; font-size: 15px; }

.btn--ink { background: var(--btn-bg); color: var(--btn-fg); box-shadow: var(--shadow-1); }
.btn--ink:hover { background: color-mix(in srgb, var(--btn-bg) 86%, var(--gold)); }

.btn--gold { background: var(--gold); color: var(--btn-fg); box-shadow: 0 2px 14px -4px color-mix(in srgb, var(--gold) 75%, transparent); }
.btn--gold:hover { background: color-mix(in srgb, var(--gold) 88%, #fff); box-shadow: 0 6px 22px -6px color-mix(in srgb, var(--gold) 80%, transparent); }

.btn--line { background: var(--paper-2); color: var(--ink); border-color: var(--rule); }
.btn--line:hover { border-color: var(--ink-3); background: var(--paper); }

.btn--quiet { background: transparent; color: var(--ink-3); }
.btn--quiet:hover { color: var(--ink); background: var(--paper-3); }

.btn[disabled], .btn[aria-busy="true"] { opacity: .55; pointer-events: none; }

/* NFC write is armed and waiting for a tag — the button stays clickable so the
   same press cancels it, hence no [disabled] here. */
.btn.is-armed {
  border-color: var(--gold); background: var(--gold-wash); color: var(--gold-deep);
  animation: armed 1.4s ease-in-out infinite;
}
@keyframes armed { 50% { background: color-mix(in srgb, var(--gold) 30%, var(--gold-wash)); } }

.btn__spin {
  display: inline-block; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 28%, transparent);
  border-top-color: currentColor; animation: spin .7s linear infinite;
}
@keyframes spin { to { rotate: 360deg; } }

.mini {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
  color: var(--ink-2); background: var(--paper-2);
  border: 1px solid var(--rule); border-radius: 8px; padding: 5px 10px; min-height: 32px;
  transition: border-color .2s, color .2s, background .2s;
}
.mini:hover { border-color: var(--ink-3); color: var(--ink); }

/* copy button: the tick draws itself */
.copy__ico { position: relative; width: 16px; height: 16px; flex: none; display: block; }
.copy__ico svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.copy__k { stroke-dasharray: 26; stroke-dashoffset: 26; opacity: 0; color: var(--good); }
.copy.is-done .copy__c { opacity: 0; scale: .6; }
.copy__c { transition: opacity .2s, scale .2s; }
.copy.is-done .copy__k { opacity: 1; animation: draw .4s var(--ease) forwards; }
.copy.is-done { color: var(--good); border-color: color-mix(in srgb, var(--good) 45%, transparent); }
@keyframes draw { to { stroke-dashoffset: 0; } }

@media (max-width: 620px) {
  .input-row { flex-direction: column; }
  .input-row .btn { width: 100%; }
}

/* ─────────────────────────── suggestions ─────────────────────────── */
.suggest {
  position: absolute; z-index: 40; top: calc(100% + 8px); left: 0; right: 0;
  margin: 0; padding: 6px; list-style: none; max-height: 330px; overflow-y: auto;
  background: var(--paper-2); border: 1px solid var(--rule);
  border-radius: var(--r); box-shadow: var(--shadow-2);
  animation: panelIn .22s var(--ease);
}
.suggest li {
  display: flex; gap: 12px; align-items: flex-start; padding: 10px 12px;
  border-radius: 9px; cursor: pointer; transition: background .15s;
}
.suggest li:hover, .suggest li.is-active { background: var(--gold-wash); }
.suggest__pin { flex: none; color: var(--ink-3); margin-top: 3px; }
.suggest__pin svg { width: 15px; height: 15px; display: block; }
.suggest__main { font-weight: 600; font-size: 14.5px; line-height: 1.35; }
.suggest__sub { font-size: 12.5px; color: var(--ink-3); line-height: 1.35; }

/* ─────────────────────────── notices ─────────────────────────── */
.notice {
  margin-top: 18px; padding: 14px 16px; border-radius: var(--r);
  background: var(--bad-wash); border: 1px solid color-mix(in srgb, var(--bad) 28%, transparent);
  color: var(--bad); font-size: 14.5px; line-height: 1.5;
  animation: panelIn .3s var(--ease);
}
.linkish {
  font: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px;
  background: none; border: 0; padding: 0; color: inherit; cursor: pointer;
}
.notice .linkish { display: inline-block; margin-top: 8px; }
.help .linkish { color: var(--gold-deep); }

/* ─────────────────────────── recent ─────────────────────────── */
.recent {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 16px; padding: 0 6px;
}
.recent__label {
  font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3);
}
.recent__items { display: flex; flex-wrap: wrap; gap: 6px; }
.recent__chip {
  font: inherit; font-size: 13px; cursor: pointer; color: var(--ink-2);
  background: var(--paper-2); border: 1px solid var(--rule); border-radius: 99px;
  padding: 4px 12px; max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: border-color .2s, color .2s;
}
.recent__chip:hover { border-color: var(--gold); color: var(--ink); }
.recent__clear {
  font: inherit; font-size: 12.5px; color: var(--ink-3); background: none; border: 0;
  cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
  /* Was 30x20 — too small to hit reliably with a thumb. The padding grows the
     target without moving the text, since the row is centre-aligned. */
  padding: 7px 8px; margin: -7px -8px;
}

/* ─────────────────────────── matches ─────────────────────────── */
.matches { margin-top: 16px; }
.match-list { list-style: none; margin: 0; padding: 0; }
.match-list li + li { border-top: 1px solid var(--rule-soft); }
.match {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  width: 100%; text-align: left; font: inherit; cursor: pointer;
  background: transparent; border: 0; padding: 14px 12px; border-radius: 10px;
  transition: background .18s, padding-left .25s var(--ease);
}
.match:hover { background: var(--gold-wash); padding-left: 18px; }
.match__name { font-weight: 600; font-size: 15px; }
.match__addr { font-size: 13px; color: var(--ink-3); }
.match__rating { font-size: 13px; color: var(--ink-2); white-space: nowrap; flex: none; font-family: var(--f-mono); }
.match__rating b { color: var(--gold-deep); font-weight: 500; }

/* ─────────────────────────── result ─────────────────────────── */
.result { padding-bottom: clamp(48px, 7vw, 88px); }

.ident {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  padding-bottom: 22px; border-bottom: 1px solid var(--rule);
}
.ident__eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-3); margin: 0 0 8px;
}
.ident__name { font-size: clamp(1.9rem, 4.4vw, 2.9rem); margin: 0 0 6px; }
.ident__addr { color: var(--ink-2); font-size: 15px; margin: 0; }

.stars { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
/* Five stars punched out of a plain bar, so the gold fill can simply slide across. */
.stars__track {
  --star-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24'%3E%3Cg fill='%23000'%3E%3Cpath d='M12 2.6l2.9 5.9 6.5.95-4.7 4.58 1.11 6.47L12 17.44 6.19 20.5 7.3 14.03 2.6 9.45l6.5-.95L12 2.6Z'/%3E%3Cpath transform='translate(24 0)' d='M12 2.6l2.9 5.9 6.5.95-4.7 4.58 1.11 6.47L12 17.44 6.19 20.5 7.3 14.03 2.6 9.45l6.5-.95L12 2.6Z'/%3E%3Cpath transform='translate(48 0)' d='M12 2.6l2.9 5.9 6.5.95-4.7 4.58 1.11 6.47L12 17.44 6.19 20.5 7.3 14.03 2.6 9.45l6.5-.95L12 2.6Z'/%3E%3Cpath transform='translate(72 0)' d='M12 2.6l2.9 5.9 6.5.95-4.7 4.58 1.11 6.47L12 17.44 6.19 20.5 7.3 14.03 2.6 9.45l6.5-.95L12 2.6Z'/%3E%3Cpath transform='translate(96 0)' d='M12 2.6l2.9 5.9 6.5.95-4.7 4.58 1.11 6.47L12 17.44 6.19 20.5 7.3 14.03 2.6 9.45l6.5-.95L12 2.6Z'/%3E%3C/g%3E%3C/svg%3E");
  position: relative; width: 90px; height: 18px; background: var(--rule);
  -webkit-mask: var(--star-mask) no-repeat center / 100% 100%;
  mask: var(--star-mask) no-repeat center / 100% 100%;
}
.stars__fill { height: 100%; width: 0; background: var(--gold); transition: width 1.1s var(--ease) .2s; }
.stars__text { font-family: var(--f-mono); font-size: 13px; color: var(--ink-2); }

/* the link box — the centrepiece */
.linkbox {
  margin-top: 26px; padding: clamp(20px, 3vw, 28px);
  background: var(--paper-2); border: 1px solid var(--rule); border-radius: var(--r-lg);
  box-shadow: var(--shadow-2); position: relative; overflow: hidden;
}
.linkbox::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, var(--gold), color-mix(in srgb, var(--gold) 20%, transparent));
}
.linkbox__top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.linkbox__label {
  font-size: 11.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink);
}
.linkbox__hint { font-size: 12.5px; color: var(--ink-3); font-style: italic; }
.linkbox__url {
  margin: 0 0 18px; font-size: clamp(12.5px, 1.6vw, 15px); line-height: 1.7;
  word-break: break-all; color: var(--ink-2);
}
.linkbox__id { color: var(--ink); font-weight: 500; }
.linkbox__id span {
  display: inline-block; background: var(--gold-wash); border-radius: 2px;
}
.linkbox__id.is-typing span { animation: charIn .34s var(--ease) backwards; }
@keyframes charIn { from { opacity: 0; transform: translateY(-5px); filter: blur(3px); } }
.linkbox__acts { display: flex; flex-wrap: wrap; gap: 10px; }

.idrow {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 20px; padding-top: 18px; border-top: 1px dashed var(--rule);
}
.idrow__label {
  font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
}
.idrow__val { flex: 1; min-width: 200px; font-size: 13.5px; word-break: break-all; color: var(--ink); }

/* ─────────────────────────── bench ─────────────────────────── */
.bench { margin-top: 26px; }
.bench__rail {
  position: relative; display: flex; gap: 4px; padding: 5px;
  background: var(--paper-3); border-radius: 14px; margin-bottom: 18px;
  overflow-x: auto; scrollbar-width: none;
}
.bench__rail::-webkit-scrollbar { display: none; }
/* Only fade the edge when there is genuinely something scrolled off it. */
.bench__rail.has-overflow {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
}
.bench__rail.has-overflow.at-end { -webkit-mask-image: none; mask-image: none; }
.bench__slider {
  position: absolute; top: 5px; bottom: 5px; left: 0; width: 0;
  background: var(--paper-2); border-radius: 10px; box-shadow: var(--shadow-1);
  transition: transform .42s var(--ease), width .42s var(--ease);
}
.bench__tab {
  position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 8px;
  flex: 1 0 auto; justify-content: center; white-space: nowrap;
  border: 0; background: transparent; font: inherit; font-size: 14px; font-weight: 500;
  color: var(--ink-3); cursor: pointer; padding: 10px 16px; border-radius: 10px; min-height: 42px;
  transition: color .25s;
}
.bench__tab svg { width: 16px; height: 16px; }
.bench__tab.is-active { color: var(--ink); font-weight: 600; }
.bench__tab:hover { color: var(--ink); }
.bench__panel {
  background: var(--paper-2); border: 1px solid var(--rule); border-radius: var(--r-lg);
  padding: clamp(18px, 3vw, 28px); animation: panelIn .4s var(--ease);
}

/* studio layout shared by QR + print */
.studio { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 300px); gap: clamp(22px, 4vw, 40px); }
.studio__stage { display: grid; place-content: center; gap: 14px; }
.studio__caption { font-size: 12.5px; color: var(--ink-3); text-align: center; margin: 0; }
.studio__caption strong { color: var(--gold-deep); font-family: var(--f-mono); }
.studio__caption .warn { color: var(--bad); font-weight: 600; }
.studio__stage--print .studio__caption { text-align: left; line-height: 1.55; }
.studio__controls { display: grid; gap: 20px; align-content: start; }
.studio__dl { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.studio__note { font-size: 12px; color: var(--ink-3); }

.qr-frame {
  width: min(300px, 68vw); aspect-ratio: 1; padding: 14px;
  background: #fff; border-radius: var(--r); border: 1px solid var(--rule);
  box-shadow: var(--shadow-2);
}
.qr-frame svg { display: block; width: 100%; height: 100%; }

/* QR module entrance, staggered outward from the middle */
.qr--anim rect, .qr--anim circle {
  transform-box: fill-box; transform-origin: center;
  animation: qrPop .42s var(--ease) backwards;
  animation-delay: calc(var(--ring, 0) * 22ms);
}
@keyframes qrPop { from { opacity: 0; scale: .25; } }

.ctl { display: grid; gap: 9px; }
.ctl__label {
  font-size: 11.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3); display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
}
.ctl__out { color: var(--ink); font-size: 12px; letter-spacing: 0; text-transform: none; }

.segmented { display: flex; gap: 3px; padding: 3px; background: var(--paper-3); border-radius: 10px; }
.seg {
  flex: 1; font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  border: 0; background: transparent; color: var(--ink-3);
  padding: 8px 10px; border-radius: 8px; min-height: 36px;
  transition: background .25s, color .25s;
}
.seg.is-active { background: var(--paper-2); color: var(--ink); font-weight: 600; box-shadow: var(--shadow-1); }
.seg:hover:not(.is-active) { color: var(--ink); }

.swatches { display: flex; gap: 7px; flex-wrap: wrap; }
.swatch {
  width: 30px; height: 30px; border-radius: 9px; cursor: pointer; padding: 0;
  background: var(--sw, #000); border: 2px solid transparent;
  box-shadow: 0 0 0 1px var(--rule) inset;
  transition: transform .2s var(--ease), border-color .2s;
}
.swatch:hover { transform: scale(1.1); }
.swatch.is-active { border-color: var(--gold); transform: scale(1.08); }
.swatch--custom {
  display: grid; place-items: center; overflow: hidden; position: relative;
  background: conic-gradient(from 0deg, #ef4444, #f59e0b, #22c55e, #3b82f6, #a855f7, #ef4444);
}
.swatch--custom input { position: absolute; inset: -6px; opacity: 0; cursor: pointer; }

.range {
  -webkit-appearance: none; appearance: none; width: 100%; height: 22px;
  /* The UA's default 2px margin survives the appearance reset and pushes a
     100%-wide track past its container on both sides. */
  margin: 0;
  background: transparent; cursor: pointer;
}
.range::-webkit-slider-runnable-track { height: 3px; background: var(--rule); border-radius: 99px; }
.range::-moz-range-track { height: 3px; background: var(--rule); border-radius: 99px; }
.range::-webkit-slider-thumb {
  -webkit-appearance: none; width: 17px; height: 17px; border-radius: 50%; margin-top: -7px;
  background: var(--paper-2); border: 2px solid var(--gold); box-shadow: var(--shadow-1);
  transition: transform .18s var(--ease);
}
.range::-moz-range-thumb {
  width: 17px; height: 17px; border-radius: 50%; border: 2px solid var(--gold);
  background: var(--paper-2); box-shadow: var(--shadow-1);
}
.range:active::-webkit-slider-thumb { transform: scale(1.2); }

.check {
  display: flex; align-items: center; gap: 9px; font-size: 14px; color: var(--ink-2); cursor: pointer;
}
.check input { width: 16px; height: 16px; accent-color: var(--gold); cursor: pointer; }

/* ── card preview stages ──────────────────────────────────────────────── */
.studio__stage--print { place-content: start; width: 100%; }

.card-stage {
  width: 100%; max-width: 340px; overflow: hidden;
  background: #fff; border: 1px solid var(--rule); border-radius: 3px;
  box-shadow: var(--shadow-2);
}
.card-stage > * { transform-origin: top left; }

/* Same `auto` minimum trap as .studio: the full-size card inside would stop the
   column shrinking, so pin the track and clear the items' min-width. */
.faces { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; width: 100%; }
.faces > * { min-width: 0; }
.face__tag {
  font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-3); margin: 0 0 7px; display: flex; align-items: center; gap: 8px;
}
.face__tag::after { content: ""; flex: 1; height: 1px; background: var(--rule); }

/* template picker */
.tilegrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.tile {
  min-width: 0;   /* grid items default to a min-content minimum */
  font: inherit; font-size: 12.5px; font-weight: 500; cursor: pointer; text-align: center;
  color: var(--ink-2); background: var(--paper); border: 1px solid var(--rule);
  border-radius: 9px; padding: 9px 6px; min-height: 38px;
  transition: border-color .2s, color .2s, background .2s, transform .2s var(--ease);
}
.tile:hover { border-color: var(--ink-3); color: var(--ink); transform: translateY(-1px); }
.tile.is-active {
  border-color: var(--gold); background: var(--gold-wash); color: var(--ink); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--gold);
}

.select {
  width: 100%; font: inherit; font-size: 15px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r);
  padding: 11px 36px 11px 14px; min-height: 46px; cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8173' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
}
.select:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 4px var(--gold-wash); }

.ctl--row { display: flex; flex-wrap: wrap; gap: 8px 20px; }
.ctl__hint { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ink-3); opacity: .8; }

.swatches--wrap { max-width: 100%; }

.randomiser {
  padding: 14px; border-radius: var(--r); text-align: center;
  background: var(--gold-wash);
  border: 1px solid color-mix(in srgb, var(--gold) 30%, transparent);
}
.btn--block { width: 100%; }
.randomiser__count { margin: 9px 0 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }
.randomiser__count b { font-family: var(--f-mono); font-size: 14px; color: var(--gold-deep); }
#cardShuffle:active svg { rotate: 180deg; transition: rotate .4s var(--ease); }

.ctl__warn {
  margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--bad); font-weight: 500;
}

.photo-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.btn--file { min-height: 40px; padding: 9px 14px; font-size: 14px; cursor: pointer; position: relative; }

/**
 * Off-screen but still in the tab order and the accessibility tree. `hidden`
 * (or display:none) would remove the file input from both, and a <label> has no
 * activation behaviour of its own — so the upload buttons were mouse-only.
 */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; white-space: nowrap;
  clip-path: inset(50%);
}
/* The focus ring has to come from the label, since the input itself is 1px. */
.btn--file:focus-within { outline: 2px solid var(--gold); outline-offset: 3px; }
.swatch--custom:focus-within { outline: 2px solid var(--gold); outline-offset: 2px; }
.photo-chip {
  width: 38px; height: 26px; border-radius: 5px; border: 1px solid var(--rule);
  background-size: cover; background-position: center; flex: none;
}

/* contact fields */
.fieldgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.fieldgrid .ctl--wide { grid-column: 1 / -1; }
.fieldgrid .ctl__label { font-size: 10.5px; margin-bottom: 5px; }
.fieldgrid .text-input { min-height: 40px; padding: 9px 12px; font-size: 14px; }
@media (max-width: 520px) { .fieldgrid { grid-template-columns: 1fr; } }

@media (max-width: 860px) {
  /* minmax(0, 1fr), not 1fr: a plain 1fr track has an `auto` minimum, so it
     refuses to shrink below the full-size card inside it and the preview spills
     off a narrow phone (invisibly, because body clips overflow-x). */
  .studio { grid-template-columns: minmax(0, 1fr); }
  .studio__stage { order: -1; min-width: 0; }
}

/* ─────────────────────────── ask kit ─────────────────────────── */
.kit { display: grid; gap: 20px; }
.kit__channels { display: flex; flex-wrap: wrap; gap: 9px; }
.channel {
  display: inline-flex; align-items: center; gap: 9px; text-decoration: none;
  font-size: 14px; font-weight: 600; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r);
  padding: 11px 18px; transition: border-color .2s, transform .2s var(--ease), background .2s;
}
.channel:hover { border-color: var(--gold); transform: translateY(-2px); background: var(--gold-wash); }
.channel__ico { font-size: 15px; }

.kit__templates { display: grid; gap: 12px; }
.tmpl {
  border: 1px solid var(--rule); border-radius: var(--r); overflow: hidden; background: var(--paper);
}
.tmpl__head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 14px; border-bottom: 1px solid var(--rule-soft); background: var(--paper-2);
}
.tmpl__name {
  font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
}
.tmpl__body {
  margin: 0; padding: 14px; font-size: 14.5px; line-height: 1.6; color: var(--ink-2);
  white-space: pre-wrap; word-break: break-word;
}
.kit__rule {
  margin: 0; padding: 14px 16px; font-size: 13.5px; color: var(--ink-2);
  background: var(--gold-wash); border-radius: var(--r);
  border-left: 3px solid var(--gold);
}
.kit__rule strong { color: var(--ink); }

/* ─────────────────────────── embed ─────────────────────────── */
.embed { display: grid; gap: 20px; }
.embed__label {
  font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
}
.embed__stage {
  display: grid; place-items: center; padding: 30px 20px; margin: 10px 0;
  background: var(--paper); border: 1px dashed var(--rule); border-radius: var(--r);
}
.embed__codehead { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.code {
  margin: 0; padding: 16px; border-radius: var(--r); overflow-x: auto;
  background: var(--paper); border: 1px solid var(--rule);
  font-size: 12.5px; line-height: 1.7; color: var(--ink-2); white-space: pre-wrap; word-break: break-word;
  max-height: 230px;
}
.embed__links { display: grid; gap: 10px; }
.linkline {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 11px 14px; border: 1px solid var(--rule); border-radius: var(--r); background: var(--paper);
}
.linkline__label {
  font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); flex: none; width: 92px;
}
.linkline__val { flex: 1; min-width: 180px; font-size: 12.5px; word-break: break-all; color: var(--ink-2); }

/* ─────────────────────────── editorial ─────────────────────────── */
.editorial { padding: clamp(56px, 9vw, 104px) 0; border-top: 1px solid var(--rule); }
.editorial--alt { background: var(--paper-3); }
.editorial__grid {
  display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: clamp(28px, 6vw, 72px); align-items: start;
}
.editorial__aside { position: sticky; top: 96px; }
.num--big {
  display: block; font-size: 13px; letter-spacing: .18em; margin-bottom: 14px;
  padding-bottom: 12px; border-bottom: 1px solid var(--rule);
}
.editorial__aside h2 { font-size: clamp(1.9rem, 3.6vw, 2.7rem); }
.editorial__body { max-width: 66ch; }
.editorial__body p { color: var(--ink-2); }
.editorial__body code { background: var(--paper-2); padding: 2px 6px; border-radius: 4px; border: 1px solid var(--rule-soft); }

.drop { font-size: 1.14rem; }
.drop::first-letter {
  float: left; font-family: var(--f-display); font-size: 3.5em; line-height: .82;
  padding: .06em .1em 0 0; color: var(--gold-deep);
}

.specs { margin: 34px 0 0; display: grid; gap: 0; }
.specs > div {
  display: grid; grid-template-columns: minmax(0, 200px) minmax(0, 1fr); gap: 22px;
  padding: 16px 0; border-top: 1px solid var(--rule);
}
.specs dt { font-weight: 600; font-size: 14.5px; }
.specs dd { margin: 0; font-size: 14.5px; color: var(--ink-2); }

.playbook { list-style: none; margin: 0; padding: 0; counter-reset: pb; }
.playbook li { counter-increment: pb; padding: 22px 0 22px 52px; border-top: 1px solid var(--rule); position: relative; }
.playbook li::before {
  content: counter(pb, decimal-leading-zero);
  position: absolute; left: 0; top: 24px;
  font-family: var(--f-mono); font-size: 12px; color: var(--gold-deep); letter-spacing: .06em;
}
.playbook h3 { font-size: 1.06rem; margin-bottom: .35em; }
.playbook p { margin: 0; font-size: 14.5px; }
.caveat {
  margin-top: 26px; padding: 16px 18px; font-size: 13.5px; color: var(--ink-2);
  border-left: 3px solid var(--gold); background: var(--paper-2); border-radius: 0 var(--r) var(--r) 0;
}

/* ───────────────────────── standalone page header ──────────────────────── */
/* about.html has no hero specimen beside it, so the head is a single column
   that simply sets the title and gets out of the way. Reuses .tag, .display and
   .lede from the front page rather than inventing a second type scale. */
.pagehead {
  padding: clamp(46px, 7vw, 88px) 0 clamp(26px, 3.5vw, 40px);
  border-bottom: 1px solid var(--rule);
}
/* .display sets the family but no size, so without this the heading falls back
   to the browser's default 2rem and the page title comes out smaller than the
   body copy around it deserves. Smaller than the home hero on purpose. */
.pagehead h1 {
  font-size: clamp(2.1rem, 5vw, 3.2rem);
  max-width: 20ch; margin: 0 0 20px;
}
.pagehead .lede { max-width: 52ch; }

/* ─────────────────────────────── about ─────────────────────────────────── */
/* Two subheads inside one editorial body, so they need more air above than a
   default heading margin gives — otherwise "The person behind it" reads as a
   continuation of the paragraph above it rather than a new part. */
.about__head {
  margin: 34px 0 10px; font-size: 1.06rem; letter-spacing: .01em;
}
.about__head:first-child { margin-top: 0; }
.editorial__body .about__head + p { margin-top: 0; }
.editorial__body strong { color: var(--ink); font-weight: 600; }
#about a {
  color: var(--gold-deep); text-decoration: underline;
  text-underline-offset: 2px; text-decoration-thickness: 1px;
}
#about a:hover, #the-owner .editorial__body a:not(.btn):hover { color: var(--ink); }
#the-owner .editorial__body a:not(.btn) {
  color: var(--gold-deep); text-decoration: underline;
  text-underline-offset: 2px; text-decoration-thickness: 1px;
}
/* Portrait beside the opening line on desktop, stacked above it on narrow
   screens. The photo is a square file; the circle is CSS, so the image itself
   needs no alpha channel. */
.bio { display: flex; gap: 22px; align-items: flex-start; }
.bio__photo {
  flex: none; width: 118px; height: 118px;
  border-radius: 50%; object-fit: cover;
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-2, 0 6px 20px rgba(0,0,0,.10));
}
.bio__text { margin: 0; }
@media (max-width: 560px) {
  .bio { flex-direction: column; gap: 16px; }
  .bio__photo { width: 96px; height: 96px; }
}

/* The way back to the finder, so the page is not a dead end. */
.about__back { margin-top: 32px; }
.about__back .btn { text-decoration: none; }

/* The nav item for the page you are already on. */
.masthead__nav a[aria-current="page"] { color: var(--ink); }

.qa details { border-top: 1px solid var(--rule); }
.qa details:last-child { border-bottom: 1px solid var(--rule); }
.qa summary {
  list-style: none; cursor: pointer; padding: 18px 40px 18px 0; position: relative;
  font-weight: 600; font-size: 15.5px; transition: color .2s;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary:hover { color: var(--gold-deep); }
.qa summary::after, .qa summary::before {
  content: ""; position: absolute; right: 6px; top: 50%; background: var(--ink-3);
  transition: transform .35s var(--ease), background .2s;
}
.qa summary::after  { width: 13px; height: 1.5px; translate: 0 -50%; }
.qa summary::before { width: 1.5px; height: 13px; translate: -5.75px -50%; }
.qa details[open] summary::before { transform: rotate(90deg); }
.qa details[open] summary { color: var(--gold-deep); }
.qa details[open] summary::after, .qa details[open] summary::before { background: var(--gold); }
.qa details > div { overflow: hidden; animation: qaOpen .42s var(--ease); }
.qa details p { padding-bottom: 6px; margin: 0 0 10px; font-size: 15px; }
@keyframes qaOpen { from { opacity: 0; transform: translateY(-8px); } }

@media (max-width: 860px) {
  /* minmax(0, …), matching the rest of the file: this track holds a 27-character
     unbreakable Place ID, and a bare 1fr refuses to shrink below it. */
  .editorial__grid { grid-template-columns: minmax(0, 1fr); }
  .editorial__aside { position: static; }
  .specs > div { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* ─────────────────────────── colophon ─────────────────────────── */
/* A black band, deliberately not a token: this footer stays dark in BOTH themes,
   so --paper/--ink would invert underneath it and put dark text on black. The
   blues below are the lifted ones — the #2f4ef0 accent is only 3.2:1 here and
   would be unreadable at 12-14px. */
.colophon {
  border-top: 1px solid rgba(255,255,255,.12);
  background: #0c0d10;
  padding: 42px 0;
  margin-top: 64px;
}
.colophon__inner {
  display: flex; flex-wrap: wrap; gap: 20px; justify-content: space-between; align-items: flex-start;
}
.colophon__title { font-family: var(--f-display); font-size: 1.25rem; margin: 0 0 4px; color: #c7d4ff; }
.colophon__sub { font-size: 14px; color: #8fa7ff; margin: 0; }

/* The masthead nav is hidden below 900px, so without this the About page — which
   lives at its own URL — has no reachable link at all on a phone. The footer is
   the conventional place for it and needs no menu button. */
.colophon__nav { display: flex; flex-wrap: wrap; gap: 2px 20px; margin-top: 14px; }
.colophon__nav a {
  font-size: 13.5px; color: #8fa7ff; text-decoration: none;
  padding: 8px 0;                       /* ≥ 32px tall: a real tap target */
  transition: color .2s;
}
.colophon__nav a:hover,
.colophon__nav a[aria-current="page"] { color: #ffffff; }
/* Quieter than the tagline above it — a colophon, not a second headline. */
.colophon__built { font-size: 12.5px; color: #8fa7ff; opacity: .8; margin: 8px 0 0; }
.colophon__legal { font-size: 12px; color: #8fa7ff; max-width: 42ch; margin: 0; line-height: 1.55; }

/* ─────────────────────────── modal & toast ─────────────────────────── */
.modal {
  border: 1px solid var(--rule); border-radius: var(--r-lg); padding: 0;
  background: var(--paper-2); color: var(--ink);
  width: min(460px, calc(100vw - 32px)); box-shadow: var(--shadow-3);
}
.modal::backdrop { background: rgba(16,20,27,.5); backdrop-filter: blur(3px); }
.modal[open] { animation: modalIn .32s var(--ease); }
@keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(.97); } }
.modal__inner { padding: 26px; }
.modal__inner h2 { font-size: 1.4rem; margin-bottom: .3em; }
.modal__inner .help { margin-bottom: 18px; }
.modal__inner .check { margin-top: 12px; }
.modal__acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 24px; }
.grow { flex: 1; }

.toast {
  position: fixed; left: 50%; bottom: 28px; translate: -50% 0; z-index: 120;
  display: flex; align-items: center; gap: 9px;
  background: var(--ink); color: var(--paper-2);
  padding: 12px 20px; border-radius: 99px; font-size: 14px; font-weight: 500;
  box-shadow: var(--shadow-3); max-width: calc(100vw - 32px);
  animation: toastIn .38s var(--ease);
}
@keyframes toastIn { from { opacity: 0; transform: translateY(16px) scale(.94); } }

/* ─────────────────────────── reveal on scroll ─────────────────────────── */
.reveal { opacity: 0; transform: translateY(18px); }
.reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  /* The deck must still be visible with motion off — cardIn starts at opacity 0,
     so cancelling the animation without restoring it would leave four blanks. */
  .specimen__deck { animation: none; }
  .specimen__card { animation: none; opacity: 1; }
}

/* Print rules live in cards.css, next to the artwork they govern. */
.print-sheet { display: none; }

/* ─────────────────────────── small screens ─────────────────────────── */
@media (max-width: 560px) {
  :root { --gut: 18px; }
  .tabs { gap: 0; }
  .tab { font-size: 13px; padding: 8px 6px; }
  .ident { flex-direction: column; align-items: stretch; }
  .ident .btn { align-self: flex-start; }
  .linkbox__acts .btn { flex: 1 1 100%; }
  .bench__tab { flex: 0 0 auto; }
  .kit__channels .channel { flex: 1 1 100%; justify-content: center; }
  .specs > div { padding: 14px 0; }
}

/* ─────────────────────────── contact page ─────────────────────────── */
.cform { margin-top: 8px; }
.cform__grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 26px 32px;
  border-top: 2px solid var(--ink); padding-top: 30px;
}
.field--wide { grid-column: 1 / -1; }
.field__label { display: block; font-size: 15px; font-weight: 600; margin-bottom: 8px; }
.field__opt { font-weight: 400; color: var(--ink-3); }
.field__hint {
  display: flex; justify-content: space-between; gap: 14px;
  font-size: 13px; color: var(--ink-3); margin: 7px 0 0;
}
.cform__count { font-family: var(--f-mono); font-size: 12px; white-space: nowrap; }
.cform__count.is-full { color: var(--bad); }
.field__err { font-size: 13px; color: var(--bad); margin: 7px 0 0; }

.input {
  width: 100%; font: inherit; font-size: 15px; color: var(--ink);
  background: var(--paper-2); border: 1.5px solid var(--rule);
  border-radius: var(--r-sm); padding: 13px 14px;
  transition: border-color .18s, box-shadow .18s;
}
.input:focus-visible {
  outline: none; border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent);
}
.input[aria-invalid="true"] { border-color: var(--bad); }
.textarea { resize: vertical; min-height: 160px; line-height: 1.55; }
/* Native arrow removed so the control matches the text inputs; the chevron is
   drawn as a background so it inherits the theme. */
.select {
  appearance: none; padding-right: 40px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 20px) calc(50% + 2px), calc(100% - 14px) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

/* Off-screen rather than display:none — bots that skip hidden inputs still
   fill this one, which is the entire point of a honeypot. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.cform__foot {
  display: flex; align-items: center; gap: 26px; flex-wrap: wrap; margin-top: 28px;
}
.cform__send.is-busy { opacity: .7; pointer-events: none; }
.cform__privacy { font-size: 13px; color: var(--ink-3); max-width: 46ch; margin: 0; line-height: 1.55; }

.cform__status {
  margin: 22px 0 0; padding: 14px 16px; border-radius: var(--r-sm);
  font-size: 14.5px; line-height: 1.55; border: 1.5px solid var(--rule);
  background: var(--paper-2);
}
.cform__status a { color: var(--gold-deep); }
.cform__status.is-good { border-color: var(--good); background: color-mix(in srgb, var(--good) 10%, var(--paper-2)); }
.cform__status.is-bad  { border-color: var(--bad);  background: var(--bad-wash); }

.cards2 { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
.panel {
  border: 1.5px solid var(--rule); border-radius: var(--r);
  background: var(--paper-2); padding: 26px 26px 22px;
}
.panel__head { font-size: 19px; margin: 0 0 10px; }
.panel__sub { font-size: 14.5px; color: var(--ink-2); margin: 0; line-height: 1.6; }
.deflist { list-style: none; margin: 20px 0 0; padding: 0; }
.deflist li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 18px;
  padding: 14px 0; border-top: 1px solid var(--rule-soft);
}
.deflist__k { font-size: 15px; font-weight: 600; white-space: nowrap; }
.deflist__v { font-size: 14px; color: var(--ink-3); text-decoration: none; text-align: right; word-break: break-word; }
.deflist__v:hover { color: var(--gold-deep); }

@media (max-width: 760px) {
  .cform__grid { grid-template-columns: 1fr; gap: 22px; }
  .cards2 { grid-template-columns: 1fr; }
  .cform__foot { gap: 18px; }
  .cform__send { width: 100%; justify-content: center; }
}

/* The three routes in "Reach me directly" are the primary mobile action on this
   page — tap to call, tap to open Telegram. At 23px they were under the ~44px
   tap-target guideline, so give them real vertical padding and let the long
   email wrap onto its own line instead of being squeezed right. */
@media (max-width: 760px) {
  .deflist li { flex-wrap: wrap; gap: 2px 18px; padding: 8px 0; }
  .deflist__v { text-align: left; padding: 11px 0; }
}
