/* ============================================================================
   High & Divine Body Expressions -- datarail.org/tattoo

   The palette is read off the shop's own material rather than invented: the
   near-black of the studio walls, the cyan glow the price card is lettered in,
   the violet of the tapestry behind the chair, and the blush of the cushions
   on it. Bone, not white, for text -- the mark is drawn in line, and line work
   on black is never quite white.

   Headings are set in whatever old-style serif the reader already has, in
   caps, letterspaced. A tattoo shop wants blackletter and no blackletter ships
   with a browser; a letterspaced serif carries the same weight and costs
   nothing to load. That matters here -- see below.

   No web fonts, no frameworks, no analytics, no icon CDN, and no JavaScript
   at all. Nothing on this page needs any. The site has to survive being picked
   up and put down on its own domain one day, so it depends on nothing it does
   not ship, and every path in it is relative for the same reason.
   ========================================================================= */

:root {
  --ink: #07070b;
  --ink-soft: #0c0c13;
  --raised: #14131d;
  --raised-hi: #1e1c2b;

  --bone: #f2eee9;
  --bone-dim: #bab3c2;
  --bone-faint: #837c91;

  /* --violet is for large text, rules and fills only: at small sizes it sits
     right on 4.5:1 against the ground and there is no reason to gamble on a
     rounding error. --violet-bright clears it comfortably and carries the
     small text. --glow clears it at any size. */
  --glow: #5ee7ff;
  --glow-deep: #1ea9c8;
  --violet: #8b5cf6;
  --violet-bright: #b794ff;
  --blush: #ffb3c7;

  --rule: #221f30;
  --rule-hi: #383150;

  --font-body: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-display: "Iowan Old Style", "Palatino Linotype", Palatino,
    "Book Antiqua", Georgia, "Times New Roman", serif;

  --shell: 1080px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --radius: 4px;
  --fast: 160ms ease-out;

  color-scheme: dark;
}

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ink);
  background-image:
    radial-gradient(ellipse at 50% -15%, #241146 0%, transparent 62%),
    radial-gradient(ellipse at 100% 8%, #06323d 0%, transparent 45%),
    radial-gradient(ellipse at 0% 100%, #1a0a24 0%, transparent 55%);
  background-attachment: fixed;
  color: var(--bone);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--glow); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--bone); }

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

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

/* The ampersand is the one piece of lettering the shop's own mark does not
   give us, so it gets set apart: italic, in the old style, in the glow. */
.amp {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--glow);
}

/* --- shell ---------------------------------------------------------------- */

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

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--violet);
  color: #fff;
  padding: 0.6rem 1rem;
  z-index: 50;
}
.skip:focus { left: 0; }

/* --- masthead ------------------------------------------------------------- */

.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(7, 7, 11, 0.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}

.masthead .shell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  padding-block: 0.7rem;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--bone);
  text-decoration: none;
  margin-right: auto;
}

.wordmark-mark {
  width: 34px;
  height: 34px;
  flex: none;
  opacity: 0.9;
  transition: opacity var(--fast);
}
.wordmark:hover .wordmark-mark { opacity: 1; }

.wordmark-text { display: grid; }

.wordmark-line {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  line-height: 1.1;
}

.wordmark-sub {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--bone-faint);
}

.masthead nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.15rem;
}

.masthead nav a {
  color: var(--bone-dim);
  text-decoration: none;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  padding-block: 0.2rem;
  border-bottom: 1px solid transparent;
  transition: color var(--fast), border-color var(--fast);
}
.masthead nav a:hover {
  color: var(--bone);
  border-bottom-color: var(--glow);
}

/* --- buttons -------------------------------------------------------------- */

.button {
  display: inline-block;
  padding: 0.7rem 1.35rem;
  border: 1px solid var(--rule-hi);
  border-radius: var(--radius);
  background: var(--raised);
  color: var(--bone);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  text-decoration: none;
  transition: background var(--fast), border-color var(--fast),
    color var(--fast), transform var(--fast);
}
.button:hover {
  background: var(--raised-hi);
  border-color: var(--glow-deep);
  color: var(--bone);
  transform: translateY(-1px);
}

.button--primary {
  background: linear-gradient(120deg, var(--violet), var(--glow-deep));
  border-color: transparent;
  color: #07070b;
  font-weight: 700;
}
.button--primary:hover {
  color: #07070b;
  filter: brightness(1.12);
}

/* --- hero ----------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.5rem, 11vw, 7rem) clamp(3rem, 8vw, 5rem);
}

/* The shop's mark, blown up and turned almost all the way down. It is the one
   decorative element on the page, and it is theirs rather than ours.

   Two elements, not one, and the split is load-bearing. The child carries the
   mask and the travelling highlight; the parent carries the glow and the
   breathing. It has to be that way round because a filter is applied BEFORE a
   mask in the rendering order, so a drop-shadow set on the masked element
   itself would be computed against the full rectangle and then masked away
   with it. Put it on the parent and it sees the bones. */
