/*
 * Components — Shear Madness Barbering
 * Buttons, hero, panels, forms, FAQ, blog, news, events, gallery.
 * Flat ink-on-paper: rules do the work, nothing floats, nothing glows.
 */

/* ---- Buttons ---- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: 0.7rem 1.4rem;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  border: var(--rule) solid var(--color-ink);
  background: var(--color-paper);
  color: var(--color-ink);
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast),
    border-color var(--transition-fast);
}

.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-offset);
}

.btn--lg {
  padding: 0.9rem 1.8rem;
  font-size: var(--text-lg);
}

.btn--primary {
  background: var(--color-brand);
  border-color: var(--color-brand);
  color: var(--color-paper-on-dark);
}

.btn--primary:hover {
  background: var(--color-brand-dark);
  border-color: var(--color-brand-dark);
  color: var(--color-paper-on-dark);
}

.btn--signal {
  background: var(--color-signal);
  border-color: var(--color-signal);
  color: var(--color-paper-on-dark);
}

.btn--signal:hover {
  background: var(--color-signal-dark);
  border-color: var(--color-signal-dark);
  color: var(--color-paper-on-dark);
}

.btn--outline {
  background: transparent;
  color: var(--color-ink);
  border-color: var(--color-ink);
}

.btn--outline:hover {
  background: var(--color-ink);
  color: var(--color-paper-on-dark);
}

/* For dark (ink or brand) surfaces */
.btn--ghost {
  background: transparent;
  color: var(--color-paper-on-dark);
  border-color: var(--color-paper-on-dark);
}

.btn--ghost:hover {
  background: var(--color-paper-on-dark);
  color: var(--color-ink);
}

/* ---- Hero ---- */

/* The hero is the loft itself: the shop's own olive wall colour, edge to
   edge, with a real photograph of the room running off the right-hand side of
   the screen. No gradient, no overlay wash, no carousel.
   The photograph used to sit as a floating rectangle inside the container with
   a caption under it, which read as a stock image dropped into a slot. Letting
   it bleed past the measure and fill the full height of the band makes it the
   wall of the room rather than a picture of one. */
.hero {
  background: var(--color-brand);
  color: var(--color-paper-on-dark);
  padding-block: var(--space-2xl) var(--space-3xl);

  /* The figure bleeds to the viewport edge; clip (not hidden) so no horizontal
     scrollbar appears and no scroll container is created. */
  overflow-x: clip;
}

.hero-grid {
  display: grid;
  gap: var(--space-2xl);
  align-items: center;
}

/* Distance from the container's content edge out to the viewport edge. */
.hero .hero-figure {
  --hero-bleed: calc(
    (100vw - min(100vw, var(--container-max))) / 2 + var(--container-padding)
  );
}

/* Banner mark, taken from the ribbon across the bottom of the shop's badge:
   solid rust bar, bone caps. Squared off — not a pill. */
.hero-stamp {
  display: inline-block;
  /* .hero-content is a flex column at desktop, and a flex item stretches on
     the cross axis by default. Without this the ribbon runs the full width of
     the text column and stops reading as a stamp. */
  align-self: flex-start;
  font-family: var(--font-body);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-label);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink-on-signal);
  background: var(--color-signal);
  padding: var(--space-xs) var(--space-md);
  margin-block-end: var(--space-lg);
}

.hero h1 {
  color: var(--color-paper-on-dark);
  margin-block-end: var(--space-lg);
  font-size: var(--display-hero);
}

/*
 * Sizing the hero headline.
 *
 * "TRANSFORMATION" is the widest word on the site: measured in Alfa Slab at
 * the tracking used here, it sets 10.849x its own font-size. That one number
 * governs this whole composition. The original build tried to satisfy it with
 * a viewport-based clamp, which cannot work, because the width of the text
 * COLUMN is not a fixed fraction of the viewport once a breakpoint changes the
 * grid. When the clamp guessed high the word overflowed, and `hyphens: auto`
 * caught it by breaking mid-word: "TRANSFORMATIO / N STARTS HERE."
 *
 * The headline is therefore sized from its own column instead of from the
 * viewport. 1cqi is 1% of .hero-content's inline size, so 8.9cqi keeps the
 * longest word at ~97% of the space it actually has, at every width, whatever
 * the grid does later. --display-hero above stays as the fallback for engines
 * without container queries.
 *
 * Declaring the container also fixes the original root cause: an inline-size
 * container's width cannot be set by its contents, so the headline can no
 * longer set a min-content floor that starves the photo column beside it.
 */
.hero-content {
  container-type: inline-size;
  min-width: 0;
}

@supports (container-type: inline-size) {
  .hero h1 {
    font-size: min(3.6rem, 8.9cqi);
  }
}


/* On olive the rust has too little contrast to carry a word, so the marked
   word keeps the bone and takes a painted rust underline instead. */
