/* Stanquette — streamline moderne, restrained Americana.
   Full-bleed colour bands, hairline-separated rows, sharp corners.
   No cards, no rounded anything, no ornament.

   This file is site composition only. Tokens, reset/typography and the
   interactive components live in design/ and load ahead of it. */

/* --- Bands ---------------------------------------------------------------
   Every top-level section is a full-bleed band with a centred measure. */

.band {
  padding: var(--band-pad) var(--gutter);

  & > * {
    max-width: var(--measure-wide);
    margin-inline: auto;
  }

  &.band--ink {
    background: var(--ink);
    color: var(--cream);
  }

  &.band--dune {
    background: var(--sand-deep);
  }

  &.band--orange {
    background: var(--orange);
    color: var(--cream);
  }
}

.section-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-section);
  font-weight: var(--weight-regular);
  line-height: var(--leading-hero);
  letter-spacing: var(--track-display);
  text-wrap: balance;
}

.section-lede {
  margin: 0.75rem 0 0;
  max-width: var(--measure-lede);
  color: var(--ink-soft);

  .band--ink & {
    color: var(--ink-soft-on-ink);
  }
}

.section-head {
  display: grid;
  gap: 0.875rem;
  margin-bottom: clamp(1.75rem, 3vw, 2.75rem);

  @media (width >= 56rem) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 4rem;
    align-items: end;

    & .section-lede {
      margin: 0;
      justify-self: end;
    }
  }
}

/* --- Masthead ------------------------------------------------------------ */

.site-masthead {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 1rem var(--gutter);
  background: var(--ink);
  color: var(--cream);

  & .wordmark {
    width: 6.875rem;

    @media (width >= 48rem) {
      width: 10.625rem;
    }
  }
}

.masthead-nav {
  display: flex;
  gap: clamp(1.25rem, 4vw, 2rem);
  align-items: center;

  & a {
    color: var(--cream);
    font-family: var(--font-body);
    font-size: var(--step-small);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: 0.1rem;
    transition: color var(--tempo) var(--ease),
      border-color var(--tempo) var(--ease);

    &:hover,
    &:focus-visible {
      color: var(--orange-tint);
      border-bottom-color: var(--orange-tint);
    }

    &[aria-current="page"] {
      border-bottom-color: var(--orange);
    }
  }
}

/* The home page opens on the hero wordmark at full size, so the masthead drops
   its slab and its miniature copy of the mark and leaves only the nav. */
.site-masthead--bare {
  background: none;
  color: var(--ink);
  justify-content: flex-end;

  & > a:has(> .wordmark) {
    display: none;
  }

  & .masthead-nav a {
    color: var(--ink);

    &:hover,
    &:focus-visible {
      color: var(--orange);
      border-bottom-color: var(--orange);
    }
  }
}

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

.hero {
  display: grid;
  justify-items: center;
  gap: 1.375rem;
  padding: clamp(2.5rem, 7vw, 4.75rem) var(--gutter) clamp(2.5rem, 6vw, 4rem);
  text-align: center;

  & .wordmark {
    width: min(100%, 56.25rem);
    color: var(--ink);
  }
}

.hero-tagline {
  margin: 0;
  max-width: 40rem;
  font-size: var(--step-name);
  color: var(--ink-soft);
}

.hero-actions,
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
  justify-content: center;
  margin-top: 0.625rem;
}

/* --- Rule lists ----------------------------------------------------------
   The one repeating structure on the site: a heavy rule opens the list,
   hairlines separate the rows. Used for values, packages, work, invoices. */

.rule-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--rule-heavy) solid var(--ink);

  .band--ink & {
    border-top-color: var(--cream);
  }
}

.rule-list-item {
  display: grid;
  gap: 0.375rem;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--rule-hair);

  .band--ink & {
    border-bottom-color: var(--rule-hair-on-ink);
  }

  @media (width >= 56rem) {
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    gap: 2.5rem;
    align-items: baseline;
  }
}

.item-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-title);
  font-weight: var(--weight-regular);
  line-height: var(--leading-title);
  color: inherit;
}

.item-body {
  margin: 0;
  color: var(--ink-soft);

  .band--ink & {
    color: var(--ink-soft-on-ink);
  }

  .band--dune & {
    color: var(--ink-soft-on-dune);
  }
}

/* Rows that are entirely a link (goodies, packages). The link carries the
   columns here, so the row must not also be a grid — otherwise the link is
   confined to the row's first track and its own columns collapse inside it. */