.hero-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;

  /* The peak and trough of the breath, as variables so a narrow screen can
     turn the whole thing down without fighting the animation for the
     opacity property. */
  --bone-lo: 0.07;
  --bone-hi: 0.17;

  animation: bone-breathe 6.5s ease-in-out infinite;
}

.hero-glow::before {
  content: "";
  position: absolute;
  inset: 0;

  /* Two layers: a highlight that travels, over a flat bone-coloured fill.
     The mask clips both to the mark, so the highlight runs along the bones
     themselves rather than sweeping across a rectangle behind them. */
  background-image:
    linear-gradient(112deg,
      transparent 40%,
      rgba(255, 255, 255, 0.9) 47%,
      rgba(94, 231, 255, 0.95) 51%,
      rgba(183, 148, 255, 0.7) 55%,
      transparent 62%),
    linear-gradient(var(--bone), var(--bone));
  background-repeat: no-repeat;
  background-size: 320% 320%, 100% 100%;
  background-position: 135% 0, 0 0;

  -webkit-mask-image: url(../img/mark.svg);
  mask-image: url(../img/mark.svg);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: 88% 42%;
  mask-position: 88% 42%;
  -webkit-mask-size: clamp(340px, 52vw, 620px);
  mask-size: clamp(340px, 52vw, 620px);

  animation: bone-shimmer 7.5s linear infinite;
}

/* The shimmer. Long and slow on purpose: this sits behind the first words
   anybody reads, and a quick sweep there reads as a fault rather than a
   finish. */
@keyframes bone-shimmer {
  0%   { background-position: 135% 0, 0 0; }
  100% { background-position: -35% 0, 0 0; }
}

/* The pulse. Opacity and the glow move together, so the mark brightens and
   blooms at the same moment instead of flickering. */
@keyframes bone-breathe {
  0%, 100% {
    opacity: var(--bone-lo);
    filter: drop-shadow(0 0 5px rgba(94, 231, 255, 0.2));
  }
  50% {
    opacity: var(--bone-hi);
    filter: drop-shadow(0 0 20px rgba(94, 231, 255, 0.55));
  }
}

.hero .shell { position: relative; }

.eyebrow {
  margin: 0 0 1.1rem;
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.26em;
  color: var(--glow);
}

.hero h1 {
  font-size: clamp(2.35rem, 8.5vw, 4.6rem);
  letter-spacing: 0.02em;
  text-shadow: 0 0 28px rgba(94, 231, 255, 0.18);
}

.lede {
  max-width: 46ch;
  margin: 1.5rem 0 0;
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.2rem);
  color: var(--bone-dim);
}

.platforms {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
}
.platforms--wide { margin-top: 1.5rem; }

/* --- bands ---------------------------------------------------------------- */

.band {
  padding-block: clamp(3rem, 8vw, 4.75rem);
  border-top: 1px solid var(--rule);
  /* The masthead is sticky, so a jump to #piercings would otherwise land with
     the heading hidden underneath it. */
  scroll-margin-top: 4.5rem;
}

.band--soft { background: rgba(12, 12, 19, 0.72); }

.band-head {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin-bottom: 1.1rem;
}
.band-head h2 { font-size: clamp(1.5rem, 4vw, 2.1rem); }
.band-head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--rule-hi), transparent);
}

.band-note {
  max-width: 62ch;
  color: var(--bone-dim);
  margin-bottom: 2rem;
}

.footnote {
  margin-top: 1.75rem;
  max-width: 62ch;
  font-size: 0.88rem;
  color: var(--bone-faint);
}

/* --- the shop's own words ------------------------------------------------- */

.band--quote { border-top: 1px solid var(--rule); }

.creed {
  margin: 0;
  max-width: 34ch;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 1.1rem + 1.4vw, 2rem);
  line-height: 1.3;
  border-left: 2px solid var(--violet);
  padding-left: clamp(1rem, 3vw, 2rem);
}
.creed p { margin-bottom: 0.7rem; }
.creed strong { color: var(--glow); font-weight: 700; }
.creed footer {
  font-family: var(--font-body);
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--bone-faint);
}

/* --- cards ---------------------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.card {
  background: var(--raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.35rem;
  transition: border-color var(--fast), background var(--fast);
}
.card:hover { border-color: var(--rule-hi); background: var(--raised-hi); }

.card h3 {
  font-size: 0.95rem;
  letter-spacing: 0.12em;
  color: var(--blush);
  margin-bottom: 0.6rem;
}
.card p { font-size: 0.92rem; color: var(--bone-dim); }

/* --- callout -------------------------------------------------------------- */

.callout {
  margin-top: 2rem;
  padding: clamp(1.25rem, 4vw, 1.9rem);
  border: 1px solid var(--rule-hi);
  border-radius: var(--radius);
  background:
    linear-gradient(140deg, rgba(139, 92, 246, 0.14), rgba(30, 169, 200, 0.08));
}
.callout h3 {
  font-size: 1.1rem;
  margin-bottom: 0.7rem;
}
.callout p { max-width: 58ch; color: var(--bone-dim); }
.callout-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-top: 1.25rem;
}

