/* ==========================================================================
   StyleSlashed — shared design system
   Palette: warm chalk base · near-black ink · denim indigo signature · sand
   Type: Fraunces (editorial display) · Archivo (structural / UI / body)
   ========================================================================== */

:root {
  --paper:        #F3F1EC;
  --paper-2:      #EAE6DD;
  --ink:          #181A1D;
  --ink-soft:     #54585E;
  --indigo:       #243A5E;
  --indigo-bright:#2F4D7A;
  --sand:         #C9B79C;
  /* Orange sits OUTSIDE the original palette, added 2026-08-30 for the core page's
     secondary CTA. This shade rather than a brighter marketplace orange because the
     button carries small uppercase text: #C2410C holds 5.2:1 against white, where a
     hotter orange drops under the 4.5:1 needed to stay legible. */
  --orange:       #C2410C;
  --orange-bright:#E2570F;
  --line:         #D8D3C8;
  --white:        #FCFBF8;

  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-sans:    'Archivo', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;

  --maxw: 1320px;
  --gutter: clamp(20px, 5vw, 64px);
  --radius: 2px;

  /* The wordmark slash, and nothing else. A brick red rather than a pure red: it stays
     legible against the chalk background and sits with the warm sand tone instead of
     fighting the indigo. Deliberately NOT added to the general palette, because a second
     accent colour loose in the design system would compete with indigo everywhere. */
  --slash: #B0392B;

  /* Colour-group swatches. These are PRODUCT colours (what the garments are), not UI
     chrome, so they sit apart from the palette above and must not be reused for
     interface elements. Each group is: primary / mid / light. */
  --grp-blue-1:  #2F4A7A;  --grp-blue-2:  #8C9199;  --grp-blue-3:  #F2F1EC;
  --grp-black-1: #1C1D20;  --grp-black-2: #8C9199;  --grp-black-3: #F2F1EC;
  --grp-brown-1: #6B4B32;  --grp-brown-2: #C2A484;  --grp-brown-3: #F2F1EC;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
img, picture, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: none; }

body {
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- type ---------- */
.eyebrow {
  font-family: var(--font-sans);
  font-size: .72rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-soft);
}
.eyebrow--indigo { color: var(--indigo); }

.display {
  font-family: var(--font-display);
  font-weight: 400;
  font-optical-sizing: auto;
  line-height: 1.02;
  letter-spacing: -0.01em;
}
h1.display { font-size: clamp(2.6rem, 7vw, 5.6rem); }
h2.display { font-size: clamp(2rem, 4.5vw, 3.4rem); }

.kicker {
  font-family: var(--font-sans);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  line-height: 1.05;
}

.lede { font-size: 1.075rem; color: var(--ink-soft); max-width: 54ch; }
.muted { color: var(--ink-soft); }

/* ---------- layout ---------- */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: clamp(56px, 9vw, 120px); }
.section--tight { padding-block: clamp(40px, 6vw, 72px); }
.section--flush { padding-top: 0; }              /* section that follows its own intro */
.page-title { margin: 12px 0 18px; }             /* spacing for a content-page H1 (care / pack / style / policy pages) */
.section--paper2 { background: var(--paper-2); }
/* .section--sand: reusable warm-tone section. Currently UNUSED in markup
   (kept intentionally as an available modifier). */
.section--sand { background: var(--sand); color: var(--ink); }
.section--sand .lede, .section--sand .muted { color: var(--ink-soft); }

.row-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: clamp(28px, 4vw, 48px); flex-wrap: wrap; }
.row-head .display { max-width: 16ch; }

/* ---------- buttons / links ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .6em;
  font-weight: 700; font-size: .82rem; letter-spacing: .06em; text-transform: uppercase;
  padding: 15px 26px; border-radius: var(--radius);
  background: var(--ink); color: var(--paper);
  transition: background .25s ease, transform .25s ease;
}
.btn:hover { background: var(--indigo); }
/* .btn--ghost: unused since the refactor (was the "Load more" button); kept as an available variant */
.btn--ghost { background: transparent; color: var(--ink); border: 1px solid var(--ink); }
.btn--ghost:hover { background: var(--indigo); border-color: var(--indigo); color: var(--paper); }
.btn--light { background: var(--paper); color: var(--ink); }
.btn--light:hover { background: var(--sand); }
.btn--indigo { background: var(--indigo); color: var(--paper); }
.btn--indigo:hover { background: var(--indigo-bright); }
.btn--orange { background: var(--orange); color: var(--white); }
.btn--orange:hover { background: var(--orange-bright); }

.textlink {
  font-weight: 700; font-size: .8rem; letter-spacing: .08em; text-transform: uppercase;
  display: inline-flex; align-items: center; gap: .5em; padding-bottom: 3px;
  border-bottom: 1.5px solid var(--ink);
  transition: gap .2s ease, color .2s ease, border-color .2s ease;
}
.textlink:hover { gap: .85em; color: var(--indigo); border-color: var(--indigo); }