.hero h1 em {
  color: inherit;
  box-shadow: inset 0 -0.13em 0 var(--color-signal-bright);
}

.hero-description {
  font-size: var(--text-lg);
  color: var(--color-ink-soft);
  max-width: 36rem;
  margin-block-end: var(--space-xl);
}

/* Only the homepage hero sits on olive. */
.hero .hero-description {
  color: var(--color-faint-on-dark);
}

/* .hero-figure is used in THREE places: the homepage hero, and as a plain
   captioned photograph inside .split on /gallery and /about. The bleed and the
   forced crop below belong only to the homepage hero, so they are scoped to
   `.hero .hero-figure`. Applying them unscoped cropped the two room
   photographs to 4:3 and pulled them outside their column. */
.hero-figure {
  margin: 0;
}

.hero-figure img {
  display: block;
  width: 100%;
  height: auto;
}

.hero-figure figcaption {
  margin-block-start: var(--space-sm);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink-faint);
}

.section--ink .hero-figure figcaption {
  color: var(--color-faint-on-dark);
}

/* Homepage hero only: bleeds both edges on mobile, and on desktop fills the
   full height of the band and runs off the right of the screen. */
.hero .hero-figure {
  margin-inline: calc(-1 * var(--container-padding));
}

.hero .hero-figure img {
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 58% 50%;   /* keeps the chair and the bowl in frame */
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
}

/* The phone is text, not a button — the way shops actually print it */
.hero-phone {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-2xl);
  letter-spacing: var(--tracking-display);
  color: var(--color-paper-on-dark);
  text-decoration: none;
  white-space: nowrap;
}

.hero-phone:hover {
  color: var(--color-paper-on-dark);
  text-decoration: underline;
  text-decoration-thickness: 3px;
  text-decoration-color: var(--color-signal-bright);
}

/* The sub-line under the phone number and the address/hours note that used to
   close the hero are both gone. Between the stamp, the headline, the
   paragraph, the button, the phone, a phone sub-line and a footnote, the hero
   was carrying seven pieces of text and none of them had room to land. The
   address and hours now sit in the shop bar directly below, where they are
   navigable rather than decorative. */

/* Shop placard — a bone card with a rust banner head, the way the shop's own
   badge puts its name on a ribbon. Used for the standing facts of the shop. */
.shop-card {
  background: var(--color-paper-shade);
  color: var(--color-ink);
}

.shop-card-title {
  font-family: var(--font-body);
  font-weight: var(--weight-bold);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  background: var(--color-signal);
  color: var(--color-ink-on-signal);
  padding: var(--space-sm) var(--space-lg);
}

.shop-card-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-lg);
  font-size: var(--text-sm);
}

.shop-card-row dt {
  color: var(--color-ink-faint);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}

.shop-card-row dd {
  margin: 0;
  text-align: right;
  font-weight: var(--weight-semibold);
}

.shop-card-row dd a {
  text-decoration: none;
  color: var(--color-brand);
}

.shop-card-row dd a:hover {
  text-decoration: underline;
}

.shop-card-foot {
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  font-size: var(--text-xs);
  color: var(--color-ink-faint);
}

/* Sub-page hero.
   The section that follows carries a full --space-section of top padding, so
   without this the page title and its own first paragraph were separated by
   roughly 190px of empty ground, which reads as a layout fault rather than as
   breathing room. The title block keeps its space above and hands off tightly
   to the content it introduces. */
.page-hero {
  padding-block: var(--space-3xl) 0;
}

.page-hero + .section,
.page-hero + .double-rule + .section {
  padding-block-start: var(--space-2xl);
}

.page-hero h1 {
  margin-block-end: var(--space-sm);
}

.page-hero .hero-description {
  margin-block-end: 0;
}

/* ---- Shop Bar ---- */
/*
 * Replaces the old .spec-line, which set four marketing adjectives
 * ("Woman-owned · Behind the chair since 2010 · Complimentary drink, every
 * visit · Sensory-friendly days") in centred caps separated by middle dots
 * directly under the hero. Two problems with it: a dot-separated strip of
 * adjectives is decoration rather than information, and all four of those
 * facts already appear, in full sentences, in the checklist one section
 * further down. It was duplication dressed as a design element.
 *
 * What sits here instead is the information a visitor actually wants within a
 * screen of arriving and would otherwise have to go to /contact for: where the
 * shop is, when it is open, and how to reach a person. Every item is a real
 * link. No facts were removed from the page.
 */

.shop-bar {
  background: var(--color-paper-shade);
  border-block-end: var(--rule-hairline) solid var(--color-rule-faint);
}

.shop-bar .container {
  display: grid;
  gap: var(--space-lg);
  padding-block: var(--space-lg);
}

.shop-bar-item {
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
}

