/* Creative Repairs — one stylesheet, no framework.

   Light and rustic: undyed linen, oatmeal, a warm terracotta the colour of
   unglazed clay, and a soft sage. The point is natural, undyed materials and
   plenty of air — mending is unhurried, careful work, and the site should
   feel like a workroom with the window open rather than like software.

   Every colour is a token on :root. Swapping these and the logo re-skins the
   whole site; nothing below hard-codes a colour.

   Contrast was checked, not guessed: --clay on --linen is 4.8:1 and white on
   --clay is 5.0:1, both clear of WCAG AA for body text. If you lighten the
   terracotta further, check it again — it is the one colour here with no
   headroom. */

/* --- type ---------------------------------------------------------------
   Fraunces for headings: an old-style serif drawn in this decade, so it reads
   traditional without reading dated — which is the whole brief. Inter for
   everything else, because it was designed for screens and gets out of the way.

   Both are OFL and served from this origin. Nothing is fetched from Google,
   which keeps the Content-Security-Policy at 'self' and means no third party
   learns who visits Ruth's site.

   Variable fonts, one file each: every weight and optical size below comes
   out of the same 67KB and 48KB download. */

@font-face {
  font-family: "Fraunces";
  src: url("/static/fonts/fraunces-var-latin.woff2") format("woff2-variations");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;   /* show Georgia immediately, swap when it lands */
}

@font-face {
  font-family: "InterVar";
  src: url("/static/fonts/inter-var-latin.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* surfaces, lightest first */
  --linen:        #fdf8f0;   /* the page — cream with sun in it, not off-white */
  --oat:          #f6eee0;   /* alternating bands, quiet fills */
  --white:        #fffcf7;   /* cards — warmed, because pure white reads cold */

  /* ink — warm charcoal, never black; black on cream reads cold */
  --ink:          #3d3630;
  --ink-soft:     #6d6358;
  --ink-faint:    #9a8f82;

  /* terracotta: unglazed clay, the one strong colour */
  --clay:         #a05e45;
  --clay-deep:    #874b35;
  --clay-pale:    #ecd9cd;   /* tags, quiet backgrounds */

  --sage:         #7d8f72;
  --ochre:        #c89a5b;

  --line:         #ece0cd;

  --ok-bg:        #eaf1e6;
  --ok-ink:       #4a6440;
  --warn-bg:      #fbf0e2;
  --warn-ink:     #8f5f2a;
  --stop-bg:      #f8e7e2;
  --stop-ink:     #96453a;

  --radius:       12px;
  /* Barely-there shadows. On a light palette a heavy one reads as grime. */
  --shadow:       0 1px 2px rgba(61,54,48,.04), 0 6px 20px rgba(61,54,48,.05);

  --serif:        "Fraunces", Georgia, "Iowan Old Style", serif;
  --sans:         "InterVar", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Older names kept as aliases so nothing below needed rewriting when the
     palette changed. New rules should use the names above. */
  --cream:        var(--linen);
  --cream-deep:   var(--oat);
  --accent:       var(--clay);
  --accent-deep:  var(--clay-deep);
  --gold:         var(--ochre);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --linen:      #1f1c19;
    --oat:        #2a2622;
    --white:      #262320;
    --ink:        #f2ece3;
    --ink-soft:   #c9bdae;
    --ink-faint:  #9d9183;
    --clay:       #dba98f;
    --clay-deep:  #eec4ad;
    --clay-pale:  #4a3a31;
    --sage:       #a3b399;
    --ochre:      #dcb77e;
    --line:       #3b3531;
    --ok-bg:      #283524;
    --ok-ink:     #bcd6b2;
    --warn-bg:    #3b2f1d;
    --warn-ink:   #e8c189;
    --stop-bg:    #3c2622;
    --stop-ink:   #e5aa9d;
    --shadow:     0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.3);
  }
}

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

/* A short page should still put its footer at the bottom of the window.
   Without this, the basket, a 404 and the shorter content pages left a
   band of page background below the footer, which reads as something
   missing rather than as a short page. */
html { min-height: 100%; }
body { min-height: 100vh; display: flex; flex-direction: column; }
body > main { flex: 1 0 auto; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4 { font-family: var(--serif); font-weight: 600; line-height: 1.2; margin: 0 0 .5em; }
h1 { font-size: clamp(1.9rem, 4.5vw, 2.8rem); letter-spacing: -.01em; }
h2 { font-size: clamp(1.4rem, 3vw, 1.9rem); }
h3 { font-size: 1.2rem; }
p { margin: 0 0 1em; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-deep); }
img { max-width: 100%; height: auto; display: block; }
hr { border: 0; border-top: 1px solid var(--line); margin: 2rem 0; }

.wrap { width: min(1080px, 100% - 2rem); margin-inline: auto; }

/* `.narrow` used to be a 720px column centred in the window, which put the
   basket, checkout, order, content and error pages on a different left edge
   from the header, the footer, the shop and the front page. It is now the
   same container as .wrap, with its contents held to a readable measure, so
   every page on the site starts at the same gutter. */