/* --- piercing rates ------------------------------------------------------- */

/* 190px rather than a rounder number so that all three groups sit on one row
   from tablet width up. The list is short enough to take in at a glance, and
   it stops being a glance the moment $40 drops to a second row on its own. */
.rates {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1rem;
}

.rate-group {
  background: var(--raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.35rem;
}

/* The price card the shop posts is lettered in a cyan that glows. This is the
   nearest a browser gets without loading anything. */
.rate-fee {
  font-size: 1.9rem;
  letter-spacing: 0.04em;
  color: var(--glow);
  text-shadow: 0 0 18px rgba(94, 231, 255, 0.35);
  margin-bottom: 0.9rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--rule-hi);
}

.rate-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.price {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding-block: 0.4rem;
}
.price + .price { border-top: 1px dashed var(--rule); }

.price-name {
  font-size: 0.97rem;
  color: var(--bone);
}

/* The amount is repeated on every row, not only in the group heading, so that
   a row copied out of context still carries its price. It is dimmed rather
   than hidden: the heading is the loud one. */
.price-fee {
  margin-left: auto;
  font-family: var(--font-display);
  font-size: 0.92rem;
  letter-spacing: 0.06em;
  color: var(--bone-faint);
}

/* --- the artist ----------------------------------------------------------- */

.artist {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 5vw, 3rem);
  align-items: start;
}

.artist-body p { max-width: 54ch; color: var(--bone-dim); }
.artist-body strong { color: var(--bone); }

.artist-side {
  background: var(--raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.35rem;
}
.artist-side h3 {
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  color: var(--bone-faint);
  margin-bottom: 1rem;
}

.plain {
  list-style: none;
  margin: 0;
  padding: 0;
}
.plain li + li { margin-top: 1rem; }
/* @highanddivinebodyexpressions is 29 characters with nowhere to break. */
.plain a { overflow-wrap: anywhere; }

.plain--row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
}
.plain--row li + li { margin-top: 0; }

.side-note {
  display: block;
  font-size: 0.82rem;
  color: var(--bone-faint);
  line-height: 1.45;
}

/* --- facts (studio, before you book) -------------------------------------- */

.facts {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--rule);
  max-width: 44rem;
}
.facts li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.5rem;
  padding-block: 0.85rem;
  border-bottom: 1px solid var(--rule);
}
.fact-key {
  flex: 0 0 9rem;
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--bone-faint);
  padding-top: 0.2rem;
}
.fact-value { flex: 1 1 14rem; }

/* --- the work ------------------------------------------------------------- */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.shot {
  margin: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--raised);
}
.shot img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}
.shot figcaption {
  padding: 0.7rem 0.85rem;
  font-size: 0.84rem;
  color: var(--bone-faint);
  line-height: 1.45;
}

/* --- booking -------------------------------------------------------------- */

.band--book {
  background:
    linear-gradient(180deg, rgba(139, 92, 246, 0.1), transparent 70%),
    rgba(12, 12, 19, 0.72);
}

/* --- colophon ------------------------------------------------------------- */

.colophon {
  border-top: 1px solid var(--rule);
  padding-block: 2.5rem 3.5rem;
  font-size: 0.88rem;
  color: var(--bone-faint);
}
.colophon strong { color: var(--bone-dim); }
.colophon-note { max-width: 62ch; }
.colophon .plain--row { margin-top: 1.25rem; }

/* --- narrow --------------------------------------------------------------- */

@media (max-width: 720px) {
  .artist { grid-template-columns: minmax(0, 1fr); }
  /* Centred behind the headline on a phone, and turned down, because there
     is no margin to put it in. */
  .hero-glow { --bone-lo: 0.045; --bone-hi: 0.11; }
  .hero-glow::before {
    -webkit-mask-position: 50% 30%;
    mask-position: 50% 30%;
  }
  .platforms .button { flex: 1 1 auto; text-align: center; }

  /* The nav wraps to a second line on a phone, which puts the masthead at
     roughly a sixth of the screen. Sticky is worth that on a desktop and is
     not worth it here, so on a narrow screen the header scrolls away with
     everything else. */
  .masthead { position: static; }
  .masthead .shell { padding-block: 0.6rem; gap: 0.5rem 1rem; }
  .masthead nav { gap: 0.3rem 0.95rem; }
  .masthead nav a { font-size: 0.76rem; letter-spacing: 0.1em; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }

  /* The blanket rule above would leave the mark frozen on the first frame of
     the breath, which is its dimmest. Stop the animations properly instead
     and hold it at a readable middle, with the highlight parked off the
     shape so no half-swept gradient is stranded across it. */
  .hero-glow,
  .hero-glow::before { animation: none !important; }
  .hero-glow {
    opacity: 0.12;
    filter: drop-shadow(0 0 8px rgba(94, 231, 255, 0.25));
  }
  .hero-glow::before { background-position: 200% 0, 0 0; }
}