/* ---------- header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--line);
}
.head-inner {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 16px; height: 64px; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter);
}
.nav { display: flex; gap: 26px; align-items: center; justify-content: center; }
.nav a {
  font-size: .82rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  padding: 4px 0; position: relative; color: var(--ink-soft);
  transition: color .2s ease;
}
.nav a::after { content:""; position:absolute; left:0; right:100%; bottom:-2px; height:1.5px; background: var(--indigo); transition: right .25s ease; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }
.nav a:hover::after, .nav a[aria-current="page"]::after { right: 0; }

.brand {
  font-family: var(--font-sans);
  font-weight: 800; letter-spacing: .28em; text-transform: uppercase;
  font-size: 1.05rem; text-align: left; padding-left: 0; color: var(--indigo);
}
/* Oversized slash in the wordmark. Transforms don't affect layout, so the glyph
   stretches past the cap height and baseline without growing the line box or the
   64px header: scaleY sets its height, scaleX its stroke weight. The negative
   margin claws back the .28em wordmark tracking that would otherwise sit on each
   side of it, closing both halves in on the slash. It's asymmetric (start, end)
   because the glyph leans: its ink sits left at the bottom, where the dropped
   SLASHED meets it, so that side needs the harder pull to look evenly spaced. */
.brand-slash {
  display: inline-block;
  color: var(--slash);
  transform: scale(1.8, 2.4);
  margin-inline: -.15em -.42em;
}
/* The two halves step up and down across the slash. em-based so the offset
   tracks the font size, and transforms again so the header height is untouched. */
.brand-up, .brand-down { display: inline-block; }
.brand-up   { transform: translateY(-.14em); }
.brand-down { transform: translateY(.14em); }
/* Header logo replaces the STYLE/SLASHED type lockup (2026-09-06). The .brand-up /
   .brand-slash / .brand-down rules above are now unused but left in place: they are
   hand-tuned, and the footer still renders the name as text.
   Height-driven with width:auto so the 4.07:1 source keeps its proportions, and well
   under the 64px header so the sticky bar's height is unchanged. */
.brand { display: flex; align-items: center; }
.brand-logo { display: block; height: 34px; width: auto; }

.head-actions { display: flex; gap: 18px; align-items: center; justify-content: flex-end; }
.icon-btn { font-size: .8rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); }
.icon-btn:hover { color: var(--ink); }
/* care/pack tab bars (JS toggles .is-active on the active tab) */
.filter-btn { cursor: pointer; }
.filter-btn.is-active { color: var(--ink); text-decoration: underline; text-underline-offset: 6px; text-decoration-thickness: 2px; text-decoration-color: var(--indigo); }
/* header social links */
.socials { display: inline-flex; align-items: center; gap: 14px; }
.social-link { color: var(--ink-soft); display: inline-flex; position: relative; padding: 4px 0; transition: color .2s ease; }
/* same left-to-right underline sweep as the nav links */
.social-link::after { content:""; position:absolute; left:0; right:100%; bottom:-2px; height:1.5px; background: var(--indigo); transition: right .25s ease; }
.social-link:hover, .social-link:focus-visible { color: var(--indigo); }
.social-link:hover::after, .social-link:focus-visible::after { right: 0; }
.social-link svg { width: 18px; height: 18px; display: block; }

.nav-toggle { display: none; }
.nav-backdrop { display: none; }   /* tap-outside layer for the mobile menu; shown only at <=640px */
/* .banner: promo strip above the header. Markup is currently commented out on
   every page; uncomment the <div class="banner"> to re-enable. */
.banner {
  background: var(--indigo); color: var(--paper);
  text-align: center; font-size: .72rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 600;
  padding: 9px 16px;
}

/* ---------- placeholders (.ph) ----------
   Every .ph is an <img> (see img.ph rule near the end of this file). The
   diagonal-stripe background is only a graceful fallback shown while an image
   loads or if one 404s; opaque photos cover it otherwise. */
.ph {
  position: relative; overflow: hidden;
  background:
    repeating-linear-gradient(135deg, transparent 0 22px, rgba(0,0,0,.025) 22px 23px),
    var(--paper-2);
  display: flex; align-items: flex-end;
}
.ph--indigo { background:
    repeating-linear-gradient(135deg, transparent 0 22px, rgba(255,255,255,.05) 22px 23px),
    var(--indigo); }
.ph--sand { background:
    repeating-linear-gradient(135deg, transparent 0 22px, rgba(0,0,0,.04) 22px 23px),
    var(--sand); }
.ph--ink { background:
    repeating-linear-gradient(135deg, transparent 0 22px, rgba(255,255,255,.04) 22px 23px),
    var(--ink); }

/* ---------- hero ---------- */
.hero { position: relative; }
.hero-media { aspect-ratio: 16 / 12; min-height: 460px; }
@media (min-width: 900px){ .hero-media { aspect-ratio: 21 / 9; min-height: 540px; } }

/* Hero slider: slides crossfade in place. The FIRST slide stays in normal flow so it
   still sets the section's height; the rest are absolutely positioned over it. Only
   .is-active is opaque, so with JS off the first slide simply stays visible. */
.hero-slider { position: relative; }
.hero-slider .hero-media { opacity: 0; transition: opacity .9s ease; }
.hero-slider .hero-media:not(:first-child) { position: absolute; inset: 0; }
.hero-slider .hero-media.is-active { opacity: 1; }