.narrow { width: min(1080px, 100% - 2rem); margin-inline: auto; }
.narrow > * { max-width: 44rem; }
.stack > * + * { margin-top: 1rem; }
.muted { color: var(--ink-faint); }
/* Read aloud, never drawn. In here rather than in admin.css because both
   the shop and the admin have labels that belong to a screen reader only. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.small { font-size: .875rem; }
.center { text-align: center; }

/* --- header ----------------------------------------------------------- */
.site-header {
  background: var(--white);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.site-header .wrap {
  display: flex; align-items: center; gap: 1.25rem;
  min-height: 72px; flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; color: var(--ink); }
.brand svg { width: 38px; height: 38px; flex: none; }
.brand-name { font-family: var(--serif); font-size: 1.25rem; font-weight: 600; line-height: 1.1; }
.brand-sub { font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }
.site-nav { margin-left: auto; display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }
.site-nav a { color: var(--ink-soft); text-decoration: none; font-size: .95rem; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--accent); }
.basket-link { display: inline-flex; align-items: center; gap: .35rem; }
.badge-count {
  background: var(--accent); color: #fff; border-radius: 999px;
  font-size: .72rem; padding: .05rem .45rem; min-width: 1.3em; text-align: center;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .badge-count { color: #1c1917; }
}

/* --- hero ------------------------------------------------------------- */
.hero { background: var(--cream-deep); border-bottom: 1px solid var(--line); }
.hero .wrap { display: grid; gap: 2.5rem; padding: 3.5rem 0; grid-template-columns: 1fr; align-items: center; }
@media (min-width: 820px) { .hero .wrap { grid-template-columns: 1.05fr .95fr; } }
.hero p.lede { font-size: 1.1rem; color: var(--ink-soft); max-width: 46ch; }
.hero-img { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
.hero-img img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }

/* --- buttons ---------------------------------------------------------- */
.btn {
  display: inline-block; border: 1px solid var(--accent); background: var(--accent);
  color: #fff; padding: .6rem 1.3rem; border-radius: var(--radius);
  font: inherit; font-size: .95rem; cursor: pointer; text-decoration: none;
  transition: background .15s ease, border-color .15s ease;
}
.btn:hover { background: var(--accent-deep); border-color: var(--accent-deep); color: #fff; }
.btn.secondary { background: transparent; color: var(--accent); }
.btn.secondary:hover { background: var(--cream-deep); color: var(--accent-deep); }
.btn.danger { background: #a1443a; border-color: #a1443a; }
.btn.danger:hover { background: #8a3730; border-color: #8a3730; }
.btn.small { padding: .35rem .8rem; font-size: .85rem; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn { color: #1c1917; }
  :root:not([data-theme="light"]) .btn:hover { color: #1c1917; }
  :root:not([data-theme="light"]) .btn.secondary { color: var(--accent); }
}

/* --- cards ------------------------------------------------------------ */
.grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column; box-shadow: var(--shadow);
}
.card-img { aspect-ratio: 4/3; background: var(--cream-deep); overflow: hidden; }
.card-img img { width: 100%; height: 100%; object-fit: cover; }
.card-body { padding: 1.1rem 1.2rem 1.3rem; display: flex; flex-direction: column; gap: .5rem; flex: 1; }
.card-body h3 { margin: 0; }
.card-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding-top: .5rem; }
.price { font-family: var(--serif); font-size: 1.15rem; color: var(--ink); }

.kind-tag {
  display: inline-block; font-size: .68rem; letter-spacing: .1em; text-transform: uppercase;
  padding: .15rem .55rem; border-radius: 999px; background: var(--cream-deep);
  color: var(--ink-soft); border: 1px solid var(--line);
}

/* --- panels, forms ---------------------------------------------------- */
.panel {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow);
}
.panel + .panel { margin-top: 1.5rem; }
section.band { padding: 3rem 0; }
section.band.alt { background: var(--cream-deep); border-block: 1px solid var(--line); }

label { display: block; font-size: .9rem; color: var(--ink-soft); margin-bottom: .3rem; }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=url], input[type=datetime-local], input[type=file], select, textarea {
  width: 100%; padding: .55rem .7rem; font: inherit; font-size: .95rem;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--cream); color: var(--ink);
}
textarea { min-height: 7rem; resize: vertical; font-family: var(--sans); }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.field + .field { margin-top: 1rem; }
.field-row { display: grid; gap: 1rem; grid-template-columns: 1fr; }
/* Inside a row the fields are side by side, but the second one is still the
   adjacent sibling of the first, so the rule above was pushing it a line
   lower than its neighbour. The grid's own gap does the spacing here. */
.field-row > .field + .field { margin-top: 0; }
@media (min-width: 640px) { .field-row.two { grid-template-columns: 1fr 1fr; } .field-row.three { grid-template-columns: repeat(3, 1fr); } }
.checkline { display: flex; align-items: center; gap: .5rem; }
.checkline input { width: auto; }
.checkline label { margin: 0; }
fieldset { border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem 1.2rem; margin: 0 0 1.25rem; }
legend { font-family: var(--serif); font-size: 1.05rem; padding-inline: .4rem; }

/* --- flash, status ---------------------------------------------------- */
.flash { border-radius: var(--radius); padding: .8rem 1.1rem; margin: 1.25rem 0; border: 1px solid transparent; }
.flash.ok { background: var(--ok-bg); color: var(--ok-ink); border-color: var(--ok-ink); }
.flash.warn { background: var(--warn-bg); color: var(--warn-ink); border-color: var(--warn-ink); }

.status {
  display: inline-block; font-size: .75rem; letter-spacing: .06em; text-transform: uppercase;
  padding: .2rem .6rem; border-radius: 999px; border: 1px solid var(--line);
  background: var(--cream-deep); color: var(--ink-soft);
}
.status.pending_review { background: var(--warn-bg); color: var(--warn-ink); border-color: var(--warn-ink); }
.status.approved, .status.completed, .status.paid { background: var(--ok-bg); color: var(--ok-ink); border-color: var(--ok-ink); }
.status.declined, .status.cancelled { background: #f7e4e1; color: #8a3730; border-color: #8a3730; }

/* --- timeline --------------------------------------------------------- */
.timeline { list-style: none; margin: 0; padding: 0; border-left: 2px solid var(--line); }
.timeline li { position: relative; padding: 0 0 1.1rem 1.3rem; }
.timeline li::before {
  content: ""; position: absolute; left: -7px; top: .5rem; width: 12px; height: 12px;
  border-radius: 50%; background: var(--cream); border: 2px solid var(--accent);
}
.timeline time { display: block; font-size: .8rem; color: var(--ink-faint); }

/* --- steps ------------------------------------------------------------ */
.steps { display: grid; gap: 1.5rem; grid-template-columns: 1fr; counter-reset: step; }
@media (min-width: 760px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.step { position: relative; padding-top: 2.6rem; }
.step::before {
  counter-increment: step; content: counter(step);
  position: absolute; top: 0; left: 0; width: 2rem; height: 2rem;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--accent); color: #fff; font-family: var(--serif); font-size: 1rem;
}
.step h3 { font-size: 1.05rem; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .step::before { color: #1c1917; }
}

/* --- photos ----------------------------------------------------------- */
.photo-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.photo { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--white); }
.photo img { aspect-ratio: 1; object-fit: cover; width: 100%; }
.photo .meta { padding: .5rem .6rem; font-size: .8rem; }
.photo.approved { border-color: var(--ok-ink); }
.photo.declined { border-color: #8a3730; opacity: .75; }

/* --- tables ----------------------------------------------------------- */
table.data { width: 100%; border-collapse: collapse; font-size: .92rem; }
table.data th, table.data td { text-align: left; padding: .6rem .7rem; border-bottom: 1px solid var(--line); vertical-align: top; }
table.data th { font-size: .78rem; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); font-weight: 600; }
table.data tr:hover td { background: var(--cream-deep); }
.table-scroll { overflow-x: auto; }

/* --- footer ----------------------------------------------------------- */
/* No margin above the footer. It had 4rem, which left a strip of bare page
   between the last section and the footer — on a page whose last band is a
   different shade, that reads as an empty section rather than as spacing.
   The sections carry their own padding; the footer butts straight up. */
.site-footer { background: var(--cream-deep); border-top: 1px solid var(--line); margin-top: 0; padding: 2.5rem 0; font-size: .9rem; color: var(--ink-soft); }
.site-footer .cols { display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 700px) { .site-footer .cols { grid-template-columns: 2fr 1fr 1fr; } }
.site-footer a { color: var(--ink-soft); }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: .35rem; }

.prose { max-width: 68ch; }
.prose h2 { margin-top: 1.8rem; }
.prose img { border-radius: var(--radius); margin: 1.5rem 0; }
.prose blockquote { border-left: 3px solid var(--accent); margin: 1.5rem 0; padding-left: 1.2rem; color: var(--ink-soft); font-style: italic; }

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 1rem; top: 1rem; background: var(--white); padding: .6rem 1rem; border-radius: 8px; z-index: 100; }