.shop-bar-label {
  font-family: var(--font-body);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-label);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-signal);
}

.shop-bar-value {
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.shop-bar-value a {
  color: var(--color-ink);
  text-decoration-color: var(--color-rule-soft);
}

.shop-bar-value a:hover {
  color: var(--color-signal);
  text-decoration-color: currentColor;
}

@media (min-width: 48rem) {
  .shop-bar .container {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-2xl);
    padding-block: var(--space-xl);
  }
}

/* ---- Panels (replaces cards) ---- */
/* Flat, ruled, indexed. No radius, no hover-lift, no shadow. */

.panel-grid {
  display: grid;
  gap: var(--space-3xl) var(--space-2xl);
}

.panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  text-decoration: none;
  color: inherit;
}

.section--ink .panel p {
  color: var(--color-faint-on-dark);
}

.panel-index {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  color: var(--color-signal);
}

.panel h3 {
  margin: 0;
}

.panel p {
  color: var(--color-ink-soft);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  flex-grow: 1;
}

.panel-link {
  display: inline-block;
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  color: var(--color-brand);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}

a.panel:hover h3 {
  color: var(--color-brand);
}

a.panel:hover .panel-link {
  color: var(--color-signal);
}

/* ---- Split (text + list or figure) ---- */

.split {
  display: grid;
  gap: var(--space-3xl);
  align-items: start;
}

.split-figure img {
  width: 100%;
  height: auto;
}

/* ---- Checklist (square ballot checks, signal red) ---- */

.checklist li {
  position: relative;
  padding-inline-start: 2.1rem;
  margin-block-end: var(--space-md);
  color: var(--color-ink-soft);
  line-height: var(--leading-relaxed);
}

.checklist li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.2em;
  width: 1.1rem;
  height: 1.1rem;
  border: var(--rule) solid var(--color-ink);
  background: no-repeat center / 78%
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23AA3D1D' stroke-width='2.6' stroke-linecap='square'%3E%3Cpath d='M3 9l3.4 3.2L13.5 3.5'/%3E%3C/svg%3E");
}

.section--ink .checklist li {
  color: var(--color-faint-on-dark);
}

/* On the olive surface the rust tick has too little contrast to be seen, so
   the check switches to bone along with the box. */
.section--ink .checklist li::before {
  border-color: var(--color-paper-on-dark);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23F4EFE6' stroke-width='2.6' stroke-linecap='square'%3E%3Cpath d='M3 9l3.4 3.2L13.5 3.5'/%3E%3C/svg%3E");
}

.checklist strong {
  color: var(--color-ink);
}

.section--ink .checklist strong {
  color: var(--color-paper-on-dark);
}

/* ---- Testimonials (newsprint pull quotes, not cards) ---- */

/*
 * The old arrangement was a 2-column grid with the lead quote spanning both
 * columns, but capped at 46ch of type. On a 72rem measure that left the whole
 * right-hand half of the section empty and made the strongest review look like
 * an afterthought. This is an asymmetric wall instead: the lead runs down a
 * wide left column at display size, the two supporting reviews stack beside
 * it. The section fills its measure and the three quotes are no longer three
 * equal cards in a row.
 */

.testimonial-list {
  display: grid;
  gap: var(--space-2xl);
}

.testimonial {
  max-width: 42ch;
}

.testimonial-text {
  font-size: var(--text-base);
  color: var(--color-ink);
  line-height: var(--leading-snug);
  margin-block-end: var(--space-md);
}

/* Attribution: name in the label register on its own line. The old markup ran
   "— Shane B., Google review" with an em-dash, which is banned outright in
   this build (see the note in the homepage source). Setting the name as a
   label does the separating that the dash was there to do. */
.testimonial-author {
  display: block;
  font-family: var(--font-body);
  font-style: normal;
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-label);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink-faint);
}

@media (min-width: 56rem) {
  .testimonial-list {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    gap: var(--space-2xl) var(--space-4xl);
    align-items: start;
  }

  .testimonial--lead {
    grid-column: 1;
    grid-row: 1 / span 2;
    max-width: none;
    align-self: stretch;
  }

  /* Large, but still Archivo. Alfa Slab is a sign face: a full sentence set in
     it turns into a wall of heavy Egyptian serifs that nobody reads. The slab
     stays on the headline above and the quote gets scale instead of weight. */
  .testimonial--lead .testimonial-text {
    font-size: clamp(1.375rem, 2.05vw, 1.7rem);
    font-weight: var(--weight-medium);
    line-height: 1.32;
    /* Sized so this review sets in four lines and fills its column. The
       quote is trimmed to the reviewer's first full sentence, verbatim; the
       complete text stays in the JSON-LD. Re-check both numbers if the
       quote is ever swapped. */
    max-width: 34ch;
  }

  /* A short rust rule marks the pull quote, the same device as the painted
     underline in the hero. This is one of the few places a rule earns its
     keep: it says "this is the quote that matters" without a card, a border
     box or a glyph. */
  .testimonial--lead .testimonial-text::before {
    content: '';
    display: block;
    width: 3.5rem;
    margin-block-end: var(--space-lg);
    border-block-start: var(--rule-heavy) solid var(--color-signal);
  }
}