.rule-list-item:has(> .item-link) {
  display: block;
  padding: 0;

  & .item-link {
    display: grid;
    gap: 0.375rem;
    padding: 1.25rem 0;
    color: inherit;
    text-decoration: none;

    /* Most of these lists mix linked rows with unlinked ones, so a row cannot
       rely on hover to admit it is a link. The name carries the same hairline
       underline prose links do. */
    & .item-name {
      text-decoration: underline;
      text-decoration-thickness: 1px;
      text-underline-offset: 3px;
      text-decoration-color: color-mix(in oklab, currentColor 35%, transparent);
    }
    transition: background-color var(--tempo) var(--ease),
      padding-inline var(--tempo) var(--ease);

    @media (width >= 56rem) {
      grid-template-columns: minmax(0, 22rem) minmax(0, 1fr) auto;
      gap: 2.5rem;
      align-items: baseline;
    }

    /* Narrow rows stack, and a lone arrow on its own line reads as debris —
       the whole row is the tap target there anyway. */
    & .item-arrow {
      display: none;
      color: var(--orange-deep);
      font-size: 1.25rem;
      line-height: 1;
      transition: transform var(--tempo-slow) var(--ease);

      @media (width >= 56rem) {
        display: block;
      }
    }

    /* A row that leads somewhere names its destination. It takes the column the
       bare arrow would take, and unlike the arrow it stays put on narrow
       screens — that is where the affordance is needed most. */
    & .item-cue {
      display: flex;
      gap: 0.4em;
      align-items: baseline;
      font-family: var(--font-label);
      font-size: var(--step-label);
      font-weight: var(--weight-semibold);
      letter-spacing: var(--track-caps);
      text-transform: uppercase;
      color: var(--orange-deep);
      white-space: nowrap;

      & span {
        transition: transform var(--tempo-slow) var(--ease);
      }
    }

    &:hover,
    &:focus-visible {
      & .item-name {
        color: var(--orange-deep);
        text-decoration-thickness: 2px;
        text-decoration-color: currentColor;
      }

      & .item-arrow,
      & .item-cue span {
        transform: translateX(0.25rem);
      }
    }
  }
}

/* Larger name for the open-source list */
.rule-list--goodies .item-name {
  font-size: var(--step-name);
}

/* --- CTA band ------------------------------------------------------------ */

.cta-band {
  display: grid;
  justify-items: center;
  gap: 1.125rem;
  text-align: center;

  & .cta-title {
    margin: 0;
    max-width: 22ch;
    font-family: var(--font-display);
    font-size: var(--step-display);
    font-weight: var(--weight-regular);
    line-height: var(--leading-display);
    text-wrap: balance;
  }

  & .cta-lede {
    margin: 0;
    max-width: 44ch;
    font-size: var(--step-lede);
    color: color-mix(in srgb, var(--cream) 90%, transparent);
  }
}

/* --- Footer -------------------------------------------------------------- */

.site-footer {
  padding: clamp(2.5rem, 5vw, 4rem) var(--gutter) 2.75rem;
  background: var(--ink);
  color: var(--cream);

  & > * {
    max-width: var(--measure-wide);
    margin-inline: auto;
  }
}

.footer-top {
  display: grid;
  gap: 2rem;

  @media (width >= 48rem) {
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 5rem;
    justify-content: space-between;
  }
}

.footer-brand {
  display: grid;
  gap: 0.875rem;
  justify-items: start;

  & .wordmark {
    width: 13.75rem;
  }

  & p {
    margin: 0;
    max-width: 24rem;
    color: var(--ink-soft-on-ink);
  }
}

.footer-nav {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;

  & .footer-nav-title {
    font-family: var(--font-label);
    font-size: var(--step-label);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--track-eyebrow);
    color: var(--orange-tint);
    margin-bottom: 0.125rem;
  }

  & a {
    color: var(--cream);
    font-size: var(--step-small);
    text-decoration: none;
    border-bottom: 1px solid transparent;

    &:hover,
    &:focus-visible {
      color: var(--orange-tint);
      border-bottom-color: var(--orange-tint);
    }
  }
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  margin-top: clamp(2rem, 4vw, 3.5rem);
  padding-top: 1.375rem;
  border-top: 1px solid var(--rule-hair-on-ink);
  font-family: var(--font-label);
  font-size: var(--step-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-legal);
  color: var(--text-muted-on-ink);

  & a {
    color: inherit;
    text-decoration: none;

    &:hover,
    &:focus-visible {
      color: var(--orange-tint);
    }
  }
}