/* Centred, NOT bottom-right: the fixed .chat-launch button (z-index 80) occupies that
   corner on every page and would sit straight on top of these. */
.hero-dots {
  position: absolute; z-index: 2;
  left: 50%; transform: translateX(-50%);
  bottom: var(--gutter);
  display: flex; gap: 9px;
}
.hero-dot {
  width: 9px; height: 9px; padding: 0; border-radius: 999px;
  background: rgba(255,255,255,.45);
  transition: background .2s ease, transform .2s ease;
}
.hero-dot:hover { background: rgba(255,255,255,.75); }
.hero-dot.is-active { background: var(--paper); transform: scale(1.3); }
/* Reduced motion: no crossfade, and scripts.js does not auto-advance either. */
@media (prefers-reduced-motion: reduce){ .hero-slider .hero-media { transition: none; } }
.hero-overlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--gutter);
  background: linear-gradient(to top, rgba(20,22,25,.55), rgba(20,22,25,.05) 45%, transparent);
  color: var(--white);
}
.hero-overlay .eyebrow { color: rgba(255,255,255,.82); }
.hero-overlay h1 { color: var(--white); max-width: 18ch; margin-block: 10px 22px; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }

/* Colour-group picker in the hero. Stacked, so the three options read as one choice
   rather than three competing CTAs. */
.hero-picker { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; margin-top: 24px; }
.hero-picker-label { color: rgba(255,255,255,.82); }
.group-pick { display: flex; gap: 10px; flex-wrap: wrap; }
.group-btn { gap: .7em; border-radius: 999px; color: var(--white); border-color: transparent; transition: background .25s ease, color .25s ease, border-color .25s ease; }
/* INVERTED 2026-09-06: each chip now WEARS its group colour, and hovering empties it to
   white. The attribute selectors are (0,2,0), so they beat .btn--ghost's transparent
   background; the plain .group-btn rules above are (0,1,0) and win over .btn--ghost only
   because they come later in the file. All three primaries are dark enough for white text,
   and the white hover takes ink. */
.group-btn[data-group="blue"]  { background: var(--grp-blue-1); }
.group-btn[data-group="black"] { background: var(--grp-black-1); }
.group-btn[data-group="brown"] { background: var(--grp-brown-1); }
.group-btn:hover, .group-btn:focus-visible { background: var(--white); color: var(--ink); border-color: var(--line); }
/* The ring follows the button, not the dot: light while the chip is coloured, dark once it
   turns white, or the primary swatch dissolves into whichever background it is sitting on.
   Hover needs the higher-specificity selector to beat the base rule below. */
.group-btn:hover .sw span, .group-btn:focus-visible .sw span { box-shadow: 0 0 0 1px rgba(20,22,25,.22); }
/* Swatch stack: the group's three colours, overlapped so they read as one palette chip. */
.group-btn .sw { display: inline-flex; align-items: center; }
.group-btn .sw span {
  width: 18px; height: 18px; border-radius: 999px; display: block;
  box-shadow: 0 0 0 1px rgba(255,255,255,.55);
}
.group-btn .sw span + span { margin-left: -6px; }
@media (max-width: 640px){
  /* Full-width rows on phones: three chips side by side get too tight to tap. */
  .group-pick { width: 100%; }
  .group-btn { flex: 1 1 100%; justify-content: center; }
  /* ...except the home page picker, which must stay a single row. */
  .home-picker .group-pick { width: auto; }
  .home-picker .group-btn { flex: 0 1 auto; }
}

/* ---------- tiles (home entry points) ---------- */
.tile { position: relative; display: block; }
.tile .ph { aspect-ratio: 3 / 4; }
.tile-label {
  position: absolute; left: 14px; bottom: 14px;
  font-weight: 700; font-size: .82rem; letter-spacing: .06em; text-transform: uppercase; color: var(--white);
  text-shadow: 0 1px 8px rgba(0,0,0,.4);
}
.tile:hover .ph { filter: brightness(.94); }

/* ---------- the honest line (signature) — home "wardrobe vs wardrobe" price device ---------- */
.honest {
  display: grid; gap: clamp(28px, 5vw, 64px); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px){ .honest { grid-template-columns: 1.1fr .9fr; } }
.honest-media .ph { aspect-ratio: 4 / 5; }

.pricetag {
  display: inline-grid; gap: 2px; border: 1px solid var(--line);
  background: var(--white); padding: 16px 20px; border-radius: var(--radius);
  margin-block: 18px 26px;
}
.pricetag .tag-row { display: flex; align-items: baseline; justify-content: space-between; gap: 28px; }
.tag-k { font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 600; color: var(--ink-soft); }
.tag-was { font-size: 1.05rem; color: var(--ink-soft); text-decoration: line-through; text-decoration-color: var(--sand); }
.tag-now { font-family: var(--font-display); font-size: 1.7rem; color: var(--indigo); font-weight: 500; }
.pricetag .tag-divider { height: 1px; background: var(--line); margin-block: 10px; }