/* --- the quieter version ---------------------------------------------- */
/* Added when the first draft turned out to be a lot to land on: more air,
   fewer edges, one obvious thing to do per screen. */

.eyebrow {
  font-size: .75rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--clay); margin: 0 0 .25rem;
}

.hero .wrap { padding: 4.5rem 0; gap: 3.5rem; }
/* Wide enough for "mended by hand" to stay on one line. */
.hero h1 { max-width: 20ch; }
.hero .lede { font-size: 1.15rem; max-width: 44ch; }
.hero-img img { aspect-ratio: 5/4; }

section.band { padding: 4rem 0; }
section.band h2.center { margin-bottom: 2.5rem; }

/* Three steps, no numbered circles. The numbers were decoration standing in
   for structure that the headings already carry. */
.steps { grid-template-columns: 1fr; gap: 2.5rem; counter-reset: none; }
@media (min-width: 760px) { .steps { grid-template-columns: repeat(3, 1fr); } }
.step { padding-top: 0; }
.step::before { content: none; }
.step h3 {
  font-size: 1.15rem; margin-bottom: .4rem;
  padding-bottom: .6rem; border-bottom: 2px solid var(--clay-pale);
}
.step p { color: var(--ink-soft); margin: 0; }

/* Cards: one border or one shadow, not both. */
.card { border-color: transparent; box-shadow: var(--shadow); }
.card-body { padding: 1.25rem 1.3rem 1.4rem; gap: .4rem; }
.card-body h3 a { text-decoration: none; }
.card-body h3 a:hover { text-decoration: underline; }
.card-foot { padding-top: .9rem; }

/* The type tag only earns its place where kinds are mixed. */
.kind-tag { background: transparent; border: 0; padding: 0; color: var(--ink-faint); }

.footer-line { margin-bottom: .75rem; }
.footer-nav { display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; margin-bottom: 1.25rem; }
.footer-nav a { color: var(--ink-soft); text-decoration: none; }
.footer-nav a:hover { color: var(--clay); text-decoration: underline; }

/* Quiet filters: text that can be chosen, not a row of competing buttons. */
.filters { display: flex; flex-wrap: wrap; gap: 1.25rem; margin: 0 0 2rem; }
.filters a { color: var(--ink-soft); text-decoration: none; padding-bottom: .2rem; }
.filters a:hover { color: var(--clay); }
.filters a[aria-current="true"] {
  color: var(--ink); border-bottom: 2px solid var(--clay);
}

.shop-category-nav {
  display: flex;
  flex-wrap: wrap;
  gap: .65rem 1.25rem;
  margin: 1.5rem 0 3rem;
  padding: .9rem 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.shop-category-nav a {
  color: var(--ink);
  font-weight: 650;
  text-decoration: none;
}
.shop-category-nav a:hover { color: var(--clay); }
.shop-category { scroll-margin-top: 1.5rem; }
.shop-category + .shop-category { margin-top: 4rem; }

/* The whole card image is the link, so the thumbnail is clickable without a
   second "Details" button competing with the product name above it. */
a.card-img { display: block; }
a.card-img img { transition: transform .4s ease; }
.card:hover a.card-img img { transform: scale(1.03); }
@media (prefers-reduced-motion: reduce) {
  a.card-img img, .card:hover a.card-img img { transition: none; transform: none; }
}

/* --- product page ----------------------------------------------------- */
.product-layout { display: grid; gap: 2.5rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) {
  .product-layout { grid-template-columns: 1fr 1fr; gap: 4rem; }
  /* The picture stays put while the description scrolls past it. */
  .product-media { position: sticky; top: 100px; }
}
.product-detail h1 { margin-bottom: .2rem; }
.price-big { font-family: var(--serif); font-size: 1.75rem; color: var(--clay); margin: 0 0 .5rem; }
.thumb-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: .75rem; margin-top: .75rem; }
.thumb-row img { border-radius: 8px; aspect-ratio: 1; object-fit: cover; }