/* --- Article pages (hire) ------------------------------------------------ */

.page-head {
  padding: clamp(2rem, 5vw, 3.5rem) var(--gutter) clamp(2rem, 4vw, 3rem);

  & > * {
    max-width: var(--measure-wide);
    margin-inline: auto;
  }
}

.page-head-inner {
  display: grid;
  gap: 2rem;
  padding-top: clamp(1.75rem, 3vw, 2.75rem);
  border-top: var(--rule-heavy) solid var(--ink);

  @media (width >= 56rem) {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: 4rem;
  }
}

/* Case studies lead with a title and a lede and nothing else, so the head is
   one column. The heavy rule still spans the wide measure — the text under it
   sits at prose measure, flush left with the body below. */
.page-head-solo {
  padding-top: clamp(1.75rem, 3vw, 2.75rem);
  border-top: var(--rule-heavy) solid var(--ink);

  & > * {
    max-width: var(--measure-prose);
  }
}

.page-title {
  margin: 0 0 0.875rem;
  font-family: var(--font-display);
  font-size: var(--step-display);
  font-weight: var(--weight-regular);
  line-height: var(--leading-hero);
  text-wrap: balance;
}

.page-lede {
  margin: 0;
  font-size: var(--step-lede);
  color: var(--ink-soft);
}

/* Key/value strip: role, location, stack, availability */
.page-meta {
  margin: 0;
  display: grid;

  & > div {
    display: grid;
    gap: 0.125rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--rule-hair);

    &:first-child {
      padding-top: 0;
    }
  }

  & dt {
    font-family: var(--font-label);
    font-size: var(--step-label);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--track-eyebrow);
    color: var(--orange-deep);
  }

  & dd {
    margin: 0;
    font-size: var(--step-small);
  }
}

.article-body {
  padding: 0 var(--gutter) clamp(3rem, 6vw, 4.5rem);

  & > * {
    max-width: var(--measure-wide);
    margin-inline: auto;
  }
}

.article-layout {
  display: grid;
  gap: 2.5rem;

  /* A grid item defaults to min-width:auto, so anything that refuses to wrap —
     a code block, a wide table — drags the whole column wider than the screen.
     The desktop track says minmax(0, …) for the same reason; single-column
     mobile has no track to say it on, so the children say it themselves. */
  & > * {
    min-width: 0;
  }

  @media (width >= 64rem) {
    grid-template-columns: 12rem minmax(0, 1fr);
    gap: 4rem;
    align-items: start;
  }
}

.contents-rail {
  font-family: var(--font-label);
  font-size: var(--step-small);

  @media (width >= 64rem) {
    position: sticky;
    top: 2rem;
  }

  & .contents-title {
    padding-top: 0.75rem;
    border-top: var(--rule-heavy) solid var(--ink);
    font-size: var(--step-label);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--track-eyebrow);
    color: var(--ink-soft);
    margin-bottom: 0.875rem;
  }

  & ol {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 0.5rem;
  }

  & a {
    color: var(--ink);
    font-size: var(--step-fine);
    text-decoration: none;
    border-bottom: 1px solid transparent;

    &:hover,
    &:focus-visible {
      color: var(--orange-deep);
      border-bottom-color: var(--orange-deep);
    }
  }
}