/* ---------- product / piece grid ---------- */
.grid { display: grid; gap: 14px 14px; grid-template-columns: repeat(2, 1fr); align-items: start; } /* start = cards size to content; prevents img.ph (height:100%) stretching and pushing text out */
@media (min-width: 720px){ .grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px){ .grid--4 { grid-template-columns: repeat(4, 1fr); } } /* 4-up: the core page runs 11 pieces as 4 / 4 / 3 */
/* Core page grid only (nothing else uses .grid--4), so the shared .grid stays as it
   is for combinations and the style cards. Wider gutters are also what makes each
   card smaller: the columns are 1fr, so every pixel of gutter comes off the cards.
   Row gap runs deeper than the column gap because the cards are tall, and equal gaps
   read as too tight between stacked rows. Set on .grid--4 itself, not inside the
   1040px query, so the page is airier at the 2-up and 3-up widths too. */
.grid--4 { column-gap: clamp(20px, 2.2vw, 34px); row-gap: clamp(32px, 3.4vw, 52px); }
.grid--4 .card-name { font-size: 1rem; font-weight: 700; }   /* 700 to match .price-now; base stays 600 for the combination and style cards */
.grid--4 .card-role { font-size: .78rem; margin: 2px 0 7px; }
.grid--4 .card-buy { padding: 9px 10px; font-size: .66rem; }
.card { display: block; }
.card .ph { aspect-ratio: 3 / 4; margin-bottom: 12px; transition: filter .25s ease; }
.card:hover .ph { filter: brightness(.95); }
/* Combination cards are inert: no link, nothing to click, they exist to prove the count.
   Kill the inherited dim so the grid doesn't offer an affordance it can't honour. */
.combo-card:hover .ph { filter: none; }
.card-name { font-weight: 600; font-size: .92rem; }
.card-note { font-size: .72rem; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); margin-top: 2px; }
/* Per-piece price, inline after the name. Lighter weight and muted so the garment
   still leads: the price is a supporting fact, not the headline. */
.card-price { font-weight: 400; color: var(--ink-soft); white-space: nowrap; }
.card-price::before { content: "\00a0\2014\00a0"; }

/* Core page card. Per-piece prices and the small "Get the piece" text link were
   dropped on 2026-08-30 in favour of one full-width CTA, so a card now reads
   image > name > role note > palette dots > button. display:block is the part that
   matters: .btn sizes to its text, and a pill that does not fill the column makes
   the 4-up grid read as ragged. */
/* Reserve two lines for the role note whether it needs them or not, so the palette
   dots and the Buy now buttons land on the same baseline right across the grid;
   otherwise a one-line note lifts everything under it. line-height is pinned here
   rather than inherited so the min-height stays tied to it: change one, change both.
   em, not rem, so it still resolves to two lines under the smaller .grid--4 size. */
.card-role { font-size: .85rem; line-height: 1.55; min-height: calc(2 * 1.55em); margin: 2px 0 8px; }
/* PLACEHOLDER PRICES (2026-09-03). The figures in collection.html are invented, marked
   data-placeholder-price so they are greppable. A struck "was" price has to be a
   real former price before this ships: see the launch note in NOTES.md.
   baseline alignment, not center: the two sizes differ enough that centring makes
   the struck figure look like it is floating. */
.card-pricing { display: flex; align-items: baseline; gap: .5em; margin: 0; }   /* no bottom margin: price and stars sit as one block. Any remaining space is the two line boxes' own leading, so go negative here to close it further. */
.price-now { font-weight: 700; font-size: 1rem; letter-spacing: -.01em; }
.price-was { font-size: .78rem; color: var(--ink-soft); text-decoration: line-through; }
.grid--4 .price-now { font-size: 1rem; }
.grid--4 .price-was { font-size: .72rem; }

/* PLACEHOLDER RATINGS (2026-09-03), invented like the prices; data-placeholder-rating
   makes them greppable. Two stacked rows of the same five glyphs: the filled row is
   clipped to --fill, which is why a 4.3 shows three tenths of the fourth star rather
   than rounding to a half. Ink and line, not the usual amber, so no new token.
   The glyph layers carry no text of their own (::before content), so the accessible
.card-stars { display: flex; align-items: center; gap: .45em; margin: 0 0 10px; }
/* Two copies of the same five glyphs, the filled one laid over the empty one and clipped
   to a width, so 4.3 shows three tenths of the fourth star instead of rounding to a half.
   The glyphs live in the MARKUP, not in CSS content: they were escapes here and the
   backslashes did not survive an edit, which rendered five replacement characters. */
.stars { position: relative; display: inline-block; font-size: .82rem; letter-spacing: .06em; line-height: 1; white-space: nowrap; }
.stars-bg { color: var(--line); }
.stars-on { position: absolute; left: 0; top: 0; overflow: hidden; white-space: nowrap; color: var(--ink); }
.stars-count { font-size: .72rem; color: var(--ink-soft); }

/* Buttons size to their own text rather than the card width, but must match each
   other. A one-column grid track of max-content resolves to the WIDER label
   ("Click here"), and both buttons stretch to fill it: no JS, no hard-coded width,
   and it re-measures itself if either label changes. width:100% on the buttons is
   gone; the track now decides. */
/* Promo tile standing in for a card image. Keeps the .ph class so it inherits the
   3/4 slot and 12px gap from .card .ph, which is what holds the grid rhythm: a
   short text box would otherwise collapse and shorten its whole row. */