/* ---- Contact Strip (replaces the dark CTA banner) ---- */
/* Left-aligned letterhead on brand blue: message, phone as text, one button. */

.cta-banner {
  background: var(--color-brand);
  color: var(--color-paper-on-dark);
  padding-block: var(--space-4xl);
}

.cta-banner .container {
  display: grid;
  gap: var(--space-xl);
  align-items: center;
}

.cta-banner h2 {
  color: var(--color-paper-on-dark);
  margin-block-end: var(--space-sm);
}

.cta-banner p {
  color: var(--color-faint-on-dark);
  max-width: 40ch;
  margin-block-end: 0;
}

.cta-banner-contact {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
}

.cta-banner-phone {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-3xl);
  letter-spacing: var(--tracking-display);
  color: var(--color-paper-on-dark);
  text-decoration: none;
  line-height: 1;
}

.cta-banner-phone:hover {
  color: var(--color-paper-on-dark);
  text-decoration: underline;
  text-decoration-thickness: 3px;
}

.cta-banner-meta {
  font-size: var(--text-sm);
  color: var(--color-faint-on-dark) !important;
}

/* ---- Process Steps (ledger rows) ---- */

.steps {
  counter-reset: step;
}

.step {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: var(--space-md);
  padding-block: var(--space-xl);
  counter-increment: step;
}

.step::before {
  content: counter(step, decimal-leading-zero);
  grid-row: 1 / span 2;
  font-family: var(--font-display);
  font-weight: var(--weight-display-heavy);
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--color-signal);
}

.step h3,
.step p {
  grid-column: 2;
}

.step h3 {
  margin-block-end: var(--space-xs);
}

.step p {
  color: var(--color-ink-soft);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
}

/* .step p and .section--ink p have equal specificity, and components.css wins
   on source order — so the dark-surface case has to be stated here. The rust
   step number is only 1.5:1 on olive, so it goes bone there too. */
.section--ink .step p {
  color: var(--color-faint-on-dark);
}

.section--ink .step::before {
  color: var(--color-paper-on-dark);
}

/* ---- Forms ---- */

.form-group {
  margin-block-end: var(--space-lg);
}

.form-label {
  display: block;
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  color: var(--color-ink);
  margin-block-end: var(--space-xs);
}

.required {
  color: var(--color-signal);
}

.form-input,
.form-textarea,
.form-select {
  width: 100%;
  padding: 0.65rem 0.85rem;
  font-size: var(--text-base);
  color: var(--color-ink);
  background: var(--color-paper);
  border: var(--rule) solid var(--color-ink);
  border-radius: 0;
  transition: box-shadow var(--transition-fast);
}

.form-input:focus,
.form-textarea:focus,
.form-select:focus {
  outline: none;
  box-shadow: var(--focus-ring);
}

.form-input.is-error,
.form-textarea.is-error {
  border-color: var(--color-error);
  background: var(--color-error-light);
}

.form-error {
  display: none;
  margin-block-start: var(--space-xs);
  font-size: var(--text-sm);
  color: var(--color-error);
}

.form-error.is-visible {
  display: block;
}

fieldset {
  border: none;
  padding: 0;
}

.checkbox-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: var(--text-sm);
  color: var(--color-ink-soft);
  cursor: pointer;
}

.checkbox-label input {
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--color-brand);
}

/* ---- Contact Info ---- */

.contact-info-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-lg);
  padding-block: var(--space-lg);
  line-height: var(--leading-relaxed);
}

.contact-info-item:first-child {
  border-block-start: var(--rule-heavy) solid var(--color-rule);
}

.contact-info-icon {
  flex-shrink: 0;
  color: var(--color-signal);
  margin-block-start: 0.2em;
}

.contact-info-icon svg {
  width: 1.25rem;
  height: 1.25rem;
}

.map-embed iframe {
  width: 100%;
  height: 340px;
  border: none;
}

/* ---- FAQ (ruled register) ---- */

/* The one place a hairline earns its keep: an accordion needs row edges. */
.faq-item + .faq-item {
  border-block-start: var(--rule-hairline) solid var(--color-rule-faint);
}

.faq-item h2 {
  font-size: inherit;
  letter-spacing: normal;
  text-transform: none;
}

.faq-question {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  width: 100%;
  padding: var(--space-xl) 0;
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  text-align: left;
  color: var(--color-ink);
  background: none;
  border: none;
  cursor: pointer;
}