/* Prose from markdown. A heavy rule above every h2 marks the section break. */
.prose {
  max-width: var(--measure-prose);

  & > :first-child {
    margin-top: 0;
  }

  & h2 {
    margin: 3rem 0 1rem;
    padding-top: 1.75rem;
    border-top: var(--rule-heavy) solid var(--ink);
    font-family: var(--font-display);
    font-size: var(--step-subsection);
    font-weight: var(--weight-regular);
    line-height: var(--leading-heading);
  }

  & > h2:first-child {
    margin-top: 0;
  }

  /* Plain markdown headings only — .item-name and friends carry their own. */
  & h3:not([class]) {
    margin: 2.25rem 0 0.5rem;
    font-family: var(--font-display);
    font-size: var(--step-title);
    font-weight: var(--weight-regular);
    color: var(--orange-deep);
  }

  & p,
  & ul,
  & ol {
    margin: 0 0 1.1em;
  }

  /* Plain markdown lists only — lists that carry a class style themselves */
  & ul:not([class]) {
    list-style: none;
    padding: 0;

    & li {
      padding-left: 1.5rem;
      margin: 0.4em 0;
      position: relative;

      &::before {
        content: "—";
        position: absolute;
        left: 0;
        color: var(--orange-deep);
      }
    }
  }

  & ol:not([class]) {
    padding-left: 1.25rem;

    & li {
      margin: 0.4em 0;

      &::marker {
        color: var(--orange-deep);
      }
    }
  }

  & strong {
    font-weight: var(--weight-semibold);
    color: var(--ink);
  }

  & a {
    color: var(--orange-deep);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;

    &:hover,
    &:focus-visible {
      color: var(--ink);
      text-decoration-thickness: 2px;
    }
  }

  & code {
    font-family: var(--font-mono);
    font-size: 0.9em;
    color: var(--orange-deep);
  }

  & blockquote {
    margin: 1.5rem 0;
    padding: 0.25rem 0 0.25rem 1.25rem;
    border-left: 3px solid var(--ink);
    color: var(--ink-soft);

    /* The quoted paragraph brought its own margins, which pushed the rule well
       past the text at both ends. The blockquote owns the space around itself;
       what sits inside it does not. */
    & > :first-child {
      margin-top: 0;
    }

    & > :last-child {
      margin-bottom: 0;
    }
  }

  /* A screenshot is evidence, not decoration: the image and a caption, nothing
     more. Case studies lean on these heavily. */
  & figure {
    margin: 2rem 0;
  }

  /* The screenshots bring their own transparency — rounded window corners and
     their shadow, the gaps between dashboard panels — so they sit straight on
     the page. A plate and a border behind them only framed what was framed. */
  & figure img {
    width: 100%;
    height: auto;
  }

  /* A dense screenshot links to itself at full size. It is the image that is
     the link, so none of the prose link decoration applies. */
  & figure a {
    display: block;
    text-decoration: none;
  }

  & figcaption {
    margin-top: 0.75rem;
    font-family: var(--font-label);
    font-size: var(--step-fine);
    line-height: var(--leading-ui);
    color: var(--ink-soft);

    & code {
      font-size: 0.95em;
    }
  }
}

/* --- Code blocks ---------------------------------------------------------
   Kramdown wraps Rouge output as
   .language-x.highlighter-rouge > .highlight > pre.highlight > code.

   Prose lines wrap at --measure-prose, but code lines do not wrap at all, so
   the slab scrolls sideways rather than forcing a reflow or a squint. */

.prose .highlighter-rouge {
  margin: 1.75rem 0;
  background: var(--code-plate);
  color: var(--code-text);
}

.prose .highlight {
  overflow-x: auto;
  padding: 1.25rem;
}

.prose pre {
  margin: 0;
}

/* The inline-code rule above paints every `code` orange; inside a slab the
   token colours below do that job instead. */
.prose pre code {
  font-family: var(--font-mono);
  font-size: var(--step-fine);
  line-height: var(--leading-control);
  color: inherit;
  white-space: pre;

  /* JetBrains Mono ligates === into a single glyph, which misreads Ruby's
     case-equality operator as an identity sign. Code shows its own bytes. */
  font-variant-ligatures: none;
}

/* Rouge tokens. Everything unlisted inherits --code-text on purpose. */
.prose .highlight {
  & .c,
  & .c1,
  & .cm,
  & .cp,
  & .cs {
    color: var(--code-comment);
    font-style: italic;
  }

  & .k,
  & .kd,
  & .kn,
  & .kp,
  & .kr,
  & .kt,
  & .o,
  & .ow {
    color: var(--code-keyword);
  }

  & .s,
  & .s1,
  & .s2,
  & .sb,
  & .sc,
  & .sd,
  & .se,
  & .sh,
  & .si,
  & .sr,
  & .ss,
  & .m,
  & .mi,
  & .mf,
  & .mh,
  & .mo {
    color: var(--code-literal);
  }

  & .no,
  & .nc,
  & .nn,
  & .vi,
  & .vg,
  & .vc {
    color: var(--code-literal);
  }

  & .nf,
  & .nb {
    color: var(--code-text);
  }

  & .gd,
  & .gi {
    color: var(--code-comment);
  }
}

/* Two-column key list inside prose (technical expertise). The columns share
   the parent's rows via subgrid, so every heading sits in one band and every
   list starts on the same line no matter how the headings wrap. */