.card-promo { display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 18px; background: var(--indigo); color: var(--white);
  font-family: var(--font-display); font-size: 1.2rem; line-height: 1.15; }
/* It is an <a>, so the whole tile is the hit area. There is no global focus ring in
   this stylesheet, so the outline is declared here or keyboard users get nothing. */
.card-promo:hover { background: var(--indigo-bright); }
.card-promo:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.card-cta { display: grid; grid-template-columns: max-content; gap: 8px; margin-top: 2px; }
.card-buy { display: block; text-align: center; padding: 11px 12px; font-size: .72rem; border-radius: 999px; }
/* .card--soon: non-clickable "coming soon" card (e.g. unwritten Style articles) */
.card--soon { opacity: .5; cursor: default; }
.card--soon:hover .ph { filter: none; }

/* ---------- editorial split ---------- */
.split { display: grid; gap: clamp(24px,4vw,48px); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 900px){ .split { grid-template-columns: 1fr 1fr; } }
.split-media .ph { aspect-ratio: 4 / 5; }

/* ---------- lookbook ---------- */
.lookbook { display: grid; gap: 14px; grid-template-columns: 1fr; }
@media (min-width: 820px){ .lookbook { grid-template-columns: repeat(6, 1fr); grid-auto-flow: dense; } }
.look { position: relative; overflow: hidden; }
.look .ph { width: 100%; height: 100%; min-height: 240px; transition: transform .8s cubic-bezier(.22,.61,.36,1); }
.look:hover .ph, .look:focus-within .ph { transform: scale(1.15); }
.look-cap { position: absolute; left: 16px; bottom: 16px; color: var(--white); text-shadow: 0 1px 10px rgba(0,0,0,.45); }
.look-cap .k { font-weight: 700; font-size: .8rem; letter-spacing: .05em; text-transform: uppercase; }
@media (min-width: 820px){
  .look.tall  { grid-column: span 2; grid-row: span 2; }
  .look.wide  { grid-column: span 3; }
  .look.std   { grid-column: span 2; }
  .look .ph { min-height: 0; }
  .look.tall .ph { aspect-ratio: 3/4; }
  .look.wide .ph { aspect-ratio: 16/9; }
  .look.std .ph  { aspect-ratio: 1/1; }
}

/* ---------- about / values ---------- */
.values { display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); }
@media (min-width: 760px){ .values { grid-template-columns: repeat(3,1fr); } }
.value { background: var(--paper); padding: clamp(28px,4vw,44px); }
.value .num { font-family: var(--font-display); font-size: 2.2rem; color: var(--indigo); display: block; margin-bottom: 10px; }
.value .kicker { font-size: 1.05rem; margin-bottom: 8px; }

/* ---------- newsletter ---------- */
.signup { display: flex; gap: 10px; max-width: 460px; flex-wrap: wrap; }
.signup input {
  flex: 1 1 220px; font: inherit; padding: 14px 16px; border: 1px solid var(--line);
  background: var(--white); border-radius: var(--radius);
}
.signup input:focus-visible { outline: 2px solid var(--indigo); outline-offset: 1px; }

/* ---------- palette switching (core page) ---------- */
.palette-bar { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding-bottom: 8px; }
.palette-note { font-size: .82rem; }
/* Page-level palette buttons are swatch-only: the label sits alongside in .palette-bar. */
.pal-btn { width: 30px; height: 30px; padding: 0; border-radius: 999px; }
.pal-btn.is-active { box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink); }

/* Core-page cards only. Scoped to [data-piece] so the shared .card hover, a brightness
   dim, stays intact on every other page.

   The image is a link, so it needs hover feedback: the photo scales up slightly inside a
   fixed frame. The card, the frame and everything below it stay exactly put; only the
   picture moves. overflow:hidden on the link is what makes it a zoom rather than an
   overspill. Same easing curve as the old .look hover, so it feels native to the site. */
[data-piece]:hover .ph { filter: none; }
.card-media-link { display: block; overflow: hidden; }
.card-media-link .ph { transition: transform .5s cubic-bezier(.22,.61,.36,1); }
.card-media-link:hover .ph,
.card-media-link:focus-visible .ph { transform: scale(1.04); }
/* Reduced motion: no zoom at all. The pointer cursor and the text-link highlight remain. */
@media (prefers-reduced-motion: reduce){
  .card-media-link .ph { transition: none; }
  .card-media-link:hover .ph, .card-media-link:focus-visible .ph { transform: none; }
}
/* Hovering the image also lights the text link, so the two are visibly the same destination. */
[data-piece]:hover .textlink { color: var(--indigo); border-color: var(--indigo); }

/* Per-piece colour dots. Each switches ONLY its own card, so a visitor can mix across
   palettes; the bar above switches all eleven at once. */
.piece-colors { display: flex; gap: 7px; margin: 0 0 10px; }
.pc {
  width: 17px; height: 17px; padding: 0; border-radius: 999px;
  box-shadow: 0 0 0 1px rgba(20,22,25,.22);
  transition: transform .18s ease, box-shadow .18s ease;
}
.pc:hover { transform: scale(1.12); }
.pc.is-active { box-shadow: 0 0 0 1px var(--paper), 0 0 0 3px var(--ink); }
/* Swapping the src mid-transition would flash; fade the image instead. */
[data-piece-img] { transition: opacity .18s ease; }
[data-piece-img].is-swapping { opacity: .35; }