/* The buy form carries no panel of its own — the page has few enough things
   on it now that a box around them is just another line to look at. */
.buy-form { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
            padding: 1.5rem 0; margin: .5rem 0; }
.btn-wide { width: 100%; padding: .8rem 1.3rem; font-size: 1rem; }
@media (min-width: 500px) { .btn-wide { width: auto; min-width: 14rem; } }

.quiet-details { border-top: 1px solid var(--line); padding-top: 1rem; }
.quiet-details summary { cursor: pointer; color: var(--clay); list-style-position: outside; }
.quiet-details summary::marker { color: var(--ink-faint); }
.quiet-details[open] summary { margin-bottom: .75rem; }

/* --- "what happens now" blocks ---------------------------------------- */
/* The customer-facing pages are a sequence of these: a heading, a sentence
   in plain English, and one thing to do. No status chips — a word like
   "label_sent" means something to Ruth and nothing to anybody else. */
.next-step {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.75rem; box-shadow: var(--shadow);
}
.next-step + .next-step { margin-top: 1.5rem; }
.next-step h2 { font-size: 1.3rem; margin-bottom: .6rem; }
.next-step > p:last-child { margin-bottom: 0; }
.next-step blockquote {
  border-left: 3px solid var(--clay-pale); margin: 1rem 0; padding-left: 1.1rem;
  color: var(--ink-soft); font-style: italic;
}

table.data.plain th, table.data.plain td { padding-left: 0; }
table.data.plain tr:hover td { background: transparent; }

.timeline { margin-top: .5rem; }

/* --- modern, warm, traditional ---------------------------------------- */
/* The traditional part is the serif and the cream; the modern part is the
   restraint — tighter headings, more air, fewer edges, one accent colour. */

body { font-size: 17px; letter-spacing: -0.003em; }

h1, h2, h3, h4 {
  /* Fraunces' SOFT axis rounds the terminals (less severe, more hand-made)
     and WONK lets the italic-ish flourishes in; a little of each keeps it
     warm without tipping into novelty. */
  font-variation-settings: "SOFT" 30, "WONK" 1;
  letter-spacing: -0.015em;
}
h1 { font-weight: 600; line-height: 1.08; }
h2 { font-weight: 600; line-height: 1.15; }
h3 { font-weight: 600; }

/* Optical sizing: Fraunces has an opsz axis, so large text gets the high
   contrast of a display cut and small text the sturdier one. */
h1 { font-optical-sizing: auto; font-size: clamp(2.1rem, 5vw, 3.1rem); }
h2 { font-size: clamp(1.5rem, 3.2vw, 2rem); }

.lede { color: var(--ink-soft); line-height: 1.6; }
.price, .price-big { font-variation-settings: "SOFT" 30; font-weight: 500; }

/* Crisper corners than the first pass: softness comes from the colour and
   the spacing now, so the radius can stop doing that job. */
:root { --radius: 8px; }
.btn {
  border-radius: 6px; font-family: var(--sans); font-weight: 500; letter-spacing: 0;
  /* Roomier than the first pass: these are the one thing on the page people
     are meant to press, and they were reading as cramped against everything
     around them. */
  padding: .75rem 1.6rem;
  line-height: 1.3;
}
.btn.small { padding: .4rem .9rem; }
input, select, textarea { border-radius: 6px; font-family: var(--sans); }

/* A hairline under the header instead of a shadow — modern, and it keeps the
   cream continuous from the top of the page down. */
.site-header { border-bottom: 1px solid var(--line); background: var(--linen); }
.site-header .wrap { min-height: 80px; }
.brand-name { font-variation-settings: "SOFT" 30, "WONK" 1; letter-spacing: -0.01em; }
.brand-sub { letter-spacing: .18em; font-size: .65rem; }
.site-nav { gap: 1.6rem; }
.site-nav a { font-size: .95rem; }

/* The hero band carries the warmth; no hard edge between it and the page. */
.hero { border-bottom: 0; }
.hero-img { border-radius: var(--radius); }

.card { border-radius: var(--radius); }
.card-img img, a.card-img img { border-radius: 0; }

/* Tables: rules, not boxes. */
table.data th {
  font-family: var(--sans); font-weight: 600; letter-spacing: .06em;
}

.step h3 { font-size: 1.1rem; }

/* On a phone the nav cannot fit beside the logo, and half-wrapping looks
   like a mistake. Below 640px it becomes a deliberate second row, spaced
   across the full width. */
@media (max-width: 639px) {
  /* Padding at the top as well as the bottom. The nav drops to its own row
     here, so the wrap is taller than its min-height and the brand sits hard
     against the top of the page: the logo was within a pixel of the edge. */
  .site-header .wrap { padding-block: .55rem .5rem; row-gap: 0; }
  .site-nav {
    width: 100%; margin-left: 0; justify-content: space-between;
    gap: .5rem; padding-top: .6rem; border-top: 1px solid var(--line);
  }
  .site-nav a { font-size: .88rem; }
  .hero .wrap { padding: 2.5rem 0 3rem; gap: 2rem; }
  section.band { padding: 3rem 0; }
  .next-step { padding: 1.25rem; }
}

/* A standing notice — the workshop being closed to new repairs is a state,
   not a one-off message, so it reads differently from a flash. */
.notice {
  background: var(--clay-pale); color: var(--ink);
  border-radius: var(--radius); padding: 1rem 1.3rem;
  /* Space below as well as above: the banner had none, so the first heading
     on the page sat right against it. */
  margin: 1.5rem 0 2rem;
  font-size: .95rem; border: 1px solid transparent;
}
.notice p:last-child { margin-bottom: 0; }
.notice.warn { background: var(--warn-bg); color: var(--warn-ink); }
.notice.ok { background: var(--ok-bg); color: var(--ok-ink); }
.notice strong { display: block; font-family: var(--serif); font-size: 1.02rem; }