.faq-question:hover {
  color: var(--color-brand);
}

.faq-question:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-offset);
}

.faq-icon {
  flex-shrink: 0;
  align-self: center;
  color: var(--color-signal);
  transition: transform var(--transition-fast);
}

.faq-question[aria-expanded="true"] .faq-icon {
  transform: rotate(45deg);
}

.faq-answer {
  padding-block-end: var(--space-xl);
  color: var(--color-ink-soft);
  line-height: var(--leading-relaxed);
  max-width: 60ch;
}

html.js .faq-answer[aria-hidden="true"] {
  display: none;
}

/* ---- Blog: entries + article ---- */

.post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-sm);
  font-size: var(--text-sm);
  color: var(--color-ink-faint);
}

.post-tag {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-signal);
}

.post-meta-sep {
  color: var(--color-rule-soft);
}

/* Article prose */
.article {
  padding-block: var(--space-3xl);
}

.article-header {
  max-width: var(--container-narrow);
  margin-inline: auto;
  margin-block-end: var(--space-2xl);
  padding-block-end: var(--space-lg);
  border-block-end: var(--rule) solid var(--color-rule);
}

.article-header h1 {
  font-size: var(--text-4xl);
  margin-block: var(--space-md);
}

.article-lede {
  font-size: var(--text-lg);
  color: var(--color-ink-soft);
}

.prose {
  max-width: var(--container-narrow);
  margin-inline: auto;
}

.prose h2 {
  font-size: var(--text-2xl);
  margin-block: var(--space-2xl) var(--space-md);
}

.prose h3 {
  margin-block: var(--space-xl) var(--space-sm);
}

.prose p,
.prose li {
  color: var(--color-ink-soft);
  line-height: var(--leading-relaxed);
}

.prose ul,
.prose ol {
  margin-block-end: var(--space-md);
  padding-inline-start: 1.25rem;
}

.prose ul { list-style: square; }
.prose ol { list-style: decimal; }

.prose li {
  margin-block-end: var(--space-sm);
}

.prose li::marker {
  color: var(--color-signal);
}

.prose blockquote {
  margin-block: var(--space-xl);
  padding-inline-start: var(--space-lg);
  border-inline-start: var(--rule) solid var(--color-signal);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  color: var(--color-ink);
}

.prose img {
  margin-block: var(--space-xl);
}

.prose hr {
  border: none;
  border-block-start: var(--rule-hairline) solid var(--color-rule-faint);
  margin-block: var(--space-2xl);
}

/* ---- News (dated register, no detail pages) ---- */

.news-list {
  border-block-start: var(--rule-heavy) solid var(--color-rule);
}

.news-item {
  display: grid;
  gap: var(--space-xs);
  padding-block: var(--space-xl);
  border-block-end: var(--rule-hairline) solid var(--color-rule-soft);
}

.news-date {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-signal);
  white-space: nowrap;
}

.news-item h3 {
  margin: 0;
}

.news-item p {
  color: var(--color-ink-soft);
  line-height: var(--leading-relaxed);
  max-width: 60ch;
}

/* ---- Events ---- */

.event-card {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-lg);
  padding: var(--space-lg);
  border: var(--rule) solid var(--color-rule);
  background: var(--color-paper);
}

/* Tear-off calendar plate — hard corners, ink header */
.event-date {
  display: flex;
  flex-direction: column;
  width: 4.25rem;
  border: var(--rule) solid var(--color-rule);
  text-align: center;
}

.event-date-month {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  background: var(--color-signal);
  color: var(--color-paper-on-dark);
  padding-block: 2px;
}

.event-date-day {
  font-family: var(--font-display);
  font-weight: var(--weight-display-heavy);
  font-size: var(--text-3xl);
  color: var(--color-ink);
  line-height: 1.1;
  padding-block: var(--space-xs);
}

.event-body h3 {
  margin-block-end: var(--space-xs);
}

.event-meta {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-ink-faint);
  margin-block-end: var(--space-sm);
}

.event-body p {
  color: var(--color-ink-soft);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

/* ---- Photo Grid ---- */

.photo-grid {
  display: grid;
  gap: var(--space-lg);
}

.photo-grid figure {
  margin: 0;
}

.photo-grid img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: var(--rule) solid var(--color-rule);
}

.photo-grid figcaption {
  margin-block-start: var(--space-xs);
  padding-block-start: var(--space-xs);
  border-block-start: var(--rule-hairline) solid var(--color-rule-soft);
  font-size: var(--text-sm);
  color: var(--color-ink-faint);
}