/* ---------- home page: two-column layout ----------
   Left third holds the copy and the palette picker, right two thirds holds the
   static hero, three portraits and a closing line. Single column below 900px:
   at narrow widths a one-third column is too tight for a headline. */
/* align-items:start on both grids below is load-bearing, not cosmetic. img.ph carries
   height:100%, and a stretched grid item resolves that against the row height instead of
   the image's own aspect-ratio, so the picture grows past its container and collides with
   whatever follows. Same fix as .grid uses. */
.home-split { display: grid; grid-template-columns: 1fr; gap: clamp(32px, 4vw, 56px); align-items: start; }
@media (min-width: 900px){
  /* 2x2, placed explicitly. The picker and the closing paragraph share row 2, so with
     align-items:start their TOPS line up: the buttons sit level with the first line of
     that paragraph rather than hanging below it. Bottom-aligning them instead (the
     obvious margin-top:auto trick) does not work, because the paragraph runs several
     lines deep and the button block is one line, so only their feet would match.
     DOM order is copy > picker > images > closing, which is also the stacked reading
     order below 900px, so nothing needs reordering there and tab order still follows
     what you see. */
  .home-split { grid-template-columns: 1fr 2fr; row-gap: 22px; }
  .home-left    { grid-column: 1; grid-row: 1; }
  .home-right   { grid-column: 2; grid-row: 1; }
  .home-closing { grid-column: 2; grid-row: 2; }
}
.home-left { display: flex; flex-direction: column; align-items: flex-start; gap: 22px; }
/* The h1 clamp is tuned for a full-width hero, which is far too large in a third
   of the page. Rescaled here rather than changing the global .display sizing. */
/* MUST outrank h1.display (line 84, clamp(2.6rem, 7vw, 5.6rem)). A bare .home-h1 is
   specificity (0,1,0) against that rule's (0,1,1), so it lost silently and the headline
   rendered at up to 5.6rem. Qualified here so it actually wins. */
h1.display.home-h1 { font-size: clamp(2.4rem, 4.2vw, 3.36rem); }
/* Picker label is white on the old dark hero overlay; on paper it needs ink. */
.home-picker .hero-picker-label { color: var(--ink-soft); }
.home-picker { margin-top: 0; }

.home-hero { width: 100%; aspect-ratio: 16 / 9; height: auto; }
/* 70% width = the three portraits render 30% smaller. Left-aligned under the hero. */
.home-portraits { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(10px, 1.2vw, 16px); margin-top: clamp(10px, 1.2vw, 16px); align-items: start; max-width: 70%; }
.home-portraits .ph { aspect-ratio: 3 / 4; height: auto; }

/* Palette buttons in the left column: shrunk to hold one row. The default .btn padding
   and .82rem type wrap three buttons onto two lines in a column this narrow. */
/* Equal-width chips. grid-auto-columns:1fr makes every column the same size, and
   width:max-content on the container makes that size resolve to the WIDEST label
   ("Black") rather than stretching the row across the whole left column. */
.home-picker .group-pick { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; width: max-content; }
.home-picker .group-btn { padding: 9px 12px; font-size: .68rem; letter-spacing: .04em; gap: .45em; justify-content: center; }
.home-picker .group-btn .sw span { width: 13px; height: 13px; }
.home-picker .group-btn .sw span + span { margin-left: -5px; }
.home-closing { margin-top: 0; max-width: 62ch; font-size: .95rem; }

/* generic form field (contact form, etc.) */
.field { width: 100%; font: inherit; padding: 13px 15px; border: 1px solid var(--line); background: var(--white); border-radius: var(--radius); }
.field--area { resize: vertical; }
.field-label { display: block; margin-bottom: 6px; }
/* Contact form result notice: shown by scripts.js from the ?sent / ?error flag
   contact.php redirects back with. Indigo left rule for success, ink for a fault. */
.form-note {
  max-width: 520px; margin-bottom: 22px; padding: 14px 16px;
  background: var(--paper-2); border: 1px solid var(--line);
  border-left: 3px solid var(--indigo); border-radius: var(--radius);
  font-size: .92rem; line-height: 1.5;
}
.form-note--error { border-left-color: var(--ink); }

/* callout / notice box (e.g. policy-page placeholder warning) */
.notice { background: var(--paper-2); border: 1px solid var(--line); padding: 14px 16px; border-radius: var(--radius); font-size: .85rem; margin-bottom: 24px; }