.footer-top { display: grid; gap: 2rem; grid-template-columns: 1fr; margin-bottom: 1.75rem; }
@media (min-width: 760px) { .footer-top { grid-template-columns: 2fr 1fr 1.2fr; gap: 3rem; } }
.footer-top p { margin-bottom: .6rem; }
.footer-top strong { color: var(--ink); }
.site-footer { padding: 3rem 0 2.5rem; }


/* The tagline under the business name in the header.
   It used to be held to a single line with an ellipsis, to stop a long one
   wrapping the lockup onto two lines. That traded the end of the sentence
   for the layout: "Clothing repairs, alterations and men…" is worse than a
   motto on two lines, and the shipped tagline was long enough to be cut.
   So it wraps. The width is held in ch rather than px so it breaks at a
   sensible number of words whatever the font is set to, and the header has
   a min-height rather than a height, so it simply grows by a line. */
.brand-sub {
  display: block; max-width: 44ch;
  overflow: visible; text-overflow: clip; white-space: normal;
  line-height: 1.35; text-wrap: pretty;
}

.brand img { border-radius: 4px; object-fit: contain; }


/* The "see everything" link under a row of cards. It was sitting straight
   under the cards and straight on top of the next band, so it read as part
   of neither. */
.band .center .btn.secondary { margin-block: .5rem; }
.band > .wrap > p.center { margin-top: 2.75rem; margin-bottom: .5rem; }

/* ======================================================================
   Order, not novelty.

   The pass before this one traded symmetry for character and overshot:
   staggered cards, a picture running off the page, a heading pinned beside
   a column of nothing. That reads as careless rather than crafted.

   Traditional means orderly. A printed brochure is left-aligned, sits on a
   clear grid, aligns its edges and uses rules instead of tricks. The
   character stays in the typeface, the warmth of the paper, the stitch and
   the plain-spoken copy — not in knocking things out of line.
   ====================================================================== */

/* Paper. Barely visible, but it stops flat colour reading as a screen. An
   SVG turbulence filter rather than an image: a few hundred bytes, no
   request, and it tiles without a seam. */
body {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
}

/* Running stitch. Used sparingly — under the main heading and above the
   closing line — because a motif repeated on every element stops being a
   motif. Short dashes with short gaps read as thread; long ones read as
   punctuation. */
.stitch {
  height: 2px; border: 0; margin: 0; border-radius: 2px;
  background-image: repeating-linear-gradient(
    to right, var(--clay) 0 7px, transparent 7px 13px);
  opacity: .55;
}
.stitch.short { width: 96px; margin-top: 1.4rem; margin-bottom: .4rem; opacity: .8; }

/* --- hero: two columns, contained, tops aligned ----------------------- */
@media (min-width: 900px) {
  .hero .wrap {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
    gap: 4rem;
    align-items: center;
    padding-block: 4.5rem 5rem;
  }
}
.hero-img img { aspect-ratio: 4/3; }

/* --- the steps: three columns, properly aligned ----------------------- */
/* A numeral, a rule, a heading, a line of text. The same shape three times,
   which is what makes it readable at a glance. */
.steps.editorial { display: grid; gap: 2.5rem; grid-template-columns: 1fr; counter-reset: step; }
@media (min-width: 760px) { .steps.editorial { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; } }

.steps.editorial .step { display: block; padding: 0; border: 0; }
.steps.editorial .step::before {
  content: counter(step) "."; counter-increment: step;
  /* The first draft styled .step::before as a filled circle and a later
     pass set content:none. Both still apply here, so every inherited
     property has to be put back explicitly or the numeral ends up white,
     absolutely positioned and invisible inside a coloured dot. */
  position: static; background: none; border-radius: 0;
  width: auto; height: auto; display: block; place-items: initial;
  font-family: var(--serif); font-size: 1.05rem; color: var(--clay);
  line-height: 1; margin-bottom: .6rem;
  font-variation-settings: "SOFT" 30, "WONK" 1;
}
.steps.editorial .step h3 {
  margin: 0 0 .45rem; font-size: 1.15rem;
  padding-top: .9rem; border-top: 1px solid var(--line); border-bottom: 0;
}
.steps.editorial .step p { margin: 0; color: var(--ink-soft); }

/* The heading sits above its section, left-aligned, like a chapter title. */
.how-layout { display: block; }
.how-layout > h2 { margin-bottom: 2.25rem; }

/* --- cards: equal, aligned, three across ------------------------------ */
.grid.staggered > * { transform: none; }
.grid.staggered { align-items: stretch; }
.grid.staggered > *:first-child .card-img { aspect-ratio: 4/3; }

/* Section headings: left-aligned and on the same axis as the text under
   them, which is what makes a page look set rather than assembled. */
section.band h2.center { text-align: left; margin-bottom: 2.25rem; }
section.band .wrap > h2.center { max-width: 28ch; }

/* --- the supporting line in the header --------------------------------
   Sits under the button rather than in a band of its own at the foot of
   the page. Set quieter and narrower than the lede above it, with a rule
   down the side, so it reads as a remark rather than a second pitch
   competing with the first. */
.hero-note {
  margin-top: 2rem; max-width: 40ch;
  padding-left: 1.1rem; border-left: 2px solid var(--clay-pale);
  font-size: .95rem; line-height: 1.6; color: var(--ink-soft);
}

.after-grid { margin-top: 2.5rem; margin-bottom: 0; }

/* --- line breaking ----------------------------------------------------
   Headings get `balance`, which evens the lines rather than filling the
   first and leaving a stray word on the second. Body text gets `pretty`,
   which stops a paragraph ending on a single word. Both are the sort of
   thing a typesetter would have done by hand, and both degrade to normal
   wrapping in browsers that don't support them. */