/* Line-art placeholder frames (until real photos are supplied) */
.photo-placeholder {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 4 / 3;
  border: var(--rule) solid var(--color-rule);
  background:
    linear-gradient(to top right, transparent calc(50% - 1px), var(--color-rule-soft) 50%, transparent calc(50% + 1px)),
    linear-gradient(to bottom right, transparent calc(50% - 1px), var(--color-rule-soft) 50%, transparent calc(50% + 1px)),
    var(--color-paper-shade);
  color: var(--color-ink-faint);
}

.photo-placeholder svg {
  width: 2.5rem;
  height: 2.5rem;
  background: var(--color-paper-shade);
}

/* ---- Two Column Helper ---- */

.two-col {
  display: grid;
  gap: var(--space-2xl);
}

/* ---- Thank You ---- */

.thank-you {
  max-width: var(--container-narrow);
  margin-inline: auto;
  padding-block: var(--space-4xl);
  text-align: center;
}

.thank-you-icon {
  width: 3.5rem;
  height: 3.5rem;
  margin-inline: auto;
  margin-block-end: var(--space-lg);
  color: var(--color-success);
}

.thank-you h1 {
  font-size: var(--text-4xl);
  margin-block-end: var(--space-md);
}

/* ---- 404 ---- */

.not-found {
  max-width: var(--container-narrow);
  margin-inline: auto;
  padding-block: var(--space-4xl);
  text-align: center;
}

.not-found-code {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-signal);
  margin-block-end: var(--space-md);
}

.not-found h1 {
  font-size: var(--text-4xl);
}

/* ---- Desktop ---- */

@media (min-width: 48rem) {
  .hero-grid {
    grid-template-columns: 7fr 4fr;
    gap: var(--space-3xl);
  }

  .panel-grid--2 { grid-template-columns: repeat(2, 1fr); }
  .panel-grid--3 { grid-template-columns: repeat(3, 1fr); }

  .split {
    grid-template-columns: 1fr 1fr;
  }

  .split--wide-left {
    grid-template-columns: 3fr 2fr;
  }

  .cta-banner .container {
    grid-template-columns: 1fr auto;
  }

  .news-item {
    grid-template-columns: 9rem 1fr;
    align-items: baseline;
  }

  .news-item h3 { grid-column: 2; }
  .news-item p { grid-column: 2; }
  .news-date { grid-row: 1; }

  .photo-grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .two-col--wide-left {
    grid-template-columns: 3fr 2fr;
  }
}


/* ---- Price Board (signature component for this shop) ---- */
/* The list of services and prices as a barber actually posts it: name on the
   left, leader dots, price on the right, set in the sign face. Replaces the
   template's three-up service cards on the homepage. */

/*
 * The old board ran one row across the full 72rem measure: the service name at
 * the far left, the price at the far right, and roughly 700px of nothing in
 * between, with the description tucked under the name. Nothing connected
 * "Haircut" to "$40+" except a shared baseline a third of a metre away, and
 * the leader dots that were supposed to do that job had been set to
 * display:none. Two things fix it: shorter rows (a real two-column board), and
 * putting the leader back now that the run between name and price is short
 * enough for it to read as a board rather than as one more horizontal rule.
 */

.price-board {
  display: grid;
  gap: var(--space-xl) var(--space-3xl);
}

.price-row {
  display: block;
  padding-block: var(--space-md);
  border-block-start: var(--rule-hairline) solid var(--color-rule-faint);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--transition-fast);
}

/* Name, leader, price: one baseline, short run. */
.price-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
}

.price-name {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--display-sub);
  text-transform: uppercase;
  letter-spacing: var(--tracking-display);
  line-height: 1.15;
  color: var(--color-ink);
  transition: color var(--transition-fast);
}

/* The leader that actually carries the eye from the name to the price. Sits on
   the baseline, grows to fill whatever run is left. */
.price-dots {
  display: block;
  flex: 1 1 auto;
  min-width: var(--space-lg);
  height: 0;
  transform: translateY(-0.28em);
  border-block-end: 2px dotted var(--color-rule-soft);
}

.price-amount {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--display-sub);
  letter-spacing: var(--tracking-display);
  color: var(--color-signal);
  white-space: nowrap;
}

.price-note {
  max-width: 42ch;
  margin-block-start: var(--space-sm);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-ink-soft);
}

/* The conditioning treatment is an add-on to another service rather than
   something you book on its own, so it runs the full width of the board under
   the four bookable services. That is a content distinction first; it also
   means five items never leave an empty cell in a two-column grid. */
.price-row--addon {
  grid-column: 1 / -1;
}

.price-row--addon .price-note {
  max-width: 64ch;
}

/* Flat hover, per the art direction: the ground and the ink change, nothing
   lifts and nothing casts a shadow. */
a.price-row:hover {
  border-block-start-color: var(--color-signal);
}

a.price-row:hover .price-name,
a.price-row:focus-visible .price-name {
  color: var(--color-signal);
}

a.price-row:hover .price-dots {
  border-block-end-color: var(--color-signal);
}