/* ---------- footer ---------- */
.site-foot { background: var(--indigo); color: var(--paper); padding-block: clamp(48px,7vw,88px) 32px; }
.foot-grid { display: grid; gap: 36px; grid-template-columns: 1fr; }
@media (min-width: 760px){ .foot-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; } }
.foot-grid h5 { font-size: .74rem; letter-spacing: .14em; text-transform: uppercase; color: var(--sand); margin-bottom: 16px; }
.foot-grid ul { list-style: none; padding: 0; display: grid; gap: 10px; }
.foot-grid a { color: #C7CAD0; font-size: .9rem; }
.foot-grid a:hover { color: var(--paper); }
.foot-brand { font-weight: 800; letter-spacing: .28em; text-transform: uppercase; font-size: 1.2rem; margin-bottom: 14px; }
.site-foot .muted { color: #B4B9C2; }            /* muted text reads light on the indigo footer */
.foot-blurb { max-width: 26ch; }                  /* the brand strapline paragraph */
.foot-bottom { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-top: 48px; padding-top: 22px; border-top: 1px solid rgba(255,255,255,.14); font-size: .78rem; color: #B4B9C2; }
.foot-bottom a:hover { color: var(--paper); }     /* links inherit the row's light grey */

/* ---------- utilities ---------- */
.stack > * + * { margin-top: var(--s, 18px); }
.center { text-align: center; }
:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }
.reveal { opacity: 0; transform: translateY(16px); transition: opacity .7s ease, transform .7s ease; }
.reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce){ .reveal { opacity: 1; transform: none; } .look .ph { transition-duration: .8s !important; } }

/* ---------- mobile nav (<=860px: tablets + large phones) ----------
   Hamburger reveals a right-hand off-canvas side drawer. On phones the MOBILE
   ONLY block below (<=640px) overrides this into a dropdown under the icon. */
@media (max-width: 860px){
  .head-inner { grid-template-columns: auto 1fr auto; }
  .nav-toggle { display: inline-flex; flex-direction: column; gap: 4px; padding: 8px 0; }
  .nav-toggle span { width: 22px; height: 2px; background: var(--ink); transition: transform .25s, opacity .25s; }
  .brand { text-align: left; padding-left: 0; }
  .nav {
    position: fixed; inset: 0 0 0 auto; width: min(80vw, 320px);
    background: var(--paper); flex-direction: column; align-items: flex-start; gap: 4px;
    padding: 88px var(--gutter) var(--gutter); border-left: 1px solid var(--line);
    transform: translateX(100%); transition: transform .3s ease; z-index: 60;
  }
  .nav.open { transform: none; }
  .nav a { font-size: 1.1rem; padding: 12px 0; width: 100%; border-bottom: 1px solid var(--line); }
  .nav a::after { display: none; }
  body.menu-open { overflow: hidden; }
  .nav-toggle[aria-expanded="true"] span:nth-child(1){ transform: translateY(6px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span:nth-child(2){ opacity: 0; }
  .nav-toggle[aria-expanded="true"] span:nth-child(3){ transform: translateY(-6px) rotate(-45deg); }
}

/* ==========================================================================
   MOBILE ONLY (phones, <=640px) — scoped overrides for the phone experience
   ========================================================================== */
@media (max-width: 640px){
  /* Nav drops down as a panel beneath the hamburger icon (not a side drawer).
     Absolute inside the sticky header, so it stays pinned under the icon. */
  .nav {
    position: absolute;
    inset: 64px auto auto var(--gutter);     /* top right bottom left: under the 64px header, aligned to the icon */
    width: min(72vw, 260px);
    height: auto; max-height: calc(100vh - 80px); overflow-y: auto;
    padding: 6px 16px; gap: 0;
    border: 1px solid var(--line); border-radius: var(--radius);
    box-shadow: 0 16px 40px rgba(20,22,25,.18);
    transform: translateY(-8px); opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .2s ease, transform .2s ease, visibility .2s;
  }
  .nav.open { transform: none; opacity: 1; visibility: visible; pointer-events: auto; }
  /* tap-outside backdrop: transparent, sits under the header (z 50) so the
     dropdown stays above it, but over page content so taps there close the menu */
  .nav-backdrop.open { display: block; position: fixed; inset: 0; z-index: 49; background: transparent; cursor: pointer; }
  .nav a { font-size: 1rem; padding: 11px 0; }
  .nav a:last-child { border-bottom: none; }
  body.menu-open { overflow: visible; }       /* small dropdown — keep page scrollable */
  /* socials show on mobile too (same as desktop); tighten gaps so the header fits */
  .head-actions { gap: 12px; }
  .socials { gap: 12px; }
  /* STYLESLASHED is a long wordmark: tighten it on phones so it clears the
     hamburger and the social icons without wrapping. Desktop sizing unchanged. */
  .brand { font-size: .92rem; letter-spacing: .18em; white-space: nowrap; }
  .brand-logo { height: 26px; }

  /* Care/pack tab bar: swipeable single row with a right-edge fade hint.
     flex:1/min-width:0 lets the flex item shrink so it scrolls internally;
     padding-right + mask keep the last chip readable when fully scrolled. */
  [data-filter-bar] {
    flex: 1; min-width: 0;
    flex-wrap: nowrap; overflow-x: auto;
    /* overflow-x:auto forces overflow-y:auto, which clips the active underline
       (offset 6px below text) on iOS Safari. Bottom padding keeps it in view. */
    padding: 2px 28px 10px 0;
    scrollbar-width: none;                     /* Firefox */
    -webkit-overflow-scrolling: touch;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  [data-filter-bar]::-webkit-scrollbar { display: none; }   /* Chromium / Edge / Safari */
  [data-filter-bar] .filter-btn { flex: 0 0 auto; white-space: nowrap; }
}

/* ==========================================================================
   Size guide
   ========================================================================== */
.sizetable { width: 100%; border-collapse: collapse; margin: 6px 0 30px; font-size: .92rem; }
.sizetable thead th {
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft);
  text-align: left; padding: 0 14px 10px; border-bottom: 1.5px solid var(--ink);
}
.sizetable td { padding: 13px 14px; border-bottom: 1px solid var(--line); }
.sizetable tbody tr:hover { background: var(--paper-2); }
.sizetable td:first-child { font-weight: 700; }
.measure { display: grid; gap: 22px; grid-template-columns: 1fr; margin-top: 8px; }
@media (min-width: 760px){ .measure { grid-template-columns: repeat(3, 1fr); } }
.measure .step .num {
  font-family: var(--font-display); font-size: 1.8rem; color: var(--indigo);
  display: block; margin-bottom: 6px;
}
.measure .step h3 { font-size: 1rem; margin-bottom: 6px; }

/* ==========================================================================
   Tabbed panels — reusable (care page, pack-for-travel page). A [data-tabs]
   filter bar (JS in scripts.js) shows one [data-panel] at a time. Filter-bar
   styling/scroll comes from .filter-btn + [data-filter-bar] (header + mobile).
   ========================================================================== */
.tab-panel { display: none; }
.tab-panel.is-active { display: block; }

/* ==========================================================================
   Chat widget "Taylor" (front-end mockup — injected by scripts.js)
   ========================================================================== */
.chat-launch {
  position: fixed; right: clamp(16px,3vw,28px); bottom: clamp(16px,3vw,28px); z-index: 80;
  display: inline-flex; align-items: center; gap: .5em;
  background: var(--indigo); color: var(--paper);
  font-weight: 700; font-size: .82rem; letter-spacing: .04em; text-transform: uppercase;
  padding: 13px 18px; border-radius: 999px;
  box-shadow: 0 8px 24px rgba(20,22,25,.22);
  transition: transform .2s ease, background .2s ease;
}
.chat-launch:hover { background: var(--indigo-bright); transform: translateY(-2px); }
.chat-launch svg { width: 18px; height: 18px; }

.chat-panel {
  position: fixed; right: clamp(16px,3vw,28px); bottom: calc(clamp(16px,3vw,28px) + 58px); z-index: 81;
  width: min(360px, calc(100vw - 32px));
  background: var(--white); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 20px 50px rgba(20,22,25,.25); overflow: hidden;
  display: flex; flex-direction: column; max-height: min(560px, 78vh);
  transform: translateY(12px) scale(.98); opacity: 0; pointer-events: none;
  transition: opacity .22s ease, transform .22s ease; transform-origin: bottom right;
}
.chat-panel.open { opacity: 1; transform: none; pointer-events: auto; }
.chat-head { background: var(--ink); color: var(--paper); padding: 15px 18px; display: flex; align-items: center; justify-content: space-between; }
.chat-head .t { font-weight: 700; letter-spacing: .03em; }
.chat-head .s { font-size: .7rem; color: #9DA1A8; }
.chat-close { color: #C7CAD0; font-size: 1.4rem; line-height: 1; }
.chat-close:hover { color: var(--paper); }
.chat-body { padding: 16px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; background: var(--paper); }
.msg { max-width: 84%; padding: 10px 13px; border-radius: 14px; font-size: .89rem; line-height: 1.45; }
.msg.bot { background: var(--white); border: 1px solid var(--line); border-bottom-left-radius: 4px; align-self: flex-start; }
.msg.user { background: var(--indigo); color: var(--paper); border-bottom-right-radius: 4px; align-self: flex-end; }
.chat-quick { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px 16px 12px; background: var(--paper); }
.chat-quick button { border: 1px solid var(--line); background: var(--white); border-radius: 999px; padding: 7px 13px; font-size: .77rem; font-weight: 600; color: var(--ink); transition: border-color .2s, color .2s; }
.chat-quick button:hover { border-color: var(--indigo); color: var(--indigo); }
.chat-input { display: flex; gap: 8px; padding: 12px 14px; border-top: 1px solid var(--line); background: var(--white); }
.chat-input input { flex: 1; border: 1px solid var(--line); border-radius: 999px; padding: 10px 14px; font: inherit; font-size: .88rem; }
.chat-send { background: var(--ink); color: var(--paper); border-radius: 999px; padding: 0 17px; font-weight: 700; font-size: .8rem; }
.chat-send:hover { background: var(--indigo); }
.chat-note { font-size: .66rem; color: var(--ink-soft); text-align: center; padding: 0 14px 12px; background: var(--white); }
@media (prefers-reduced-motion: reduce){ .chat-panel { transition: opacity .01ms; } .chat-launch { transition: none; } }

/* ==========================================================================
   Images — placeholders (.ph) now hold <img>; cover-fit within their frames.
   Replace files in /images to swap photography. Background stays as a
   graceful fallback while an image loads or if one is missing.
   ========================================================================== */
img.ph { object-fit: cover; display: block; width: 100%; height: 100%; }
.hero-media.ph, .honest-media .ph, .split-media .ph,
.tile .ph, .card .ph, .look .ph { width: 100%; }