h1, h2, h3, h4, .brand-name { text-wrap: balance; }
p, .lede, li, figcaption { text-wrap: pretty; }

/* ======================================================================
   The editorial home page.

   Modern through scale and restraint rather than through novelty: one very
   large opening line, one photograph at full width, and sections announced
   by a small-caps label and a rule. The palette and the serif are unchanged,
   which is what keeps it traditional.
   ====================================================================== */

/* A slimmer masthead. The header should sit on the page, not sit on top of
   it, so the opening statement is the first thing with any weight. */
.site-header .wrap { min-height: 68px; }
.brand svg, .brand img { width: 34px; height: 34px; }
.brand-name { font-size: 1.12rem; }

/* --- the opening ------------------------------------------------------ */
.opening { background: var(--oat); padding-top: 4.5rem; }
@media (min-width: 900px) { .opening { padding-top: 6rem; } }

.display {
  font-size: clamp(2.6rem, 7.4vw, 5.1rem);
  line-height: 1.0;
  letter-spacing: -0.025em;
  margin: 0 0 2.5rem;
  max-width: 15ch;
}

.opening-foot { display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 820px) {
  .opening-foot { grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: 4rem; }
}
.opening-foot .lede { font-size: 1.12rem; max-width: 46ch; }
.opening-foot .hero-note { margin-top: 0; }

/* The photograph runs the full width of the window. It sits outside .wrap
   rather than breaking out of it with a 100vw trick, which would add a
   horizontal scrollbar whenever a vertical one is present. */
.full-bleed { margin-top: 4rem; }
.full-bleed img {
  width: 100%;
  height: clamp(260px, 44vh, 540px);
  object-fit: cover;
  display: block;
}

/* --- section labels --------------------------------------------------- */
/* Small caps, a rule running off to the right. It announces a section
   without spending a whole heading on it. */
.label {
  display: flex; align-items: center; gap: 1.2rem;
  margin: 0 0 2.5rem;
  font-size: .72rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-faint); font-family: var(--sans); font-weight: 600;
}
.label::after {
  /* The rule is a running stitch rather than a solid line. It is the one
     place the motif appears on this page, which is what keeps it a motif. */
  content: ""; flex: 1; height: 2px; border-radius: 2px;
  background-image: repeating-linear-gradient(
    to right, var(--clay) 0 7px, transparent 7px 13px);
  opacity: .4;
}

/* --- steps, numbered 01 02 03 ----------------------------------------- */
.steps.editorial .step::before {
  content: counter(step, decimal-leading-zero);
  font-size: .95rem; letter-spacing: .08em; color: var(--ink-faint);
  font-family: var(--sans); font-variation-settings: normal;
  margin-bottom: .9rem;
}
.steps.editorial .step h3 {
  padding-top: 1rem; font-size: 1.28rem;
}
.steps.editorial { gap: 3rem; }

/* --- products as an index --------------------------------------------- */
/* No card, no border, no shadow. A photograph, a name, a price — the way a
   catalogue sets a plate and its caption. */
.grid.index { gap: 2.5rem; }
.grid.index .card {
  background: none; border: 0; box-shadow: none; border-radius: 0;
}
.grid.index .card-img { border-radius: 4px; aspect-ratio: 3/4; }
.grid.index .card-body { padding: 1.1rem 0 0; gap: .35rem; }
.grid.index .card-body h3 { font-size: 1.22rem; }
.grid.index .card-foot {
  padding-top: .7rem; margin-top: .5rem; border-top: 1px solid var(--line);
}
.grid.index .price { font-size: 1.05rem; }

/* Tightened at Gary's request: 5rem left too much air between sections on a
   page whose bands already differ in shade. */
section.band { padding: 3.25rem 0; }
@media (max-width: 639px) { section.band { padding: 2.5rem 0; } }
.after-grid { margin-top: 3rem; }

/* ======================================================================
   The home page: a traditional shop front.

   A framed photograph with a caption, a welcome beside it, and a price list
   set like a menu. Chosen over three alternatives; the others are gone.
   ====================================================================== */
.ar-intro { display: grid; gap: 3rem; grid-template-columns: 1fr; align-items: center; }
@media (min-width: 900px) { .ar-intro { grid-template-columns: 1.05fr .95fr; gap: 4.5rem; } }
.ar-intro h1 { font-size: clamp(2rem, 4vw, 2.9rem); }
.ar-figure { margin: 0; }
.ar-figure img {
  width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 2px;
  /* A mount and a hairline, the way a framed print sits on a wall. */
  padding: 12px; background: var(--white); border: 1px solid var(--line);
  box-shadow: var(--shadow);
}
.ar-figure figcaption {
  margin-top: .9rem; font-size: .85rem; color: var(--ink-faint);
  font-style: italic; max-width: 40ch;
}

.ar-pricelist dl { margin: 0; max-width: 46rem; }
.ar-row {
  display: flex; align-items: baseline; gap: .75rem;
  padding: 1rem 0; border-bottom: 1px solid var(--line);
}
.ar-row dt { flex: 1; }
.ar-row dt a { font-family: var(--serif); font-size: 1.2rem; text-decoration: none; }
.ar-sub { display: block; font-size: .9rem; color: var(--ink-faint); margin-top: .15rem; }
.ar-row dd {
  margin: 0; font-family: var(--serif); font-size: 1.2rem; white-space: nowrap;
}
.ar-pricelist .btn { margin-top: 2rem; }

.ar-steps { display: grid; gap: 2rem; grid-template-columns: 1fr; max-width: 70rem; }
@media (min-width: 760px) { .ar-steps { grid-template-columns: repeat(3, 1fr); } }
.ar-steps h3 { font-size: 1.1rem; margin-bottom: .35rem; }
.ar-steps p { color: var(--ink-soft); margin: 0; }

/* ======================================================================
   The two alternative home page layouts, chosen in Admin → Appearance.
   Each is scoped to a wrapper class so none of them can reach the others
   or the rest of the site.
   ====================================================================== */