a.price-row:hover .price-note {
  color: var(--color-ink);
}

a.price-row:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.price-board-foot {
  margin-block-start: var(--space-2xl);
  font-size: var(--text-sm);
  color: var(--color-ink-faint);
}

/* ---- Work Mosaic (the cuts) ---- */
/*
 * Nine photographs. The old layout put them in a 3x3 grid of identical 3:4
 * cells, which gives every cut exactly the same weight and reads as a contact
 * sheet, not as a wall of work. This is a real mosaic: one large square lead,
 * four tall portraits and four small squares, tiled so that every cell in the
 * grid is filled. Cell shapes are square or portrait only, never landscape,
 * because every source photograph is a portrait and a landscape crop would cut
 * the head off.
 *
 * Desktop is 4 columns x 4 rows = 16 units, spent exactly:
 *   lead 2x2 (4) + four tall 1x2 (8) + four small 1x1 (4) = 16
 * Mobile is 2 columns: the lead stays 2x2, everything else drops to 1x1,
 * which tiles 2 cols x 6 rows exactly.
 */

.work-mosaic {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: clamp(7rem, 31vw, 12rem);
  gap: var(--space-sm);
}

/* The grid children are anchors now (each photograph opens the viewer), so the
   anchor is the grid item and the image fills it. Grid items stretch to their
   row by default, which is what gives the image a definite height to fill. */
.work-mosaic > .gallery-item {
  height: 100%;
}

.work-mosaic img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--color-paper-shade);
}

/* Mobile: the lead cut is the only one given extra weight. */
.work-mosaic .work-lead {
  grid-column: span 2;
  grid-row: span 2;
}

@media (min-width: 48rem) {
  .work-mosaic {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-rows: clamp(9rem, 16.5vw, 15.5rem);
    gap: var(--space-md);
  }

  .work-mosaic .work-lead  { grid-column: 1 / 3; grid-row: 1 / 3; }
  .work-mosaic .work-tall  { grid-row: span 2; }
}

/* ---- Badge Figure ---- */
/* The shop's own flash badge, used at size where it can be read. */

.badge-figure {
  margin: 0;
  text-align: center;
}

.badge-figure img {
  width: 100%;
  max-width: 20rem;
  height: auto;
}

/* ---- Booking Block ---- */
/* Two ways in, given equal weight, because this shop takes both. */

.booking-block {
  display: grid;
  gap: var(--space-2xl);
  padding: var(--space-2xl);
  background: var(--color-paper-shade);
}

/* Each option is a column so the two buttons sit on the same line even when
   the two descriptions run to different lengths. */
.booking-option {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.booking-option h3 {
  margin-block-end: var(--space-xs);
  color: var(--color-signal);
}

.booking-option .btn {
  margin-block-start: auto;
}

.booking-option p {
  font-size: var(--text-base);
  color: var(--color-ink-soft);
  margin-block-end: var(--space-md);
}

/* The label carries a phone number — never let it break across lines. */
.booking-option .btn {
  white-space: nowrap;
}

/* ---- Testimonial attribution to a real source ---- */

.review-source {
  margin-block-start: var(--space-2xl);
  font-size: var(--text-sm);
  color: var(--color-ink-faint);
}

@media (min-width: 56rem) {
  /* Text column wide enough that the widest word in the headline
     (TRANSFORMATION) never sets a min-content floor that starves the photo. */
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
    gap: var(--space-3xl);
    align-items: stretch;
  }

  .hero-content {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: var(--space-2xl);
  }

  /* Fill the height of the band and run off the right of the screen. */
  .hero .hero-figure {
    margin-inline: 0 calc(-1 * var(--hero-bleed));
    margin-block: calc(-1 * var(--space-2xl)) calc(-1 * var(--space-3xl));
  }

  .hero .hero-figure img {
    aspect-ratio: auto;
    min-height: 30rem;
  }

  /* Two columns halve the run between a service name and its price. */
  .price-board {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .booking-block {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3xl);
    padding: var(--space-3xl);
  }
}

/* Preview-only: the contact form has no endpoint until the client signs up, so
   it carries an explanation where the submit button goes. Delete this rule and
   restore the button when SwiftForms is wired up. */
.form-preview-note {
  max-width: 52ch;
  margin-block-end: var(--space-lg);
  padding-inline-start: var(--space-md);
  border-inline-start: var(--rule) solid var(--color-signal);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-ink-soft);
}

/* ---- Gallery grid + photo viewer (the /gallery page) ---- */
/*
 * Nine portraits, tiled 3x3 on desktop so the set closes exactly. The homepage
 * uses .work-mosaic for editorial rhythm; here the job is different, so an even
 * grid is right: this page exists to let someone scan every cut and open the
 * one they want to show Arika. Uniformity is the feature, and tapping is the
 * interaction.
 */

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-sm);
  list-style: none;
  margin: 0;
  padding: 0;
}