.column-list {
  display: grid;
  gap: 2rem;
  margin: 1.5rem 0 0;

  @media (width >= 40rem) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto auto;

    & > div {
      display: grid;
      grid-row: span 2;
      grid-template-rows: subgrid;
      gap: 0.625rem;
    }
  }

  & .column-title {
    /* Bottom-aligned so a one-line heading keeps its baseline with the last
       line of a heading that wrapped. */
    align-self: end;
    margin: 0 0 0.625rem;
    font-family: var(--font-label);
    font-size: var(--step-label);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--track-eyebrow);
    color: var(--ink-soft);

    @media (width >= 40rem) {
      margin-bottom: 0;
    }
  }

  & ul {
    margin-bottom: 0;
  }
}

/* --- Kitchen sink -------------------------------------------------------- */

.kitchen-section {
  padding: clamp(2.5rem, 5vw, 3.375rem) var(--gutter) 0;

  & > * {
    max-width: var(--measure-wide);
    margin-inline: auto;
  }

  & > .section-title {
    margin-bottom: 1.125rem;
  }

  & > .kitchen-rule {
    height: var(--rule-heavy);
    background: var(--ink);
    margin-bottom: 2rem;
  }

  & > .kitchen-note {
    margin: 0 0 1.75rem;
    max-width: var(--measure-prose);
    color: var(--ink-soft);
  }
}

.kitchen-grid {
  display: grid;
  gap: 1.875rem;

  @media (width >= 48rem) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  @media (width >= 64rem) {
    grid-template-columns: repeat(var(--columns, 3), minmax(0, 1fr));
  }

  /* Specimens are a single row of columns, so they share the grid's rows: the
     captions line up even when one specimen's swatch is taller than another's. */
  @media (width >= 48rem) {
    &:has(> .specimen) {
      grid-template-rows: auto auto;
      row-gap: 0.75rem;

      & > .specimen {
        grid-row: span 2;
        grid-template-rows: subgrid;
      }
    }
  }
}

/* A labelled specimen: the thing itself, with a caption underneath */
.specimen {
  display: grid;
  gap: 0.75rem;
  align-content: start;

  & .specimen-label {
    font-family: var(--font-label);
    font-size: var(--step-label);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--track-caps);
    text-transform: uppercase;
    color: var(--ink-soft);
  }

  & .specimen-caption {
    margin: 0;
    font-size: var(--step-small);
    line-height: var(--leading-control);
    color: var(--ink-soft);
  }
}

/* Button matrix: one variant per row, one state per column */
.button-matrix {
  display: grid;
  border-top: var(--rule-heavy) solid var(--ink);

  & .button-row {
    display: grid;
    gap: 1.25rem;
    padding: 1.5rem 0;
    border-bottom: 1px solid var(--rule-hair);

    @media (width >= 64rem) {
      grid-template-columns: 9rem repeat(4, minmax(0, 1fr));
      gap: 1.5rem;
      align-items: start;
    }
  }

  & .button-row-name {
    font-family: var(--font-display);
    font-size: var(--step-title);
    font-weight: var(--weight-regular);
  }

  & .button-cell {
    display: grid;
    gap: 0.625rem;
    justify-items: start;
  }
}

/* The kitchen sink shows disabled/hover/active as static specimens, so the
   states need to be forced rather than waited for. */
.is-hover.button--primary {
  background: var(--orange-hover);
  box-shadow: var(--lift-primary-hover);
}

.is-active.button--primary {
  background: var(--orange-press);
  box-shadow: var(--lift-primary-press);
}

.is-hover.button--secondary {
  background: var(--ink-hover);
  box-shadow: var(--lift-secondary-hover);
}

.is-active.button--secondary {
  background: var(--ink-press);
  box-shadow: var(--lift-secondary-press);
}

.is-hover.button--quiet {
  background: var(--cream);
  box-shadow: var(--lift-quiet-hover);
}

.is-active.button--quiet {
  background: var(--sand-press);
  box-shadow: var(--lift-quiet-press);
}

.is-hover.button--destructive {
  background: var(--orange-wash);
  box-shadow: var(--lift-destructive-hover);
}

.is-active.button--destructive {
  background: var(--orange-wash-press);
  box-shadow: var(--lift-destructive-press);
}

/* Focus cannot be photographed, so the specimen forces it. Border colour
   only: the box keeps exactly the same size, so nothing reflows. */
.is-focus.field-control,
.is-focus.code-box {
  border-color: var(--orange);
}

.badge-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.notice-stack {
  display: grid;
  gap: 0.875rem;
}