/* --- shopfront: banner, reassurance strip, service cards -------------- */
.sf-banner { position: relative; }
.sf-banner > img {
  width: 100%; height: clamp(340px, 52vh, 520px); object-fit: cover; display: block;
}
.sf-banner-text {
  position: absolute; inset: 0; display: flex; align-items: center;
  /* A wash rather than a flat overlay, so the photograph still reads
     through it and the text still has something to sit on. */
  background: linear-gradient(to right,
    rgba(28, 25, 22, .72) 0%, rgba(28, 25, 22, .55) 45%, rgba(28, 25, 22, .1) 100%);
}
.sf-banner-text h1 { color: #fff; max-width: 16ch; margin-bottom: .75rem; }
.sf-banner-text p { color: rgba(255, 255, 255, .92); max-width: 44ch; }
.sf-banner-text .btn { margin-top: .5rem; }

.sf-assurance { background: var(--white); border-bottom: 1px solid var(--line); }
.sf-assurance .wrap { display: grid; gap: 1.25rem; grid-template-columns: 1fr; padding: 1.5rem 0; }
@media (min-width: 760px) { .sf-assurance .wrap { grid-template-columns: repeat(3, 1fr); } }
.sf-assurance strong { display: block; font-family: var(--serif); font-size: 1.05rem; }
.sf-assurance span { font-size: .9rem; color: var(--ink-faint); }

.sf-grid { gap: 2rem; }
.sf-card {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 0 0 1.25rem; overflow: hidden;
}
.sf-card-img { display: block; aspect-ratio: 4/3; overflow: hidden; }
.sf-card-img img { width: 100%; height: 100%; object-fit: cover; }
.sf-card h3 { margin: 1rem 1.25rem .3rem; font-size: 1.18rem; }
.sf-card h3 a { text-decoration: none; }
.sf-card p { margin: 0 1.25rem .6rem; font-size: .92rem; color: var(--ink-soft); }
.sf-price { font-family: var(--serif); font-size: 1.15rem; color: var(--ink) !important; }
.sf-price span { font-family: var(--sans); font-size: .85rem; color: var(--ink-faint); }

.sf-steps { margin: 0; padding-left: 1.3rem; max-width: 60ch; }
.sf-steps li { margin-bottom: .9rem; color: var(--ink-soft); }
.sf-steps strong { color: var(--ink); }
.sf-closing { margin-top: 2rem; max-width: 60ch; font-size: 1.05rem; }

/* --- panels: alternating half-and-half blocks ------------------------- */
.pn-panel { display: grid; grid-template-columns: 1fr; align-items: stretch; }
@media (min-width: 900px) { .pn-panel { grid-template-columns: 1fr 1fr; } }
.pn-panel.alt { background: var(--oat); }
.pn-text {
  display: flex; flex-direction: column; justify-content: center;
  padding: 3rem max(1rem, 6%);
}
@media (min-width: 900px) { .pn-text { padding: 4rem clamp(2rem, 5vw, 4.5rem); } }
.pn-image { min-height: 280px; }
.pn-image img { width: 100%; height: 100%; min-height: 280px; object-fit: cover; display: block; }
@media (min-width: 900px) {
  .pn-panel.reverse .pn-text { order: 2; }
  .pn-panel.reverse .pn-image { order: 1; }
}
.pn-text h1 { font-size: clamp(2.1rem, 4.4vw, 3.2rem); margin-bottom: 1rem; }
.pn-text .lede { max-width: 42ch; }
.pn-steps { margin: 0; padding: 0; list-style: none; max-width: 44ch; }
.pn-steps li { padding: 1rem 0; border-bottom: 1px solid var(--line); }
.pn-steps li:last-child { border-bottom: 0; }
.pn-steps strong { display: block; font-family: var(--serif); font-size: 1.1rem; }
.pn-steps span { color: var(--ink-soft); font-size: .95rem; }
.pn-quote { background: var(--white); border-top: 1px solid var(--line); padding: 3rem 0; }
.pn-quote p {
  margin: 0 auto; max-width: 46rem; text-align: center;
  font-family: var(--serif); font-size: clamp(1.15rem, 2.2vw, 1.5rem); line-height: 1.45;
}

/* The "back" line above a page title. Quiet, and on the same axis as the
   heading beneath it. */
.backlink { margin-bottom: .4rem; }
.backlink a { color: var(--ink-faint); text-decoration: none; }
.backlink a:hover { color: var(--clay); text-decoration: underline; }


/* The logo at its own shape and its own size.
   It used to be drawn in a fixed 40 by 40 box with `object-fit: contain`,
   which is right for a square mark and wrong for a wordmark: a logo three
   times wider than it is tall was letterboxed down to a sliver. The height
   now comes from --logo-h, set on the element from the size chosen under
   Appearance, and the width follows from the file's own proportions. An SVG
   is usually a proper piece of artwork rather than a 40px icon, and at icon
   size it reads as a smudge.
   max-width is the backstop that stops a very wide one pushing the menu off
   the page; it scales with the height so a large setting is not quietly
   clipped back to a medium one. */
.brand img {
  height: var(--logo-h, 46px); width: auto;
  /* Never taller than the band it sits in. The sizes chosen on Appearance
     all fit, and this is the backstop: the logo grows within the header, the
     header does not grow to fit the logo. */
  max-height: calc(var(--header-h, 68px) - 4px);
  max-width: calc(var(--logo-h, 46px) * 6.5);
}
@media (max-width: 600px) {
  /* Two thirds of the chosen height on a phone, where the header is sharing
     a narrow row with the basket link. */
  .brand img {
    height: calc(var(--logo-h, 48px) * 0.7);
    max-width: calc(var(--logo-h, 48px) * 3.6);
  }
  /* Narrower, so a long motto breaks over two or three short lines instead
     of crowding the basket link. */
  .brand-sub { max-width: 22ch; }
}

/* A sold-out tag reads as a state rather than a category, so it borrows the
   warning colours the rest of the site uses for one. */
.kind-tag.sold-out { background: var(--warn-bg); color: var(--warn-ink); }

/* The gallery. Photographs at their own shape rather than cropped square:
   a coat is tall and a cuff is wide, and the grid is better for admitting
   that than the pictures are for being forced into a box. */
.gallery-grid {
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.gallery-item { margin: 0; }
.gallery-item img {
  display: block; width: 100%; height: auto; border-radius: var(--radius);
  background: var(--oat); box-shadow: var(--shadow);
}
.gallery-item figcaption {
  margin-top: .5rem; font-size: .9rem; color: var(--ink-soft); line-height: 1.4;
}
.gallery-item figcaption .small { display: block; margin-top: .15rem; }

/* A written page with a photograph beside it. One column until there is
   room for two, so the picture never squeezes the words on a phone. */
.page-with-image { display: grid; gap: 2rem; align-items: start; }
@media (min-width: 820px) {
  .page-with-image { grid-template-columns: 1fr 22rem; gap: 3rem; }
}
.page-image img {
  display: block; width: 100%; height: auto; border-radius: var(--radius);
  background: var(--oat); box-shadow: var(--shadow);
}

/* --- the chat widget -------------------------------------------------- */
/* Bottom right, where everyone has been trained to look for one. */
.chat-widget { position: fixed; right: 1rem; bottom: 1rem; z-index: 60; }

.chat-launch {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--accent); color: var(--white);
  padding: .7rem 1.1rem; border-radius: 999px; text-decoration: none;
  font-size: .95rem; box-shadow: 0 2px 6px rgba(61,54,48,.18), var(--shadow);
  border: 1px solid transparent;
}
.chat-launch:hover { background: var(--accent-deep); color: var(--white); }
.chat-launch:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.chat-launch-icon { display: inline-flex; }
/* The green dot means somebody is actually there, which is the whole point
   of the thing being offered at all. */
.chat-dot {
  width: .5rem; height: .5rem; border-radius: 50%; background: #7ddc8f;
  box-shadow: 0 0 0 2px rgba(255,255,255,.5); flex: none;
}

.chat-panel {
  position: absolute; right: 0; bottom: calc(100% + .6rem);
  width: min(23rem, calc(100vw - 2rem));
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 10px 30px rgba(61,54,48,.18);
  display: flex; flex-direction: column; overflow: hidden;
  max-height: calc(100vh - 6rem);
}
.chat-panel[hidden] { display: none; }
.chat-head {
  display: flex; align-items: center; gap: .5rem;
  padding: .75rem 1rem; border-bottom: 1px solid var(--line);
  background: var(--cream-deep);
}
.chat-title { flex: 1; font-family: var(--serif); }
.chat-close {
  background: none; border: 0; font-size: 1.4rem; line-height: 1;
  color: var(--ink-soft); cursor: pointer; padding: 0 .2rem;
}
.chat-close:hover { color: var(--ink); }
.chat-body {
  padding: 1rem; display: flex; flex-direction: column; gap: .75rem;
  overflow-y: auto;
}
/* The site's textareas are sized for a page. In a panel this wide, seven
   rems of empty box pushes the button out of sight. */
.chat-body textarea { min-height: 4.5rem; }
.chat-intro { margin: 0; }

.chat-log {
  display: flex; flex-direction: column; gap: .5rem;
  max-height: 46vh; overflow-y: auto;
}
.chat-greeting {
  margin: 0; font-size: .9rem; color: var(--ink-soft);
  background: var(--cream-deep); padding: .6rem .8rem; border-radius: 10px;
}
.chat-line { display: flex; }
.chat-line > span {
  padding: .5rem .8rem; border-radius: 12px; font-size: .95rem;
  line-height: 1.45; max-width: 85%; white-space: pre-wrap; word-break: break-word;
}
.chat-line.from-me { justify-content: flex-end; }
.chat-line.from-me > span { background: var(--accent); color: var(--white); }
.chat-line.from-them > span { background: var(--cream-deep); color: var(--ink); }

/* One line, with the box and the button the same height. They start from
   different paddings in the base styles, so the input is matched to the
   button rather than the other way round. */
.chat-compose { display: flex; gap: .5rem; align-items: center; }
/* Matched to the button rather than the other way round. The button's
   padding and line-height are set twice in this file, the later block
   winning, so these are that block's values and not the first one's. */
.chat-compose input[type=text] {
  flex: 1; min-width: 0; padding: .75rem .7rem; line-height: 1.3;
}
.chat-compose textarea { flex: 1; min-height: 2.6rem; resize: vertical; }
.chat-compose .btn { flex: none; }

/* The honeypot. Off-screen rather than display:none, because a script that
   bothers to check whether a field is visible is a script that checks for
   the obvious thing. */
.honeypot {
  position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden;
}

@media (max-width: 480px) {
  .chat-widget { right: .75rem; bottom: .75rem; }
  /* The label goes; the icon is enough once the screen is this narrow. */
  .chat-launch-text { display: none; }
  .chat-launch { padding: .8rem; }
  .chat-panel { width: calc(100vw - 1.5rem); }
}

/* Print, and anyone who would rather not have things moving: a floating
   button is furniture, and neither needs it. */
@media print { .chat-widget { display: none; } }

/* The page somebody gets when the shop is not open to them. Centred, roomy
   and quiet: it is the whole page rather than a notice on one. */
.closed-band { min-height: 80vh; display: flex; align-items: center; }
/* `.narrow > *` caps each child at 44rem but does not centre the box, which
   is right for a page of text and wrong here: `.center` then centres the
   words inside a block still sitting against the left edge. These are the
   only things on the page, so they are centred as boxes too. */
.closed-band .narrow > * { margin-inline: auto; }
.closed-logo { max-width: 160px; height: auto; margin: 0 auto 1rem; display: block; }
.closed-words { margin-inline: auto; max-width: 34rem; }
.closed-words p { margin-bottom: .9rem; }