.gallery-item {
  display: block;
  position: relative;
  text-decoration: none;
  background: var(--color-paper-shade);
  cursor: zoom-in;
}

.gallery-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity var(--transition-fast);
}

/* Uniform 3:4 portrait cells belong to the gallery page's grid only. The
   homepage mosaic sets its own cell shapes and must not inherit this. */
.gallery-grid .gallery-item img {
  aspect-ratio: 3 / 4;
}

/* Flat affordance, per the art direction: a rust rule drawn INSIDE the frame,
   so nothing lifts, nothing shadows and nothing shifts the layout. */
.gallery-item::after {
  content: '';
  position: absolute;
  inset: 0;
  border: var(--rule-heavy) solid transparent;
  transition: border-color var(--transition-fast);
  pointer-events: none;
}

.gallery-item:hover img,
.gallery-item:focus-visible img {
  opacity: 0.88;
}

.gallery-item:hover::after,
.gallery-item:focus-visible::after {
  border-color: var(--color-signal);
}

.gallery-item:focus-visible {
  outline: none;
}

@media (min-width: 48rem) {
  .gallery-grid {
    /* 9 photographs, 3 columns, 3 full rows. Change the count and re-check. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-md);
  }
}

/* ---- The viewer ---- */

.lightbox {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-paper-on-dark);
  overflow: hidden;
}

.lightbox::backdrop {
  /* Ink, not black: the same green-cast near-black used for type. At 0.94 the
     page headline and the rust nav button still read through clearly enough to
     compete with the photograph, which is the one thing this view is for. */
  background: rgba(24, 28, 22, 0.975);
}

.lightbox-frame {
  display: grid;
  gap: var(--space-md);
  place-content: center;
  justify-items: center;
  width: 100%;
  height: 100%;
  padding: var(--space-4xl) var(--space-md) var(--space-3xl);
}

.lightbox-image {
  display: block;
  max-width: min(92vw, 46rem);
  /* Leaves room for the caption and the close button at any viewport height.
     These photographs are portrait and 1013px tall at source, so on a landscape
     screen they are always height-bound; there is no point going wider. */
  max-height: 78vh;
  width: auto;
  height: auto;
  object-fit: contain;
  background: var(--color-brand-dark);
}

.lightbox-caption {
  display: grid;
  gap: var(--space-2xs);
  max-width: 46rem;
  margin: 0;
  text-align: center;
}

.lightbox-count {
  font-family: var(--font-body);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-label);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-signal-on-ink);
}

.lightbox-alt {
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--color-faint-on-dark);
}

.lightbox-btn {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-paper-on-dark);
  background: transparent;
  border: var(--rule) solid var(--color-paper-on-dark);
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.lightbox-btn:hover {
  background: var(--color-paper-on-dark);
  color: var(--color-ink);
}

.lightbox-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--color-signal-bright);
}

.lightbox-close {
  top: var(--space-md);
  right: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  font-size: var(--text-xs);
}

/* Big tap targets. 44px is the minimum comfortable touch size. */
.lightbox-prev,
.lightbox-next {
  top: 50%;
  transform: translateY(-50%);
  width: 2.75rem;
  height: 3.5rem;
  padding: 0;
  /* The guillemets are optically high in most faces; nudge them onto centre. */
  font-size: var(--text-2xl);
  line-height: 1;
}

.lightbox-prev { left: var(--space-md); }
.lightbox-next { right: var(--space-md); }

/* A single photograph needs no stepper. */
.lightbox[data-single="true"] .lightbox-prev,
.lightbox[data-single="true"] .lightbox-next {
  display: none;
}

@media (min-width: 48rem) {
  .lightbox-prev { left: var(--space-2xl); }
  .lightbox-next { right: var(--space-2xl); }
  .lightbox-close {
    top: var(--space-xl);
    right: var(--space-xl);
  }
}

/*
 * Small screens: there is no room beside a photograph that is already 92vw
 * wide, so side-positioned arrows sit on top of the picture and fight it. Below
 * 48rem they become a stepper under the caption instead, and the frame reserves
 * a band for them. Each is 4rem wide with a 1rem gap, centred as a pair.
 */
@media (max-width: 47.99rem) {
  .lightbox-frame {
    padding-block: var(--space-3xl) 6rem;
  }

  .lightbox-image {
    /* Leaves room for the caption and the stepper band below it. */
    max-height: 56vh;
  }

  .lightbox-prev,
  .lightbox-next {
    top: auto;
    bottom: var(--space-xl);
    transform: none;
    width: 4rem;
    height: 2.75rem;
  }

  .lightbox-prev { left: calc(50% - 4.5rem); }
  .lightbox-next { right: calc(50% - 4.5rem); }
}
